officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu |    8 
 sw/Library_swui.mk                                                  |    1 
 sw/UIConfig_swriter.mk                                              |    1 
 sw/inc/cmdid.h                                                      |    1 
 sw/inc/formatcontentcontrol.hxx                                     |    4 
 sw/inc/swabstdlg.hxx                                                |    1 
 sw/qa/core/unocore/unocore.cxx                                      |    6 
 sw/qa/uibase/wrtsh/wrtsh.cxx                                        |    4 
 sw/sdi/_textsh.sdi                                                  |    6 
 sw/sdi/swriter.sdi                                                  |   17 +
 sw/source/core/crsr/contentcontrolbutton.cxx                        |    6 
 sw/source/core/crsr/crstrvl.cxx                                     |    2 
 sw/source/core/crsr/dropdowncontentcontrolbutton.cxx                |   11 
 sw/source/core/crsr/viscrs.cxx                                      |    6 
 sw/source/core/inc/contentcontrolbutton.hxx                         |    7 
 sw/source/core/inc/dropdowncontentcontrolbutton.hxx                 |    3 
 sw/source/filter/ww8/docxattributeoutput.hxx                        |    2 
 sw/source/ui/dialog/swdlgfact.cxx                                   |    7 
 sw/source/ui/dialog/swdlgfact.hxx                                   |    1 
 sw/source/ui/misc/contentcontroldlg.cxx                             |   84 
+++++++
 sw/source/uibase/inc/contentcontroldlg.hxx                          |   46 ++++
 sw/source/uibase/shells/textsh.cxx                                  |   12 +
 sw/source/uibase/shells/textsh1.cxx                                 |    8 
 sw/source/uibase/uno/unotxdoc.cxx                                   |    2 
 sw/source/uibase/wrtsh/wrtsh3.cxx                                   |    2 
 sw/uiconfig/swriter/menubar/menubar.xml                             |    1 
 sw/uiconfig/swriter/menubar/mscompatibleformsmenu.xml               |    1 
 sw/uiconfig/swriter/ui/contentcontroldlg.ui                         |  114 
++++++++++
 28 files changed, 337 insertions(+), 27 deletions(-)

New commits:
commit 268443a55340bf9d106fef870827bd2cff06f7ee
Author:     Miklos Vajna <[email protected]>
AuthorDate: Fri May 13 13:35:23 2022 +0200
Commit:     Miklos Vajna <[email protected]>
CommitDate: Mon May 16 12:25:09 2022 +0200

    sw content controls, dropdown: add an initial properties dialog
    
    - read the doc model: show if a content control is a placeholder or not
    
    - work with a shared pointer in the dialog, which avoids lifetime issues
      in case the content control we edit in one view gets deleted in an
      other view
    
    - write the doc model: set the placeholder mode of the content control
      based on the checkbox state and mark the doc as modified if any widget
      is touched when pressing OK
    
    - handle command state: allow this dialog only inside content controls
    
    (cherry picked from commit 75f7e057039aaa49558e22d18cad651d11589da9)
    
    Change-Id: Ie0b9075ccd3450dd403cc7f8bbf93fc04de3b234
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134386
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git 
a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu 
b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
index 0e99196e6893..a460cf46e5eb 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/WriterCommands.xcu
@@ -512,6 +512,14 @@
           <value>1</value>
         </prop>
       </node>
+      <node oor:name=".uno:ContentControlProperties" oor:op="replace">
+        <prop oor:name="Label" oor:type="xs:string">
+          <value xml:lang="en-US">Content Control Properties</value>
+        </prop>
+        <prop oor:name="Properties" oor:type="xs:int">
+          <value>1</value>
+        </prop>
+      </node>
       <node oor:name=".uno:SetReminder" oor:op="replace">
         <prop oor:name="Label" oor:type="xs:string">
           <value xml:lang="en-US">Set Reminder</value>
