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 | 161 +++++++++++++++++ sw/source/ui/vba/vbacontentcontrollistentry.hxx | 54 +++++ 12 files changed, 595 insertions(+), 6 deletions(-)
New commits: commit 0632c2df0f0b6524bd5c4bb8e7e62a3996359a2e Author: Justin Luth <[email protected]> AuthorDate: Mon Nov 21 19:57:15 2022 -0500 Commit: Justin Luth <[email protected]> CommitDate: Mon Dec 12 17:34:18 2022 +0000 tdf#151548 vba ContentControls: Add word::XContentControlListEntry make CppunitTest_sw_macros_test CPPUNIT_TEST_NAME=testVba Squashed commit containing various cleanups. 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 <[email protected]> Reviewed-by: Miklos Vajna <[email protected]> Fix typo Change-Id: I2f93357f2291312e91002fe3b104261a6aee8734 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143318 Tested-by: Jenkins Reviewed-by: Julien Nabet <[email protected]> Fix typo Change-Id: Ief6a37b977f464c50888291ec9764c7b05cba297 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143320 Tested-by: Julien Nabet <[email protected]> Reviewed-by: Julien Nabet <[email protected]> tdf#151548 ContentControls: improve ListEntry::setValue The LO implementation pulls the display text from the value in case there is no display text provided. This is the opposite from VBA. So when we set the Value, make sure that we aren't unintentionally changing the display as well. Change-Id: I699bfc1c2e9fbab6574a3c1363fe1dc21c7354e1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143416 Tested-by: Jenkins Reviewed-by: Justin Luth <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143421 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Tor Lillqvist <[email protected]> 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 ec4e8f044672..8ad9dcc604e7 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 9ae6205e87b3..8546e78dabc4 100644 --- a/sw/inc/formatcontentcontrol.hxx +++ b/sw/inc/formatcontentcontrol.hxx @@ -247,6 +247,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 836b9a638c8f..3a7d0155c23e 100644 --- a/sw/source/core/txtnode/attrcontentcontrol.cxx +++ b/sw/source/core/txtnode/attrcontentcontrol.cxx @@ -225,6 +225,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..dcf71afb9337 --- /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 choose 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..1f758c4ba30a --- /dev/null +++ b/sw/source/ui/vba/vbacontentcontrollistentry.cxx @@ -0,0 +1,161 @@ +/* -*- 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(); + + // LO may pull the display text from Value. Ensure changing Value doesn't alter display text. + if (vListItems[m_nZIndex].m_aDisplayText.isEmpty()) + vListItems[m_nZIndex].m_aDisplayText = vListItems[m_nZIndex].ToString(); + + 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 position, 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: */
