sw/inc/formatcontentcontrol.hxx                 |    4 ++
 sw/inc/textcontentcontrol.hxx                   |    2 +
 sw/source/core/txtnode/attrcontentcontrol.cxx   |   33 ++++++++++++++++++++++++
 sw/source/ui/vba/vbacontentcontrollistentry.cxx |   16 +++++------
 4 files changed, 46 insertions(+), 9 deletions(-)

New commits:
commit 64ad923652a11dc68a93f41044df9719c15dec86
Author:     Justin Luth <jl...@mail.com>
AuthorDate: Mon Nov 28 14:16:57 2022 -0500
Commit:     Justin Luth <jl...@mail.com>
CommitDate: Thu Dec 1 21:26:49 2022 +0100

    tdf#151548 ContentControls: improve GetSelectedListItem
    
    Before there was only an option to get the temporarily
    selected list item that had not yet been committed to text.
    
    Add a function that checks whether there is a valid
    selected item, regardless of whether it has been
    written out or not.
    
    Change-Id: I1199bdccd2e665089750eefa5c3a445d56935556
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143420
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <jl...@mail.com>

diff --git a/sw/inc/formatcontentcontrol.hxx b/sw/inc/formatcontentcontrol.hxx
index 88d32e83d31a..94399d6818e8 100644
--- a/sw/inc/formatcontentcontrol.hxx
+++ b/sw/inc/formatcontentcontrol.hxx
@@ -306,6 +306,10 @@ public:
 
     const std::optional<size_t>& GetSelectedListItem() const { return 
m_oSelectedListItem; }
 
+    /// Get a copy of selected list item's index,
+    /// potentially even if the selection is already written out to text (i.e. 
validated).
+    std::optional<size_t> GetSelectedListItem(bool bCheckDocModel) const;
+
     void SetSelectedDate(std::optional<double> oSelectedDate) { 
m_oSelectedDate = oSelectedDate; }
 
     const std::optional<double>& GetSelectedDate() const { return 
m_oSelectedDate; }
diff --git a/sw/inc/textcontentcontrol.hxx b/sw/inc/textcontentcontrol.hxx
index 8c8a3b3ee044..a9bc4e4a1054 100644
--- a/sw/inc/textcontentcontrol.hxx
+++ b/sw/inc/textcontentcontrol.hxx
@@ -42,6 +42,8 @@ public:
     void ChgTextNode(SwTextNode* pNode);
 
     SwTextNode* GetTextNode() const;
+    /// Get the current (potentially invalid) string from the doc
+    OUString ToString() const;
     void Invalidate();
 
     void dumpAsXml(xmlTextWriterPtr pWriter) const override;
diff --git a/sw/source/core/txtnode/attrcontentcontrol.cxx 
b/sw/source/core/txtnode/attrcontentcontrol.cxx
index 98cfa13f9611..e3d0c2237b3b 100644
--- a/sw/source/core/txtnode/attrcontentcontrol.cxx
+++ b/sw/source/core/txtnode/attrcontentcontrol.cxx
@@ -232,6 +232,25 @@ void SwContentControl::SwClientNotify(const SwModify&, 
const SfxHint& rHint)
     }
 }
 
+std::optional<size_t> SwContentControl::GetSelectedListItem(bool 
bCheckDocModel) const
+{
+    if (!bCheckDocModel || m_oSelectedListItem)
+        return m_oSelectedListItem;
+
+    const size_t nLen = GetListItems().size();
+    if (GetShowingPlaceHolder() || !nLen || !GetTextAttr())
+        return std::nullopt;
+
+    const OUString& rText = GetTextAttr()->ToString();
+    for (size_t i = 0; i < nLen; ++i)
+    {
+        if (GetTextAttr()[i].ToString() == rText)
+            return i;
+    }
+    assert(!GetDropDown() && "DropDowns must always have an associated list 
item");
+    return std::nullopt;
+}
+
 bool SwContentControl::AddListItem(size_t nZIndex, const OUString& 
rDisplayText,
                                    const OUString& rValue)
 {
@@ -662,6 +681,20 @@ SwTextNode* SwTextContentControl::GetTextNode() const
     return rFormatContentControl.GetTextNode();
 }
 
+OUString SwTextContentControl::ToString() const
+{
+    if (!GetTextNode())
+        return OUString();
+
+    // Don't select the text attribute itself at the start.
+    sal_Int32 nStart = GetStart() + 1;
+    // Don't select the CH_TXTATR_BREAKWORD itself at the end.
+    sal_Int32 nEnd = *End() - 1;
+
+    SwPaM aPaM(*GetTextNode(), nStart, *GetTextNode(), nEnd);
+    return aPaM.GetText();
+}
+
 void SwTextContentControl::Invalidate()
 {
     SwDocShell* pDocShell = GetTextNode() ? 
GetTextNode()->GetDoc().GetDocShell() : nullptr;
diff --git a/sw/source/ui/vba/vbacontentcontrollistentry.cxx 
b/sw/source/ui/vba/vbacontentcontrollistentry.cxx
index 61d2a1faf6a8..80603df21309 100644
--- a/sw/source/ui/vba/vbacontentcontrollistentry.cxx
+++ b/sw/source/ui/vba/vbacontentcontrollistentry.cxx
@@ -63,19 +63,17 @@ void SwVbaContentControlListEntry::setText(const OUString& 
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;
-    }
+    const std::optional<size_t> 
oSel(pCC->GetSelectedListItem(/*bCheckDocModel=*/true));
+    const bool bNeedsInvalidation = pCC->GetDropDown() && oSel && *oSel == 
m_nZIndex;
 
     vListItems[m_nZIndex].m_aDisplayText = rSet;
     pCC->SetListItems(vListItems);
 
     if (bNeedsInvalidation)
+    {
+        pCC->SetSelectedListItem(m_nZIndex);
         m_rCC.Invalidate();
+    }
 }
 
 OUString SwVbaContentControlListEntry::getValue()
@@ -114,7 +112,7 @@ void SwVbaContentControlListEntry::MoveDown()
     if (m_nZIndex >= pCC->GetListItems().size() - 1)
         return;
 
-    const std::optional<size_t>& oSelected = pCC->GetSelectedListItem();
+    const std::optional<size_t> oSelected = 
pCC->GetSelectedListItem(/*bCheckDocModel=*/false);
     if (oSelected)
     {
         if (*oSelected == m_nZIndex)
@@ -135,7 +133,7 @@ void SwVbaContentControlListEntry::MoveUp()
     if (!m_nZIndex || m_nZIndex >= pCC->GetListItems().size())
         return;
 
-    const std::optional<size_t>& oSelected = pCC->GetSelectedListItem();
+    const std::optional<size_t> oSelected = 
pCC->GetSelectedListItem(/*bCheckDocModel=*/false);
     if (oSelected)
     {
         if (*oSelected == m_nZIndex)

Reply via email to