sw/inc/formatcontentcontrol.hxx               |   14 +++
 sw/inc/textcontentcontrol.hxx                 |    2 
 sw/inc/txatbase.hxx                           |   10 ++
 sw/inc/unomap.hxx                             |    4 -
 sw/inc/unoprnms.hxx                           |    1 
 sw/qa/core/unocore/unocore.cxx                |    9 ++
 sw/source/core/inc/unocontentcontrol.hxx      |   21 +++++
 sw/source/core/txtnode/attrcontentcontrol.cxx |   36 +++++++++
 sw/source/core/txtnode/txatbase.cxx           |    1 
 sw/source/core/unocore/unocontentcontrol.cxx  |   95 ++++++++++++++++++++++++++
 sw/source/core/unocore/unomap.cxx             |    5 +
 sw/source/core/unocore/unomap1.cxx            |   17 ++++
 12 files changed, 212 insertions(+), 3 deletions(-)

New commits:
commit 5da08b21cd23f2e70f5003733b03a7aee7915225
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Apr 1 10:58:01 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Apr 1 11:54:33 2022 +0200

    sw content controls: add UNO API to insert this with custom props
    
    Add the ability to specify if the content control is a placeholder or
    not on the content control object itself before insertion.
    
    Change-Id: Ia06869c69a5b85cfc1d0a55739bbb23a53bef4d5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132404
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/inc/formatcontentcontrol.hxx b/sw/inc/formatcontentcontrol.hxx
index 0fa075bf7036..c1ac07279efe 100644
--- a/sw/inc/formatcontentcontrol.hxx
+++ b/sw/inc/formatcontentcontrol.hxx
@@ -61,6 +61,8 @@ public:
     void NotifyChangeTextNode(SwTextNode* pTextNode);
     static SwFormatContentControl* CreatePoolDefault(sal_uInt16 nWhich);
     SwContentControl* GetContentControl() { return m_pContentControl.get(); }
+
+    void dumpAsXml(xmlTextWriterPtr pWriter) const override;
 };
 
 /// Stores the properties of a content control.
@@ -73,6 +75,9 @@ class SwContentControl : public sw::BroadcastingModify
     /// Can be nullptr if not in a document for undo purposes.
     SwTextNode* m_pTextNode;
 
+    /// Current content is placeholder text.
+    bool m_bShowingPlaceHolder = false;
+
 public:
     SwTextContentControl* GetTextAttr() const;
 
@@ -99,6 +104,15 @@ public:
     explicit SwContentControl(SwFormatContentControl* pFormat);
 
     virtual ~SwContentControl() override;
+
+    void SetShowingPlaceHolder(bool bShowingPlaceHolder)
+    {
+        m_bShowingPlaceHolder = bShowingPlaceHolder;
+    }
+
+    bool GetShowingPlaceHolder() const { return m_bShowingPlaceHolder; }
+
+    virtual void dumpAsXml(xmlTextWriterPtr pWriter) const;
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/inc/textcontentcontrol.hxx b/sw/inc/textcontentcontrol.hxx
index 3410a6a35506..1c445d812099 100644
--- a/sw/inc/textcontentcontrol.hxx
+++ b/sw/inc/textcontentcontrol.hxx
@@ -36,6 +36,8 @@ public:
     ~SwTextContentControl() override;
 
     void ChgTextNode(SwTextNode* pNode);
+
+    void dumpAsXml(xmlTextWriterPtr pWriter) const override;
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/inc/txatbase.hxx b/sw/inc/txatbase.hxx
index 110e12064c9c..183e254f8817 100644
--- a/sw/inc/txatbase.hxx
+++ b/sw/inc/txatbase.hxx
@@ -29,6 +29,7 @@
 #include "fmtflcnt.hxx"
 #include "fmtftn.hxx"
 #include "formatlinebreak.hxx"
+#include "formatcontentcontrol.hxx"
 #include "fchrfmt.hxx"
 #include "tox.hxx"
 #include "ndhints.hxx"
@@ -39,7 +40,7 @@ class SfxItemPool;
  * A wrapper around SfxPoolItem to store the start position of (usually) a 
text portion, with an
  * optional end.
  */
