officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu | 13 ++ sw/inc/cmdid.h | 1 sw/inc/formatcontentcontrol.hxx | 6 + sw/qa/uibase/wrtsh/wrtsh.cxx | 23 +++- sw/sdi/_textsh.sdi | 6 + sw/sdi/swriter.sdi | 17 ++ sw/source/uibase/inc/wrtsh.hxx | 3 sw/source/uibase/shells/textsh.cxx | 8 + sw/source/uibase/uiview/view.cxx | 2 sw/source/uibase/wrtsh/wrtsh1.cxx | 31 ++++- sw/uiconfig/swriter/menubar/menubar.xml | 7 + writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx | 46 ++++++++ writerfilter/qa/cppunittests/dmapper/data/sdt-run-checkbox.docx |binary writerfilter/source/dmapper/DomainMapper.cxx | 57 +++++++++- writerfilter/source/dmapper/DomainMapper_Impl.cxx | 21 +++ writerfilter/source/dmapper/DomainMapper_Impl.hxx | 4 writerfilter/source/dmapper/SdtHelper.cxx | 18 +++ writerfilter/source/dmapper/SdtHelper.hxx | 23 +++- writerfilter/source/dmapper/TextEffectsHandler.cxx | 1 writerfilter/source/dmapper/TextEffectsHandler.hxx | 8 - writerfilter/source/ooxml/model.xml | 7 - 21 files changed, 278 insertions(+), 24 deletions(-)
New commits: commit 018776f52ffa14a579b0ea752a2b59de1a62b4e4 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon May 2 08:43:19 2022 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue May 3 13:29:26 2022 +0200 sw content controls, checkbox: add insert UI - extend SwWrtShell::InsertContentControl() to be able to create multiple content control types - a new checkbox content control's content is always a non-checked checkbox - expose this as a new .uno:InsertCheckboxContentControl uno command - add this new command to the bottom of the form menu -- now that we have two types of content controls, have that in a sub-menu (cherry picked from commit 02a5bd2e6c4eee50cbd8cb4ed009731c409711a5) Change-Id: I058659600b3face69b89262feb0979fff32521c4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133744 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu index 86c6302f6e18..b15b1ebb6a30 100644 --- a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu +++ b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu @@ -614,6 +614,11 @@ <value>1</value> </prop> </node> + <node oor:name=".uno:ContentControlsMenu" oor:op="replace"> + <prop oor:name="Label" oor:type="xs:string"> + <value xml:lang="en-US">Content Controls</value> + </prop> + </node> <node oor:name=".uno:InsertContentControl" oor:op="replace"> <prop oor:name="Label" oor:type="xs:string"> <value xml:lang="en-US">Insert Rich Text Content Control</value> @@ -622,6 +627,14 @@ <value>1</value> </prop> </node> + <node oor:name=".uno:InsertCheckboxContentControl" oor:op="replace"> + <prop oor:name="Label" oor:type="xs:string"> + <value xml:lang="en-US">Insert Check Box Content Control</value> + </prop> + <prop oor:name="Properties" oor:type="xs:int"> + <value>1</value> + </prop> + </node> <node oor:name=".uno:InsertObjectDialog" oor:op="replace"> <prop oor:name="Label" oor:type="xs:string"> <value xml:lang="en-US">Insert Other Objects</value> diff --git a/sw/inc/cmdid.h b/sw/inc/cmdid.h index 8499a54b2b28..6f3673b62811 100644 --- a/sw/inc/cmdid.h +++ b/sw/inc/cmdid.h @@ -211,6 +211,7 @@ #define FN_INSERT_LINEBREAK (FN_INSERT + 18) /* Newline */ #define FN_INSERT_FIELD_DATA_ONLY (FN_INSERT + 19) /* Field dialog for mail merge*/ #define FN_INSERT_CONTENT_CONTROL (FN_INSERT + 20) /* Content control */ +#define FN_INSERT_CHECKBOX_CONTENT_CONTROL (FN_INSERT + 21) /* Checkbox content control */ #define FN_INSERT_OBJECT_DLG (FN_INSERT + 22) /* Object */ #define FN_INSERT_PAGEBREAK (FN_INSERT + 23) /* Page break*/ #define FN_POSTIT (FN_INSERT + 29) /* Insert/edit PostIt */ diff --git a/sw/inc/formatcontentcontrol.hxx b/sw/inc/formatcontentcontrol.hxx index 54804612a2b5..43309f49f55c 100644 --- a/sw/inc/formatcontentcontrol.hxx +++ b/sw/inc/formatcontentcontrol.hxx @@ -31,6 +31,12 @@ class SwTextContentControl; class SwTextNode; class SwXContentControl; +enum class SwContentControlType +{ + RICH_TEXT, + CHECKBOX, +}; + /// SfxPoolItem subclass that wraps an SwContentControl. class SwFormatContentControl final : public SfxPoolItem { diff --git a/sw/qa/uibase/wrtsh/wrtsh.cxx b/sw/qa/uibase/wrtsh/wrtsh.cxx index b4d4cca09df6..5fddff1d884f 100644 --- a/sw/qa/uibase/wrtsh/wrtsh.cxx +++ b/sw/qa/uibase/wrtsh/wrtsh.cxx @@ -136,7 +136,7 @@ CPPUNIT_TEST_FIXTURE(Test, testInsertContentControl) // When inserting a content control: SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); - pWrtShell->InsertContentControl(); + pWrtShell->InsertContentControl(SwContentControlType::RICH_TEXT); // Then make sure that the matching text attribute is added to the document model: SwTextNode* pTextNode = pWrtShell->GetCursor()->GetNode().GetTextNode(); @@ -144,6 +144,27 @@ CPPUNIT_TEST_FIXTURE(Test, testInsertContentControl) // InsertContentControl(). CPPUNIT_ASSERT(pTextNode->GetTextAttrForCharAt(0, RES_TXTATR_CONTENTCONTROL)); } + +CPPUNIT_TEST_FIXTURE(Test, testInsertCheckboxContentControl) +{ + // Given an empty document: + SwDoc* pDoc = createSwDoc(); + + // When inserting a content control: + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + pWrtShell->InsertContentControl(SwContentControlType::CHECKBOX); + + // Then make sure that the matching text attribute is added to the document model: + SwTextNode* pTextNode = pWrtShell->GetCursor()->GetNode().GetTextNode(); + SwTextAttr* pAttr = pTextNode->GetTextAttrForCharAt(0, RES_TXTATR_CONTENTCONTROL); + auto pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr); + auto& rFormatContentControl + = static_cast<SwFormatContentControl&>(pTextContentControl->GetAttr()); + SwContentControl* pContentControl = rFormatContentControl.GetContentControl(); + // Without the accompanying fix in place, this test would have failed, the inserted content + // control wasn't a checkbox one. + CPPUNIT_ASSERT(pContentControl->GetCheckbox()); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/sdi/_textsh.sdi b/sw/sdi/_textsh.sdi index f1689474467f..8c76493bf36b 100644 --- a/sw/sdi/_textsh.sdi +++ b/sw/sdi/_textsh.sdi @@ -278,6 +278,12 @@ interface BaseText StateMethod = NoState ; DisableFlags="SfxDisableFlags::SwOnProtectedCursor"; ] + FN_INSERT_CHECKBOX_CONTENT_CONTROL // status(final|play) + [ + ExecMethod = ExecInsert ; + StateMethod = NoState ; + DisableFlags="SfxDisableFlags::SwOnProtectedCursor"; + ] FN_INSERT_COLUMN_BREAK // status(final|play) [ ExecMethod = ExecInsert ; diff --git a/sw/sdi/swriter.sdi b/sw/sdi/swriter.sdi index 16922267cf85..93d16693c296 100644 --- a/sw/sdi/swriter.sdi +++ b/sw/sdi/swriter.sdi @@ -3049,6 +3049,23 @@ SfxVoidItem InsertContentControl FN_INSERT_CONTENT_CONTROL GroupId = SfxGroupId::Insert; ] +SfxVoidItem InsertCheckboxContentControl FN_INSERT_CHECKBOX_CONTENT_CONTROL +() +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = FALSE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = TRUE, + MenuConfig = TRUE, + ToolBoxConfig = TRUE, + GroupId = SfxGroupId::Insert; +] + SfxVoidItem InsertMultiIndex FN_INSERT_MULTI_TOX () [ diff --git a/sw/source/uibase/inc/wrtsh.hxx b/sw/source/uibase/inc/wrtsh.hxx index 37d82557ac03..a80f42c8315a 100644 --- a/sw/source/uibase/inc/wrtsh.hxx +++ b/sw/source/uibase/inc/wrtsh.hxx @@ -55,6 +55,7 @@ class SwFieldMgr; class SfxRequest; enum class SwLineBreakClear; class SwContentControl; +enum class SwContentControlType; namespace i18nutil { struct SearchOptions2; @@ -316,7 +317,7 @@ typedef bool (SwWrtShell::*FNSimpleMove)(); void InsertPageBreak(const OUString *pPageDesc = nullptr, const ::std::optional<sal_uInt16>& rPgNum = std::nullopt); void InsertLineBreak(std::optional<SwLineBreakClear> oClear = std::nullopt); void InsertColumnBreak(); - void InsertContentControl(); + void InsertContentControl(SwContentControlType eType); void InsertFootnote(const OUString &, bool bEndNote = false, bool bEdit = true ); void SplitNode( bool bAutoFormat = false ); bool CanInsert(); diff --git a/sw/source/uibase/shells/textsh.cxx b/sw/source/uibase/shells/textsh.cxx index 7fec748ba488..e8b05efb83b2 100644 --- a/sw/source/uibase/shells/textsh.cxx +++ b/sw/source/uibase/shells/textsh.cxx @@ -91,6 +91,7 @@ using namespace ::com::sun::star; #include <com/sun/star/ui/dialogs/DialogClosedEvent.hpp> #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> #include <IDocumentUndoRedo.hxx> +#include <formatcontentcontrol.hxx> SFX_IMPL_INTERFACE(SwTextShell, SwBaseShell) @@ -219,7 +220,12 @@ void SwTextShell::ExecInsert(SfxRequest &rReq) break; case FN_INSERT_CONTENT_CONTROL: - rSh.InsertContentControl(); + rSh.InsertContentControl(SwContentControlType::RICH_TEXT); + rReq.Done(); + break; + + case FN_INSERT_CHECKBOX_CONTENT_CONTROL: + rSh.InsertContentControl(SwContentControlType::CHECKBOX); rReq.Done(); break; diff --git a/sw/source/uibase/uiview/view.cxx b/sw/source/uibase/uiview/view.cxx index b43ff17782fc..2fe2ad061456 100644 --- a/sw/source/uibase/uiview/view.cxx +++ b/sw/source/uibase/uiview/view.cxx @@ -594,7 +594,7 @@ void SwView::CheckReadonlyState() SID_CHARMAP, SID_EMOJI_CONTROL, FN_INSERT_SOFT_HYPHEN, FN_INSERT_HARDHYPHEN, FN_INSERT_HARD_SPACE, FN_INSERT_NNBSP, FN_INSERT_BREAK, FN_INSERT_LINEBREAK, FN_INSERT_COLUMN_BREAK, - FN_INSERT_BREAK_DLG, FN_INSERT_CONTENT_CONTROL, + FN_INSERT_BREAK_DLG, FN_INSERT_CONTENT_CONTROL, FN_INSERT_CHECKBOX_CONTENT_CONTROL, FN_DELETE_SENT, FN_DELETE_BACK_SENT, FN_DELETE_WORD, FN_DELETE_BACK_WORD, FN_DELETE_LINE, FN_DELETE_BACK_LINE, FN_DELETE_PARA, FN_DELETE_BACK_PARA, FN_DELETE_WHOLE_LINE, diff --git a/sw/source/uibase/wrtsh/wrtsh1.cxx b/sw/source/uibase/wrtsh/wrtsh1.cxx index 1d93f1e31983..78e18197f39b 100644 --- a/sw/source/uibase/wrtsh/wrtsh1.cxx +++ b/sw/source/uibase/wrtsh/wrtsh1.cxx @@ -1007,7 +1007,7 @@ void SwWrtShell::InsertColumnBreak() EndUndo(SwUndoId::UI_INSERT_COLUMN_BREAK); } -void SwWrtShell::InsertContentControl() +void SwWrtShell::InsertContentControl(SwContentControlType eType) { if (!lcl_IsAllowed(this)) { @@ -1021,13 +1021,32 @@ void SwWrtShell::InsertContentControl() } auto pContentControl = std::make_shared<SwContentControl>(nullptr); - pContentControl->SetShowingPlaceHolder(true); - if (!HasSelection()) + OUString aPlaceholder; + switch (eType) { - OUString aPlaceholder = SwResId(STR_CONTENT_CONTROL_PLACEHOLDER); - Insert(aPlaceholder); - Left(CRSR_SKIP_CHARS, /*bSelect=*/true, aPlaceholder.getLength(), /*bBasicCall=*/false); + case SwContentControlType::RICH_TEXT: + { + pContentControl->SetShowingPlaceHolder(true); + if (!HasSelection()) + { + aPlaceholder = SwResId(STR_CONTENT_CONTROL_PLACEHOLDER); + } + break; + } + case SwContentControlType::CHECKBOX: + { + pContentControl->SetCheckbox(true); + // Ballot Box with X + pContentControl->SetCheckedState(u"\u2612"); + // Ballot Box + pContentControl->SetUncheckedState(OUString(u"\u2610")); + aPlaceholder = u"\u2610"; + break; + } } + Insert(aPlaceholder); + Left(CRSR_SKIP_CHARS, /*bSelect=*/true, aPlaceholder.getLength(), + /*bBasicCall=*/false); SwFormatContentControl aContentControl(pContentControl, RES_TXTATR_CONTENTCONTROL); SetAttrItem(aContentControl); } diff --git a/sw/uiconfig/swriter/menubar/menubar.xml b/sw/uiconfig/swriter/menubar/menubar.xml index 526cbac6a8ca..e40052d1384a 100644 --- a/sw/uiconfig/swriter/menubar/menubar.xml +++ b/sw/uiconfig/swriter/menubar/menubar.xml @@ -710,7 +710,12 @@ <menu:menuitem menu:id=".uno:OpenReadOnly"/> <menu:menuitem menu:id=".uno:AutoControlFocus"/> <menu:menuseparator/> - <menu:menuitem menu:id=".uno:InsertContentControl"/> + <menu:menu menu:id=".uno:ContentControlsMenu"> + <menu:menupopup> + <menu:menuitem menu:id=".uno:InsertContentControl"/> + <menu:menuitem menu:id=".uno:InsertCheckboxContentControl"/> + </menu:menupopup> + </menu:menu> </menu:menupopup> </menu:menu> <menu:menu menu:id=".uno:ToolsMenu"> commit 55e63a2b953be99ceb742407263be92eb3a54df4 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Fri Apr 29 08:12:25 2022 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Tue May 3 13:29:08 2022 +0200 sw content controls, checkbox: add DOCX import My expectation was that <w14:checked w14:val="0"/> would be mapped to a single SPRM where the int value is 0 or 1 depending on if this is a true or false boolean. But the w14 tokenizer rules actually created a NS_ooxml::LN_CT_SdtCheckbox_checked token with a NS_ooxml::LN_CT_OnOff_val token in it, which itself again didn't contain just a bool but dedicated NS_ooxml::LN_ST_OnOff_true, NS_ooxml::LN_ST_OnOff_1, etc values. To make this more complicated, TextEffectsHandler even depends on this weird behavior. Bring the w14 rules closer to the "main" wml rules by folding the NS_ooxml::LN_CT_OnOff_val token into the parent token (NS_ooxml::LN_CT_SdtCheckbox_checked in this case), but leave the NS_ooxml::LN_ST_OnOff_* values unchanged for now. The rest of the changes are more straightforward: we now handle inline/run checkbox SDTs similar to rich text ones, i.e. map them to Writer content controls, rather than just doing a poor mapping to grab-bags. The main benefit here is that the checkbox type of Writer content controls actually change their value on mouse click, so it's possible to fill in such forms. (cherry picked from commit c53d3a1f4b8430507d54f5fac336870df7a700af) Conflicts: writerfilter/source/dmapper/SdtHelper.hxx Change-Id: Idbf49a8ff1843d5271f2836e5299c4387bb58e55 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133743 Tested-by: Miklos Vajna <vmik...@collabora.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx b/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx index da2663b93409..c96cb604f91f 100644 --- a/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx +++ b/writerfilter/qa/cppunittests/dmapper/SdtHelper.cxx @@ -84,6 +84,52 @@ CPPUNIT_TEST_FIXTURE(Test, testSdtRunRichText) xContent->getPropertyValue("CharHeight") >>= fCharheight; CPPUNIT_ASSERT_EQUAL(24.f, fCharheight); } + +CPPUNIT_TEST_FIXTURE(Test, testSdtRunCheckbox) +{ + // Given a document with a checkbox inline/run SDT: + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "sdt-run-checkbox.docx"; + + // When loading the document: + getComponent() = loadFromDesktop(aURL); + + // Then make sure that the doc model has a clickable checkbox content control: + uno::Reference<text::XTextDocument> xTextDocument(getComponent(), uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(), + uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration(); + uno::Reference<container::XEnumerationAccess> xPara(xParaEnum->nextElement(), uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xPortionEnum = xPara->createEnumeration(); + uno::Reference<beans::XPropertySet> xPortion(xPortionEnum->nextElement(), uno::UNO_QUERY); + OUString aTextPortionType; + xPortion->getPropertyValue("TextPortionType") >>= aTextPortionType; + // Without the accompanying fix in place, this test would have failed with: + // - Expected: ContentControl + // - Actual : Text + // i.e. the SDT was imported as plain text, making it hard to fill in checkboxes. + CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aTextPortionType); + uno::Reference<text::XTextContent> xContentControl; + xPortion->getPropertyValue("ContentControl") >>= xContentControl; + uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY); + bool bCheckbox{}; + xContentControlProps->getPropertyValue("Checkbox") >>= bCheckbox; + CPPUNIT_ASSERT(bCheckbox); + bool bChecked{}; + xContentControlProps->getPropertyValue("Checked") >>= bChecked; + CPPUNIT_ASSERT(bChecked); + OUString aCheckedState; + xContentControlProps->getPropertyValue("CheckedState") >>= aCheckedState; + CPPUNIT_ASSERT_EQUAL(OUString(u"☒"), aCheckedState); + OUString aUncheckedState; + xContentControlProps->getPropertyValue("UncheckedState") >>= aUncheckedState; + CPPUNIT_ASSERT_EQUAL(OUString(u"☐"), aUncheckedState); + uno::Reference<text::XTextRange> xContentControlRange(xContentControl, uno::UNO_QUERY); + uno::Reference<text::XText> xText = xContentControlRange->getText(); + uno::Reference<container::XEnumerationAccess> xContentEnumAccess(xText, uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xContentEnum = xContentEnumAccess->createEnumeration(); + uno::Reference<text::XTextRange> xContent(xContentEnum->nextElement(), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(OUString(u"☒"), xContent->getString()); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/qa/cppunittests/dmapper/data/sdt-run-checkbox.docx b/writerfilter/qa/cppunittests/dmapper/data/sdt-run-checkbox.docx new file mode 100644 index 000000000000..c6718b97c2a0 Binary files /dev/null and b/writerfilter/qa/cppunittests/dmapper/data/sdt-run-checkbox.docx differ diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index 59215a9d6aa5..2bd6ece56ad4 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -1083,6 +1083,7 @@ void DomainMapper::lcl_attribute(Id nName, Value & val) { m_pImpl->m_pSdtHelper->setControlType(SdtControlType::richText); m_pImpl->PushSdt(); + break; } } m_pImpl->SetSdt(true); @@ -1094,6 +1095,7 @@ void DomainMapper::lcl_attribute(Id nName, Value & val) switch (m_pImpl->m_pSdtHelper->getControlType()) { case SdtControlType::richText: + case SdtControlType::checkBox: m_pImpl->PopSdt(); break; default: @@ -2771,6 +2773,20 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) case NS_ooxml::LN_CT_SdtPlaceholder_docPart: case NS_ooxml::LN_CT_SdtPr_color: { + if (!m_pImpl->GetSdtStarts().empty()) + { + if (nSprmId == NS_ooxml::LN_CT_SdtPr_checkbox) + { + m_pImpl->m_pSdtHelper->setControlType(SdtControlType::checkBox); + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if (pProperties) + { + pProperties->resolve(*this); + } + break; + } + } + // this is an unsupported SDT property, create a grab bag for it OUString sName; switch (nSprmId) @@ -2819,13 +2835,42 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) } break; case NS_ooxml::LN_CT_SdtCheckbox_checked: - m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtCheckbox_checked", sStringValue); + if (!m_pImpl->GetSdtStarts().empty()) + { + // nIntValue is not just 0 or 1, because we're in the w14 namespace's ST_OnOff. + if (nIntValue == NS_ooxml::LN_ST_OnOff_true || nIntValue == NS_ooxml::LN_ST_OnOff_1) + { + m_pImpl->m_pSdtHelper->SetChecked(); + } + } + else + { + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtCheckbox_checked", + TextEffectsHandler::getOnOffString(nIntValue)); + } break; case NS_ooxml::LN_CT_SdtCheckbox_checkedState: - m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtCheckbox_checkedState", sStringValue); + if (!m_pImpl->GetSdtStarts().empty()) + { + m_pImpl->m_pSdtHelper->SetCheckedState(OUString(sal_Unicode(sStringValue.toInt32(16)))); + } + else + { + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtCheckbox_checkedState", + sStringValue); + } break; case NS_ooxml::LN_CT_SdtCheckbox_uncheckedState: - m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtCheckbox_uncheckedState", sStringValue); + if (!m_pImpl->GetSdtStarts().empty()) + { + m_pImpl->m_pSdtHelper->SetUncheckedState( + OUString(sal_Unicode(sStringValue.toInt32(16)))); + } + else + { + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, + "ooxml:CT_SdtCheckbox_uncheckedState", sStringValue); + } break; case NS_ooxml::LN_CT_SdtDocPart_docPartGallery: m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtDocPart_docPartGallery", sStringValue); @@ -2931,6 +2976,12 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) rContext->Insert(PROP_CHAR_TRANSPARENCE, uno::makeAny(nTransparency)); } } + else if (nSprmId == NS_ooxml::LN_cntxtAlts_cntxtAlts) + { + pTextEffectsHandlerPtr->lcl_sprm(rSprm); + beans::PropertyValue aGrabBag = pTextEffectsHandlerPtr->getInteropGrabBag(); + rContext->Insert(*aPropertyId, uno::makeAny(aGrabBag), true, CHAR_GRAB_BAG); + } } } break; diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index 3edffc00121f..760a923c1c00 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -844,6 +844,11 @@ void DomainMapper_Impl::PushSdt() m_xSdtStarts.push({bStart, OUString(), xCursor->getStart()}); } +const std::stack<BookmarkInsertPosition>& DomainMapper_Impl::GetSdtStarts() const +{ + return m_xSdtStarts; +} + void DomainMapper_Impl::PopSdt() { if (m_xSdtStarts.empty()) @@ -881,7 +886,23 @@ void DomainMapper_Impl::PopSdt() xContentControlProps->setPropertyValue("ShowingPlaceHolder", uno::makeAny(m_pSdtHelper->GetShowingPlcHdr())); } + + if (m_pSdtHelper->getControlType() == SdtControlType::checkBox) + { + xContentControlProps->setPropertyValue("Checkbox", uno::makeAny(true)); + + xContentControlProps->setPropertyValue("Checked", uno::makeAny(m_pSdtHelper->GetChecked())); + + xContentControlProps->setPropertyValue("CheckedState", + uno::makeAny(m_pSdtHelper->GetCheckedState())); + + xContentControlProps->setPropertyValue("UncheckedState", + uno::makeAny(m_pSdtHelper->GetUncheckedState())); + } + xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true); + + m_pSdtHelper->clear(); } void DomainMapper_Impl::PushProperties(ContextType eId) diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx index 3b4602f252b5..67ed5b090e4e 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -716,8 +716,12 @@ public: /// Setter method for m_bSdt. void SetSdt(bool bSdt); + void PushSdt(); void PopSdt(); + /// Gives access to the currently open run/inline SDTs. + const std::stack<BookmarkInsertPosition>& GetSdtStarts() const; + /// Getter method for m_bSdt. bool GetSdt() const { return m_bSdt;} bool GetParaChanged() const { return m_bParaChanged;} diff --git a/writerfilter/source/dmapper/SdtHelper.cxx b/writerfilter/source/dmapper/SdtHelper.cxx index 0d91a242c0d5..23c8ba0e4dc4 100644 --- a/writerfilter/source/dmapper/SdtHelper.cxx +++ b/writerfilter/source/dmapper/SdtHelper.cxx @@ -425,6 +425,21 @@ void SdtHelper::SetShowingPlcHdr() { m_bShowingPlcHdr = true; } bool SdtHelper::GetShowingPlcHdr() const { return m_bShowingPlcHdr; } +void SdtHelper::SetChecked() { m_bChecked = true; } + +bool SdtHelper::GetChecked() const { return m_bChecked; } + +void SdtHelper::SetCheckedState(const OUString& rCheckedState) { m_aCheckedState = rCheckedState; } + +OUString SdtHelper::GetCheckedState() const { return m_aCheckedState; } + +void SdtHelper::SetUncheckedState(const OUString& rUncheckedState) +{ + m_aUncheckedState = rUncheckedState; +} + +OUString SdtHelper::GetUncheckedState() const { return m_aUncheckedState; } + void SdtHelper::clear() { m_aDropDownItems.clear(); @@ -434,6 +449,9 @@ void SdtHelper::clear() m_sDataBindingStoreItemID.clear(); m_aGrabBag.clear(); m_bShowingPlcHdr = false; + m_bChecked = false; + m_aCheckedState.clear(); + m_aUncheckedState.clear(); } } // namespace writerfilter::dmapper diff --git a/writerfilter/source/dmapper/SdtHelper.hxx b/writerfilter/source/dmapper/SdtHelper.hxx index 578bb5edd4fd..dfc43c80fce8 100644 --- a/writerfilter/source/dmapper/SdtHelper.hxx +++ b/writerfilter/source/dmapper/SdtHelper.hxx @@ -43,6 +43,7 @@ enum class SdtControlType dropDown, plainText, richText, + checkBox, unsupported, // Sdt block is defined, but we still do not support such type of field unknown }; @@ -97,6 +98,15 @@ class SdtHelper final : public virtual SvRefBase /// Current contents are placeholder text. bool m_bShowingPlcHdr = false; + /// If this is a checkbox, is the checkbox checked? + bool m_bChecked = false; + + /// If this is a checkbox, the value of a checked checkbox. + OUString m_aCheckedState; + + /// If this is a checkbox, the value of an unchecked checkbox. + OUString m_aUncheckedState; + /// Create and append the drawing::XControlShape, containing the various models. void createControlShape(css::awt::Size aSize, css::uno::Reference<css::awt::XControlModel> const& xControlModel, @@ -106,9 +116,6 @@ class SdtHelper final : public virtual SvRefBase void loadPropertiesXMLs(); - /// Clear all collected attributes for futher reuse - void clear(); - public: explicit SdtHelper(DomainMapper_Impl& rDM_Impl, css::uno::Reference<css::uno::XComponentContext> const& xContext); @@ -162,6 +169,16 @@ public: void SetShowingPlcHdr(); bool GetShowingPlcHdr() const; + + void SetChecked(); + bool GetChecked() const; + void SetCheckedState(const OUString& rCheckedState); + OUString GetCheckedState() const; + void SetUncheckedState(const OUString& rUncheckedState); + OUString GetUncheckedState() const; + + /// Clear all collected attributes for further reuse + void clear(); }; } // namespace writerfilter::dmapper diff --git a/writerfilter/source/dmapper/TextEffectsHandler.cxx b/writerfilter/source/dmapper/TextEffectsHandler.cxx index 3288556c8979..d145c854fc80 100644 --- a/writerfilter/source/dmapper/TextEffectsHandler.cxx +++ b/writerfilter/source/dmapper/TextEffectsHandler.cxx @@ -66,6 +66,7 @@ OUString lclGetNameForElementId(sal_uInt32 aId) aIdMap[NS_ooxml::LN_CT_Props3D_extrusionClr] = "extrusionClr"; aIdMap[NS_ooxml::LN_CT_Props3D_contourClr] = "contourClr"; aIdMap[NS_ooxml::LN_CT_StylisticSets_styleSet] = "styleSet"; + aIdMap[NS_ooxml::LN_cntxtAlts_cntxtAlts] = "cntxtAlts"; } return aIdMap[aId]; } diff --git a/writerfilter/source/dmapper/TextEffectsHandler.hxx b/writerfilter/source/dmapper/TextEffectsHandler.hxx index 22127c6c81b2..30a8435b2829 100644 --- a/writerfilter/source/dmapper/TextEffectsHandler.hxx +++ b/writerfilter/source/dmapper/TextEffectsHandler.hxx @@ -33,10 +33,6 @@ private: void convertElementIdToPropertyId(sal_Int32 aElementId); - // LoggedProperties - virtual void lcl_attribute(Id aName, Value& aValue) override; - virtual void lcl_sprm(Sprm& sprm) override; - public: explicit TextEffectsHandler(sal_uInt32 aElementId); virtual ~TextEffectsHandler() override; @@ -63,6 +59,10 @@ public: static OUString getNumSpacingString(sal_Int32 nType); static sal_uInt8 GetTextFillSolidFillAlpha(const css::beans::PropertyValue& rValue); + + // LoggedProperties + virtual void lcl_attribute(Id aName, Value& aValue) override; + virtual void lcl_sprm(Sprm& sprm) override; }; } diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml index 04fb1934b8d5..38dd9ba15b08 100644 --- a/writerfilter/source/ooxml/model.xml +++ b/writerfilter/source/ooxml/model.xml @@ -4886,7 +4886,7 @@ </define> <define name="CT_SdtCheckbox"> <element name="checked"> - <ref name="CT_String"/> + <ref name="CT_OnOff"/> </element> <element name="checkedState"> <ref name="CT_String"/> @@ -5260,8 +5260,9 @@ <attribute name="id" tokenid="ooxml:CT_StyleSet_id"/> <attribute name="val" tokenid="ooxml:CT_StyleSet_val"/> </resource> - <resource name="CT_OnOff" resource="Properties"> - <attribute name="val" tokenid="ooxml:CT_OnOff_val"/> + <resource name="CT_OnOff" resource="Value"> + <attribute name="val" tokenid="ooxml:CT_OnOff_val" action="setValue"/> + <action name="start" action="setDefaultBooleanValue"/> </resource> <!-- Main element content -->