[Libreoffice-commits] core.git: include/svtools include/svx include/vcl officecfg/registry sc/source sc/uiconfig sd/source solenv/bin solenv/sanitizers svtools/source svx/source svx/uiconfig svx/UIConfig_svx.mk svx/util sw/source vcl/source vcl/uiconfig vcl/unx

Caolán McNamara (via logerrit) logerrit at kemper.freedesktop.org
Fri Apr 24 15:48:44 UTC 2020


 include/svtools/ctrlbox.hxx                                     |    2 
 include/svx/tbcontrl.hxx                                        |   24 
 include/vcl/weld.hxx                                            |   19 
 officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu |   11 
 sc/source/ui/app/scdll.cxx                                      |    1 
 sc/uiconfig/scalc/ui/sidebaralignment.ui                        |    4 
 sd/source/ui/app/sddll.cxx                                      |    2 
 solenv/bin/native-code.py                                       |    1 
 solenv/sanitizers/ui/vcl.suppr                                  |    1 
 svtools/source/control/ctrlbox.cxx                              |    2 
 svx/UIConfig_svx.mk                                             |    1 
 svx/source/sidebar/styles/StylesPropertyPanel.cxx               |   17 
 svx/source/sidebar/styles/StylesPropertyPanel.hxx               |   10 
 svx/source/tbxctrls/tbcontrl.cxx                                |  793 +++++-----
 svx/uiconfig/ui/applystylebox.ui                                |   30 
 svx/uiconfig/ui/sidebarlists.ui                                 |    2 
 svx/uiconfig/ui/sidebarparagraph.ui                             |    2 
 svx/uiconfig/ui/sidebarstylespanel.ui                           |   55 
 svx/util/svxcore.component                                      |    4 
 sw/source/uibase/app/swmodule.cxx                               |    2 
 vcl/source/app/salvtables.cxx                                   |   74 
 vcl/uiconfig/ui/combobox.ui                                     |   50 
 vcl/unx/gtk3/gtk3gtkinst.cxx                                    |  166 +-
 23 files changed, 806 insertions(+), 467 deletions(-)

New commits:
commit 16309a9516c1f173056fc103c6428e74217c7927
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Sun Dec 22 17:08:01 2019 +0000
Commit:     Caolán McNamara <caolanm at redhat.com>
CommitDate: Fri Apr 24 17:48:00 2020 +0200

    weld StylesPropertyPanel
    
    and SvxStyleToolBoxControl, etc.
    
    use a GtkOverlay to support the submenu hackery in the Style
    wysiwyg combobox dropdown
    
    Change-Id: I17baa56f382243070ee49e6d707e97324e4f4d67
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/85720
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/include/svtools/ctrlbox.hxx b/include/svtools/ctrlbox.hxx
index 4ecff16ec1ef..8cdb5efd1fed 100644
--- a/include/svtools/ctrlbox.hxx
+++ b/include/svtools/ctrlbox.hxx
@@ -339,7 +339,7 @@ private:
     SVT_DLLPRIVATE void         ImplDestroyFontList();
 
     DECL_LINK(CustomRenderHdl, weld::ComboBox::render_args, void);
-    DECL_STATIC_LINK(FontNameBox, CustomGetSizeHdl, weld::ComboBox::get_size_args, Size);
+    DECL_STATIC_LINK(FontNameBox, CustomGetSizeHdl, OutputDevice&, Size);
     DECL_LINK(UpdateHdl, Timer*, void);
 
     void            LoadMRUEntries( const OUString& aFontMRUEntriesFile );
diff --git a/include/svx/tbcontrl.hxx b/include/svx/tbcontrl.hxx
index 0c7da003291f..387c67f4bdb3 100644
--- a/include/svx/tbcontrl.hxx
+++ b/include/svx/tbcontrl.hxx
@@ -146,7 +146,6 @@ class SvxFontItem;
 class SfxStyleControllerItem_Impl;
 class SfxStyleSheetBasePool;
 class SfxTemplateItem;
-class SvxStyleBox_Impl;
 class PaletteManager;
 
 namespace svx
@@ -154,25 +153,22 @@ namespace svx
     class ToolboxButtonColorUpdaterBase;
 }
 
-class SVXCORE_DLLPUBLIC SvxStyleToolBoxControl final : public SfxToolBoxControl
+class SVXCORE_DLLPUBLIC SvxStyleToolBoxControl final : public cppu::ImplInheritanceHelper<svt::ToolboxController,
+                                                                                          css::lang::XServiceInfo>
 {
     struct Impl;
     std::unique_ptr<Impl> pImpl;
 
 public:
-    SFX_DECL_TOOLBOX_CONTROL();
-
-    SvxStyleToolBoxControl(sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rToolBox);
+    SvxStyleToolBoxControl();
     virtual ~SvxStyleToolBoxControl() override;
 
-    virtual VclPtr<vcl::Window> CreateItemWindow(vcl::Window* pParent) override;
-
-    virtual void StateChanged(sal_uInt16 nSID, SfxItemState eState,
-                              const SfxPoolItem* pState) override;
+    // XStatusListener
+    virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override;
 
-    DECL_LINK( VisibilityNotification, SvxStyleBox_Impl&, void );
+    // XToolbarController
+    virtual css::uno::Reference<css::awt::XWindow> SAL_CALL createItemWindow(const css::uno::Reference<css::awt::XWindow>& rParent) override;
 
-private:
     // XInitialization
     virtual void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& aArguments) override;
 
@@ -182,6 +178,12 @@ private:
     // XComponent
     virtual void SAL_CALL dispose() override;
 
+    // XServiceInfo
+    virtual OUString SAL_CALL getImplementationName() override;
+    virtual sal_Bool SAL_CALL supportsService(const OUString& rServiceName) override;
+    virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
 #define MAX_FAMILIES 5
 
     SfxStyleSheetBasePool* pStyleSheetPool;
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 2d94323d6434..d059e9cd455d 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -585,6 +585,8 @@ enum class EntryMessageType
     Error,
 };
 
+class Menu;
+
 /// A widget used to choose from a list of items.
 class VCL_DLLPUBLIC ComboBox : virtual public Container
 {
@@ -593,7 +595,6 @@ private:
 
 public:
     // OUString is the id of the row, it may be null to measure the height of a generic line
-    typedef std::pair<vcl::RenderContext&, const OUString&> get_size_args;
     typedef std::tuple<vcl::RenderContext&, const tools::Rectangle&, bool, const OUString&>
         render_args;
 
@@ -615,11 +616,8 @@ protected:
                 rDevice, rRect, bSelected, rId));
     }
 
