sw/qa/uibase/wrtsh/wrtsh.cxx      |   38 ++++++++++++++++++++++++++++++++++++++
 sw/source/core/crsr/crstrvl.cxx   |    2 +-
 sw/source/uibase/wrtsh/wrtsh3.cxx |   38 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 77 insertions(+), 1 deletion(-)

New commits:
commit 6f60a89a6be85d4cbe5840f9d0146eae98dbf543
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Tue Apr 26 08:20:50 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue Apr 26 12:28:53 2022 +0200

    sw content controls, checkbox: toggle the checkbox on click
    
    Implement this by selecting the content control's text (similar to
    placeholders), then replacing the selection with the content control's
    relevant state.
    
    Change-Id: I280ce45822fe3fd9615511a9a62d23dc230aa275
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133424
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/qa/uibase/wrtsh/wrtsh.cxx b/sw/qa/uibase/wrtsh/wrtsh.cxx
index 51489553d30f..b4d4cca09df6 100644
--- a/sw/qa/uibase/wrtsh/wrtsh.cxx
+++ b/sw/qa/uibase/wrtsh/wrtsh.cxx
@@ -91,6 +91,44 @@ CPPUNIT_TEST_FIXTURE(Test, testGotoContentControl)
     CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(5), nEnd);
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testTickCheckboxContentControl)
+{
+    // Given a document with a checkbox (checked) 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, OUString(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::makeAny(true));
+    xContentControlProps->setPropertyValue("Checked", uno::makeAny(true));
+    xContentControlProps->setPropertyValue("CheckedState", 
uno::makeAny(OUString(u"☒")));
+    xContentControlProps->setPropertyValue("UncheckedState", 
uno::makeAny(OUString(u"☐")));
+    xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true);
+
+    // When clicking on that content control:
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    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());
+    pWrtShell->GotoContentControl(rFormatContentControl);
+
+    // Then make sure that the checkbox is no longer checked:
+    // Without the accompanying fix in place, this test would have failed:
+    // - Expected: ☐
+    // - Actual  : ☒
+    // i.e. the text node's text was CH_TXTATR_BREAKWORD + "Ballot Box with 
X", not just
+    // CH_TXTATR_BREAKWORD + "Ballot Box".
+    CPPUNIT_ASSERT_EQUAL(OUString(u"\x0001☐"), pTextNode->GetText());
+}
+
 CPPUNIT_TEST_FIXTURE(Test, testInsertContentControl)
 {
     // Given an empty document:
diff --git a/sw/source/core/crsr/crstrvl.cxx b/sw/source/core/crsr/crstrvl.cxx
index b5720002e916..cfc57e901827 100644
--- a/sw/source/core/crsr/crstrvl.cxx
+++ b/sw/source/core/crsr/crstrvl.cxx
@@ -857,7 +857,7 @@ bool SwCursorShell::GotoFormatContentControl(const 
SwFormatContentControl& rCont
 {
     bool bRet = false;
     auto pContentControl = 
const_cast<SwContentControl*>(rContentControl.GetContentControl());
-    if (!pContentControl->GetShowingPlaceHolder())
+    if (!pContentControl->GetShowingPlaceHolder() && 
!pContentControl->GetCheckbox())
     {
         return bRet;
     }
diff --git a/sw/source/uibase/wrtsh/wrtsh3.cxx 
b/sw/source/uibase/wrtsh/wrtsh3.cxx
index 2b0b9385467e..35d1d3bd45ee 100644
--- a/sw/source/uibase/wrtsh/wrtsh3.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh3.cxx
@@ -33,6 +33,10 @@
 #include <view.hxx>
 #include <IMark.hxx>
 #include <doc.hxx>
+#include <formatcontentcontrol.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <SwRewriter.hxx>
+#include <strings.hrc>
 
 using namespace ::com::sun::star;
 
@@ -88,6 +92,40 @@ bool SwWrtShell::GotoContentControl(const 
SwFormatContentControl& rContentContro
     (this->*m_fnKillSel)(nullptr, false);
 
     bool bRet = SwCursorShell::GotoFormatContentControl(rContentControl);
+
+    auto pContentControl = 
const_cast<SwContentControl*>(rContentControl.GetContentControl());
+    if (bRet && pContentControl && pContentControl->GetCheckbox())
+    {
+        // Checkbox: GotoFormatContentControl() selected the old state.
+        LockView(/*bViewLocked=*/true);
+        OUString aOldState;
+        OUString aNewState;
+        if (pContentControl->GetChecked())
+        {
+            aOldState = pContentControl->GetCheckedState();
+            aNewState = pContentControl->GetUncheckedState();
+        }
+        else
+        {
+            aOldState = pContentControl->GetUncheckedState();
+            aNewState = pContentControl->GetCheckedState();
+        }
+        SwRewriter aRewriter;
+        aRewriter.AddRule(UndoArg1, aOldState);
+        aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
+        aRewriter.AddRule(UndoArg3, aNewState);
+        GetIDocumentUndoRedo().StartUndo(SwUndoId::REPLACE, &aRewriter);
+
+        // Toggle the state.
+        DelLeft();
+        pContentControl->SetChecked(!pContentControl->GetChecked());
+        Insert(aNewState);
+
+        GetIDocumentUndoRedo().EndUndo(SwUndoId::REPLACE, &aRewriter);
+        LockView(/*bViewLocked=*/false);
+        ShowCursor();
+    }
+
     if (bRet && IsSelFrameMode())
     {
         UnSelectFrame();

Reply via email to