sw/inc/formatcontentcontrol.hxx                 |    2 +
 sw/inc/textcontentcontrol.hxx                   |    1 
 sw/source/core/crsr/crstrvl.cxx                 |    3 --
 sw/source/core/txtnode/attrcontentcontrol.cxx   |   25 +++++++++++++++++++++++-
 sw/source/ui/vba/vbacontentcontrol.cxx          |   21 ++++++++------------
 sw/source/ui/vba/vbacontentcontrollistentry.cxx |   16 +++++++++++++--
 sw/source/uibase/inc/wrtsh.hxx                  |    7 +++++-
 sw/source/uibase/wrtsh/wrtsh3.cxx               |   25 +++++++++++++-----------
 8 files changed, 70 insertions(+), 30 deletions(-)

New commits:
commit f281cdd13347b86db4a9eb8b36162ffe30f2c52b
Author:     Justin Luth <[email protected]>
AuthorDate: Wed Nov 23 08:15:15 2022 -0500
Commit:     Miklos Vajna <[email protected]>
CommitDate: Tue Dec 13 08:27:02 2022 +0000

    tdf#151548 ContentControls: Add Invalidate()
    
    Squashed commit.
    
    Up until now, all changes made to a content control
    have been triggered by the UI.
    However, VBA makes changes by code,
    and those property changes were just being ignored
    until the control received the focus.
    
    Change-Id: Ife865dd493f7eae4d4e95096071f05b8c27d51db
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143194
    Reviewed-by: Justin Luth <[email protected]>
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <[email protected]>
    
    tdf#151548 ContentControls: improve Invalidation
    
    This addresses some hack concerns that Miklos raised
    in his review.
    
    Change-Id: Ic6d906e9eb1d23700fb743e179ba87899ce2f4a1
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143412
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144011
    Tested-by: Jenkins CollaboraOffice <[email protected]>

diff --git a/sw/inc/formatcontentcontrol.hxx b/sw/inc/formatcontentcontrol.hxx
index 8546e78dabc4..a782112fb917 100644
--- a/sw/inc/formatcontentcontrol.hxx
+++ b/sw/inc/formatcontentcontrol.hxx
@@ -179,9 +179,11 @@ class SW_DLLPUBLIC SwContentControl : public 
sw::BroadcastingModify
     sal_Int32 m_nId = 0;
 
     /// Stores a list item index, in case the doc model is not yet updated.
+    // i.e. temporarily store the selected item until the text is inserted by 
GotoContentControl.
     std::optional<size_t> m_oSelectedListItem;
 
     /// Stores a date timestamp, in case the doc model is not yet updated.
