diff options
author | Tamás Zolnai <tamas.zolnai@collabora.com> | 2019-03-09 14:44:50 +0100 |
---|---|---|
committer | Tamás Zolnai <tamas.zolnai@collabora.com> | 2019-03-09 15:40:56 +0100 |
commit | f66a83c95c21b4311918a64bb85016857b49f4d4 (patch) | |
tree | 0d0c507947bad6c711003ede66f09a7f20238cbc | |
parent | 499501e8cf1d511eb95a7b72b755c2dc69985719 (diff) |
MSForms: Introduce a new IFieldMark for drop-down form field
* It was weird anyway that a drop-down form field was represented
as an CheckboxFieldmark.
* It will be useful for later commits, to have a separate field type
for drop-down field.
* Needed to fix-up the API a bit because it was designed to specify
the field type after initialization. I solved it in a way to not break
the API behavior. Hopefully it's not very slow.
Change-Id: I3103e6b1c36289b27b62ab9ca7dfeebc14901c8a
Reviewed-on: https://gerrit.libreoffice.org/68960
Tested-by: Jenkins
Reviewed-by: Tamás Zolnai <tamas.zolnai@collabora.com>
-rw-r--r-- | sw/inc/IDocumentMarkAccess.hxx | 2 | ||||
-rw-r--r-- | sw/source/core/crsr/bookmrk.cxx | 33 | ||||
-rw-r--r-- | sw/source/core/doc/docbm.cxx | 50 | ||||
-rw-r--r-- | sw/source/core/inc/MarkManager.hxx | 1 | ||||
-rw-r--r-- | sw/source/core/inc/bookmrk.hxx | 12 | ||||
-rw-r--r-- | sw/source/core/inc/unobookmark.hxx | 2 | ||||
-rw-r--r-- | sw/source/core/text/itrform2.cxx | 4 | ||||
-rw-r--r-- | sw/source/core/unocore/unobkm.cxx | 23 | ||||
-rw-r--r-- | writerfilter/source/dmapper/FormControlHelper.cxx | 17 |
9 files changed, 133 insertions, 11 deletions
diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx index 823326e2b8ac..cbd523c012b1 100644 --- a/sw/inc/IDocumentMarkAccess.hxx +++ b/sw/inc/IDocumentMarkAccess.hxx @@ -47,6 +47,7 @@ class IDocumentMarkAccess ANNOTATIONMARK, TEXT_FIELDMARK, CHECKBOX_FIELDMARK, + DROPDOWN_FIELDMARK, NAVIGATOR_REMINDER }; @@ -255,6 +256,7 @@ class IDocumentMarkAccess virtual std::vector< ::sw::mark::IFieldmark* > getDropDownsFor(const SwPaM &rPaM) const=0; virtual void deleteFieldmarkAt(const SwPosition& rPos) = 0; + virtual ::sw::mark::IFieldmark* changeNonTextFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType) = 0; // Annotation Marks virtual const_iterator_t getAnnotationMarksBegin() const = 0; diff --git a/sw/source/core/crsr/bookmrk.cxx b/sw/source/core/crsr/bookmrk.cxx index 92bb4c67d786..4bb6d6780295 100644 --- a/sw/source/core/crsr/bookmrk.cxx +++ b/sw/source/core/crsr/bookmrk.cxx @@ -478,6 +478,39 @@ namespace sw { namespace mark pResult->second >>= bResult; return bResult; } + + DropDownFieldmark::DropDownFieldmark(const SwPaM& rPaM) + : Fieldmark(rPaM) + { + } + + DropDownFieldmark::~DropDownFieldmark() + { + } + + void DropDownFieldmark::InitDoc(SwDoc* const io_pDoc, sw::mark::InsertMode const eMode) + { + if (eMode == sw::mark::InsertMode::New) + { + lcl_SetFieldMarks(this, io_pDoc, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT); + + // For some reason the end mark is moved from 1 by the Insert: + // we don't want this for checkboxes + SwPosition aNewEndPos = GetMarkEnd(); + aNewEndPos.nContent--; + SetMarkEndPos( aNewEndPos ); + } + else + { + lcl_AssertFieldMarksSet(this, CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT); + } + } + + void DropDownFieldmark::ReleaseDoc(SwDoc* const pDoc) + { + lcl_RemoveFieldMarks(this, pDoc, + CH_TXT_ATR_FIELDSTART, CH_TXT_ATR_FORMELEMENT); + } }} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx index e06908f3438a..d34508e1b254 100644 --- a/sw/source/core/doc/docbm.cxx +++ b/sw/source/core/doc/docbm.cxx @@ -338,6 +338,8 @@ IDocumentMarkAccess::MarkType IDocumentMarkAccess::GetType(const IMark& rBkmk) return MarkType::TEXT_FIELDMARK; else if(*pMarkTypeInfo == typeid(CheckboxFieldmark)) return MarkType::CHECKBOX_FIELDMARK; + else if(*pMarkTypeInfo == typeid(DropDownFieldmark)) + return MarkType::DROPDOWN_FIELDMARK; else if(*pMarkTypeInfo == typeid(NavigatorReminder)) return MarkType::NAVIGATOR_REMINDER; else @@ -414,6 +416,9 @@ namespace sw { namespace mark case IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK: pMark = std::shared_ptr<IMark>(new CheckboxFieldmark(rPaM)); break; + case IDocumentMarkAccess::MarkType::DROPDOWN_FIELDMARK: + pMark = std::shared_ptr<IMark>(new DropDownFieldmark(rPaM)); + break; case IDocumentMarkAccess::MarkType::NAVIGATOR_REMINDER: pMark = std::shared_ptr<IMark>(new NavigatorReminder(rPaM)); break; @@ -462,6 +467,7 @@ namespace sw { namespace mark break; case IDocumentMarkAccess::MarkType::TEXT_FIELDMARK: case IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK: + case IDocumentMarkAccess::MarkType::DROPDOWN_FIELDMARK: lcl_InsertMarkSorted(m_vFieldmarks, pMark); break; case IDocumentMarkAccess::MarkType::ANNOTATIONMARK: @@ -522,9 +528,20 @@ namespace sw { namespace mark bool bEnableSetModified = m_pDoc->getIDocumentState().IsEnableSetModified(); m_pDoc->getIDocumentState().SetEnableSetModified(false); - sw::mark::IMark* pMark = makeMark( rPaM, rName, - IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK, - sw::mark::InsertMode::New); + sw::mark::IMark* pMark = nullptr; + if(rType == ODF_FORMCHECKBOX) + { + pMark = makeMark( rPaM, rName, + IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK, + sw::mark::InsertMode::New); + } + else if(rType == ODF_FORMDROPDOWN) + { + pMark = makeMark( rPaM, rName, + IDocumentMarkAccess::MarkType::DROPDOWN_FIELDMARK, + sw::mark::InsertMode::New); + } + sw::mark::IFieldmark* pFieldMark = dynamic_cast<sw::mark::IFieldmark*>( pMark ); if (pFieldMark) pFieldMark->SetFieldname( rType ); @@ -934,6 +951,7 @@ namespace sw { namespace mark case IDocumentMarkAccess::MarkType::TEXT_FIELDMARK: case IDocumentMarkAccess::MarkType::CHECKBOX_FIELDMARK: + case IDocumentMarkAccess::MarkType::DROPDOWN_FIELDMARK: { IDocumentMarkAccess::iterator_t ppFieldmark = lcl_FindMark(m_vFieldmarks, *ppMark); if ( ppFieldmark != m_vFieldmarks.end() ) @@ -1077,6 +1095,32 @@ namespace sw { namespace mark deleteMark(lcl_FindMark(m_vAllMarks, *pFieldmark)); } + ::sw::mark::IFieldmark* MarkManager::changeNonTextFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType) + { + bool bActualChange = false; + if(rNewType == ODF_FORMDROPDOWN) + { + if (dynamic_cast<::sw::mark::CheckboxFieldmark*>(pFieldmark)) + bActualChange = true; + } + else if(rNewType == ODF_FORMCHECKBOX) + { + if (dynamic_cast<::sw::mark::DropDownFieldmark*>(pFieldmark)) + bActualChange = true; + } + + if (!bActualChange) + return nullptr; + + // Store attributes needed to create the new fieldmark + OUString sName = pFieldmark->GetName(); + SwPaM aPaM(pFieldmark->GetMarkPos()); + + // Remove the old fieldmark and create a new one with the new type + deleteFieldmarkAt(*aPaM.GetPoint()); + return makeNoTextFieldBookmark(aPaM, sName, rNewType); + } + IFieldmark* MarkManager::getDropDownFor(const SwPosition& rPos) const { diff --git a/sw/source/core/inc/MarkManager.hxx b/sw/source/core/inc/MarkManager.hxx index cbae235520e8..71ad5c913d6c 100644 --- a/sw/source/core/inc/MarkManager.hxx +++ b/sw/source/core/inc/MarkManager.hxx @@ -86,6 +86,7 @@ namespace sw { virtual std::vector< ::sw::mark::IFieldmark* > getDropDownsFor(const SwPaM &rPaM) const override; virtual void deleteFieldmarkAt(const SwPosition& rPos) override; + virtual ::sw::mark::IFieldmark* changeNonTextFieldmarkType(::sw::mark::IFieldmark* pFieldmark, const OUString& rNewType) override; void dumpAsXml(xmlTextWriterPtr pWriter) const; diff --git a/sw/source/core/inc/bookmrk.hxx b/sw/source/core/inc/bookmrk.hxx index 9bf1c9d7679c..3bde575ab399 100644 --- a/sw/source/core/inc/bookmrk.hxx +++ b/sw/source/core/inc/bookmrk.hxx @@ -245,6 +245,7 @@ namespace sw { virtual void ReleaseDoc(SwDoc* const pDoc) override; }; + /// Fieldmark representing a checkbox form field. class CheckboxFieldmark : virtual public ICheckboxFieldmark , public Fieldmark @@ -256,6 +257,17 @@ namespace sw { bool IsChecked() const override; void SetChecked(bool checked) override; }; + + /// Fieldmark representing a drop-down form field. + class DropDownFieldmark + : public Fieldmark + { + public: + DropDownFieldmark(const SwPaM& rPaM); + virtual ~DropDownFieldmark() override; + virtual void InitDoc(SwDoc* const io_pDoc, sw::mark::InsertMode eMode) override; + virtual void ReleaseDoc(SwDoc* const pDoc) override; + }; } } #endif diff --git a/sw/source/core/inc/unobookmark.hxx b/sw/source/core/inc/unobookmark.hxx index 95763c1b0a09..5c38402ba17c 100644 --- a/sw/source/core/inc/unobookmark.hxx +++ b/sw/source/core/inc/unobookmark.hxx @@ -68,6 +68,8 @@ protected: const ::sw::mark::IMark* GetBookmark() const; + IDocumentMarkAccess* GetIDocumentMarkAccess(); + void registerInMark( SwXBookmark& rXMark, ::sw::mark::IMark* const pMarkBase ); virtual ~SwXBookmark() override; diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx index 631373f98d99..2697f3022639 100644 --- a/sw/source/core/text/itrform2.cxx +++ b/sw/source/core/text/itrform2.cxx @@ -917,10 +917,6 @@ SwTextPortion *SwTextFormatter::WhichTextPor( SwTextFormatInfo &rInf ) const { pPor = new SwFieldMarkPortion(); } - else - { - assert( false ); // unknown type... - } } } if( !pPor ) diff --git a/sw/source/core/unocore/unobkm.cxx b/sw/source/core/unocore/unobkm.cxx index 753263a2aa6f..0a53c27c4516 100644 --- a/sw/source/core/unocore/unobkm.cxx +++ b/sw/source/core/unocore/unobkm.cxx @@ -134,6 +134,11 @@ const ::sw::mark::IMark* SwXBookmark::GetBookmark() const return m_pImpl->m_pRegisteredBookmark; } +IDocumentMarkAccess* SwXBookmark::GetIDocumentMarkAccess() +{ + return m_pImpl->m_pDoc->getIDocumentMarkAccess(); +} + SwXBookmark::SwXBookmark(SwDoc *const pDoc) : m_pImpl( new SwXBookmark::Impl(pDoc) ) { @@ -620,7 +625,21 @@ void SwXFieldmark::setFieldType(const OUString & fieldType) dynamic_cast<const IFieldmark*>(GetBookmark())); if(!pBkm) throw uno::RuntimeException(); - pBkm->SetFieldname(fieldType); + if(fieldType != getFieldType()) + { + if(fieldType == ODF_FORMDROPDOWN || fieldType == ODF_FORMCHECKBOX) + { + ::sw::mark::IFieldmark* pNewFieldmark = GetIDocumentMarkAccess()->changeNonTextFieldmarkType(pBkm, fieldType); + if (pNewFieldmark) + { + registerInMark(*this, pNewFieldmark); + return; + } + } + + // We did not generate a new fieldmark, so set the type ID + pBkm->SetFieldname(fieldType); + } } uno::Reference<container::XNameContainer> SwXFieldmark::getParameters() @@ -654,6 +673,8 @@ SwXFieldmark::CreateXFieldmark(SwDoc & rDoc, ::sw::mark::IMark *const pMark, pXBkmk = new SwXFieldmark(false, &rDoc); else if (dynamic_cast< ::sw::mark::CheckboxFieldmark* >(pMark)) pXBkmk = new SwXFieldmark(true, &rDoc); + else if (dynamic_cast< ::sw::mark::DropDownFieldmark* >(pMark)) + pXBkmk = new SwXFieldmark(true, &rDoc); else pXBkmk = new SwXFieldmark(isReplacementObject, &rDoc); diff --git a/writerfilter/source/dmapper/FormControlHelper.cxx b/writerfilter/source/dmapper/FormControlHelper.cxx index 3088a4a27361..98e7bb0ba319 100644 --- a/writerfilter/source/dmapper/FormControlHelper.cxx +++ b/writerfilter/source/dmapper/FormControlHelper.cxx @@ -202,6 +202,20 @@ bool FormControlHelper::createCheckbox(uno::Reference<text::XTextRange> const& x void FormControlHelper::processField(uno::Reference<text::XFormField> const& xFormField) { + // Set field type first before adding parameters. + if (m_pImpl->m_eFieldId == FIELD_FORMTEXT ) + { + xFormField->setFieldType(ODF_FORMTEXT); + } + else if (m_pImpl->m_eFieldId == FIELD_FORMCHECKBOX ) + { + xFormField->setFieldType(ODF_FORMCHECKBOX); + } + else if (m_pImpl->m_eFieldId == FIELD_FORMDROPDOWN ) + { + xFormField->setFieldType(ODF_FORMDROPDOWN); + } + uno::Reference<container::XNameContainer> xNameCont = xFormField->getParameters(); uno::Reference<container::XNamed> xNamed( xFormField, uno::UNO_QUERY ); if ( m_pFFData && xNamed.is() && xNameCont.is() ) @@ -223,7 +237,6 @@ void FormControlHelper::processField(uno::Reference<text::XFormField> const& xFo if (m_pImpl->m_eFieldId == FIELD_FORMTEXT ) { - xFormField->setFieldType(ODF_FORMTEXT); sTmp = m_pFFData->getName(); try { @@ -255,7 +268,6 @@ void FormControlHelper::processField(uno::Reference<text::XFormField> const& xFo } else if (m_pImpl->m_eFieldId == FIELD_FORMCHECKBOX ) { - xFormField->setFieldType(ODF_FORMCHECKBOX); uno::Reference<beans::XPropertySet> xPropSet(xFormField, uno::UNO_QUERY); uno::Any aAny; aAny <<= m_pFFData->getCheckboxChecked(); @@ -264,7 +276,6 @@ void FormControlHelper::processField(uno::Reference<text::XFormField> const& xFo } else if (m_pImpl->m_eFieldId == FIELD_FORMDROPDOWN ) { - xFormField->setFieldType(ODF_FORMDROPDOWN); const FFDataHandler::DropDownEntries_t& rEntries = m_pFFData->getDropDownEntries(); if (!rEntries.empty()) { |