weld the sidebar deck

Change-Id: Idc6710df7e59bcb5f61fca783e0cc0666cb13a1f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112404
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/include/sfx2/sidebar/Deck.hxx b/include/sfx2/sidebar/Deck.hxx
index 5122d7a..76f92f8 100644
--- a/include/sfx2/sidebar/Deck.hxx
+++ b/include/sfx2/sidebar/Deck.hxx
@@ -19,15 +19,14 @@
#pragma once

#include <sfx2/sidebar/Panel.hxx>

#include <vcl/window.hxx>

class ScrollBar;
#include <vcl/InterimItemWindow.hxx>
#include <vcl/weld.hxx>

namespace sfx2::sidebar
{
class DeckDescriptor;
class DeckTitleBar;
class SidebarDockingWindow;

/** This is the parent window of the panels.
    It displays the deck title.
@@ -35,25 +34,25 @@ class DeckTitleBar;
    A deck consists of multiple panels.
    E.g. Properties, Styles, Navigator.
*/
class Deck final : public vcl::Window
class Deck final : public InterimItemWindow
{
public:
    Deck(const DeckDescriptor& rDeckDescriptor, vcl::Window* pParentWindow,
    Deck(const DeckDescriptor& rDeckDescriptor, SidebarDockingWindow* pParentWindow,
         const std::function<void()>& rCloserAction);
    virtual ~Deck() override;
    virtual void dispose() override;

    const OUString& GetId() const { return msId; }

    VclPtr<DeckTitleBar> const& GetTitleBar() const;
    DeckTitleBar* GetTitleBar() const;
    tools::Rectangle GetContentArea() const;
    void ResetPanels(const SharedPanelContainer& rPanels);
    const SharedPanelContainer& GetPanels() const { return maPanels; }

    Panel* GetPanel(std::u16string_view panelId);
    std::shared_ptr<Panel> GetPanel(std::u16string_view panelId);

    void RequestLayout();
    vcl::Window* GetPanelParentWindow();
    weld::Widget* GetPanelParentWindow();

    /** Try to make the panel completely visible.
        When the whole panel does not fit then make its top visible
@@ -61,28 +60,15 @@ public:
    */
    void ShowPanel(const Panel& rPanel);

    virtual void ApplySettings(vcl::RenderContext& rRenderContext) override;
    virtual void Paint(vcl::RenderContext& rRenderContext,
                       const tools::Rectangle& rUpdateArea) override;
    virtual void DataChanged(const DataChangedEvent& rEvent) override;
    virtual bool EventNotify(NotifyEvent& rEvent) override;

    virtual void Resize() override;

    virtual void DumpAsPropertyTree(tools::JsonWriter&) override;

    sal_Int32 GetMinimalWidth() const { return mnMinimalWidth; }

    class ScrollContainerWindow final : public vcl::Window
    {
    public:
        ScrollContainerWindow(vcl::Window* pParentWindow);
        virtual void Paint(vcl::RenderContext& rRenderContext,
                           const tools::Rectangle& rUpdateArea) override;
        void SetSeparators(const ::std::vector<sal_Int32>& rSeparators);

    private:
        std::vector<sal_Int32> maSeparators;
    };
    SidebarDockingWindow* GetDockingWindow() const { return mxParentWindow; }

private:
    void RequestLayoutInternal();
@@ -92,14 +78,11 @@ private:
    sal_Int32 mnMinimalWidth;
    sal_Int32 mnMinimalHeight;
    SharedPanelContainer maPanels;
    VclPtr<DeckTitleBar> mpTitleBar;
    VclPtr<vcl::Window> mpScrollClipWindow;
    VclPtr<ScrollContainerWindow> mpScrollContainer;
    VclPtr<vcl::Window> mpFiller;
    VclPtr<ScrollBar> mpVerticalScrollBar;

    DECL_LINK(HandleVerticalScrollBarChange, ScrollBar*, void);
    bool ProcessWheelEvent(CommandEvent const* pCommandEvent);
    VclPtr<SidebarDockingWindow> mxParentWindow;
    std::unique_ptr<DeckTitleBar> mxTitleBar;
    std::unique_ptr<weld::ScrolledWindow> mxVerticalScrollBar;
    std::unique_ptr<weld::Container> mxContents;
};

} // end of namespace sfx2::sidebar
diff --git a/include/sfx2/sidebar/FocusManager.hxx b/include/sfx2/sidebar/FocusManager.hxx
index d20e7c4..fd5d2e8 100644
--- a/include/sfx2/sidebar/FocusManager.hxx
+++ b/include/sfx2/sidebar/FocusManager.hxx
@@ -20,6 +20,7 @@

#include <sfx2/sidebar/Panel.hxx>
#include <tools/link.hxx>
#include <vcl/vclevent.hxx>
#include <vcl/keycod.hxx>

namespace weld {
@@ -64,12 +65,13 @@ public:
    void GrabFocus();
    void GrabFocusPanel();

    void SetDeckTitle(DeckTitleBar* pDeckTitleBar);
    void SetDeck(Deck* pDeck);
    void SetPanels(const SharedPanelContainer& rPanels);
    void SetButtons(const std::vector<weld::Widget*>& rButtons);

private:
    VclPtr<DeckTitleBar> mpDeckTitleBar;
    VclPtr<Deck> mxDeck;
    DeckTitleBar* mpDeckTitleBar;
    SharedPanelContainer maPanels;
    std::vector<weld::Widget*> maButtons;
    const std::function<void(const Panel&)> maShowPanelFunctor;
@@ -94,7 +96,6 @@ private:
    /** Listen for key events for panels and buttons.
    */
    DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
    DECL_LINK(ChildEventListener, VclWindowEvent&, void);

    void ClearPanels();
    void ClearButtons();
@@ -125,13 +126,12 @@ private:
    void FocusButton(const sal_Int32 nButtonIndex);
    void MoveFocusInsidePanel(const FocusLocation& rLocation,
                              const sal_Int32 nDirection);
    void MoveFocusInsideDeckTitle(const FocusLocation& rLocation,
    bool MoveFocusInsideDeckTitle(const FocusLocation& rLocation,
                                  const sal_Int32 nDirection);

    bool HandleKeyEvent(const vcl::KeyCode& rKeyCode,
                        const FocusLocation& rLocation);

    FocusLocation GetFocusLocation(const vcl::Window& rWindow) const;
    FocusLocation GetFocusLocation() const;

};
diff --git a/include/sfx2/sidebar/Panel.hxx b/include/sfx2/sidebar/Panel.hxx
index 28fa9cd..8ab43b3 100644
--- a/include/sfx2/sidebar/Panel.hxx
+++ b/include/sfx2/sidebar/Panel.hxx
@@ -19,9 +19,7 @@
#pragma once

#include <sfx2/dllapi.h>

#include <vcl/InterimItemWindow.hxx>

#include <vcl/weld.hxx>
#include <vector>

namespace com::sun::star::frame
@@ -43,27 +41,28 @@ class XWindow;

namespace sfx2::sidebar
{
class Context;
class Deck;
class PanelDescriptor;
class PanelTitleBar;
class Context;

/**
 * Multiple panels form a single deck.
 * E.g. the Properties deck has panels like Styles, Character, paragraph.
 */
class SFX2_DLLPUBLIC Panel final : public InterimItemWindow
class SFX2_DLLPUBLIC Panel final
{
public:
    Panel(const PanelDescriptor& rPanelDescriptor, vcl::Window* pParentWindow,
          const bool bIsInitiallyExpanded, const std::function<void()>& rDeckLayoutTrigger,
    Panel(const PanelDescriptor& rPanelDescriptor, weld::Widget* pParentWindow,
          const bool bIsInitiallyExpanded, Deck* pDeck,
          const std::function<Context()>& rContextAccess,
          const css::uno::Reference<css::frame::XFrame>& rxFrame);

    virtual ~Panel() override;
    virtual void dispose() override;
    ~Panel();

    PanelTitleBar* GetTitleBar() const;
    void ShowTitlebar(bool bShowTitlebar);
    weld::Container* GetContents() const;
    void Show(bool bShow);
    bool IsTitleBarOptional() const { return mbIsTitleBarOptional; }
    void SetUIElement(const css::uno::Reference<css::ui::XUIElement>& rxElement);
    const css::uno::Reference<css::ui::XSidebarPanel>& GetPanelComponent() const
@@ -76,32 +75,48 @@ public:
    bool IsExpanded() const { return mbIsExpanded; }
    bool HasIdPredicate(std::u16string_view rsId) const;
    const OUString& GetId() const { return msPanelId; }
    void TriggerDeckLayouting() { maDeckLayoutTrigger(); }
    const OUString& GetTitle() const { return msTitle; }
    void TriggerDeckLayouting();

    void SetHeightPixel(int nHeight);

    bool get_extents(tools::Rectangle& rExtents) const;

    /// Set whether a panel should be present but invisible / inactive
    void SetLurkMode(bool bLurk);
    bool IsLurking() const { return mbLurking; }

    virtual void DataChanged(const DataChangedEvent& rEvent) override;
    virtual void ApplySettings(vcl::RenderContext& rRenderContext) override;
    virtual void DumpAsPropertyTree(tools::JsonWriter&) override;
    void set_margin_top(int nMargin);
    void set_margin_bottom(int nMargin);
    void set_vexpand(bool bExpand);

    weld::Window* GetFrameWeld();

    void DataChanged();

private:
    std::unique_ptr<weld::Builder> mxBuilder;
    const OUString msPanelId;
    const OUString msTitle;
    const bool mbIsTitleBarOptional;
    const bool mbWantsAWT;
    css::uno::Reference<css::ui::XUIElement> mxElement;
    css::uno::Reference<css::ui::XSidebarPanel> mxPanelComponent;
    bool mbIsExpanded;
    bool mbLurking;
    const std::function<void()> maDeckLayoutTrigger;
    const std::function<Context()> maContextAccess;
    const css::uno::Reference<css::frame::XFrame>& mxFrame;
    weld::Widget* mpParentWindow;
    VclPtr<Deck> mxDeck;
    std::unique_ptr<weld::Container> mxContainer;
    std::unique_ptr<PanelTitleBar> mxTitleBar;
    std::unique_ptr<weld::Container> mxContents;
    css::uno::Reference<css::awt::XWindow> mxXWindow;

    DECL_LINK(DumpAsPropertyTreeHdl, tools::JsonWriter&, void);
};
typedef std::vector<VclPtr<Panel>> SharedPanelContainer;

typedef std::vector<std::shared_ptr<Panel>> SharedPanelContainer;

} // end of namespace sfx2::sidebar

diff --git a/include/sfx2/sidebar/PanelLayout.hxx b/include/sfx2/sidebar/PanelLayout.hxx
index b03ebf9..e563018 100644
--- a/include/sfx2/sidebar/PanelLayout.hxx
+++ b/include/sfx2/sidebar/PanelLayout.hxx
@@ -21,9 +21,9 @@ namespace tools { class JsonWriter; }
class SFX2_DLLPUBLIC PanelLayout
{
protected:
    VclPtr<sfx2::sidebar::Panel> m_xPanel;
    std::unique_ptr<weld::Builder> m_xBuilder;
    std::unique_ptr<weld::Container> m_xContainer;
    sfx2::sidebar::Panel* m_pPanel;