-class SAL_DLLPUBLIC_RTTI SwTextAttr
+class SW_DLLPUBLIC SwTextAttr
 {
 friend class SwpHints;
 private:
@@ -121,6 +122,7 @@ public:
     inline const SwFormatField               &GetFormatField() const;
     inline const SwFormatFootnote               &GetFootnote() const;
     inline const SwFormatLineBreak& GetLineBreak() const;
+    inline const SwFormatContentControl& GetContentControl() const;
     inline const SwFormatFlyCnt            &GetFlyCnt() const;
     inline const SwTOXMark              &GetTOXMark() const;
     inline const SwFormatRefMark           &GetRefMark() const;
@@ -215,6 +217,12 @@ inline const SwFormatLineBreak& SwTextAttr::GetLineBreak() 
const
     return static_cast<const SwFormatLineBreak&>(*m_pAttr);
 }
 
+inline const SwFormatContentControl& SwTextAttr::GetContentControl() const
+{
+    assert(m_pAttr && m_pAttr->Which() == RES_TXTATR_CONTENTCONTROL);
+    return static_cast<const SwFormatContentControl&>(*m_pAttr);
+}
+
 inline const SwFormatFlyCnt& SwTextAttr::GetFlyCnt() const
 {
     assert( m_pAttr && m_pAttr->Which() == RES_TXTATR_FLYCNT );
diff --git a/sw/inc/unomap.hxx b/sw/inc/unomap.hxx
index a9a78d550285..bae3be46d40f 100644
--- a/sw/inc/unomap.hxx
+++ b/sw/inc/unomap.hxx
@@ -126,7 +126,8 @@ struct SfxItemPropertyMapEntry;
 #define PROPERTY_MAP_CELL_STYLE                         101
 #define PROPERTY_MAP_FIELDMARK                          102
 #define PROPERTY_MAP_LINEBREAK                          103
-#define PROPERTY_MAP_END                                104
+#define PROPERTY_MAP_CONTENTCONTROL                     104
+#define PROPERTY_MAP_END                                105
 
 //S&E
 #define WID_WORDS                0
@@ -352,6 +353,7 @@ private:
     static const SfxItemPropertyMapEntry*  GetRedlinePortionPropertyMap();
     static       SfxItemPropertyMapEntry*  GetTextDefaultPropertyMap();
     static const SfxItemPropertyMapEntry* GetLineBreakPropertyMap();
+    static const SfxItemPropertyMapEntry* GetContentControlPropertyMap();
 };
 
 extern SwUnoPropertyMapProvider aSwMapProvider;
diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx
index 579e1752508a..6a04072fdae5 100644
--- a/sw/inc/unoprnms.hxx
+++ b/sw/inc/unoprnms.hxx
@@ -870,6 +870,7 @@
 #define UNO_NAME_ALLOW_OVERLAP "AllowOverlap"
 #define UNO_NAME_CLEAR "Clear"
 #define UNO_NAME_LINEBREAK "LineBreak"
+#define UNO_NAME_SHOWING_PLACE_HOLDER "ShowingPlaceHolder"
 #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 3d5bb93f2600..b03c91b39425 100644
--- a/sw/qa/core/unocore/unocore.cxx
+++ b/sw/qa/core/unocore/unocore.cxx
@@ -325,6 +325,9 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, 
testContentControlInsert)
     xCursor->gotoEnd(/*bExpand=*/true);
     uno::Reference<text::XTextContent> xContentControl(
         xMSF->createInstance("com.sun.star.text.ContentControl"), 
uno::UNO_QUERY);
+    // Set a custom property on the content control:
+    uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, 
uno::UNO_QUERY);
+    xContentControlProps->setPropertyValue("ShowingPlaceHolder", 
uno::makeAny(true));
     xText->insertTextContent(xCursor, xContentControl, /*bAbsorb=*/true);
 
     // Then make sure that the text attribute is inserted:
@@ -335,6 +338,12 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, 
testContentControlInsert)
     // Without the accompanying fix in place, this test would have failed, as 
the
     // SwXContentControl::attach() implementation was missing.
     CPPUNIT_ASSERT(pAttr);
+    // Also verify that the custom property was set:
+    auto pTextContentControl = 
static_txtattr_cast<SwTextContentControl*>(pAttr);
+    auto& rFormatContentControl
+        = static_cast<SwFormatContentControl&>(pTextContentControl->GetAttr());
+    SwContentControl* pContentControl = 
rFormatContentControl.GetContentControl();
+    CPPUNIT_ASSERT(pContentControl->GetShowingPlaceHolder());
 }
 
 CPPUNIT_TEST_FIXTURE(SwModelTestBase, testImageTooltip)
