From e7950b8e8f7f4a52a841a5f1ebfedc68be3454ea Mon Sep 17 00:00:00 2001 From: Caolán McNamara Date: Fri, 16 Jul 2021 17:26:23 +0100 Subject: tdf#143357 use a DateFormatter and a separate Calendar menubutton similar to what we ended up with in DateControl in svtools/source/brwbox/ebbcontrols.cxx Change-Id: I37c843ff7e1e8e39b318db80fe590ce5f796f46a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120453 Tested-by: Jenkins Reviewed-by: Adolfo Jayme Barrientos --- extensions/source/propctrlr/propcontroller.cxx | 4 +- extensions/source/propctrlr/standardcontrol.cxx | 57 +++++++++++++++++++++---- extensions/source/propctrlr/standardcontrol.hxx | 23 ++++++++-- extensions/uiconfig/spropctrlr/ui/datefield.ui | 43 +++++++++++++++---- include/svtools/ctrlbox.hxx | 4 +- solenv/sanitizers/ui/modules/spropctrlr.suppr | 2 + svtools/source/control/ctrlbox.cxx | 7 ++- 7 files changed, 115 insertions(+), 25 deletions(-) diff --git a/extensions/source/propctrlr/propcontroller.cxx b/extensions/source/propctrlr/propcontroller.cxx index d9166b64dff6..a24384459d7d 100644 --- a/extensions/source/propctrlr/propcontroller.cxx +++ b/extensions/source/propctrlr/propcontroller.cxx @@ -754,8 +754,8 @@ namespace pcr case PropertyControlType::DateField: { std::unique_ptr xBuilder(PropertyHandlerHelper::makeBuilder("modules/spropctrlr/ui/datefield.ui", m_xContext)); - auto pMenuButton = xBuilder->weld_menu_button("datefield"); - rtl::Reference pControl = new ODateControl(std::make_unique(std::move(pMenuButton)), std::move(xBuilder), bCreateReadOnly); + auto pContainer = xBuilder->weld_container("datefield"); + rtl::Reference pControl = new ODateControl(std::move(pContainer), std::move(xBuilder), bCreateReadOnly); pControl->SetModifyHandler(); xControl = pControl; break; diff --git a/extensions/source/propctrlr/standardcontrol.cxx b/extensions/source/propctrlr/standardcontrol.cxx index 7cbca1c276b4..584c66889348 100644 --- a/extensions/source/propctrlr/standardcontrol.cxx +++ b/extensions/source/propctrlr/standardcontrol.cxx @@ -90,34 +90,75 @@ namespace pcr } //= ODateControl - ODateControl::ODateControl(std::unique_ptr xWidget, std::unique_ptr xBuilder, bool bReadOnly) + ODateControl::ODateControl(std::unique_ptr xWidget, std::unique_ptr xBuilder, bool bReadOnly) : ODateControl_Base(PropertyControlType::DateField, std::move(xBuilder), std::move(xWidget), bReadOnly) + , m_xEntry(m_xBuilder->weld_entry("entry")) + , m_xCalendarBox(std::make_unique(m_xBuilder->weld_menu_button("button"), false)) { + m_xEntryFormatter.reset(new weld::DateFormatter(*m_xEntry)); + + m_xEntryFormatter->SetStrictFormat(true); + m_xEntryFormatter->SetMin(::Date(1, 1, 1600)); + m_xEntryFormatter->SetMax(::Date(1, 1, 9999)); + + m_xEntryFormatter->SetExtDateFormat(ExtDateFieldFormat::SystemShortYYYY); + m_xEntryFormatter->EnableEmptyField(true); + + m_xCalendarBox->connect_activated(LINK(this, ODateControl, ActivateHdl)); + + m_xCalendarBox->get_button().connect_toggled(LINK(this, ODateControl, ToggleHdl)); } - void SAL_CALL ODateControl::setValue( const Any& _rValue ) + void SAL_CALL ODateControl::disposing() { - SvtCalendarBox* pCalendarBox = getTypedControlWindow(); + m_xEntryFormatter.reset(); + m_xEntry.reset(); + m_xCalendarBox.reset(); + ODateControl_Base::disposing(); + } + void SAL_CALL ODateControl::setValue( const Any& _rValue ) + { util::Date aUNODate; if ( !( _rValue >>= aUNODate ) ) { - pCalendarBox->set_date(::Date(::Date::SYSTEM)); - pCalendarBox->set_label(""); + m_xEntry->set_text(OUString()); } else { ::Date aDate( aUNODate.Day, aUNODate.Month, aUNODate.Year ); - pCalendarBox->set_date(aDate); + m_xEntryFormatter->SetDate(aDate); } } + IMPL_LINK_NOARG(ODateControl, ActivateHdl, SvtCalendarBox&, void) + { + m_xEntryFormatter->SetDate(m_xCalendarBox->get_date()); + setModified(); + m_xEntry->grab_focus(); + } + + IMPL_LINK(ODateControl, ToggleHdl, weld::Toggleable&, rToggle, void) + { + if (!rToggle.get_active()) + return; + ::Date aDate = m_xEntryFormatter->GetDate(); + if (aDate.IsEmpty()) + { + // with an empty date preselect today in the calendar + aDate = ::Date(::Date::SYSTEM); + } + m_xCalendarBox->set_date(aDate); + } + Any SAL_CALL ODateControl::getValue() { Any aPropValue; - ::Date aDate(getTypedControlWindow()->get_date()); - if (!aDate.IsEmpty()) + if (!m_xEntry->get_text().isEmpty()) + { + ::Date aDate(m_xEntryFormatter->GetDate()); aPropValue <<= aDate.GetUNODate(); + } return aPropValue; } diff --git a/extensions/source/propctrlr/standardcontrol.hxx b/extensions/source/propctrlr/standardcontrol.hxx index 4463ed1038bf..a54af78c3a3a 100644 --- a/extensions/source/propctrlr/standardcontrol.hxx +++ b/extensions/source/propctrlr/standardcontrol.hxx @@ -60,11 +60,18 @@ namespace pcr }; //= ODateControl - typedef CommonBehaviourControl ODateControl_Base; + typedef CommonBehaviourControl ODateControl_Base; class ODateControl : public ODateControl_Base { + std::unique_ptr m_xEntry; + std::unique_ptr m_xCalendarBox; + std::unique_ptr m_xEntryFormatter; + + DECL_LINK(ActivateHdl, SvtCalendarBox&, void); + DECL_LINK(ToggleHdl, weld::Toggleable&, void); + public: - ODateControl(std::unique_ptr xWidget, std::unique_ptr xBuilder, bool bReadOnly); + ODateControl(std::unique_ptr xWidget, std::unique_ptr xBuilder, bool bReadOnly); // XPropertyControl virtual css::uno::Any SAL_CALL getValue() override; @@ -74,10 +81,18 @@ namespace pcr virtual void SetModifyHandler() override { ODateControl_Base::SetModifyHandler(); - getTypedControlWindow()->connect_selected( LINK( this, CommonBehaviourControlHelper, DateModifiedHdl ) ); + + m_xEntry->connect_focus_in( LINK( this, CommonBehaviourControlHelper, GetFocusHdl ) ); + m_xEntryFormatter->connect_focus_out( LINK( this, CommonBehaviourControlHelper, LoseFocusHdl ) ); + m_xCalendarBox->connect_focus_in( LINK( this, CommonBehaviourControlHelper, GetFocusHdl ) ); + m_xCalendarBox->connect_focus_out( LINK( this, CommonBehaviourControlHelper, LoseFocusHdl ) ); + + m_xEntryFormatter->connect_changed(LINK(this, CommonBehaviourControlHelper, EditModifiedHdl)); } - virtual weld::Widget* getWidget() override { return &getTypedControlWindow()->get_button(); } + virtual void SAL_CALL disposing() override; + + virtual weld::Widget* getWidget() override { return getTypedControlWindow(); } }; //= OEditControl diff --git a/extensions/uiconfig/spropctrlr/ui/datefield.ui b/extensions/uiconfig/spropctrlr/ui/datefield.ui index e064f618bfd5..02fdbc54e253 100644 --- a/extensions/uiconfig/spropctrlr/ui/datefield.ui +++ b/extensions/uiconfig/spropctrlr/ui/datefield.ui @@ -1,17 +1,44 @@ - + - + True - True - True - False + False + x-office-calendar + 2 + + + True + False True - True - + 6 + + + True + True + True + + + False + True + 0 + + - + + True + True + True + image7 + 1 + True + + + False + True + 1 + diff --git a/include/svtools/ctrlbox.hxx b/include/svtools/ctrlbox.hxx index eda2f1cd08dc..e58f3ede418e 100644 --- a/include/svtools/ctrlbox.hxx +++ b/include/svtools/ctrlbox.hxx @@ -291,7 +291,7 @@ private: class SVT_DLLPUBLIC SvtCalendarBox { public: - SvtCalendarBox(std::unique_ptr pControl); + SvtCalendarBox(std::unique_ptr pControl, bool bUseLabel = true); ~SvtCalendarBox(); weld::MenuButton& get_button() { return *m_xControl; } @@ -317,6 +317,8 @@ private: DECL_LINK(SelectHdl, weld::Calendar&, void); DECL_LINK(ActivateHdl, weld::Calendar&, void); + bool m_bUseLabel; + std::unique_ptr m_xControl; std::unique_ptr m_xBuilder; std::unique_ptr m_xTopLevel; diff --git a/solenv/sanitizers/ui/modules/spropctrlr.suppr b/solenv/sanitizers/ui/modules/spropctrlr.suppr index 466a32974a5d..5a7ccb3e54a8 100644 --- a/solenv/sanitizers/ui/modules/spropctrlr.suppr +++ b/solenv/sanitizers/ui/modules/spropctrlr.suppr @@ -1,4 +1,6 @@ extensions/uiconfig/spropctrlr/ui/browserline.ui://GtkLabel[@id='label'] orphan-label +extensions/uiconfig/spropctrlr/ui/datefield.ui://GtkEntry[@id='entry'] no-labelled-by +extensions/uiconfig/spropctrlr/ui/datefield.ui://GtkMenuButton[@id='button'] button-no-label extensions/uiconfig/spropctrlr/ui/datetimefield.ui://GtkSpinButton[@id='timefield'] no-labelled-by extensions/uiconfig/spropctrlr/ui/formattedcontrol.ui://GtkSpinButton[@id='formattedcontrol'] no-labelled-by extensions/uiconfig/spropctrlr/ui/formattedsample.ui://GtkEntry[@id='entry'] no-labelled-by diff --git a/svtools/source/control/ctrlbox.cxx b/svtools/source/control/ctrlbox.cxx index e5778d949bee..ee534ba154df 100644 --- a/svtools/source/control/ctrlbox.cxx +++ b/svtools/source/control/ctrlbox.cxx @@ -1636,8 +1636,9 @@ void SvtLineListBox::UpdatePreview() } } -SvtCalendarBox::SvtCalendarBox(std::unique_ptr pControl) - : m_xControl(std::move(pControl)) +SvtCalendarBox::SvtCalendarBox(std::unique_ptr pControl, bool bUseLabel) + : m_bUseLabel(bUseLabel) + , m_xControl(std::move(pControl)) , m_xBuilder(Application::CreateBuilder(m_xControl.get(), "svt/ui/datewindow.ui")) , m_xTopLevel(m_xBuilder->weld_widget("date_popup_window")) , m_xCalendar(m_xBuilder->weld_calendar("date")) @@ -1655,6 +1656,8 @@ void SvtCalendarBox::set_date(const Date& rDate) void SvtCalendarBox::set_label_from_date() { + if (!m_bUseLabel) + return; const LocaleDataWrapper& rLocaleData = Application::GetSettings().GetLocaleDataWrapper(); m_xControl->set_label(rLocaleData.getDate(m_xCalendar->get_date())); } -- cgit