    virtual void DataChanged(const DataChangedEvent& rEvent);
    virtual void DumpAsPropertyTree(tools::JsonWriter&);
diff --git a/include/sfx2/sidebar/SidebarController.hxx b/include/sfx2/sidebar/SidebarController.hxx
index 8bcaa85..7c0b429 100644
--- a/include/sfx2/sidebar/SidebarController.hxx
+++ b/include/sfx2/sidebar/SidebarController.hxx
@@ -239,9 +239,9 @@ private:
    void CreatePanels(
        std::u16string_view rDeckId,
        const Context& rContext);
    VclPtr<Panel> CreatePanel (
    std::shared_ptr<Panel> CreatePanel (
        std::u16string_view rsPanelId,
        vcl::Window* pParentWindow,
        weld::Widget* pParentWindow,
        const bool bIsInitiallyExpanded,
        const Context& rContext,
        const VclPtr<Deck>& pDeck);
diff --git a/include/sfx2/sidebar/Theme.hxx b/include/sfx2/sidebar/Theme.hxx
index ebacb43..5d01fc4 100644
--- a/include/sfx2/sidebar/Theme.hxx
+++ b/include/sfx2/sidebar/Theme.hxx
@@ -57,8 +57,6 @@ public:

        Image_Color_,

        Color_DeckTitleFont,
        Color_PanelTitleFont,
        Color_Highlight,
        Color_HighlightText,
        Color_DeckBackground,
@@ -66,16 +64,11 @@ public:
        Color_PanelBackground,
        Color_PanelTitleBarBackground,
        Color_TabBarBackground,
        Color_HorizontalBorder,
        Color_VerticalBorder,
        Color_DropDownBackground,

        Color_Int_,

        Int_DeckTitleBarHeight,
        Int_DeckBorderSize,
        Int_DeckSeparatorHeight,
        Int_PanelTitleBarHeight,
        Int_DeckLeftPadding,
        Int_DeckTopPadding,
        Int_DeckRightPadding,
diff --git a/sd/source/ui/sidebar/SlideBackground.cxx b/sd/source/ui/sidebar/SlideBackground.cxx
index 7ee626e..eaee1c1 100644
--- a/sd/source/ui/sidebar/SlideBackground.cxx
+++ b/sd/source/ui/sidebar/SlideBackground.cxx
@@ -341,8 +341,8 @@ void SlideBackground::HandleContextChange(
            mxInsertImage->hide();

        // Need to do a relayouting, otherwise the panel size is not updated after show / hide controls
        if (m_xPanel)
            m_xPanel->TriggerDeckLayouting();
        if (m_pPanel)
            m_pPanel->TriggerDeckLayouting();

    }
    else if ( IsDraw() )
diff --git a/sfx2/UIConfig_sfx.mk b/sfx2/UIConfig_sfx.mk
index 4ecfe45..a9eacaf 100644
--- a/sfx2/UIConfig_sfx.mk
+++ b/sfx2/UIConfig_sfx.mk
@@ -22,7 +22,7 @@ $(eval $(call gb_UIConfig_add_uifiles,sfx,\
	sfx2/uiconfig/ui/cmisinfopage \
	sfx2/uiconfig/ui/cmisline \
	sfx2/uiconfig/ui/custominfopage \
	sfx2/uiconfig/ui/decktitlebar \
	sfx2/uiconfig/ui/deck \
	sfx2/uiconfig/ui/descriptioninfopage \
	sfx2/uiconfig/ui/developmenttool \
	sfx2/uiconfig/ui/devtoolsmenu \
diff --git a/sfx2/inc/sidebar/DeckLayouter.hxx b/sfx2/inc/sidebar/DeckLayouter.hxx
index b84496c..c814abd 100644
--- a/sfx2/inc/sidebar/DeckLayouter.hxx
+++ b/sfx2/inc/sidebar/DeckLayouter.hxx
@@ -20,27 +20,26 @@

#include <sfx2/sidebar/Panel.hxx>

class ScrollBar;
namespace vcl { class Window; }
namespace tools { class Rectangle; }

namespace sfx2::sidebar {

class DeckTitleBar;
class SidebarDockingWindow;

/** Helper for layouting the direct and indirect children of a
    deck like title bars, panels, and scroll bars.
*/
namespace DeckLayouter
{
    void LayoutDeck (
        SidebarDockingWindow* pDockingWindow,
        const tools::Rectangle& rContentArea,
        sal_Int32& rMinimalWidth,
        sal_Int32& rMinimalHeight,
        SharedPanelContainer& rPanels,
        vcl::Window& pDeckTitleBar,
        vcl::Window& pScrollClipWindow,
        vcl::Window& pScrollContainer,
        vcl::Window& pFiller,
        ScrollBar& pVerticalScrollBar);
        DeckTitleBar& pDeckTitleBar,
        weld::ScrolledWindow& pVerticalScrollBar);
}

} // end of namespace sfx2::sidebar
diff --git a/sfx2/inc/sidebar/DeckTitleBar.hxx b/sfx2/inc/sidebar/DeckTitleBar.hxx
index cad5dac..1566b89 100644
--- a/sfx2/inc/sidebar/DeckTitleBar.hxx
+++ b/sfx2/inc/sidebar/DeckTitleBar.hxx
@@ -23,14 +23,14 @@

namespace sfx2::sidebar
{
class Deck;
class GripWidget;

class DeckTitleBar final : public TitleBar
{
public:
    DeckTitleBar(const OUString& rsTitle, vcl::Window* pParentWindow,
    DeckTitleBar(const OUString& rsTitle, weld::Builder& rBuilder,
                 const std::function<void()>& rCloserAction);
    virtual void dispose() override;
    virtual ~DeckTitleBar() override;

    virtual void SetTitle(const OUString& rsTitle) override;
@@ -39,7 +39,7 @@ public:
    void SetCloserVisible(const bool bIsCloserVisible);
    tools::Rectangle GetDragArea();

    virtual void DataChanged(const DataChangedEvent& rEvent) override;
    virtual void DataChanged() override;

private:
    virtual void HandleToolBoxItemClick() override;
diff --git a/sfx2/inc/sidebar/PanelTitleBar.hxx b/sfx2/inc/sidebar/PanelTitleBar.hxx
index 64a7783..8a90f8a 100644
--- a/sfx2/inc/sidebar/PanelTitleBar.hxx
+++ b/sfx2/inc/sidebar/PanelTitleBar.hxx
@@ -28,8 +28,7 @@ namespace sfx2::sidebar {

class Panel;

class PanelTitleBar final
    : public TitleBarBase
class PanelTitleBar final : public TitleBar
{
public:
    PanelTitleBar(const OUString& rsTitle, weld::Builder& rBuilder, Panel* pPanel);
@@ -37,17 +36,12 @@ public:

    virtual void SetTitle (const OUString& rsTitle) override;
    virtual OUString GetTitle() const override;
    virtual bool GetVisible() const override;

    void SetMoreOptionsCommand(const OUString& rsCommandName,
                               const css::uno::Reference<css::frame::XFrame>& rxFrame,
                               const css::uno::Reference<css::frame::XController>& rxController);

    void UpdateExpandedState();
    void Show(bool bShow)
    {
        mxTitlebar->set_visible(bShow);
    }

    weld::Expander& GetExpander()
    {
@@ -59,12 +53,11 @@ private:

    DECL_LINK(ExpandHdl, weld::Expander&, void);

    std::unique_ptr<weld::Container> mxTitlebar;
    std::unique_ptr<weld::Expander> mxExpander;

    css::uno::Reference<css::frame::XToolbarController> mxController;

    VclPtr<Panel> mpPanel;
    Panel* mpPanel;
    OString msIdent;
    OUString msMoreOptionsCommand;
};
diff --git a/sfx2/inc/sidebar/TitleBar.hxx b/sfx2/inc/sidebar/TitleBar.hxx
index 425e859..4672342 100644
--- a/sfx2/inc/sidebar/TitleBar.hxx
+++ b/sfx2/inc/sidebar/TitleBar.hxx
@@ -21,20 +21,24 @@
#include <sidebar/SidebarToolBox.hxx>
#include <sfx2/sidebar/Theme.hxx>
#include <sfx2/weldutils.hxx>
#include <vcl/InterimItemWindow.hxx>

namespace sfx2::sidebar {

class TitleBarBase
class TitleBar
{
public:
    TitleBarBase(weld::Builder& rBuilder, Theme::ThemeItem eThemeItem);
    void reset();
    virtual ~TitleBarBase();
    TitleBar(weld::Builder& rBuilder, Theme::ThemeItem eThemeItem);
    virtual ~TitleBar();

    virtual void SetTitle (const OUString& rsTitle) = 0;
    virtual OUString GetTitle() const = 0;
    virtual bool GetVisible() const = 0;

    virtual void DataChanged();

    void Show(bool bShow);
    bool GetVisible() const;

    Size get_preferred_size() const;

    void SetIcon(const css::uno::Reference<css::graphic::XGraphic>& rIcon);

@@ -49,6 +53,7 @@ public:

protected:
    weld::Builder& mrBuilder;
    std::unique_ptr<weld::Container> mxTitlebar;
    std::unique_ptr<weld::Image> mxAddonImage;
    std::unique_ptr<weld::Toolbar> mxToolBox;
    std::unique_ptr<ToolbarUnoDispatcher> mxToolBoxController;
@@ -57,20 +62,9 @@ protected:
    virtual void HandleToolBoxItemClick() = 0;

    DECL_LINK(SelectionHandler, const OString&, void);
};

class TitleBar : public InterimItemWindow
               , public TitleBarBase
{
public:
    TitleBar(vcl::Window* pParentWindow,
             const OUString& rUIXMLDescription, const OString& rID,
             Theme::ThemeItem eThemeItem);
    virtual void dispose() override;
    virtual bool GetVisible() const override { return IsVisible(); }
    virtual ~TitleBar() override;

    virtual void DataChanged (const DataChangedEvent& rEvent) override;
private:
    void SetBackground();
};

} // end of namespace sfx2::sidebar
diff --git a/sfx2/inc/sidebar/UnoPanel.hxx b/sfx2/inc/sidebar/UnoPanel.hxx
index 50d9aba..2b1197e 100644
--- a/sfx2/inc/sidebar/UnoPanel.hxx
+++ b/sfx2/inc/sidebar/UnoPanel.hxx
@@ -60,7 +60,7 @@ private:
    const OUString mDeckId;

    VclPtr<sfx2::sidebar::Deck> mpDeck;
    VclPtr<sfx2::sidebar::Panel> mpPanel;
    std::weak_ptr<sfx2::sidebar::Panel> mxPanel;

    sal_Int32 GetMaxOrderIndex(sfx2::sidebar::ResourceManager::PanelContextDescriptorContainer aPanels);
    sal_Int32 GetMinOrderIndex(sfx2::sidebar::ResourceManager::PanelContextDescriptorContainer aPanels);
diff --git a/sfx2/source/sidebar/Deck.cxx b/sfx2/source/sidebar/Deck.cxx
index 7444f7f..4b0eb65 100644
--- a/sfx2/source/sidebar/Deck.cxx
+++ b/sfx2/source/sidebar/Deck.cxx
@@ -24,6 +24,7 @@
#include <sidebar/DeckTitleBar.hxx>
#include <sidebar/PanelTitleBar.hxx>
#include <sfx2/sidebar/Panel.hxx>
#include <sfx2/sidebar/SidebarDockingWindow.hxx>
#include <sfx2/sidebar/Theme.hxx>
#include <sfx2/viewsh.hxx>

@@ -42,36 +43,24 @@ using namespace css::uno;

namespace sfx2::sidebar {

Deck::Deck(const DeckDescriptor& rDeckDescriptor, vcl::Window* pParentWindow,
Deck::Deck(const DeckDescriptor& rDeckDescriptor, SidebarDockingWindow* pParentWindow,
           const std::function<void()>& rCloserAction)
    : Window(pParentWindow, 0)
    : InterimItemWindow(pParentWindow, "sfx/ui/deck.ui", "Deck")
    , msId(rDeckDescriptor.msId)
    , mnMinimalWidth(0)
    , mnMinimalHeight(0)
    , maPanels()
    , mpTitleBar(VclPtr<DeckTitleBar>::Create(rDeckDescriptor.msTitle, this, rCloserAction))
    , mpScrollClipWindow(VclPtr<vcl::Window>::Create(this))
    , mpScrollContainer(VclPtr<ScrollContainerWindow>::Create(mpScrollClipWindow.get()))
    , mpFiller(VclPtr<vcl::Window>::Create(this))
    , mpVerticalScrollBar(VclPtr<ScrollBar>::Create(this))
    , mxParentWindow(pParentWindow)
    , mxTitleBar(new DeckTitleBar(rDeckDescriptor.msTitle, *m_xBuilder, rCloserAction))
    , mxVerticalScrollBar(m_xBuilder->weld_scrolled_window("scrolledwindow"))
    , mxContents(m_xBuilder->weld_container("contents"))
{
    mpScrollClipWindow->SetBackground(Wallpaper());
    mpScrollClipWindow->Show();
    SetStyle(GetStyle() | WB_DIALOGCONTROL);

    mpScrollContainer->SetStyle(mpScrollContainer->GetStyle() | WB_DIALOGCONTROL);
    mpScrollContainer->SetBackground(Wallpaper());
    mpScrollContainer->Show();
    m_xContainer->set_background(Theme::GetColor(Theme::Color_DeckBackground));

    mpVerticalScrollBar->SetScrollHdl(LINK(this, Deck, HandleVerticalScrollBarChange));
    mpVerticalScrollBar->SetLineSize(10);
    mpVerticalScrollBar->SetPageSize(100);

#ifdef DEBUG
    SetText(OUString("Deck"));
    mpScrollClipWindow->SetText(OUString("ScrollClipWindow"));
    mpFiller->SetText(OUString("Filler"));
    mpVerticalScrollBar->SetText(OUString("VerticalScrollBar"));
#endif
    mxVerticalScrollBar->vadjustment_set_step_increment(10);
    mxVerticalScrollBar->vadjustment_set_page_increment(100);
}

Deck::~Deck()
@@ -87,22 +76,22 @@ void Deck::dispose()
    // We have to explicitly trigger the destruction of panels.
    // Otherwise that is done by one of our base class destructors
    // without updating maPanels.
    for (VclPtr<Panel> & rpPanel : aPanels)
        rpPanel.disposeAndClear();
    for (auto& rpPanel : aPanels)
        rpPanel.reset();

    maPanels.clear(); // just to keep the loplugin:vclwidgets happy
    mpTitleBar.disposeAndClear();
    mpFiller.disposeAndClear();
    mpVerticalScrollBar.disposeAndClear();
    mpScrollContainer.disposeAndClear();
    mpScrollClipWindow.disposeAndClear();
    maPanels.clear();
    mxTitleBar.reset();
    mxContents.reset();
    mxVerticalScrollBar.reset();

    vcl::Window::dispose();
    mxParentWindow.clear();

    InterimItemWindow::dispose();
}

VclPtr<DeckTitleBar> const & Deck::GetTitleBar() const
DeckTitleBar* Deck::GetTitleBar() const
{
    return mpTitleBar;
    return mxTitleBar.get();
}

tools::Rectangle Deck::GetContentArea() const
@@ -119,65 +108,17 @@ tools::Rectangle Deck::GetContentArea() const
        aWindowSize.Height() - 1 - Theme::GetInteger(Theme::Int_DeckBottomPadding) - nBorderSize);
}

void Deck::ApplySettings(vcl::RenderContext& rRenderContext)
void Deck::DataChanged(const DataChangedEvent&)
{
    rRenderContext.SetBackground(Wallpaper());
}
    for (auto& rpPanel : maPanels)
        rpPanel->DataChanged();

void Deck::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rUpdateArea*/)
{
    const Size aWindowSize (GetSizePixel());
    const SvBorder aPadding(Theme::GetInteger(Theme::Int_DeckLeftPadding),
                            Theme::GetInteger(Theme::Int_DeckTopPadding),
                            Theme::GetInteger(Theme::Int_DeckRightPadding),
                            Theme::GetInteger(Theme::Int_DeckBottomPadding));

    // Paint deck background outside the border.
    tools::Rectangle aBox(0, 0, aWindowSize.Width() - 1, aWindowSize.Height() - 1);
    DrawHelper::DrawBorder(rRenderContext, aBox, aPadding,
                           Theme::GetColor(Theme::Color_DeckBackground),
                           Theme::GetColor(Theme::Color_DeckBackground));

    // Paint the border.
    const int nBorderSize(Theme::GetInteger(Theme::Int_DeckBorderSize));
    aBox.AdjustLeft(aPadding.Left() );
    aBox.AdjustTop(aPadding.Top() );
    aBox.AdjustRight( -(aPadding.Right()) );
    aBox.AdjustBottom( -(aPadding.Bottom()) );
    const Color nHorizontalBorderPaint(Theme::GetColor(Theme::Color_HorizontalBorder));
    DrawHelper::DrawBorder(rRenderContext, aBox,
                           SvBorder(nBorderSize, nBorderSize, nBorderSize, nBorderSize),
                           nHorizontalBorderPaint,
                           Theme::GetColor(Theme::Color_VerticalBorder));
}

void Deck::DataChanged (const DataChangedEvent&)
{
    RequestLayoutInternal();
}

bool Deck::EventNotify(NotifyEvent& rEvent)
{
    if (rEvent.GetType() == MouseNotifyEvent::COMMAND)
    {
        CommandEvent* pCommandEvent = static_cast<CommandEvent*>(rEvent.GetData());
        if (pCommandEvent != nullptr)
            switch (pCommandEvent->GetCommand())
            {
                case CommandEventId::Wheel:
                    return ProcessWheelEvent(pCommandEvent);

                default:
                    break;
            }
    }

    return Window::EventNotify(rEvent);
}

void Deck::Resize()
{
    Window::Resize();
    InterimItemWindow::Resize();

    if (const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier())
    {
@@ -207,52 +148,26 @@ void Deck::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
            continue;

        // collapse the panel itself out
        auto xContent = it->GetElementWindow();
        if (!xContent.is())
            continue;
        VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xContent);
        if (!pWindow)
        auto xContent = it->GetContents();
        if (!xContent)
            continue;

        auto childNode = rJsonWriter.startStruct();
        rJsonWriter.put("id", it->GetId());
        rJsonWriter.put("type", "panel");
        rJsonWriter.put("text", it->GetText());
        rJsonWriter.put("text", it->GetTitle());
        rJsonWriter.put("enabled", true);

        {
            auto children2Node = rJsonWriter.startArray("children");
            {
                auto child2Node = rJsonWriter.startStruct();
                pWindow->DumpAsPropertyTree(rJsonWriter);
                xContent->get_property_tree(rJsonWriter);
            }
        }
    }
}

bool Deck::ProcessWheelEvent(CommandEvent const * pCommandEvent)
{
    if ( ! mpVerticalScrollBar)
        return false;
    if ( ! mpVerticalScrollBar->IsVisible())
        return false;

    // Get the wheel data and check that it describes a valid vertical
    // scroll.
    const CommandWheelData* pData = pCommandEvent->GetWheelData();
    if (pData==nullptr
        || pData->GetModifier()
        || pData->GetMode() != CommandWheelMode::SCROLL
        || pData->IsHorz())
        return false;

    // Execute the actual scroll action.
    tools::Long nDelta = pData->GetDelta();
    mpVerticalScrollBar->DoScroll(
        mpVerticalScrollBar->GetThumbPos() - nDelta);
    return true;
}

/**
 * This container may contain existing panels that are
 * being re-used, and new ones too.
@@ -262,7 +177,7 @@ void Deck::ResetPanels(const SharedPanelContainer& rPanelContainer)
    SharedPanelContainer aHiddens;

    // First hide old panels we don't need just now.
    for (VclPtr<Panel> & rpPanel : maPanels)
    for (auto& rpPanel : maPanels)
    {
        bool bFound = false;
        for (const auto & i : rPanelContainer)
@@ -286,9 +201,9 @@ void Deck::RequestLayoutInternal()
    mnMinimalWidth = 0;
    mnMinimalHeight = 0;

    DeckLayouter::LayoutDeck(GetContentArea(), mnMinimalWidth, mnMinimalHeight, maPanels,
                             *GetTitleBar(), *mpScrollClipWindow, *mpScrollContainer,
                             *mpFiller, *mpVerticalScrollBar);
    DeckLayouter::LayoutDeck(mxParentWindow.get(), GetContentArea(),
                             mnMinimalWidth, mnMinimalHeight, maPanels,
                             *GetTitleBar(), *mxVerticalScrollBar);
}

void Deck::RequestLayout()
@@ -323,18 +238,18 @@ void Deck::RequestLayout()
        setPosSizePixel(0, 0, aParentSize.Width(), aParentSize.Height());
}

vcl::Window* Deck::GetPanelParentWindow()
weld::Widget* Deck::GetPanelParentWindow()
{
    return mpScrollContainer.get();
    return mxContents.get();
}

Panel* Deck::GetPanel(std::u16string_view panelId)
std::shared_ptr<Panel> Deck::GetPanel(std::u16string_view panelId)
{
    for (const VclPtr<Panel> & pPanel : maPanels)
    for (const auto& pPanel : maPanels)
    {
        if(pPanel->GetId() == panelId)
        {
            return pPanel.get();
            return pPanel;
        }
    }
    return nullptr;
@@ -343,69 +258,27 @@ Panel* Deck::GetPanel(std::u16string_view panelId)

void Deck::ShowPanel(const Panel& rPanel)
{
    if (!mpVerticalScrollBar || !mpVerticalScrollBar->IsVisible())
    if (!mxVerticalScrollBar || mxVerticalScrollBar->get_vpolicy() == VclPolicyType::NEVER)
        return;

    // Get vertical extent of the panel.
    sal_Int32 nPanelTop (rPanel.GetPosPixel().Y());
    const sal_Int32 nPanelBottom (nPanelTop + rPanel.GetSizePixel().Height() - 1);
    tools::Rectangle aExtents;
    if (!rPanel.get_extents(aExtents))
        return;

    auto nPanelTop = aExtents.Top();
    auto nPanelBottom = aExtents.Bottom() - 1;

    // Determine what the new thumb position should be like.
    // When the whole panel does not fit then make its top visible
    // and it off at the bottom.
    sal_Int32 nNewThumbPos (mpVerticalScrollBar->GetThumbPos());
    if (nPanelBottom >= nNewThumbPos+mpVerticalScrollBar->GetVisibleSize())
        nNewThumbPos = nPanelBottom - mpVerticalScrollBar->GetVisibleSize();
    sal_Int32 nNewThumbPos(mxVerticalScrollBar->vadjustment_get_value());
    if (nPanelBottom >= nNewThumbPos + mxVerticalScrollBar->vadjustment_get_page_size())
        nNewThumbPos = nPanelBottom - mxVerticalScrollBar->vadjustment_get_page_size();
    if (nPanelTop < nNewThumbPos)
        nNewThumbPos = nPanelTop;

    mpVerticalScrollBar->SetThumbPos(nNewThumbPos);
    mpScrollContainer->SetPosPixel(
        Point(
            mpScrollContainer->GetPosPixel().X(),
            -nNewThumbPos));
}

IMPL_LINK_NOARG(Deck, HandleVerticalScrollBarChange, ScrollBar*, void)
{
    const sal_Int32 nYOffset (-mpVerticalScrollBar->GetThumbPos());
    mpScrollContainer->SetPosPixel(Point(mpScrollContainer->GetPosPixel().X(),
                                         nYOffset));
    mpScrollContainer->Invalidate();
}

//----- Deck::ScrollContainerWindow -------------------------------------------

Deck::ScrollContainerWindow::ScrollContainerWindow (vcl::Window* pParentWindow)
    : Window(pParentWindow),
      maSeparators()
{
#ifdef DEBUG
    SetText(OUString("ScrollContainerWindow"));
#endif
}

void Deck::ScrollContainerWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rUpdateArea*/)
{
    // Paint the separators.
    const sal_Int32 nSeparatorHeight(Theme::GetInteger(Theme::Int_DeckSeparatorHeight));
    const sal_Int32 nLeft(0);
    const sal_Int32 nRight(GetSizePixel().Width() - 1);
    const Color nHorizontalBorderPaint(Theme::GetColor(Theme::Color_HorizontalBorder));
    for (auto const& separator : maSeparators)
    {
        DrawHelper::DrawHorizontalLine(rRenderContext, nLeft, nRight, separator,
                                       nSeparatorHeight, nHorizontalBorderPaint);
    }
}

void Deck::ScrollContainerWindow::SetSeparators (const ::std::vector<sal_Int32>& rSeparators)
{
    if (rSeparators != maSeparators)
    {
        maSeparators = rSeparators;
        Invalidate();
    }
    mxVerticalScrollBar->vadjustment_set_value(nNewThumbPos);
}

} // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/DeckLayouter.cxx b/sfx2/source/sidebar/DeckLayouter.cxx
index 0509898..36d6357e 100644
--- a/sfx2/source/sidebar/DeckLayouter.cxx
+++ b/sfx2/source/sidebar/DeckLayouter.cxx
@@ -18,10 +18,12 @@
 */

#include <sidebar/DeckLayouter.hxx>
#include <sfx2/sidebar/Theme.hxx>
#include <sfx2/sidebar/Panel.hxx>
#include <sidebar/DeckTitleBar.hxx>
#include <sidebar/PanelTitleBar.hxx>
#include <sfx2/sidebar/Deck.hxx>
#include <sfx2/sidebar/Panel.hxx>
#include <sfx2/sidebar/Theme.hxx>
#include <sfx2/sidebar/SidebarDockingWindow.hxx>
#include <sfx2/sidebar/SidebarController.hxx>
#include <comphelper/lok.hxx>

@@ -52,14 +54,14 @@ namespace {
    class LayoutItem
    {
    public:
        VclPtr<Panel> mpPanel;
        std::shared_ptr<Panel> mpPanel;
        css::ui::LayoutSize maLayoutSize;
        sal_Int32 mnDistributedHeight;
        sal_Int32 mnWeight;
        bool mbShowTitleBar;

        LayoutItem(const VclPtr<Panel>& rPanel)
            : mpPanel(rPanel)
        LayoutItem(std::shared_ptr<Panel>& pPanel)
            : mpPanel(pPanel)
            , maLayoutSize(0, 0, 0)
            , mnDistributedHeight(0)
            , mnWeight(0)
@@ -67,14 +69,12 @@ namespace {
        {
        }
    };
    tools::Rectangle LayoutPanels (
    void LayoutPanels (
        const tools::Rectangle& rContentArea,
        sal_Int32& rMinimalWidth,
        sal_Int32& rMinimalHeight,
        ::std::vector<LayoutItem>& rLayoutItems,
        vcl::Window& rScrollClipWindow,
        vcl::Window& rScrollContainer,
        ScrollBar& pVerticalScrollBar,
        weld::ScrolledWindow& pVerticalScrollBar,
        const bool bShowVerticalScrollBar);
    void GetRequestedSizes (
        ::std::vector<LayoutItem>& rLayoutItem,
@@ -86,81 +86,66 @@ namespace {
        const sal_Int32 nHeightToDistribute,
        const sal_Int32 nContainerHeight,
        const bool bMinimumHeightIsBase);
    bool MoveResizePixel(const VclPtr<vcl::Window> &pWindow,
                         const Point &rNewPos, const Size &rNewSize);
    sal_Int32 PlacePanels (
        ::std::vector<LayoutItem>& rLayoutItems,
        const sal_Int32 nWidth,
        const LayoutMode eMode,
        vcl::Window& rScrollContainer);
        const LayoutMode eMode_);
    tools::Rectangle PlaceDeckTitle (
        vcl::Window& rTitleBar,
        SidebarDockingWindow* pDockingWindow,
        DeckTitleBar& rTitleBar,
        const tools::Rectangle& rAvailableSpace);
    tools::Rectangle PlaceVerticalScrollBar (
        ScrollBar& rVerticalScrollBar,
        weld::ScrolledWindow& rVerticalScrollBar,
        const tools::Rectangle& rAvailableSpace,
        const bool bShowVerticalScrollBar);
    void SetupVerticalScrollBar(
        ScrollBar& rVerticalScrollBar,
        weld::ScrolledWindow& rVerticalScrollBar,
        const sal_Int32 nContentHeight,
        const sal_Int32 nVisibleHeight);
    void UpdateFiller (
        vcl::Window& rFiller,
        const tools::Rectangle& rBox);
}

void DeckLayouter::LayoutDeck (
    SidebarDockingWindow* pDockingWindow,
    const tools::Rectangle& rContentArea,
    sal_Int32& rMinimalWidth,
    sal_Int32& rMinimalHeight,
    SharedPanelContainer& rPanels,
    vcl::Window& rDeckTitleBar,
    vcl::Window& rScrollClipWindow,
    vcl::Window& rScrollContainer,
    vcl::Window& rFiller,
    ScrollBar& rVerticalScrollBar)
    DeckTitleBar& rDeckTitleBar,
    weld::ScrolledWindow& rVerticalScrollBar)
{
    if (rContentArea.GetWidth()<=0 || rContentArea.GetHeight()<=0)
        return;
    tools::Rectangle aBox (PlaceDeckTitle(rDeckTitleBar, rContentArea));
    tools::Rectangle aBox(PlaceDeckTitle(pDockingWindow, rDeckTitleBar, rContentArea));

    if ( ! rPanels.empty())
    {
        // Prepare the layout item container.
        ::std::vector<LayoutItem> aLayoutItems;
        aLayoutItems.reserve(rPanels.size());
        for (const auto& rPanel : rPanels)
        for (auto& rPanel : rPanels)
            aLayoutItems.emplace_back(rPanel);

        aBox = LayoutPanels(
        LayoutPanels(
            aBox,
            rMinimalWidth,
            rMinimalHeight,
            aLayoutItems,
            rScrollClipWindow,
            rScrollContainer,
            rVerticalScrollBar,
            false);
    }
    UpdateFiller(rFiller, aBox);
}

namespace {

tools::Rectangle LayoutPanels (
void LayoutPanels (
    const tools::Rectangle& rContentArea,
    sal_Int32& rMinimalWidth,
    sal_Int32& rMinimalHeight,
    ::std::vector<LayoutItem>& rLayoutItems,
    vcl::Window& rScrollClipWindow,
    vcl::Window& rScrollContainer,
    ScrollBar& rVerticalScrollBar,
    weld::ScrolledWindow& rVerticalScrollBar,
    const bool bShowVerticalScrollBar)
{
    tools::Rectangle aBox (PlaceVerticalScrollBar(rVerticalScrollBar, rContentArea, bShowVerticalScrollBar));

    const sal_Int32 nWidth (aBox.GetWidth());

    // Get the requested heights of the panels and the available
    // height that is left when all panel titles and separators are
    // taken into account.
@@ -186,15 +171,14 @@ tools::Rectangle LayoutPanels (
        // Not enough space, even when all panels are shrunk to their
        // minimum height.
        // Show a vertical scrollbar.
        return LayoutPanels(
        LayoutPanels(
            rContentArea,
            rMinimalWidth,
            rMinimalHeight,
            rLayoutItems,
            rScrollClipWindow,
            rScrollContainer,
            rVerticalScrollBar,
            true);
        return;
    }

    // We are now in one of three modes.
@@ -227,58 +211,26 @@ tools::Rectangle LayoutPanels (
            eMode==MinimumOrLarger);
    }

    // Set position and size of the mpScrollClipWindow to the available
    // size.  Its child, the mpScrollContainer, may have a bigger
    // height.
    rScrollClipWindow.setPosSizePixel(aBox.Left(), aBox.Top(), aBox.GetWidth(), aBox.GetHeight());

    const sal_Int32 nContentHeight (
        eMode==Preferred
            ? nTotalPreferredHeight + nTotalDecorationHeight
            : aBox.GetHeight());
    sal_Int32 nY = rVerticalScrollBar.GetThumbPos();
    if (nContentHeight-nY < aBox.GetHeight())
        nY = nContentHeight-aBox.GetHeight();
    if (nY < 0)
        nY = 0;
    rScrollContainer.setPosSizePixel(
        0,
        -nY,
        nWidth,
        nContentHeight);

    if (bShowVerticalScrollBar)
    {
        const sal_Int32 nContentHeight(
            eMode==Preferred
                ? nTotalPreferredHeight + nTotalDecorationHeight
                : aBox.GetHeight());
        SetupVerticalScrollBar(rVerticalScrollBar, nContentHeight, aBox.GetHeight());
    }

    const sal_Int32 nUsedHeight (PlacePanels(rLayoutItems, nWidth, eMode, rScrollContainer));
    aBox.AdjustTop(nUsedHeight );
    const sal_Int32 nUsedHeight(PlacePanels(rLayoutItems, eMode));
    rMinimalHeight = nUsedHeight;
    return aBox;
}

bool MoveResizePixel(const VclPtr<vcl::Window> &pWindow,
                     const Point &rNewPos, const Size &rNewSize)
{
    Point aCurPos = pWindow->GetPosPixel();
    Size aCurSize = pWindow->GetSizePixel();
    if (rNewPos == aCurPos && aCurSize == rNewSize)
        return false;
    pWindow->setPosSizePixel(rNewPos.X(), rNewPos.Y(), rNewSize.Width(), rNewSize.Height());
    return true;
}

sal_Int32 PlacePanels (
    ::std::vector<LayoutItem>& rLayoutItems,
    const sal_Int32 nWidth,
    const LayoutMode eMode,
    vcl::Window& rScrollContainer)
    const LayoutMode eMode)
{
    ::std::vector<sal_Int32> aSeparators;
    const sal_Int32 nDeckSeparatorHeight (Theme::GetInteger(Theme::Int_DeckSeparatorHeight));
    sal_Int32 nY (0);

    vcl::Region aInvalidRegions;

    // Assign heights and places.
    for(::std::vector<LayoutItem>::const_iterator iItem(rLayoutItems.begin()),
         iEnd(rLayoutItems.end());
@@ -290,22 +242,26 @@ sal_Int32 PlacePanels (

        Panel& rPanel (*iItem->mpPanel);

        rPanel.set_margin_top(nDeckSeparatorHeight);
        rPanel.set_margin_bottom(0);

        // Separator above the panel title bar.
        if (!rPanel.IsLurking())
        {
            aSeparators.push_back(nY);
            nY += nDeckSeparatorHeight;
        }

        const sal_Int32 nPanelTitleBarHeight(Theme::GetInteger(Theme::Int_PanelTitleBarHeight) * rPanel.GetDPIScaleFactor());

        bool bShowTitlebar = iItem->mbShowTitleBar;
        rPanel.ShowTitlebar(bShowTitlebar);
        PanelTitleBar* pTitleBar = rPanel.GetTitleBar();
        pTitleBar->Show(bShowTitlebar);
        rPanel.set_vexpand(!bShowTitlebar);
        weld::Container* pContents = rPanel.GetContents();
        pContents->set_vexpand(true);

        bool bExpanded = rPanel.IsExpanded() && !rPanel.IsLurking();
        if (bShowTitlebar || bExpanded)
        {
            rPanel.Show();
            rPanel.Show(true);

            sal_Int32 nPanelHeight(0);
            if (bExpanded)
@@ -329,24 +285,15 @@ sal_Int32 PlacePanels (
                }
            }
            if (bShowTitlebar)
                nPanelHeight += nPanelTitleBarHeight;
                nPanelHeight += pTitleBar->get_preferred_size().Height();

            // Place the panel.
            Point aNewPos(0, nY);
            Size  aNewSize(nWidth, nPanelHeight);

            // Only invalidate if we moved
            if (MoveResizePixel(&rPanel, aNewPos, aNewSize))
            {
                tools::Rectangle aRect(aNewPos, aNewSize);
                aInvalidRegions.Union(rPanel.PixelToLogic(aRect));
            }
            rPanel.SetHeightPixel(nPanelHeight);

            nY += nPanelHeight;
        }
        else
        {
            rPanel.Hide();
            rPanel.Show(false);
        }

        if (!bExpanded)
@@ -356,19 +303,12 @@ sal_Int32 PlacePanels (
            if (iItem == rLayoutItems.end()-1)
            {
                // Separator below the panel title bar.
                aSeparators.push_back(nY);
                rPanel.set_margin_bottom(nDeckSeparatorHeight);
                nY += nDeckSeparatorHeight;
            }
        }
    }

    Deck::ScrollContainerWindow* pScrollContainerWindow
        = dynamic_cast<Deck::ScrollContainerWindow*>(&rScrollContainer);
    if (pScrollContainerWindow != nullptr)
        pScrollContainerWindow->SetSeparators(aSeparators);

    rScrollContainer.Invalidate(aInvalidRegions);

    return nY;
}

@@ -407,7 +347,8 @@ void GetRequestedSizes (
        {
            // Show the title bar and a separator above and below
            // the title bar.
            const sal_Int32 nPanelTitleBarHeight (Theme::GetInteger(Theme::Int_PanelTitleBarHeight) * rItem.mpPanel->GetDPIScaleFactor());
            PanelTitleBar* pTitleBar = rItem.mpPanel->GetTitleBar();
            const sal_Int32 nPanelTitleBarHeight = pTitleBar->get_preferred_size().Height();

            rAvailableHeight -= nPanelTitleBarHeight;
            rAvailableHeight -= nDeckSeparatorHeight;
@@ -548,25 +489,21 @@ void DistributeHeights (
    OSL_ASSERT(nRemainingHeightToDistribute==0);
}

tools::Rectangle PlaceDeckTitle (
    vcl::Window& rDeckTitleBar,
tools::Rectangle PlaceDeckTitle(
    SidebarDockingWindow* pDockingWindow,
    DeckTitleBar& rDeckTitleBar,
    const tools::Rectangle& rAvailableSpace)
{
    if (static_cast<DockingWindow*>(rDeckTitleBar.GetParent()->GetParent())->IsFloatingMode())
    if (pDockingWindow->IsFloatingMode())
    {
        // When the side bar is undocked then the outer system window displays the deck title.
        rDeckTitleBar.Hide();
        rDeckTitleBar.Show(false);
        return rAvailableSpace;
    }
    else
    {
        const sal_Int32 nDeckTitleBarHeight (Theme::GetInteger(Theme::Int_DeckTitleBarHeight) * rDeckTitleBar.GetDPIScaleFactor());
        rDeckTitleBar.setPosSizePixel(
            rAvailableSpace.Left(),
            rAvailableSpace.Top(),
            rAvailableSpace.GetWidth(),
            nDeckTitleBarHeight);
        rDeckTitleBar.Show();
        rDeckTitleBar.Show(true);
        const sal_Int32 nDeckTitleBarHeight(rDeckTitleBar.get_preferred_size().Height());
        return tools::Rectangle(
            rAvailableSpace.Left(),
            rAvailableSpace.Top() + nDeckTitleBarHeight,
@@ -576,19 +513,14 @@ tools::Rectangle PlaceDeckTitle (
}

tools::Rectangle PlaceVerticalScrollBar (
    ScrollBar& rVerticalScrollBar,
    weld::ScrolledWindow& rVerticalScrollBar,
    const tools::Rectangle& rAvailableSpace,
    const bool bShowVerticalScrollBar)
{
    if (bShowVerticalScrollBar)
    {
        const sal_Int32 nScrollBarWidth (rVerticalScrollBar.GetSizePixel().Width());
        rVerticalScrollBar.setPosSizePixel(
            rAvailableSpace.Right() - nScrollBarWidth + 1,
            rAvailableSpace.Top(),
            nScrollBarWidth,
            rAvailableSpace.GetHeight());
        rVerticalScrollBar.Show();
        const sal_Int32 nScrollBarWidth(rVerticalScrollBar.get_scroll_thickness());
        rVerticalScrollBar.set_vpolicy(VclPolicyType::ALWAYS);
        return tools::Rectangle(
            rAvailableSpace.Left(),
            rAvailableSpace.Top(),
@@ -597,44 +529,20 @@ tools::Rectangle PlaceVerticalScrollBar (
    }
    else
    {
        rVerticalScrollBar.Hide();
        rVerticalScrollBar.set_vpolicy(VclPolicyType::NEVER);
        return rAvailableSpace;
    }
}

void SetupVerticalScrollBar(
    ScrollBar& rVerticalScrollBar,
    weld::ScrolledWindow& rVerticalScrollBar,
    const sal_Int32 nContentHeight,
    const sal_Int32 nVisibleHeight)
{
    OSL_ASSERT(nContentHeight > nVisibleHeight);

    rVerticalScrollBar.SetRangeMin(0);
    rVerticalScrollBar.SetRangeMax(nContentHeight-1);
    rVerticalScrollBar.SetVisibleSize(nVisibleHeight);
}

void UpdateFiller (
    vcl::Window& rFiller,
    const tools::Rectangle& rBox)
{
    if (comphelper::LibreOfficeKit::isActive())
    {
        // Not shown on LOK, and causes invalidation thrash
        rFiller.Hide();
    }
    else if (rBox.GetHeight() > 0)
    {
        // Show the filler.
        rFiller.SetBackground(Theme::GetColor(Theme::Color_PanelBackground));
        rFiller.SetPosSizePixel(rBox.TopLeft(), rBox.GetSize());
        rFiller.Show();
    }
    else
    {
        // Hide the filler.
        rFiller.Hide();
    }
    rVerticalScrollBar.vadjustment_set_upper(nContentHeight-1);
    rVerticalScrollBar.vadjustment_set_page_size(nVisibleHeight);
}

}
diff --git a/sfx2/source/sidebar/DeckTitleBar.cxx b/sfx2/source/sidebar/DeckTitleBar.cxx
index 59e9aa0..9a7e348 100644
--- a/sfx2/source/sidebar/DeckTitleBar.cxx
+++ b/sfx2/source/sidebar/DeckTitleBar.cxx
@@ -58,46 +58,30 @@ public:
};

DeckTitleBar::DeckTitleBar (const OUString& rsTitle,
                            vcl::Window* pParentWindow,
                            weld::Builder& rBuilder,
                            const std::function<void()>& rCloserAction)
    : TitleBar(pParentWindow, "sfx/ui/decktitlebar.ui", "DeckTitleBar",
               Theme::Color_DeckTitleBarBackground)
    : TitleBar(rBuilder, Theme::Color_DeckTitleBarBackground)
    , mxGripWidget(new GripWidget)
    , mxGripWeld(new weld::CustomWeld(*m_xBuilder, "grip", *mxGripWidget))
    , mxLabel(m_xBuilder->weld_label("label"))
    , mxGripWeld(new weld::CustomWeld(rBuilder, "grip", *mxGripWidget))
    , mxLabel(rBuilder.weld_label("label"))
    , maCloserAction(rCloserAction)
    , mbIsCloserVisible(false)
{
    mxLabel->set_label(rsTitle);
    mxGripWidget->SetPointer(PointerStyle::Move);

    OSL_ASSERT(pParentWindow != nullptr);

    if (maCloserAction)
        SetCloserVisible(true);

#ifdef DEBUG
    SetText(OUString("DeckTitleBar"));
#endif
}

DeckTitleBar::~DeckTitleBar()
{
    disposeOnce();
}

void DeckTitleBar::dispose()
{
    mxLabel.reset();
    mxGripWeld.reset();
    mxGripWidget.reset();
    TitleBar::dispose();
}

tools::Rectangle DeckTitleBar::GetDragArea()
{
    int x, y, width, height;
    if (mxGripWidget->GetDrawingArea()->get_extents_relative_to(*m_xContainer, x, y, width, height))
    if (mxGripWidget->GetDrawingArea()->get_extents_relative_to(*mxTitlebar, x, y, width, height))
        return tools::Rectangle(Point(x, y), Size(width, height));
    return tools::Rectangle();
}
@@ -128,10 +112,10 @@ void DeckTitleBar::HandleToolBoxItemClick()
        maCloserAction();
}

void DeckTitleBar::DataChanged (const DataChangedEvent& rEvent)
void DeckTitleBar::DataChanged()
{
    mxToolBox->set_item_icon_name("button", "sfx2/res/closedoc.png");
    TitleBar::DataChanged(rEvent);
    TitleBar::DataChanged();
}

} // end of namespace sfx2::sidebar
diff --git a/sfx2/source/sidebar/FocusManager.cxx b/sfx2/source/sidebar/FocusManager.cxx
index b513234..ebdc039 100644
--- a/sfx2/source/sidebar/FocusManager.cxx
+++ b/sfx2/source/sidebar/FocusManager.cxx
@@ -18,13 +18,13 @@
 */

#include <sfx2/sidebar/FocusManager.hxx>
#include <sfx2/sidebar/Deck.hxx>
#include <sfx2/sidebar/Panel.hxx>
#include <sidebar/DeckTitleBar.hxx>
#include <sidebar/PanelTitleBar.hxx>
#include <sidebar/TitleBar.hxx>
#include <vcl/event.hxx>
#include <vcl/svapp.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <vcl/weld.hxx>

namespace sfx2::sidebar {

@@ -35,7 +35,7 @@ FocusManager::FocusLocation::FocusLocation (const PanelComponent eComponent, con
}

FocusManager::FocusManager(const std::function<void(const Panel&)>& rShowPanelFunctor)
    : mpDeckTitleBar(),
    : mpDeckTitleBar(nullptr),
      maPanels(),
      maButtons(),
      maShowPanelFunctor(rShowPanelFunctor)
@@ -59,14 +59,14 @@ void FocusManager::GrabFocusPanel()

void FocusManager::Clear()
{
    SetDeckTitle(nullptr);
    SetDeck(nullptr);
    ClearPanels();
    ClearButtons();
}

void FocusManager::ClearPanels()
{
    std::vector<VclPtr<Panel> > aPanels;
    SharedPanelContainer aPanels;
    aPanels.swap(maPanels);
    for (auto const& panel : aPanels)
    {
@@ -76,7 +76,8 @@ void FocusManager::ClearPanels()
            UnregisterWindow(panel->GetTitleBar()->GetExpander());
        }

        panel->RemoveChildEventListener(LINK(this, FocusManager, ChildEventListener));
        weld::Container* pContents = panel->GetContents();
        UnregisterWindow(*pContents);
    }
}

@@ -90,12 +91,13 @@ void FocusManager::ClearButtons()
    }
}

void FocusManager::SetDeckTitle (DeckTitleBar* pDeckTitleBar)
void FocusManager::SetDeck(Deck* pDeck)
{
    DeckTitleBar* pDeckTitleBar = pDeck ? pDeck->GetTitleBar() : nullptr;
    if (mpDeckTitleBar != nullptr)
        UnregisterWindow(mpDeckTitleBar->GetToolBox());
    mxDeck = pDeck;
    mpDeckTitleBar = pDeckTitleBar;

    if (mpDeckTitleBar != nullptr)
        RegisterWindow(mpDeckTitleBar->GetToolBox());
}
@@ -111,10 +113,11 @@ void FocusManager::SetPanels (const SharedPanelContainer& rPanels)
            RegisterWindow(panel->GetTitleBar()->GetExpander());
        }

        // Register also as child event listener at the panel.
        panel->AddChildEventListener(LINK(this, FocusManager, ChildEventListener));
        // Register also as key event listener at the panel.
        weld::Container* pContents = panel->GetContents();
        RegisterWindow(*pContents);

        maPanels.emplace_back(panel.get());
        maPanels.emplace_back(panel);
    }
}

@@ -139,18 +142,6 @@ void FocusManager::UnregisterWindow(weld::Widget& rWidget)
    rWidget.connect_key_press(Link<const KeyEvent&, bool>());
}

FocusManager::FocusLocation FocusManager::GetFocusLocation (const vcl::Window& rWindow) const
{
    // Search the panels.
    for (size_t nIndex = 0; nIndex < maPanels.size(); ++nIndex)
    {
        if (maPanels[nIndex] == &rWindow)
            return FocusLocation(PC_PanelContent, nIndex);
    }

    return FocusLocation(PC_None, -1);
}

FocusManager::FocusLocation FocusManager::GetFocusLocation() const
{
    // Check the deck title.
@@ -167,6 +158,9 @@ FocusManager::FocusLocation FocusManager::GetFocusLocation() const
            return FocusLocation(PC_PanelTitle, nIndex);
        if (pTitleBar->GetToolBox().has_focus())
            return FocusLocation(PC_PanelToolBox, nIndex);
        weld::Container* pContents = maPanels[nIndex]->GetContents();
        if (pContents->has_child_focus())
            return FocusLocation(PC_PanelContent, nIndex);
    }

    // Search the buttons.
@@ -204,7 +198,7 @@ bool FocusManager::IsPanelTitleVisible (const sal_Int32 nPanelIndex) const
    if (nPanelIndex<0 || nPanelIndex>=static_cast<sal_Int32>(maPanels.size()))
        return false;

    TitleBarBase* pTitleBar = maPanels[nPanelIndex]->GetTitleBar();
    TitleBar* pTitleBar = maPanels[nPanelIndex]->GetTitleBar();
    if (!pTitleBar)
        return false;
    return pTitleBar->GetVisible();
@@ -247,14 +241,13 @@ void FocusManager::FocusPanel (
        maShowPanelFunctor(rPanel);
}

void FocusManager::FocusPanelContent (const sal_Int32 nPanelIndex)
void FocusManager::FocusPanelContent(const sal_Int32 nPanelIndex)
{
    if (!maPanels[nPanelIndex]->IsExpanded())
        maPanels[nPanelIndex]->SetExpanded(true);

    VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(maPanels[nPanelIndex]->GetElementWindow());
    if (pWindow)
        pWindow->GrabFocus();
    weld::Container* pContents = maPanels[nPanelIndex]->GetContents();
    pContents->child_grab_focus();
}

void FocusManager::FocusButton (const sal_Int32 nButtonIndex)
@@ -288,10 +281,11 @@ void FocusManager::MoveFocusInsidePanel (
    }
}

void FocusManager::MoveFocusInsideDeckTitle (
bool FocusManager::MoveFocusInsideDeckTitle (
    const FocusLocation& rFocusLocation,
    const sal_Int32 nDirection)
{
    bool bConsumed = false;
    // Note that when the title bar of the first (and only) panel is
    // not visible then the deck title takes its place and the focus
    // is moved between a) deck closer and b) content of panel 0.
@@ -299,11 +293,15 @@ void FocusManager::MoveFocusInsideDeckTitle (
    {
        case PC_DeckToolBox:
            if (nDirection>0 && ! IsPanelTitleVisible(0))
            {
                FocusPanelContent(0);
                bConsumed = true;
            }
            break;

        default: break;
    }
    return bConsumed;
}

bool FocusManager::HandleKeyEvent(
@@ -322,15 +320,21 @@ bool FocusManager::HandleKeyEvent(
                case PC_PanelTitle:
                case PC_PanelToolBox:
                {
                    vcl::Window* pFocusWin = Application::GetFocusWindow();
                    if (pFocusWin)
                    if (mxDeck)
                    {
                        pFocusWin->GrabFocusToDocument();
                        mxDeck->GrabFocusToDocument();
                        bConsumed = true;
                    }
                    break;
                }

                case PC_PanelContent:
                    // Return focus to tab bar sidebar settings button or panel title.
                    if (!IsDeckTitleVisible() && maPanels.size() == 1)
                        FocusButton(0);
                    else
                        FocusPanel(aLocation.mnIndex, true);
                    bConsumed = true;
                    break;
                default:
                    break;
            }
@@ -365,19 +369,31 @@ bool FocusManager::HandleKeyEvent(
            {
                case PC_PanelTitle:
                case PC_PanelToolBox:
                case PC_PanelContent:
                    MoveFocusInsidePanel(aLocation, nDirection);
                    bConsumed = true;
                    break;

                case PC_DeckToolBox:
                    MoveFocusInsideDeckTitle(aLocation, nDirection);
                    bConsumed = MoveFocusInsideDeckTitle(aLocation, nDirection);
                    break;

                case PC_TabBar:
                    if (rKeyCode.IsShift())
                        FocusPanel(maPanels.size()-1, true);
                    else
                    {
                        if (IsDeckTitleVisible())
                            FocusDeckTitle();
                        else
                            FocusPanel(0, true);
                    }
                    bConsumed = true;
                    break;

                default:
                    break;
            }
            fprintf(stderr, "seen here, consumed %d\n", bConsumed);
            break;
        }

@@ -387,7 +403,6 @@ bool FocusManager::HandleKeyEvent(
            {
                case PC_PanelTitle:
                case PC_PanelToolBox:
                case PC_PanelContent:
                    // Go to previous panel or the deck title.
                    if (aLocation.mnIndex > 0)
                        FocusPanel(aLocation.mnIndex-1, true);
@@ -437,7 +452,6 @@ bool FocusManager::HandleKeyEvent(
            {
                case PC_PanelTitle:
                case PC_PanelToolBox:
                case PC_PanelContent:
                    // Go to next panel.
                    if (aLocation.mnIndex < static_cast<sal_Int32>(maPanels.size())-1)
                        FocusPanel(aLocation.mnIndex+1, false);
@@ -488,56 +502,6 @@ IMPL_LINK(FocusManager, KeyInputHdl, const KeyEvent&, rKeyEvent, bool)
    return HandleKeyEvent(rKeyEvent.GetKeyCode(), GetFocusLocation());
}

IMPL_LINK(FocusManager, ChildEventListener, VclWindowEvent&, rEvent, void)
{
    vcl::Window* pSource = rEvent.GetWindow();
    if (pSource == nullptr)
        return;

    switch (rEvent.GetId())
    {
        case VclEventId::WindowKeyInput:
        {
            KeyEvent* pKeyEvent = static_cast<KeyEvent*>(rEvent.GetData());

            // Go up the window hierarchy to find out whether the
            // parent of the event source is known to us.
            vcl::Window* pWindow = pSource;
            FocusLocation aLocation (PC_None, -1);
            while (true)
            {
                if (pWindow == nullptr)
                    break;
                aLocation = GetFocusLocation(*pWindow);
                if (aLocation.meComponent != PC_None)
                    break;
                pWindow = pWindow->GetParent();
            }

            if (aLocation.meComponent != PC_None)
            {
                switch (pKeyEvent->GetKeyCode().GetCode())
                {
                    case KEY_ESCAPE:
                        // Return focus to tab bar sidebar settings button or panel title.
                        if (!IsDeckTitleVisible() && maPanels.size() == 1)
                            FocusButton(0);
                        else
                            FocusPanel(aLocation.mnIndex, true);
                        break;

                    default:
                        break;
                }
            }
            return;
        }

        default:
            break;
    }
}

} // end of namespace sfx2::sidebar

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/sidebar/Panel.cxx b/sfx2/source/sidebar/Panel.cxx
index f82ef61..2d799a3 100644
--- a/sfx2/source/sidebar/Panel.cxx
+++ b/sfx2/source/sidebar/Panel.cxx
@@ -45,33 +45,62 @@ using namespace css::uno;
namespace sfx2::sidebar {

Panel::Panel(const PanelDescriptor& rPanelDescriptor,
             vcl::Window* pParentWindow,
             weld::Widget* pParentWindow,
             const bool bIsInitiallyExpanded,
             const std::function<void()>& rDeckLayoutTrigger,
             Deck* pDeck,
             const std::function<Context()>& rContextAccess,
             const css::uno::Reference<css::frame::XFrame>& rxFrame)
    : InterimItemWindow(pParentWindow, "sfx/ui/panel.ui", "Panel")
    : mxBuilder(Application::CreateBuilder(pParentWindow, "sfx/ui/panel.ui"))
    , msPanelId(rPanelDescriptor.msId)
    , msTitle(rPanelDescriptor.msTitle)
    , mbIsTitleBarOptional(rPanelDescriptor.mbIsTitleBarOptional)
    , mbWantsAWT(rPanelDescriptor.mbWantsAWT)
    , mxElement()
    , mxPanelComponent()
    , mbIsExpanded(bIsInitiallyExpanded)
    , mbLurking(false)
    , maDeckLayoutTrigger(rDeckLayoutTrigger)
    , maContextAccess(rContextAccess)
    , mxFrame(rxFrame)
    , mxTitleBar(new PanelTitleBar(rPanelDescriptor.msTitle, *m_xBuilder, this))
    , mxContents(m_xBuilder->weld_container("contents"))
    , mpParentWindow(pParentWindow)
    , mxDeck(pDeck)
    , mxContainer(mxBuilder->weld_container("Panel"))
    , mxTitleBar(new PanelTitleBar(rPanelDescriptor.msTitle, *mxBuilder, this))
    , mxContents(mxBuilder->weld_container("contents"))
{
    SetText(rPanelDescriptor.msTitle);
    mxContents->set_visible(mbIsExpanded);
    mxContainer->connect_get_property_tree(LINK(this, Panel, DumpAsPropertyTreeHdl));
}

Panel::~Panel()
bool Panel::get_extents(tools::Rectangle &rExtents) const
{
    disposeOnce();
    assert(!mxTitleBar);
    // Get vertical extent of the panel.
    int x, y, width, height;
    if (mxContainer->get_extents_relative_to(*mpParentWindow, x, y, width, height))
    {
        rExtents = tools::Rectangle(Point(x, y), Size(width, height));
        return true;
    }
    return false;
}

void Panel::SetHeightPixel(int nHeight)
{
    mxContainer->set_size_request(-1, nHeight);
}

void Panel::set_margin_top(int nMargin)
{
    mxContainer->set_margin_top(nMargin);
}

void Panel::set_margin_bottom(int nMargin)
{
    mxContainer->set_margin_bottom(nMargin);
}

void Panel::set_vexpand(bool bExpand)
{
    mxContainer->set_vexpand(bExpand);
}

void Panel::SetLurkMode(bool bLurk)
@@ -80,21 +109,13 @@ void Panel::SetLurkMode(bool bLurk)
    mbLurking = bLurk;
}

void Panel::ApplySettings(vcl::RenderContext& rRenderContext)
{
    rRenderContext.SetBackground(Theme::GetColor(Theme::Color_PanelBackground));
}

void Panel::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
IMPL_LINK(Panel, DumpAsPropertyTreeHdl, tools::JsonWriter&, rJsonWriter, void)
{
    if (!IsLurking())
    {
        InterimItemWindow::DumpAsPropertyTree(rJsonWriter);
        rJsonWriter.put("type", "panel");
    }
}

void Panel::dispose()
Panel::~Panel()
{
    mxPanelComponent = nullptr;

@@ -120,7 +141,7 @@ void Panel::dispose()
    }
    mxContents.reset();

    InterimItemWindow::dispose();
    assert(!mxTitleBar);
}

PanelTitleBar* Panel::GetTitleBar() const
@@ -128,9 +149,14 @@ PanelTitleBar* Panel::GetTitleBar() const
    return mxTitleBar.get();
}

void Panel::ShowTitlebar(bool bShowTitlebar)
weld::Container* Panel::GetContents() const
{
    mxTitleBar->Show(bShowTitlebar);
    return mxContents.get();
}

void Panel::Show(bool bShow)
{
    mxContainer->set_visible(bShow);
}

void Panel::SetUIElement (const Reference<ui::XUIElement>& rxElement)
@@ -146,6 +172,16 @@ void Panel::SetUIElement (const Reference<ui::XUIElement>& rxElement)
    pPanelBase->SetParentPanel(this);
}

void Panel::TriggerDeckLayouting()
{
    mxDeck->RequestLayout();
}

weld::Window* Panel::GetFrameWeld()
{
    return mxDeck->GetFrameWeld();
}

void Panel::SetExpanded (const bool bIsExpanded)
{
    SidebarController* pSidebarController = SidebarController::GetSidebarControllerForFrame(mxFrame);
@@ -155,7 +191,7 @@ void Panel::SetExpanded (const bool bIsExpanded)

    mbIsExpanded = bIsExpanded;
    mxTitleBar->UpdateExpandedState();
    maDeckLayoutTrigger();
    TriggerDeckLayouting();

    if (maContextAccess && pSidebarController)
    {
@@ -173,9 +209,9 @@ bool Panel::HasIdPredicate (std::u16string_view rsId) const
    return msPanelId == rsId;
}

void Panel::DataChanged (const DataChangedEvent&)
void Panel::DataChanged()
{
    Invalidate();
    mxTitleBar->DataChanged();
}

Reference<awt::XWindow> Panel::GetElementWindow()
diff --git a/sfx2/source/sidebar/PanelLayout.cxx b/sfx2/source/sidebar/PanelLayout.cxx
index 3a47773..271f4d8 100644
--- a/sfx2/source/sidebar/PanelLayout.cxx
+++ b/sfx2/source/sidebar/PanelLayout.cxx
@@ -19,6 +19,7 @@ using namespace sfx2::sidebar;
PanelLayout::PanelLayout(weld::Widget* pParent, const OString& rID, const OUString& rUIXMLDescription)
    : m_xBuilder(Application::CreateBuilder(pParent, rUIXMLDescription))
    , m_xContainer(m_xBuilder->weld_container(rID))
    , m_pPanel(nullptr)
{
    m_xContainer->set_background(Theme::GetColor(Theme::Color_PanelBackground));
    m_xContainer->connect_get_property_tree(LINK(this, PanelLayout, DumpAsPropertyTreeHdl));
@@ -53,17 +54,17 @@ void PanelLayout::DataChanged(const DataChangedEvent& rEvent)

void PanelLayout::SetPanel(sfx2::sidebar::Panel* pPanel)
{
    m_xPanel = pPanel;
    m_pPanel = pPanel;
}

weld::Window* PanelLayout::GetFrameWeld() const
{
    if (!m_xPanel)
    if (!m_pPanel)
    {
        SAL_WARN("sfx.sidebar", "Expected a toplevel Panel to exist");
        return nullptr;
    }
    return m_xPanel->GetFrameWeld();
    return m_pPanel->GetFrameWeld();
}

PanelLayout::~PanelLayout()
diff --git a/sfx2/source/sidebar/PanelTitleBar.cxx b/sfx2/source/sidebar/PanelTitleBar.cxx
index 2ac2a6f..47de8e4 100644
--- a/sfx2/source/sidebar/PanelTitleBar.cxx
+++ b/sfx2/source/sidebar/PanelTitleBar.cxx
@@ -33,15 +33,12 @@ namespace sfx2::sidebar {
PanelTitleBar::PanelTitleBar(const OUString& rsTitle,
                             weld::Builder& rBuilder,
                             Panel* pPanel)
    : TitleBarBase(rBuilder, Theme::Color_PanelTitleBarBackground),
      mxTitlebar(rBuilder.weld_container("titlebar")),
    : TitleBar(rBuilder, Theme::Color_PanelTitleBarBackground),
      mxExpander(rBuilder.weld_expander("expander")),
      mpPanel(pPanel),
      msIdent("button"),
      msMoreOptionsCommand()
{
    mxTitlebar->set_background(Theme::GetColor(meThemeItem));

    mxExpander->set_label(rsTitle);
    mxExpander->connect_expanded(LINK(this, PanelTitleBar, ExpandHdl));

@@ -54,11 +51,6 @@ PanelTitleBar::PanelTitleBar(const OUString& rsTitle,
#endif
}

bool PanelTitleBar::GetVisible() const
{
    return mxTitlebar->get_visible();
}

void PanelTitleBar::SetTitle(const OUString& rsTitle)
{
    mxExpander->set_label(rsTitle);
@@ -80,10 +72,8 @@ PanelTitleBar::~PanelTitleBar()
    if (xComponent.is())
        xComponent->dispose();
    mxController.clear();
    mpPanel.clear();
    mpPanel = nullptr;
    mxExpander.reset();
    mxTitlebar.reset();
    reset();
}

void PanelTitleBar::SetMoreOptionsCommand(const OUString& rsCommandName,
diff --git a/sfx2/source/sidebar/SidebarController.cxx b/sfx2/source/sidebar/SidebarController.cxx
index dce6688..b8df3b6 100644
--- a/sfx2/source/sidebar/SidebarController.cxx
+++ b/sfx2/source/sidebar/SidebarController.cxx
@@ -491,8 +491,8 @@ void SidebarController::NotifyResize()
    sal_Int32 nMinimalWidth = 0;
    if (mpCurrentDeck && !mpCurrentDeck->isDisposed())
    {
        VclPtr<DeckTitleBar> pTitleBar = mpCurrentDeck->GetTitleBar();
        if (pTitleBar && pTitleBar->IsVisible())
        DeckTitleBar* pTitleBar = mpCurrentDeck->GetTitleBar();
        if (pTitleBar && pTitleBar->GetVisible())
            pTitleBar->SetCloserVisible(CanModifyChildWindowWidth());
        nMinimalWidth = mpCurrentDeck->GetMinimalWidth();
    }
@@ -752,37 +752,36 @@ void SidebarController::CreatePanels(std::u16string_view rDeckId, const Context&
        if ( ! bIsPanelVisible)
            continue;

        Panel *const pPanel(pDeck->GetPanel(rPanelContexDescriptor.msId));
        if (pPanel != nullptr)
        auto xOldPanel(pDeck->GetPanel(rPanelContexDescriptor.msId));
        if (xOldPanel)
        {
            pPanel->SetLurkMode(false);
            aNewPanels[nWriteIndex] = pPanel;
            pPanel->SetExpanded( rPanelContexDescriptor.mbIsInitiallyVisible );
            xOldPanel->SetLurkMode(false);
            aNewPanels[nWriteIndex] = xOldPanel;
            xOldPanel->SetExpanded(rPanelContexDescriptor.mbIsInitiallyVisible);
            ++nWriteIndex;
        }
        else
        {
                VclPtr<Panel>  aPanel = CreatePanel(
                                            rPanelContexDescriptor.msId,
                                            pDeck->GetPanelParentWindow(),
                                            rPanelContexDescriptor.mbIsInitiallyVisible,
                                            rContext,
                                            pDeck);
                if (aPanel )
                {
                    aNewPanels[nWriteIndex] = aPanel;
            auto aPanel = CreatePanel(rPanelContexDescriptor.msId,
                                      pDeck->GetPanelParentWindow(),
                                      rPanelContexDescriptor.mbIsInitiallyVisible,
                                      rContext,
                                      pDeck);
            if (aPanel)
            {
                aNewPanels[nWriteIndex] = std::move(aPanel);

                    // Depending on the context we have to change the command
                    // for the "more options" dialog.
                    PanelTitleBar* pTitleBar = aNewPanels[nWriteIndex]->GetTitleBar();
                    if (pTitleBar)
                    {
                        pTitleBar->SetMoreOptionsCommand(
                            rPanelContexDescriptor.msMenuCommand,
                            mxFrame, xController);
                    }
                    ++nWriteIndex;
                // Depending on the context we have to change the command
                // for the "more options" dialog.
                PanelTitleBar* pTitleBar = aNewPanels[nWriteIndex]->GetTitleBar();
                if (pTitleBar)
                {
                    pTitleBar->SetMoreOptionsCommand(
                        rPanelContexDescriptor.msMenuCommand,
                        mxFrame, xController);
                }
                ++nWriteIndex;
            }
        }
    }

@@ -915,7 +914,7 @@ void SidebarController::SwitchToDeck (

    // Tell the focus manager about the new panels and tab bar
    // buttons.
    maFocusManager.SetDeckTitle(mpCurrentDeck->GetTitleBar());
    maFocusManager.SetDeck(mpCurrentDeck);
    maFocusManager.SetPanels(mpCurrentDeck->GetPanels());

    mpTabBar->UpdateFocusManager(maFocusManager);
@@ -926,15 +925,15 @@ void SidebarController::notifyDeckTitle(std::u16string_view targetDeckId)
{
    if (msCurrentDeckId == targetDeckId)
    {
        maFocusManager.SetDeckTitle(mpCurrentDeck->GetTitleBar());
        maFocusManager.SetDeck(mpCurrentDeck);
        mpTabBar->UpdateFocusManager(maFocusManager);
        UpdateTitleBarIcons();
    }
}

VclPtr<Panel> SidebarController::CreatePanel (
std::shared_ptr<Panel> SidebarController::CreatePanel (
    std::u16string_view rsPanelId,
    vcl::Window* pParentWindow,
    weld::Widget* pParentWindow,
    const bool bIsInitiallyExpanded,
    const Context& rContext,
    const VclPtr<Deck>& pDeck)
@@ -945,31 +944,31 @@ VclPtr<Panel> SidebarController::CreatePanel (
        return nullptr;

    // Create the panel which is the parent window of the UIElement.
    VclPtr<Panel> pPanel = VclPtr<Panel>::Create(
    auto xPanel = std::make_shared<Panel>(
        *xPanelDescriptor,
        pParentWindow,
        bIsInitiallyExpanded,
        [pDeck]() { return pDeck->RequestLayout(); },
        pDeck,
        [this]() { return this->GetCurrentContext(); },
        mxFrame);

    // Create the XUIElement.
    Reference<ui::XUIElement> xUIElement (CreateUIElement(
            pPanel->GetElementParentWindow(),
            xPanel->GetElementParentWindow(),
            xPanelDescriptor->msImplementationURL,
            xPanelDescriptor->mbWantsCanvas,
            rContext));
    if (xUIElement.is())
    {
        // Initialize the panel and add it to the active deck.
        pPanel->SetUIElement(xUIElement);
        xPanel->SetUIElement(xUIElement);
    }
    else
    {
        pPanel.disposeAndClear();
        xPanel.reset();
    }

    return pPanel;
    return xPanel;
}

Reference<ui::XUIElement> SidebarController::CreateUIElement (
@@ -1583,9 +1582,7 @@ tools::Rectangle SidebarController::GetDeckDragArea() const
    tools::Rectangle aRect;
    if (mpCurrentDeck)
    {
        VclPtr<DeckTitleBar> pTitleBar(mpCurrentDeck->GetTitleBar());

        if (pTitleBar)
        if (DeckTitleBar* pTitleBar = mpCurrentDeck->GetTitleBar())
        {
            aRect = pTitleBar->GetDragArea();
        }
diff --git a/sfx2/source/sidebar/TabBar.cxx b/sfx2/source/sidebar/TabBar.cxx
index b989cb7..f77cd0e 100644
--- a/sfx2/source/sidebar/TabBar.cxx
+++ b/sfx2/source/sidebar/TabBar.cxx
@@ -59,6 +59,8 @@ TabBar::TabBar(vcl::Window* pParentWindow,
    , maPopupMenuProvider(rPopupMenuProvider)
    , pParentSidebarController(rParentSidebarController)
{
    InitControlBase(mxMenuButton.get());

    mxTempToplevel->move(mxContents.get(), m_xContainer.get());

    gDefaultWidth = m_xContainer->get_preferred_size().Width();
diff --git a/sfx2/source/sidebar/Theme.cxx b/sfx2/source/sidebar/Theme.cxx
index dd187aa..dde8737 100644
--- a/sfx2/source/sidebar/Theme.cxx
+++ b/sfx2/source/sidebar/Theme.cxx
@@ -118,14 +118,10 @@ void Theme::UpdateTheme()
    try
    {
        const StyleSettings& rStyle (Application::GetSettings().GetStyleSettings());
        const bool bUseSystemColors (GetBoolean(Bool_UseSystemColors));

#define Alternatives(n,hc,sys) (mbIsHighContrastMode ? hc : (bUseSystemColors ? sys : n))

        Color aBaseBackgroundColor (rStyle.GetDialogColor());
        // UX says this should be a little brighter, but that looks off when compared to the other windows.
        //aBaseBackgroundColor.IncreaseLuminance(7);
        Color aBorderColor (aBaseBackgroundColor);
        Color aSecondColor (aBaseBackgroundColor);
        aSecondColor.DecreaseLuminance(15);

@@ -140,15 +136,6 @@ void Theme::UpdateTheme()
            maPropertyIdToNameMap[Int_DeckSeparatorHeight],
            Any(sal_Int32(1)));
        setPropertyValue(
            maPropertyIdToNameMap[Color_DeckTitleFont],
            Any(sal_Int32(rStyle.GetFontColor().GetRGBColor())));
        setPropertyValue(
            maPropertyIdToNameMap[Int_DeckTitleBarHeight],
            Any(sal_Int32(Alternatives(
                        26,
                        26,
                        rStyle.GetFloatTitleHeight()))));
        setPropertyValue(
            maPropertyIdToNameMap[Color_PanelBackground],
            Any(sal_Int32(aBaseBackgroundColor.GetRGBColor())));

@@ -156,36 +143,15 @@ void Theme::UpdateTheme()
            maPropertyIdToNameMap[Color_PanelTitleBarBackground],
            Any(sal_Int32(aSecondColor.GetRGBColor())));
        setPropertyValue(
            maPropertyIdToNameMap[Color_PanelTitleFont],
            Any(sal_Int32(mbIsHighContrastMode ? 0x00ff00 : 0x262626)));
        setPropertyValue(
            maPropertyIdToNameMap[Int_PanelTitleBarHeight],
            Any(sal_Int32(Alternatives(
                        26,
                        26,
                        rStyle.GetTitleHeight()))));
        setPropertyValue(
            maPropertyIdToNameMap[Color_TabBarBackground],
            Any(sal_Int32(aBaseBackgroundColor.GetRGBColor())));

        setPropertyValue(
            maPropertyIdToNameMap[Color_DropDownBackground],
            Any(sal_Int32(aBaseBackgroundColor.GetRGBColor())));

        setPropertyValue(
            maPropertyIdToNameMap[Color_Highlight],
            Any(sal_Int32(rStyle.GetHighlightColor().GetRGBColor())));
        setPropertyValue(
            maPropertyIdToNameMap[Color_HighlightText],
            Any(sal_Int32(rStyle.GetHighlightTextColor().GetRGBColor())));

        setPropertyValue(
            maPropertyIdToNameMap[Color_HorizontalBorder],
            Any(sal_Int32(aBorderColor.GetRGBColor())));

        setPropertyValue(
            maPropertyIdToNameMap[Color_VerticalBorder],
            Any(sal_Int32(aBorderColor.GetRGBColor())));
    }
    catch(beans::UnknownPropertyException const &)
    {
@@ -476,12 +442,6 @@ void Theme::SetupPropertyMaps()
    maIntegers.resize(Int_Bool_ - Color_Int_ - 1);
    maBooleans.resize(Post_Bool_ - Int_Bool_ - 1);

    maPropertyNameToIdMap["Color_DeckTitleFont"]=Color_DeckTitleFont;
    maPropertyIdToNameMap[Color_DeckTitleFont]="Color_DeckTitleFont";

    maPropertyNameToIdMap["Color_PanelTitleFont"]=Color_PanelTitleFont;
    maPropertyIdToNameMap[Color_PanelTitleFont]="Color_PanelTitleFont";

    maPropertyNameToIdMap["Color_Highlight"]=Color_Highlight;
    maPropertyIdToNameMap[Color_Highlight]="Color_Highlight";

@@ -504,18 +464,6 @@ void Theme::SetupPropertyMaps()
    maPropertyNameToIdMap["Color_TabBarBackground"]=Color_TabBarBackground;
    maPropertyIdToNameMap[Color_TabBarBackground]="Color_TabBarBackground";

    maPropertyNameToIdMap["Color_HorizontalBorder"]=Color_HorizontalBorder;
    maPropertyIdToNameMap[Color_HorizontalBorder]="Color_HorizontalBorder";

    maPropertyNameToIdMap["Color_VerticalBorder"]=Color_VerticalBorder;
    maPropertyIdToNameMap[Color_VerticalBorder]="Color_VerticalBorder";

    maPropertyNameToIdMap["Color_DropDownBackground"]=Color_DropDownBackground;
    maPropertyIdToNameMap[Color_DropDownBackground]="Color_DropDownBackground";


    maPropertyNameToIdMap["Int_DeckTitleBarHeight"]=Int_DeckTitleBarHeight;
    maPropertyIdToNameMap[Int_DeckTitleBarHeight]="Int_DeckTitleBarHeight";

    maPropertyNameToIdMap["Int_DeckBorderSize"]=Int_DeckBorderSize;
    maPropertyIdToNameMap[Int_DeckBorderSize]="Int_DeckBorderSize";
@@ -523,9 +471,6 @@ void Theme::SetupPropertyMaps()
    maPropertyNameToIdMap["Int_DeckSeparatorHeight"]=Int_DeckSeparatorHeight;
    maPropertyIdToNameMap[Int_DeckSeparatorHeight]="Int_DeckSeparatorHeight";

    maPropertyNameToIdMap["Int_PanelTitleBarHeight"]=Int_PanelTitleBarHeight;
    maPropertyIdToNameMap[Int_PanelTitleBarHeight]="Int_PanelTitleBarHeight";

    maPropertyNameToIdMap["Int_DeckLeftPadding"]=Int_DeckLeftPadding;
    maPropertyIdToNameMap[Int_DeckLeftPadding]="Int_DeckLeftPadding";

@@ -552,8 +497,6 @@ Theme::PropertyType Theme::GetPropertyType (const ThemeItem eItem)
{
    switch(eItem)
    {
        case Color_DeckTitleFont:
        case Color_PanelTitleFont:
        case Color_Highlight:
        case Color_HighlightText:
        case Color_DeckBackground:
@@ -561,15 +504,10 @@ Theme::PropertyType Theme::GetPropertyType (const ThemeItem eItem)
        case Color_PanelBackground:
        case Color_PanelTitleBarBackground:
        case Color_TabBarBackground:
        case Color_HorizontalBorder:
        case Color_VerticalBorder:
        case Color_DropDownBackground:
            return PT_Color;

        case Int_DeckTitleBarHeight:
        case Int_DeckBorderSize:
        case Int_DeckSeparatorHeight:
        case Int_PanelTitleBarHeight:
        case Int_DeckLeftPadding:
        case Int_DeckTopPadding:
        case Int_DeckRightPadding:
diff --git a/sfx2/source/sidebar/TitleBar.cxx b/sfx2/source/sidebar/TitleBar.cxx
index b88b4e9..9dc13d3 100644
--- a/sfx2/source/sidebar/TitleBar.cxx
+++ b/sfx2/source/sidebar/TitleBar.cxx
@@ -21,63 +21,60 @@

namespace sfx2::sidebar {

TitleBarBase::TitleBarBase(weld::Builder& rBuilder, Theme::ThemeItem eThemeItem)
TitleBar::TitleBar(weld::Builder& rBuilder, Theme::ThemeItem eThemeItem)
    : mrBuilder(rBuilder)
    , mxTitlebar(rBuilder.weld_container("titlebar"))
    , mxAddonImage(rBuilder.weld_image("addonimage"))
    , mxToolBox(rBuilder.weld_toolbar("toolbar"))
    , meThemeItem(eThemeItem)
{
    mxToolBox->set_background(Theme::GetColor(meThemeItem));
    SetBackground();

    mxToolBox->connect_clicked(LINK(this, TitleBarBase, SelectionHandler));
    mxToolBox->connect_clicked(LINK(this, TitleBar, SelectionHandler));
}

TitleBarBase::~TitleBarBase()
void TitleBar::SetBackground()
{
    Color aColor(Theme::GetColor(meThemeItem));
    mxTitlebar->set_background(aColor);
    mxToolBox->set_background(aColor);
}

void TitleBar::DataChanged()
{
    SetBackground();
}

TitleBar::~TitleBar()
{
}

void TitleBarBase::reset()
Size TitleBar::get_preferred_size() const
{
    mxToolBox.reset();
    mxAddonImage.reset();
    return mxTitlebar->get_preferred_size();
}

void TitleBarBase::SetIcon(const css::uno::Reference<css::graphic::XGraphic>& rIcon)
void TitleBar::Show(bool bShow)
{
    mxTitlebar->set_visible(bShow);
}

bool TitleBar::GetVisible() const
{
    return mxTitlebar->get_visible();
}

void TitleBar::SetIcon(const css::uno::Reference<css::graphic::XGraphic>& rIcon)
{
    mxAddonImage->set_image(rIcon);
    mxAddonImage->set_visible(rIcon.is());
}

IMPL_LINK_NOARG(TitleBarBase, SelectionHandler, const OString&, void)
IMPL_LINK_NOARG(TitleBar, SelectionHandler, const OString&, void)
{
    HandleToolBoxItemClick();
}

TitleBar::TitleBar(vcl::Window* pParentWindow,
                   const OUString& rUIXMLDescription, const OString& rID,
                   Theme::ThemeItem eThemeItem)
    : InterimItemWindow(pParentWindow, rUIXMLDescription, rID)
    , TitleBarBase(*m_xBuilder, eThemeItem)
{
    m_xContainer->set_background(Theme::GetColor(meThemeItem));
}

TitleBar::~TitleBar()
{
    disposeOnce();
}

void TitleBar::dispose()
{
    reset();
    InterimItemWindow::dispose();
}

void TitleBar::DataChanged (const DataChangedEvent& /*rEvent*/)
{
    m_xContainer->set_background(Theme::GetColor(meThemeItem));
}

} // end of namespace sfx2::sidebar

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sfx2/source/sidebar/UnoDeck.cxx b/sfx2/source/sidebar/UnoDeck.cxx
index 0350ef1..30a68cd 100644
--- a/sfx2/source/sidebar/UnoDeck.cxx
+++ b/sfx2/source/sidebar/UnoDeck.cxx
@@ -54,7 +54,7 @@ OUString SAL_CALL  SfxUnoDeck::getTitle()
        pDeck = pSidebarController->GetResourceManager()->GetDeckDescriptor(mDeckId)->mpDeck;
    }

    VclPtr<DeckTitleBar> pTitleBar = pDeck->GetTitleBar();
    DeckTitleBar* pTitleBar = pDeck->GetTitleBar();
    return pTitleBar->GetTitle();
}

@@ -70,7 +70,7 @@ void SAL_CALL SfxUnoDeck::setTitle( const OUString& newTitle )
    if (xDeckDescriptor)
    {
        Deck* pDeck = xDeckDescriptor->mpDeck;
        const VclPtr<DeckTitleBar>& pTitleBar = pDeck->GetTitleBar();
        DeckTitleBar* pTitleBar = pDeck->GetTitleBar();
        pTitleBar->SetTitle(newTitle);

        xDeckDescriptor->msTitle = newTitle;
diff --git a/sfx2/source/sidebar/UnoPanel.cxx b/sfx2/source/sidebar/UnoPanel.cxx
index 1170cbc..8021268 100644
--- a/sfx2/source/sidebar/UnoPanel.cxx
+++ b/sfx2/source/sidebar/UnoPanel.cxx
@@ -29,13 +29,13 @@ xFrame(rFrame),
mPanelId(panelId),
mDeckId(deckId),
mpDeck(),
mpPanel()
mxPanel()
{
    SidebarController* pSidebarController = getSidebarController();

    pSidebarController->CreateDeck(mDeckId); // creates deck object is not already
    mpDeck = pSidebarController->GetResourceManager()->GetDeckDescriptor(mDeckId)->mpDeck;
    mpPanel = mpDeck->GetPanel(mPanelId);
    mxPanel = mpDeck->GetPanel(mPanelId);
}

SidebarController* SfxUnoPanel::getSidebarController()
@@ -54,7 +54,8 @@ OUString SAL_CALL SfxUnoPanel::getTitle()
{
    SolarMutexGuard aGuard;

    PanelTitleBar* pTitleBar = mpPanel->GetTitleBar();
    auto xPanel = mxPanel.lock();
    PanelTitleBar* pTitleBar = xPanel ? xPanel->GetTitleBar() : nullptr;
    if (pTitleBar)
        return pTitleBar->GetTitle();
    else
@@ -71,7 +72,8 @@ void SAL_CALL SfxUnoPanel::setTitle( const OUString& newTitle )
    if (xPanelDescriptor)
    {
        xPanelDescriptor->msTitle = newTitle;
        PanelTitleBar* pTitleBar = mpPanel->GetTitleBar();
        auto xPanel = mxPanel.lock();
        PanelTitleBar* pTitleBar = xPanel ? xPanel->GetTitleBar() : nullptr;
        if (pTitleBar)
            pTitleBar->SetTitle(newTitle);
    }
@@ -81,7 +83,8 @@ sal_Bool SAL_CALL SfxUnoPanel::isExpanded()
{
    SolarMutexGuard aGuard;

    return mpPanel->IsExpanded();
    auto xPanel = mxPanel.lock();
    return xPanel && xPanel->IsExpanded();
}


@@ -90,7 +93,9 @@ void SAL_CALL SfxUnoPanel::expand( const sal_Bool bCollapseOther )

    SolarMutexGuard aGuard;

    mpPanel->SetExpanded(true);
    auto xPanel = mxPanel.lock();
    if (xPanel)
        xPanel->SetExpanded(true);

    if (bCollapseOther)
    {
@@ -111,7 +116,9 @@ void SAL_CALL SfxUnoPanel::collapse()
{
    SolarMutexGuard aGuard;

    mpPanel->SetExpanded(false);
    auto xPanel = mxPanel.lock();
    if (xPanel)
        xPanel->SetExpanded(false);
    SidebarController* pSidebarController = getSidebarController();
    pSidebarController->NotifyResize();
}
@@ -120,10 +127,10 @@ uno::Reference<awt::XWindow> SAL_CALL SfxUnoPanel::getDialog()
{
    SolarMutexGuard aGuard;

    return mpPanel->GetElementWindow();
    auto xPanel = mxPanel.lock();
    return xPanel ? xPanel->GetElementWindow() : nullptr;
}


sal_Int32 SAL_CALL SfxUnoPanel::getOrderIndex()
{
    SolarMutexGuard aGuard;
diff --git a/sfx2/uiconfig/ui/deck.ui b/sfx2/uiconfig/ui/deck.ui
new file mode 100644
index 0000000..61ad555
--- /dev/null
+++ b/sfx2/uiconfig/ui/deck.ui
@@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface domain="sfx">
  <requires lib="gtk+" version="3.20"/>
  <!-- n-columns=1 n-rows=2 -->
  <object class="GtkGrid" id="Deck">
    <property name="visible">True</property>
    <property name="can-focus">False</property>
    <property name="vexpand">True</property>
    <child>
      <object class="GtkScrolledWindow" id="scrolledwindow">
        <property name="visible">True</property>
        <property name="can-focus">True</property>
        <property name="hexpand">True</property>
        <property name="vexpand">True</property>
        <child>
          <object class="GtkViewport">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="hexpand">True</property>
            <property name="vexpand">True</property>
            <child>
              <object class="GtkBox" id="contents">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="hexpand">True</property>
                <property name="vexpand">True</property>
                <property name="orientation">vertical</property>
                <child>
                  <placeholder/>
                </child>
              </object>
            </child>
          </object>
        </child>
      </object>
      <packing>
        <property name="left-attach">0</property>
        <property name="top-attach">1</property>
      </packing>
    </child>
    <child>
      <object class="GtkBox" id="titlebar">
        <property name="visible">True</property>
        <property name="can-focus">False</property>
        <property name="hexpand">True</property>
        <property name="spacing">6</property>
        <child>
          <object class="GtkDrawingArea" id="grip">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="valign">center</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkImage" id="addonimage">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="valign">center</property>
            <property name="icon-name">missing-image</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkLabel" id="label">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="valign">center</property>
            <property name="hexpand">True</property>
            <property name="xalign">0</property>
            <attributes>
              <attribute name="weight" value="bold"/>
            </attributes>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">2</property>
          </packing>
        </child>
        <child>
          <object class="GtkToolbar" id="toolbar">
            <property name="can-focus">False</property>
            <property name="no-show-all">True</property>
            <property name="toolbar-style">icons</property>
            <property name="show-arrow">False</property>
            <property name="icon_size">2</property>
            <child>
              <object class="GtkToolButton" id="button">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="tooltip-text" translatable="yes" context="deck|SFX_STR_SIDEBAR_CLOSE_DECK">Close Sidebar Deck</property>
                <property name="use-underline">True</property>
                <property name="icon-name">sfx2/res/closedoc.png</property>
                <child internal-child="accessible">
                  <object class="AtkObject" id="button-atkobject">
                    <property name="AtkObject::accessible-name" translatable="yes" context="deck|SFX_STR_SIDEBAR_CLOSE_DECK">Close Sidebar Deck</property>
                  </object>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="homogeneous">False</property>
              </packing>
            </child>
            <style>
              <class name="small-button"/>
            </style>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">3</property>
          </packing>
        </child>
      </object>
      <packing>
        <property name="left-attach">0</property>
        <property name="top-attach">0</property>
      </packing>
    </child>
  </object>
</interface>
diff --git a/sfx2/uiconfig/ui/decktitlebar.ui b/sfx2/uiconfig/ui/decktitlebar.ui
deleted file mode 100644
index 8c34a7d..0000000
--- a/sfx2/uiconfig/ui/decktitlebar.ui
+++ /dev/null
@@ -1,89 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface domain="sfx">
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkBox" id="DeckTitleBar">
    <property name="visible">True</property>
    <property name="can-focus">False</property>
    <property name="hexpand">True</property>
    <property name="vexpand">True</property>
    <property name="spacing">6</property>
    <child>
      <object class="GtkDrawingArea" id="grip">
        <property name="visible">True</property>
        <property name="can-focus">False</property>
        <property name="valign">center</property>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">0</property>
      </packing>
    </child>
    <child>
      <object class="GtkImage" id="addonimage">
        <property name="visible">True</property>
        <property name="can-focus">False</property>
        <property name="valign">center</property>
        <property name="icon-name">missing-image</property>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">1</property>
      </packing>
    </child>
    <child>
      <object class="GtkLabel" id="label">
        <property name="visible">True</property>
        <property name="can-focus">False</property>
        <property name="valign">center</property>
        <property name="hexpand">True</property>
        <property name="xalign">0</property>
        <attributes>
          <attribute name="weight" value="bold"/>
        </attributes>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">2</property>
      </packing>
    </child>
    <child>
      <object class="GtkToolbar" id="toolbar">
        <property name="can-focus">False</property>
        <property name="no-show-all">True</property>
        <property name="toolbar-style">icons</property>
        <property name="show-arrow">False</property>
        <property name="icon_size">2</property>
        <child>
          <object class="GtkToolButton" id="button">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="tooltip-text" translatable="yes" context="decktitlebar|SFX_STR_SIDEBAR_CLOSE_DECK">Close Sidebar Deck</property>
            <property name="use-underline">True</property>
            <property name="icon-name">sfx2/res/closedoc.png</property>
            <child internal-child="accessible">
              <object class="AtkObject" id="button-atkobject">
                <property name="AtkObject::accessible-name" translatable="yes" context="decktitlebar|SFX_STR_SIDEBAR_CLOSE_DECK">Close Sidebar Deck</property>
              </object>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="homogeneous">False</property>
          </packing>
        </child>
        <style>
          <class name="small-button"/>
        </style>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">3</property>
      </packing>
    </child>
  </object>
</interface>
diff --git a/sfx2/uiconfig/ui/panel.ui b/sfx2/uiconfig/ui/panel.ui
index 689236e2..b2c5f92 100644
--- a/sfx2/uiconfig/ui/panel.ui
+++ b/sfx2/uiconfig/ui/panel.ui
@@ -6,7 +6,6 @@
  <object class="GtkGrid" id="Panel">
    <property name="visible">True</property>
    <property name="can-focus">False</property>
    <property name="vexpand">True</property>
    <child>
      <object class="GtkBox" id="titlebar">
        <property name="visible">True</property>
@@ -72,12 +71,12 @@
              <object class="GtkToolButton" id="button">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="tooltip-text" translatable="yes" context="paneltitlebar|SFX_STR_SIDEBAR_MORE_OPTIONS">More Options</property>
                <property name="tooltip-text" translatable="yes" context="panel|SFX_STR_SIDEBAR_MORE_OPTIONS">More Options</property>
                <property name="use-underline">True</property>
                <property name="icon-name">sfx2/res/symphony/morebutton.png</property>
                <child internal-child="accessible">
                  <object class="AtkObject" id="button-atkobject">
                    <property name="AtkObject::accessible-name" translatable="yes" context="paneltitlebar|SFX_STR_SIDEBAR_MORE_OPTIONS">More Options</property>
                    <property name="AtkObject::accessible-name" translatable="yes" context="panel|SFX_STR_SIDEBAR_MORE_OPTIONS">More Options</property>
                  </object>
                </child>
              </object>
@@ -107,7 +106,6 @@
        <property name="visible">True</property>
        <property name="can-focus">False</property>
        <property name="hexpand">True</property>
        <property name="vexpand">True</property>
        <property name="orientation">vertical</property>
        <child>
          <placeholder/>
diff --git a/solenv/sanitizers/ui/sfx.suppr b/solenv/sanitizers/ui/sfx.suppr
index faef6d0..e9358da 100644
--- a/solenv/sanitizers/ui/sfx.suppr
+++ b/solenv/sanitizers/ui/sfx.suppr
@@ -10,8 +10,8 @@ sfx2/uiconfig/ui/cmisline.ui://GtkSpinButton[@id='time'] no-labelled-by
sfx2/uiconfig/ui/custominfopage.ui://GtkLabel[@id='name'] orphan-label
sfx2/uiconfig/ui/custominfopage.ui://GtkLabel[@id='type'] orphan-label
sfx2/uiconfig/ui/custominfopage.ui://GtkLabel[@id='value'] orphan-label
sfx2/uiconfig/ui/decktitlebar.ui://GtkImage[@id='addonimage'] no-labelled-by
sfx2/uiconfig/ui/decktitlebar.ui://GtkLabel[@id='label'] orphan-label
sfx2/uiconfig/ui/deck.ui://GtkImage[@id='addonimage'] no-labelled-by
sfx2/uiconfig/ui/deck.ui://GtkLabel[@id='label'] orphan-label
sfx2/uiconfig/ui/documentinfopage.ui://GtkLabel[@id='showcreate'] orphan-label
sfx2/uiconfig/ui/documentinfopage.ui://GtkLabel[@id='showmodify'] orphan-label
sfx2/uiconfig/ui/documentinfopage.ui://GtkLabel[@id='showsigned'] orphan-label
diff --git a/svx/source/sidebar/area/AreaPropertyPanelBase.cxx b/svx/source/sidebar/area/AreaPropertyPanelBase.cxx
index 2e9df08..727c2f3 100644
--- a/svx/source/sidebar/area/AreaPropertyPanelBase.cxx
+++ b/svx/source/sidebar/area/AreaPropertyPanelBase.cxx
@@ -437,8 +437,8 @@ IMPL_LINK_NOARG(AreaPropertyPanelBase, SelectFillTypeHdl, weld::ComboBox&, void)

    meLastXFS = static_cast<sal_uInt16>(nPos);

    if (m_xPanel)
        m_xPanel->TriggerDeckLayouting();
    if (m_pPanel)
        m_pPanel->TriggerDeckLayouting();
}

IMPL_LINK_NOARG(AreaPropertyPanelBase, SelectFillColorHdl, ColorListBox&, void)
@@ -596,8 +596,8 @@ void AreaPropertyPanelBase::SelectFillAttrHdl_Impl()
            break;
        }
    }
    if (m_xPanel)
        m_xPanel->TriggerDeckLayouting();
    if (m_pPanel)
        m_pPanel->TriggerDeckLayouting();
}

void AreaPropertyPanelBase::ImpUpdateTransparencies()
@@ -852,8 +852,8 @@ void AreaPropertyPanelBase::updateFillStyle(bool bDisabled, bool bDefaultOrSet, 
    mxToolBoxColor->hide();
    meLastXFS = static_cast<sal_uInt16>(-1);
    mpStyleItem.reset();
    if (m_xPanel)
        m_xPanel->TriggerDeckLayouting();
    if (m_pPanel)
        m_pPanel->TriggerDeckLayouting();
}

void AreaPropertyPanelBase::updateFillGradient(bool bDisabled, bool bDefaultOrSet, const SfxPoolItem* pState)
@@ -893,8 +893,8 @@ void AreaPropertyPanelBase::updateFillGradient(bool bDisabled, bool bDefaultOrSe
            mxLbFillGradTo->SetNoSelection();
        }
    }
    if (m_xPanel)
        m_xPanel->TriggerDeckLayouting();
    if (m_pPanel)
        m_pPanel->TriggerDeckLayouting();
}

void AreaPropertyPanelBase::updateFillHatch(bool bDisabled, bool bDefaultOrSet, const SfxPoolItem* pState)
@@ -926,8 +926,8 @@ void AreaPropertyPanelBase::updateFillHatch(bool bDisabled, bool bDefaultOrSet, 
            mxLbFillAttr->set_active(-1);
        }
    }
    if (m_xPanel)
        m_xPanel->TriggerDeckLayouting();
    if (m_pPanel)
        m_pPanel->TriggerDeckLayouting();
}

void AreaPropertyPanelBase::updateFillColor(bool bDefaultOrSet, const SfxPoolItem* pState)
@@ -945,8 +945,8 @@ void AreaPropertyPanelBase::updateFillColor(bool bDefaultOrSet, const SfxPoolIte
        mxLbFillType->set_active(SOLID);
        Update();
    }
    if (m_xPanel)
        m_xPanel->TriggerDeckLayouting();
    if (m_pPanel)
        m_pPanel->TriggerDeckLayouting();
}

void AreaPropertyPanelBase::updateFillBitmap(bool bDisabled, bool bDefaultOrSet, const SfxPoolItem* pState)
@@ -980,8 +980,8 @@ void AreaPropertyPanelBase::updateFillBitmap(bool bDisabled, bool bDefaultOrSet,
            mxLbFillAttr->set_active(-1);
        }
    }
    if (m_xPanel)
        m_xPanel->TriggerDeckLayouting();
    if (m_pPanel)
        m_pPanel->TriggerDeckLayouting();
}

void AreaPropertyPanelBase::NotifyItemUpdate(
@@ -1248,8 +1248,8 @@ void AreaPropertyPanelBase::Update()
                OSL_ENSURE(false, "Non supported FillType (!)");
            break;
        }
        if (m_xPanel)
            m_xPanel->TriggerDeckLayouting();
        if (m_pPanel)
            m_pPanel->TriggerDeckLayouting();
}

IMPL_LINK_NOARG(AreaPropertyPanelBase, ModifyTransSliderHdl, weld::Scale&, void)