+    // i.e. temporarily store the date until the text is inserted by 
GotoContentControl.
     std::optional<double> m_oSelectedDate;
 
     /**
diff --git a/sw/inc/textcontentcontrol.hxx b/sw/inc/textcontentcontrol.hxx
index 78a4d5120b1b..8c8a3b3ee044 100644
--- a/sw/inc/textcontentcontrol.hxx
+++ b/sw/inc/textcontentcontrol.hxx
@@ -42,6 +42,7 @@ public:
     void ChgTextNode(SwTextNode* pNode);
 
     SwTextNode* GetTextNode() const;
+    void Invalidate();
 
     void dumpAsXml(xmlTextWriterPtr pWriter) const override;
 };
diff --git a/sw/source/core/crsr/crstrvl.cxx b/sw/source/core/crsr/crstrvl.cxx
index 463a1d05dada..42f80e9bd013 100644
--- a/sw/source/core/crsr/crstrvl.cxx
+++ b/sw/source/core/crsr/crstrvl.cxx
@@ -883,9 +883,6 @@ bool SwCursorShell::GotoFormatContentControl(const 
SwFormatContentControl& rCont
         sal_Int32 nEnd = *pTextContentControl->End() - 1;
         pCursor->GetMark()->nContent.Assign(pTextNode, nEnd);
 
-        // Assume that once the placeholder is selected, the content is no 
longer the placeholder.
-        pContentControl->SetShowingPlaceHolder(false);
-
         bRet = !pCursor->IsSelOvr();
         if (bRet)
         {
diff --git a/sw/source/core/txtnode/attrcontentcontrol.cxx 
b/sw/source/core/txtnode/attrcontentcontrol.cxx
index 3a7d0155c23e..8963d256939c 100644
--- a/sw/source/core/txtnode/attrcontentcontrol.cxx
+++ b/sw/source/core/txtnode/attrcontentcontrol.cxx
@@ -30,6 +30,7 @@
 #include <ndtxt.hxx>
 #include <textcontentcontrol.hxx>
 #include <doc.hxx>
+#include <wrtsh.hxx>
 
 using namespace com::sun::star;
 
@@ -273,7 +274,8 @@ void SwContentControl::DeleteListItem(size_t nZIndex)
         if (*oSelected == nZIndex)
         {
             SetSelectedListItem(std::nullopt);
-            //Invalidate();
+            if (m_bDropDown && GetTextAttr())
+                GetTextAttr()->Invalidate();
         }
         else if (*oSelected < nZIndex)
             SetSelectedListItem(*oSelected - 1);
@@ -289,6 +291,8 @@ void SwContentControl::ClearListItems()
 {
     SetSelectedListItem(std::nullopt);
     SetListItems(std::vector<SwContentControlListItem>());
+    if (m_bDropDown && GetTextAttr())
+        GetTextAttr()->Invalidate();
 }
 
 OUString SwContentControl::GetDateString() const
@@ -652,6 +656,25 @@ SwTextNode* SwTextContentControl::GetTextNode() const
     return rFormatContentControl.GetTextNode();
 }
 
+void SwTextContentControl::Invalidate()
+{
+    SwDocShell* pDocShell = GetTextNode() ? 
GetTextNode()->GetDoc().GetDocShell() : nullptr;
+    if (!pDocShell || !pDocShell->GetWrtShell())
+        return;
+
+    // save the cursor
+    // NOTE: needs further testing to see if this is adequate (i.e. in 
auto-run macros...)
+    pDocShell->GetWrtShell()->Push();
+
+    // visit the control in the text (which makes any necessary visual changes)
+    // NOTE: simply going to a control indicates cancelling 
ShowingPlaceHolder, unless bOnlyRefresh
+    // NOTE: simply going to a checkbox causes a toggle, unless bOnlyRefresh
+    auto& rFormatContentControl = 
static_cast<SwFormatContentControl&>(GetAttr());
+    pDocShell->GetWrtShell()->GotoContentControl(rFormatContentControl, 
/*bOnlyRefresh=*/true);
+
+    pDocShell->GetWrtShell()->Pop(SwCursorShell::PopMode::DeleteCurrent);
+}
+
 void SwTextContentControl::dumpAsXml(xmlTextWriterPtr pWriter) const
 {
     (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwTextContentControl"));
diff --git a/sw/source/ui/vba/vbacontentcontrol.cxx 
b/sw/source/ui/vba/vbacontentcontrol.cxx
index 62ee4a4f7be6..d75ce84d7f4a 100644
--- a/sw/source/ui/vba/vbacontentcontrol.cxx
+++ b/sw/source/ui/vba/vbacontentcontrol.cxx
@@ -99,7 +99,8 @@ void SwVbaContentControl::setChecked(sal_Bool bSet)
     if (pCC->GetCheckbox() && pCC->GetChecked() != static_cast<bool>(bSet))
     {
         pCC->SetChecked(bSet);
-        //pCC->Invalidate();
+        pCC->SetShowingPlaceHolder(false);
+        m_rCC.Invalidate();
     }
 }
 
@@ -694,8 +695,9 @@ void SwVbaContentControl::SetCheckedSymbol(sal_Int32 
Character, const uno::Any&
 
     std::shared_ptr<SwContentControl> pCC = 
m_rCC.GetContentControl().GetContentControl();
     pCC->SetCheckedState(OUString(static_cast<sal_Unicode>(Character)));
-    //if (getChecked())
-    //    pCC->Invalidate();
+
+    if (pCC->GetCheckbox() && pCC->GetChecked())
+        m_rCC.Invalidate();
 }
 
 void SwVbaContentControl::SetUnCheckedSymbol(sal_Int32 Character, const 
uno::Any& Font)
@@ -706,8 +708,9 @@ void SwVbaContentControl::SetUnCheckedSymbol(sal_Int32 
Character, const uno::Any
 
     std::shared_ptr<SwContentControl> pCC = 
m_rCC.GetContentControl().GetContentControl();
     pCC->SetUncheckedState(OUString(static_cast<sal_Unicode>(Character)));
-    //if (!getChecked())
-    //    pCC->Invalidate();
+
+    if (pCC->GetCheckbox() && !pCC->GetChecked())
+        m_rCC.Invalidate();
 }
 
 void SwVbaContentControl::SetPlaceholderText(const uno::Any& BuildingBlock, 
const uno::Any& Range,
@@ -732,13 +735,7 @@ void SwVbaContentControl::SetPlaceholderText(const 
uno::Any& BuildingBlock, cons
         // Remove placeholder text.
         pCC->SetPlaceholderDocPart("");
     }
-    //if (getShowingPlaceholderText())
-    //{
-    //    if (!pCC->GetCheckbox())
-    //      pCC->Invalidate();
-    //    // Ensure that invalidation doesn't turn off showing placeholder as 
true
-    //    pCC->SetShowingPlaceHolder(true);
-    //}
+    m_rCC.Invalidate();
 }
 
 void SwVbaContentControl::Ungroup() { SAL_INFO("sw.vba", 
"SwVbaContentControl::UnGroup stub"); }
diff --git a/sw/source/ui/vba/vbacontentcontrollistentry.cxx 
b/sw/source/ui/vba/vbacontentcontrollistentry.cxx
index 1f758c4ba30a..61d2a1faf6a8 100644
--- a/sw/source/ui/vba/vbacontentcontrollistentry.cxx
+++ b/sw/source/ui/vba/vbacontentcontrollistentry.cxx
@@ -62,9 +62,20 @@ void SwVbaContentControlListEntry::setText(const OUString& 
rSet)
         if (vListItems[i].ToString() == rSet)
             return;
     }