diff --git a/sw/source/core/inc/unocontentcontrol.hxx 
b/sw/source/core/inc/unocontentcontrol.hxx
index 7f90f2ec18e7..631ccdaf02d3 100644
--- a/sw/source/core/inc/unocontentcontrol.hxx
+++ b/sw/source/core/inc/unocontentcontrol.hxx
@@ -29,6 +29,7 @@
 #include <com/sun/star/container/XEnumerationAccess.hpp>
 #include <com/sun/star/text/XTextContent.hpp>
 #include <com/sun/star/text/XTextField.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
 
 #include <cppuhelper/implbase.hxx>
 
@@ -47,7 +48,7 @@ class SwContentControl;
 class SwXContentControl
     : public cppu::WeakImplHelper<css::lang::XUnoTunnel, 
css::lang::XServiceInfo,
                                   css::container::XEnumerationAccess, 
css::text::XTextContent,
-                                  css::text::XText>
+                                  css::text::XText, css::beans::XPropertySet>
 {
 public:
     class Impl;
@@ -134,6 +135,24 @@ public:
                                     sal_Bool bAbsorb) override;
     void SAL_CALL
     removeTextContent(const css::uno::Reference<css::text::XTextContent>& 
xContent) override;
+
+    // XPropertySet
+    css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL 
getPropertySetInfo() override;
+    void SAL_CALL setPropertyValue(const OUString& rPropertyName,
+                                   const css::uno::Any& rValue) override;
+    css::uno::Any SAL_CALL getPropertyValue(const OUString& rPropertyName) 
override;
+    void SAL_CALL addPropertyChangeListener(
+        const OUString& rPropertyName,
+        const css::uno::Reference<css::beans::XPropertyChangeListener>& 
xListener) override;
+    void SAL_CALL removePropertyChangeListener(
+        const OUString& rPropertyName,
+        const css::uno::Reference<css::beans::XPropertyChangeListener>& 
xListener) override;
+    void SAL_CALL addVetoableChangeListener(
+        const OUString& rPropertyName,
+        const css::uno::Reference<css::beans::XVetoableChangeListener>& 
xListener) override;
+    void SAL_CALL removeVetoableChangeListener(
+        const OUString& rPropertyName,
+        const css::uno::Reference<css::beans::XVetoableChangeListener>& 
xListener) override;
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/attrcontentcontrol.cxx 
b/sw/source/core/txtnode/attrcontentcontrol.cxx
index eb127f1a1ba6..01af0eaec704 100644
--- a/sw/source/core/txtnode/attrcontentcontrol.cxx
+++ b/sw/source/core/txtnode/attrcontentcontrol.cxx
@@ -19,6 +19,8 @@
 
 #include <formatcontentcontrol.hxx>
 
+#include <libxml/xmlwriter.h>
+
 #include <sal/log.hxx>
 
 #include <ndtxt.hxx>
@@ -139,6 +141,21 @@ void SwFormatContentControl::DoCopy(SwTextNode& 
rTargetTextNode)
     m_pContentControl->NotifyChangeTextNode(&rTargetTextNode);
 }
 
+void SwFormatContentControl::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+    (void)xmlTextWriterStartElement(pWriter, 
BAD_CAST("SwFormatContentControl"));
+    (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", 
this);
+    (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("m_pTextAttr"), 
"%p", m_pTextAttr);
+    SfxPoolItem::dumpAsXml(pWriter);
+
+    if (m_pContentControl)
+    {
+        m_pContentControl->dumpAsXml(pWriter);
+    }
+
+    (void)xmlTextWriterEndElement(pWriter);
+}
+
 SwContentControl::SwContentControl(SwFormatContentControl* pFormat)
     : sw::BroadcastingModify()
     , m_pFormat(pFormat)
@@ -188,6 +205,16 @@ void SwContentControl::SwClientNotify(const SwModify&, 
const SfxHint& rHint)
     }
 }
 
+void SwContentControl::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+    (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwContentControl"));
+    (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", 
this);
+    (void)xmlTextWriterWriteFormatAttribute(
+        pWriter, BAD_CAST("showing-place-holder"), "%s",
+        BAD_CAST(OString::boolean(m_bShowingPlaceHolder).getStr()));
+    (void)xmlTextWriterEndElement(pWriter);
+}
+
 SwTextContentControl* 
SwTextContentControl::CreateTextContentControl(SwTextNode* pTargetTextNode,
                                                                      
SwFormatContentControl& rAttr,
                                                                      sal_Int32 
nStart,
@@ -234,4 +261,13 @@ void SwTextContentControl::ChgTextNode(SwTextNode* pNode)
     }
 }
 
