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@redhat.com>
diff --git a/include/svtools/ctrlbox.hxx b/include/svtools/ctrlbox.hxx
index 4ecff16..8cdb5ef 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 0c7da00..387c67f 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;
// XStatusListener
virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) override;
virtual void StateChanged(sal_uInt16 nSID, SfxItemState eState,
const SfxPoolItem* pState) override;
// XToolbarController
virtual css::uno::Reference<css::awt::XWindow> SAL_CALL createItemWindow(const css::uno::Reference<css::awt::XWindow>& rParent) override;
DECL_LINK( VisibilityNotification, SvxStyleBox_Impl&, void );
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 2d94323..d059e9c 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 b9c4d64..48ed82b 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 c50fcce..2d254db 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 5d5474b..ce04c24 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 dcaab83..bb52a97 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 3ea5f08..dff4cc4 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 b267355..96a13e0 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 78be607..b31ccc4 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 98ef36a..861eea4 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 24189c8..931862f4 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 b576503..3576345 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 5ab016d..cf55416 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
{
using Window::IsVisible;
class 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 );
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;
virtual void UserDraw( const UserDrawEvent& rUDEvt ) override;
void SetVisibilityListener( const Link<SvxStyleBox_Impl&,void>& aVisListener ) { aVisibilityListener = aVisListener; }
void SetDefaultStyle( const OUString& rDefault ) { sDefaultStyle = rDefault; }
virtual boost::property_tree::ptree DumpAsPropertyTree() override;
protected:
/// Calculate the optimal width of the dropdown. Very expensive operation, triggers lots of font measurement.
DECL_LINK(CalcOptimalExtraUserWidth, VclWindowEvent&, void);
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(); }
virtual void Select() override;
void append_text(const OUString& rStr)
{
OUString sId(OUString::number(m_xWidget->get_count()));
m_xWidget->append(sId, rStr);
}
void insert_separator(int pos, const OUString& rId)
{
m_xWidget->insert_separator(pos, rId);
}
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();
}
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,10 +817,57 @@ class SfxStyleControllerItem_Impl : public SfxStatusListener
SvxStyleToolBoxControl& rControl;
};
#define BUTTON_WIDTH 20
#define BUTTON_PADDING 10
#define ITEM_HEIGHT 30
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, 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 )
, m_nMaxUserDrawFontWidth(0)
, bRelease( true )
, bVisible(false)
, m_xDispatchProvider( rDispatchProvider )
, m_xFrame(_xFrame)
, m_aCommand( rCommand )
, aClearFormatKey( rClearFormatKey )
, aMoreKey( rMoreKey )
, bInSpecialMode( bInSpec )
{
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);
}
IMPL_LINK(SvxStyleBox_Base, CustomGetSizeHdl, OutputDevice&, rArg, Size)
{
CalcOptimalExtraUserWidth(rArg);
return Size(m_nMaxUserDrawFontWidth, ITEM_HEIGHT);
}
SvxStyleBox_Impl::SvxStyleBox_Impl(vcl::Window* pParent,
const OUString& rCommand,
SfxStyleFamily eFamily,
@@ -739,55 +875,16 @@ SvxStyleBox_Impl::SvxStyleBox_Impl(vcl::Window* pParent,
const Reference< XFrame >& _xFrame,
const OUString& rClearFormatKey,
const OUString& rMoreKey,
bool bInSpec)
: ComboBox(pParent, WB_SORT | WB_BORDER | WB_HIDE | WB_DROPDOWN | WB_AUTOHSCROLL)
, eStyleFamily( eFamily )
, nCurSel(0)
, bRelease( true )
, aLogicalSize(60, 86)
, bVisible(false)
, m_xDispatchProvider( rDispatchProvider )
, m_xFrame(_xFrame)
, m_aCommand( rCommand )
, aClearFormatKey( rClearFormatKey )
, aMoreKey( rMoreKey )
, bInSpecialMode( bInSpec )
, m_aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "svx/ui/stylemenu.ui", "")
, m_pMenu(m_aBuilder.get_menu("menu"))
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)
{
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");
SetOptimalSize();
}
SvxStyleBox_Impl::~SvxStyleBox_Impl()
{
disposeOnce();
}
void SvxStyleBox_Impl::dispose()
{
RemoveEventListener(LINK(this, SvxStyleBox_Impl, CalcOptimalExtraUserWidth));
for (VclPtr<MenuButton>& rButton : m_pButtons)
{
rButton.disposeAndClear();
}
m_pMenu.clear();
m_aBuilder.disposeBuilder();
ComboBox::dispose();
}
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)
{
// Tell base class about selection so that AT get informed about it.
ComboBox::Select();
Select(rCombo.changed_by_direct_pick()); // only when picked from the list
}
if ( IsTravelSelect() )
IMPL_LINK_NOARG(SvxStyleBox_Base, ActivateHdl, weld::ComboBox&, bool)
{
Select(true);
return true;
}
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 ( 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 );
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());
}
bool SvxStyleBox_Impl::EventNotify( NotifyEvent& rNEvt )
IMPL_LINK(SvxStyleBox_Base, KeyInputHdl, const KeyEvent&, rKEvt, bool)
{
return DoKeyInput(rKEvt);
}
bool SvxStyleBox_Base::DoKeyInput(const KeyEvent& rKEvt)
{
bool bHandled = false;
if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
switch (nCode)
{
sal_uInt16 nCode = rNEvt.GetKeyEvent()->GetKeyCode().GetCode();
switch ( nCode )
{
case KEY_CONTEXTMENU:
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(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:
{
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 );
InterimItemWindow::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 );
}
}
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)
{
if(nId < MAX_STYLES_ENTRIES && m_pButtons[nId])
m_pButtons[nId]->Hide();
}
const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
if (!bIsNotSelected)
rRenderContext.SetTextColor(rStyleSettings.GetHighlightTextColor());
else
rRenderContext.SetTextColor(rStyleSettings.GetDialogTextColor());
// handle the push-button
if (!bIsNotSelected)
{
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());
}
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();
}
OUString SvxStyleToolBoxControl::getImplementationName()
{
return "com.sun.star.comp.svx.StyleToolBoxControl";
}
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()
{
// 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();
bindListener();
}
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;
}
pBox->InsertEntry( pImpl->aClearForm, 0 );
pBox->SetSeparatorPos( 0 );
pBox->InsertEntry( pImpl->aMore );
// enable sort again
nWinBits |= WB_SORT;
pBox->SetStyle( nWinBits );
for (const auto &rStyle : pImpl->aDefaultStyles)
pBox->append_text(rStyle);
}
pBox->SetUpdateMode( true );
pBox->SetFamily( eFamily );
std::sort(aStyles.begin(), aStyles.end());
sal_uInt16 nLines = static_cast<sal_uInt16>(
std::min( pBox->GetEntryCount(), static_cast<sal_Int32>(MAX_STYLES_ENTRIES)));
pBox->SetDropDownLineCount( nLines );
for (const auto& rStyle : aStyles)
pBox->append_text(rStyle);
if (pImpl->bSpecModeWriter || pImpl->bSpecModeCalc)
pBox->append_text(pImpl->aMore);
pBox->thaw();
pBox->set_active_or_entry_text(aStrSel);
pBox->SetFamily( eFamily );
}
}
}
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() ));
SolarMutexGuard aGuard;
if ( pBox && pBox->IsVisible() && !isBound() )
{
for (SfxStyleControllerItem_Impl* pBoundItem : pBoundItems)
pBoundItem->ReBind();
bindListener();
}
else if ( (!pBox || !pBox->IsVisible()) && isBound() )
{
for (SfxStyleControllerItem_Impl* pBoundItem : pBoundItems)
pBoundItem->UnBind();
unbindListener();
}
}
void SvxStyleToolBoxControl::StateChanged(
sal_uInt16 , SfxItemState eState, const SfxPoolItem* pState )
{
sal_uInt16 nId = GetId();
ToolBox& rTbx = GetToolBox();
SvxStyleBox_Impl* pBox = static_cast<SvxStyleBox_Impl*>(rTbx.GetItemWindow( nId ));
TriState eTri = TRISTATE_FALSE;
DBG_ASSERT( pBox, "Control not found!" );
if ( SfxItemState::DISABLED == eState )
pBox->Disable();
if (m_pToolbar)
m_pToolbar->set_item_sensitive(m_aCommandURL.toUtf8(), rEvent.IsEnabled);
else
pBox->Enable();
rTbx.EnableItem( nId, SfxItemState::DISABLED != eState );
switch ( eState )
{
case SfxItemState::DEFAULT:
eTri = static_cast<const SfxTemplateItem*>(pState)->GetValue() != SfxStyleSearchBits::Auto
? TRISTATE_TRUE
: TRISTATE_FALSE;
break;
case SfxItemState::DONTCARE:
eTri = TRISTATE_INDET;
break;
default:
break;
ToolBox* pToolBox = nullptr;
sal_uInt16 nId = 0;
if (!getToolboxId( nId, &pToolBox ) )
return;
pToolBox->EnableItem( nId, rEvent.IsEnabled );
}
rTbx.SetItemState( nId, eTri );
if ( SfxItemState::DISABLED != eState )
if (rEvent.IsEnabled)
Update();
}
VclPtr<vcl::Window> SvxStyleToolBoxControl::CreateItemWindow( vcl::Window *pParent )
css::uno::Reference<css::awt::XWindow> SvxStyleToolBoxControl::createItemWindow(const css::uno::Reference< css::awt::XWindow>& rParent)
{
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 ));
uno::Reference< awt::XWindow > xItemWindow;
return pBox.get();
if (m_pBuilder)
{
SolarMutexGuard aSolarMutexGuard;
std::unique_ptr<weld::ComboBox> xWidget(m_pBuilder->weld_combo_box("applystyle"));
xItemWindow = css::uno::Reference<css::awt::XWindow>(new weld::TransportAsXWindow(xWidget.get()));
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
{
VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow(rParent);
if ( pParent )
{
SolarMutexGuard aSolarMutexGuard;
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);
}
}
if (pImpl->m_pBox && !pImpl->aDefaultStyles.empty())
pImpl->m_pBox->SetDefaultStyle(pImpl->aDefaultStyles[0]);
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 0000000..3dcd64b
--- /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 2f28064..3937f21 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 ce0b0dd..49d18ae 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 a495547..7e87f0a 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,15 +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>
<child>
<object class="GtkToolButton" id=".uno:StyleNewByExample">
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="expand">True</property>
@@ -77,29 +103,6 @@
<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">
<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>
<property name="homogeneous">True</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
diff --git a/svx/util/svxcore.component b/svx/util/svxcore.component
index 2c5a103..f5a8113 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 d68c2ef..59b5d1e 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 35c6049..5313ae3 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 e5d3174..24b0787 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 4a0f975..04a6f68 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)