+
+    bool bNeedsInvalidation = false;
+    if (!pCC->GetShowingPlaceHolder())
+    {
+        // TODO: implement bCheckDocModel
+        std::optional<size_t> 
oSel(pCC->GetSelectedListItem(/*bCheckDocModel=true*/));
+        bNeedsInvalidation = oSel && *oSel == m_nZIndex;
+    }
+
     vListItems[m_nZIndex].m_aDisplayText = rSet;
     pCC->SetListItems(vListItems);
-    //pCC->Invalidate();
+
+    if (bNeedsInvalidation)
+        m_rCC.Invalidate();
 }
 
 OUString SwVbaContentControlListEntry::getValue()
@@ -143,7 +154,8 @@ void SwVbaContentControlListEntry::Select()
     std::shared_ptr<SwContentControl> pCC = 
m_rCC.GetContentControl().GetContentControl();
     assert(m_nZIndex < pCC->GetListItems().size());
     pCC->SetSelectedListItem(m_nZIndex);
-    //pCC->Invalidate();
+    pCC->SetShowingPlaceHolder(false);
+    m_rCC.Invalidate();
 }
 
 // XHelperInterface
diff --git a/sw/source/uibase/inc/wrtsh.hxx b/sw/source/uibase/inc/wrtsh.hxx
index 664af50018d7..bd46da908876 100644
--- a/sw/source/uibase/inc/wrtsh.hxx
+++ b/sw/source/uibase/inc/wrtsh.hxx
@@ -428,7 +428,12 @@ typedef bool (SwWrtShell::*FNSimpleMove)();
 
     bool GotoField( const SwFormatField& rField );
 
-    bool GotoContentControl(const SwFormatContentControl& rContentControl);
+    /** @param bOnlyRefresh:
+     *         false: run default actions (e.g. toggle checkbox, remove 
placeholder content)
+     *         true: do not alter the content control, just refresh the doc 
model
+     */
+    bool GotoContentControl(const SwFormatContentControl& rContentControl,
+                            bool bOnlyRefresh = false);
 
     // jump to the next / previous hyperlink - inside text and also
     // on graphics
diff --git a/sw/source/uibase/wrtsh/wrtsh3.cxx 
b/sw/source/uibase/wrtsh/wrtsh3.cxx
index 58204886933e..aa170d1374a4 100644
--- a/sw/source/uibase/wrtsh/wrtsh3.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh3.cxx
@@ -93,7 +93,8 @@ bool SwWrtShell::GotoField( const SwFormatField& rField )
     return bRet;
 }
 
-bool SwWrtShell::GotoContentControl(const SwFormatContentControl& 
rContentControl)
+bool SwWrtShell::GotoContentControl(const SwFormatContentControl& 
rContentControl,
+                                    bool bOnlyRefresh)
 {
     std::shared_ptr<SwContentControl> pContentControl = 
rContentControl.GetContentControl();
     if (IsFrameSelected() && pContentControl && pContentControl->GetPicture())
@@ -124,23 +125,24 @@ bool SwWrtShell::GotoContentControl(const 
SwFormatContentControl& rContentContro
     (this->*m_fnKillSel)(nullptr, false);
 
     bool bRet = SwCursorShell::GotoFormatContentControl(rContentControl);
+    // Assume that once the placeholder is selected, the content is no longer 
the placeholder.
+    if (!bOnlyRefresh && pContentControl)
+        pContentControl->SetShowingPlaceHolder(false);
+
 
     if (bRet && pContentControl && pContentControl->GetCheckbox())
     {
         // Checkbox: GotoFormatContentControl() selected the old state.
         LockView(/*bViewLocked=*/true);
-        OUString aOldState;
+        OUString aOldState = GetCursorDescr();
         OUString aNewState;
         if (pContentControl->GetChecked())
-        {
-            aOldState = pContentControl->GetCheckedState();
-            aNewState = pContentControl->GetUncheckedState();
-        }
+            aNewState = bOnlyRefresh ? pContentControl->GetCheckedState()
+                                     : pContentControl->GetUncheckedState();
         else
-        {
-            aOldState = pContentControl->GetUncheckedState();
-            aNewState = pContentControl->GetCheckedState();
-        }
+            aNewState = bOnlyRefresh ? pContentControl->GetUncheckedState()
+                                     : pContentControl->GetCheckedState();
+
         SwRewriter aRewriter;
         aRewriter.AddRule(UndoArg1, aOldState);
         aRewriter.AddRule(UndoArg2, SwResId(STR_YIELDS));
@@ -150,7 +152,8 @@ bool SwWrtShell::GotoContentControl(const 
SwFormatContentControl& rContentContro
         // Toggle the state.
         pContentControl->SetReadWrite(true);
         DelLeft();
-        pContentControl->SetChecked(!pContentControl->GetChecked());
+        if (!bOnlyRefresh)
+            pContentControl->SetChecked(!pContentControl->GetChecked());
         Insert(aNewState);
         pContentControl->SetReadWrite(false);
 

Reply via email to