sw/inc/formatcontentcontrol.hxx               |   28 ++++++
 sw/inc/unoprnms.hxx                           |    4 
 sw/qa/core/unocore/unocore.cxx                |   38 ++++++++
 sw/source/core/txtnode/attrcontentcontrol.cxx |    8 +
 sw/source/core/unocore/unocontentcontrol.cxx  |  114 ++++++++++++++++++++++++++
 sw/source/core/unocore/unomap1.cxx            |    4 
 6 files changed, 196 insertions(+)

New commits:
commit cd2272874d1b1911dec6c6e7bf3d67861be4a015
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon Apr 25 08:47:32 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Apr 25 12:36:00 2022 +0200

    sw content controls, checkbox: add document model & UNO API
    
    Add 4 new properties: if this is a checkbox, and is so:
    
    - if it's checked
    - unicode value for the checked state
    - unicode value for the unchecked state
    
    This should be enough for the UI to be able to update checkmark state on
    click.
    
    Change-Id: I723532fd2d3377cf09a1127c69c55f9539649088
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133363
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/inc/formatcontentcontrol.hxx b/sw/inc/formatcontentcontrol.hxx
index bb92454ffd09..368720a0cb76 100644
--- a/sw/inc/formatcontentcontrol.hxx
+++ b/sw/inc/formatcontentcontrol.hxx
@@ -80,6 +80,18 @@ class SAL_DLLPUBLIC_RTTI SwContentControl : public 
sw::BroadcastingModify
     /// Current content is placeholder text.
     bool m_bShowingPlaceHolder = false;
 
+    /// Display the content control as a checkbox.
+    bool m_bCheckbox = false;
+
+    /// If m_bCheckbox is true, is the checkbox checked?
+    bool m_bChecked = false;
+
+    /// If m_bCheckbox is true, the value of a checked checkbox.
+    OUString m_aCheckedState;
+
+    /// If m_bCheckbox is true, the value of an unchecked checkbox.
+    OUString m_aUncheckedState;
+
 public:
     SwTextContentControl* GetTextAttr() const;
 
@@ -114,6 +126,22 @@ public:
 
     bool GetShowingPlaceHolder() const { return m_bShowingPlaceHolder; }
 
+    void SetCheckbox(bool bCheckbox) { m_bCheckbox = bCheckbox; }
+
+    bool GetCheckbox() const { return m_bCheckbox; }
+
+    void SetChecked(bool bChecked) { m_bChecked = bChecked; }
+
+    bool GetChecked() const { return m_bChecked; }
+
+    void SetCheckedState(const OUString& rCheckedState) { m_aCheckedState = 
rCheckedState; }
+
+    OUString GetCheckedState() const { return m_aCheckedState; }
+
+    void SetUncheckedState(const OUString& rUncheckedState) { 
m_aUncheckedState = rUncheckedState; }
+
+    OUString GetUncheckedState() const { return m_aUncheckedState; }
+
     virtual void dumpAsXml(xmlTextWriterPtr pWriter) const;
 };
 
diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx
index 3e6516b3551c..bfc3a28aeecc 100644
--- a/sw/inc/unoprnms.hxx
+++ b/sw/inc/unoprnms.hxx
@@ -872,6 +872,10 @@
 #define UNO_NAME_LINEBREAK "LineBreak"
 #define UNO_NAME_CONTENT_CONTROL "ContentControl"
 #define UNO_NAME_SHOWING_PLACE_HOLDER "ShowingPlaceHolder"
+#define UNO_NAME_CHECKBOX "Checkbox"
+#define UNO_NAME_CHECKED "Checked"
+#define UNO_NAME_CHECKED_STATE "CheckedState"
+#define UNO_NAME_UNCHECKED_STATE "UncheckedState"
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx
index 19ad5d5fd48b..0f1b6a5e7623 100644
--- a/sw/qa/core/unocore/unocore.cxx
+++ b/sw/qa/core/unocore/unocore.cxx
@@ -418,6 +418,44 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, 
testContentControlTextPortionEnum)
     assertXPath(pXmlDoc, "//SwParaPortion/SwLineLayout/SwLinePortion", 
"portion", "test");
 }
 
+CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testContentControlCheckbox)
+{
+    // Given an empty document:
+    SwDoc* pDoc = createSwDoc();
+
+    // When inserting a checkbox content control:
+    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, "test", /*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);
+    // Without the accompanying fix in place, this test would have failed with:
+    // An uncaught exception of type 
com.sun.star.beans.UnknownPropertyException
+    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);
+
+    // Then make sure that the specified properties are set:
+    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());
+    SwContentControl* pContentControl = 
rFormatContentControl.GetContentControl();
+    CPPUNIT_ASSERT(pContentControl->GetCheckbox());
+    CPPUNIT_ASSERT(pContentControl->GetChecked());
+    CPPUNIT_ASSERT_EQUAL(OUString(u"☒"), pContentControl->GetCheckedState());
+    CPPUNIT_ASSERT_EQUAL(OUString(u"☐"), pContentControl->GetUncheckedState());
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/attrcontentcontrol.cxx 
b/sw/source/core/txtnode/attrcontentcontrol.cxx
index 066ddd0494be..e469bab96e1d 100644
--- a/sw/source/core/txtnode/attrcontentcontrol.cxx
+++ b/sw/source/core/txtnode/attrcontentcontrol.cxx
@@ -212,6 +212,14 @@ void SwContentControl::dumpAsXml(xmlTextWriterPtr pWriter) 
const
     (void)xmlTextWriterWriteFormatAttribute(
         pWriter, BAD_CAST("showing-place-holder"), "%s",
         BAD_CAST(OString::boolean(m_bShowingPlaceHolder).getStr()));
+    (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("checkbox"), 
"%s",
+                                            
BAD_CAST(OString::boolean(m_bCheckbox).getStr()));
+    (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("checked"), "%s",
+                                            
BAD_CAST(OString::boolean(m_bChecked).getStr()));
+    (void)xmlTextWriterWriteFormatAttribute(pWriter, 
BAD_CAST("checked-state"), "%s",
+                                            
BAD_CAST(m_aCheckedState.toUtf8().getStr()));
+    (void)xmlTextWriterWriteFormatAttribute(pWriter, 
BAD_CAST("unchecked-state"), "%s",
+                                            
BAD_CAST(m_aUncheckedState.toUtf8().getStr()));
     (void)xmlTextWriterEndElement(pWriter);
 }
 
diff --git a/sw/source/core/unocore/unocontentcontrol.cxx 
b/sw/source/core/unocore/unocontentcontrol.cxx
index 93b7c976ae0d..81ccc9fd088c 100644
--- a/sw/source/core/unocore/unocontentcontrol.cxx
+++ b/sw/source/core/unocore/unocontentcontrol.cxx
@@ -156,6 +156,10 @@ public:
     rtl::Reference<SwXContentControlText> m_xText;
     SwContentControl* m_pContentControl;
     bool m_bShowingPlaceHolder;
+    bool m_bCheckbox;
+    bool m_bChecked;
+    OUString m_aCheckedState;
+    OUString m_aUncheckedState;
 
     Impl(SwXContentControl& rThis, SwDoc& rDoc, SwContentControl* 
pContentControl,
          const uno::Reference<text::XText>& xParentText,
@@ -167,6 +171,8 @@ public:
         , m_xText(new SwXContentControlText(rDoc, rThis))
         , m_pContentControl(pContentControl)
         , m_bShowingPlaceHolder(false)
+        , m_bCheckbox(false)
+        , m_bChecked(false)
     {
         if (m_pContentControl)
         {
@@ -506,6 +512,10 @@ void SwXContentControl::AttachImpl(const 
uno::Reference<text::XTextRange>& xText
     auto pContentControl = std::make_shared<SwContentControl>(nullptr);
 
     pContentControl->SetShowingPlaceHolder(m_pImpl->m_bShowingPlaceHolder);
+    pContentControl->SetCheckbox(m_pImpl->m_bCheckbox);
+    pContentControl->SetChecked(m_pImpl->m_bChecked);
+    pContentControl->SetCheckedState(m_pImpl->m_aCheckedState);
+    pContentControl->SetUncheckedState(m_pImpl->m_aUncheckedState);
 
     SwFormatContentControl aContentControl(pContentControl, nWhich);
     bool bSuccess
@@ -672,6 +682,66 @@ void SAL_CALL SwXContentControl::setPropertyValue(const 
OUString& rPropertyName,
             }
         }
     }
+    else if (rPropertyName == UNO_NAME_CHECKBOX)
+    {
+        bool bValue;
+        if (rValue >>= bValue)
+        {
+            if (m_pImpl->m_bIsDescriptor)
+            {
+                m_pImpl->m_bCheckbox = bValue;
+            }
+            else
+            {
+                m_pImpl->m_pContentControl->SetCheckbox(bValue);
+            }
+        }
+    }
+    else if (rPropertyName == UNO_NAME_CHECKED)
+    {
+        bool bValue;
+        if (rValue >>= bValue)
+        {
+            if (m_pImpl->m_bIsDescriptor)
+            {
+                m_pImpl->m_bChecked = bValue;
+            }
+            else
+            {
+                m_pImpl->m_pContentControl->SetChecked(bValue);
+            }
+        }
+    }
+    else if (rPropertyName == UNO_NAME_CHECKED_STATE)
+    {
+        OUString aValue;
+        if (rValue >>= aValue)
+        {
+            if (m_pImpl->m_bIsDescriptor)
+            {
+                m_pImpl->m_aCheckedState = aValue;
+            }
+            else
+            {
+                m_pImpl->m_pContentControl->SetCheckedState(aValue);
+            }
+        }
+    }
+    else if (rPropertyName == UNO_NAME_UNCHECKED_STATE)
+    {
+        OUString aValue;
+        if (rValue >>= aValue)
+        {
+            if (m_pImpl->m_bIsDescriptor)
+            {
+                m_pImpl->m_aUncheckedState = aValue;
+            }
+            else
+            {
+                m_pImpl->m_pContentControl->SetUncheckedState(aValue);
+            }
+        }
+    }
     else
     {
         throw beans::UnknownPropertyException();
@@ -694,6 +764,50 @@ uno::Any SAL_CALL 
SwXContentControl::getPropertyValue(const OUString& rPropertyN
             aRet <<= m_pImpl->m_pContentControl->GetShowingPlaceHolder();
         }
     }
+    else if (rPropertyName == UNO_NAME_CHECKBOX)
+    {
+        if (m_pImpl->m_bIsDescriptor)
+        {
+            aRet <<= m_pImpl->m_bCheckbox;
+        }
+        else
+        {
+            aRet <<= m_pImpl->m_pContentControl->GetCheckbox();
+        }
+    }
+    else if (rPropertyName == UNO_NAME_CHECKED)
+    {
+        if (m_pImpl->m_bIsDescriptor)
+        {
+            aRet <<= m_pImpl->m_bChecked;
+        }
+        else
+        {
+            aRet <<= m_pImpl->m_pContentControl->GetChecked();
+        }
+    }
+    else if (rPropertyName == UNO_NAME_CHECKED_STATE)
+    {
+        if (m_pImpl->m_bIsDescriptor)
+        {
+            aRet <<= m_pImpl->m_aCheckedState;
+        }
+        else
+        {
+            aRet <<= m_pImpl->m_pContentControl->GetCheckedState();
+        }
+    }
+    else if (rPropertyName == UNO_NAME_UNCHECKED_STATE)
+    {
+        if (m_pImpl->m_bIsDescriptor)
+        {
+            aRet <<= m_pImpl->m_aUncheckedState;
+        }
+        else
+        {
+            aRet <<= m_pImpl->m_pContentControl->GetUncheckedState();
+        }
+    }
     else
     {
         throw beans::UnknownPropertyException();
diff --git a/sw/source/core/unocore/unomap1.cxx 
b/sw/source/core/unocore/unomap1.cxx
index acf803d34253..3da6c8097051 100644
--- a/sw/source/core/unocore/unomap1.cxx
+++ b/sw/source/core/unocore/unomap1.cxx
@@ -1023,6 +1023,10 @@ const SfxItemPropertyMapEntry* 
SwUnoPropertyMapProvider::GetContentControlProper
     static SfxItemPropertyMapEntry const aContentControlMap_Impl[] =
     {
         { u"" UNO_NAME_SHOWING_PLACE_HOLDER, 0, cppu::UnoType<bool>::get(), 
PROPERTY_NONE, 0 },
+        { u"" UNO_NAME_CHECKBOX, 0, cppu::UnoType<bool>::get(), PROPERTY_NONE, 
0 },
+        { u"" UNO_NAME_CHECKED, 0, cppu::UnoType<bool>::get(), PROPERTY_NONE, 
0 },
+        { u"" UNO_NAME_CHECKED_STATE, 0, cppu::UnoType<OUString>::get(), 
PROPERTY_NONE, 0 },
+        { u"" UNO_NAME_UNCHECKED_STATE, 0, cppu::UnoType<OUString>::get(), 
PROPERTY_NONE, 0 },
         { u"", 0, css::uno::Type(), 0, 0 }
     };
 

Reply via email to