diff --git a/sw/Library_swui.mk b/sw/Library_swui.mk
index 99f1dd20ae3d..75a4242b854d 100644
--- a/sw/Library_swui.mk
+++ b/sw/Library_swui.mk
@@ -137,6 +137,7 @@ $(eval $(call gb_Library_add_exception_objects,swui,\
     sw/source/ui/index/multmrk \
     sw/source/ui/index/swuiidxmrk \
     sw/source/ui/misc/bookmark \
+    sw/source/ui/misc/contentcontroldlg \
     sw/source/ui/misc/docfnote \
     sw/source/ui/misc/glosbib \
     sw/source/ui/misc/glossary \
diff --git a/sw/UIConfig_swriter.mk b/sw/UIConfig_swriter.mk
index f38c894695dc..db135a854595 100644
--- a/sw/UIConfig_swriter.mk
+++ b/sw/UIConfig_swriter.mk
@@ -118,6 +118,7 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/swriter,\
        sw/uiconfig/swriter/ui/columndialog \
        sw/uiconfig/swriter/ui/columnpage \
        sw/uiconfig/swriter/ui/columnwidth \
+       sw/uiconfig/swriter/ui/contentcontroldlg \
        sw/uiconfig/swriter/ui/combobox \
        sw/uiconfig/swriter/ui/comboboxfragment \
        sw/uiconfig/swriter/ui/conditionpage \
diff --git a/sw/inc/cmdid.h b/sw/inc/cmdid.h
index 38a965802806..e477ccd054aa 100644
--- a/sw/inc/cmdid.h
+++ b/sw/inc/cmdid.h
@@ -215,6 +215,7 @@
 #define FN_INSERT_OBJECT_DLG    (FN_INSERT + 22)    /* Object */
 #define FN_INSERT_PAGEBREAK     (FN_INSERT + 23)    /* Page break*/
 #define FN_INSERT_DROPDOWN_CONTENT_CONTROL (FN_INSERT + 24)  /* Dropdown 
content control */
+#define FN_CONTENT_CONTROL_PROPERTIES (FN_INSERT + 25)  /* Content control 
properties */
 #define FN_POSTIT               (FN_INSERT + 29)    /* Insert/edit PostIt */
 #define FN_INSERT_TABLE         (FN_INSERT + 30)    /* Insert Table */
 #define FN_INSERT_STRING        (FN_INSERT+31)
diff --git a/sw/inc/formatcontentcontrol.hxx b/sw/inc/formatcontentcontrol.hxx
index d544021cdd8b..c99382340025 100644
--- a/sw/inc/formatcontentcontrol.hxx
+++ b/sw/inc/formatcontentcontrol.hxx
@@ -68,8 +68,8 @@ public:
      */
     void NotifyChangeTextNode(SwTextNode* pTextNode);
     static SwFormatContentControl* CreatePoolDefault(sal_uInt16 nWhich);
-    SwContentControl* GetContentControl() { return m_pContentControl.get(); }
-    const SwContentControl* GetContentControl() const { return 
m_pContentControl.get(); }
+    std::shared_ptr<SwContentControl> GetContentControl() { return 
m_pContentControl; }
+    const std::shared_ptr<SwContentControl>& GetContentControl() const { 
return m_pContentControl; }
 
     void dumpAsXml(xmlTextWriterPtr pWriter) const override;
 };
diff --git a/sw/inc/swabstdlg.hxx b/sw/inc/swabstdlg.hxx
index 08c71a2f33d1..8661310d8d38 100644
--- a/sw/inc/swabstdlg.hxx
+++ b/sw/inc/swabstdlg.hxx
@@ -379,6 +379,7 @@ public:
     virtual VclPtr<AbstractSwAsciiFilterDlg>  
CreateSwAsciiFilterDlg(weld::Window* pParent, SwDocShell& rDocSh,
                                                                 SvStream* 
pStream) = 0;
     virtual VclPtr<VclAbstractDialog> CreateSwInsertBookmarkDlg(weld::Window 
*pParent, SwWrtShell &rSh) = 0;
+    virtual VclPtr<VclAbstractDialog> CreateSwContentControlDlg(weld::Window 
*pParent, SwWrtShell &rSh) = 0;
 
     virtual std::shared_ptr<AbstractSwBreakDlg> CreateSwBreakDlg(weld::Window 
*pParent, SwWrtShell &rSh) = 0;
     virtual VclPtr<VclAbstractDialog> CreateSwChangeDBDlg(SwView& rVw) = 0;
diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx
index 8eb74623ad28..1e663a7bb156 100644
--- a/sw/qa/core/unocore/unocore.cxx
+++ b/sw/qa/core/unocore/unocore.cxx
@@ -315,7 +315,7 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, 
testContentControlInsert)
     auto pTextContentControl = 
static_txtattr_cast<SwTextContentControl*>(pAttr);
     auto& rFormatContentControl
         = static_cast<SwFormatContentControl&>(pTextContentControl->GetAttr());
-    SwContentControl* pContentControl = 
rFormatContentControl.GetContentControl();
+    std::shared_ptr<SwContentControl> pContentControl = 
rFormatContentControl.GetContentControl();
     CPPUNIT_ASSERT(pContentControl->GetShowingPlaceHolder());
 }
 
@@ -407,7 +407,7 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, 
testContentControlCheckbox)
     auto pTextContentControl = 