+void SwTextContentControl::dumpAsXml(xmlTextWriterPtr pWriter) const
+{
+    (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwTextContentControl"));
+    (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", 
this);
+    SwTextAttr::dumpAsXml(pWriter);
+
+    (void)xmlTextWriterEndElement(pWriter);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/txatbase.cxx 
b/sw/source/core/txtnode/txatbase.cxx
index cd18549c58d8..a6fe1599519b 100644
--- a/sw/source/core/txtnode/txatbase.cxx
+++ b/sw/source/core/txtnode/txatbase.cxx
@@ -166,6 +166,7 @@ void SwTextAttr::dumpAsXml(xmlTextWriterPtr pWriter) const
         case RES_TXTATR_META:
             break;
         case RES_TXTATR_CONTENTCONTROL:
+            GetContentControl().dumpAsXml(pWriter);
             break;
         default:
             SAL_WARN("sw.core", "Unhandled TXTATR");
diff --git a/sw/source/core/unocore/unocontentcontrol.cxx 
b/sw/source/core/unocore/unocontentcontrol.cxx
index 63d80cc831fc..2b431a20de96 100644
--- a/sw/source/core/unocore/unocontentcontrol.cxx
+++ b/sw/source/core/unocore/unocontentcontrol.cxx
@@ -35,6 +35,8 @@
 #include <unotextrange.hxx>
 #include <doc.hxx>
 #include <unoport.hxx>
+#include <unomap.hxx>
+#include <unoprnms.hxx>
 
 using namespace com::sun::star;
 
@@ -153,6 +155,7 @@ public:
     uno::Reference<text::XText> m_xParentText;
     rtl::Reference<SwXContentControlText> m_xText;
     SwContentControl* m_pContentControl;
+    bool m_bShowingPlaceHolder;
 
     Impl(SwXContentControl& rThis, SwDoc& rDoc, SwContentControl* 
pContentControl,
          const uno::Reference<text::XText>& xParentText,
@@ -163,6 +166,7 @@ public:
         , m_xParentText(xParentText)
         , m_xText(new SwXContentControlText(rDoc, rThis))
         , m_pContentControl(pContentControl)
+        , m_bShowingPlaceHolder(false)
     {
         if (m_pContentControl)
         {
@@ -500,6 +504,9 @@ void SwXContentControl::AttachImpl(const 
uno::Reference<text::XTextRange>& xText
                                    : SetAttrMode::DONTEXPAND;
 
     auto pContentControl = std::make_shared<SwContentControl>(nullptr);
+
+    pContentControl->SetShowingPlaceHolder(m_pImpl->m_bShowingPlaceHolder);
+
     SwFormatContentControl aContentControl(pContentControl, nWhich);
     bool bSuccess
         = pDoc->getIDocumentContentOperations().InsertPoolItem(aPam, 
aContentControl, nInsertFlags);
@@ -635,6 +642,94 @@ SwXContentControl::removeTextContent(const 
uno::Reference<text::XTextContent>& x
     return m_pImpl->m_xText->removeTextContent(xContent);
 }
 
+// XPropertySet
+uno::Reference<beans::XPropertySetInfo> SAL_CALL 
SwXContentControl::getPropertySetInfo()
+{
+    SolarMutexGuard aGuard;
+
+    static uno::Reference<beans::XPropertySetInfo> xRet
+        = 
aSwMapProvider.GetPropertySet(PROPERTY_MAP_CONTENTCONTROL)->getPropertySetInfo();
+    return xRet;
+}
+
+void SAL_CALL SwXContentControl::setPropertyValue(const OUString& 
rPropertyName,
+                                                  const css::uno::Any& rValue)
+{
+    SolarMutexGuard aGuard;
+
+    if (rPropertyName == UNO_NAME_SHOWING_PLACE_HOLDER)
+    {
+        bool bValue;
+        if (rValue >>= bValue)
+        {
+            if (m_pImpl->m_bIsDescriptor)
+            {
+                m_pImpl->m_bShowingPlaceHolder = bValue;
+            }
+            else
+            {
+                m_pImpl->m_pContentControl->SetShowingPlaceHolder(bValue);
+            }
+        }
+    }
+    else
+    {
+        throw beans::UnknownPropertyException();
+    }
+}
+
+uno::Any SAL_CALL SwXContentControl::getPropertyValue(const OUString& 
rPropertyName)
+{
+    SolarMutexGuard aGuard;
+
+    uno::Any aRet;
+    if (rPropertyName == UNO_NAME_SHOWING_PLACE_HOLDER)
+    {
+        if (m_pImpl->m_bIsDescriptor)
+        {
+            aRet <<= m_pImpl->m_bShowingPlaceHolder;
+        }
+        else
+        {
+            m_pImpl->m_pContentControl->GetShowingPlaceHolder();
+        }
+    }
+    else
+    {
+        throw beans::UnknownPropertyException();
+    }
+
+    return aRet;
+}
+
+void SAL_CALL SwXContentControl::addPropertyChangeListener(
+    const OUString& /*rPropertyName*/,
+    const uno::Reference<beans::XPropertyChangeListener>& /*xListener*/)
+{
+    SAL_WARN("sw.uno", "SwXContentControl::addPropertyChangeListener: not 
implemented");
+}
+
+void SAL_CALL SwXContentControl::removePropertyChangeListener(
+    const OUString& /*rPropertyName*/,
+    const uno::Reference<beans::XPropertyChangeListener>& /*xListener*/)
+{
+    SAL_WARN("sw.uno", "SwXContentControl::removePropertyChangeListener: not 
implemented");
+}
+
+void SAL_CALL SwXContentControl::addVetoableChangeListener(
+    const OUString& /*rPropertyName*/,
+    const uno::Reference<beans::XVetoableChangeListener>& /*xListener*/)
+{
+    SAL_WARN("sw.uno", "SwXContentControl::addVetoableChangeListener: not 
implemented");
+}
+
+void SAL_CALL SwXContentControl::removeVetoableChangeListener(
+    const OUString& /*rPropertyName*/,
+    const uno::Reference<beans::XVetoableChangeListener>& /*xListener*/)
+{
+    SAL_WARN("sw.uno", "SwXContentControl::removeVetoableChangeListener: not 
implemented");
+}
+
 // XElementAccess
 uno::Type SAL_CALL SwXContentControl::getElementType()
 {
diff --git a/sw/source/core/unocore/unomap.cxx 
b/sw/source/core/unocore/unomap.cxx
index b8e6f166fc80..e07481448d40 100644
--- a/sw/source/core/unocore/unomap.cxx
+++ b/sw/source/core/unocore/unomap.cxx
@@ -1559,6 +1559,11 @@ const SfxItemPropertyMapEntry* 
SwUnoPropertyMapProvider::GetPropertyMapEntries(s
                 m_aMapEntriesArr[nPropertyId] = GetLineBreakPropertyMap();
             }
             break;
+            case PROPERTY_MAP_CONTENTCONTROL:
+            {
+                m_aMapEntriesArr[nPropertyId] = GetContentControlPropertyMap();
+            }
+            break;
 
             default:
                 OSL_FAIL( "unexpected property map ID" );
diff --git a/sw/source/core/unocore/unomap1.cxx 
b/sw/source/core/unocore/unomap1.cxx
index cc27bdc8b549..0b138f1d772c 100644
--- a/sw/source/core/unocore/unomap1.cxx
+++ b/sw/source/core/unocore/unomap1.cxx
@@ -1017,6 +1017,17 @@ const SfxItemPropertyMapEntry* 
SwUnoPropertyMapProvider::GetLineBreakPropertyMap
     return aLineBreakMap_Impl;
 }
 
+const SfxItemPropertyMapEntry* 
SwUnoPropertyMapProvider::GetContentControlPropertyMap()
+{
+    static SfxItemPropertyMapEntry const aContentControlMap_Impl[] =
+    {
+        { u"" UNO_NAME_SHOWING_PLACE_HOLDER, 0, cppu::UnoType<bool>::get(), 
PROPERTY_NONE, 0 },
+        { u"", 0, css::uno::Type(), 0, 0 }
+    };
+
+    return aContentControlMap_Impl;
+}
+
 const SfxItemPropertyMapEntry*  
SwUnoPropertyMapProvider::GetRedlinePropertyMap()
 {
     static SfxItemPropertyMapEntry const aRedlineMap_Impl[] =
@@ -1676,6 +1687,12 @@ const SfxItemPropertySet*  
SwUnoPropertyMapProvider::GetPropertySet( sal_uInt16
                 m_aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_LINEBREAK;
             }
             break;
+            case PROPERTY_MAP_CONTENTCONTROL:
+            {
+                static SfxItemPropertySet 
aPROPERTY_MAP_CONTENTCONTROL(pEntries);
+                m_aPropertySetArr[nPropertyId] = &aPROPERTY_MAP_CONTENTCONTROL;
+            }
+            break;
         }
     }
     return m_aPropertySetArr[nPropertyId];

Reply via email to