diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2022-06-10 08:16:48 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2022-06-13 08:07:02 +0200 |
commit | c321498f915f4e8b3f4853232860ce040ab48e46 (patch) | |
tree | d29f5b59e086d287791a19bdbef52b162a8ca7fe /sw | |
parent | 37dde4ef13dee5107249ff6604c0bb134235143e (diff) |
sw content controls: reject typing inside checkbox or picture content controls
Content controls are editable by default (and not only editable, but
also capable of hosting rich text content), and Writer doesn't limit
the possibility to edit explicitly, either.
Certain content control types (checkbox and picture for now) limit the
hosted content though: checkbox overwrites the content on click and
picture is meant to host a single as-char anchored image. So far the
simple implementation Writer didn't enforce these limits, leading the
unexpected behavior when clicking on checkbox content controls (possibly
not only a checked/non-checked checkmark was toggled, but other content
was removed).
Fix the problem by making these content control types read-only: this is
what also Word does and this way you can't loose the content when you
can't enter it earlier.
We may want to also do this for dropdowns in the future, once combo
boxes will be supported.
Change-Id: I9d44206b3c719a64ec552f2fa0a076901094163e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135574
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Diffstat (limited to 'sw')
-rw-r--r-- | sw/inc/formatcontentcontrol.hxx | 10 | ||||
-rw-r--r-- | sw/qa/core/crsr/crsr.cxx | 28 | ||||
-rw-r--r-- | sw/source/core/crsr/pam.cxx | 26 | ||||
-rw-r--r-- | sw/source/uibase/wrtsh/wrtsh3.cxx | 2 |
4 files changed, 66 insertions, 0 deletions
diff --git a/sw/inc/formatcontentcontrol.hxx b/sw/inc/formatcontentcontrol.hxx index 17ff97cd1fa6..82f4fca9e2be 100644 --- a/sw/inc/formatcontentcontrol.hxx +++ b/sw/inc/formatcontentcontrol.hxx @@ -160,6 +160,12 @@ class SW_DLLPUBLIC SwContentControl : public sw::BroadcastingModify /// Stores a date timestamp, in case the doc model is not yet updated. std::optional<double> m_oSelectedDate; + /** + * E.g. checkbox is read-only by default, but we still update contents on interaction + * internally. This flag is true for the duration of that interaction. + */ + bool m_bReadWrite = false; + public: SwTextContentControl* GetTextAttr() const; @@ -292,6 +298,10 @@ public: void SetColor(const OUString& rColor) { m_aColor = rColor; } OUString GetColor() const { return m_aColor; } + + void SetReadWrite(bool bReadWrite) { m_bReadWrite = bReadWrite; } + + bool GetReadWrite() const { return m_bReadWrite; } }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/core/crsr/crsr.cxx b/sw/qa/core/crsr/crsr.cxx index 882f9b6bcbab..8f8d9963a285 100644 --- a/sw/qa/core/crsr/crsr.cxx +++ b/sw/qa/core/crsr/crsr.cxx @@ -136,6 +136,34 @@ CPPUNIT_TEST_FIXTURE(SwCoreCrsrTest, testContentControlLineBreak) CPPUNIT_ASSERT_EQUAL(OUString("t\nest"), pTextNode->GetExpandText(pWrtShell->GetLayout())); } +CPPUNIT_TEST_FIXTURE(SwCoreCrsrTest, testContentControlReadOnly) +{ + // Given a document with a checkbox content control: + SwDoc* pDoc = createSwDoc(); + uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XText> xText = xTextDocument->getText(); + uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor(); + xText->insertString(xCursor, u"☐", /*bAbsorb=*/false); + xCursor->gotoStart(/*bExpand=*/false); + xCursor->gotoEnd(/*bExpand=*/true); + uno::Reference<text::XTextContent> xContentControl( + xMSF->createInstance("com.sun.star.text.ContentControl"), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY); + xContentControlProps->setPropertyValue("Checkbox", uno::Any(true)); + xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true); + + // When entering the content control: + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + pWrtShell->SttEndDoc(/*bStt=*/true); + pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false); + + // Then make sure that the cursor is read-only: + // Without the accompanying fix in place, this test would have failed, it was possible to type + // into the checkbox content control, just to loose the typed content on the next click. + CPPUNIT_ASSERT(pWrtShell->HasReadonlySel()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/crsr/pam.cxx b/sw/source/core/crsr/pam.cxx index c54d500cb15d..f771e09f5739 100644 --- a/sw/source/core/crsr/pam.cxx +++ b/sw/source/core/crsr/pam.cxx @@ -49,6 +49,7 @@ #include <rtl/ustrbuf.hxx> #include <editsh.hxx> +#include <textcontentcontrol.hxx> // for the dump "MSC-" compiler static sal_Int32 GetSttOrEnd( bool bCondition, const SwContentNode& rNd ) @@ -811,6 +812,31 @@ bool SwPaM::HasReadonlySel( bool bFormView ) const } } + if (!bRet) + { + // See if we're inside a read-only content control. + const SwPosition* pStart = Start(); + SwTextNode* pTextNode = pStart->nNode.GetNode().GetTextNode(); + if (pTextNode) + { + sal_Int32 nIndex = pStart->nContent.GetIndex(); + SwTextAttr* pAttr + = pTextNode->GetTextAttrAt(nIndex, RES_TXTATR_CONTENTCONTROL, SwTextNode::PARENT); + auto pTextContentControl = static_txtattr_cast<SwTextContentControl*>(pAttr); + if (pTextContentControl) + { + const SwFormatContentControl& rFormatContentControl + = pTextContentControl->GetContentControl(); + std::shared_ptr<SwContentControl> pContentControl + = rFormatContentControl.GetContentControl(); + if (pContentControl && !pContentControl->GetReadWrite()) + { + bRet = pContentControl->GetCheckbox() || pContentControl->GetPicture(); + } + } + } + } + return bRet; } diff --git a/sw/source/uibase/wrtsh/wrtsh3.cxx b/sw/source/uibase/wrtsh/wrtsh3.cxx index e4b594770282..27ca0353bac1 100644 --- a/sw/source/uibase/wrtsh/wrtsh3.cxx +++ b/sw/source/uibase/wrtsh/wrtsh3.cxx @@ -148,9 +148,11 @@ bool SwWrtShell::GotoContentControl(const SwFormatContentControl& rContentContro GetIDocumentUndoRedo().StartUndo(SwUndoId::REPLACE, &aRewriter); // Toggle the state. + pContentControl->SetReadWrite(true); DelLeft(); pContentControl->SetChecked(!pContentControl->GetChecked()); Insert(aNewState); + pContentControl->SetReadWrite(false); GetIDocumentUndoRedo().EndUndo(SwUndoId::REPLACE, &aRewriter); LockView(/*bViewLocked=*/false); |