diff options
-rw-r--r-- | include/svtools/ctrlbox.hxx | 11 | ||||
-rw-r--r-- | include/vcl/combobox.hxx | 3 | ||||
-rw-r--r-- | include/vcl/weld.hxx | 14 | ||||
-rw-r--r-- | svtools/source/control/ctrlbox.cxx | 11 | ||||
-rw-r--r-- | svx/UIConfig_svx.mk | 1 | ||||
-rw-r--r-- | svx/source/inc/InterimItemWindow.hxx | 35 | ||||
-rw-r--r-- | svx/source/sidebar/paragraph/ParaSpacingWindow.cxx | 46 | ||||
-rw-r--r-- | svx/source/sidebar/paragraph/ParaSpacingWindow.hxx | 20 | ||||
-rw-r--r-- | svx/source/tbxctrls/tbunocontroller.cxx | 182 | ||||
-rw-r--r-- | svx/uiconfig/ui/fontsizebox.ui | 29 | ||||
-rw-r--r-- | vcl/source/app/salvtables.cxx | 26 | ||||
-rw-r--r-- | vcl/source/control/combobox.cxx | 15 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkinst.cxx | 76 |
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) |