include/xmloff/odffields.hxx | 6 sw/Library_sw.mk | 2 sw/inc/swabstdlg.hxx | 3 sw/source/core/crsr/DateFormFieldButton.cxx | 115 +++++++++++++++++ sw/source/core/crsr/DropDownFormFieldButton.cxx | 122 ------------------ sw/source/core/crsr/FormFieldButton.cxx | 157 ++++++++++++++++++++++++ sw/source/core/crsr/bookmrk.cxx | 79 +++++------- sw/source/core/doc/docbm.cxx | 13 + sw/source/core/inc/DateFormFieldButton.hxx | 45 ++++++ sw/source/core/inc/DropDownFormFieldButton.hxx | 20 --- sw/source/core/inc/FormFieldButton.hxx | 57 ++++++++ sw/source/core/inc/MarkManager.hxx | 4 sw/source/core/inc/bookmrk.hxx | 40 +++--- sw/source/core/text/itrform2.cxx | 41 +++++- sw/source/ui/dialog/swdlgfact.cxx | 4 sw/source/ui/dialog/swdlgfact.hxx | 2 sw/source/ui/fldui/DateFormFieldDialog.cxx | 54 ++++++-- sw/source/uibase/inc/DateFormFieldDialog.hxx | 6 sw/source/uibase/shells/textfld.cxx | 17 ++ sw/source/uibase/shells/textsh1.cxx | 2 20 files changed, 565 insertions(+), 224 deletions(-)
New commits: commit 541dcbf8b0d3d64330943bef53e11607bea520e9 Author: Tamás Zolnai <[email protected]> AuthorDate: Fri Jun 14 22:00:07 2019 +0200 Commit: Tamás Zolnai <[email protected]> CommitDate: Sat Jun 15 17:57:24 2019 +0200 MSForms: Implement calculating the date text displayed in the date field * Change ODF_FORMDATE_DATEFORMAT to store the date format in a standard way (e.g. "MM.DD.YY") * Also add a new attribute called ODF_FORMDATE_DATEFORMAT_LANGUAGE to store the language for the date format. * Set a default date format and language by insertion. * Display the date in the field using the set format. * Store the current date in a specific format, which will make import / export easier (MSO DOCX format). Change-Id: I852975bbf81556f0e21f8f85d1c293707fdf672e diff --git a/include/xmloff/odffields.hxx b/include/xmloff/odffields.hxx index fc119fe0a295..901ff43087e4 100644 --- a/include/xmloff/odffields.hxx +++ b/include/xmloff/odffields.hxx @@ -34,8 +34,11 @@ #define ODF_FORMDROPDOWN_RESULT "Dropdown_Selected" #define ODF_FORMDATE "vnd.oasis.opendocument.field.FORMDATE" -#define ODF_FORMDATE_DATEFORMAT "DateField_DateFormat" -#define ODF_FORMDATE_CURRENTDATE "DateField_CurrentDate" +#define ODF_FORMDATE_DATEFORMAT "DateField_DateFormat" // e.g. "MM.DD.YY" +#define ODF_FORMDATE_DATEFORMAT_LANGUAGE "DateField_DateFormat_Language" // e.g. "en-US", "hu-HU" +#define ODF_FORMDATE_CURRENTDATE "DateField_CurrentDate" // date string in a specific format: "YYYY-MM-DD", using en-US language +#define ODF_FORMDATE_CURRENTDATE_FORMAT "YYYY-MM-DD" +#define ODF_FORMDATE_CURRENTDATE_LANGUAGE LANGUAGE_ENGLISH_US #define ODF_TOC "vnd.oasis.opendocument.field.TOC" diff --git a/sw/inc/swabstdlg.hxx b/sw/inc/swabstdlg.hxx index c5607dceb0b8..c793069b8a41 100644 --- a/sw/inc/swabstdlg.hxx +++ b/sw/inc/swabstdlg.hxx @@ -37,6 +37,7 @@ class SwGlossaryHdl; class SwField; class SwAsciiOptions; +class SwDoc; class SwDocShell; class SvStream; class SwWrtShell; @@ -391,7 +392,7 @@ public: SwField* pField, bool bPrevButton, bool bNextButton) = 0; virtual VclPtr<VclAbstractDialog> CreateDropDownFormFieldDialog(weld::Widget* pParent, sw::mark::IFieldmark* pDropDownField) = 0; - virtual VclPtr<VclAbstractDialog> CreateDateFormFieldDialog(weld::Widget* pParent, sw::mark::IFieldmark* pDateField) = 0; + virtual VclPtr<VclAbstractDialog> CreateDateFormFieldDialog(weld::Widget* pParent, sw::mark::IFieldmark* pDateField, SwDoc* pDoc) = 0; virtual VclPtr<SfxAbstractTabDialog> CreateSwEnvDlg(weld::Window* pParent, const SfxItemSet& rSet, SwWrtShell* pWrtSh, Printer* pPrt, bool bInsert) = 0; diff --git a/sw/source/core/crsr/DateFormFieldButton.cxx b/sw/source/core/crsr/DateFormFieldButton.cxx index 466f6961f589..180f47af53b8 100644 --- a/sw/source/core/crsr/DateFormFieldButton.cxx +++ b/sw/source/core/crsr/DateFormFieldButton.cxx @@ -22,35 +22,44 @@ #include <strings.hrc> #include <vcl/calendar.hxx> #include <tools/date.hxx> +#include <svx/numfmtsh.hxx> class SwDatePickerDialog : public FloatingWindow { private: VclPtr<Calendar> m_pCalendar; sw::mark::IFieldmark* m_pFieldmark; + SvNumberFormatter* m_pNumberFormatter; DECL_LINK(ImplSelectHdl, Calendar*, void); public: - SwDatePickerDialog(SwEditWin* parent, sw::mark::IFieldmark* pFieldmark); + SwDatePickerDialog(SwEditWin* parent, sw::mark::IFieldmark* pFieldmark, SvNumberFormatter* pNumberFormatter); virtual ~SwDatePickerDialog() override; virtual void dispose() override; }; -SwDatePickerDialog::SwDatePickerDialog(SwEditWin* parent, sw::mark::IFieldmark* pFieldmark) +SwDatePickerDialog::SwDatePickerDialog(SwEditWin* parent, sw::mark::IFieldmark* pFieldmark, SvNumberFormatter* pNumberFormatter) : FloatingWindow(parent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW) , m_pCalendar(VclPtr<Calendar>::Create(this, WB_TABSTOP)) , m_pFieldmark(pFieldmark) + , m_pNumberFormatter(pNumberFormatter) { if (m_pFieldmark != nullptr) { sw::mark::IFieldmark::parameter_map_t* pParameters = m_pFieldmark->GetParameters(); + auto pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE); if (pResult != pParameters->end()) { - sal_Int32 nCurrentDate = 0; - pResult->second >>= nCurrentDate; - m_pCalendar->SetCurDate(Date(nCurrentDate)); + OUString sDateString; + pResult->second >>= sDateString; + double dCurrentDate = 0; + sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(ODF_FORMDATE_CURRENTDATE_FORMAT, ODF_FORMDATE_CURRENTDATE_LANGUAGE); + m_pNumberFormatter->IsNumberFormat(sDateString, nFormat, dCurrentDate); + + const Date& rNullDate = m_pNumberFormatter->GetNullDate(); + m_pCalendar->SetCurDate(rNullDate + dCurrentDate); } } m_pCalendar->SetSelectHdl(LINK(this, SwDatePickerDialog, ImplSelectHdl)); @@ -73,16 +82,25 @@ IMPL_LINK(SwDatePickerDialog, ImplSelectHdl, Calendar*, pCalendar, void) { if (m_pFieldmark != nullptr) { + Color* pCol = nullptr; + OUString sOutput; + sal_uInt32 nFormat = m_pNumberFormatter->GetEntryKey(ODF_FORMDATE_CURRENTDATE_FORMAT, ODF_FORMDATE_CURRENTDATE_LANGUAGE); + + const Date& rNullDate = m_pNumberFormatter->GetNullDate(); + double dDate = pCalendar->GetFirstSelectedDate() - rNullDate; + + m_pNumberFormatter->GetOutputString(dDate, nFormat, sOutput, &pCol, false); + sw::mark::IFieldmark::parameter_map_t* pParameters = m_pFieldmark->GetParameters(); - (*pParameters)[ODF_FORMDATE_CURRENTDATE] - <<= pCalendar->GetFirstSelectedDate().GetDate(); + (*pParameters)[ODF_FORMDATE_CURRENTDATE] <<= sOutput; } EndPopupMode(); } } -DateFormFieldButton::DateFormFieldButton(SwEditWin* pEditWin, sw::mark::DateFieldmark& rFieldmark) +DateFormFieldButton::DateFormFieldButton(SwEditWin* pEditWin, sw::mark::DateFieldmark& rFieldmark, SvNumberFormatter* pNumberFormatter) : FormFieldButton(pEditWin, rFieldmark) + , m_pNumberFormatter(pNumberFormatter) { } @@ -91,7 +109,7 @@ DateFormFieldButton::~DateFormFieldButton() { disposeOnce(); } void DateFormFieldButton::InitPopup() { m_pFieldPopup - = VclPtr<SwDatePickerDialog>::Create(static_cast<SwEditWin*>(GetParent()), &m_rFieldmark); + = VclPtr<SwDatePickerDialog>::Create(static_cast<SwEditWin*>(GetParent()), &m_rFieldmark, m_pNumberFormatter); } /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sw/source/core/crsr/bookmrk.cxx b/sw/source/core/crsr/bookmrk.cxx index bfc1875208c2..88e9007aa3bc 100644 --- a/sw/source/core/crsr/bookmrk.cxx +++ b/sw/source/core/crsr/bookmrk.cxx @@ -40,6 +40,7 @@ #include <edtwin.hxx> #include "DateFormFieldButton.hxx" #include "DropDownFormFieldButton.hxx" +#include <svx/numfmtsh.hxx> using namespace ::sw::mark; using namespace ::com::sun::star; @@ -554,12 +555,18 @@ namespace sw { namespace mark { } + void DateFieldmark::InitDoc(SwDoc* const io_pDoc, sw::mark::InsertMode eMode) + { + m_pNumberFormatter = io_pDoc->GetNumberFormatter(); + NonTextFieldmark::InitDoc(io_pDoc, eMode); + } + void DateFieldmark::ShowButton(SwEditWin* pEditWin) { if(pEditWin) { if(!m_pButton) - m_pButton = VclPtr<DateFormFieldButton>::Create(pEditWin, *this); + m_pButton = VclPtr<DateFormFieldButton>::Create(pEditWin, *this, m_pNumberFormatter); m_pButton->CalcPosAndSize(m_aPortionPaintArea); m_pButton->Show(); } diff --git a/sw/source/core/inc/DateFormFieldButton.hxx b/sw/source/core/inc/DateFormFieldButton.hxx index c76352bb9a33..35f81fff8526 100644 --- a/sw/source/core/inc/DateFormFieldButton.hxx +++ b/sw/source/core/inc/DateFormFieldButton.hxx @@ -16,6 +16,7 @@ class SwEditWin; class FloatingWindow; +class SvNumberFormatter; namespace sw { namespace mark @@ -30,10 +31,13 @@ class DateFieldmark; class DateFormFieldButton : public FormFieldButton { public: - DateFormFieldButton(SwEditWin* pEditWin, sw::mark::DateFieldmark& rFieldMark); + DateFormFieldButton(SwEditWin* pEditWin, sw::mark::DateFieldmark& rFieldMark, SvNumberFormatter* pNumberFormatter); virtual ~DateFormFieldButton() override; virtual void InitPopup() override; + +private: + SvNumberFormatter* m_pNumberFormatter; }; #endif diff --git a/sw/source/core/inc/bookmrk.hxx b/sw/source/core/inc/bookmrk.hxx index f77978963e3a..ee5e9b45c4bd 100644 --- a/sw/source/core/inc/bookmrk.hxx +++ b/sw/source/core/inc/bookmrk.hxx @@ -44,6 +44,7 @@ namespace com { class SwDoc; class SwEditWin; class SwServerObject; +class SvNumberFormatter; namespace sw { namespace mark { @@ -307,7 +308,12 @@ namespace sw { DateFieldmark(const SwPaM& rPaM); virtual ~DateFieldmark() override; + virtual void InitDoc(SwDoc* const io_pDoc, sw::mark::InsertMode eMode) override; + virtual void ShowButton(SwEditWin* pEditWin); + + private: + SvNumberFormatter* m_pNumberFormatter; }; } } diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx index c5f6f6b1da0b..b164132862ff 100644 --- a/sw/source/core/text/itrform2.cxx +++ b/sw/source/core/text/itrform2.cxx @@ -59,6 +59,7 @@ #include <IDocumentSettingAccess.hxx> #include <IMark.hxx> #include <IDocumentMarkAccess.hxx> +#include <svl/zforlist.hxx> #include <vector> @@ -864,8 +865,43 @@ namespace sw { namespace mark { return OUString(vEnSpaces, ODF_FORMFIELD_DEFAULT_LENGTH); } - OUString ExpandDateFieldmark(IFieldmark* pBM) + OUString ExpandDateFieldmark(IFieldmark* pBM, SvNumberFormatter* pFormatter) { + OUString sDateFormat; + mark::IFieldmark::parameter_map_t* pParameters = pBM->GetParameters(); + auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT); + if (pResult != pParameters->end()) + { + pResult->second >>= sDateFormat; + } + + OUString sLang; + pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT_LANGUAGE); + if (pResult != pParameters->end()) + { + pResult->second >>= sLang; + } + + double dCurrentDate = 0.0; + pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE); + if (pResult != pParameters->end()) + { + OUString sFormattedDate; + pResult->second >>= sFormattedDate; + + sal_uInt32 nFormat = pFormatter->GetEntryKey(ODF_FORMDATE_CURRENTDATE_FORMAT, ODF_FORMDATE_CURRENTDATE_LANGUAGE); + pFormatter->IsNumberFormat(sFormattedDate, nFormat, dCurrentDate); + } + + Color* pCol = nullptr; + if (!sDateFormat.isEmpty() && !sLang.isEmpty() && dCurrentDate > 0.0) + { + OUString sOutput; + sal_uInt32 nFormat = pFormatter->GetEntryKey(sDateFormat, LanguageTag(sLang).getLanguageType()); + pFormatter->GetOutputString(dCurrentDate, nFormat, sOutput, &pCol, false); + return sOutput; + } + sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = {8194, 8194, 8194, 8194, 8194}; return OUString(vEnSpaces, ODF_FORMFIELD_DEFAULT_LENGTH); } @@ -918,7 +954,8 @@ SwTextPortion *SwTextFormatter::WhichTextPor( SwTextFormatInfo &rInf ) const } else if (pBM->GetFieldname( ) == ODF_FORMDATE) { - pPor = new SwFieldFormDatePortion(pBM, sw::mark::ExpandDateFieldmark(pBM)); + SvNumberFormatter* pFormatter = const_cast<SvNumberFormatter*>(GetTextFrame()->GetDoc().GetNumberFormatter()); + pPor = new SwFieldFormDatePortion(pBM, sw::mark::ExpandDateFieldmark(pBM, pFormatter)); } /* we need to check for ODF_FORMTEXT for scenario having FormFields inside FORMTEXT. * Otherwise file will crash on open. diff --git a/sw/source/ui/dialog/swdlgfact.cxx b/sw/source/ui/dialog/swdlgfact.cxx index cde201bc7d56..2a954af248c7 100644 --- a/sw/source/ui/dialog/swdlgfact.cxx +++ b/sw/source/ui/dialog/swdlgfact.cxx @@ -875,9 +875,9 @@ VclPtr<VclAbstractDialog> SwAbstractDialogFactory_Impl::CreateDropDownFormFieldD return VclPtr<AbstractDropDownFormFieldDialog_Impl>::Create(std::make_unique<sw::DropDownFormFieldDialog>(pParent, pDropDownField)); } -VclPtr<VclAbstractDialog> SwAbstractDialogFactory_Impl::CreateDateFormFieldDialog(weld::Widget *pParent, sw::mark::IFieldmark* pDateField) +VclPtr<VclAbstractDialog> SwAbstractDialogFactory_Impl::CreateDateFormFieldDialog(weld::Widget *pParent, sw::mark::IFieldmark* pDateField, SwDoc* pDoc) { - return VclPtr<AbstractDateFormFieldDialog_Impl>::Create(std::make_unique<sw::DateFormFieldDialog>(pParent, pDateField)); + return VclPtr<AbstractDateFormFieldDialog_Impl>::Create(std::make_unique<sw::DateFormFieldDialog>(pParent, pDateField, pDoc)); } VclPtr<SfxAbstractTabDialog> SwAbstractDialogFactory_Impl::CreateSwEnvDlg(weld::Window* pParent, const SfxItemSet& rSet, diff --git a/sw/source/ui/dialog/swdlgfact.hxx b/sw/source/ui/dialog/swdlgfact.hxx index 8c70da33a556..7638f7d150fd 100644 --- a/sw/source/ui/dialog/swdlgfact.hxx +++ b/sw/source/ui/dialog/swdlgfact.hxx @@ -652,7 +652,7 @@ public: virtual VclPtr<AbstractDropDownFieldDialog> CreateDropDownFieldDialog(weld::Widget* pParent, SwWrtShell &rSh, SwField* pField, bool bPrevButton, bool bNextButton) override; virtual VclPtr<VclAbstractDialog> CreateDropDownFormFieldDialog(weld::Widget* pParent, sw::mark::IFieldmark* pDropDownField) override; - virtual VclPtr<VclAbstractDialog> CreateDateFormFieldDialog(weld::Widget* pParent, sw::mark::IFieldmark* pDateField) override; + virtual VclPtr<VclAbstractDialog> CreateDateFormFieldDialog(weld::Widget* pParent, sw::mark::IFieldmark* pDateField, SwDoc* pDoc) override; virtual VclPtr<SfxAbstractTabDialog> CreateSwEnvDlg(weld::Window* pParent, const SfxItemSet& rSet, SwWrtShell* pWrtSh, Printer* pPrt, bool bInsert) override; virtual VclPtr<AbstractSwLabDlg> CreateSwLabDlg(weld::Window* pParent, const SfxItemSet& rSet, diff --git a/sw/source/ui/fldui/DateFormFieldDialog.cxx b/sw/source/ui/fldui/DateFormFieldDialog.cxx index 555c99d11392..e5cc6961b05e 100644 --- a/sw/source/ui/fldui/DateFormFieldDialog.cxx +++ b/sw/source/ui/fldui/DateFormFieldDialog.cxx @@ -11,19 +11,24 @@ #include <vcl/event.hxx> #include <IMark.hxx> #include <xmloff/odffields.hxx> +#include <svl/zforlist.hxx> +#include <svl/zformat.hxx> +#include <svx/numfmtsh.hxx> +#include <doc.hxx> namespace sw { DateFormFieldDialog::DateFormFieldDialog(weld::Widget* pParent, - mark::IFieldmark* pDateField) + mark::IFieldmark* pDateField, SwDoc* pDoc) : GenericDialogController(pParent, "modules/swriter/ui/dateformfielddialog.ui", "DateFormFieldDialog") , m_pDateField(pDateField) + , m_pNumberFormatter(pDoc->GetNumberFormatter()) , m_xFormatLB(new SwNumFormatTreeView(m_xBuilder->weld_tree_view("date_formats_treeview"))) { - m_xFormatLB->SetFormatType(SvNumFormatType::DATETIME); - m_xFormatLB->SetShowLanguageControl(true); + m_xFormatLB->SetFormatType(SvNumFormatType::DATE); m_xFormatLB->SetAutomaticLanguage(true); + m_xFormatLB->SetShowLanguageControl(true); m_xFormatLB->SetOneArea(true); // Set a default height @@ -39,8 +44,12 @@ void DateFormFieldDialog::Apply() { if (m_pDateField != nullptr) { - mark::IFieldmark::parameter_map_t* pParameters = m_pDateField->GetParameters(); - (*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= m_xFormatLB->GetFormat(); + const SvNumberformat* pFormat = m_pNumberFormatter->GetEntry(m_xFormatLB->GetFormat()); + sw::mark::IFieldmark::parameter_map_t* pParameters = m_pDateField->GetParameters(); + (*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= pFormat->GetFormatstring(); + + LanguageType aLang = pFormat->GetLanguage(); + (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] <<= LanguageTag(aLang).getBcp47(); } } @@ -48,14 +57,41 @@ void DateFormFieldDialog::InitControls() { if (m_pDateField != nullptr) { - mark::IFieldmark::parameter_map_t* pParameters = m_pDateField->GetParameters(); + sw::mark::IFieldmark::parameter_map_t* pParameters = m_pDateField->GetParameters(); + OUString sFormatString; auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT); if (pResult != pParameters->end()) { - sal_uInt32 nDateFormat = 0; - pResult->second >>= nDateFormat; - m_xFormatLB->SetDefFormat(nDateFormat); + pResult->second >>= sFormatString; + } + + OUString sLang; + pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT_LANGUAGE); + if (pResult != pParameters->end()) + { + pResult->second >>= sLang; + } + + if(!sFormatString.isEmpty() && !sLang.isEmpty()) + { + LanguageType aLangType = LanguageTag(sLang).getLanguageType(); + sal_uInt32 nFormatKey = m_pNumberFormatter->GetEntryKey(sFormatString, aLangType); + + if (m_xFormatLB->GetCurLanguage() == aLangType) + { + m_xFormatLB->SetAutomaticLanguage(true); + } + else + { + m_xFormatLB->SetAutomaticLanguage(false); + m_xFormatLB->SetLanguage(aLangType); + + // Change format and change back for regenerating the list + m_xFormatLB->SetFormatType(SvNumFormatType::ALL); + m_xFormatLB->SetFormatType(SvNumFormatType::DATE); + } + m_xFormatLB->SetDefFormat(nFormatKey); } } } diff --git a/sw/source/uibase/inc/DateFormFieldDialog.hxx b/sw/source/uibase/inc/DateFormFieldDialog.hxx index 19002e3e7f49..3d7d8b75d79d 100644 --- a/sw/source/uibase/inc/DateFormFieldDialog.hxx +++ b/sw/source/uibase/inc/DateFormFieldDialog.hxx @@ -14,6 +14,9 @@ #include "actctrl.hxx" #include <numfmtlb.hxx> +class SvNumberFormatter; +class SwDoc; + namespace sw { namespace mark @@ -29,6 +32,7 @@ class DateFormFieldDialog : public weld::GenericDialogController { private: mark::IFieldmark* m_pDateField; + SvNumberFormatter* m_pNumberFormatter; std::unique_ptr<SwNumFormatTreeView> m_xFormatLB; @@ -36,7 +40,7 @@ private: void InitControls(); public: - DateFormFieldDialog(weld::Widget* pParent, mark::IFieldmark* pDateField); + DateFormFieldDialog(weld::Widget* pParent, mark::IFieldmark* pDateField, SwDoc* pDoc); virtual ~DateFormFieldDialog() override; virtual short run() override diff --git a/sw/source/uibase/shells/textfld.cxx b/sw/source/uibase/shells/textfld.cxx index 82506e4c0f76..e7fb07417aa5 100644 --- a/sw/source/uibase/shells/textfld.cxx +++ b/sw/source/uibase/shells/textfld.cxx @@ -77,6 +77,12 @@ #include <xmloff/odffields.hxx> #include <IDocumentContentOperations.hxx> #include <IDocumentUndoRedo.hxx> +#include <svx/numfmtsh.hxx> +#include <svl/zforlist.hxx> +#include <svl/zformat.hxx> +#include <IMark.hxx> +#include <xmloff/odffields.hxx> + using namespace nsSwDocInfoSubType; @@ -787,7 +793,16 @@ FIELD_INSERT: if(pCursorPos) { IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess(); - pMarksAccess->makeNoTextFieldBookmark(*pCursorPos, OUString(), ODF_FORMDATE); + sw::mark::IFieldmark* pFieldBM = pMarksAccess->makeNoTextFieldBookmark(*pCursorPos, OUString(), ODF_FORMDATE); + + // Use a default date format and language + sw::mark::IFieldmark::parameter_map_t* pParameters = pFieldBM->GetParameters(); + SvNumberFormatter* pFormatter = rSh.GetDoc()->GetNumberFormatter(); + sal_uInt32 nStandardFormat = pFormatter->GetStandardFormat(SvNumFormatType::DATE); + const SvNumberformat* pFormat = pFormatter->GetEntry(nStandardFormat); + + (*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= pFormat->GetFormatstring(); + (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] <<= LanguageTag(pFormat->GetLanguage()).getBcp47(); } rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr); diff --git a/sw/source/uibase/shells/textsh1.cxx b/sw/source/uibase/shells/textsh1.cxx index 009e0c2fa508..50445cff3d99 100644 --- a/sw/source/uibase/shells/textsh1.cxx +++ b/sw/source/uibase/shells/textsh1.cxx @@ -1377,7 +1377,7 @@ void SwTextShell::Execute(SfxRequest &rReq) else if ( pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDATE ) { SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); - ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateDateFormFieldDialog(rWrtSh.GetView().GetFrameWeld(), pFieldBM)); + ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateDateFormFieldDialog(rWrtSh.GetView().GetFrameWeld(), pFieldBM, GetView().GetDocShell()->GetDoc())); if (pDlg->Execute() == RET_OK) { pFieldBM->Invalidate(); commit 2324ec8fcf1c53fccc923eb4fa37dd1f0e0bdc76 Author: Tamás Zolnai <[email protected]> AuthorDate: Mon Jun 10 12:59:23 2019 +0200 Commit: Tamás Zolnai <[email protected]> CommitDate: Thu Jun 13 19:10:11 2019 +0200 MSForms: Add a drop-down button for text-based date field * A calendar is opened by this button, where the user can select a date. * I used the same activation method which is used for drop-down fields. Change-Id: If0e63083463b9ead93baa2f27bdaaaf80aa9ce2f diff --git a/include/xmloff/odffields.hxx b/include/xmloff/odffields.hxx index 0b0ec4676f39..fc119fe0a295 100644 --- a/include/xmloff/odffields.hxx +++ b/include/xmloff/odffields.hxx @@ -35,6 +35,7 @@ #define ODF_FORMDATE "vnd.oasis.opendocument.field.FORMDATE" #define ODF_FORMDATE_DATEFORMAT "DateField_DateFormat" +#define ODF_FORMDATE_CURRENTDATE "DateField_CurrentDate" #define ODF_TOC "vnd.oasis.opendocument.field.TOC" diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk index 15b921947018..e3a2f1b1177b 100644 --- a/sw/Library_sw.mk +++ b/sw/Library_sw.mk @@ -150,6 +150,7 @@ $(eval $(call gb_Library_add_exception_objects,sw,\ sw/source/core/crsr/crsrsh \ sw/source/core/crsr/crstrvl \ sw/source/core/crsr/crstrvl1 \ + sw/source/core/crsr/DateFormFieldButton \ sw/source/core/crsr/DropDownFormFieldButton \ sw/source/core/crsr/findattr \ sw/source/core/crsr/findcoll \ diff --git a/sw/source/core/crsr/DateFormFieldButton.cxx b/sw/source/core/crsr/DateFormFieldButton.cxx new file mode 100644 index 000000000000..466f6961f589 --- /dev/null +++ b/sw/source/core/crsr/DateFormFieldButton.cxx @@ -0,0 +1,97 @@ +/* -*- 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/. + */ + +#include <DateFormFieldButton.hxx> +#include <edtwin.hxx> +#include <basegfx/color/bcolortools.hxx> +#include <viewopt.hxx> +#include <bookmrk.hxx> +#include <vcl/floatwin.hxx> +#include <vcl/event.hxx> +#include <vcl/lstbox.hxx> +#include <xmloff/odffields.hxx> +#include <IMark.hxx> +#include <view.hxx> +#include <docsh.hxx> +#include <strings.hrc> +#include <vcl/calendar.hxx> +#include <tools/date.hxx> + +class SwDatePickerDialog : public FloatingWindow +{ +private: + VclPtr<Calendar> m_pCalendar; + sw::mark::IFieldmark* m_pFieldmark; + + DECL_LINK(ImplSelectHdl, Calendar*, void); + +public: + SwDatePickerDialog(SwEditWin* parent, sw::mark::IFieldmark* pFieldmark); + virtual ~SwDatePickerDialog() override; + virtual void dispose() override; +}; + +SwDatePickerDialog::SwDatePickerDialog(SwEditWin* parent, sw::mark::IFieldmark* pFieldmark) + : FloatingWindow(parent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW) + , m_pCalendar(VclPtr<Calendar>::Create(this, WB_TABSTOP)) + , m_pFieldmark(pFieldmark) +{ + if (m_pFieldmark != nullptr) + { + sw::mark::IFieldmark::parameter_map_t* pParameters = m_pFieldmark->GetParameters(); + auto pResult = pParameters->find(ODF_FORMDATE_CURRENTDATE); + if (pResult != pParameters->end()) + { + sal_Int32 nCurrentDate = 0; + pResult->second >>= nCurrentDate; + m_pCalendar->SetCurDate(Date(nCurrentDate)); + } + } + m_pCalendar->SetSelectHdl(LINK(this, SwDatePickerDialog, ImplSelectHdl)); + m_pCalendar->SetOutputSizePixel(m_pCalendar->CalcWindowSizePixel()); + m_pCalendar->Show(); + SetOutputSizePixel(m_pCalendar->GetSizePixel()); +} + +SwDatePickerDialog::~SwDatePickerDialog() { disposeOnce(); } + +void SwDatePickerDialog::dispose() +{ + m_pCalendar.clear(); + FloatingWindow::dispose(); +} + +IMPL_LINK(SwDatePickerDialog, ImplSelectHdl, Calendar*, pCalendar, void) +{ + if (!pCalendar->IsTravelSelect()) + { + if (m_pFieldmark != nullptr) + { + sw::mark::IFieldmark::parameter_map_t* pParameters = m_pFieldmark->GetParameters(); + (*pParameters)[ODF_FORMDATE_CURRENTDATE] + <<= pCalendar->GetFirstSelectedDate().GetDate(); + } + EndPopupMode(); + } +} + +DateFormFieldButton::DateFormFieldButton(SwEditWin* pEditWin, sw::mark::DateFieldmark& rFieldmark) + : FormFieldButton(pEditWin, rFieldmark) +{ +} + +DateFormFieldButton::~DateFormFieldButton() { disposeOnce(); } + +void DateFormFieldButton::InitPopup() +{ + m_pFieldPopup + = VclPtr<SwDatePickerDialog>::Create(static_cast<SwEditWin*>(GetParent()), &m_rFieldmark); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sw/source/core/crsr/bookmrk.cxx b/sw/source/core/crsr/bookmrk.cxx index 1b2da58c6787..bfc1875208c2 100644 --- a/sw/source/core/crsr/bookmrk.cxx +++ b/sw/source/core/crsr/bookmrk.cxx @@ -38,6 +38,8 @@ #include <comphelper/anytostring.hxx> #include <sal/log.hxx> #include <edtwin.hxx> +#include "DateFormFieldButton.hxx" +#include "DropDownFormFieldButton.hxx" using namespace ::sw::mark; using namespace ::com::sun::star; @@ -485,18 +487,18 @@ namespace sw { namespace mark return bResult; } - DropDownFieldmark::DropDownFieldmark(const SwPaM& rPaM) + FieldmarkWithDropDownButton::FieldmarkWithDropDownButton(const SwPaM& rPaM) : NonTextFieldmark(rPaM) , m_pButton(nullptr) { } - DropDownFieldmark::~DropDownFieldmark() + FieldmarkWithDropDownButton::~FieldmarkWithDropDownButton() { m_pButton.disposeAndClear(); } - void DropDownFieldmark::SetPortionPaintArea(const SwRect& rPortionPaintArea) + void FieldmarkWithDropDownButton::SetPortionPaintArea(const SwRect& rPortionPaintArea) { if(m_aPortionPaintArea == rPortionPaintArea && m_pButton && m_pButton->IsVisible()) @@ -511,76 +513,56 @@ namespace sw { namespace mark } } - void DropDownFieldmark::ShowButton(SwEditWin* pEditWin) - { - if(pEditWin) - { - if(!m_pButton) - m_pButton = VclPtr<DropDownFormFieldButton>::Create(pEditWin, *this); - m_pButton->CalcPosAndSize(m_aPortionPaintArea); - m_pButton->Show(); - } - } - - void DropDownFieldmark::HideButton() + void FieldmarkWithDropDownButton::HideButton() { if(m_pButton) m_pButton->Show(false); } - void DropDownFieldmark::RemoveButton() + void FieldmarkWithDropDownButton::RemoveButton() { if(m_pButton) m_pButton.disposeAndClear(); } - DateFieldmark::DateFieldmark(const SwPaM& rPaM) - : NonTextFieldmark(rPaM) - //, m_pButton(nullptr) + DropDownFieldmark::DropDownFieldmark(const SwPaM& rPaM) + : FieldmarkWithDropDownButton(rPaM) { } - DateFieldmark::~DateFieldmark() + DropDownFieldmark::~DropDownFieldmark() { - //m_pButton.disposeAndClear(); } - void DateFieldmark::SetPortionPaintArea(const SwRect& rPortionPaintArea) + void DropDownFieldmark::ShowButton(SwEditWin* pEditWin) { - /*if(m_aPortionPaintArea == rPortionPaintArea && - m_pButton && m_pButton->IsVisible()) - return; - - m_aPortionPaintArea = rPortionPaintArea; - if(m_pButton) + if(pEditWin) { - m_pButton->Show(); + if(!m_pButton) + m_pButton = VclPtr<DropDownFormFieldButton>::Create(pEditWin, *this); m_pButton->CalcPosAndSize(m_aPortionPaintArea); - m_pButton->Invalidate(); - }*/ + m_pButton->Show(); + } } - void DateFieldmark::ShowButton(SwEditWin* pEditWin) + DateFieldmark::DateFieldmark(const SwPaM& rPaM) + : FieldmarkWithDropDownButton(rPaM) { - if(pEditWin) - { - //if(!m_pButton) - // m_pButton = VclPtr<DropDownFormFieldButton>::Create(pEditWin, *this); - //m_pButton->CalcPosAndSize(m_aPortionPaintArea); - //m_pButton->Show(); - } } - void DateFieldmark::HideButton() + DateFieldmark::~DateFieldmark() { - //if(m_pButton) - //m_pButton->Show(false); } - void DateFieldmark::RemoveButton() + void DateFieldmark::ShowButton(SwEditWin* pEditWin) { - //if(m_pButton) - //m_pButton.disposeAndClear(); + if(pEditWin) + { + if(!m_pButton) + m_pButton = VclPtr<DateFormFieldButton>::Create(pEditWin, *this); + m_pButton->CalcPosAndSize(m_aPortionPaintArea); + m_pButton->Show(); + } } }} diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx index 89a4bf1782a5..404a67f25379 100644 --- a/sw/source/core/doc/docbm.cxx +++ b/sw/source/core/doc/docbm.cxx @@ -1188,21 +1188,22 @@ namespace sw { namespace mark SwEditWin& rEditWin = pSwView->GetEditWin(); SwPosition aPos(*rCursorShell.GetCursor()->GetPoint()); IFieldmark* pFieldBM = getFieldmarkFor(aPos); - DropDownFieldmark* pNewActiveFieldmark = nullptr; - if ((!pFieldBM || pFieldBM->GetFieldname() != ODF_FORMDROPDOWN) + FieldmarkWithDropDownButton* pNewActiveFieldmark = nullptr; + if ((!pFieldBM || (pFieldBM->GetFieldname() != ODF_FORMDROPDOWN && pFieldBM->GetFieldname() != ODF_FORMDATE)) && aPos.nContent.GetIndex() > 0 ) { --aPos.nContent; pFieldBM = getFieldmarkFor(aPos); } - if ( pFieldBM && pFieldBM->GetFieldname() == ODF_FORMDROPDOWN ) + if ( pFieldBM && (pFieldBM->GetFieldname() == ODF_FORMDROPDOWN || + pFieldBM->GetFieldname() == ODF_FORMDATE)) { if (m_pLastActiveFieldmark != pFieldBM) { - DropDownFieldmark* pDropDownFm = dynamic_cast<DropDownFieldmark*>(pFieldBM); - pDropDownFm->ShowButton(&rEditWin); - pNewActiveFieldmark = pDropDownFm; + auto pFormField = dynamic_cast<FieldmarkWithDropDownButton*>(pFieldBM); + pFormField->ShowButton(&rEditWin); + pNewActiveFieldmark = pFormField; } else { diff --git a/sw/source/core/inc/DateFormFieldButton.hxx b/sw/source/core/inc/DateFormFieldButton.hxx new file mode 100644 index 000000000000..c76352bb9a33 --- /dev/null +++ b/sw/source/core/inc/DateFormFieldButton.hxx @@ -0,0 +1,41 @@ +/* -*- 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/. + */ + +#ifndef INCLUDED_SW_SOURCE_CORE_TEXT_DATEFORMEFIELDBUTTO_HXX +#define INCLUDED_SW_SOURCE_CORE_TEXT_DATEFORMEFIELDBUTTO_HXX + +#include <vcl/menubtn.hxx> +#include <swrect.hxx> +#include <FormFieldButton.hxx> + +class SwEditWin; +class FloatingWindow; +namespace sw +{ +namespace mark +{ +class DateFieldmark; +} +} // namespace sw + +/** + * This button is shown when the cursor is on a drop-down form field. + */ +class DateFormFieldButton : public FormFieldButton +{ +public: + DateFormFieldButton(SwEditWin* pEditWin, sw::mark::DateFieldmark& rFieldMark); + virtual ~DateFormFieldButton() override; + + virtual void InitPopup() override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sw/source/core/inc/MarkManager.hxx b/sw/source/core/inc/MarkManager.hxx index e901510e08b5..7690fe1ece07 100644 --- a/sw/source/core/inc/MarkManager.hxx +++ b/sw/source/core/inc/MarkManager.hxx @@ -31,7 +31,7 @@ namespace sw { namespace mark { typedef std::unordered_map<OUString, sal_Int32> MarkBasenameMapUniqueOffset_t; - class DropDownFieldmark; + class FieldmarkWithDropDownButton; class MarkManager : virtual public IDocumentMarkAccess @@ -136,7 +136,7 @@ namespace sw { SwDoc * const m_pDoc; - sw::mark::DropDownFieldmark* m_pLastActiveFieldmark; + sw::mark::FieldmarkWithDropDownButton* m_pLastActiveFieldmark; }; } // namespace mark } diff --git a/sw/source/core/inc/bookmrk.hxx b/sw/source/core/inc/bookmrk.hxx index 7a28f9c7cb1b..f77978963e3a 100644 --- a/sw/source/core/inc/bookmrk.hxx +++ b/sw/source/core/inc/bookmrk.hxx @@ -29,7 +29,7 @@ #include <tools/ref.hxx> #include <IMark.hxx> #include <swrect.hxx> -#include "DropDownFormFieldButton.hxx" +#include "FormFieldButton.hxx" namespace com { namespace sun { @@ -268,44 +268,46 @@ namespace sw { void SetChecked(bool checked) override; }; - /// Fieldmark representing a drop-down form field. - class DropDownFieldmark + /// Fieldmark with a drop down button (e.g. this button opens the date picker for a date field) + class FieldmarkWithDropDownButton : public NonTextFieldmark { public: - DropDownFieldmark(const SwPaM& rPaM); - virtual ~DropDownFieldmark() override; + FieldmarkWithDropDownButton(const SwPaM& rPaM); + virtual ~FieldmarkWithDropDownButton() override; // This method should be called only by the portion so we can now the portion's painting area void SetPortionPaintArea(const SwRect& rPortionPaintArea); - void ShowButton(SwEditWin* pEditWin); + virtual void ShowButton(SwEditWin* pEditWin) = 0; void HideButton(); void RemoveButton(); - private: + protected: SwRect m_aPortionPaintArea; - VclPtr<DropDownFormFieldButton> m_pButton; + VclPtr<FormFieldButton> m_pButton; + }; + + /// Fieldmark representing a drop-down form field. + class DropDownFieldmark + : public FieldmarkWithDropDownButton + { + public: + DropDownFieldmark(const SwPaM& rPaM); + virtual ~DropDownFieldmark() override; + + virtual void ShowButton(SwEditWin* pEditWin); }; /// Fieldmark representing a date form field. class DateFieldmark - : public NonTextFieldmark + : public FieldmarkWithDropDownButton { public: DateFieldmark(const SwPaM& rPaM); virtual ~DateFieldmark() override; - // This method should be called only by the portion so we can now the portion's painting area - void SetPortionPaintArea(const SwRect& rPortionPaintArea); - - void ShowButton(SwEditWin* pEditWin); - void HideButton(); - void RemoveButton(); - - private: - SwRect m_aPortionPaintArea; - //VclPtr<DropDownFormFieldButton> m_pButton; + virtual void ShowButton(SwEditWin* pEditWin); }; } } commit a29a5f5894801e8d94859aeffb1bedd6c0b537d2 Author: Tamás Zolnai <[email protected]> AuthorDate: Fri Jun 7 17:46:58 2019 +0200 Commit: Tamás Zolnai <[email protected]> CommitDate: Fri Jun 7 17:46:58 2019 +0200 MSForms: Generalize some parts of the drop-down form field popup button We'll need a similar button for the new text-based date field. Change-Id: I9cf69f98dae3d761d9cddfbaed138d6453af887d diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk index ededa54c689b..15b921947018 100644 --- a/sw/Library_sw.mk +++ b/sw/Library_sw.mk @@ -155,6 +155,7 @@ $(eval $(call gb_Library_add_exception_objects,sw,\ sw/source/core/crsr/findcoll \ sw/source/core/crsr/findfmt \ sw/source/core/crsr/findtxt \ + sw/source/core/crsr/FormFieldButton \ sw/source/core/crsr/pam \ sw/source/core/crsr/paminit \ sw/source/core/crsr/swcrsr \ diff --git a/sw/source/core/crsr/DropDownFormFieldButton.cxx b/sw/source/core/crsr/DropDownFormFieldButton.cxx index 158751fe308d..d2c97f382e22 100644 --- a/sw/source/core/crsr/DropDownFormFieldButton.cxx +++ b/sw/source/core/crsr/DropDownFormFieldButton.cxx @@ -8,8 +8,6 @@ */ #include <DropDownFormFieldButton.hxx> -#include <vcl/svapp.hxx> -#include <vcl/settings.hxx> #include <edtwin.hxx> #include <basegfx/color/bcolortools.hxx> #include <viewopt.hxx> @@ -124,132 +122,16 @@ IMPL_LINK(SwFieldDialog, MyListBoxHandler, ListBox&, rBox, void) DropDownFormFieldButton::DropDownFormFieldButton(SwEditWin* pEditWin, sw::mark::DropDownFieldmark& rFieldmark) - : MenuButton(pEditWin, WB_DIALOGCONTROL) - , m_rFieldmark(rFieldmark) + : FormFieldButton(pEditWin, rFieldmark) { - assert(GetParent()); - assert(dynamic_cast<SwEditWin*>(GetParent())); } DropDownFormFieldButton::~DropDownFormFieldButton() { disposeOnce(); } -void DropDownFormFieldButton::dispose() +void DropDownFormFieldButton::InitPopup() { - m_pFieldPopup.disposeAndClear(); - MenuButton::dispose(); -} - -void DropDownFormFieldButton::CalcPosAndSize(const SwRect& rPortionPaintArea) -{ - assert(GetParent()); - - Point aBoxPos = GetParent()->LogicToPixel(rPortionPaintArea.Pos()); - Size aBoxSize = GetParent()->LogicToPixel(rPortionPaintArea.SSize()); - - // First calculate the size of the frame around the field - int nPadding = aBoxSize.Height() / 4; - aBoxPos.AdjustX(-nPadding); - aBoxPos.AdjustY(-nPadding); - aBoxSize.AdjustWidth(2 * nPadding); - aBoxSize.AdjustHeight(2 * nPadding); - - m_aFieldFramePixel = tools::Rectangle(aBoxPos, aBoxSize); - - // Then extend the size with the button area - aBoxSize.AdjustWidth(GetParent()->LogicToPixel(rPortionPaintArea.SSize()).Height()); - - SetPosSizePixel(aBoxPos, aBoxSize); -} - -void DropDownFormFieldButton::MouseButtonUp(const MouseEvent&) -{ - assert(GetParent()); - - Point aPixPos = GetPosPixel(); - aPixPos.AdjustY(GetSizePixel().Height()); - m_pFieldPopup = VclPtr<SwFieldDialog>::Create(static_cast<SwEditWin*>(GetParent()), &m_rFieldmark, GetSizePixel().Width()); - m_pFieldPopup->SetPopupModeEndHdl(LINK(this, DropDownFormFieldButton, FieldPopupModeEndHdl)); - - tools::Rectangle aRect(GetParent()->OutputToScreenPixel(aPixPos), Size(0, 0)); - m_pFieldPopup->StartPopupMode(aRect, FloatWinPopupFlags::Down | FloatWinPopupFlags::GrabFocus); - Invalidate(); -} - -IMPL_LINK_NOARG(DropDownFormFieldButton, FieldPopupModeEndHdl, FloatingWindow*, void) -{ - m_pFieldPopup.disposeAndClear(); - m_rFieldmark.Invalidate(); - // Hide the button here and make it visible later, to make transparent background work with SAL_USE_VCLPLUGIN=gen - Show(false); - Invalidate(); -} - -static basegfx::BColor lcl_GetFillColor(const basegfx::BColor& rLineColor, double aLuminance) -{ - basegfx::BColor aHslLine = basegfx::utils::rgb2hsl(rLineColor); - aHslLine.setZ(aLuminance); - return basegfx::utils::hsl2rgb(aHslLine); -} - -void DropDownFormFieldButton::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) -{ - SetMapMode(MapMode(MapUnit::MapPixel)); - - //const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); - Color aLineColor = COL_BLACK; - Color aFillColor(lcl_GetFillColor(aLineColor.getBColor(), (m_pFieldPopup ? 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 - int nPadding = 1; - Point aPos(nPadding, nPadding); - Size aSize(m_aFieldFramePixel.GetSize().Width() - nPadding, - m_aFieldFramePixel.GetSize().Height() - nPadding); - const tools::Rectangle aFrameRect(tools::Rectangle(aPos, aSize)); - rRenderContext.SetLineColor(aLineColor); - rRenderContext.SetFillColor(COL_TRANSPARENT); - rRenderContext.DrawRect(aFrameRect); - - // Draw the button next to the frame - Point aButtonPos(aFrameRect.TopLeft()); - aButtonPos.AdjustX(aFrameRect.GetSize().getWidth() - 1); - Size aButtonSize(aFrameRect.GetSize()); - aButtonSize.setWidth(GetSizePixel().getWidth() - aFrameRect.getWidth() - nPadding); - const tools::Rectangle aButtonRect(tools::Rectangle(aButtonPos, aButtonSize)); - - // Background & border - rRenderContext.SetLineColor(aLineColor); - rRenderContext.SetFillColor(aFillColor); - rRenderContext.DrawRect(aButtonRect); - - // the arrowhead - rRenderContext.SetLineColor(aLineColor); - rRenderContext.SetFillColor(aLineColor); - - Point aCenter(aButtonPos.X() + (aButtonSize.Width() / 2), - aButtonPos.Y() + (aButtonSize.Height() / 2)); - Size aArrowSize(aButtonSize.Width() / 4, aButtonSize.Height() / 10); - - tools::Polygon aPoly(3); - aPoly.SetPoint(Point(aCenter.X() - aArrowSize.Width(), aCenter.Y() - aArrowSize.Height()), 0); - aPoly.SetPoint(Point(aCenter.X() + aArrowSize.Width(), aCenter.Y() - aArrowSize.Height()), 1); - aPoly.SetPoint(Point(aCenter.X(), aCenter.Y() + aArrowSize.Height()), 2); - rRenderContext.DrawPolygon(aPoly); -} - -WindowHitTest DropDownFormFieldButton::ImplHitTest(const Point& rFramePos) -{ - // We need to check whether the position hits the button (the frame should be mouse transparent) - WindowHitTest aResult = MenuButton::ImplHitTest(rFramePos); - if (aResult != WindowHitTest::Inside) - return aResult; - else - { - return rFramePos.X() >= m_aFieldFramePixel.Right() ? WindowHitTest::Inside - : WindowHitTest::Transparent; - } } /* 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 new file mode 100644 index 000000000000..37b97d998b61 --- /dev/null +++ b/sw/source/core/crsr/FormFieldButton.cxx @@ -0,0 +1,157 @@ +/* -*- 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/. + */ + +#include <DropDownFormFieldButton.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <edtwin.hxx> +#include <basegfx/color/bcolortools.hxx> +#include <viewopt.hxx> +#include <bookmrk.hxx> +#include <vcl/floatwin.hxx> +#include <vcl/event.hxx> +#include <vcl/lstbox.hxx> +#include <IMark.hxx> +#include <view.hxx> +#include <docsh.hxx> +#include <strings.hrc> + + +FormFieldButton::FormFieldButton(SwEditWin* pEditWin, + sw::mark::Fieldmark& rFieldmark) + : MenuButton(pEditWin, WB_DIALOGCONTROL) + , m_rFieldmark(rFieldmark) +{ + assert(GetParent()); + assert(dynamic_cast<SwEditWin*>(GetParent())); +} + +FormFieldButton::~FormFieldButton() { disposeOnce(); } + +void FormFieldButton::dispose() +{ + m_pFieldPopup.disposeAndClear(); + MenuButton::dispose(); +} + +void FormFieldButton::CalcPosAndSize(const SwRect& rPortionPaintArea) +{ + assert(GetParent()); + + Point aBoxPos = GetParent()->LogicToPixel(rPortionPaintArea.Pos()); + Size aBoxSize = GetParent()->LogicToPixel(rPortionPaintArea.SSize()); + + // First calculate the size of the frame around the field + int nPadding = aBoxSize.Height() / 4; + aBoxPos.AdjustX(-nPadding); + aBoxPos.AdjustY(-nPadding); + aBoxSize.AdjustWidth(2 * nPadding); + aBoxSize.AdjustHeight(2 * nPadding); + + m_aFieldFramePixel = tools::Rectangle(aBoxPos, aBoxSize); + + // Then extend the size with the button area + aBoxSize.AdjustWidth(GetParent()->LogicToPixel(rPortionPaintArea.SSize()).Height()); + + SetPosSizePixel(aBoxPos, aBoxSize); +} + +void FormFieldButton::MouseButtonUp(const MouseEvent&) +{ + assert(GetParent()); + + Point aPixPos = GetPosPixel(); + aPixPos.AdjustY(GetSizePixel().Height()); + + // sets m_pFieldPopup + InitPopup(); + + m_pFieldPopup->SetPopupModeEndHdl(LINK(this, DropDownFormFieldButton, FieldPopupModeEndHdl)); + + tools::Rectangle aRect(GetParent()->OutputToScreenPixel(aPixPos), Size(0, 0)); + m_pFieldPopup->StartPopupMode(aRect, FloatWinPopupFlags::Down | FloatWinPopupFlags::GrabFocus); + Invalidate(); +} + +IMPL_LINK_NOARG(FormFieldButton, FieldPopupModeEndHdl, FloatingWindow*, void) +{ + m_pFieldPopup.disposeAndClear(); + m_rFieldmark.Invalidate(); + // Hide the button here and make it visible later, to make transparent background work with SAL_USE_VCLPLUGIN=gen + Show(false); + Invalidate(); +} + +static basegfx::BColor lcl_GetFillColor(const basegfx::BColor& rLineColor, double aLuminance) +{ + basegfx::BColor aHslLine = basegfx::utils::rgb2hsl(rLineColor); + aHslLine.setZ(aLuminance); + return basegfx::utils::hsl2rgb(aHslLine); +} + +void FormFieldButton::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&) +{ + SetMapMode(MapMode(MapUnit::MapPixel)); + + //const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + Color aLineColor = COL_BLACK; + Color aFillColor(lcl_GetFillColor(aLineColor.getBColor(), (m_pFieldPopup ? 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 + int nPadding = 1; + Point aPos(nPadding, nPadding); + Size aSize(m_aFieldFramePixel.GetSize().Width() - nPadding, + m_aFieldFramePixel.GetSize().Height() - nPadding); + const tools::Rectangle aFrameRect(tools::Rectangle(aPos, aSize)); + rRenderContext.SetLineColor(aLineColor); + rRenderContext.SetFillColor(COL_TRANSPARENT); + rRenderContext.DrawRect(aFrameRect); + + // Draw the button next to the frame + Point aButtonPos(aFrameRect.TopLeft()); + aButtonPos.AdjustX(aFrameRect.GetSize().getWidth() - 1); + Size aButtonSize(aFrameRect.GetSize()); + aButtonSize.setWidth(GetSizePixel().getWidth() - aFrameRect.getWidth() - nPadding); + const tools::Rectangle aButtonRect(tools::Rectangle(aButtonPos, aButtonSize)); + + // Background & border + rRenderContext.SetLineColor(aLineColor); + rRenderContext.SetFillColor(aFillColor); + rRenderContext.DrawRect(aButtonRect); + + // the arrowhead + rRenderContext.SetLineColor(aLineColor); + rRenderContext.SetFillColor(aLineColor); + + Point aCenter(aButtonPos.X() + (aButtonSize.Width() / 2), + aButtonPos.Y() + (aButtonSize.Height() / 2)); + Size aArrowSize(aButtonSize.Width() / 4, aButtonSize.Height() / 10); + + tools::Polygon aPoly(3); + aPoly.SetPoint(Point(aCenter.X() - aArrowSize.Width(), aCenter.Y() - aArrowSize.Height()), 0); + aPoly.SetPoint(Point(aCenter.X() + aArrowSize.Width(), aCenter.Y() - aArrowSize.Height()), 1); + aPoly.SetPoint(Point(aCenter.X(), aCenter.Y() + aArrowSize.Height()), 2); + rRenderContext.DrawPolygon(aPoly); +} + +WindowHitTest FormFieldButton::ImplHitTest(const Point& rFramePos) +{ + // We need to check whether the position hits the button (the frame should be mouse transparent) + WindowHitTest aResult = MenuButton::ImplHitTest(rFramePos); + if (aResult != WindowHitTest::Inside) + return aResult; + else + { + return rFramePos.X() >= m_aFieldFramePixel.Right() ? WindowHitTest::Inside + : WindowHitTest::Transparent; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sw/source/core/inc/DropDownFormFieldButton.hxx b/sw/source/core/inc/DropDownFormFieldButton.hxx index 1147f59dfc9b..f1b317ca1263 100644 --- a/sw/source/core/inc/DropDownFormFieldButton.hxx +++ b/sw/source/core/inc/DropDownFormFieldButton.hxx @@ -12,6 +12,7 @@ #include <vcl/menubtn.hxx> #include <swrect.hxx> +#include <FormFieldButton.hxx> class SwEditWin; class FloatingWindow; @@ -24,28 +25,15 @@ class DropDownFieldmark; } /** - * This button is shown when the cursor is in a drop-down form field. - * The user can select an item of the field using this button while filling in a form. + * This button is shown when the cursor is on a drop-down form field. */ -class DropDownFormFieldButton : public MenuButton +class DropDownFormFieldButton : public FormFieldButton { public: DropDownFormFieldButton(SwEditWin* pEditWin, sw::mark::DropDownFieldmark& rFieldMark); virtual ~DropDownFormFieldButton() override; - virtual void dispose() override; - void CalcPosAndSize(const SwRect& rPortionPaintArea); - - virtual void MouseButtonUp(const MouseEvent& rMEvt) override; - DECL_LINK(FieldPopupModeEndHdl, FloatingWindow*, void); - - virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; - virtual WindowHitTest ImplHitTest(const Point& rFramePos) override; - -private: - tools::Rectangle m_aFieldFramePixel; - sw::mark::DropDownFieldmark& m_rFieldmark; - VclPtr<FloatingWindow> m_pFieldPopup; + virtual void InitPopup() override; }; #endif diff --git a/sw/source/core/inc/FormFieldButton.hxx b/sw/source/core/inc/FormFieldButton.hxx new file mode 100644 index 000000000000..9cbc9bc5662a --- /dev/null +++ b/sw/source/core/inc/FormFieldButton.hxx @@ -0,0 +1,57 @@ +/* -*- 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/. + */ + +#ifndef INCLUDED_SW_SOURCE_CORE_TEXT_FORMEFIELDBUTTO_HXX +#define INCLUDED_SW_SOURCE_CORE_TEXT_FORMEFIELDBUTTO_HXX + +#include <vcl/menubtn.hxx> +#include <swrect.hxx> + +class SwEditWin; +class FloatingWindow; +namespace sw +{ +namespace mark +{ +class Fieldmark; +} +} + +/** + * This button is shown when the cursor is on a form field with drop-down capability. + * The user can select an item of the field using this button while filling in a form. + */ +class FormFieldButton : public MenuButton +{ +public: + FormFieldButton(SwEditWin* pEditWin, sw::mark::Fieldmark& rFieldMark); + virtual ~FormFieldButton() override; + virtual void dispose() override; + + void CalcPosAndSize(const SwRect& rPortionPaintArea); + + virtual void MouseButtonUp(const MouseEvent& rMEvt) override; + DECL_LINK(FieldPopupModeEndHdl, FloatingWindow*, void); + + virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override; + virtual WindowHitTest ImplHitTest(const Point& rFramePos) override; + + virtual void InitPopup() = 0; + +private: + tools::Rectangle m_aFieldFramePixel; + +protected: + sw::mark::Fieldmark& m_rFieldmark; + VclPtr<FloatingWindow> m_pFieldPopup; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
