summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2020-02-04 11:34:29 +0000
committerCaolán McNamara <caolanm@redhat.com>2020-02-06 12:26:37 +0100
commit8950cb8ae6a1621729ec43a6dd1c29cf04260797 (patch)
tree2f0a50e6778ab425813ad626e634cd8b233514ca
parent415c1b05242b80ca883596952caa0e179a07b409 (diff)
weld SvxFontSizeBox_Impl
which enables making a native gtk widget a member of a toolbar This widget wants to distinguish between a value getting selected by the menu or not, which is fairly tricky Change-Id: I9014785530bd0d82ffa66842f940feb2d3237e68 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/87971 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r--include/svtools/ctrlbox.hxx11
-rw-r--r--include/vcl/combobox.hxx3
-rw-r--r--include/vcl/weld.hxx14
-rw-r--r--svtools/source/control/ctrlbox.cxx11
-rw-r--r--svx/UIConfig_svx.mk1
-rw-r--r--svx/source/inc/InterimItemWindow.hxx35
-rw-r--r--svx/source/sidebar/paragraph/ParaSpacingWindow.cxx46
-rw-r--r--svx/source/sidebar/paragraph/ParaSpacingWindow.hxx20
-rw-r--r--svx/source/tbxctrls/tbunocontroller.cxx182
-rw-r--r--svx/uiconfig/ui/fontsizebox.ui29
-rw-r--r--vcl/source/app/salvtables.cxx26
-rw-r--r--vcl/source/control/combobox.cxx15
-rw-r--r--vcl/unx/gtk3/gtk3gtkinst.cxx76
13 files changed, 358 insertions, 111 deletions
diff --git a/include/svtools/ctrlbox.hxx b/include/svtools/ctrlbox.hxx
index 8036d513ad05..30551c592dc2 100644
--- a/include/svtools/ctrlbox.hxx
+++ b/include/svtools/ctrlbox.hxx
@@ -428,6 +428,7 @@ class SVT_DLLPUBLIC SvtFontSizeBox
bPtRelative:1,
bStdSize:1;
Link<weld::ComboBox&, void> m_aChangeHdl;
+ Link<weld::Widget&, void> m_aFocusOutHdl;
std::unique_ptr<weld::ComboBox> m_xComboBox;
sal_uInt16 GetDecimalDigits() const { return nDecimalDigits; }
@@ -461,14 +462,24 @@ public:
bool IsPtRelative() const { return bPtRelative; }
void connect_changed(const Link<weld::ComboBox&, void>& rLink) { m_aChangeHdl = rLink; }
+ void connect_focus_out(const Link<weld::Widget&, void>& rLink) { m_aFocusOutHdl = rLink; }
+ void connect_key_press(const Link<const KeyEvent&, bool>& rLink) { m_xComboBox->connect_key_press(rLink); }
OUString get_active_text() const { return m_xComboBox->get_active_text(); }
void set_active_text(const OUString& rText) { m_xComboBox->set_active_text(rText); }
void set_sensitive(bool bSensitive) { m_xComboBox->set_sensitive(bSensitive); }
+ int get_active() const { return m_xComboBox->get_active(); }
int get_value() const;
void set_value(int nValue);
void save_value() { nSavedValue = get_value(); }
int get_saved_value() const { return nSavedValue; }
bool get_value_changed_from_saved() const { return get_value() != get_saved_value(); }
+ int get_count() const { return m_xComboBox->get_count(); }
+ OUString get_text(int i) const { return m_xComboBox->get_text(i); }
+ void grab_focus() { m_xComboBox->grab_focus(); }
+ bool has_focus() const { return m_xComboBox->has_focus(); }
+ void connect_entry_activate(const Link<weld::ComboBox&, bool>& rLink) { m_xComboBox->connect_entry_activate(rLink); }
+ void disable_entry_completion() { m_xComboBox->set_entry_completion(false, false); }
+ boost::property_tree::ptree get_property_tree() const;
private:
SvtFontSizeBox(const SvtFontSizeBox&) = delete;
diff --git a/include/vcl/combobox.hxx b/include/vcl/combobox.hxx
index ff34c96411b4..f2f96dca1b37 100644
--- a/include/vcl/combobox.hxx
+++ b/include/vcl/combobox.hxx
@@ -152,6 +152,9 @@ public:
void SetNoSelection();
tools::Rectangle GetBoundingRectangle( sal_Int32 nItem ) const;
+ // determine if Select was called due to something selected from the menu
+ bool IsModifyByMenu() const;
+
/** checks whether a certain point lies within the bounds of
a list item and returns the item as well as the character position
the point is at.
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 742290822c32..464047bdf843 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -27,6 +27,8 @@
#include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <boost/property_tree/ptree_fwd.hpp>
+
#include <assert.h>
#include <memory>
#include <vector>
@@ -263,6 +265,8 @@ public:
virtual css::uno::Reference<css::datatransfer::dnd::XDropTarget> get_drop_target() = 0;
+ virtual boost::property_tree::ptree get_property_tree() const = 0;
+
virtual ~Widget() {}
};
@@ -643,7 +647,17 @@ public:
virtual int find_id(const OUString& rId) const = 0;
void remove_id(const OUString& rId) { remove(find_id(rId)); }
+ /* m_aChangeHdl is called when the active item is changed. The can be due
+ to the user selecting a different item from the list or while typing
+ into the entry of a combo box with an entry.
+
+ Use changed_by_menu() to discover whether an item was actually selected
+ from the menu.
+ */
void connect_changed(const Link<ComboBox&, void>& rLink) { m_aChangeHdl = rLink; }
+
+ virtual bool changed_by_menu() const = 0;
+
virtual void connect_popup_toggled(const Link<ComboBox&, void>& rLink)
{
m_aPopupToggledHdl = rLink;
diff --git a/svtools/source/control/ctrlbox.cxx b/svtools/source/control/ctrlbox.cxx
index b47b3ba74e2e..6ecbfd596bc5 100644
--- a/svtools/source/control/ctrlbox.cxx
+++ b/svtools/source/control/ctrlbox.cxx
@@ -52,6 +52,8 @@
#include <rtl/bootstrap.hxx>
+#include <boost/property_tree/ptree.hpp>
+
#include <borderline.hrc>
#include <stdio.h>
@@ -1025,7 +1027,12 @@ SvtFontSizeBox::SvtFontSizeBox(std::unique_ptr<weld::ComboBox> p)
m_xComboBox->connect_changed(LINK(this, SvtFontSizeBox, ModifyHdl));
}
-IMPL_LINK_NOARG(SvtFontSizeBox, ReformatHdl, weld::Widget&, void)
+boost::property_tree::ptree SvtFontSizeBox::get_property_tree() const
+{
+ return m_xComboBox->get_property_tree();
+}
+
+IMPL_LINK(SvtFontSizeBox, ReformatHdl, weld::Widget&, rWidget, void)
{
FontSizeNames aFontSizeNames(Application::GetSettings().GetUILanguageTag().getLanguageType());
if (!bRelativeMode || !aFontSizeNames.IsEmpty())
@@ -1035,6 +1042,8 @@ IMPL_LINK_NOARG(SvtFontSizeBox, ReformatHdl, weld::Widget&, void)
}
set_value(get_value());
+
+ m_aFocusOutHdl.Call(rWidget);
}
IMPL_LINK(SvtFontSizeBox, ModifyHdl, weld::ComboBox&, rBox, void)
diff --git a/svx/UIConfig_svx.mk b/svx/UIConfig_svx.mk
index e8a02daec4b6..15f4bb7f7326 100644
--- a/svx/UIConfig_svx.mk
+++ b/svx/UIConfig_svx.mk
@@ -59,6 +59,7 @@ $(eval $(call gb_UIConfig_add_uifiles,svx,\
svx/uiconfig/ui/fontworkcharacterspacingcontrol \
svx/uiconfig/ui/fontworkgallerydialog \
svx/uiconfig/ui/fontworkspacingdialog \
+ svx/uiconfig/ui/fontsizebox \
svx/uiconfig/ui/formdatamenu \
svx/uiconfig/ui/formfielddialog \
svx/uiconfig/ui/formlinkwarndialog \
diff --git a/svx/source/inc/InterimItemWindow.hxx b/svx/source/inc/InterimItemWindow.hxx
new file mode 100644
index 000000000000..715cf41fc020
--- /dev/null
+++ b/svx/source/inc/InterimItemWindow.hxx
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <vcl/layout.hxx>
+
+class InterimItemWindow : public Control
+{
+public:
+ virtual ~InterimItemWindow() override;
+ virtual void dispose() override;
+
+ virtual void Resize() override;
+ virtual Size GetOptimalSize() const override;
+
+protected:
+ InterimItemWindow(vcl::Window* pParent, const OUString& rUIXMLDescription, const OString& rID);
+
+ // pass keystrokes from our child window through this to handle focus changes correctly
+ // returns true if keystroke is consumed
+ bool ChildKeyInput(const KeyEvent& rKEvt);
+
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ VclPtr<vcl::Window> m_xVclContentArea;
+ std::unique_ptr<weld::Container> m_xContainer;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/svx/source/sidebar/paragraph/ParaSpacingWindow.cxx b/svx/source/sidebar/paragraph/ParaSpacingWindow.cxx
index f098f29cb6e7..8af67e22ab55 100644
--- a/svx/source/sidebar/paragraph/ParaSpacingWindow.cxx
+++ b/svx/source/sidebar/paragraph/ParaSpacingWindow.cxx
@@ -70,6 +70,42 @@ Size InterimItemWindow::GetOptimalSize() const
return VclContainer::getLayoutRequisition(*GetWindow(GetWindowType::FirstChild));
}
+bool InterimItemWindow::ChildKeyInput(const KeyEvent& rKEvt)
+{
+ sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
+ if (nCode != KEY_TAB)
+ return false;
+
+ /* if the native widget has focus, then no vcl window has focus.
+
+ We want to grab focus to this vcl widget so that pressing tab will travese
+ to the next vcl widget.
+
+ But just using GrabFocus will, because no vcl widget has focus, trigger
+ bringing the toplevel to front with the expectation that a suitable widget
+ will be picked for focus when that happen, which is no use to us here.
+
+ SetFakeFocus avoids the problem, allowing GrabFocus to do the expected thing
+ then sending the Tab to our parent will do the right traversal
+ */
+ SetFakeFocus(true);
+ GrabFocus();
+
+ /* let toolbox know we have focus so it updates its mnHighItemId to point
+ to this toolitem in case tab means to move to another toolitem within
+ the toolbox
+ */
+ NotifyEvent aNEvt(MouseNotifyEvent::GETFOCUS, this);
+ vcl::Window* pToolBox = GetParent();
+ pToolBox->EventNotify(aNEvt);
+
+ /* now give focus to our toolbox parent and send it the tab */
+ pToolBox->GrabFocus();
+ pToolBox->KeyInput(rKEvt);
+
+ return true;
+}
+
// ParaULSpacingWindow
ParaULSpacingWindow::ParaULSpacingWindow(vcl::Window* pParent)
@@ -149,7 +185,7 @@ ParaAboveSpacingWindow::ParaAboveSpacingWindow(vcl::Window* pParent)
m_xAboveContainer->show();
m_xBelowContainer->hide();
- SetSizePixel(GetOptimalSize());
+ SetSizePixel(get_preferred_size());
}
void ParaAboveSpacingWindow::GetFocus()
@@ -165,7 +201,7 @@ ParaBelowSpacingWindow::ParaBelowSpacingWindow(vcl::Window* pParent)
m_xAboveContainer->hide();
m_xBelowContainer->show();
- SetSizePixel(GetOptimalSize());
+ SetSizePixel(get_preferred_size());
}
void ParaBelowSpacingWindow::GetFocus()
@@ -350,7 +386,7 @@ ParaLeftSpacingWindow::ParaLeftSpacingWindow(vcl::Window* pParent)
m_xAfterContainer->hide();
m_xFirstLineContainer->hide();
- SetSizePixel(GetOptimalSize());
+ SetSizePixel(get_preferred_size());
}
void ParaLeftSpacingWindow::GetFocus()
@@ -367,7 +403,7 @@ ParaRightSpacingWindow::ParaRightSpacingWindow(vcl::Window* pParent)
m_xAfterContainer->show();
m_xFirstLineContainer->hide();
- SetSizePixel(GetOptimalSize());
+ SetSizePixel(get_preferred_size());
}
void ParaRightSpacingWindow::GetFocus()
@@ -384,7 +420,7 @@ ParaFirstLineSpacingWindow::ParaFirstLineSpacingWindow(vcl::Window* pParent)
m_xAfterContainer->hide();
m_xFirstLineContainer->show();
- SetSizePixel(GetOptimalSize());
+ SetSizePixel(get_preferred_size());
}
void ParaFirstLineSpacingWindow::GetFocus()
diff --git a/svx/source/sidebar/paragraph/ParaSpacingWindow.hxx b/svx/source/sidebar/paragraph/ParaSpacingWindow.hxx
index d25030c3d9f6..af103d5d1f8a 100644
--- a/svx/source/sidebar/paragraph/ParaSpacingWindow.hxx
+++ b/svx/source/sidebar/paragraph/ParaSpacingWindow.hxx
@@ -20,30 +20,12 @@
#define INCLUDED_SVX_SOURCE_SIDEBAR_PARAGRAPH_PARASPACINGWINDOW_HXX
#include <editeng/ulspitem.hxx>
-#include <vcl/builder.hxx>
-#include <vcl/layout.hxx>
#include <vcl/EnumContext.hxx>
#include <svx/relfld.hxx>
+#include <InterimItemWindow.hxx>
using namespace com::sun::star;
-class InterimItemWindow : public Control
-{
-public:
- virtual ~InterimItemWindow() override;
- virtual void dispose() override;
-
- virtual void Resize() override;
- virtual Size GetOptimalSize() const override;
-
-protected:
- InterimItemWindow(vcl::Window* pParent, const OUString& rUIXMLDescription, const OString& rID);
-
- std::unique_ptr<weld::Builder> m_xBuilder;
- VclPtr<vcl::Window> m_xVclContentArea;
- std::unique_ptr<weld::Container> m_xContainer;
-};
-
namespace svx {
class ParaULSpacingWindow : public InterimItemWindow
diff --git a/svx/source/tbxctrls/tbunocontroller.cxx b/svx/source/tbxctrls/tbunocontroller.cxx
index 313810b6a329..980c4dd30385 100644
--- a/svx/source/tbxctrls/tbunocontroller.cxx
+++ b/svx/source/tbxctrls/tbunocontroller.cxx
@@ -41,6 +41,7 @@
#include <sfx2/sidebar/SidebarToolBox.hxx>
#include <boost/property_tree/ptree.hpp>
+#include <InterimItemWindow.hxx>
using namespace ::com::sun::star;
@@ -85,32 +86,40 @@ class FontHeightToolBoxControl : public svt::ToolboxController,
css::awt::FontDescriptor m_aCurrentFont;
};
-class SvxFontSizeBox_Impl : public FontSizeBox
+class SvxFontSizeBox_Impl : public InterimItemWindow
{
public:
SvxFontSizeBox_Impl( vcl::Window* pParent,
const uno::Reference< frame::XFrame >& _xFrame,
FontHeightToolBoxControl& rCtrl );
+ virtual void dispose() override;
+ virtual ~SvxFontSizeBox_Impl() override;
void statusChanged_Impl( long nHeight, bool bErase );
void UpdateFont( const css::awt::FontDescriptor& rCurrentFont );
void SetOptimalSize();
- virtual bool EventNotify( NotifyEvent& rNEvt ) override;
virtual boost::property_tree::ptree DumpAsPropertyTree() override;
protected:
- virtual void Select() override;
virtual void DataChanged( const DataChangedEvent& rDCEvt ) override;
+ virtual void GetFocus() override;
private:
- FontHeightToolBoxControl* m_pCtrl;
+ FontHeightToolBoxControl& m_rCtrl;
OUString m_aCurText;
- Size const m_aLogicalSize;
bool m_bRelease;
uno::Reference< frame::XFrame > m_xFrame;
+ std::unique_ptr<SvtFontSizeBox> m_xWidget;
void ReleaseFocus_Impl();
+
+ void Select();
+
+ DECL_LINK(SelectHdl, weld::ComboBox&, void);
+ DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
+ DECL_LINK(ActivateHdl, weld::ComboBox&, bool);
+ DECL_LINK(FocusOutHdl, weld::Widget&, void);
};
SvxFontSizeBox_Impl::SvxFontSizeBox_Impl(
@@ -118,16 +127,38 @@ SvxFontSizeBox_Impl::SvxFontSizeBox_Impl(
const uno::Reference< frame::XFrame >& _xFrame,
FontHeightToolBoxControl& _rCtrl ) :
- FontSizeBox( _pParent, WinBits( WB_DROPDOWN ) ),
+ InterimItemWindow(_pParent, "svx/ui/fontsizebox.ui", "FontSizeBox"),
- m_pCtrl ( &_rCtrl ),
- m_aLogicalSize ( 0,100 ),
+ m_rCtrl ( _rCtrl ),
m_bRelease ( true ),
- m_xFrame ( _xFrame )
+ m_xFrame ( _xFrame ),
+ m_xWidget(new SvtFontSizeBox(m_xBuilder->weld_combo_box("fontsize")))
{
- SetValue( 0 );
- SetText( "" );
set_id("fontsizecombobox");
+ m_xWidget->set_value(0);
+ m_xWidget->set_active_text("");
+ m_xWidget->disable_entry_completion();
+
+ m_xWidget->connect_changed(LINK(this, SvxFontSizeBox_Impl, SelectHdl));
+ m_xWidget->connect_key_press(LINK(this, SvxFontSizeBox_Impl, KeyInputHdl));
+ m_xWidget->connect_entry_activate(LINK(this, SvxFontSizeBox_Impl, ActivateHdl));
+ m_xWidget->connect_focus_out(LINK(this, SvxFontSizeBox_Impl, FocusOutHdl));
+}
+
+void SvxFontSizeBox_Impl::dispose()
+{
+ m_xWidget.reset();
+ InterimItemWindow::dispose();
+}
+
+SvxFontSizeBox_Impl::~SvxFontSizeBox_Impl()
+{
+ disposeOnce();
+}
+
+void SvxFontSizeBox_Impl::GetFocus()
+{
+ m_xWidget->grab_focus();
}
void SvxFontSizeBox_Impl::ReleaseFocus_Impl()
@@ -142,30 +173,35 @@ void SvxFontSizeBox_Impl::ReleaseFocus_Impl()
m_xFrame->getContainerWindow()->setFocus();
}
+IMPL_LINK(SvxFontSizeBox_Impl, SelectHdl, weld::ComboBox&, rCombo, void)
+{
+ if (rCombo.changed_by_menu()) // only when picked from the list
+ Select();
+}
-void SvxFontSizeBox_Impl::Select()
+IMPL_LINK_NOARG(SvxFontSizeBox_Impl, ActivateHdl, weld::ComboBox&, bool)
{
- FontSizeBox::Select();
+ Select();
+ return true;
+}
- if ( !IsTravelSelect() )
- {
- sal_Int64 nSelVal = GetValue();
- float fSelVal = float( nSelVal ) / 10;
+void SvxFontSizeBox_Impl::Select()
+{
+ sal_Int64 nSelVal = m_xWidget->get_value();
+ float fSelVal = float( nSelVal ) / 10;
- uno::Sequence< beans::PropertyValue > aArgs( 1 );
- aArgs[0].Name = "FontHeight.Height";
- aArgs[0].Value <<= fSelVal;
+ uno::Sequence< beans::PropertyValue > aArgs( 1 );
+ aArgs[0].Name = "FontHeight.Height";
+ aArgs[0].Value <<= fSelVal;
- /* #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call.
- This instance may be deleted in the meantime (i.e. when a dialog is opened
- while in Dispatch()), accessing members will crash in this case. */
- ReleaseFocus_Impl();
+ /* #i33380# DR 2004-09-03 Moved the following line above the Dispatch() call.
+ This instance may be deleted in the meantime (i.e. when a dialog is opened
+ while in Dispatch()), accessing members will crash in this case. */
+ ReleaseFocus_Impl();
- m_pCtrl->dispatchCommand( aArgs );
- }
+ m_rCtrl.dispatchCommand( aArgs );
}
-
void SvxFontSizeBox_Impl::statusChanged_Impl( long nPoint, bool bErase )
{
if ( !bErase )
@@ -174,23 +210,22 @@ void SvxFontSizeBox_Impl::statusChanged_Impl( long nPoint, bool bErase )
long nVal = nPoint;
// changed => set new value
- if ( GetValue() != nVal )
- SetValue( nVal );
+ if (m_xWidget->get_value() != nVal)
+ m_xWidget->set_value(nVal);
}
else
{
// delete value in the display
- SetValue( -1L );
- SetText( "" );
+ m_xWidget->set_value(-1L);
+ m_xWidget->set_active_text("");
}
- SaveValue();
+ m_xWidget->save_value();
}
-
void SvxFontSizeBox_Impl::UpdateFont( const css::awt::FontDescriptor& rCurrentFont )
{
// filling up the sizes list
- sal_Int64 nOldVal = GetValue(); // memorize old value
+ auto nOldVal = m_xWidget->get_value(); // memorize old value
const FontList* _pFontList = nullptr;
std::unique_ptr<FontList> aHold( new FontList( this ));
_pFontList = aHold.get();
@@ -201,61 +236,49 @@ void SvxFontSizeBox_Impl::UpdateFont( const css::awt::FontDescriptor& rCurrentFo
_aFontMetric.SetFamilyName( rCurrentFont.Name );
_aFontMetric.SetStyleName( rCurrentFont.StyleName );
_aFontMetric.SetFontHeight( rCurrentFont.Height );
- Fill( &_aFontMetric, _pFontList );
+ m_xWidget->Fill(&_aFontMetric, _pFontList);
}
else
{
- Fill( nullptr, _pFontList );
+ m_xWidget->Fill(nullptr, _pFontList);
}
- SetValue( nOldVal ); // restore old value
- m_aCurText = GetText(); // memorize to reset at ESC
+ m_xWidget->set_value(nOldVal); // restore old value
+ m_aCurText = m_xWidget->get_active_text(); // memorize to reset at ESC
}
-
-bool SvxFontSizeBox_Impl::EventNotify( NotifyEvent& rNEvt )
+IMPL_LINK(SvxFontSizeBox_Impl, KeyInputHdl, const KeyEvent&, rKEvt, bool)
{
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_RETURN:
- case KEY_TAB:
- {
- if ( KEY_TAB == nCode )
- m_bRelease = false;
- else
- bHandled = true;
- Select();
- break;
- }
-
- case KEY_ESCAPE:
- SetText( m_aCurText );
- if ( typeid( *GetParent() ) != typeid( sfx2::sidebar::SidebarToolBox ) )
- ReleaseFocus_Impl();
- bHandled = true;
- break;
- }
- }
- else if( MouseNotifyEvent::LOSEFOCUS == rNEvt.GetType() )
+ switch (nCode)
{
- vcl::Window* pFocusWin = Application::GetFocusWindow();
- if(!HasFocus() && GetSubEdit() != pFocusWin)
- SetText(GetSavedValue());
+ case KEY_TAB:
+ m_bRelease = false;
+ Select();
+ break;
+
+ case KEY_ESCAPE:
+ m_xWidget->set_active_text(m_aCurText);
+ if ( typeid( *GetParent() ) != typeid( sfx2::sidebar::SidebarToolBox ) )
+ ReleaseFocus_Impl();
+ bHandled = true;
+ break;
}
- return bHandled || FontSizeBox::EventNotify( rNEvt );
+ return bHandled || ChildKeyInput(rKEvt);
+}
+
+IMPL_LINK_NOARG(SvxFontSizeBox_Impl, FocusOutHdl, weld::Widget&, void)
+{
+ if (!m_xWidget->has_focus()) // a combobox can be comprised of different subwidget so double-check if none of those has focus
+ m_xWidget->set_value(m_xWidget->get_saved_value());
}
void SvxFontSizeBox_Impl::SetOptimalSize()
{
- Size aPrefSize(LogicToPixel(m_aLogicalSize, MapMode(MapUnit::MapAppFont)));
- aPrefSize.setWidth( get_preferred_size().Width() );
- SetSizePixel(aPrefSize);
+ SetSizePixel(get_preferred_size());
}
void SvxFontSizeBox_Impl::DataChanged( const DataChangedEvent& rDCEvt )
@@ -265,20 +288,18 @@ void SvxFontSizeBox_Impl::DataChanged( const DataChangedEvent& rDCEvt )
{
SetOptimalSize();
}
-
- FontSizeBox::DataChanged( rDCEvt );
}
boost::property_tree::ptree SvxFontSizeBox_Impl::DumpAsPropertyTree()
{
- boost::property_tree::ptree aTree(FontSizeBox::DumpAsPropertyTree());
+ boost::property_tree::ptree aTree(m_xWidget->get_property_tree());
boost::property_tree::ptree aEntries;
- for (int i = 0; i < GetEntryCount(); ++i)
+ for (int i = 0, nCount = m_xWidget->get_count(); i < nCount; ++i)
{
boost::property_tree::ptree aEntry;
- aEntry.put("", GetEntry(i));
+ aEntry.put("", m_xWidget->get_text(i));
aEntries.push_back(std::make_pair("", aEntry));
}
@@ -286,14 +307,15 @@ boost::property_tree::ptree SvxFontSizeBox_Impl::DumpAsPropertyTree()
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.put("selectedCount", nActive == -1 ? 0 : 1);
aTree.add_child("selectedEntries", aSelected);
aTree.put("command", ".uno:FontHeight");
diff --git a/svx/uiconfig/ui/fontsizebox.ui b/svx/uiconfig/ui/fontsizebox.ui
new file mode 100644
index 000000000000..c1702822b3e2
--- /dev/null
+++ b/svx/uiconfig/ui/fontsizebox.ui
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="svx">
+ <requires lib="gtk+" version="3.18"/>
+ <object class="GtkBox" id="FontSizeBox">
+ <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="fontsize">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="has_entry">True</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/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index fb68ee0c605d..f1bc5c341d47 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -73,6 +73,8 @@
#include <bitmaps.hlst>
#include <wizdlg.hxx>
+#include <boost/property_tree/ptree.hpp>
+
SalFrame::SalFrame()
: m_pWindow(nullptr)
, m_pProc(nullptr)
@@ -722,6 +724,11 @@ public:
return m_xWidget->GetDropTarget();
}
+ virtual boost::property_tree::ptree get_property_tree() const override
+ {
+ return m_xWidget->DumpAsPropertyTree();
+ }
+
virtual void set_stack_background() override
{
set_background(m_xWidget->GetSettings().GetStyleSettings().GetWindowColor());
@@ -6153,6 +6160,11 @@ public:
return false;
}
+ virtual bool changed_by_menu() const override
+ {
+ return true;
+ }
+
virtual void set_entry_message_type(weld::EntryMessageType /*eType*/) override
{
assert(false);
@@ -6225,6 +6237,11 @@ public:
return true;
}
+ virtual bool changed_by_menu() const override
+ {
+ return m_xComboBox->IsModifyByMenu(); // && !m_xComboBox->IsTravelSelect();
+ }
+
virtual void set_entry_message_type(weld::EntryMessageType eType) override
{
if (eType == weld::EntryMessageType::Error)
@@ -6328,6 +6345,7 @@ private:
DECL_LINK(KeyPressListener, VclWindowEvent&, void);
SalInstanceEntry* m_pEntry;
SalInstanceTreeView* m_pTreeView;
+ bool m_bTreeChange;
public:
SalInstanceEntryTreeView(vcl::Window *pContainer, SalInstanceBuilder* pBuilder, bool bTakeOwnership,
std::unique_ptr<weld::Entry> xEntry, std::unique_ptr<weld::TreeView> xTreeView)
@@ -6335,6 +6353,7 @@ public:
, SalInstanceContainer(pContainer, pBuilder, bTakeOwnership)
, m_pEntry(dynamic_cast<SalInstanceEntry*>(m_xEntry.get()))
, m_pTreeView(dynamic_cast<SalInstanceTreeView*>(m_xTreeView.get()))
+ , m_bTreeChange(false)
{
assert(m_pEntry && m_pTreeView);
@@ -6373,6 +6392,11 @@ public:
m_xEntry->connect_focus_out(rLink);
}
+ virtual bool changed_by_menu() const override
+ {
+ return m_bTreeChange;
+ }
+
virtual ~SalInstanceEntryTreeView() override
{
Edit& rEntry = m_pEntry->getEntry();
@@ -6398,7 +6422,9 @@ IMPL_LINK(SalInstanceEntryTreeView, KeyPressListener, VclWindowEvent&, rEvent, v
m_xEntry->set_text(m_xTreeView->get_selected_text());
m_xEntry->select_region(0, -1);
m_pTreeView->enable_notify_events();
+ m_bTreeChange = true;
m_pEntry->fire_signal_changed();
+ m_bTreeChange = false;
}
}
diff --git a/vcl/source/control/combobox.cxx b/vcl/source/control/combobox.cxx
index 3fac924ea4d6..c42ef08e8e38 100644
--- a/vcl/source/control/combobox.cxx
+++ b/vcl/source/control/combobox.cxx
@@ -57,6 +57,7 @@ struct ComboBox::Impl
sal_Unicode m_cMultiSep;
bool m_isDDAutoSize : 1;
bool m_isSyntheticModify : 1;
+ bool m_isMenuModify : 1;
bool m_isMatchCase : 1;
sal_Int32 m_nMaxWidthChars;
sal_Int32 m_nWidthInChars;
@@ -69,6 +70,7 @@ struct ComboBox::Impl
, m_cMultiSep(0)
, m_isDDAutoSize(false)
, m_isSyntheticModify(false)
+ , m_isMenuModify(false)
, m_isMatchCase(false)
, m_nMaxWidthChars(0)
, m_nWidthInChars(-1)
@@ -142,6 +144,7 @@ void ComboBox::Impl::ImplInitComboBoxData()
m_nDDHeight = 0;
m_isDDAutoSize = true;
m_isSyntheticModify = false;
+ m_isMenuModify = false;
m_isMatchCase = false;
m_cMultiSep = ';';
m_nMaxWidthChars = -1;
@@ -422,9 +425,8 @@ IMPL_LINK_NOARG(ComboBox::Impl, ImplSelectHdl, LinkParamNone*, void)
}
// #84652# Call GrabFocus and EndPopupMode before calling Select/Modify, but after changing the text
-
- if (bPopup && !m_pImplLB->IsTravelSelect() &&
- (!m_rThis.IsMultiSelectionEnabled() || !m_pImplLB->GetSelectModifier()))
+ bool bMenuSelect = bPopup && !m_pImplLB->IsTravelSelect() && (!m_rThis.IsMultiSelectionEnabled() || !m_pImplLB->GetSelectModifier());
+ if (bMenuSelect)
{
m_pFloatWin->EndPopupMode();
m_rThis.GrabFocus();
@@ -434,12 +436,19 @@ IMPL_LINK_NOARG(ComboBox::Impl, ImplSelectHdl, LinkParamNone*, void)
{
m_pSubEdit->SetModifyFlag();
m_isSyntheticModify = true;
+ m_isMenuModify = bMenuSelect;
m_rThis.Modify();
+ m_isMenuModify = false;
m_isSyntheticModify = false;
m_rThis.Select();
}
}
+bool ComboBox::IsModifyByMenu() const
+{
+ return m_pImpl->m_isMenuModify;
+}
+
IMPL_LINK_NOARG( ComboBox::Impl, ImplListItemSelectHdl, LinkParamNone*, void )
{
m_rThis.CallEventListeners( VclEventId::DropdownSelect );
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index 4eb3e5b4d430..41978048ee36 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -82,6 +82,8 @@
#include <window.h>
#include <numeric>
+#include <boost/property_tree/ptree.hpp>
+
using namespace com::sun::star;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
@@ -2862,6 +2864,12 @@ public:
return m_xDropTarget.get();
}
+ virtual boost::property_tree::ptree get_property_tree() const override
+ {
+ //not implemented for the gtk variant
+ return boost::property_tree::ptree();
+ }
+
virtual void set_stack_background() override
{
OUString sColor = Application::GetSettings().GetStyleSettings().GetWindowColor().AsRGBHexString();
@@ -11749,6 +11757,7 @@ private:
bool m_bPopupActive;
bool m_bAutoComplete;
bool m_bAutoCompleteCaseSensitive;
+ bool m_bChangedByMenu;
gulong m_nToggleFocusInSignalId;
gulong m_nToggleFocusOutSignalId;
gulong m_nChangedSignalId;
@@ -11758,6 +11767,8 @@ private:
gulong m_nEntryActivateSignalId;
gulong m_nEntryFocusInSignalId;
gulong m_nEntryFocusOutSignalId;
+ gulong m_nOriginalMenuActivateEventId;
+ gulong m_nMenuActivateSignalId;
guint m_nAutoCompleteIdleId;
static gboolean idleAutoComplete(gpointer widget)
@@ -11855,7 +11866,13 @@ private:
{
GtkInstanceComboBox* pThis = static_cast<GtkInstanceComboBox*>(widget);
SolarMutexGuard aGuard;
- pThis->signal_changed();
+ pThis->fire_signal_changed();
+ }
+
+ void fire_signal_changed()
+ {
+ signal_changed();
+ m_bChangedByMenu = false;
}
static void signalPopupToggled(GtkComboBox*, GParamSpec*, gpointer widget)
@@ -12012,6 +12029,27 @@ private:
return pThis->signal_key_press(pEvent);
}
+ static void signalMenuActivate(GtkWidget* pWidget, const gchar *path, gpointer widget)
+ {
+ GtkInstanceComboBox* pThis = static_cast<GtkInstanceComboBox*>(widget);
+ return pThis->signal_menu_activate(pWidget, path);
+ }
+
+ void signal_menu_activate(GtkWidget* pWidget, const gchar *path)
+ {
+ // we disabled the original menu-active to get our own handler in first
+ // so we know before changed is called that it will be called by the
+ // menu, now block our handler and unblock the original and replay the
+ // event to call the original handler
+ m_bChangedByMenu = true;
+ g_signal_handler_block(m_pMenu, m_nMenuActivateSignalId);
+ g_signal_handler_unblock(m_pMenu, m_nOriginalMenuActivateEventId);
+ guint nMenuActivateSignalId = g_signal_lookup("menu-activate", G_TYPE_FROM_INSTANCE(m_pMenu));
+ g_signal_emit(pWidget, nMenuActivateSignalId, 0, path);
+ g_signal_handler_block(m_pMenu, m_nOriginalMenuActivateEventId);
+ g_signal_handler_unblock(m_pMenu, m_nMenuActivateSignalId);
+ }
+
bool signal_key_press(const GdkEventKey* pEvent)
{
KeyEvent aKEvt(GtkToVcl(*pEvent));
@@ -12134,12 +12172,21 @@ private:
return;
m_pMenu = GTK_MENU(pWidget);
- guint nSignalId = g_signal_lookup("key-press-event", GTK_TYPE_MENU);
+ guint nKeyPressSignalId = g_signal_lookup("key-press-event", GTK_TYPE_MENU);
gulong nOriginalMenuKeyPressEventId = g_signal_handler_find(m_pMenu,
static_cast<GSignalMatchType>(G_SIGNAL_MATCH_DATA | G_SIGNAL_MATCH_ID),
- nSignalId, 0,
+ nKeyPressSignalId, 0,
nullptr, nullptr, m_pComboBox);
+ guint nMenuActivateSignalId = g_signal_lookup("menu-activate", G_TYPE_FROM_INSTANCE(m_pMenu));
+ m_nOriginalMenuActivateEventId = g_signal_handler_find(m_pMenu,
+ static_cast<GSignalMatchType>(G_SIGNAL_MATCH_DATA | G_SIGNAL_MATCH_ID),
+ nMenuActivateSignalId, 0,
+ nullptr, nullptr, m_pComboBox);
+
+ g_signal_handler_block(m_pMenu, m_nOriginalMenuActivateEventId);
+ m_nMenuActivateSignalId = g_signal_connect(m_pMenu, "menu-activate", G_CALLBACK(signalMenuActivate), this);
+
g_signal_handler_block(m_pMenu, nOriginalMenuKeyPressEventId);
g_signal_connect(m_pMenu, "key-press-event", G_CALLBACK(signalKeyPress), this);
}
@@ -12166,10 +12213,13 @@ public:
, m_bPopupActive(false)
, m_bAutoComplete(false)
, m_bAutoCompleteCaseSensitive(false)
+ , m_bChangedByMenu(false)
, m_nToggleFocusInSignalId(0)
, m_nToggleFocusOutSignalId(0)
, m_nChangedSignalId(g_signal_connect(m_pComboBox, "changed", G_CALLBACK(signalChanged), this))
, m_nPopupShownSignalId(g_signal_connect(m_pComboBox, "notify::popup-shown", G_CALLBACK(signalPopupToggled), this))
+ , m_nOriginalMenuActivateEventId(0)
+ , m_nMenuActivateSignalId(0)
, m_nAutoCompleteIdleId(0)
{
GList* cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(m_pComboBox));
@@ -12232,6 +12282,7 @@ public:
disable_notify_events();
OString aId(OUStringToOString(rStr, RTL_TEXTENCODING_UTF8));
gtk_combo_box_set_active_id(m_pComboBox, aId.getStr());
+ m_bChangedByMenu = false;
enable_notify_events();
}
@@ -12278,6 +12329,7 @@ public:
{
disable_notify_events();
gtk_combo_box_set_active(m_pComboBox, pos);
+ m_bChangedByMenu = false;
enable_notify_events();
}
@@ -12591,8 +12643,17 @@ public:
return gtk_widget_has_focus(m_pToggleButton) || GtkInstanceWidget::has_focus();
}
+ virtual bool changed_by_menu() const override
+ {
+ return m_bChangedByMenu;
+ }
+
virtual ~GtkInstanceComboBox() override
{
+ if (m_nOriginalMenuActivateEventId)
+ g_signal_handler_unblock(m_pMenu, m_nOriginalMenuActivateEventId);
+ if (m_nMenuActivateSignalId)
+ g_signal_handler_disconnect(m_pMenu, m_nMenuActivateSignalId);
if (m_nAutoCompleteIdleId)
g_source_remove(m_nAutoCompleteIdleId);
if (GtkEntry* pEntry = get_entry())
@@ -12622,6 +12683,7 @@ private:
gulong m_nEntryInsertTextSignalId;
guint m_nAutoCompleteIdleId;
bool m_bAutoCompleteCaseSensitive;
+ bool m_bTreeChange;
bool signal_key_press(GdkEventKey* pEvent)
{
@@ -12646,7 +12708,9 @@ private:
}
m_xEntry->select_region(0, -1);
enable_notify_events();
+ m_bTreeChange = true;
m_pEntry->fire_signal_changed();
+ m_bTreeChange = false;
return true;
}
return false;
@@ -12747,6 +12811,7 @@ public:
, m_pTreeView(dynamic_cast<GtkInstanceTreeView*>(m_xTreeView.get()))
, m_nAutoCompleteIdleId(0)
, m_bAutoCompleteCaseSensitive(false)
+ , m_bTreeChange(false)
{
assert(m_pEntry);
GtkWidget* pWidget = m_pEntry->getWidget();
@@ -12803,6 +12868,11 @@ public:
GtkInstanceContainer::disable_notify_events();
}
+ virtual bool changed_by_menu() const override
+ {
+ return m_bTreeChange;
+ }
+
virtual ~GtkInstanceEntryTreeView() override
{
if (m_nAutoCompleteIdleId)