static_txtattr_cast<SwTextContentControl*>(pAttr);
     auto& rFormatContentControl
         = static_cast<SwFormatContentControl&>(pTextContentControl->GetAttr());
-    SwContentControl* pContentControl = 
rFormatContentControl.GetContentControl();
+    std::shared_ptr<SwContentControl> pContentControl = 
rFormatContentControl.GetContentControl();
     CPPUNIT_ASSERT(pContentControl->GetCheckbox());
     CPPUNIT_ASSERT(pContentControl->GetChecked());
     CPPUNIT_ASSERT_EQUAL(OUString(u"☒"), pContentControl->GetCheckedState());
@@ -458,7 +458,7 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, 
testContentControlDropdown)
     auto pTextContentControl = 
static_txtattr_cast<SwTextContentControl*>(pAttr);
     auto& rFormatContentControl
         = static_cast<SwFormatContentControl&>(pTextContentControl->GetAttr());
-    SwContentControl* pContentControl = 
rFormatContentControl.GetContentControl();
+    std::shared_ptr<SwContentControl> pContentControl = 
rFormatContentControl.GetContentControl();
     std::vector<SwContentControlListItem> aListItems = 
pContentControl->GetListItems();
     CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aListItems.size());
     CPPUNIT_ASSERT_EQUAL(OUString("red"), aListItems[0].m_aDisplayText);
diff --git a/sw/qa/uibase/wrtsh/wrtsh.cxx b/sw/qa/uibase/wrtsh/wrtsh.cxx
index 9e9cee69f9ee..7317c0e2bbfa 100644
--- a/sw/qa/uibase/wrtsh/wrtsh.cxx
+++ b/sw/qa/uibase/wrtsh/wrtsh.cxx
@@ -160,7 +160,7 @@ CPPUNIT_TEST_FIXTURE(Test, testInsertCheckboxContentControl)
     auto pTextContentControl = 
static_txtattr_cast<SwTextContentControl*>(pAttr);
     auto& rFormatContentControl
         = static_cast<SwFormatContentControl&>(pTextContentControl->GetAttr());
-    SwContentControl* pContentControl = 
rFormatContentControl.GetContentControl();
+    std::shared_ptr<SwContentControl> pContentControl = 
rFormatContentControl.GetContentControl();
     // Without the accompanying fix in place, this test would have failed, the 
inserted content
     // control wasn't a checkbox one.
     CPPUNIT_ASSERT(pContentControl->GetCheckbox());
@@ -232,7 +232,7 @@ CPPUNIT_TEST_FIXTURE(Test, testInsertDropdownContentControl)
     auto pTextContentControl = 
static_txtattr_cast<SwTextContentControl*>(pAttr);
     auto& rFormatContentControl
         = static_cast<SwFormatContentControl&>(pTextContentControl->GetAttr());
-    SwContentControl* pContentControl = 
rFormatContentControl.GetContentControl();
+    std::shared_ptr<SwContentControl> pContentControl = 
rFormatContentControl.GetContentControl();
     // Without the accompanying fix in place, this test would have failed:
     // - Expected: 1
     // - Actual  : 0
diff --git a/sw/sdi/_textsh.sdi b/sw/sdi/_textsh.sdi
index f9ec02b66f6d..816439cee140 100644
--- a/sw/sdi/_textsh.sdi
+++ b/sw/sdi/_textsh.sdi
@@ -290,6 +290,12 @@ interface BaseText
         StateMethod = NoState ;
         DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
     ]
+    FN_CONTENT_CONTROL_PROPERTIES  // status(final|play)
+    [
+        ExecMethod = ExecInsert ;
+        StateMethod = GetState ;
+        DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
+    ]
     FN_INSERT_COLUMN_BREAK // status(final|play)
     [
         ExecMethod = ExecInsert ;
diff --git a/sw/sdi/swriter.sdi b/sw/sdi/swriter.sdi
index aeae14479435..7663d3f2c6b1 100644
--- a/sw/sdi/swriter.sdi
+++ b/sw/sdi/swriter.sdi
@@ -3083,6 +3083,23 @@ SfxVoidItem InsertDropdownContentControl 
FN_INSERT_DROPDOWN_CONTENT_CONTROL
     GroupId = SfxGroupId::Insert;
 ]
 
