include/vcl/weld.hxx | 16 ++ sw/source/core/crsr/DateFormFieldButton.cxx | 116 ++++------------- sw/source/core/crsr/DropDownFormFieldButton.cxx | 163 +++++++----------------- sw/source/core/crsr/FormFieldButton.cxx | 37 +++-- sw/source/core/inc/DateFormFieldButton.hxx | 15 +- sw/source/core/inc/DropDownFormFieldButton.hxx | 16 +- sw/source/core/inc/FormFieldButton.hxx | 10 - sw/uiconfig/swriter/ui/calendar.ui | 38 +++-- sw/uiconfig/swriter/ui/formdropdown.ui | 72 +++++----- vcl/inc/salvtables.hxx | 2 vcl/source/app/salvtables.cxx | 62 +++++++++ vcl/unx/gtk3/gtk3gtkinst.cxx | 120 ++++++++++++++--- 12 files changed, 369 insertions(+), 298 deletions(-)
New commits: commit a5a71c7bb58a16a64c586c3ea142e0dd88cf7104 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Thu Feb 25 17:03:31 2021 +0000 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Fri Feb 26 20:57:31 2021 +0100 drop intermediate vcl container for these welded floating toplevels Change-Id: I4a528485de62a0e0acabd41abf6872e2f0e1710e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111567 Tested-by: Caolán McNamara <caol...@redhat.com> Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx index 14c7e77b33ea..eda93398b8d6 100644 --- a/include/vcl/weld.hxx +++ b/include/vcl/weld.hxx @@ -2264,6 +2264,21 @@ public: virtual ~Menu() {} }; +class VCL_DLLPUBLIC Popover : virtual public Container +{ +private: + Link<weld::Popover&, void> m_aCloseHdl; + +protected: + void signal_closed() { m_aCloseHdl.Call(*this); } + +public: + virtual void popup_at_rect(weld::Widget* pParent, const tools::Rectangle& rRect) = 0; + virtual void popdown() = 0; + + void connect_closed(const Link<weld::Popover&, void>& rLink) { m_aCloseHdl = rLink; } +}; + class VCL_DLLPUBLIC Toolbar : virtual public Widget { protected: @@ -2383,6 +2398,7 @@ public: const OString& treeviewid) = 0; virtual std::unique_ptr<Menu> weld_menu(const OString& id) = 0; + virtual std::unique_ptr<Popover> weld_popover(const OString& id) = 0; virtual std::unique_ptr<Toolbar> weld_toolbar(const OString& id) = 0; virtual std::unique_ptr<SizeGroup> create_size_group() = 0; /* return a Dialog suitable to take a screenshot of containing the contents of the .ui file. diff --git a/sw/source/core/crsr/DateFormFieldButton.cxx b/sw/source/core/crsr/DateFormFieldButton.cxx index 2d4b66815daf..5a1bb75f7733 100644 --- a/sw/source/core/crsr/DateFormFieldButton.cxx +++ b/sw/source/core/crsr/DateFormFieldButton.cxx @@ -10,113 +10,55 @@ #include <DateFormFieldButton.hxx> #include <edtwin.hxx> #include <bookmrk.hxx> -#include <vcl/floatwin.hxx> -#include <vcl/InterimItemWindow.hxx> #include <tools/date.hxx> #include <svl/zforlist.hxx> +#include <vcl/svapp.hxx> -namespace +IMPL_LINK(DateFormFieldButton, ImplSelectHdl, weld::Calendar&, rCalendar, void) { -class SwCalendarBox final : public InterimItemWindow -{ -private: - std::unique_ptr<weld::Calendar> m_xCalendar; - -public: - SwCalendarBox(vcl::Window* pParent) - : InterimItemWindow(pParent, "modules/swriter/ui/calendar.ui", "Calendar") - , m_xCalendar(m_xBuilder->weld_calendar("date")) - { - } - weld::Calendar& get_widget() { return *m_xCalendar; } - virtual ~SwCalendarBox() override { disposeOnce(); } - virtual void dispose() override - { - m_xCalendar.reset(); - InterimItemWindow::dispose(); - } -}; - -class SwDatePickerDialog : public FloatingWindow -{ -private: - VclPtr<SwCalendarBox> m_xCalendar; - sw::mark::DateFieldmark* m_pFieldmark; - SvNumberFormatter* m_pNumberFormatter; - - DECL_LINK(ImplSelectHdl, weld::Calendar&, void); - -public: - SwDatePickerDialog(SwEditWin* parent, sw::mark::DateFieldmark* pFieldmark, - SvNumberFormatter* pNumberFormatter); - virtual ~SwDatePickerDialog() override; - virtual void dispose() override; -}; -} - -SwDatePickerDialog::SwDatePickerDialog(SwEditWin* parent, sw::mark::DateFieldmark* pFieldmark, - SvNumberFormatter* pNumberFormatter) - : FloatingWindow(parent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW) - , m_xCalendar(VclPtr<SwCalendarBox>::Create(this)) - , m_pFieldmark(pFieldmark) - , m_pNumberFormatter(pNumberFormatter) -{ - weld::Calendar& rCalendar = m_xCalendar->get_widget(); - - if (m_pFieldmark != nullptr) - { - std::pair<bool, double> aResult = m_pFieldmark->GetCurrentDate(); - if (aResult.first) - { - const Date& rNullDate = m_pNumberFormatter->GetNullDate(); - rCalendar.set_date(rNullDate + sal_Int32(aResult.second)); - } - } - - Size lbSize(rCalendar.get_preferred_size()); - - m_xCalendar->SetSizePixel(lbSize); - rCalendar.connect_activated(LINK(this, SwDatePickerDialog, ImplSelectHdl)); - m_xCalendar->Show(); - - rCalendar.grab_focus(); - - SetSizePixel(lbSize); -} - -SwDatePickerDialog::~SwDatePickerDialog() { disposeOnce(); } - -void SwDatePickerDialog::dispose() -{ - m_xCalendar.disposeAndClear(); - FloatingWindow::dispose(); -} - -IMPL_LINK(SwDatePickerDialog, ImplSelectHdl, weld::Calendar&, rCalendar, void) -{ - if (m_pFieldmark != nullptr) + if (m_pDateFieldmark) { const Date& rNullDate = m_pNumberFormatter->GetNullDate(); double dDate = rCalendar.get_date() - rNullDate; - m_pFieldmark->SetCurrentDate(dDate); + m_pDateFieldmark->SetCurrentDate(dDate); } - EndPopupMode(); + m_xFieldPopup->popdown(); } DateFormFieldButton::DateFormFieldButton(SwEditWin* pEditWin, sw::mark::DateFieldmark& rFieldmark, SvNumberFormatter* pNumberFormatter) : FormFieldButton(pEditWin, rFieldmark) , m_pNumberFormatter(pNumberFormatter) + , m_pDateFieldmark(dynamic_cast<sw::mark::DateFieldmark*>(&m_rFieldmark)) { } DateFormFieldButton::~DateFormFieldButton() { disposeOnce(); } -void DateFormFieldButton::InitPopup() +void DateFormFieldButton::LaunchPopup() +{ + m_xFieldPopupBuilder.reset( + Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/calendar.ui")); + m_xFieldPopup = m_xFieldPopupBuilder->weld_popover("Calendar"); + m_xCalendar = m_xFieldPopupBuilder->weld_calendar("date"); + if (m_pDateFieldmark) + { + std::pair<bool, double> aResult = m_pDateFieldmark->GetCurrentDate(); + if (aResult.first) + { + const Date& rNullDate = m_pNumberFormatter->GetNullDate(); + m_xCalendar->set_date(rNullDate + sal_Int32(aResult.second)); + } + } + m_xCalendar->connect_activated(LINK(this, DateFormFieldButton, ImplSelectHdl)); + FormFieldButton::LaunchPopup(); + m_xCalendar->grab_focus(); +} + +void DateFormFieldButton::DestroyPopup() { - sw::mark::DateFieldmark* pDateFieldmark = dynamic_cast<sw::mark::DateFieldmark*>(&m_rFieldmark); - m_pFieldPopup = VclPtr<SwDatePickerDialog>::Create(static_cast<SwEditWin*>(GetParent()), - pDateFieldmark, m_pNumberFormatter); + m_xCalendar.reset(); + FormFieldButton::DestroyPopup(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sw/source/core/crsr/DropDownFormFieldButton.cxx b/sw/source/core/crsr/DropDownFormFieldButton.cxx index 5a876f907f96..4dd968e7ee62 100644 --- a/sw/source/core/crsr/DropDownFormFieldButton.cxx +++ b/sw/source/core/crsr/DropDownFormFieldButton.cxx @@ -10,9 +10,6 @@ #include <DropDownFormFieldButton.hxx> #include <edtwin.hxx> #include <bookmrk.hxx> -#include <vcl/event.hxx> -#include <vcl/floatwin.hxx> -#include <vcl/InterimItemWindow.hxx> #include <vcl/settings.hxx> #include <vcl/svapp.hxx> #include <xmloff/odffields.hxx> @@ -21,146 +18,76 @@ #include <docsh.hxx> #include <strings.hrc> -namespace -{ -class SwFieldListBox final : public InterimItemWindow -{ -private: - std::unique_ptr<weld::TreeView> m_xTreeView; - -public: - SwFieldListBox(vcl::Window* pParent) - : InterimItemWindow(pParent, "modules/swriter/ui/formdropdown.ui", "FormDropDown") - , m_xTreeView(m_xBuilder->weld_tree_view("list")) - { - } - weld::TreeView& get_widget() { return *m_xTreeView; } - virtual ~SwFieldListBox() override { disposeOnce(); } - virtual void dispose() override - { - m_xTreeView.reset(); - InterimItemWindow::dispose(); - } -}; - /** * Popup dialog for drop-down form field showing the list items of the field. * The user can select the item using this popup while filling in a form. */ -class SwFieldDialog : public FloatingWindow -{ -private: - VclPtr<SwFieldListBox> m_xListBox; - sw::mark::IFieldmark* m_pFieldmark; - - DECL_LINK(MyListBoxHandler, weld::TreeView&, bool); - DECL_STATIC_LINK(SwFieldDialog, KeyInputHdl, const KeyEvent&, bool); - -public: - SwFieldDialog(SwEditWin* parent, sw::mark::IFieldmark* fieldBM, tools::Long nMinListWidth); - virtual ~SwFieldDialog() override; - virtual void dispose() override; -}; -} -SwFieldDialog::SwFieldDialog(SwEditWin* parent, sw::mark::IFieldmark* fieldBM, - tools::Long nMinListWidth) - : FloatingWindow(parent, WB_BORDER | WB_SYSTEMWINDOW) - , m_xListBox(VclPtr<SwFieldListBox>::Create(this)) - , m_pFieldmark(fieldBM) +void DropDownFormFieldButton::InitDropdown() { - weld::TreeView& rTreeView = m_xListBox->get_widget(); + const sw::mark::IFieldmark::parameter_map_t* const pParameters = m_rFieldmark.GetParameters(); + + sw::mark::IFieldmark::parameter_map_t::const_iterator pListEntries + = pParameters->find(ODF_FORMDROPDOWN_LISTENTRY); + css::uno::Sequence<OUString> vListEntries; + if (pListEntries != pParameters->end()) + { + pListEntries->second >>= vListEntries; + for (OUString const& i : std::as_const(vListEntries)) + m_xTreeView->append_text(i); + } + + if (!vListEntries.hasElements()) + { + m_xTreeView->append_text(SwResId(STR_DROP_DOWN_EMPTY_LIST)); + } - if (fieldBM != nullptr) + // Select the current one + sw::mark::IFieldmark::parameter_map_t::const_iterator pResult + = pParameters->find(ODF_FORMDROPDOWN_RESULT); + if (pResult != pParameters->end()) { - const sw::mark::IFieldmark::parameter_map_t* const pParameters = fieldBM->GetParameters(); - - sw::mark::IFieldmark::parameter_map_t::const_iterator pListEntries - = pParameters->find(ODF_FORMDROPDOWN_LISTENTRY); - css::uno::Sequence<OUString> vListEntries; - if (pListEntries != pParameters->end()) - { - pListEntries->second >>= vListEntries; - for (OUString const& i : std::as_const(vListEntries)) - rTreeView.append_text(i); - } - - if (!vListEntries.hasElements()) - { - rTreeView.append_text(SwResId(STR_DROP_DOWN_EMPTY_LIST)); - } - - // Select the current one - sw::mark::IFieldmark::parameter_map_t::const_iterator pResult - = pParameters->find(ODF_FORMDROPDOWN_RESULT); - if (pResult != pParameters->end()) - { - sal_Int32 nSelection = -1; - pResult->second >>= nSelection; - rTreeView.set_cursor(nSelection); - rTreeView.select(nSelection); - } + sal_Int32 nSelection = -1; + pResult->second >>= nSelection; + m_xTreeView->set_cursor(nSelection); + m_xTreeView->select(nSelection); } - auto nHeight = rTreeView.get_height_rows( + auto nHeight = m_xTreeView->get_height_rows( std::min<int>(Application::GetSettings().GetStyleSettings().GetListBoxMaximumLineCount(), - rTreeView.n_children())); - rTreeView.set_size_request(-1, nHeight); - Size lbSize(rTreeView.get_preferred_size()); + m_xTreeView->n_children())); + m_xTreeView->set_size_request(-1, nHeight); + Size lbSize(m_xTreeView->get_preferred_size()); lbSize.AdjustWidth(4); lbSize.AdjustHeight(4); + auto nMinListWidth = GetSizePixel().Width(); lbSize.setWidth(std::max(lbSize.Width(), nMinListWidth)); - m_xListBox->SetSizePixel(lbSize); - rTreeView.connect_row_activated(LINK(this, SwFieldDialog, MyListBoxHandler)); - rTreeView.connect_key_press(LINK(this, SwFieldDialog, KeyInputHdl)); - m_xListBox->Show(); - - rTreeView.grab_focus(); - - SetSizePixel(lbSize); -} - -SwFieldDialog::~SwFieldDialog() { disposeOnce(); } - -void SwFieldDialog::dispose() -{ - m_xListBox.disposeAndClear(); - FloatingWindow::dispose(); + m_xTreeView->set_size_request(lbSize.Width(), lbSize.Height()); } -IMPL_LINK(SwFieldDialog, MyListBoxHandler, weld::TreeView&, rBox, bool) +IMPL_LINK(DropDownFormFieldButton, MyListBoxHandler, weld::TreeView&, rBox, bool) { OUString sSelection = rBox.get_selected_text(); if (sSelection == SwResId(STR_DROP_DOWN_EMPTY_LIST)) { - EndPopupMode(); + m_xFieldPopup->popdown(); return true; } sal_Int32 nSelection = rBox.get_selected_index(); if (nSelection >= 0) { - (*m_pFieldmark->GetParameters())[ODF_FORMDROPDOWN_RESULT] <<= nSelection; - m_pFieldmark->Invalidate(); + (*m_rFieldmark.GetParameters())[ODF_FORMDROPDOWN_RESULT] <<= nSelection; + m_rFieldmark.Invalidate(); SwView& rView = static_cast<SwEditWin*>(GetParent())->GetView(); rView.GetDocShell()->SetModified(); } - EndPopupMode(); + m_xFieldPopup->popdown(); return true; } -IMPL_STATIC_LINK(SwFieldDialog, KeyInputHdl, const KeyEvent&, rKeyEvent, bool) -{ - bool bDone = false; - vcl::KeyCode aCode = rKeyEvent.GetKeyCode(); - // nowhere to tab to - if (aCode.GetCode() == KEY_TAB) - bDone = true; - return bDone; -} - DropDownFormFieldButton::DropDownFormFieldButton(SwEditWin* pEditWin, sw::mark::DropDownFieldmark& rFieldmark) : FormFieldButton(pEditWin, rFieldmark) @@ -169,10 +96,22 @@ DropDownFormFieldButton::DropDownFormFieldButton(SwEditWin* pEditWin, DropDownFormFieldButton::~DropDownFormFieldButton() { disposeOnce(); } -void DropDownFormFieldButton::InitPopup() +void DropDownFormFieldButton::LaunchPopup() +{ + m_xFieldPopupBuilder.reset( + Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/formdropdown.ui")); + m_xFieldPopup = m_xFieldPopupBuilder->weld_popover("FormDropDown"); + m_xTreeView = m_xFieldPopupBuilder->weld_tree_view("list"); + InitDropdown(); + m_xTreeView->connect_row_activated(LINK(this, DropDownFormFieldButton, MyListBoxHandler)); + FormFieldButton::LaunchPopup(); + m_xTreeView->grab_focus(); +} + +void DropDownFormFieldButton::DestroyPopup() { - m_pFieldPopup = VclPtr<SwFieldDialog>::Create(static_cast<SwEditWin*>(GetParent()), - &m_rFieldmark, GetSizePixel().Width()); + m_xTreeView.reset(); + FormFieldButton::DestroyPopup(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sw/source/core/crsr/FormFieldButton.cxx b/sw/source/core/crsr/FormFieldButton.cxx index 8ae84826a3f9..0f13494b648e 100644 --- a/sw/source/core/crsr/FormFieldButton.cxx +++ b/sw/source/core/crsr/FormFieldButton.cxx @@ -11,7 +11,7 @@ #include <edtwin.hxx> #include <basegfx/color/bcolortools.hxx> #include <bookmrk.hxx> -#include <vcl/floatwin.hxx> +#include <vcl/weldutils.hxx> #include <vcl/event.hxx> FormFieldButton::FormFieldButton(SwEditWin* pEditWin, sw::mark::Fieldmark& rFieldmark) @@ -29,9 +29,24 @@ FormFieldButton::FormFieldButton(SwEditWin* pEditWin, sw::mark::Fieldmark& rFiel FormFieldButton::~FormFieldButton() { disposeOnce(); } +void FormFieldButton::LaunchPopup() +{ + m_xFieldPopup->connect_closed(LINK(this, DropDownFormFieldButton, FieldPopupModeEndHdl)); + + tools::Rectangle aRect(Point(0, 0), GetSizePixel()); + weld::Window* pParent = weld::GetPopupParent(*this, aRect); + m_xFieldPopup->popup_at_rect(pParent, aRect); +} + +void FormFieldButton::DestroyPopup() +{ + m_xFieldPopup.reset(); + m_xFieldPopupBuilder.reset(); +} + void FormFieldButton::dispose() { - m_pFieldPopup.disposeAndClear(); + DestroyPopup(); Control::dispose(); } @@ -63,23 +78,13 @@ void FormFieldButton::CalcPosAndSize(const SwRect& rPortionPaintArea) void FormFieldButton::MouseButtonDown(const MouseEvent&) { - assert(GetParent()); - - // sets m_pFieldPopup - InitPopup(); - - m_pFieldPopup->SetPopupModeEndHdl(LINK(this, DropDownFormFieldButton, FieldPopupModeEndHdl)); - - Size aSize = GetSizePixel(); - Point aPos(GetParent()->OutputToScreenPixel(GetPosPixel())); - tools::Rectangle aRect(aPos, aSize); - m_pFieldPopup->StartPopupMode(aRect, FloatWinPopupFlags::Down | FloatWinPopupFlags::GrabFocus); + LaunchPopup(); Invalidate(); } -IMPL_LINK_NOARG(FormFieldButton, FieldPopupModeEndHdl, FloatingWindow*, void) +IMPL_LINK_NOARG(FormFieldButton, FieldPopupModeEndHdl, weld::Popover&, void) { - m_pFieldPopup.disposeAndClear(); + DestroyPopup(); m_rFieldmark.Invalidate(); // Hide the button here and make it visible later, to make transparent background work with SAL_USE_VCLPLUGIN=gen Show(false); @@ -99,7 +104,7 @@ void FormFieldButton::Paint(vcl::RenderContext& rRenderContext, const tools::Rec //const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); Color aLineColor = COL_BLACK; - Color aFillColor(lcl_GetFillColor(aLineColor.getBColor(), (m_pFieldPopup ? 0.5 : 0.75))); + Color aFillColor(lcl_GetFillColor(aLineColor.getBColor(), (m_xFieldPopup ? 0.5 : 0.75))); // Draw the frame around the field // GTK3 backend cuts down the frame's top and left border, to avoid that add a padding around the frame diff --git a/sw/source/core/inc/DateFormFieldButton.hxx b/sw/source/core/inc/DateFormFieldButton.hxx index 60aad2777aba..a03bfc9117be 100644 --- a/sw/source/core/inc/DateFormFieldButton.hxx +++ b/sw/source/core/inc/DateFormFieldButton.hxx @@ -13,7 +13,6 @@ #include "FormFieldButton.hxx" class SwEditWin; -class FloatingWindow; class SvNumberFormatter; namespace sw::mark { @@ -26,15 +25,21 @@ class DateFieldmark; */ class DateFormFieldButton : public FormFieldButton { +private: + SvNumberFormatter* m_pNumberFormatter; + sw::mark::DateFieldmark* m_pDateFieldmark; + + std::unique_ptr<weld::Calendar> m_xCalendar; + + DECL_LINK(ImplSelectHdl, weld::Calendar&, void); + public: DateFormFieldButton(SwEditWin* pEditWin, sw::mark::DateFieldmark& rFieldMark, SvNumberFormatter* pNumberFormatter); virtual ~DateFormFieldButton() override; - virtual void InitPopup() override; - -private: - SvNumberFormatter* m_pNumberFormatter; + virtual void LaunchPopup() override; + virtual void DestroyPopup() override; }; #endif diff --git a/sw/source/core/inc/DropDownFormFieldButton.hxx b/sw/source/core/inc/DropDownFormFieldButton.hxx index ffaa2af2d2b8..9853c57a3116 100644 --- a/sw/source/core/inc/DropDownFormFieldButton.hxx +++ b/sw/source/core/inc/DropDownFormFieldButton.hxx @@ -7,13 +7,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef INCLUDED_SW_SOURCE_CORE_TEXT_DROPDOWNFORMEFIELDBUTTO_HXX -#define INCLUDED_SW_SOURCE_CORE_TEXT_DROPDOWNFORMEFIELDBUTTO_HXX +#pragma once #include "FormFieldButton.hxx" class SwEditWin; -class FloatingWindow; namespace sw::mark { class DropDownFieldmark; @@ -25,13 +23,19 @@ class DropDownFieldmark; */ class DropDownFormFieldButton : public FormFieldButton { +private: + std::unique_ptr<weld::TreeView> m_xTreeView; + + DECL_LINK(MyListBoxHandler, weld::TreeView&, bool); + + void InitDropdown(); + public: DropDownFormFieldButton(SwEditWin* pEditWin, sw::mark::DropDownFieldmark& rFieldMark); virtual ~DropDownFormFieldButton() override; - virtual void InitPopup() override; + virtual void LaunchPopup() override; + virtual void DestroyPopup() override; }; -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sw/source/core/inc/FormFieldButton.hxx b/sw/source/core/inc/FormFieldButton.hxx index 4dec3b752d13..22a9b3e8c7b0 100644 --- a/sw/source/core/inc/FormFieldButton.hxx +++ b/sw/source/core/inc/FormFieldButton.hxx @@ -10,10 +10,10 @@ #pragma once #include <vcl/ctrl.hxx> +#include <vcl/weld.hxx> #include <swrect.hxx> class SwEditWin; -class FloatingWindow; namespace sw::mark { class Fieldmark; @@ -32,19 +32,21 @@ public: void CalcPosAndSize(const SwRect& rPortionPaintArea); virtual void MouseButtonDown(const MouseEvent& rMEvt) override; - DECL_LINK(FieldPopupModeEndHdl, FloatingWindow*, void); + DECL_LINK(FieldPopupModeEndHdl, weld::Popover&, void); virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; virtual WindowHitTest ImplHitTest(const Point& rFramePos) override; - virtual void InitPopup() = 0; + virtual void LaunchPopup(); + virtual void DestroyPopup(); private: tools::Rectangle m_aFieldFramePixel; protected: sw::mark::Fieldmark& m_rFieldmark; - VclPtr<FloatingWindow> m_pFieldPopup; + std::unique_ptr<weld::Builder> m_xFieldPopupBuilder; + std::unique_ptr<weld::Popover> m_xFieldPopup; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sw/uiconfig/swriter/ui/calendar.ui b/sw/uiconfig/swriter/ui/calendar.ui index 760309ac0009..5c8d3eb43bfd 100644 --- a/sw/uiconfig/swriter/ui/calendar.ui +++ b/sw/uiconfig/swriter/ui/calendar.ui @@ -1,25 +1,31 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.22.2 --> +<!-- Generated with glade 3.38.2 --> <interface domain="sw"> <requires lib="gtk+" version="3.20"/> - <object class="GtkBox" id="Calendar"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">6</property> + <object class="GtkPopover" id="Calendar"> + <property name="can-focus">False</property> + <property name="position">bottom</property> <child> - <object class="GtkCalendar" id="date"> + <object class="GtkBox"> <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="year">2019</property> - <property name="month">1</property> - <property name="day">14</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkCalendar" id="date"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="year">2019</property> + <property name="month">1</property> + <property name="day">14</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </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/sw/uiconfig/swriter/ui/formdropdown.ui b/sw/uiconfig/swriter/ui/formdropdown.ui index 9a35356a9770..8863f52659e3 100644 --- a/sw/uiconfig/swriter/ui/formdropdown.ui +++ b/sw/uiconfig/swriter/ui/formdropdown.ui @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.22.2 --> +<!-- Generated with glade 3.38.2 --> <interface domain="sw"> <requires lib="gtk+" version="3.20"/> <object class="GtkTreeStore" id="liststore1"> @@ -10,53 +10,59 @@ <column type="gchararray"/> </columns> </object> - <object class="GtkBox" id="FormDropDown"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="hexpand">True</property> - <property name="vexpand">True</property> - <property name="orientation">vertical</property> - <property name="spacing">6</property> + <object class="GtkPopover" id="FormDropDown"> + <property name="can-focus">False</property> + <property name="position">bottom</property> <child> - <object class="GtkScrolledWindow"> + <object class="GtkBox"> <property name="visible">True</property> - <property name="can_focus">True</property> + <property name="can-focus">False</property> <property name="hexpand">True</property> <property name="vexpand">True</property> - <property name="hscrollbar_policy">never</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> <child> - <object class="GtkTreeView" id="list"> + <object class="GtkScrolledWindow"> <property name="visible">True</property> - <property name="can_focus">True</property> + <property name="can-focus">True</property> + <property name="hexpand">True</property> <property name="vexpand">True</property> - <property name="model">liststore1</property> - <property name="headers_visible">False</property> - <property name="headers_clickable">False</property> - <property name="search_column">0</property> - <property name="hover_selection">True</property> - <property name="show_expanders">False</property> - <property name="activate_on_single_click">True</property> - <child internal-child="selection"> - <object class="GtkTreeSelection" id="treeview-selection1"/> - </child> + <property name="hscrollbar-policy">never</property> <child> - <object class="GtkTreeViewColumn" id="treeviewcolumn1"> + <object class="GtkTreeView" id="list"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="vexpand">True</property> + <property name="model">liststore1</property> + <property name="headers-visible">False</property> + <property name="headers-clickable">False</property> + <property name="search-column">0</property> + <property name="hover-selection">True</property> + <property name="show-expanders">False</property> + <property name="activate-on-single-click">True</property> + <child internal-child="selection"> + <object class="GtkTreeSelection"/> + </child> <child> - <object class="GtkCellRendererText" id="cellrenderertext1"/> - <attributes> - <attribute name="text">0</attribute> - </attributes> + <object class="GtkTreeViewColumn" id="treeviewcolumn1"> + <child> + <object class="GtkCellRendererText" id="cellrenderertext1"/> + <attributes> + <attribute name="text">0</attribute> + </attributes> + </child> + </object> </child> </object> </child> </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> </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/inc/salvtables.hxx b/vcl/inc/salvtables.hxx index b8c5888572d0..4322cb242b1b 100644 --- a/vcl/inc/salvtables.hxx +++ b/vcl/inc/salvtables.hxx @@ -121,6 +121,8 @@ public: virtual std::unique_ptr<weld::Menu> weld_menu(const OString& id) override; + virtual std::unique_ptr<weld::Popover> weld_popover(const OString& id) override; + virtual std::unique_ptr<weld::Toolbar> weld_toolbar(const OString& id) override; virtual std::unique_ptr<weld::SizeGroup> create_size_group() override; diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 7bb05907ecba..6c86215bd808 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -6611,6 +6611,54 @@ IMPL_LINK(SalInstanceEntryTreeView, AutocompleteHdl, Edit&, rEdit, void) } } +namespace +{ +class SalInstancePopover : public SalInstanceContainer, public virtual weld::Popover +{ +private: + VclPtr<DockingWindow> m_xPopover; + + DECL_LINK(PopupModeEndHdl, FloatingWindow*, void); + +public: + SalInstancePopover(DockingWindow* pPopover, SalInstanceBuilder* pBuilder, bool bTakeOwnership) + : SalInstanceContainer(pPopover, pBuilder, bTakeOwnership) + , m_xPopover(pPopover) + { + } + + virtual void popup_at_rect(weld::Widget* pParent, const tools::Rectangle& rRect) override + { + SalInstanceWidget* pVclWidget = dynamic_cast<SalInstanceWidget*>(pParent); + assert(pVclWidget); + vcl::Window* pWidget = pVclWidget->getWidget(); + + tools::Rectangle aRect; + Point aPt = pWidget->OutputToScreenPixel(rRect.TopLeft()); + aRect.SetLeft(aPt.X()); + aRect.SetTop(aPt.Y()); + aPt = pWidget->OutputToScreenPixel(rRect.BottomRight()); + aRect.SetRight(aPt.X()); + aRect.SetBottom(aPt.Y()); + + FloatWinPopupFlags nFlags = FloatWinPopupFlags::Down | FloatWinPopupFlags::GrabFocus; + m_xPopover->EnableDocking(); + DockingManager* pDockingManager = vcl::Window::GetDockingManager(); + pDockingManager->SetPopupModeEndHdl(m_xPopover, + LINK(this, SalInstancePopover, PopupModeEndHdl)); + pDockingManager->StartPopupMode(m_xPopover, aRect, nFlags); + } + + virtual void popdown() override + { + vcl::Window::GetDockingManager()->EndPopupMode(m_xPopover); + m_xPopover->EnableDocking(false); + } +}; +} + +IMPL_LINK_NOARG(SalInstancePopover, PopupModeEndHdl, FloatingWindow*, void) { signal_closed(); } + SalInstanceBuilder::SalInstanceBuilder(vcl::Window* pParent, const OUString& rUIRoot, const OUString& rUIFile, const css::uno::Reference<css::frame::XFrame>& rFrame) @@ -6922,6 +6970,20 @@ std::unique_ptr<weld::Menu> SalInstanceBuilder::weld_menu(const OString& id) return pMenu ? std::make_unique<SalInstanceMenu>(pMenu, true) : nullptr; } +std::unique_ptr<weld::Popover> SalInstanceBuilder::weld_popover(const OString& id) +{ + DockingWindow* pDockingWindow = m_xBuilder->get<DockingWindow>(id); + std::unique_ptr<weld::Popover> pRet( + pDockingWindow ? new SalInstancePopover(pDockingWindow, this, false) : nullptr); + if (pDockingWindow) + { + assert(!m_aOwnedToplevel && "only one toplevel per .ui allowed"); + m_aOwnedToplevel.set(pDockingWindow); + m_xBuilder->drop_ownership(pDockingWindow); + } + return pRet; +} + std::unique_ptr<weld::Toolbar> SalInstanceBuilder::weld_toolbar(const OString& id) { ToolBox* pToolBox = m_xBuilder->get<ToolBox>(id); diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index 1c9e284be0c3..682f4ebe757f 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -1754,6 +1754,30 @@ namespace return AllSettings::GetLayoutRTL(); } + GtkWidget* getPopupRect(GtkWidget* pWidget, const tools::Rectangle& rInRect, GdkRectangle& rOutRect) + { + if (GtkSalFrame* pFrame = GtkSalFrame::getFromWindow(pWidget)) + { + // this is the relatively unusual case where pParent is the toplevel GtkSalFrame and not a stock GtkWidget + // so use the same style of logic as GtkSalMenu::ShowNativePopupMenu to get the right position + tools::Rectangle aFloatRect = FloatingWindow::ImplConvertToAbsPos(pFrame->GetWindow(), rInRect); + aFloatRect.Move(-pFrame->maGeometry.nX, -pFrame->maGeometry.nY); + + rOutRect = GdkRectangle{static_cast<int>(aFloatRect.Left()), static_cast<int>(aFloatRect.Top()), + static_cast<int>(aFloatRect.GetWidth()), static_cast<int>(aFloatRect.GetHeight())}; + + pWidget = pFrame->getMouseEventWidget(); + } + else + { + rOutRect = GdkRectangle{static_cast<int>(rInRect.Left()), static_cast<int>(rInRect.Top()), + static_cast<int>(rInRect.GetWidth()), static_cast<int>(rInRect.GetHeight())}; + if (SwapForRTL(pWidget)) + rOutRect.x = gtk_widget_get_allocated_width(pWidget) - rOutRect.width - 1 - rOutRect.x; + } + return pWidget; + } + void replaceWidget(GtkWidget* pWidget, GtkWidget* pReplacement) { // remove the widget and replace it with pReplacement @@ -8150,25 +8174,7 @@ public: if (gtk_check_version(3, 22, 0) == nullptr) { GdkRectangle aRect; - if (GtkSalFrame* pFrame = GtkSalFrame::getFromWindow(pWidget)) - { - // this is the relatively unusual case where pParent is the toplevel GtkSalFrame and not a stock GtkWidget - // so use the same style of logic as GtkSalMenu::ShowNativePopupMenu to get the right position - tools::Rectangle aFloatRect = FloatingWindow::ImplConvertToAbsPos(pFrame->GetWindow(), rRect); - aFloatRect.Move(-pFrame->maGeometry.nX, -pFrame->maGeometry.nY); - - aRect = GdkRectangle{static_cast<int>(aFloatRect.Left()), static_cast<int>(aFloatRect.Top()), - static_cast<int>(aFloatRect.GetWidth()), static_cast<int>(aFloatRect.GetHeight())}; - - pWidget = pFrame->getMouseEventWidget(); - } - else - { - aRect = GdkRectangle{static_cast<int>(rRect.Left()), static_cast<int>(rRect.Top()), - static_cast<int>(rRect.GetWidth()), static_cast<int>(rRect.GetHeight())}; - if (SwapForRTL(pWidget)) - aRect.x = gtk_widget_get_allocated_width(pWidget) - aRect.width - 1 - aRect.x; - } + pWidget = getPopupRect(pWidget, rRect, aRect); // Send a keyboard event through gtk_main_do_event to toggle any active tooltip offs // before trying to launch the menu @@ -16579,6 +16585,74 @@ public: return false; } + +class GtkInstancePopover : public GtkInstanceContainer, public virtual weld::Popover +{ +private: + GtkPopover* m_pPopover; + gulong m_nSignalId; + ImplSVEvent* m_pClosedEvent; + + static void signalClosed(GtkPopover*, gpointer widget) + { + GtkInstancePopover* pThis = static_cast<GtkInstancePopover*>(widget); + // call signal-closed async so the closed callback isn't called + // whilc the GtkPopover handler is still in-execution + pThis->launch_signal_closed(); + } + + DECL_LINK(async_signal_closed, void*, void); + + void launch_signal_closed() + { + if (m_pClosedEvent) + Application::RemoveUserEvent(m_pClosedEvent); + m_pClosedEvent = Application::PostUserEvent(LINK(this, GtkInstancePopover, async_signal_closed)); + } + +public: + GtkInstancePopover(GtkPopover* pPopover, GtkInstanceBuilder* pBuilder, bool bTakeOwnership) + : GtkInstanceContainer(GTK_CONTAINER(pPopover), pBuilder, bTakeOwnership) + , m_pPopover(pPopover) + , m_nSignalId(g_signal_connect(m_pPopover, "closed", G_CALLBACK(signalClosed), this)) + , m_pClosedEvent(nullptr) + { + } + + virtual void popup_at_rect(weld::Widget* pParent, const tools::Rectangle& rRect) override + { + GtkInstanceWidget* pGtkWidget = dynamic_cast<GtkInstanceWidget*>(pParent); + assert(pGtkWidget); + + GtkWidget* pWidget = pGtkWidget->getWidget(); + + GdkRectangle aRect; + pWidget = getPopupRect(pWidget, rRect, aRect); + + gtk_popover_set_relative_to(m_pPopover, pWidget); + gtk_popover_set_pointing_to(m_pPopover, &aRect); + gtk_popover_popup(m_pPopover); + } + + virtual void popdown() override + { + gtk_popover_popdown(m_pPopover); + } + + virtual ~GtkInstancePopover() override + { + if (m_pClosedEvent) + Application::RemoveUserEvent(m_pClosedEvent); + g_signal_handler_disconnect(m_pPopover, m_nSignalId); + } +}; + +IMPL_LINK_NOARG(GtkInstancePopover, async_signal_closed, void*, void) +{ + m_pClosedEvent = nullptr; + signal_closed(); +} + } namespace @@ -17375,6 +17449,14 @@ public: return std::make_unique<GtkInstanceMenu>(pMenu, true); } + virtual std::unique_ptr<weld::Popover> weld_popover(const OString &id) override + { + GtkPopover* pPopover = GTK_POPOVER(gtk_builder_get_object(m_pBuilder, id.getStr())); + if (!pPopover) + return nullptr; + return std::make_unique<GtkInstancePopover>(pPopover, this, true); + } + virtual std::unique_ptr<weld::Toolbar> weld_toolbar(const OString &id) override { GtkToolbar* pToolbar = GTK_TOOLBAR(gtk_builder_get_object(m_pBuilder, id.getStr())); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits