oovbaapi/UnoApi_oovbaapi.mk                          |    2 
 oovbaapi/ooo/vba/word/XContentControlListEntries.idl |   30 +++
 oovbaapi/ooo/vba/word/XContentControlListEntry.idl   |   43 ++++
 sw/Library_vbaswobj.mk                               |    2 
 sw/inc/formatcontentcontrol.hxx                      |    4 
 sw/qa/core/data/docm/testModernVBA.docm              |binary
 sw/source/core/txtnode/attrcontentcontrol.cxx        |   66 +++++++
 sw/source/ui/vba/vbacontentcontrol.cxx               |   12 -
 sw/source/ui/vba/vbacontentcontrollistentries.cxx    |  176 +++++++++++++++++++
 sw/source/ui/vba/vbacontentcontrollistentries.hxx    |   51 +++++
 sw/source/ui/vba/vbacontentcontrollistentry.cxx      |  156 ++++++++++++++++
 sw/source/ui/vba/vbacontentcontrollistentry.hxx      |   54 +++++
 12 files changed, 590 insertions(+), 6 deletions(-)

New commits:
commit 432e5e6e33c3687cdb67ee0a64d57169a82e641d
Author:     Justin Luth <justin.l...@collabora.com>
AuthorDate: Mon Nov 21 19:57:15 2022 -0500
Commit:     Justin Luth <jl...@mail.com>
CommitDate: Fri Nov 25 18:09:32 2022 +0100

    tdf#151548 vba ContentControls: Add word::XContentControlListEntry
    
    make CppunitTest_sw_macros_test CPPUNIT_TEST_NAME=testVba
    
    This now allows MS Word's modern content control list boxes
    (combobox and dropbox) to be controlled by VBA basic.
    -allows getting and setting the selected list entry
    -allows adding/deleting/renaming/moving list entries
    
      If .DropdownListEntries.Count <> 3 Then GoTo errorhandler:
      .DropdownListEntries.Item(2).Select
      .DropdownListEntries.Item(2).Delete
    
      If .DropdownListEntries.Item(2).Text <> "infinity"
      If .DropdownListEntries.Item(2).Value <> "infinity and beyond"
    
      'With .DropdownListEntries.Add("third", "3rd", 2)
      Dim LE As ContentControlListEntry
      Set LE = .DropdownListEntries.Add("third", "3rd", 2)
      With LE
        If LE.Index <> 2 Then GoTo errorhandler:
        If LE.Value <> "3rd" Then GoTo errorhandler:
        .MoveUp
        .MoveUp
        .MoveUp
        If .Index <> 1 Then GoTo errorhandler:
        .MoveDown
        .MoveDown
        If .Index <> 3 Then GoTo errorhandler:
        End With 'LE
      If .DropdownListEntries.Item(3).Text <> "third" Then GoTo errorhandler:
      End With 'Item 1
    runOnceDropDown:
    
    With ActiveDocument.ContentControls.Item(4)
      If .Type <> wdContentControlComboBox Then GoTo errorhandler:
      .DropdownListEntries.Clear
    End With
    
    Change-Id: Iffebb2bd69abec1cbcfaed05b58f940664852eae
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143082
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <jl...@mail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/oovbaapi/UnoApi_oovbaapi.mk b/oovbaapi/UnoApi_oovbaapi.mk
index 063700762e46..dcd514f7ea3e 100644
--- a/oovbaapi/UnoApi_oovbaapi.mk
+++ b/oovbaapi/UnoApi_oovbaapi.mk
@@ -1060,6 +1060,8 @@ $(eval $(call 
gb_UnoApi_add_idlfiles,oovbaapi,ooo/vba/word,\
        XFont \
        XContentControl \
        XContentControls \
+       XContentControlListEntry \
+       XContentControlListEntries \
        XFormField \
        XFormFields \
        XFrame \
diff --git a/oovbaapi/ooo/vba/word/XContentControlListEntries.idl 
b/oovbaapi/ooo/vba/word/XContentControlListEntries.idl
new file mode 100644
index 000000000000..fddf2318afe0
--- /dev/null
+++ b/oovbaapi/ooo/vba/word/XContentControlListEntries.idl
@@ -0,0 +1,30 @@
+/* -*- 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/.
+ */
+
+module ooo {  module vba {  module word {
+
+interface XContentControlListEntry;
+interface XContentControlListEntries
+{
+    interface ooo::vba::XCollection;
+
+    /// Adds a new list item to a drop-down list or combo box content control
+    /// and returns a ContentControlListEntry object.
+    /// Entries must have a unique display Name,
+    /// Value is optional - uses Name if not specified.
+    /// Index is optional. It inserts at the end if not specified, otherwise 
inserted into list.
+    XContentControlListEntry Add( [in] string Name, [in] /*optional*/ any 
Value, [in] /*optional*/ any Index );
+
+    /// Remove all items from the dropdown list
+    void Clear();
+};
+
+}; }; };
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oovbaapi/ooo/vba/word/XContentControlListEntry.idl 
b/oovbaapi/ooo/vba/word/XContentControlListEntry.idl
new file mode 100644
index 000000000000..15b52a774cc1
--- /dev/null
+++ b/oovbaapi/ooo/vba/word/XContentControlListEntry.idl
@@ -0,0 +1,43 @@
+/* -*- 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/.
+ */
+
+module ooo {  module vba {  module word {
+
+interface XContentControlListEntry
+{
+    interface ooo::vba::XHelperInterface;
+
+    /// Returns or sets the ordinal position of a list item in the collection 
of list items.
+    [attribute] long Index;
+
+    /// Returns or sets a String that represents the display text of the list 
item.
+    [attribute] string Text;
+
+    /// Returns or sets a String that represents the programmatic value of the 
list item.
+    [attribute] string Value;
+
+    /// Deletes the specified item in a combo box or drop-down list content 
control.
+    void Delete();
+
+    /// Moves an item in a drop-down list or combo box content control down 
one item,
+    /// so that it is after the item that originally followed it.
+    void MoveDown();
+
+    /// Moves an item in a drop-down list or combo box content control up one 
item,
+    /// so that it is before the item that originally preceded it.
+    void MoveUp();
+
+    /// Selects the list entry in a drop-down list or combo box content control
+    /// and sets the text of the content control to the value of the item.
+    void Select();
+};
+
+}; }; };
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/Library_vbaswobj.mk b/sw/Library_vbaswobj.mk
index e6b45b4e2f37..efb2e35d9677 100644
--- a/sw/Library_vbaswobj.mk
+++ b/sw/Library_vbaswobj.mk
@@ -74,6 +74,8 @@ $(eval $(call gb_Library_add_exception_objects,vbaswobj,\
     sw/source/ui/vba/vbacolumns \
     sw/source/ui/vba/vbacontentcontrol \
     sw/source/ui/vba/vbacontentcontrols \
+    sw/source/ui/vba/vbacontentcontrollistentry \
+    sw/source/ui/vba/vbacontentcontrollistentries \
     sw/source/ui/vba/vbaformfield \
     sw/source/ui/vba/vbaformfields \
     sw/source/ui/vba/vbaformfieldcheckbox \
diff --git a/sw/inc/formatcontentcontrol.hxx b/sw/inc/formatcontentcontrol.hxx
index 3ac6848e388f..415132409e10 100644
--- a/sw/inc/formatcontentcontrol.hxx
+++ b/sw/inc/formatcontentcontrol.hxx
@@ -245,6 +245,10 @@ public:
         m_aListItems = rListItems;
     }
 
+    bool AddListItem(size_t nZIndex, const OUString& rDisplayText, const 
OUString& rValue);
+    void DeleteListItem(size_t nZIndex);
+    void ClearListItems();
+
     void SetPicture(bool bPicture) { m_bPicture = bPicture; }
 
     bool GetPicture() const { return m_bPicture; }
diff --git a/sw/qa/core/data/docm/testModernVBA.docm 
b/sw/qa/core/data/docm/testModernVBA.docm
index faa85768884b..dd96686659ca 100644
Binary files a/sw/qa/core/data/docm/testModernVBA.docm and 
b/sw/qa/core/data/docm/testModernVBA.docm differ
diff --git a/sw/source/core/txtnode/attrcontentcontrol.cxx 
b/sw/source/core/txtnode/attrcontentcontrol.cxx
index 33ee4faa1e07..118d60258f27 100644
--- a/sw/source/core/txtnode/attrcontentcontrol.cxx
+++ b/sw/source/core/txtnode/attrcontentcontrol.cxx
@@ -231,6 +231,72 @@ void SwContentControl::SwClientNotify(const SwModify&, 
const SfxHint& rHint)
     }
 }
 
+bool SwContentControl::AddListItem(size_t nZIndex, const OUString& 
rDisplayText,
+                                   const OUString& rValue)
+{
+    SwContentControlListItem aListItem;
+    if (rValue.isEmpty())
+    {
+        if (rDisplayText.isEmpty())
+            return false;
+        aListItem.m_aValue = rDisplayText;
+    }
+    else
+    {
+        aListItem.m_aValue = rValue;
+        aListItem.m_aDisplayText = rDisplayText;
+    }
+
+    // Avoid adding duplicates
+    for (auto& rListItem : GetListItems())
+    {
+        if (rListItem == aListItem)
+            return false;
+    }
+
+    const size_t nLen = GetListItems().size();
+    nZIndex = std::min(nZIndex, nLen);
+    const std::optional<size_t> oSelected = GetSelectedListItem();
+    if (oSelected && *oSelected >= nZIndex)
+    {
+        if (*oSelected < nLen)
+            SetSelectedListItem(*oSelected + 1);
+    }
+    std::vector<SwContentControlListItem> vListItems = GetListItems();
+    vListItems.insert(vListItems.begin() + nZIndex, aListItem);
+    SetListItems(vListItems);
+    return true;
+}
+
+void SwContentControl::DeleteListItem(size_t nZIndex)
+{
+    if (nZIndex >= GetListItems().size())
+        return;
+
+    const std::optional<size_t> oSelected = GetSelectedListItem();
+    if (oSelected)
+    {
+        if (*oSelected == nZIndex)
+        {
+            SetSelectedListItem(std::nullopt);
+            //Invalidate();
+        }
+        else if (*oSelected < nZIndex)
+            SetSelectedListItem(*oSelected - 1);
+    }
+
+    std::vector<SwContentControlListItem> vListItems = GetListItems();
+    vListItems.erase(vListItems.begin() + nZIndex);
+    SetListItems(vListItems);
+    return;
+}
+
+void SwContentControl::ClearListItems()
+{
+    SetSelectedListItem(std::nullopt);
+    SetListItems(std::vector<SwContentControlListItem>());
+}
+
 OUString SwContentControl::GetDateString() const
 {
     SwDoc& rDoc = m_pTextNode->GetDoc();
diff --git a/sw/source/ui/vba/vbacontentcontrol.cxx 
b/sw/source/ui/vba/vbacontentcontrol.cxx
index 3d51d8bd4448..62ee4a4f7be6 100644
--- a/sw/source/ui/vba/vbacontentcontrol.cxx
+++ b/sw/source/ui/vba/vbacontentcontrol.cxx
@@ -17,7 +17,7 @@
 #include <ndtxt.hxx>
 
 #include "vbacontentcontrol.hxx"
-//#include "vbacontentcontroldropdownlistentries.hxx"
+#include "vbacontentcontrollistentries.hxx"
 
 using namespace ::ooo::vba;
 using namespace ::com::sun::star;
@@ -463,11 +463,11 @@ sal_Int32 SwVbaContentControl::getDateDisplayLocale()
 uno::Any SwVbaContentControl::getDropdownListEntries()
 {
     std::shared_ptr<SwContentControl> pCC = 
m_rCC.GetContentControl().GetContentControl();
-    //if (!pCC->GetDropDown() && !pCC->GetComboBox())
-    //    return uno::Any();
-    //return uno::Any(uno::Reference<XCollection>(
-    //    new SwVbaContentControlDropDownListEntries(this, mxContext, m_rCC)));
-    return uno::Any();
+    if (!pCC->GetDropDown() && !pCC->GetComboBox())
+        return uno::Any();
+
+    return uno::Any(
+        uno::Reference<XCollection>(new SwVbaContentControlListEntries(this, 
mxContext, m_rCC)));
 }
 
 OUString SwVbaContentControl::getID()
diff --git a/sw/source/ui/vba/vbacontentcontrollistentries.cxx 
b/sw/source/ui/vba/vbacontentcontrollistentries.cxx
new file mode 100644
index 000000000000..a96d6b3ad3dd
--- /dev/null
+++ b/sw/source/ui/vba/vbacontentcontrollistentries.cxx
@@ -0,0 +1,176 @@
+/* -*- 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/.
+ */
+
+#include "vbacontentcontrollistentries.hxx"
+
+using namespace ::ooo::vba;
+using namespace ::com::sun::star;
+
+namespace
+{
+class ContentControlListEntriesEnumWrapper : public EnumerationHelper_BASE
+{
+    uno::Reference<container::XIndexAccess> mxIndexAccess;
+    sal_Int32 nIndex;
+
+public:
+    explicit ContentControlListEntriesEnumWrapper(
+        uno::Reference<container::XIndexAccess> xIndexAccess)
+        : mxIndexAccess(xIndexAccess)
+        , nIndex(0)
+    {
+    }
+
+    virtual sal_Bool SAL_CALL hasMoreElements() override
+    {
+        return (nIndex < mxIndexAccess->getCount());
+    }
+
+    virtual uno::Any SAL_CALL nextElement() override
+    {
+        if (nIndex < mxIndexAccess->getCount())
+        {
+            return mxIndexAccess->getByIndex(nIndex++);
+        }
+        throw container::NoSuchElementException();
+    }
+};
+
+class ContentControlListEntryCollectionHelper
+    : public ::cppu::WeakImplHelper<container::XIndexAccess, 
container::XEnumerationAccess>
+{
+private:
+    uno::Reference<XHelperInterface> mxParent;
+    uno::Reference<uno::XComponentContext> mxContext;
+    SwTextContentControl& m_rCC;
+
+public:
+    /// @throws css::uno::RuntimeException
+    
ContentControlListEntryCollectionHelper(uno::Reference<ov::XHelperInterface> 
xParent,
+                                            
uno::Reference<uno::XComponentContext> xContext,
+                                            SwTextContentControl& rCC)
+        : mxParent(xParent)
+        , mxContext(xContext)
+        , m_rCC(rCC)
+    {
+    }
+
+    sal_Int32 SAL_CALL getCount() override
+    {
+        return 
m_rCC.GetContentControl().GetContentControl()->GetListItems().size();
+    }
+
+    uno::Any SAL_CALL getByIndex(sal_Int32 Index) override
+    {
+        if (Index < 0 || Index >= getCount())
+            throw lang::IndexOutOfBoundsException();
+
+        return uno::Any(uno::Reference<word::XContentControlListEntry>(
+            new SwVbaContentControlListEntry(mxParent, mxContext, m_rCC, 
Index)));
+    }
+
+    uno::Type SAL_CALL getElementType() override
+    {
+        return cppu::UnoType<word::XContentControlListEntry>::get();
+    }
+
+    sal_Bool SAL_CALL hasElements() override { return getCount() != 0; }
+
+    // XEnumerationAccess
+    uno::Reference<container::XEnumeration> SAL_CALL createEnumeration() 
override
+    {
+        return new ContentControlListEntriesEnumWrapper(this);
+    }
+};
+}
+
+/**
+ * DropDownLists and ComboBoxes contain a list of name/value pairs to chose 
from.
+ * Use of DropDownListEntries from any other control is invalid.
+ */
+SwVbaContentControlListEntries::SwVbaContentControlListEntries(
+    const uno::Reference<XHelperInterface>& xParent,
+    const uno::Reference<uno::XComponentContext>& xContext, 
SwTextContentControl& rCC)
+    : SwVbaContentControlListEntries_BASE(
+          xParent, xContext,
+          uno::Reference<container::XIndexAccess>(
+              new ContentControlListEntryCollectionHelper(xParent, xContext, 
rCC)))
+    , m_rCC(rCC)
+{
+}
+
+uno::Reference<word::XContentControlListEntry>
+SwVbaContentControlListEntries::Add(const OUString& rName, const uno::Any& 
rValue,
+                                    const uno::Any& rIndex)
+{
+    // No duplicate Names allowed in VBA
+    std::shared_ptr<SwContentControl> pCC = 
m_rCC.GetContentControl().GetContentControl();
+    for (auto& rListItem : pCC->GetListItems())
+    {
+        if (rListItem.ToString() == rName)
+            return uno::Reference<word::XContentControlListEntry>();
+    }
+
+    sal_Int32 nZIndex = SAL_MAX_INT32;
+    rIndex >>= nZIndex;
+    // rIndex is 1-based, nZIndex is 0-based. If rIndex is not given, then add 
as the last choice.
+    assert(nZIndex > 0);
+    --nZIndex;
+    nZIndex = std::min(static_cast<size_t>(nZIndex), 
pCC->GetListItems().size());
+
+    OUString sValue;
+    rValue >>= sValue;
+    if (pCC->AddListItem(nZIndex, rName, sValue))
+    {
+        return uno::Reference<word::XContentControlListEntry>(
+            new SwVbaContentControlListEntry(mxParent, mxContext, m_rCC, 
nZIndex));
+    }
+
+    return uno::Reference<word::XContentControlListEntry>();
+}
+
+void SwVbaContentControlListEntries::Clear()
+{
+    m_rCC.GetContentControl().GetContentControl()->ClearListItems();
+}
+
+sal_Int32 SwVbaContentControlListEntries::getCount()
+{
+    return 
m_rCC.GetContentControl().GetContentControl()->GetListItems().size();
+}
+
+// XEnumerationAccess
+uno::Type SwVbaContentControlListEntries::getElementType()
+{
+    return cppu::UnoType<word::XContentControlListEntry>::get();
+}
+
+uno::Reference<container::XEnumeration> 
SwVbaContentControlListEntries::createEnumeration()
+{
+    return new ContentControlListEntriesEnumWrapper(m_xIndexAccess);
+}
+
+// SwVbaContentControlListEntries_BASE
+uno::Any SwVbaContentControlListEntries::createCollectionObject(const 
uno::Any& aSource)
+{
+    return aSource;
+}
+
+OUString SwVbaContentControlListEntries::getServiceImplName()
+{
+    return "SwVbaContentControlListEntries";
+}
+
+uno::Sequence<OUString> SwVbaContentControlListEntries::getServiceNames()
+{
+    static uno::Sequence<OUString> const sNames{ 
"ooo.vba.word.ContentControlListEntries" };
+    return sNames;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/vba/vbacontentcontrollistentries.hxx 
b/sw/source/ui/vba/vbacontentcontrollistentries.hxx
new file mode 100644
index 000000000000..65ee6ac814a9
--- /dev/null
+++ b/sw/source/ui/vba/vbacontentcontrollistentries.hxx
@@ -0,0 +1,51 @@
+/* -*- 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/.
+ */
+#pragma once
+
+#include <ooo/vba/word/XContentControlListEntries.hpp>
+#include <ooo/vba/word/XContentControlListEntry.hpp>
+
+#include <vbahelper/vbacollectionimpl.hxx>
+
+#include <textcontentcontrol.hxx>
+
+#include "vbacontentcontrollistentries.hxx"
+#include "vbacontentcontrollistentry.hxx"
+
+typedef CollTestImplHelper<ooo::vba::word::XContentControlListEntries>
+    SwVbaContentControlListEntries_BASE;
+
+class SwVbaContentControlListEntries : public 
SwVbaContentControlListEntries_BASE
+{
+private:
+    SwTextContentControl& m_rCC;
+
+public:
+    /// @throws css::uno::RuntimeException
+    SwVbaContentControlListEntries(const 
css::uno::Reference<ov::XHelperInterface>& xParent,
+                                   const 
css::uno::Reference<css::uno::XComponentContext>& xContext,
+                                   SwTextContentControl& rCC);
+
+    // XContentControlListEntries
+    css::uno::Reference<ooo::vba::word::XContentControlListEntry> SAL_CALL
+    Add(const OUString& rName, const css::uno::Any& rValue, const 
css::uno::Any& rIndex) override;
+    void SAL_CALL Clear() override;
+    sal_Int32 SAL_CALL getCount() override;
+
+    // XEnumerationAccess
+    css::uno::Type SAL_CALL getElementType() override;
+    css::uno::Reference<css::container::XEnumeration> SAL_CALL 
createEnumeration() override;
+
+    // SwVbaContentControlListEntries_BASE
+    css::uno::Any createCollectionObject(const css::uno::Any& aSource) 
override;
+    OUString getServiceImplName() override;
+    css::uno::Sequence<OUString> getServiceNames() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/vba/vbacontentcontrollistentry.cxx 
b/sw/source/ui/vba/vbacontentcontrollistentry.cxx
new file mode 100644
index 000000000000..7be9c758f19d
--- /dev/null
+++ b/sw/source/ui/vba/vbacontentcontrollistentry.cxx
@@ -0,0 +1,156 @@
+/* -*- 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/.
+ */
+
+#include "vbacontentcontrollistentry.hxx"
+
+using namespace ::ooo::vba;
+using namespace ::com::sun::star;
+
+SwVbaContentControlListEntry::SwVbaContentControlListEntry(
+    const uno::Reference<ooo::vba::XHelperInterface>& rParent,
+    const uno::Reference<uno::XComponentContext>& rContext, 
SwTextContentControl& rCC,
+    size_t nZIndex)
+    : SwVbaContentControlListEntry_BASE(rParent, rContext)
+    , m_rCC(rCC)
+    , m_nZIndex(nZIndex)
+{
+}
+
+SwVbaContentControlListEntry::~SwVbaContentControlListEntry() {}
+
+sal_Int32 SwVbaContentControlListEntry::getIndex() { return m_nZIndex + 1; }
+
+void SwVbaContentControlListEntry::setIndex(sal_Int32 nSet)
+{
+    if (nSet < 1 || static_cast<size_t>(nSet) == m_nZIndex + 1)
+        return;
+
+    std::shared_ptr<SwContentControl> pCC = 
m_rCC.GetContentControl().GetContentControl();
+    // Given a one-based index to set to
+    size_t nIndex = std::min(static_cast<size_t>(nSet), 
pCC->GetListItems().size());
+    // change to zero-based index
+    --nIndex;
+    while (nIndex < m_nZIndex)
+        MoveUp();
+    while (m_nZIndex < nIndex)
+        MoveDown();
+}
+
+OUString SwVbaContentControlListEntry::getText()
+{
+    const std::shared_ptr<SwContentControl> pCC = 
m_rCC.GetContentControl().GetContentControl();
+    assert(m_nZIndex < pCC->GetListItems().size());
+    const SwContentControlListItem& rListItem = pCC->GetListItems()[m_nZIndex];
+    return rListItem.ToString();
+}
+
+void SwVbaContentControlListEntry::setText(const OUString& rSet)
+{
+    const std::shared_ptr<SwContentControl> pCC = 
m_rCC.GetContentControl().GetContentControl();
+    std::vector<SwContentControlListItem> vListItems = pCC->GetListItems();
+    assert(m_nZIndex < vListItems.size());
+
+    // prevent duplicates
+    for (size_t i = 0; i < vListItems.size(); ++i)
+    {
+        if (vListItems[i].ToString() == rSet)
+            return;
+    }
+    vListItems[m_nZIndex].m_aDisplayText = rSet;
+    pCC->SetListItems(vListItems);
+    //pCC->Invalidate();
+}
+
+OUString SwVbaContentControlListEntry::getValue()
+{
+    const std::shared_ptr<SwContentControl> pCC = 
m_rCC.GetContentControl().GetContentControl();
+    assert(m_nZIndex < pCC->GetListItems().size());
+    const SwContentControlListItem& rListItem = pCC->GetListItems()[m_nZIndex];
+
+    return rListItem.m_aValue;
+}
+
+void SwVbaContentControlListEntry::setValue(const OUString& rSet)
+{
+    const std::shared_ptr<SwContentControl> pCC = 
m_rCC.GetContentControl().GetContentControl();
+    assert(m_nZIndex < pCC->GetListItems().size());
+    std::vector<SwContentControlListItem> vListItems = pCC->GetListItems();
+    vListItems[m_nZIndex].m_aValue = rSet;
+    pCC->SetListItems(vListItems);
+}
+
+void SwVbaContentControlListEntry::Delete()
+{
+    std::shared_ptr<SwContentControl> pCC = 
m_rCC.GetContentControl().GetContentControl();
+    pCC->DeleteListItem(m_nZIndex);
+}
+
+void SwVbaContentControlListEntry::MoveDown()
+{
+    std::shared_ptr<SwContentControl> pCC = 
m_rCC.GetContentControl().GetContentControl();
+    // if already at last positin, can't move down
+    if (m_nZIndex >= pCC->GetListItems().size() - 1)
+        return;
+
+    const std::optional<size_t>& oSelected = pCC->GetSelectedListItem();
+    if (oSelected)
+    {
+        if (*oSelected == m_nZIndex)
+            pCC->SetSelectedListItem(m_nZIndex + 1);
+        else if (*oSelected == m_nZIndex + 1)
+            pCC->SetSelectedListItem(*oSelected - 1);
+    }
+    std::vector<SwContentControlListItem> vListItems = pCC->GetListItems();
+    std::swap(vListItems[m_nZIndex], vListItems[m_nZIndex + 1]);
+    pCC->SetListItems(vListItems);
+    ++m_nZIndex;
+}
+
+void SwVbaContentControlListEntry::MoveUp()
+{
+    std::shared_ptr<SwContentControl> pCC = 
m_rCC.GetContentControl().GetContentControl();
+    // if already at position 0, can't move up
+    if (!m_nZIndex || m_nZIndex >= pCC->GetListItems().size())
+        return;
+
+    const std::optional<size_t>& oSelected = pCC->GetSelectedListItem();
+    if (oSelected)
+    {
+        if (*oSelected == m_nZIndex)
+            pCC->SetSelectedListItem(m_nZIndex - 1);
+        else if (*oSelected == m_nZIndex - 1)
+            pCC->SetSelectedListItem(*oSelected + 1);
+    }
+    std::vector<SwContentControlListItem> vListItems = pCC->GetListItems();
+    std::swap(vListItems[m_nZIndex], vListItems[m_nZIndex - 1]);
+    pCC->SetListItems(vListItems);
+    --m_nZIndex;
+}
+
+void SwVbaContentControlListEntry::Select()
+{
+    std::shared_ptr<SwContentControl> pCC = 
m_rCC.GetContentControl().GetContentControl();
+    assert(m_nZIndex < pCC->GetListItems().size());
+    pCC->SetSelectedListItem(m_nZIndex);
+    //pCC->Invalidate();
+}
+
+// XHelperInterface
+OUString SwVbaContentControlListEntry::getServiceImplName()
+{
+    return "SwVbaContentControlListEntry";
+}
+
+uno::Sequence<OUString> SwVbaContentControlListEntry::getServiceNames()
+{
+    static uno::Sequence<OUString> const aServiceNames{ 
"ooo.vba.word.ContentControlListEntry" };
+    return aServiceNames;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/ui/vba/vbacontentcontrollistentry.hxx 
b/sw/source/ui/vba/vbacontentcontrollistentry.hxx
new file mode 100644
index 000000000000..e6e3c341afe0
--- /dev/null
+++ b/sw/source/ui/vba/vbacontentcontrollistentry.hxx
@@ -0,0 +1,54 @@
+/* -*- 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/.
+ */
+#pragma once
+
+#include <ooo/vba/word/XContentControlListEntry.hpp>
+
+#include <vbahelper/vbahelperinterface.hxx>
+
+#include <textcontentcontrol.hxx>
+
+typedef 
InheritedHelperInterfaceWeakImpl<ooo::vba::word::XContentControlListEntry>
+    SwVbaContentControlListEntry_BASE;
+
+class SwVbaContentControlListEntry : public SwVbaContentControlListEntry_BASE
+{
+private:
+    SwTextContentControl& m_rCC;
+    // All LO and internal UNO functions are 0-based. Convert to 1-based when 
sending to VBA
+    size_t m_nZIndex;
+
+public:
+    /// @throws css::uno::RuntimeException
+    SwVbaContentControlListEntry(const 
css::uno::Reference<ooo::vba::XHelperInterface>& rParent,
+                                 const 
css::uno::Reference<css::uno::XComponentContext>& rContext,
+                                 SwTextContentControl& rCC, size_t nZIndex);
+    ~SwVbaContentControlListEntry() override;
+
+    // XContentControlListEntry
+    sal_Int32 SAL_CALL getIndex() override;
+    void SAL_CALL setIndex(sal_Int32 nSet) override;
+
+    OUString SAL_CALL getText() override;
+    void SAL_CALL setText(const OUString& sSet) override;
+
+    OUString SAL_CALL getValue() override;
+    void SAL_CALL setValue(const OUString& sSet) override;
+
+    void SAL_CALL Delete() override;
+    void SAL_CALL MoveDown() override;
+    void SAL_CALL MoveUp() override;
+    void SAL_CALL Select() override;
+
+    // XHelperInterface
+    OUString getServiceImplName() override;
+    css::uno::Sequence<OUString> getServiceNames() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to