From f3ad8a70c3c15fd57891b0d2fe0bb0a5d2aa39a2 Mon Sep 17 00:00:00 2001 From: Caolán McNamara Date: Tue, 4 Feb 2020 11:34:29 +0000 Subject: weld SvxFontSizeBox_Impl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- svx/UIConfig_svx.mk | 1 + svx/source/inc/InterimItemWindow.hxx | 35 ++++ svx/source/sidebar/paragraph/ParaSpacingWindow.cxx | 82 +++++++++- svx/source/sidebar/paragraph/ParaSpacingWindow.hxx | 5 +- svx/source/tbxctrls/tbunocontroller.cxx | 182 ++++++++++++--------- svx/uiconfig/ui/fontsizebox.ui | 29 ++++ 6 files changed, 245 insertions(+), 89 deletions(-) create mode 100644 svx/source/inc/InterimItemWindow.hxx create mode 100644 svx/uiconfig/ui/fontsizebox.ui (limited to 'svx') diff --git a/svx/UIConfig_svx.mk b/svx/UIConfig_svx.mk index 9f6a55c266e3..853dc5ba397b 100644 --- a/svx/UIConfig_svx.mk +++ b/svx/UIConfig_svx.mk @@ -48,6 +48,7 @@ $(eval $(call gb_UIConfig_add_uifiles,svx,\ svx/uiconfig/ui/floatingundoredo \ svx/uiconfig/ui/fontworkgallerydialog \ svx/uiconfig/ui/fontworkspacingdialog \ + svx/uiconfig/ui/fontsizebox \ svx/uiconfig/ui/formdatamenu \ svx/uiconfig/ui/formlinkwarndialog \ svx/uiconfig/ui/formnavimenu \ 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 + +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 m_xBuilder; + VclPtr m_xVclContentArea; + std::unique_ptr 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 a5cff78f2521..184448e00f1f 100644 --- a/svx/source/sidebar/paragraph/ParaSpacingWindow.cxx +++ b/svx/source/sidebar/paragraph/ParaSpacingWindow.cxx @@ -34,6 +34,78 @@ using namespace svx; #define MAX_SC_SD 116220200 #define NEGA_MAXVALUE -10000000 +InterimItemWindow::InterimItemWindow(vcl::Window* pParent, const OUString& rUIXMLDescription, const OString& rID) + : Control(pParent, WB_TABSTOP) +{ + m_xVclContentArea = VclPtr::Create(this); + m_xVclContentArea->Show(); + m_xBuilder.reset(Application::CreateInterimBuilder(m_xVclContentArea, rUIXMLDescription)); + m_xContainer = m_xBuilder->weld_container(rID); +} + +InterimItemWindow::~InterimItemWindow() +{ + disposeOnce(); +} + +void InterimItemWindow::dispose() +{ + m_xContainer.reset(); + m_xBuilder.reset(); + m_xVclContentArea.disposeAndClear(); + + Control::dispose(); +} + +void InterimItemWindow::Resize() +{ + vcl::Window *pChild = GetWindow(GetWindowType::FirstChild); + assert(pChild); + VclContainer::setLayoutAllocation(*pChild, Point(0, 0), GetSizePixel()); + Control::Resize(); +} + +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) @@ -135,7 +207,7 @@ ParaAboveSpacingWindow::ParaAboveSpacingWindow(vcl::Window* pParent) m_xAboveContainer->show(); m_xBelowContainer->hide(); - SetSizePixel(GetOptimalSize()); + SetSizePixel(get_preferred_size()); } void ParaAboveSpacingWindow::GetFocus() @@ -151,7 +223,7 @@ ParaBelowSpacingWindow::ParaBelowSpacingWindow(vcl::Window* pParent) m_xAboveContainer->hide(); m_xBelowContainer->show(); - SetSizePixel(GetOptimalSize()); + SetSizePixel(get_preferred_size()); } void ParaBelowSpacingWindow::GetFocus() @@ -358,7 +430,7 @@ ParaLeftSpacingWindow::ParaLeftSpacingWindow(vcl::Window* pParent) m_xAfterContainer->hide(); m_xFirstLineContainer->hide(); - SetSizePixel(GetOptimalSize()); + SetSizePixel(get_preferred_size()); } void ParaLeftSpacingWindow::GetFocus() @@ -375,7 +447,7 @@ ParaRightSpacingWindow::ParaRightSpacingWindow(vcl::Window* pParent) m_xAfterContainer->show(); m_xFirstLineContainer->hide(); - SetSizePixel(GetOptimalSize()); + SetSizePixel(get_preferred_size()); } void ParaRightSpacingWindow::GetFocus() @@ -392,7 +464,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 adb697f88497..138a7c3c4e78 100644 --- a/svx/source/sidebar/paragraph/ParaSpacingWindow.hxx +++ b/svx/source/sidebar/paragraph/ParaSpacingWindow.hxx @@ -22,12 +22,9 @@ #include #include #include -#include -#include #include #include -#include -#include +#include using namespace com::sun::star; diff --git a/svx/source/tbxctrls/tbunocontroller.cxx b/svx/source/tbxctrls/tbunocontroller.cxx index 11f5cc2f2fce..7f648766bc12 100644 --- a/svx/source/tbxctrls/tbunocontroller.cxx +++ b/svx/source/tbxctrls/tbunocontroller.cxx @@ -41,6 +41,7 @@ #include #include +#include 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 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 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 @@ + + + + + + True + False + True + 6 + + + True + False + True + True + + + True + + + + + False + True + 0 + + + + -- cgit