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 4a0f65c338f32dffc9ecc47811aa199d13205a9e
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Tue Apr 26 08:20:50 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon May 2 08:14:44 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.
    
    (cherry picked from commit 6f60a89a6be85d4cbe5840f9d0146eae98dbf543)
    
    Change-Id: I280ce45822fe3fd9615511a9a62d23dc230aa275
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133642
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

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 e1e9aa08913f..48c10a666c7f 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