diff options
23 files changed, 806 insertions, 467 deletions
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) |