-    Link<get_size_args, Size> m_aGetSizeHdl;
-    Size signal_custom_get_size(vcl::RenderContext& rDevice, const OUString& rId)
-    {
-        return m_aGetSizeHdl.Call(std::pair<vcl::RenderContext&, const OUString&>(rDevice, rId));
-    }
+    Link<vcl::RenderContext&, Size> m_aGetSizeHdl;
+    Size signal_custom_get_size(vcl::RenderContext& rDevice) { return m_aGetSizeHdl.Call(rDevice); }
 
 public:
     virtual void insert(int pos, const OUString& rStr, const OUString* pId,
@@ -717,12 +715,19 @@ public:
     bool get_value_changed_from_saved() const { return m_sSavedValue != get_active_text(); }
 
     // for custom rendering a row
-    void connect_custom_get_size(const Link<get_size_args, Size>& rLink) { m_aGetSizeHdl = rLink; }
+    void connect_custom_get_size(const Link<vcl::RenderContext&, Size>& rLink)
+    {
+        m_aGetSizeHdl = rLink;
+    }
     void connect_custom_render(const Link<render_args, void>& rLink) { m_aRenderHdl = rLink; }
     // call set_custom_renderer after setting custom callbacks
     virtual void set_custom_renderer() = 0;
     // create a virtual device compatible with the device passed in render_args wrt alpha
     virtual VclPtr<VirtualDevice> create_render_virtual_device() const = 0;
+    // set a sub menu for a entry, only works with custom rendering
+    virtual void set_item_menu(const OString& rIdent, weld::Menu* pMenu) = 0;
+    // get the width needed to show the menu launcher in a custom row
+    virtual int get_menu_button_width() const = 0;
 
     // for mru support
     virtual int get_max_mru_count() const = 0;
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu b/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu
index b9c4d64f4278..48ed82b932aa 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu
@@ -1701,6 +1701,17 @@
           <value>com.sun.star.comp.svx.FontNameToolBoxControl</value>
         </prop>
       </node>
+      <node oor:name="StyleToolBox" oor:op="replace">
+        <prop oor:name="Command">
+          <value>.uno:StyleApply</value>
+        </prop>
+        <prop oor:name="Module">
+          <value/>
+        </prop>
+        <prop oor:name="Controller">
+          <value>com.sun.star.comp.svx.StyleToolBoxControl</value>
+        </prop>
+      </node>
       <node oor:name="OpenToolbarController" oor:op="replace">
         <prop oor:name="Command">
           <value>.uno:Open</value>
diff --git a/sc/source/ui/app/scdll.cxx b/sc/source/ui/app/scdll.cxx
index c50fcce995cd..2d254dbe1bac 100644
--- a/sc/source/ui/app/scdll.cxx
+++ b/sc/source/ui/app/scdll.cxx
@@ -147,7 +147,6 @@ void ScDLL::Init()
     SvxTbxCtlDraw                   ::RegisterControl(SID_INSERT_DRAW,          pMod);
     SvxFillToolBoxControl           ::RegisterControl(0, pMod);
     SvxLineWidthToolBoxControl      ::RegisterControl(0, pMod);
-    SvxStyleToolBoxControl          ::RegisterControl(SID_STYLE_APPLY,          pMod);
     SvxClipBoardControl             ::RegisterControl(SID_PASTE,                pMod );
     SvxClipBoardControl             ::RegisterControl(SID_PASTE_UNFORMATTED,    pMod );
     svx::FormatPaintBrushToolBoxControl::RegisterControl(SID_FORMATPAINTBRUSH,  pMod );
diff --git a/sc/uiconfig/scalc/ui/sidebaralignment.ui b/sc/uiconfig/scalc/ui/sidebaralignment.ui
index 5d5474ba6e01..ce04c242bddf 100644
--- a/sc/uiconfig/scalc/ui/sidebaralignment.ui
+++ b/sc/uiconfig/scalc/ui/sidebaralignment.ui
@@ -165,7 +165,6 @@
                   <object class="GtkToggleToolButton" id=".uno:ParaLeftToRight">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="is_important">True</property>
                     <property name="use_underline">True</property>
                   </object>
                   <packing>
@@ -177,7 +176,6 @@
                   <object class="GtkToggleToolButton" id=".uno:ParaRightToLeft">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="is_important">True</property>
                     <property name="use_underline">True</property>
                   </object>
                   <packing>
@@ -249,7 +247,6 @@
               <object class="GtkToolButton" id=".uno:IncrementIndent">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="is_important">True</property>
                 <property name="use_underline">True</property>
               </object>
               <packing>
@@ -261,7 +258,6 @@
               <object class="GtkToolButton" id=".uno:DecrementIndent">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="is_important">True</property>
                 <property name="use_underline">True</property>
               </object>
               <packing>
diff --git a/sd/source/ui/app/sddll.cxx b/sd/source/ui/app/sddll.cxx
index dcaab836ec68..bb52a9722dbd 100644
--- a/sd/source/ui/app/sddll.cxx
+++ b/sd/source/ui/app/sddll.cxx
@@ -179,8 +179,6 @@ void SdDLL::RegisterControllers(SdModule* pMod)
     SvxFillToolBoxControl::RegisterControl(0, pMod);
     SvxLineWidthToolBoxControl::RegisterControl(0, pMod);
 
-    SvxStyleToolBoxControl::RegisterControl(0, pMod);
-
     SvxGrafModeToolBoxControl::RegisterControl( SID_ATTR_GRAF_MODE, pMod );
     SvxGrafRedToolBoxControl::RegisterControl( SID_ATTR_GRAF_RED, pMod );
     SvxGrafGreenToolBoxControl::RegisterControl( SID_ATTR_GRAF_GREEN, pMod );
diff --git a/solenv/bin/native-code.py b/solenv/bin/native-code.py
index 3ea5f085b66e..dff4cc4cb489 100755
--- a/solenv/bin/native-code.py
+++ b/solenv/bin/native-code.py
@@ -257,6 +257,7 @@ core_constructor_list = [
     "com_sun_star_comp_svx_FontNameToolBoxControl_get_implementation",
     "com_sun_star_comp_Svx_GraphicExportHelper_get_implementation",
     "com_sun_star_comp_Svx_GraphicImportHelper_get_implementation",
+    "com_sun_star_comp_svx_StyleToolBoxControl_get_implementation",
 # toolkit/util/tk.component
     "stardiv_Toolkit_StdTabController_get_implementation",
     "stardiv_Toolkit_UnoButtonControl_get_implementation",
diff --git a/solenv/sanitizers/ui/vcl.suppr b/solenv/sanitizers/ui/vcl.suppr
index b26735592919..96a13e0cac4f 100644
--- a/solenv/sanitizers/ui/vcl.suppr
+++ b/solenv/sanitizers/ui/vcl.suppr
@@ -5,6 +5,7 @@ vcl/uiconfig/ui/aboutbox.ui://GtkLabel[@id='description'] orphan-label
 vcl/uiconfig/ui/aboutbox.ui://GtkLabel[@id='copyright'] orphan-label
 vcl/uiconfig/ui/combobox.ui://GtkEntry[@id='entry'] no-labelled-by
 vcl/uiconfig/ui/combobox.ui://GtkToggleButton[@id='button'] button-no-label
+vcl/uiconfig/ui/combobox.ui://GtkMenuButton[@id='overlaybutton'] button-no-label
 vcl/uiconfig/ui/cupspassworddialog.ui://GtkLabel[@id='text'] orphan-label
 vcl/uiconfig/ui/printdialog.ui://GtkEntry[@id='pageedit-nospin'] no-labelled-by
 vcl/uiconfig/ui/printdialog.ui://GtkLabel[@id='totalnumpages'] orphan-label
diff --git a/svtools/source/control/ctrlbox.cxx b/svtools/source/control/ctrlbox.cxx
index 78be607b51fc..b31ccc45d4a3 100644
--- a/svtools/source/control/ctrlbox.cxx
+++ b/svtools/source/control/ctrlbox.cxx
@@ -489,7 +489,7 @@ void FontNameBox::EnableWYSIWYG()
     mbWYSIWYG = true;
 }
 
-IMPL_STATIC_LINK_NOARG(FontNameBox, CustomGetSizeHdl, weld::ComboBox::get_size_args, Size)
+IMPL_STATIC_LINK_NOARG(FontNameBox, CustomGetSizeHdl, OutputDevice&, Size)
 {
     return gUserItemSz;
 }
diff --git a/svx/UIConfig_svx.mk b/svx/UIConfig_svx.mk
index 98ef36a88c6c..861eea48776c 100644
--- a/svx/UIConfig_svx.mk
+++ b/svx/UIConfig_svx.mk
@@ -21,6 +21,7 @@ $(eval $(call gb_UIConfig_add_uifiles,svx,\
 	svx/uiconfig/ui/addnamespacedialog \
 	svx/uiconfig/ui/addsubmissiondialog \
 	svx/uiconfig/ui/asianphoneticguidedialog \
+	svx/uiconfig/ui/applystylebox \
 	svx/uiconfig/ui/cellmenu \
 	svx/uiconfig/ui/charsetmenu \
 	svx/uiconfig/ui/checkbuttonbox \
diff --git a/svx/source/sidebar/styles/StylesPropertyPanel.cxx b/svx/source/sidebar/styles/StylesPropertyPanel.cxx
index 24189c80cfc7..931862f4f1ed 100644
--- a/svx/source/sidebar/styles/StylesPropertyPanel.cxx
+++ b/svx/source/sidebar/styles/StylesPropertyPanel.cxx
@@ -22,9 +22,12 @@ VclPtr<vcl::Window> StylesPropertyPanel::Create (
 }
 
 StylesPropertyPanel::StylesPropertyPanel ( vcl::Window* pParent, const css::uno::Reference<css::frame::XFrame>& rxFrame )
-    : PanelLayout(pParent, "SidebarStylesPanel", "svx/ui/sidebarstylespanel.ui", rxFrame)
+    : PanelLayout(pParent, "SidebarStylesPanel", "svx/ui/sidebarstylespanel.ui", rxFrame, true)
+    , m_xFontStyle(m_xBuilder->weld_toolbar("fontstyletoolbox"))
+    , m_xFontStyleDispatch(new ToolbarUnoDispatcher(*m_xFontStyle, *m_xBuilder, rxFrame))
+    , m_xStyle(m_xBuilder->weld_toolbar("style"))
+    , m_xStyleDispatch(new ToolbarUnoDispatcher(*m_xStyle, *m_xBuilder, rxFrame))
 {
-
 }
 
 StylesPropertyPanel::~StylesPropertyPanel()
@@ -32,6 +35,16 @@ StylesPropertyPanel::~StylesPropertyPanel()
     disposeOnce();
 }
 
+void StylesPropertyPanel::dispose()
+{
+    m_xStyleDispatch.reset();
+    m_xStyle.reset();
+    m_xFontStyleDispatch.reset();
+    m_xFontStyle.reset();
+
+    PanelLayout::dispose();
+}
+
 void StylesPropertyPanel::DataChanged( const DataChangedEvent& /*rEvent*/)
 {
 
diff --git a/svx/source/sidebar/styles/StylesPropertyPanel.hxx b/svx/source/sidebar/styles/StylesPropertyPanel.hxx
index b57650348136..357634504f2a 100644
--- a/svx/source/sidebar/styles/StylesPropertyPanel.hxx
+++ b/svx/source/sidebar/styles/StylesPropertyPanel.hxx
@@ -2,12 +2,20 @@
 #define INCLUDED_SVX_SOURCE_SIDEBAR_STYLES_STYLESPROPERTYPANEL_HXX
 
 #include <svx/sidebar/PanelLayout.hxx>
+#include <sfx2/weldutils.hxx>
 
 namespace svx { namespace sidebar{
 
 class StylesPropertyPanel:
     public PanelLayout
 {
+private:
+    std::unique_ptr<weld::Toolbar> m_xFontStyle;
+    std::unique_ptr<ToolbarUnoDispatcher> m_xFontStyleDispatch;
+
+    std::unique_ptr<weld::Toolbar> m_xStyle;
+    std::unique_ptr<ToolbarUnoDispatcher> m_xStyleDispatch;
+
 public:
     virtual ~StylesPropertyPanel() override;
 
@@ -17,6 +25,8 @@ public:
 
     virtual void DataChanged( const DataChangedEvent& rEvent ) override;
 
+    virtual void dispose() override;
+
     StylesPropertyPanel(
         vcl::Window* pParent,
         const css::uno::Reference<css::frame::XFrame>& rxFrame);
diff --git a/svx/source/tbxctrls/tbcontrl.cxx b/svx/source/tbxctrls/tbcontrl.cxx
index 5ab016dc50fa..cf5541622150 100644
--- a/svx/source/tbxctrls/tbcontrl.cxx
+++ b/svx/source/tbxctrls/tbcontrl.cxx
@@ -27,7 +27,6 @@
 #include <vcl/commandinfoprovider.hxx>
 #include <vcl/combobox.hxx>
 #include <vcl/event.hxx>
-#include <vcl/menubtn.hxx>
 #include <vcl/toolbox.hxx>
 #include <vcl/customweld.hxx>
 #include <vcl/vclptr.hxx>
@@ -106,8 +105,7 @@
 
 #define MAX_MRU_FONTNAME_ENTRIES    5
 
-// don't make more than 15 entries visible at once
-#define MAX_STYLES_ENTRIES          15
+#define COMBO_WIDTH_IN_CHARS        16
 
 // namespaces
 using namespace ::editeng;
@@ -117,44 +115,105 @@ using namespace ::com::sun::star::frame;
 using namespace ::com::sun::star::beans;
 using namespace ::com::sun::star::lang;
 
-SFX_IMPL_TOOLBOX_CONTROL( SvxStyleToolBoxControl, SfxTemplateItem );
-
-class SvxStyleBox_Impl : public ComboBox
+namespace
+{
+class SvxStyleBox_Base
 {
-    using Window::IsVisible;
 public:
-    SvxStyleBox_Impl( vcl::Window* pParent, const OUString& rCommand, SfxStyleFamily eFamily, const Reference< XDispatchProvider >& rDispatchProvider,
-                        const Reference< XFrame >& _xFrame,const OUString& rClearFormatKey, const OUString& rMoreKey, bool bInSpecialMode );
-    virtual ~SvxStyleBox_Impl() override;
-    virtual void dispose() override;
+    SvxStyleBox_Base(std::unique_ptr<weld::ComboBox> xWidget, const OUString& rCommand, SfxStyleFamily eFamily,
+                     const Reference<XDispatchProvider>& rDispatchProvider,
+                     const Reference<XFrame>& _xFrame,const OUString& rClearFormatKey,
+                     const OUString& rMoreKey, bool bInSpecialMode, SvxStyleToolBoxControl& rCtrl);
+
+    virtual ~SvxStyleBox_Base()
+    {
+    }
 
     void            SetFamily( SfxStyleFamily eNewFamily );
-    bool            IsVisible() const { return bVisible; }
 
-    virtual bool    PreNotify( NotifyEvent& rNEvt ) override;
-    virtual bool    EventNotify( NotifyEvent& rNEvt ) override;
-    virtual void    DataChanged( const DataChangedEvent& rDCEvt ) override;
-    virtual void    StateChanged( StateChangedType nStateChange ) override;
+    void            SetDefaultStyle( const OUString& rDefault ) { sDefaultStyle = rDefault; }
 
-    virtual void    UserDraw( const UserDrawEvent& rUDEvt ) override;
+    int get_count() const { return m_xWidget->get_count(); }
+    OUString get_text(int nIndex) const { return m_xWidget->get_text(nIndex); }
+    OUString get_active_text() const { return m_xWidget->get_active_text(); }
 
-    void            SetVisibilityListener( const Link<SvxStyleBox_Impl&,void>& aVisListener ) { aVisibilityListener = aVisListener; }
+    void append_text(const OUString& rStr)
+    {
+        OUString sId(OUString::number(m_xWidget->get_count()));
+        m_xWidget->append(sId, rStr);
+    }
 
-    void            SetDefaultStyle( const OUString& rDefault ) { sDefaultStyle = rDefault; }
-    virtual boost::property_tree::ptree DumpAsPropertyTree() override;
+    void insert_separator(int pos, const OUString& rId)
+    {
+        m_xWidget->insert_separator(pos, rId);
+    }
 
-protected:
-    /// Calculate the optimal width of the dropdown.  Very expensive operation, triggers lots of font measurement.
-    DECL_LINK(CalcOptimalExtraUserWidth, VclWindowEvent&, void);
+    virtual void set_sensitive(bool bSensitive)
+    {
+        m_xWidget->set_sensitive(bSensitive);
+    }
+
+    void set_active_or_entry_text(const OUString& rText)
+    {
+        const int nFound = m_xWidget->find_text(rText);
+        if (nFound != -1)
+            m_xWidget->set_active(nFound);
+        else
+            m_xWidget->set_entry_text(rText);
+    }
+
+    void set_active(int nActive)
+    {
+        m_xWidget->set_active(nActive);
+    }
+
+    void freeze()
+    {
+        m_xWidget->freeze();
+    }
+
+    void save_value()
+    {
+        m_xWidget->save_value();
+    }
 
-    virtual void    Select() override;
+    void clear()
+    {
+        m_xWidget->clear();
+        m_nMaxUserDrawFontWidth = 0;
+    }
+
+    void thaw()
+    {
+        m_xWidget->thaw();
+    }
+
+    virtual bool DoKeyInput(const KeyEvent& rKEvt);
 
 private:
+    DECL_LINK(SelectHdl, weld::ComboBox&, void);
+    DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
+    DECL_LINK(ActivateHdl, weld::ComboBox&, bool);
+    DECL_LINK(FocusOutHdl, weld::Widget&, void);
+    DECL_LINK(DumpAsPropertyTreeHdl, boost::property_tree::ptree&, void);
+    DECL_LINK(CustomRenderHdl, weld::ComboBox::render_args, void);
+    DECL_LINK(CustomGetSizeHdl, OutputDevice&, Size);
+
+    /// Calculate the optimal width of the dropdown.  Very expensive operation, triggers lots of font measurement.
+    void CalcOptimalExtraUserWidth(vcl::RenderContext& rRenderContext);
+
+    void Select(bool bNonTravelSelect);
+
+protected:
+    SvxStyleToolBoxControl& m_rCtrl;
+
+    std::unique_ptr<weld::Builder>  m_xMenuBuilder;
+    std::unique_ptr<weld::Menu>     m_xMenu;
+    std::unique_ptr<weld::ComboBox> m_xWidget;
+
     SfxStyleFamily                  eStyleFamily;
-    sal_Int32                       nCurSel;
+    int                             m_nMaxUserDrawFontWidth;
     bool                            bRelease;
-    Size                            aLogicalSize;
-    Link<SvxStyleBox_Impl&,void>    aVisibilityListener;
     bool                            bVisible;
     Reference< XDispatchProvider >  m_xDispatchProvider;
     Reference< XFrame >             m_xFrame;
@@ -163,27 +222,58 @@ private:
     OUString                        aMoreKey;
     OUString                        sDefaultStyle;
     bool                            bInSpecialMode;
-    VclPtr<MenuButton>              m_pButtons[MAX_STYLES_ENTRIES];
-    VclBuilder                      m_aBuilder;
-    VclPtr<PopupMenu>               m_pMenu;
 
     void            ReleaseFocus();
     static Color    TestColorsVisible(const Color &FontCol, const Color &BackCol);
-    static void     UserDrawEntry(const UserDrawEvent& rUDEvt, const OUString &rStyleName);
-    void            SetupEntry(vcl::RenderContext& rRenderContext, vcl::Window* pParent, sal_Int32 nItem, const tools::Rectangle& rRect, const OUString& rStyleName, bool bIsNotSelected);
-    static bool     AdjustFontForItemHeight(OutputDevice* pDevice, tools::Rectangle const & rTextRect, long nHeight);
-    void            SetOptimalSize();
-    DECL_LINK( MenuSelectHdl, Menu *, bool );
-    DECL_STATIC_LINK(SvxStyleBox_Impl, ShowMoreHdl, void*, void);
+    static void     UserDrawEntry(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect, const OUString &rStyleName);
+    void            SetupEntry(vcl::RenderContext& rRenderContext, sal_Int32 nItem, const tools::Rectangle& rRect, const OUString& rStyleName, bool bIsNotSelected);
+    static bool     AdjustFontForItemHeight(OutputDevice& rDevice, tools::Rectangle const & rTextRect, long nHeight);
+    DECL_LINK(MenuSelectHdl, const OString&, void);
+    DECL_STATIC_LINK(SvxStyleBox_Base, ShowMoreHdl, void*, void);
 };
 
-namespace {
+class SvxStyleBox_Impl final : public InterimItemWindow
+                             , public SvxStyleBox_Base
+{
+public:
+    SvxStyleBox_Impl(vcl::Window* pParent, const OUString& rCommand, SfxStyleFamily eFamily, const Reference< XDispatchProvider >& rDispatchProvider,
+                     const Reference< XFrame >& _xFrame,const OUString& rClearFormatKey, const OUString& rMoreKey, bool bInSpecialMode, SvxStyleToolBoxControl& rCtrl);
+
+    virtual ~SvxStyleBox_Impl() override
+    {
+        disposeOnce();
+    }
+
+    virtual void dispose() override
+    {
+        m_xWidget.reset();
+        m_xMenu.reset();
+        m_xMenuBuilder.reset();
+        InterimItemWindow::dispose();
+    }
+
+    virtual bool DoKeyInput(const KeyEvent& rKEvt) override;
+
+private:
+
+    virtual void set_sensitive(bool bSensitive) override
+    {
+        m_xWidget->set_sensitive(bSensitive);
+        if (bSensitive)
+            InterimItemWindow::Enable();
+        else
+            InterimItemWindow::Disable();
+    }
+
+    virtual void    DataChanged( const DataChangedEvent& rDCEvt ) override;
+    void            SetOptimalSize();
+};
 
 class SvxFontNameBox_Impl;
 class SvxFontNameBox_Base;
 
-class SvxFontNameToolBoxControl : public cppu::ImplInheritanceHelper< svt::ToolboxController,
-                                                                      css::lang::XServiceInfo >
+class SvxFontNameToolBoxControl final : public cppu::ImplInheritanceHelper<svt::ToolboxController,
+                                                                           css::lang::XServiceInfo>
 {
 public:
     SvxFontNameToolBoxControl();
@@ -192,7 +282,7 @@ public:
     virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override;
 
     // XToolbarController
-    virtual css::uno::Reference< css::awt::XWindow > SAL_CALL createItemWindow( const css::uno::Reference< css::awt::XWindow >& rParent ) override;
+    virtual css::uno::Reference<css::awt::XWindow> SAL_CALL createItemWindow(const css::uno::Reference<css::awt::XWindow>& rParent) override;
 
     // XComponent
     virtual void SAL_CALL dispose() override;
@@ -218,7 +308,6 @@ protected:
     const FontList*                pFontList;
     ::std::unique_ptr<FontList>    m_aOwnFontList;
     vcl::Font                      aCurFont;
-    OUString                       aCurText;
     sal_uInt16                     nFtCount;
     bool                           bRelease;
     Reference< XDispatchProvider > m_xDispatchProvider;
@@ -477,7 +566,7 @@ private:
                                 Color aColor1, Color aColor2, Color aColorDist,
                                 SvxBorderLineStyle nStyle, BitmapEx& rBmp )
     {
-        auto nMinWidth = GetDrawingArea()->get_ref_device().approximate_digit_width() * 15;
+        auto nMinWidth = GetDrawingArea()->get_ref_device().approximate_digit_width() * COMBO_WIDTH_IN_CHARS;
         Size aSize(nMinWidth, aTxtSize.Height());
         aSize.AdjustWidth( -(aTxtSize.Width()) );
         aSize.AdjustWidth( -6 );
@@ -728,23 +817,24 @@ class SfxStyleControllerItem_Impl : public SfxStatusListener
         SvxStyleToolBoxControl& rControl;
 };
 
-#define BUTTON_WIDTH 20
 #define BUTTON_PADDING 10
 #define ITEM_HEIGHT 30
 
-SvxStyleBox_Impl::SvxStyleBox_Impl(vcl::Window* pParent,
+SvxStyleBox_Base::SvxStyleBox_Base(std::unique_ptr<weld::ComboBox> xWidget,
                                    const OUString& rCommand,
                                    SfxStyleFamily eFamily,
                                    const Reference< XDispatchProvider >& rDispatchProvider,
                                    const Reference< XFrame >& _xFrame,
                                    const OUString& rClearFormatKey,
                                    const OUString& rMoreKey,
-                                   bool bInSpec)
-    : ComboBox(pParent, WB_SORT | WB_BORDER | WB_HIDE | WB_DROPDOWN | WB_AUTOHSCROLL)
+                                   bool bInSpec, SvxStyleToolBoxControl& rCtrl)
+    : m_rCtrl(rCtrl)
+    , m_xMenuBuilder(Application::CreateBuilder(nullptr, "svx/ui/stylemenu.ui"))
+    , m_xMenu(m_xMenuBuilder->weld_menu("menu"))
+    , m_xWidget(std::move(xWidget))
     , eStyleFamily( eFamily )
-    , nCurSel(0)
+    , m_nMaxUserDrawFontWidth(0)
     , bRelease( true )
-    , aLogicalSize(60, 86)
     , bVisible(false)
     , m_xDispatchProvider( rDispatchProvider )
     , m_xFrame(_xFrame)
@@ -752,42 +842,49 @@ SvxStyleBox_Impl::SvxStyleBox_Impl(vcl::Window* pParent,
     , aClearFormatKey( rClearFormatKey )
     , aMoreKey( rMoreKey )
     , bInSpecialMode( bInSpec )
-    , m_aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "svx/ui/stylemenu.ui", "")
-    , m_pMenu(m_aBuilder.get_menu("menu"))
 {
-    SetHelpId(HID_STYLE_LISTBOX);
-    m_pMenu->SetSelectHdl( LINK( this, SvxStyleBox_Impl, MenuSelectHdl ) );
-    for(VclPtr<MenuButton> & rpButton : m_pButtons)
-        rpButton = nullptr;
-    SetOptimalSize();
-    EnableAutocomplete( true );
-    EnableUserDraw( true );
-    AddEventListener(LINK(this, SvxStyleBox_Impl, CalcOptimalExtraUserWidth));
-    SetUserItemSize( Size( 0, ITEM_HEIGHT ) );
-    set_id("applystyle");
+    m_xWidget->connect_changed(LINK(this, SvxStyleBox_Base, SelectHdl));
+    m_xWidget->connect_key_press(LINK(this, SvxStyleBox_Base, KeyInputHdl));
+    m_xWidget->connect_entry_activate(LINK(this, SvxStyleBox_Base, ActivateHdl));
+    m_xWidget->connect_focus_out(LINK(this, SvxStyleBox_Base, FocusOutHdl));
+    m_xWidget->connect_get_property_tree(LINK(this, SvxStyleBox_Base, DumpAsPropertyTreeHdl));
+    m_xWidget->set_help_id(HID_STYLE_LISTBOX);
+    m_xWidget->set_entry_completion(true);
+    m_xMenu->connect_activate(LINK(this, SvxStyleBox_Base, MenuSelectHdl));
+
+    m_xWidget->connect_custom_get_size(LINK(this, SvxStyleBox_Base, CustomGetSizeHdl));
+    m_xWidget->connect_custom_render(LINK(this, SvxStyleBox_Base, CustomRenderHdl));
+    m_xWidget->set_custom_renderer();
+
+    int nCharWidth = m_xWidget->get_approximate_digit_width() * COMBO_WIDTH_IN_CHARS;
+    // set width in chars low so the size request will not be overridden
+    m_xWidget->set_entry_width_chars(1);
+    m_xWidget->set_size_request(nCharWidth, -1);
 }
 
-SvxStyleBox_Impl::~SvxStyleBox_Impl()
+IMPL_LINK(SvxStyleBox_Base, CustomGetSizeHdl, OutputDevice&, rArg, Size)
 {
-    disposeOnce();
+    CalcOptimalExtraUserWidth(rArg);
+    return Size(m_nMaxUserDrawFontWidth, ITEM_HEIGHT);
 }
 
-void SvxStyleBox_Impl::dispose()
+SvxStyleBox_Impl::SvxStyleBox_Impl(vcl::Window* pParent,
+                                   const OUString& rCommand,
+                                   SfxStyleFamily eFamily,
+                                   const Reference< XDispatchProvider >& rDispatchProvider,
+                                   const Reference< XFrame >& _xFrame,
+                                   const OUString& rClearFormatKey,
+                                   const OUString& rMoreKey,
+                                   bool bInSpec, SvxStyleToolBoxControl& rCtrl)
+    : InterimItemWindow(pParent, "svx/ui/applystylebox.ui", "ApplyStyleBox")
+    , SvxStyleBox_Base(m_xBuilder->weld_combo_box("applystyle"), rCommand, eFamily,
+                       rDispatchProvider, _xFrame, rClearFormatKey, rMoreKey, bInSpec, rCtrl)
 {
-    RemoveEventListener(LINK(this, SvxStyleBox_Impl, CalcOptimalExtraUserWidth));
-
-    for (VclPtr<MenuButton>& rButton : m_pButtons)
-    {
-        rButton.disposeAndClear();
-    }
-
-    m_pMenu.clear();
-    m_aBuilder.disposeBuilder();
-
-    ComboBox::dispose();
+    set_id("applystyle");
+    SetOptimalSize();
 }
 
-void SvxStyleBox_Impl::ReleaseFocus()
+void SvxStyleBox_Base::ReleaseFocus()
 {
     if ( !bRelease )
     {
@@ -798,56 +895,60 @@ void SvxStyleBox_Impl::ReleaseFocus()
         m_xFrame->getContainerWindow()->setFocus();
 }
 
-IMPL_LINK( SvxStyleBox_Impl, MenuSelectHdl, Menu*, pMenu, bool)
+IMPL_LINK(SvxStyleBox_Base, MenuSelectHdl, const OString&, rMenuIdent, void)
 {
-    OUString sEntry = GetSelectedEntry();
-    OString sMenuIdent = pMenu->GetCurItemIdent();
+    OUString sEntry = m_xWidget->get_active_text();
+
     ReleaseFocus(); // It must be after getting entry pos!
-    if (IsInDropDown())
-        ToggleDropDown();
-    Sequence< PropertyValue > aArgs( 2 );
+    Sequence<PropertyValue> aArgs(2);
     aArgs[0].Name   = "Param";
     aArgs[0].Value  <<= sEntry;
     aArgs[1].Name   = "Family";
     aArgs[1].Value  <<= sal_Int16( eStyleFamily );
 
-    if (sMenuIdent == "update")
+    if (rMenuIdent == "update")
     {
         SfxToolBoxControl::Dispatch( m_xDispatchProvider,
             ".uno:StyleUpdateByExample", aArgs );
     }
-    else if (sMenuIdent == "edit")
+    else if (rMenuIdent == "edit")
     {
         SfxToolBoxControl::Dispatch( m_xDispatchProvider,
             ".uno:EditStyle", aArgs );
     }
-
-    return false;
 }
 
-IMPL_STATIC_LINK_NOARG(SvxStyleBox_Impl, ShowMoreHdl, void*, void)
+IMPL_STATIC_LINK_NOARG(SvxStyleBox_Base, ShowMoreHdl, void*, void)
 {
     SfxViewFrame* pViewFrm = SfxViewFrame::Current();
-    DBG_ASSERT( pViewFrm, "SvxStyleBox_Impl::Select(): no viewframe" );
+    DBG_ASSERT( pViewFrm, "SvxStyleBox_Base::Select(): no viewframe" );
     if (!pViewFrm)
         return;
     pViewFrm->ShowChildWindow(SID_SIDEBAR);
     ::sfx2::sidebar::Sidebar::ShowPanel("StyleListPanel", pViewFrm->GetFrame().GetFrameInterface(), true);
 }
 
-void SvxStyleBox_Impl::Select()
+IMPL_LINK(SvxStyleBox_Base, SelectHdl, weld::ComboBox&, rCombo, void)
+{
+    Select(rCombo.changed_by_direct_pick()); // only when picked from the list
+}
+
+IMPL_LINK_NOARG(SvxStyleBox_Base, ActivateHdl, weld::ComboBox&, bool)
 {
-    // Tell base class about selection so that AT get informed about it.
-    ComboBox::Select();
+    Select(true);
+    return true;
+}
 
-    if ( IsTravelSelect() )
+void SvxStyleBox_Base::Select(bool bNonTravelSelect)
+{
+    if (!bNonTravelSelect)
         return;
 
-    OUString aSearchEntry( GetText() );
+    OUString aSearchEntry(m_xWidget->get_active_text());
     bool bDoIt = true, bClear = false;
     if( bInSpecialMode )
     {
-        if( aSearchEntry == aClearFormatKey && GetSelectedEntryPos() == 0 )
+        if( aSearchEntry == aClearFormatKey && m_xWidget->get_active() == 0 )
         {
             aSearchEntry = sDefaultStyle;
             bClear = true;
@@ -856,11 +957,11 @@ void SvxStyleBox_Impl::Select()
             SfxToolBoxControl::Dispatch( m_xDispatchProvider, ".uno:ResetAttributes",
                 aEmptyVals);
         }
-        else if( aSearchEntry == aMoreKey && GetSelectedEntryPos() == ( GetEntryCount() - 1 ) )
+        else if (aSearchEntry == aMoreKey && m_xWidget->get_active() == (m_xWidget->get_count() - 1))
         {
-            Application::PostUserEvent(LINK(nullptr, SvxStyleBox_Impl, ShowMoreHdl));
+            Application::PostUserEvent(LINK(nullptr, SvxStyleBox_Base, ShowMoreHdl));
             //tdf#113214 change text back to previous entry
-            SetText(GetSavedValue());
+            set_active_or_entry_text(m_xWidget->get_saved_value());
             bDoIt = false;
         }
     }
@@ -896,8 +997,8 @@ void SvxStyleBox_Impl::Select()
     if( bDoIt )
     {
         if ( bClear )
-            SetText( aSearchEntry );
-        SaveValue();
+            set_active_or_entry_text(aSearchEntry);
+        m_xWidget->save_value();
 
         Sequence< PropertyValue > aArgs( 2 );
         aArgs[0].Value  <<= aSearchEntry;
@@ -916,67 +1017,50 @@ void SvxStyleBox_Impl::Select()
     }
 }
 
-void SvxStyleBox_Impl::SetFamily( SfxStyleFamily eNewFamily )
+void SvxStyleBox_Base::SetFamily( SfxStyleFamily eNewFamily )
 {
     eStyleFamily = eNewFamily;
 }
 
-bool SvxStyleBox_Impl::PreNotify( NotifyEvent& rNEvt )
+IMPL_LINK_NOARG(SvxStyleBox_Base, FocusOutHdl, weld::Widget&, void)
 {
-    MouseNotifyEvent nType = rNEvt.GetType();
+    if (!m_xWidget->has_focus()) // a combobox can be comprised of different subwidget so double-check if none of those has focus
+        set_active_or_entry_text(m_xWidget->get_saved_value());
+}
 
-    if ( MouseNotifyEvent::MOUSEBUTTONDOWN == nType || MouseNotifyEvent::GETFOCUS == nType )
-        nCurSel = GetSelectedEntryPos();
-    else if ( MouseNotifyEvent::LOSEFOCUS == nType )
-    {
-        // don't handle before our Select() is called
-        if (!HasFocus() && !HasChildPathFocus() && !IsChild(rNEvt.GetWindow()))
-            SetText( GetSavedValue() );
-    }
-    return ComboBox::PreNotify( rNEvt );
+IMPL_LINK(SvxStyleBox_Base, KeyInputHdl, const KeyEvent&, rKEvt, bool)
+{
+    return DoKeyInput(rKEvt);
 }
 
-bool SvxStyleBox_Impl::EventNotify( NotifyEvent& rNEvt )
+bool SvxStyleBox_Base::DoKeyInput(const KeyEvent& rKEvt)
 {
     bool bHandled = false;
 
-    if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
-    {
-        sal_uInt16 nCode = rNEvt.GetKeyEvent()->GetKeyCode().GetCode();
+    sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
 
-        switch ( nCode )
-        {
-            case KEY_CONTEXTMENU:
-            {
-                if(IsInDropDown())
-                {
-                    const sal_Int32 nItem = GetSelectedEntryPos() - 1;
-                    if(nItem < MAX_STYLES_ENTRIES)
-                        m_pButtons[nItem]->ExecuteMenu();
-                    bHandled = true;
-                }
-                break;
-            }
-            case KEY_RETURN:
-            case KEY_TAB:
+    switch (nCode)
+    {
+        case KEY_TAB:
+            bRelease = false;
+            Select(true);
+            break;
+        case KEY_ESCAPE:
+            set_active_or_entry_text(m_xWidget->get_saved_value());
+            if (!m_rCtrl.IsInSidebar())
             {
-                if ( KEY_TAB == nCode )
-                    bRelease = false;
-                else
-                    bHandled = true;
-                Select();
-                break;
-            }
-
-            case KEY_ESCAPE:
-                SelectEntryPos( nCurSel );
-                if ( typeid( *GetParent() ) != typeid( sfx2::sidebar::SidebarToolBox ) )
-                    ReleaseFocus();
+                ReleaseFocus();
                 bHandled = true;
-                break;
-        }
+            }
+            break;
     }
-    return bHandled || ComboBox::EventNotify( rNEvt );
+
+    return bHandled;
+}
+
+bool SvxStyleBox_Impl::DoKeyInput(const KeyEvent& rKEvt)
+{
+    return SvxStyleBox_Base::DoKeyInput(rKEvt) || ChildKeyInput(rKEvt);
 }
 
 void SvxStyleBox_Impl::DataChanged( const DataChangedEvent& rDCEvt )
@@ -987,37 +1071,21 @@ void SvxStyleBox_Impl::DataChanged( const DataChangedEvent& rDCEvt )
         SetOptimalSize();
     }
 
-    ComboBox::DataChanged( rDCEvt );
-}
-
-void SvxStyleBox_Impl::StateChanged( StateChangedType nStateChange )
-{
-    ComboBox::StateChanged( nStateChange );
-
-    if ( nStateChange == StateChangedType::Visible )
-    {
-        bVisible = IsReallyVisible();
-        aVisibilityListener.Call( *this );
-    }
-    else if ( nStateChange == StateChangedType::InitShow )
-    {
-        bVisible = true;
-        aVisibilityListener.Call( *this );
-    }
+    InterimItemWindow::DataChanged( rDCEvt );
 }
 
-bool SvxStyleBox_Impl::AdjustFontForItemHeight(OutputDevice* pDevice, tools::Rectangle const & rTextRect, long nHeight)
+bool SvxStyleBox_Base::AdjustFontForItemHeight(OutputDevice& rDevice, tools::Rectangle const & rTextRect, long nHeight)
 {
     if (rTextRect.Bottom() > nHeight)
     {
         // the text does not fit, adjust the font size
         double ratio = static_cast< double >( nHeight ) / rTextRect.Bottom();
-        vcl::Font aFont(pDevice->GetFont());
+        vcl::Font aFont(rDevice.GetFont());
         Size aPixelSize(aFont.GetFontSize());
         aPixelSize.setWidth( aPixelSize.Width() * ratio );
         aPixelSize.setHeight( aPixelSize.Height() * ratio );
         aFont.SetFontSize(aPixelSize);
-        pDevice->SetFont(aFont);
+        rDevice.SetFont(aFont);
         return true;
     }
     return false;
@@ -1025,42 +1093,46 @@ bool SvxStyleBox_Impl::AdjustFontForItemHeight(OutputDevice* pDevice, tools::Rec
 
 void SvxStyleBox_Impl::SetOptimalSize()
 {
-    Size aSize(LogicToPixel(aLogicalSize, MapMode(MapUnit::MapAppFont)));
-    set_width_request(aSize.Width());
-    set_height_request(aSize.Height());
-    SetSizePixel(aSize);
+    SetSizePixel(get_preferred_size());
 }
 
-void SvxStyleBox_Impl::UserDrawEntry(const UserDrawEvent& rUDEvt, const OUString &rStyleName)
+void SvxStyleBox_Base::UserDrawEntry(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect, const OUString &rStyleName)
 {
-    vcl::RenderContext *pDevice = rUDEvt.GetRenderContext();
-
     // IMG_TXT_DISTANCE in ilstbox.hxx is 6, then 1 is added as
     // nBorder, and we are adding 1 in order to look better when
     // italics is present
     const int nLeftDistance = 8;
 
     tools::Rectangle aTextRect;
-    pDevice->GetTextBoundRect(aTextRect, rStyleName);
+    rRenderContext.GetTextBoundRect(aTextRect, rStyleName);
 
-    Point aPos( rUDEvt.GetRect().TopLeft() );
+    Point aPos(rRect.TopLeft());
     aPos.AdjustX(nLeftDistance );
 
-    if (!AdjustFontForItemHeight(pDevice, aTextRect, rUDEvt.GetRect().GetHeight()))
-        aPos.AdjustY(( rUDEvt.GetRect().GetHeight() - aTextRect.Bottom() ) / 2 );
+    if (!AdjustFontForItemHeight(rRenderContext, aTextRect, rRect.GetHeight()))
+        aPos.AdjustY((rRect.GetHeight() - aTextRect.Bottom() ) / 2);
 
-    pDevice->DrawText(aPos, rStyleName);
+    rRenderContext.DrawText(aPos, rStyleName);
 }
 
-void SvxStyleBox_Impl::SetupEntry(vcl::RenderContext& rRenderContext, vcl::Window* pParent, sal_Int32 nItem, const tools::Rectangle& rRect, const OUString& rStyleName, bool bIsNotSelected)
+void SvxStyleBox_Base::SetupEntry(vcl::RenderContext& rRenderContext, sal_Int32 nItem, const tools::Rectangle& rRect, const OUString& rStyleName, bool bIsNotSelected)
 {
-    unsigned int nId = rRect.GetHeight() != 0 ? (rRect.getY() / rRect.GetHeight()) : MAX_STYLES_ENTRIES;
-    if (nItem == 0 || nItem == GetEntryCount() - 1)
+    const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+    if (!bIsNotSelected)
+        rRenderContext.SetTextColor(rStyleSettings.GetHighlightTextColor());
+    else
+        rRenderContext.SetTextColor(rStyleSettings.GetDialogTextColor());
+
+    // handle the push-button
+    if (!bIsNotSelected)
     {
-        if(nId < MAX_STYLES_ENTRIES && m_pButtons[nId])
-            m_pButtons[nId]->Hide();
+        if (nItem == 0 || nItem == m_xWidget->get_count() - 1)
+            m_xWidget->set_item_menu(OString::number(nItem), nullptr);
+        else
+            m_xWidget->set_item_menu(OString::number(nItem), m_xMenu.get());
     }
-    else
+
+    if (nItem > 0 && nItem < m_xWidget->get_count() - 1)
     {
         SfxObjectShell *pShell = SfxObjectShell::Current();
         SfxStyleSheetBasePool* pPool = pShell->GetStyleSheetPool();
@@ -1181,93 +1253,69 @@ void SvxStyleBox_Impl::SetupEntry(vcl::RenderContext& rRenderContext, vcl::Windo
                 // set text color
                 if ( aFontCol != COL_AUTO )
                     rRenderContext.SetTextColor(aFontCol);
-
-                // handle the push-button
-                if (bIsNotSelected)
-                {
-                    if (nId < MAX_STYLES_ENTRIES && m_pButtons[nId])
-                        m_pButtons[nId]->Hide();
-                }
-                else
-                {
-                    if (nId < MAX_STYLES_ENTRIES)
-                    {
-                        if (!m_pButtons[nId] && pParent)
-                        {
-                            m_pButtons[nId] = VclPtr<MenuButton>::Create(pParent, WB_FLATBUTTON | WB_NOPOINTERFOCUS);
-                            m_pButtons[nId]->SetSizePixel(Size(BUTTON_WIDTH, rRect.GetHeight()));
-                            m_pButtons[nId]->SetPopupMenu(m_pMenu);
-                        }
-                        m_pButtons[nId]->SetPosPixel(Point(rRect.GetWidth() - BUTTON_WIDTH, rRect.getY()));
-                        m_pButtons[nId]->Show();
-                    }
-                }
             }
         }
     }
 }
 
-void SvxStyleBox_Impl::UserDraw( const UserDrawEvent& rUDEvt )
+IMPL_LINK(SvxStyleBox_Base, CustomRenderHdl, weld::ComboBox::render_args, aPayload, void)
 {
-    sal_uInt16 nItem = rUDEvt.GetItemId();
-    OUString aStyleName( GetEntry( nItem ) );
+    vcl::RenderContext& rRenderContext = std::get<0>(aPayload);
+    const ::tools::Rectangle& rRect = std::get<1>(aPayload);
+    bool bSelected = std::get<2>(aPayload);
+    const OUString& rId = std::get<3>(aPayload);
 
-    vcl::RenderContext *pDevice = rUDEvt.GetRenderContext();
-    pDevice->Push(PushFlags::FILLCOLOR | PushFlags::FONT | PushFlags::TEXTCOLOR);
+    sal_uInt32 nIndex = rId.toUInt32();
 
-    const tools::Rectangle& rRect(rUDEvt.GetRect());
-    bool bIsNotSelected = rUDEvt.GetItemId() != GetSelectedEntryPos();
+    OUString aStyleName(m_xWidget->get_text(nIndex));
 
-    SetupEntry(*pDevice, rUDEvt.GetWindow(), nItem, rRect, aStyleName, bIsNotSelected);
+    rRenderContext.Push(PushFlags::FILLCOLOR | PushFlags::FONT | PushFlags::TEXTCOLOR);
 
-    UserDrawEntry(rUDEvt, aStyleName);
+    SetupEntry(rRenderContext, nIndex, rRect, aStyleName, !bSelected);
 
-    pDevice->Pop();
-    // draw separator, if present
-    DrawEntry( rUDEvt, false, false );
+    UserDrawEntry(rRenderContext, rRect, aStyleName);
+
+    rRenderContext.Pop();
 }
 
-IMPL_LINK(SvxStyleBox_Impl, CalcOptimalExtraUserWidth, VclWindowEvent&, event, void)
+void SvxStyleBox_Base::CalcOptimalExtraUserWidth(vcl::RenderContext& rRenderContext)
 {
-    // perform the calculation only when we are opening the dropdown
-    if (event.GetId() != VclEventId::DropdownPreOpen)
+    if (m_nMaxUserDrawFontWidth)
         return;
 
     long nMaxNormalFontWidth = 0;
-    sal_Int32 nEntryCount = GetEntryCount();
+    sal_Int32 nEntryCount = m_xWidget->get_count();
     for (sal_Int32 i = 0; i < nEntryCount; ++i)
     {
-        OUString sStyleName(GetEntry(i));
+        OUString sStyleName(get_text(i));
         tools::Rectangle aTextRectForDefaultFont;
-        GetTextBoundRect(aTextRectForDefaultFont, sStyleName);
+        rRenderContext.GetTextBoundRect(aTextRectForDefaultFont, sStyleName);
 
         const long nWidth = aTextRectForDefaultFont.GetWidth();
 
         nMaxNormalFontWidth = std::max(nWidth, nMaxNormalFontWidth);
     }
 
-    long nMaxUserDrawFontWidth = nMaxNormalFontWidth;
+    m_nMaxUserDrawFontWidth = nMaxNormalFontWidth;
     for (sal_Int32 i = 1; i < nEntryCount-1; ++i)
     {
-        OUString sStyleName(GetEntry(i));
+        OUString sStyleName(get_text(i));
 
-        Push(PushFlags::FILLCOLOR | PushFlags::FONT | PushFlags::TEXTCOLOR);
-        SetupEntry(*this /*FIXME rendercontext*/, this, i, tools::Rectangle(0, 0, RECT_MAX, ITEM_HEIGHT), sStyleName, true);
+        rRenderContext.Push(PushFlags::FILLCOLOR | PushFlags::FONT | PushFlags::TEXTCOLOR);
+        SetupEntry(rRenderContext, i, tools::Rectangle(0, 0, RECT_MAX, ITEM_HEIGHT), sStyleName, true);
         tools::Rectangle aTextRectForActualFont;
-        GetTextBoundRect(aTextRectForActualFont, sStyleName);
-        if (AdjustFontForItemHeight(this, aTextRectForActualFont, ITEM_HEIGHT))
+        rRenderContext.GetTextBoundRect(aTextRectForActualFont, sStyleName);
+        if (AdjustFontForItemHeight(rRenderContext, aTextRectForActualFont, ITEM_HEIGHT))
         {
             //Font didn't fit, so it was changed, refetch with final font size
-            GetTextBoundRect(aTextRectForActualFont, sStyleName);
+            rRenderContext.GetTextBoundRect(aTextRectForActualFont, sStyleName);
         }
-        Pop();
+        rRenderContext.Pop();
 
-        const long nWidth = aTextRectForActualFont.GetWidth() + BUTTON_WIDTH + BUTTON_PADDING;
+        const int nWidth = aTextRectForActualFont.GetWidth() + m_xWidget->get_menu_button_width() + BUTTON_PADDING;
 
-        nMaxUserDrawFontWidth = std::max(nWidth, nMaxUserDrawFontWidth);
+        m_nMaxUserDrawFontWidth = std::max(nWidth, m_nMaxUserDrawFontWidth);
     }
-
-    SetUserItemSize(Size(nMaxUserDrawFontWidth, ITEM_HEIGHT));
 }
 
 // test is the color between Font- and background-color to be identify
@@ -1275,7 +1323,7 @@ IMPL_LINK(SvxStyleBox_Impl, CalcOptimalExtraUserWidth, VclWindowEvent&, event, v
 //        when both light or dark, change the Contrast
 //        in other case do not change the origin color
 //        when the color is R=G=B=128 the DecreaseContrast make 128 the need an exception
-Color SvxStyleBox_Impl::TestColorsVisible(const Color &FontCol, const Color &BackCol)
+Color SvxStyleBox_Base::TestColorsVisible(const Color &FontCol, const Color &BackCol)
 {
     const sal_uInt8  ChgVal = 60;       // increase/decrease the Contrast
 
@@ -1293,38 +1341,35 @@ Color SvxStyleBox_Impl::TestColorsVisible(const Color &FontCol, const Color &Bac
     return retCol;
 }
 
-boost::property_tree::ptree SvxStyleBox_Impl::DumpAsPropertyTree()
+IMPL_LINK(SvxStyleBox_Base, DumpAsPropertyTreeHdl, boost::property_tree::ptree&, rTree, void)
 {
-    boost::property_tree::ptree aTree(ComboBox::DumpAsPropertyTree());
-
     boost::property_tree::ptree aEntries;
 
-    for (int i = 0; i < GetEntryCount(); ++i)
+    for (int i = 0, nEntryCount = m_xWidget->get_count(); i < nEntryCount; ++i)
     {
         boost::property_tree::ptree aEntry;
-        aEntry.put("", GetEntry(i));
+        aEntry.put("", m_xWidget->get_text(i));
         aEntries.push_back(std::make_pair("", aEntry));
     }
 
-    aTree.add_child("entries", aEntries);
+    rTree.add_child("entries", aEntries);
 
     boost::property_tree::ptree aSelected;
 
-    for (int i = 0; i < GetSelectedEntryCount(); ++i)
+    int nActive = m_xWidget->get_active();
+
+    if (nActive != -1)
     {
         boost::property_tree::ptree aEntry;
-        aEntry.put("", GetSelectedEntryPos(i));
+        aEntry.put("", nActive);
         aSelected.push_back(std::make_pair("", aEntry));
     }
 
-    aTree.put("selectedCount", GetSelectedEntryCount());
-    aTree.add_child("selectedEntries", aSelected);
-    aTree.put("command", ".uno:StyleApply");
-
-    return aTree;
+    rTree.put("selectedCount", nActive == -1 ? 0 : 1);
+    rTree.add_child("selectedEntries", aSelected);
+    rTree.put("command", ".uno:StyleApply");
 }
 
-
 static bool lcl_GetDocFontList(const FontList** ppFontList, SvxFontNameBox_Base* pBox)
 {
     bool bChanged = false;
@@ -1400,7 +1445,7 @@ SvxFontNameBox_Base::SvxFontNameBox_Base(std::unique_ptr<weld::ComboBox> xWidget
                                          const Reference<XFrame>& rFrame,
                                          SvxFontNameToolBoxControl& rCtrl)
     : m_rCtrl(rCtrl)
-    , m_nCharWidth(xWidget->get_approximate_digit_width() * 16)
+    , m_nCharWidth(xWidget->get_approximate_digit_width() * COMBO_WIDTH_IN_CHARS)
     , m_xWidget(new FontNameBox(std::move(xWidget)))
     , pFontList(nullptr)
     , nFtCount(0)
@@ -1443,7 +1488,6 @@ void SvxFontNameBox_Base::FillList()
     // Did Doc-Fontlist change?
     lcl_GetDocFontList(&pFontList, this);
 
-    aCurText = m_xWidget->get_active_text();
     m_xWidget->select_entry_region(nStartPos, nEndPos);
 }
 
@@ -1524,7 +1568,7 @@ bool SvxFontNameBox_Base::DoKeyInput(const KeyEvent& rKEvt)
             break;
 
         case KEY_ESCAPE:
-            set_active_or_entry_text(aCurText);
+            set_active_or_entry_text(m_xWidget->get_saved_value());
             if (!m_rCtrl.IsInSidebar())
             {
                 ReleaseFocus_Impl();
@@ -2464,17 +2508,24 @@ struct SvxStyleToolBoxControl::Impl
     bool                     bSpecModeWriter;
     bool                     bSpecModeCalc;
 
+    VclPtr<SvxStyleBox_Impl> m_xVclBox;
+    std::unique_ptr<SvxStyleBox_Base> m_xWeldBox;
+    SvxStyleBox_Base* m_pBox;
+
     Impl()
         :aClearForm         ( SvxResId( RID_SVXSTR_CLEARFORM ) )
         ,aMore              ( SvxResId( RID_SVXSTR_MORE_STYLES ) )
         ,bSpecModeWriter    ( false )
         ,bSpecModeCalc      ( false )
+        ,m_pBox             ( nullptr )
     {
 
 
     }
     void InitializeStyles(const Reference < frame::XModel >& xModel)
     {
+        aDefaultStyles.clear();
+
         //now convert the default style names to the localized names
         try
         {
@@ -2564,14 +2615,12 @@ static const char* StyleSlotToStyleCommand[MAX_FAMILIES] =
     ".uno:TemplateFamily5"
 };
 
-SvxStyleToolBoxControl::SvxStyleToolBoxControl(
-    sal_uInt16 nSlotId, sal_uInt16 nId, ToolBox& rTbx )
-    :   SfxToolBoxControl   ( nSlotId, nId, rTbx ),
-        pImpl               ( new Impl ),
-        pStyleSheetPool     ( nullptr ),
-        nActFamily          ( 0xffff )
+SvxStyleToolBoxControl::SvxStyleToolBoxControl()
+    : pImpl(new Impl)
+    , pStyleSheetPool(nullptr)
+    , nActFamily(0xffff)
 {
-    for ( sal_uInt16 i=0; i<MAX_FAMILIES; i++ )
+    for (sal_uInt16 i = 0; i < MAX_FAMILIES; ++i)
     {
         pBoundItems[i] = nullptr;
         m_xBoundItems[i].clear();
@@ -2583,9 +2632,9 @@ SvxStyleToolBoxControl::~SvxStyleToolBoxControl()
 {
 }
 
-void SAL_CALL SvxStyleToolBoxControl::initialize( const Sequence< Any >& aArguments )
+void SAL_CALL SvxStyleToolBoxControl::initialize(const Sequence<Any>& rArguments)
 {
-    SfxToolBoxControl::initialize( aArguments );
+    svt::ToolboxController::initialize(rArguments);
 
     // After initialize we should have a valid frame member where we can retrieve our
     // dispatch provider.
@@ -2608,7 +2657,20 @@ void SAL_CALL SvxStyleToolBoxControl::initialize( const Sequence< Any >& aArgume
 // XComponent
 void SAL_CALL SvxStyleToolBoxControl::dispose()
 {
-    SfxToolBoxControl::dispose();
+    svt::ToolboxController::dispose();
+
+    SolarMutexGuard aSolarMutexGuard;
+    pImpl->m_xVclBox.disposeAndClear();
+    pImpl->m_xWeldBox.reset();
+    pImpl->m_pBox = nullptr;
+
+    for (SfxStyleControllerItem_Impl* pBoundItem : pBoundItems)
+    {
+        if (!pBoundItem)
+            continue;
+        pBoundItem->UnBind();
+    }
+    unbindListener();
 
     for( sal_uInt16 i=0; i<MAX_FAMILIES; i++ )
     {
@@ -2631,18 +2693,34 @@ void SAL_CALL SvxStyleToolBoxControl::dispose()
     pImpl.reset();
 }
 
-void SAL_CALL SvxStyleToolBoxControl::update()
+OUString SvxStyleToolBoxControl::getImplementationName()
 {
-    // Do nothing, we will start binding our listener when we are visible.
-    // See link SvxStyleToolBoxControl::VisibilityNotification.
-    SvxStyleBox_Impl* pBox = static_cast<SvxStyleBox_Impl*>(GetToolBox().GetItemWindow( GetId() ));
-    if ( pBox->IsVisible() )
-    {
-        for (SfxStyleControllerItem_Impl* pBoundItem : pBoundItems)
-            pBoundItem->ReBind();
+    return "com.sun.star.comp.svx.StyleToolBoxControl";
+}
 
-        bindListener();
-    }
+sal_Bool SvxStyleToolBoxControl::supportsService( const OUString& rServiceName )
+{
+    return cppu::supportsService( this, rServiceName );
+}
+
+css::uno::Sequence< OUString > SvxStyleToolBoxControl::getSupportedServiceNames()
+{
+    return { "com.sun.star.frame.ToolbarController" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_svx_StyleToolBoxControl_get_implementation(
+    css::uno::XComponentContext*,
+    css::uno::Sequence<css::uno::Any> const & )
+{
+    return cppu::acquire( new SvxStyleToolBoxControl() );
+}
+
+void SAL_CALL SvxStyleToolBoxControl::update()
+{
+    for (SfxStyleControllerItem_Impl* pBoundItem : pBoundItems)
+        pBoundItem->ReBind();
+    bindListener();
 }
 
 SfxStyleFamily SvxStyleToolBoxControl::GetActFamily() const
@@ -2663,7 +2741,7 @@ SfxStyleFamily SvxStyleToolBoxControl::GetActFamily() const
 
 void SvxStyleToolBoxControl::FillStyleBox()
 {
-    SvxStyleBox_Impl* pBox = static_cast<SvxStyleBox_Impl*>(GetToolBox().GetItemWindow( GetId() ));
+    SvxStyleBox_Base* pBox = pImpl->m_pBox;
 
     DBG_ASSERT( pStyleSheetPool, "StyleSheetPool not found!" );
     DBG_ASSERT( pBox,            "Control not found!" );
@@ -2681,7 +2759,7 @@ void SvxStyleToolBoxControl::FillStyleBox()
         pStyle = pStyleSheetPool->First();
         //!!! TODO: This condition isn't right any longer, because we always show some default entries
         //!!! so the list doesn't show the count
-        if ( nCount != pBox->GetEntryCount() )
+        if ( nCount != pBox->get_count() )
         {
             bDoFill = true;
         }
@@ -2690,7 +2768,7 @@ void SvxStyleToolBoxControl::FillStyleBox()
             sal_uInt16 i= 0;
             while ( pStyle && !bDoFill )
             {
-                bDoFill = ( pBox->GetEntry(i) != pStyle->GetName() );
+                bDoFill = ( pBox->get_text(i) != pStyle->GetName() );
                 pStyle = pStyleSheetPool->Next();
                 i++;
             }
@@ -2698,8 +2776,11 @@ void SvxStyleToolBoxControl::FillStyleBox()
 
         if ( bDoFill )
         {
-            pBox->SetUpdateMode( false );
-            pBox->Clear();
+            OUString aStrSel(pBox->get_active_text());
+            pBox->freeze();
+            pBox->clear();
+
+            std::vector<OUString> aStyles;
 
             {
                 pStyle = pStyleSheetPool->Next();
@@ -2721,7 +2802,7 @@ void SvxStyleToolBoxControl::FillStyleBox()
                         }
 
                         if( bInsert )
-                            pBox->InsertEntry( aName );
+                            aStyles.push_back(aName);
                         pStyle = pStyleSheetPool->Next();
                     }
                 }
@@ -2729,64 +2810,54 @@ void SvxStyleToolBoxControl::FillStyleBox()
                 {
                     while ( pStyle )
                     {
-                        pBox->InsertEntry( pStyle->GetName() );
+                        aStyles.push_back(pStyle->GetName());
                         pStyle = pStyleSheetPool->Next();
                     }
                 }
             }
 
-            if( pImpl->bSpecModeWriter || pImpl->bSpecModeCalc )
+            if (pImpl->bSpecModeWriter || pImpl->bSpecModeCalc)
             {
-                // disable sort to preserve special order
-                WinBits nWinBits = pBox->GetStyle();
-                nWinBits &= ~WB_SORT;
-                pBox->SetStyle( nWinBits );
+                pBox->append_text(pImpl->aClearForm);
+                pBox->insert_separator(1, "separator");
 
                 // insert default styles
-                sal_uInt16 nPos = 1;
-                for( auto const & _i: pImpl->aDefaultStyles )
-                {
-                    pBox->InsertEntry( _i, nPos );
-                    ++nPos;
-                }
+                for (const auto &rStyle : pImpl->aDefaultStyles)
+                    pBox->append_text(rStyle);
+            }
 
-                pBox->InsertEntry( pImpl->aClearForm, 0 );
-                pBox->SetSeparatorPos( 0 );
+            std::sort(aStyles.begin(), aStyles.end());
 
-                pBox->InsertEntry( pImpl->aMore );
+            for (const auto& rStyle : aStyles)
+                pBox->append_text(rStyle);
 
-                // enable sort again
-                nWinBits |= WB_SORT;
-                pBox->SetStyle( nWinBits );
-            }
+            if (pImpl->bSpecModeWriter || pImpl->bSpecModeCalc)
+                pBox->append_text(pImpl->aMore);
 
-            pBox->SetUpdateMode( true );
+            pBox->thaw();
+            pBox->set_active_or_entry_text(aStrSel);
             pBox->SetFamily( eFamily );
-
-            sal_uInt16 nLines = static_cast<sal_uInt16>(
-                    std::min( pBox->GetEntryCount(), static_cast<sal_Int32>(MAX_STYLES_ENTRIES)));
-            pBox->SetDropDownLineCount( nLines );
         }
     }
 }
 
 void SvxStyleToolBoxControl::SelectStyle( const OUString& rStyleName )
 {
-    SvxStyleBox_Impl* pBox = static_cast<SvxStyleBox_Impl*>(GetToolBox().GetItemWindow( GetId() ));
+    SvxStyleBox_Base* pBox = pImpl->m_pBox;
     DBG_ASSERT( pBox, "Control not found!" );
 
     if ( pBox )
     {
-        OUString aStrSel( pBox->GetText() );
+        OUString aStrSel(pBox->get_active_text());
 
         if ( !rStyleName.isEmpty() )
         {
             if ( rStyleName != aStrSel )
-                pBox->SetText( rStyleName );
+                pBox->set_active_or_entry_text( rStyleName );
         }
         else
-            pBox->SetNoSelection();
-        pBox->SaveValue();
+            pBox->set_active(-1);
+        pBox->save_value();
     }
 }
 
@@ -2841,81 +2912,71 @@ void SvxStyleToolBoxControl::SetFamilyState( sal_uInt16 nIdx,
     Update();
 }
 
-IMPL_LINK_NOARG(SvxStyleToolBoxControl, VisibilityNotification, SvxStyleBox_Impl&, void)
+void SvxStyleToolBoxControl::statusChanged( const css::frame::FeatureStateEvent& rEvent )
 {
-    // Call ReBind() && UnBind() according to visibility
-    SvxStyleBox_Impl* pBox = static_cast<SvxStyleBox_Impl*>( GetToolBox().GetItemWindow( GetId() ));
-
-    if ( pBox && pBox->IsVisible() && !isBound() )
-    {
-        for (SfxStyleControllerItem_Impl* pBoundItem : pBoundItems)
-            pBoundItem->ReBind();
+    SolarMutexGuard aGuard;
 
-        bindListener();
-    }
-    else if ( (!pBox || !pBox->IsVisible()) && isBound() )
+    if (m_pToolbar)
+        m_pToolbar->set_item_sensitive(m_aCommandURL.toUtf8(), rEvent.IsEnabled);
+    else
     {
-        for (SfxStyleControllerItem_Impl* pBoundItem : pBoundItems)
-            pBoundItem->UnBind();
-        unbindListener();
+        ToolBox* pToolBox = nullptr;
+        sal_uInt16 nId = 0;
+        if (!getToolboxId( nId, &pToolBox ) )
+            return;
+        pToolBox->EnableItem( nId, rEvent.IsEnabled );
     }
+
+    if (rEvent.IsEnabled)
+        Update();
 }
 
-void SvxStyleToolBoxControl::StateChanged(
-    sal_uInt16 , SfxItemState eState, const SfxPoolItem* pState )
+css::uno::Reference<css::awt::XWindow> SvxStyleToolBoxControl::createItemWindow(const css::uno::Reference< css::awt::XWindow>& rParent)
 {
-    sal_uInt16       nId    = GetId();
-    ToolBox&     rTbx   = GetToolBox();
-    SvxStyleBox_Impl* pBox   = static_cast<SvxStyleBox_Impl*>(rTbx.GetItemWindow( nId ));
-    TriState     eTri   = TRISTATE_FALSE;
+    uno::Reference< awt::XWindow > xItemWindow;
 
-    DBG_ASSERT( pBox, "Control not found!" );
+    if (m_pBuilder)
+    {
+        SolarMutexGuard aSolarMutexGuard;
 
-    if ( SfxItemState::DISABLED == eState )
-        pBox->Disable();
-    else
-        pBox->Enable();
+        std::unique_ptr<weld::ComboBox> xWidget(m_pBuilder->weld_combo_box("applystyle"));
 
-    rTbx.EnableItem( nId, SfxItemState::DISABLED != eState );
+        xItemWindow = css::uno::Reference<css::awt::XWindow>(new weld::TransportAsXWindow(xWidget.get()));
 
-    switch ( eState )
+        pImpl->m_xWeldBox.reset(new SvxStyleBox_Base(std::move(xWidget),
+                                                     ".uno:StyleApply",
+                                                     SfxStyleFamily::Para,
+                                                     Reference< XDispatchProvider >( m_xFrame->getController(), UNO_QUERY ),
+                                                     m_xFrame,
+                                                     pImpl->aClearForm,
+                                                     pImpl->aMore,
+                                                     pImpl->bSpecModeWriter || pImpl->bSpecModeCalc, *this));
+        pImpl->m_pBox = pImpl->m_xWeldBox.get();
+    }
+    else
     {
-        case SfxItemState::DEFAULT:
-            eTri = static_cast<const SfxTemplateItem*>(pState)->GetValue() != SfxStyleSearchBits::Auto
-                        ? TRISTATE_TRUE
-                        : TRISTATE_FALSE;
-            break;
-
-        case SfxItemState::DONTCARE:
-            eTri = TRISTATE_INDET;
-            break;
+        VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow(rParent);
+        if ( pParent )
+        {
+            SolarMutexGuard aSolarMutexGuard;
 
-        default:
-            break;
+            pImpl->m_xVclBox = VclPtr<SvxStyleBox_Impl>::Create(pParent,
+                                                                ".uno:StyleApply",
+                                                                SfxStyleFamily::Para,
+                                                                Reference< XDispatchProvider >( m_xFrame->getController(), UNO_QUERY ),
+                                                                m_xFrame,
+                                                                pImpl->aClearForm,
+                                                                pImpl->aMore,
+                                                                pImpl->bSpecModeWriter || pImpl->bSpecModeCalc, *this);
+            pImpl->m_pBox = pImpl->m_xVclBox.get();
+            xItemWindow = VCLUnoHelper::GetInterface(pImpl->m_xVclBox);
+        }
     }
 
-    rTbx.SetItemState( nId, eTri );
-
-    if ( SfxItemState::DISABLED != eState )
-        Update();
-}
-
-VclPtr<vcl::Window> SvxStyleToolBoxControl::CreateItemWindow( vcl::Window *pParent )
-{
-    VclPtrInstance<SvxStyleBox_Impl> pBox( pParent,
-                                           OUString( ".uno:StyleApply" ),
-                                           SfxStyleFamily::Para,
-                                           Reference< XDispatchProvider >( m_xFrame->getController(), UNO_QUERY ),
-                                           m_xFrame,
-                                           pImpl->aClearForm,
-                                           pImpl->aMore,
-                                           pImpl->bSpecModeWriter || pImpl->bSpecModeCalc );
-    if( !pImpl->aDefaultStyles.empty())
-        pBox->SetDefaultStyle( pImpl->aDefaultStyles[0] );
-    // Set visibility listener to bind/unbind controller
-    pBox->SetVisibilityListener( LINK( this, SvxStyleToolBoxControl, VisibilityNotification ));
+    if (pImpl->m_pBox && !pImpl->aDefaultStyles.empty())
+        pImpl->m_pBox->SetDefaultStyle(pImpl->aDefaultStyles[0]);
 
-    return pBox.get();
+    return xItemWindow;
 }
 
 SvxFontNameToolBoxControl::SvxFontNameToolBoxControl()
@@ -2960,7 +3021,7 @@ void SvxFontNameToolBoxControl::statusChanged( const css::frame::FeatureStateEve
     }
 }
 
-css::uno::Reference< css::awt::XWindow > SvxFontNameToolBoxControl::createItemWindow( const css::uno::Reference< css::awt::XWindow >& rParent )
+css::uno::Reference<css::awt::XWindow> SvxFontNameToolBoxControl::createItemWindow(const css::uno::Reference<css::awt::XWindow>& rParent)
 {
     uno::Reference< awt::XWindow > xItemWindow;
 
diff --git a/svx/uiconfig/ui/applystylebox.ui b/svx/uiconfig/ui/applystylebox.ui
new file mode 100644
index 000000000000..3dcd64bb1e16
--- /dev/null
+++ b/svx/uiconfig/ui/applystylebox.ui
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.2 -->
+<interface domain="svx">
+  <requires lib="gtk+" version="3.18"/>
+  <object class="GtkBox" id="ApplyStyleBox">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="hexpand">True</property>
+    <property name="spacing">6</property>
+    <child>
+      <object class="GtkComboBoxText" id="applystyle">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="hexpand">True</property>
+        <property name="has_entry">True</property>
+        <property name="popup_fixed_width">False</property>
+        <child internal-child="entry">
+          <object class="GtkEntry">
+            <property name="can_focus">True</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/svx/uiconfig/ui/sidebarlists.ui b/svx/uiconfig/ui/sidebarlists.ui
index 2f2806459acd..3937f21c4b30 100644
--- a/svx/uiconfig/ui/sidebarlists.ui
+++ b/svx/uiconfig/ui/sidebarlists.ui
@@ -26,7 +26,6 @@
               <object class="GtkMenuToolButton" id=".uno:DefaultBullet">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="is_important">True</property>
                 <property name="use_underline">True</property>
               </object>
               <packing>
@@ -38,7 +37,6 @@
               <object class="GtkMenuToolButton" id=".uno:DefaultNumbering">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="is_important">True</property>
                 <property name="use_underline">True</property>
               </object>
               <packing>
diff --git a/svx/uiconfig/ui/sidebarparagraph.ui b/svx/uiconfig/ui/sidebarparagraph.ui
index ce0b0dda1379..49d18aef5dc6 100644
--- a/svx/uiconfig/ui/sidebarparagraph.ui
+++ b/svx/uiconfig/ui/sidebarparagraph.ui
@@ -627,7 +627,6 @@
                   <object class="GtkMenuToolButton" id=".uno:DefaultBullet">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="is_important">True</property>
                     <property name="use_underline">True</property>
                   </object>
                   <packing>
@@ -639,7 +638,6 @@
                   <object class="GtkMenuToolButton" id=".uno:DefaultNumbering">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="is_important">True</property>
                     <property name="use_underline">True</property>
                   </object>
                   <packing>
diff --git a/svx/uiconfig/ui/sidebarstylespanel.ui b/svx/uiconfig/ui/sidebarstylespanel.ui
index a4955472f50d..7e87f0ae4091 100644
--- a/svx/uiconfig/ui/sidebarstylespanel.ui
+++ b/svx/uiconfig/ui/sidebarstylespanel.ui
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.18.3 -->
+<!-- Generated with glade 3.22.2 -->
 <interface domain="svx">
   <requires lib="gtk+" version="3.18"/>
   <object class="GtkGrid" id="SidebarStylesPanel">
@@ -21,19 +21,35 @@
             <property name="hexpand">True</property>
             <property name="orientation">vertical</property>
             <child>
-              <object class="sfxlo-SidebarToolBox" id="fontstyletoolbox">
+              <object class="GtkToolbar" id="fontstyletoolbox">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
+                <property name="hexpand">True</property>
+                <property name="toolbar_style">icons</property>
+                <property name="show_arrow">False</property>
                 <child>
-                  <object class="GtkToolButton" id="fontstyle">
+                  <object class="GtkToolItem" id=".uno:StyleApply">
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="is_important">True</property>
-                    <property name="action_name">.uno:StyleApply</property>
+                    <property name="can_focus">False</property>
+                    <property name="hexpand">True</property>
+                    <child>
+                      <object class="GtkComboBoxText" id="applystyle">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="has_entry">True</property>
+                        <property name="popup_fixed_width">False</property>
+                        <child internal-child="entry">
+                          <object class="GtkEntry">
+                            <property name="can_focus">True</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
                   </object>
                   <packing>
                     <property name="expand">True</property>
-                    <property name="homogeneous">True</property>
+                    <property name="homogeneous">False</property>
                   </packing>
                 </child>
               </object>
@@ -55,38 +71,25 @@
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <child>
-              <object class="sfxlo-SidebarToolBox" id="styleupdate">
+              <object class="GtkToolbar" id="style">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
+                <property name="toolbar_style">icons</property>
+                <property name="show_arrow">False</property>
                 <child>
-                  <object class="GtkToolButton" id="styleupdateexample">
+                  <object class="GtkToolButton" id=".uno:StyleUpdateByExample">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
-                    <property name="is_important">True</property>
-                    <property name="action_name">.uno:StyleUpdateByExample</property>
                   </object>
                   <packing>
                     <property name="expand">True</property>
                     <property name="homogeneous">True</property>
                   </packing>
                 </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="sfxlo-SidebarToolBox" id="stylenew">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
                 <child>
-                  <object class="GtkToolButton" id="stylenewexample">
+                  <object class="GtkToolButton" id=".uno:StyleNewByExample">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
-                    <property name="is_important">True</property>
-                    <property name="action_name">.uno:StyleNewByExample</property>
                   </object>
                   <packing>
                     <property name="expand">True</property>
@@ -97,7 +100,7 @@
               <packing>
                 <property name="expand">False</property>
                 <property name="fill">True</property>
-                <property name="position">1</property>
+                <property name="position">0</property>
               </packing>
             </child>
           </object>
diff --git a/svx/util/svxcore.component b/svx/util/svxcore.component
index 2c5a103857c4..f5a81131fac9 100644
--- a/svx/util/svxcore.component
+++ b/svx/util/svxcore.component
@@ -62,6 +62,10 @@
     constructor="com_sun_star_comp_svx_FontNameToolBoxControl_get_implementation">
     <service name="com.sun.star.frame.ToolbarController"/>
   </implementation>
+  <implementation name="com.sun.star.comp.svx.StyleToolBoxControl"
+    constructor="com_sun_star_comp_svx_StyleToolBoxControl_get_implementation">
+    <service name="com.sun.star.frame.ToolbarController"/>
+  </implementation>
   <implementation name="com.sun.star.comp.svx.LineEndToolBoxControl"
       constructor="com_sun_star_comp_svx_LineEndToolBoxControl_get_implementation">
     <service name="com.sun.star.frame.ToolbarController"/>
diff --git a/sw/source/uibase/app/swmodule.cxx b/sw/source/uibase/app/swmodule.cxx
index d68c2eff51d4..59b5d1ee6b38 100644
--- a/sw/source/uibase/app/swmodule.cxx
+++ b/sw/source/uibase/app/swmodule.cxx
@@ -286,8 +286,6 @@ void SwDLL::RegisterControls()
     SvxFillToolBoxControl::RegisterControl(SID_ATTR_FILL_STYLE, pMod );
     SvxLineWidthToolBoxControl::RegisterControl(SID_ATTR_LINE_WIDTH, pMod );
 
-    SvxStyleToolBoxControl::RegisterControl(SID_STYLE_APPLY, pMod );
-
     SwZoomControl::RegisterControl(SID_ATTR_ZOOM, pMod );
     SwPreviewZoomControl::RegisterControl(FN_PREVIEW_ZOOM, pMod);
     SvxPosSizeStatusBarControl::RegisterControl(0, pMod );
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index 35c604955179..5313ae39d01f 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -5691,6 +5691,8 @@ protected:
     // owner for ListBox/ComboBox UserData
     std::vector<std::unique_ptr<OUString>> m_aUserData;
     VclPtr<vcl_type> m_xComboBox;
+    ScopedVclPtr<MenuButton> m_xMenuButton;
+    OUString m_sMenuButtonRow;
 
 public:
     SalInstanceComboBox(vcl_type* pComboBox, SalInstanceBuilder* pBuilder, bool bTakeOwnership)
@@ -5714,7 +5716,10 @@ public:
 
     // ComboBoxes are comprised of multiple subwidgets, consider the lot as
     // one thing for focus
-    virtual bool has_focus() const override { return m_xWidget->HasChildPathFocus(); }
+    virtual bool has_focus() const override
+    {
+        return m_xWidget->HasChildPathFocus() || (m_xMenuButton && (m_xMenuButton->HasFocus() || m_xMenuButton->InPopupMode()));
+    }
 
     virtual OUString get_active_id() const override
     {
@@ -5827,8 +5832,19 @@ public:
     {
         vcl::RenderContext* pRenderContext = pEvent->GetRenderContext();
         auto nPos = pEvent->GetItemId();
-        signal_custom_render(*pRenderContext, pEvent->GetRect(), pEvent->IsSelected(), get_id(nPos));
+        const tools::Rectangle& rRect = pEvent->GetRect();
+        const OUString sId = get_id(nPos);
+        signal_custom_render(*pRenderContext, rRect, pEvent->IsSelected(), sId);
         m_xComboBox->DrawEntry(*pEvent, false, false);  // draw separator
+
+        if (m_xMenuButton && m_xMenuButton->IsVisible() && m_sMenuButtonRow == sId)
+        {
+            if (m_xMenuButton->GetParent() != pEvent->GetWindow())
+                m_xMenuButton->SetParent(pEvent->GetWindow());
+            int nButtonWidth = get_menu_button_width();
+            m_xMenuButton->SetSizePixel(Size(nButtonWidth, rRect.GetHeight()));
+            m_xMenuButton->SetPosPixel(Point(rRect.GetWidth() - nButtonWidth, rRect.getY()));
+        }
     }
 
     VclPtr<VirtualDevice> create_render_virtual_device() const override
@@ -5836,10 +5852,30 @@ public:
         return VclPtr<VirtualDevice>::Create();
     }
 
-    virtual void HandleEventListener(VclWindowEvent& rEvent) override
+    virtual void set_item_menu(const OString& rIdent, weld::Menu* pMenu) override
     {
-        if (rEvent.GetId() == VclEventId::DropdownPreOpen
-            || rEvent.GetId() == VclEventId::DropdownClose)
+        SalInstanceMenu* pInstanceMenu = dynamic_cast<SalInstanceMenu*>(pMenu);
+
+        PopupMenu* pPopup = pInstanceMenu ? pInstanceMenu->getMenu() : nullptr;
+
+        if (!m_xMenuButton)
+            m_xMenuButton = VclPtr<MenuButton>::Create(m_xComboBox, WB_FLATBUTTON | WB_NOPOINTERFOCUS);
+
+        m_xMenuButton->SetPopupMenu(pPopup);
+        m_xMenuButton->Show(pPopup != nullptr);
+        m_sMenuButtonRow = OUString::fromUtf8(rIdent);
+    }
+
+    int get_menu_button_width() const override
+    {
+        const int nButtonWidth = 20;
+        return nButtonWidth;
+    }
+
+    void CallHandleEventListener(VclWindowEvent& rEvent)
+    {
+        if (rEvent.GetId() == VclEventId::DropdownPreOpen ||
+            rEvent.GetId() == VclEventId::DropdownClose)
         {
             signal_popup_toggled();
             return;
@@ -5947,6 +5983,11 @@ public:
         assert(false && "not implemented");
     }
 
+    virtual void HandleEventListener(VclWindowEvent& rEvent) override
+    {
+        CallHandleEventListener(rEvent);
+    }
+
     virtual ~SalInstanceComboBoxWithoutEdit() override
     {
         m_xComboBox->SetSelectHdl(Link<ListBox&, void>());
@@ -6083,9 +6124,7 @@ public:
         auto nOldEntryHeight = m_xComboBox->GetDropDownEntryHeight();
         auto nDropDownLineCount = m_xComboBox->GetDropDownLineCount();
 
-        Size aRowSize(signal_custom_get_size(*m_xComboBox, OUString()));
         m_xComboBox->EnableUserDraw(true);
-        m_xComboBox->SetUserItemSize(aRowSize);
         m_xComboBox->SetUserDrawHdl(LINK(this, SalInstanceComboBoxWithEdit, UserDrawHdl));
 
         // adjust the line count to fit approx the height it would have been before
@@ -6115,6 +6154,16 @@ public:
         m_xComboBox->SetMRUEntries(rEntries);
     }
 
+    virtual void HandleEventListener(VclWindowEvent& rEvent) override
+    {
+        if (rEvent.GetId() == VclEventId::DropdownPreOpen)
+        {
+            Size aRowSize(signal_custom_get_size(*m_xComboBox));
+            m_xComboBox->SetUserItemSize(aRowSize);
+        }
+        CallHandleEventListener(rEvent);
+    }
+
     virtual ~SalInstanceComboBoxWithEdit() override
     {
         m_xComboBox->SetTextFilter(nullptr);
@@ -6251,6 +6300,17 @@ public:
         assert(false && "not implemented");
     }
 
+    virtual void set_item_menu(const OString&, weld::Menu*) override
+    {
+        assert(false && "not implemented");
+    }
+
+    int get_menu_button_width() const override
+    {
+        assert(false && "not implemented");
+        return 0;
+    }
+
     VclPtr<VirtualDevice> create_render_virtual_device() const override
     {
         return VclPtr<VirtualDevice>::Create();
diff --git a/vcl/uiconfig/ui/combobox.ui b/vcl/uiconfig/ui/combobox.ui
index e5d31743fcf1..24b07878f69b 100644
--- a/vcl/uiconfig/ui/combobox.ui
+++ b/vcl/uiconfig/ui/combobox.ui
@@ -64,6 +64,20 @@
       <class name="linked"/>
     </style>
   </object>
+  <object class="GtkMenuButton" id="overlaybutton">
+    <property name="can_focus">True</property>
+    <property name="receives_default">True</property>
+    <property name="no_show_all">True</property>
+    <property name="draw_indicator">True</property>
+    <property name="use_popover">False</property>
+    <child>
+      <object class="GtkImage" id="overlayarrow">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="icon_name">pan-down-symbolic</property>
+      </object>
+    </child>
+  </object>
   <object class="GtkWindow" id="popup">
     <property name="name">gtk-combobox-popup-window</property>
     <property name="can_focus">False</property>
@@ -75,26 +89,34 @@
       <placeholder/>
     </child>
     <child>
-      <object class="GtkScrolledWindow" id="scrolledwindow">
+      <object class="GtkOverlay" id="overlay">
         <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="hscrollbar_policy">never</property>
-        <property name="shadow_type">in</property>
-        <property name="overlay_scrolling">False</property>
+        <property name="can_focus">False</property>
         <child>
-          <object class="GtkTreeView" id="treeview">
+          <object class="GtkScrolledWindow" id="scrolledwindow">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
-            <property name="headers_visible">False</property>
-            <property name="headers_clickable">False</property>
-            <property name="enable_search">False</property>
-            <property name="search_column">0</property>
-            <property name="show_expanders">False</property>
-            <property name="activate_on_single_click">True</property>
-            <child internal-child="selection">
-              <object class="GtkTreeSelection"/>
+            <property name="hscrollbar_policy">never</property>
+            <property name="shadow_type">in</property>
+            <property name="overlay_scrolling">False</property>
+            <child>
+              <object class="GtkTreeView" id="treeview">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="headers_visible">False</property>
+                <property name="enable_search">False</property>
+                <property name="search_column">0</property>
+                <property name="show_expanders">False</property>
+                <property name="activate_on_single_click">True</property>
+                <child internal-child="selection">
+                  <object class="GtkTreeSelection"/>
+                </child>
+              </object>
             </child>
           </object>
+          <packing>
+            <property name="index">-1</property>
+          </packing>
         </child>
       </object>
     </child>
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 4a0f975b2fd1..04a6f68837ea 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -8899,6 +8899,21 @@ int get_height_rows(int nRowHeight, int nSeparatorHeight, int nRows)
     return (nRowHeight * nRows) + (nSeparatorHeight * (nRows + 1));
 }
 
+tools::Rectangle get_row_area(GtkTreeView* pTreeView, GList* pColumns, GtkTreePath* pPath)
+{
+    tools::Rectangle aRet;
+
+    GdkRectangle aRect;
+    for (GList* pEntry = g_list_last(pColumns); pEntry; pEntry = g_list_previous(pEntry))
+    {
+        GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(pEntry->data);
+        gtk_tree_view_get_cell_area(pTreeView, pPath, pColumn, &aRect);
+        aRet.Union(tools::Rectangle(aRect.x, aRect.y, aRect.x + aRect.width, aRect.y + aRect.height));
+    }
+
+    return aRet;
+}
+
 class GtkInstanceTreeView : public GtkInstanceContainer, public virtual weld::TreeView
 {
 private:
@@ -11042,22 +11057,11 @@ public:
 
     virtual tools::Rectangle get_row_area(const weld::TreeIter& rIter) const override
     {
-        tools::Rectangle aRet;
-
         const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter);
         GtkTreeModel* pModel = GTK_TREE_MODEL(m_pTreeStore);
         GtkTreePath* pPath = gtk_tree_model_get_path(pModel, const_cast<GtkTreeIter*>(&rGtkIter.iter));
-
-        GdkRectangle aRect;
-        for (GList* pEntry = g_list_last(m_pColumns); pEntry; pEntry = g_list_previous(pEntry))
-        {
-            GtkTreeViewColumn* pColumn = GTK_TREE_VIEW_COLUMN(pEntry->data);
-            gtk_tree_view_get_cell_area(m_pTreeView, pPath, pColumn, &aRect);
-            aRet.Union(tools::Rectangle(aRect.x, aRect.y, aRect.x + aRect.width, aRect.y + aRect.height));
-        }
-
+        tools::Rectangle aRet = ::get_row_area(m_pTreeView, m_pColumns, pPath);
         gtk_tree_path_free(pPath);
-
         return aRet;
     }
 
@@ -12529,12 +12533,32 @@ struct GtkTreeRowReferenceDeleter
     }
 };
 
+// pop down the toplevel combobox menu when something is activated from a custom
+// submenu, i.e. wysiwyg style menu
+class CustomRenderMenuButtonHelper : public MenuHelper
+{
+private:
+    GtkToggleButton* m_pComboBox;
+public:
+    CustomRenderMenuButtonHelper(GtkMenu* pMenu, GtkToggleButton* pComboBox)
+        : MenuHelper(pMenu, false)
+        , m_pComboBox(pComboBox)
+    {
+    }
+    virtual void signal_activate(GtkMenuItem*) override
+    {
+        gtk_toggle_button_set_active(m_pComboBox, false);
+    }
+};
+
 class GtkInstanceComboBox : public GtkInstanceContainer, public vcl::ISearchableStringList, public virtual weld::ComboBox
 {
 private:
     GtkBuilder* m_pComboBuilder;
     GtkComboBox* m_pComboBox;
+    GtkOverlay* m_pOverlay;
     GtkTreeView* m_pTreeView;
+    GtkMenuButton* m_pOverlayButton; // button that the StyleDropdown uses on an active row
     GtkWindow* m_pMenuWindow;
     GtkTreeModel* m_pTreeModel;
     GtkCellRenderer* m_pButtonTextRenderer;
@@ -12542,11 +12566,14 @@ private:
     GtkWidget* m_pToggleButton;
     GtkWidget* m_pEntry;
     GtkCellView* m_pCellView;
+    std::unique_ptr<CustomRenderMenuButtonHelper> m_xCustomMenuButtonHelper;
     std::unique_ptr<vcl::Font> m_xFont;
     std::unique_ptr<comphelper::string::NaturalStringSorter> m_xSorter;
     vcl::QuickSelectionEngine m_aQuickSelectionEngine;
     std::vector<std::unique_ptr<GtkTreeRowReference, GtkTreeRowReferenceDeleter>> m_aSeparatorRows;
+    OUString m_sMenuButtonRow;
     bool m_bHoverSelection;
+    bool m_bMouseInOverlayButton;
     bool m_bPopupActive;
     bool m_bAutoComplete;
     bool m_bAutoCompleteCaseSensitive;
@@ -13296,7 +13323,7 @@ private:
     void signal_motion()
     {
         // if hover-selection was disabled after pressing a key, then turn it back on again
-        if (!m_bHoverSelection)
+        if (!m_bHoverSelection && !m_bMouseInOverlayButton)
         {
             gtk_tree_view_set_hover_selection(m_pTreeView, true);
             m_bHoverSelection = true;
@@ -13366,8 +13393,6 @@ private:
                     break;
                 }
             }
-
-//TODO            set_active(0);
         }
 
         while (m_nMRUCount > m_nMaxMRUCount)
@@ -13489,12 +13514,70 @@ private:
         enable_notify_events();
     }
 
+    static gboolean signalGetChildPosition(GtkOverlay*, GtkWidget*, GdkRectangle* pAllocation, gpointer widget)
+    {
+        GtkInstanceComboBox* pThis = static_cast<GtkInstanceComboBox*>(widget);
+        return pThis->signal_get_child_position(pAllocation);
+    }
+
+    bool signal_get_child_position(GdkRectangle* pAllocation)
+    {
+        if (!gtk_widget_get_visible(GTK_WIDGET(m_pOverlayButton)))
+            return false;
+        if (!gtk_widget_get_realized(GTK_WIDGET(m_pTreeView)))
+            return false;
+        int nRow = find_id_including_mru(m_sMenuButtonRow, true);
+        if (nRow == -1)
+            return false;
+
+        gtk_widget_get_preferred_width(GTK_WIDGET(m_pOverlayButton), &pAllocation->width, nullptr);
+
+        GtkTreePath* pPath = gtk_tree_path_new_from_indices(nRow, -1);
+        GList* pColumns = gtk_tree_view_get_columns(m_pTreeView);
+        tools::Rectangle aRect = get_row_area(m_pTreeView, pColumns, pPath);
+        gtk_tree_path_free(pPath);
+        g_list_free(pColumns);
+
+        pAllocation->x = aRect.Right() - pAllocation->width;
+        pAllocation->y = aRect.Top();
+        pAllocation->height = aRect.GetHeight();
+
+        return true;
+    }
+
+    static gboolean signalOverlayButtonCrossing(GtkWidget*, GdkEventCrossing* pEvent, gpointer widget)
+    {
+        GtkInstanceComboBox* pThis = static_cast<GtkInstanceComboBox*>(widget);
+        pThis->signal_overlay_button_crossing(pEvent->type == GDK_ENTER_NOTIFY);
+        return false;
+    }
+
+    void signal_overlay_button_crossing(bool bEnter)
+    {
+        m_bMouseInOverlayButton = bEnter;
+        if (bEnter)
+        {
+            if (m_bHoverSelection)
+            {
+                // once toggled button is pressed, turn off hover selection until
+                // mouse leaves the overlay button
+                gtk_tree_view_set_hover_selection(m_pTreeView, false);
+                m_bHoverSelection = false;
+            }
+            int nRow = find_id_including_mru(m_sMenuButtonRow, true);
+            assert(nRow != -1);
+            tree_view_set_cursor(nRow); // select the buttons row
+        }
+    }
+
 public:
     GtkInstanceComboBox(GtkBuilder* pComboBuilder, GtkComboBox* pComboBox, GtkInstanceBuilder* pBuilder, bool bTakeOwnership)
         : GtkInstanceContainer(GTK_CONTAINER(gtk_builder_get_object(pComboBuilder, "box")), pBuilder, bTakeOwnership)
         , m_pComboBuilder(pComboBuilder)
         , m_pComboBox(pComboBox)
+        , m_pOverlay(GTK_OVERLAY(gtk_builder_get_object(pComboBuilder, "overlay")))
         , m_pTreeView(GTK_TREE_VIEW(gtk_builder_get_object(pComboBuilder, "treeview")))
+        , m_pOverlayButton(GTK_MENU_BUTTON(gtk_builder_get_object(pComboBuilder, "overlaybutton")))
         , m_pMenuWindow(GTK_WINDOW(gtk_builder_get_object(pComboBuilder, "popup")))
         , m_pTreeModel(gtk_combo_box_get_model(pComboBox))
         , m_pButtonTextRenderer(nullptr)
@@ -13503,6 +13586,7 @@ public:
         , m_pCellView(nullptr)
         , m_aQuickSelectionEngine(*this)
         , m_bHoverSelection(false)
+        , m_bMouseInOverlayButton(false)
         , m_bPopupActive(false)
         , m_bAutoComplete(false)
         , m_bAutoCompleteCaseSensitive(false)
@@ -13615,6 +13699,11 @@ public:
         // support typeahead for the menu itself, typing into the menu will
         // select via the vcl selection engine, a matching entry.
         g_signal_connect(m_pMenuWindow, "key-press-event", G_CALLBACK(signalKeyPress), this);
+
+        g_signal_connect(m_pOverlay, "get-child-position", G_CALLBACK(signalGetChildPosition), this);
+        gtk_overlay_add_overlay(m_pOverlay, GTK_WIDGET(m_pOverlayButton));
+        g_signal_connect(m_pOverlayButton, "leave-notify-event", G_CALLBACK(signalOverlayButtonCrossing), this);
+        g_signal_connect(m_pOverlayButton, "enter-notify-event", G_CALLBACK(signalOverlayButtonCrossing), this);
     }
 
     virtual int get_active() const override
@@ -13986,7 +14075,9 @@ public:
 
     virtual bool has_focus() const override
     {
-        return gtk_widget_has_focus(m_pToggleButton) || gtk_widget_has_focus(m_pEntry) || GtkInstanceWidget::has_focus();
+        return gtk_widget_has_focus(m_pToggleButton) || gtk_widget_has_focus(m_pEntry) ||
+               gtk_widget_has_focus(GTK_WIDGET(m_pOverlayButton)) ||
+               gtk_widget_has_focus(GTK_WIDGET(m_pTreeView)) || GtkInstanceWidget::has_focus();
     }
 
     virtual bool changed_by_direct_pick() const override
@@ -14017,9 +14108,9 @@ public:
         signal_custom_render(rOutput, rRect, bSelected, rId);
     }
 
-    Size call_signal_custom_get_size(VirtualDevice& rOutput, const OUString& rId)
+    Size call_signal_custom_get_size(VirtualDevice& rOutput)
     {
-        return signal_custom_get_size(rOutput, rId);
+        return signal_custom_get_size(rOutput);
     }
 
     VclPtr<VirtualDevice> create_render_virtual_device() const override
@@ -14027,6 +14118,19 @@ public:
         return create_virtual_device();
     }
 
+    virtual void set_item_menu(const OString& rIdent, weld::Menu* pMenu) override
+    {
+        m_xCustomMenuButtonHelper.reset();
+        GtkInstanceMenu* pPopoverWidget = dynamic_cast<GtkInstanceMenu*>(pMenu);
+        GtkWidget* pMenuWidget = GTK_WIDGET(pPopoverWidget ? pPopoverWidget->getMenu() : nullptr);
+        gtk_menu_button_set_popup(m_pOverlayButton, pMenuWidget);
+        gtk_widget_set_visible(GTK_WIDGET(m_pOverlayButton), pMenuWidget != nullptr);
+        gtk_widget_queue_resize_no_redraw(GTK_WIDGET(m_pOverlayButton)); // force location recalc
+        if (pMenuWidget)
+            m_xCustomMenuButtonHelper.reset(new CustomRenderMenuButtonHelper(GTK_MENU(pMenuWidget), GTK_TOGGLE_BUTTON(m_pToggleButton)));
+        m_sMenuButtonRow = OUString::fromUtf8(rIdent);
+    }
+
     OUString get_mru_entries() const override
     {
         const sal_Unicode cSep = ';';
@@ -14073,8 +14177,21 @@ public:
         m_nMRUCount = nMRUCount;
     }
 
+    int get_menu_button_width() const override
+    {
+        bool bVisible = gtk_widget_get_visible(GTK_WIDGET(m_pOverlayButton));
+        if (!bVisible)
+            gtk_widget_set_visible(GTK_WIDGET(m_pOverlayButton), true);
+        gint nWidth;
+        gtk_widget_get_preferred_width(GTK_WIDGET(m_pOverlayButton), &nWidth, nullptr);
+        if (!bVisible)
+            gtk_widget_set_visible(GTK_WIDGET(m_pOverlayButton), false);
+        return nWidth;
+    }
+
     virtual ~GtkInstanceComboBox() override
     {
+        m_xCustomMenuButtonHelper.reset();
         do_clear();
         if (m_nAutoCompleteIdleId)
             g_source_remove(m_nAutoCompleteIdleId);
@@ -14129,7 +14246,7 @@ bool custom_cell_renderer_surface_get_preferred_size(GtkCellRenderer *cell,
     if (GtkInstanceTreeView* pTreeView = dynamic_cast<GtkInstanceTreeView*>(pWidget))
         aSize = pTreeView->call_signal_custom_get_size(*cellsurface->device, sId);
     else if (GtkInstanceComboBox* pComboBox = dynamic_cast<GtkInstanceComboBox*>(pWidget))
-        aSize = pComboBox->call_signal_custom_get_size(*cellsurface->device, sId);
+        aSize = pComboBox->call_signal_custom_get_size(*cellsurface->device);
 
     if (orientation == GTK_ORIENTATION_HORIZONTAL)
     {
@@ -14446,11 +14563,22 @@ public:
         assert(false && "not implemented");
     }
 
+    virtual void set_item_menu(const OString&, weld::Menu*) override
+    {
+        assert(false && "not implemented");
+    }
+
     VclPtr<VirtualDevice> create_render_virtual_device() const override
     {
         return create_virtual_device();
     }
 
+    int get_menu_button_width() const override
+    {
+        assert(false && "not implemented");
+        return 0;
+    }
+
     virtual ~GtkInstanceEntryTreeView() override
     {
         if (m_nAutoCompleteIdleId)


More information about the Libreoffice-commits mailing list