summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/vcl/weld.hxx16
-rw-r--r--sw/source/core/crsr/DateFormFieldButton.cxx116
-rw-r--r--sw/source/core/crsr/DropDownFormFieldButton.cxx163
-rw-r--r--sw/source/core/crsr/FormFieldButton.cxx37
-rw-r--r--sw/source/core/inc/DateFormFieldButton.hxx15
-rw-r--r--sw/source/core/inc/DropDownFormFieldButton.hxx16
-rw-r--r--sw/source/core/inc/FormFieldButton.hxx10
-rw-r--r--sw/uiconfig/swriter/ui/calendar.ui38
-rw-r--r--sw/uiconfig/swriter/ui/formdropdown.ui72
-rw-r--r--vcl/inc/salvtables.hxx2
-rw-r--r--vcl/source/app/salvtables.cxx62
-rw-r--r--vcl/unx/gtk3/gtk3gtkinst.cxx120
12 files changed, 369 insertions, 298 deletions
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()));