+SfxVoidItem ContentControlProperties FN_CONTENT_CONTROL_PROPERTIES
+()
+[
+    AutoUpdate = FALSE,
+    FastCall = FALSE,
+    ReadOnlyDoc = FALSE,
+    Toggle = FALSE,
+    Container = FALSE,
+    RecordAbsolute = FALSE,
+    RecordPerSet;
+
+    AccelConfig = TRUE,
+    MenuConfig = TRUE,
+    ToolBoxConfig = TRUE,
+    GroupId = SfxGroupId::Insert;
+]
+
 SfxVoidItem InsertMultiIndex FN_INSERT_MULTI_TOX
 ()
 [
diff --git a/sw/source/core/crsr/contentcontrolbutton.cxx 
b/sw/source/core/crsr/contentcontrolbutton.cxx
index c135e25bd188..00deb260981c 100644
--- a/sw/source/core/crsr/contentcontrolbutton.cxx
+++ b/sw/source/core/crsr/contentcontrolbutton.cxx
@@ -14,10 +14,10 @@
 
 #include <edtwin.hxx>
 
-SwContentControlButton::SwContentControlButton(SwEditWin* pEditWin,
-                                               const SwContentControl& 
rContentControl)
+SwContentControlButton::SwContentControlButton(
+    SwEditWin* pEditWin, const std::shared_ptr<SwContentControl>& 
pContentControl)
     : Control(pEditWin, WB_DIALOGCONTROL)
-    , m_rContentControl(rContentControl)
+    , m_pContentControl(pContentControl)
 {
     assert(GetParent());
     assert(dynamic_cast<SwEditWin*>(GetParent()));
diff --git a/sw/source/core/crsr/crstrvl.cxx b/sw/source/core/crsr/crstrvl.cxx
index 4c3f8eb16fb2..4e4400531d97 100644
--- a/sw/source/core/crsr/crstrvl.cxx
+++ b/sw/source/core/crsr/crstrvl.cxx
@@ -856,7 +856,7 @@ bool SwCursorShell::GotoFootnoteAnchor(const 
SwTextFootnote& rTextFootnote)
 bool SwCursorShell::GotoFormatContentControl(const SwFormatContentControl& 
rContentControl)
 {
     bool bRet = false;
-    auto pContentControl = 
const_cast<SwContentControl*>(rContentControl.GetContentControl());
+    std::shared_ptr<SwContentControl> pContentControl = 
rContentControl.GetContentControl();
     if (!pContentControl->GetShowingPlaceHolder() && 
!pContentControl->GetCheckbox()
         && !pContentControl->GetSelectedListItem())
     {
diff --git a/sw/source/core/crsr/dropdowncontentcontrolbutton.cxx 
b/sw/source/core/crsr/dropdowncontentcontrolbutton.cxx
index a1f73dc1b522..2fa456e41ee5 100644
--- a/sw/source/core/crsr/dropdowncontentcontrolbutton.cxx
+++ b/sw/source/core/crsr/dropdowncontentcontrolbutton.cxx
@@ -21,7 +21,7 @@
 
 void SwDropDownContentControlButton::InitDropdown()
 {
-    std::vector<SwContentControlListItem> aListItems = 
m_rContentControl.GetListItems();
+    std::vector<SwContentControlListItem> aListItems = 
m_pContentControl->GetListItems();
 
     for (const auto& rListItem : aListItems)
     {
@@ -60,17 +60,16 @@ IMPL_LINK(SwDropDownContentControlButton, ListBoxHandler, 
weld::TreeView&, rBox,
     {
         SwView& rView = static_cast<SwEditWin*>(GetParent())->GetView();
         SwWrtShell& rWrtShell = rView.GetWrtShell();
-        auto& rContentControl = 
const_cast<SwContentControl&>(m_rContentControl);
-        rContentControl.SetSelectedListItem(nSelection);
-        
rWrtShell.GotoContentControl(*m_rContentControl.GetFormatContentControl());
+        m_pContentControl->SetSelectedListItem(nSelection);
+        
rWrtShell.GotoContentControl(*m_pContentControl->GetFormatContentControl());
     }
 
     return true;
 }
 
 SwDropDownContentControlButton::SwDropDownContentControlButton(
-    SwEditWin* pEditWin, const SwContentControl& rContentControl)
-    : SwContentControlButton(pEditWin, rContentControl)
+    SwEditWin* pEditWin, const std::shared_ptr<SwContentControl>& 
pContentControl)
+    : SwContentControlButton(pEditWin, pContentControl)
 {
 }
 
diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx
index 531379114af9..6320ea8d1d4a 100644
--- a/sw/source/core/crsr/viscrs.cxx
+++ b/sw/source/core/crsr/viscrs.cxx
@@ -639,7 +639,7 @@ void SwSelPaintRects::HighlightContentControl()
     std::vector<basegfx::B2DRange> aContentControlRanges;
     std::vector<OString> aLOKRectangles;
     SwRect aLastPortionPaintArea;
-    const SwContentControl* pContentControl = nullptr;
+    std::shared_ptr<SwContentControl> pContentControl;
 
     if (m_bShowContentControlOverlay)
     {
@@ -739,14 +739,14 @@ void SwSelPaintRects::HighlightContentControl()
             {
                 auto& rEditWin = 
const_cast<SwEditWin&>(pWrtShell->GetView().GetEditWin());
                 if (m_pContentControlButton
-                    && &m_pContentControlButton->GetContentControl() != 
pContentControl)
+                    && m_pContentControlButton->GetContentControl() != 
pContentControl)
                 {
                     m_pContentControlButton.disposeAndClear();
                 }
                 if (!m_pContentControlButton)
                 {
                     m_pContentControlButton = 
VclPtr<SwDropDownContentControlButton>::Create(
-                        &rEditWin, *pContentControl);
+                        &rEditWin, pContentControl);
                 }
                 m_pContentControlButton->CalcPosAndSize(aLastPortionPaintArea);
                 m_pContentControlButton->Show();
diff --git a/sw/source/core/inc/contentcontrolbutton.hxx 
b/sw/source/core/inc/contentcontrolbutton.hxx
index d840887fb460..a921680ed7d4 100644
--- a/sw/source/core/inc/contentcontrolbutton.hxx
+++ b/sw/source/core/inc/contentcontrolbutton.hxx
@@ -20,7 +20,8 @@ class SwContentControl;
 class SwContentControlButton : public Control
 {
 public:
-    SwContentControlButton(SwEditWin* pEditWin, const SwContentControl& 
rContentControl);
+    SwContentControlButton(SwEditWin* pEditWin,
+                           const std::shared_ptr<SwContentControl>& 
pContentControl);
     virtual ~SwContentControlButton() override;
     virtual void dispose() override;
 
@@ -35,13 +36,13 @@ public:
     virtual void LaunchPopup();
     virtual void DestroyPopup();
 
-    const SwContentControl& GetContentControl() const { return 
m_rContentControl; }
+    const std::shared_ptr<SwContentControl>& GetContentControl() const { 
return m_pContentControl; }
 
 private:
     tools::Rectangle m_aFramePixel;
 
 protected:
-    const SwContentControl& m_rContentControl;
+    std::shared_ptr<SwContentControl> m_pContentControl;
     std::unique_ptr<weld::Builder> m_xPopupBuilder;
     std::unique_ptr<weld::Popover> m_xPopup;
 };
diff --git a/sw/source/core/inc/dropdowncontentcontrolbutton.hxx 
b/sw/source/core/inc/dropdowncontentcontrolbutton.hxx
index 5be95ae5adf6..6ca32974e196 100644
--- a/sw/source/core/inc/dropdowncontentcontrolbutton.hxx
+++ b/sw/source/core/inc/dropdowncontentcontrolbutton.hxx
@@ -28,7 +28,8 @@ private:
     void InitDropdown();
 
 public:
-    SwDropDownContentControlButton(SwEditWin* pEditWin, const 
SwContentControl& rContentControl);
+    SwDropDownContentControlButton(SwEditWin* pEditWin,
+                                   const std::shared_ptr<SwContentControl>& 
pContentControl);
     virtual ~SwDropDownContentControlButton() override;
 
     virtual void LaunchPopup() override;
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx 
b/sw/source/filter/ww8/docxattributeoutput.hxx
index eec6b438e498..a264b879fd9b 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -788,7 +788,7 @@ private:
     rtl::Reference<sax_fastparser::FastAttributeList> 
m_pSectionSpacingAttrList;
     rtl::Reference<sax_fastparser::FastAttributeList> 
m_pParagraphSpacingAttrList;
     rtl::Reference<sax_fastparser::FastAttributeList> m_pHyperlinkAttrList;
-    const SwContentControl* m_pContentControl = nullptr;
+    std::shared_ptr<SwContentControl> m_pContentControl;
     /// If the current SDT around runs should be ended before the current run.
     bool m_bEndCharSdt;
     /// Attributes of the run color
diff --git a/sw/source/ui/dialog/swdlgfact.cxx 
b/sw/source/ui/dialog/swdlgfact.cxx
index dd5211277832..62697ffe2953 100644
--- a/sw/source/ui/dialog/swdlgfact.cxx
+++ b/sw/source/ui/dialog/swdlgfact.cxx
@@ -33,6 +33,7 @@
 #include <changedb.hxx>
 #include <chrdlg.hxx>
 #include <colwd.hxx>
+#include <contentcontroldlg.hxx>
 #include <convert.hxx>
 #include <cption.hxx>
 #include <dbinsdlg.hxx>
@@ -835,6 +836,12 @@ VclPtr<VclAbstractDialog> 
SwAbstractDialogFactory_Impl::CreateSwInsertBookmarkDl
     return 
VclPtr<AbstractGenericDialog_Impl>::Create(std::make_shared<SwInsertBookmarkDlg>(pParent,
 rSh));
 }
 
+VclPtr<VclAbstractDialog> 
SwAbstractDialogFactory_Impl::CreateSwContentControlDlg(weld::Window* pParent,
+                                                                               
   SwWrtShell &rSh)
+{
+    return 
VclPtr<AbstractGenericDialog_Impl>::Create(std::make_shared<SwContentControlDlg>(pParent,
 rSh));
+}
+
 std::shared_ptr<AbstractSwBreakDlg> 
SwAbstractDialogFactory_Impl::CreateSwBreakDlg(weld::Window* pParent, 
SwWrtShell &rSh)
 {
     return 
std::make_shared<AbstractSwBreakDlg_Impl>(std::make_unique<SwBreakDlg>(pParent, 
rSh));
diff --git a/sw/source/ui/dialog/swdlgfact.hxx 
b/sw/source/ui/dialog/swdlgfact.hxx
index 867b37a467f6..6eb68355762c 100644
--- a/sw/source/ui/dialog/swdlgfact.hxx
+++ b/sw/source/ui/dialog/swdlgfact.hxx
@@ -658,6 +658,7 @@ public:
     virtual VclPtr<AbstractSwAsciiFilterDlg>  
CreateSwAsciiFilterDlg(weld::Window* pParent, SwDocShell& rDocSh,
                                                                 SvStream* 
pStream) override;
     virtual VclPtr<VclAbstractDialog> CreateSwInsertBookmarkDlg(weld::Window 
*pParent, SwWrtShell &rSh) override;
+    virtual VclPtr<VclAbstractDialog> CreateSwContentControlDlg(weld::Window 
*pParent, SwWrtShell &rSh) override;
     virtual std::shared_ptr<AbstractSwBreakDlg> CreateSwBreakDlg(weld::Window 
*pParent, SwWrtShell &rSh) override;
     virtual VclPtr<VclAbstractDialog> CreateSwChangeDBDlg(SwView& rVw) 
override;
     virtual VclPtr<SfxAbstractTabDialog>  CreateSwCharDlg(weld::Window* 
pParent, SwView& pVw, const SfxItemSet& rCoreSet,
diff --git a/sw/source/ui/misc/contentcontroldlg.cxx 
b/sw/source/ui/misc/contentcontroldlg.cxx
new file mode 100644
index 000000000000..d18c3077f24d
--- /dev/null
+++ b/sw/source/ui/misc/contentcontroldlg.cxx
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <contentcontroldlg.hxx>
+
+#include <vcl/weld.hxx>
+
+#include <wrtsh.hxx>
+#include <ndtxt.hxx>
+#include <textcontentcontrol.hxx>
+#include <IDocumentState.hxx>
+
+using namespace com::sun::star;
+
+SwContentControlDlg::SwContentControlDlg(weld::Window* pParent, SwWrtShell& 
rWrtShell)
+    : SfxDialogController(pParent, "modules/swriter/ui/contentcontroldlg.ui",
+                          "ContentControlDialog")
+    , m_rWrtShell(rWrtShell)
+    , 
m_xShowingPlaceHolderCB(m_xBuilder->weld_check_button("showing_place_holder"))
+    , m_xOk(m_xBuilder->weld_button("ok"))
+{
+    m_xOk->connect_clicked(LINK(this, SwContentControlDlg, OkHdl));
+
+    const SwPosition* pStart = rWrtShell.GetCursor()->Start();
+    SwTextNode* pTextNode = pStart->nNode.GetNode().GetTextNode();
+    if (!pTextNode)
+    {
+        return;
+    }
+
+    SwTextAttr* pAttr = pTextNode->GetTextAttrAt(pStart->nContent.GetIndex(),
+                                                 RES_TXTATR_CONTENTCONTROL, 
SwTextNode::PARENT);
+    if (!pAttr)
+    {
+        return;
+    }
+
+    SwTextContentControl* pTextContentControl = 
static_txtattr_cast<SwTextContentControl*>(pAttr);
+    const SwFormatContentControl& rFormatContentControl = 
pTextContentControl->GetContentControl();
+    m_pContentControl = rFormatContentControl.GetContentControl();
+
+    bool bShowingPlaceHolder = m_pContentControl->GetShowingPlaceHolder();
+    TriState eShowingPlaceHolder = bShowingPlaceHolder ? TRISTATE_TRUE : 
TRISTATE_FALSE;
+    m_xShowingPlaceHolderCB->set_state(eShowingPlaceHolder);
+    m_xShowingPlaceHolderCB->save_state();
+}
+
+SwContentControlDlg::~SwContentControlDlg() {}
+
+IMPL_LINK_NOARG(SwContentControlDlg, OkHdl, weld::Button&, void)
+{
+    bool bChanged = false;
+    if (m_xShowingPlaceHolderCB->get_state_changed_from_saved())
+    {
+        bool bShowingPlaceHolder = m_xShowingPlaceHolderCB->get_state() == 
TRISTATE_TRUE;
+        m_pContentControl->SetShowingPlaceHolder(bShowingPlaceHolder);
+        bChanged = true;
+    }
+
+    if (bChanged)
+    {
+        m_rWrtShell.GetDoc()->getIDocumentState().SetModified();
+    }
+
+    m_xDialog->response(RET_OK);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/contentcontroldlg.hxx 
b/sw/source/uibase/inc/contentcontroldlg.hxx
new file mode 100644
index 000000000000..6b354a39e7c4
--- /dev/null
+++ b/sw/source/uibase/inc/contentcontroldlg.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <sfx2/basedlgs.hxx>
+#include <vcl/weld.hxx>
+
+class SwWrtShell;
+class SwContentControl;
+
+/**
+ * The content control dialog allows editing the properties of the content 
control under the
+ * cursor.
+ */
+class SwContentControlDlg final : public SfxDialogController
+{
+    SwWrtShell& m_rWrtShell;
+    std::shared_ptr<SwContentControl> m_pContentControl;
+
+    std::unique_ptr<weld::CheckButton> m_xShowingPlaceHolderCB;
+    std::unique_ptr<weld::Button> m_xOk;
+
+    DECL_LINK(OkHdl, weld::Button&, void);
+
+public:
+    SwContentControlDlg(weld::Window* pParent, SwWrtShell& rSh);
+    virtual ~SwContentControlDlg() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/textsh.cxx 
b/sw/source/uibase/shells/textsh.cxx
index 168f551d8bd1..a8326e40200e 100644
--- a/sw/source/uibase/shells/textsh.cxx
+++ b/sw/source/uibase/shells/textsh.cxx
@@ -234,6 +234,18 @@ void SwTextShell::ExecInsert(SfxRequest &rReq)
         rReq.Done();
         break;
 
+    case FN_CONTENT_CONTROL_PROPERTIES:
+    {
+        SwWrtShell& rWrtSh = GetShell();
+        SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+        ScopedVclPtr<VclAbstractDialog> 
pDlg(pFact->CreateSwContentControlDlg(GetView().GetFrameWeld(), rWrtSh));
+        VclAbstractDialog::AsyncContext aContext;
+        aContext.maEndDialogFn = [](sal_Int32){};
+        pDlg->StartExecuteAsync(aContext);
+        rReq.Done();
+        break;
+    }
+
     case FN_INSERT_COLUMN_BREAK:
         rSh.InsertColumnBreak();
         rReq.Done();
diff --git a/sw/source/uibase/shells/textsh1.cxx 
b/sw/source/uibase/shells/textsh1.cxx
index 76f200435fa5..ceba4f56522c 100644
--- a/sw/source/uibase/shells/textsh1.cxx
+++ b/sw/source/uibase/shells/textsh1.cxx
@@ -2238,6 +2238,14 @@ void SwTextShell::GetState( SfxItemSet &rSet )
                 rSet.Put(SfxBoolItem(nWhich, bProtected));
             }
             break;
+            case FN_CONTENT_CONTROL_PROPERTIES:
+            {
+                if (!GetShell().CursorInsideContentControl())
+                {
+                    rSet.DisableItem(nWhich);
+                }
+            }
+            break;
         }
         nWhich = aIter.NextWhich();
     }
diff --git a/sw/source/uibase/uno/unotxdoc.cxx 
b/sw/source/uibase/uno/unotxdoc.cxx
index 2234e1a19863..877ebf67cb23 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3382,7 +3382,7 @@ void SwXTextDocument::executeContentControlEvent(const 
StringMap& rArguments)
 
     auto pTextContentControl = 
static_txtattr_cast<SwTextContentControl*>(pAttr);
     const SwFormatContentControl& rFormatContentControl = 
pTextContentControl->GetContentControl();
-    auto pContentControl = 
const_cast<SwContentControl*>(rFormatContentControl.GetContentControl());
+    std::shared_ptr<SwContentControl> pContentControl = 
rFormatContentControl.GetContentControl();
     auto it = rArguments.find("type");
     if (it == rArguments.end())
     {
diff --git a/sw/source/uibase/wrtsh/wrtsh3.cxx 
b/sw/source/uibase/wrtsh/wrtsh3.cxx
index 5225c7278357..c0567d03427b 100644
--- a/sw/source/uibase/wrtsh/wrtsh3.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh3.cxx
@@ -94,7 +94,7 @@ bool SwWrtShell::GotoContentControl(const 
SwFormatContentControl& rContentContro
 
     bool bRet = SwCursorShell::GotoFormatContentControl(rContentControl);
 
-    auto pContentControl = 
const_cast<SwContentControl*>(rContentControl.GetContentControl());
+    std::shared_ptr<SwContentControl> pContentControl = 
rContentControl.GetContentControl();
     if (bRet && pContentControl && pContentControl->GetCheckbox())
     {
         // Checkbox: GotoFormatContentControl() selected the old state.
diff --git a/sw/uiconfig/swriter/menubar/menubar.xml 
b/sw/uiconfig/swriter/menubar/menubar.xml
index c5d48d6375b3..50be3dde2bba 100644
--- a/sw/uiconfig/swriter/menubar/menubar.xml
+++ b/sw/uiconfig/swriter/menubar/menubar.xml
@@ -715,6 +715,7 @@
           <menu:menuitem menu:id=".uno:InsertContentControl"/>
           <menu:menuitem menu:id=".uno:InsertCheckboxContentControl"/>
           <menu:menuitem menu:id=".uno:InsertDropdownContentControl"/>
+          <menu:menuitem menu:id=".uno:ContentControlProperties"/>
         </menu:menupopup>
       </menu:menu>
     </menu:menupopup>
diff --git a/sw/uiconfig/swriter/menubar/mscompatibleformsmenu.xml 
b/sw/uiconfig/swriter/menubar/mscompatibleformsmenu.xml
index 83b8cd35d98a..147b4dd03d6e 100644
--- a/sw/uiconfig/swriter/menubar/mscompatibleformsmenu.xml
+++ b/sw/uiconfig/swriter/menubar/mscompatibleformsmenu.xml
@@ -19,6 +19,7 @@
           <menu:menuitem menu:id=".uno:InsertCheckboxContentControl"/>
           <menu:menuitem menu:id=".uno:InsertDropdownContentControl"/>
           <menu:menuitem menu:id=".uno:DatePickerFormField"/>
+          <menu:menuitem menu:id=".uno:ContentControlProperties"/>
         </menu:menupopup>
       </menu:menu>
       <menu:menu menu:id=".uno:MSCompatLegacyControls">
diff --git a/sw/uiconfig/swriter/ui/contentcontroldlg.ui 
b/sw/uiconfig/swriter/ui/contentcontroldlg.ui
new file mode 100644
index 000000000000..5ac95091d71c
--- /dev/null
+++ b/sw/uiconfig/swriter/ui/contentcontroldlg.ui
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="sw">
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkDialog" id="ContentControlDialog">
+    <property name="can-focus">False</property>
+    <property name="border-width">6</property>
+    <property name="title" translatable="yes" 
context="contentcontroldlg|ContentControlDialog">Content Control 
Properties</property>
+    <property name="modal">True</property>
+    <property name="default-width">0</property>
+    <property name="default-height">0</property>
+    <property name="type-hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="can-focus">False</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">6</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox">
+            <property name="can-focus">False</property>
+            <child>
+              <object class="GtkButton" id="ok">
+                <property name="label" translatable="yes" 
context="stock">_OK</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="has_default">True</property>
+                <property name="receives_default">True</property>
+                <property name="use-underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="cancel">
+                <property name="label" translatable="yes" 
context="stock">_Cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use-underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="help">
+                <property name="label" translatable="yes" 
context="stock">_Help</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use-underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+                <property name="secondary">True</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <!-- n-columns=1 n-rows=1 -->
+          <object class="GtkGrid">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="row-spacing">6</property>
+            <property name="column-spacing">6</property>
+            <child>
+              <object class="GtkCheckButton" id="showing_place_holder">
+                <property name="label" translatable="yes" 
context="contentcontroldlg|showing_place_holder">Content is placeholder 
text</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="receives-default">False</property>
+                <property name="halign">start</property>
+                <property name="valign">start</property>
+                <property name="use-underline">True</property>
+                <property name="draw-indicator">True</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-5">ok</action-widget>
+      <action-widget response="-6">cancel</action-widget>
+      <action-widget response="-11">help</action-widget>
+    </action-widgets>
+  </object>
+  <object class="GtkSizeGroup" id="sgLabels"/>
+</interface>

Reply via email to