LibreOffice Module sw (master) 1
vbacontentcontrols.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
11#include <sal/log.hxx>
12
13#include <doc.hxx>
14#include <docsh.hxx>
16
17#include "vbacontentcontrol.hxx"
19#include "wordvbahelper.hxx"
20
21using namespace ::ooo::vba;
22using namespace ::com::sun::star;
23
24// Helper function to access the content controls
25// @param rIndex
26// [in] negative indexes indicate the need to search by name, otherwise get by index,
27// using SAL_MAX_INT32 to indicate the need to just get the total count.
28// [out] rIndex indicates the found index, or the total number of content controls
29static std::shared_ptr<SwContentControl>
30lcl_getContentControl(std::u16string_view sName, std::u16string_view sTag,
31 std::u16string_view sTitle, sal_Int32& rIndex,
32 const uno::Reference<text::XTextDocument>& xTextDocument,
33 uno::Sequence<OUString>* pElementNames = nullptr)
34{
35 SwDoc* pDoc = word::getDocShell(xTextDocument)->GetDoc();
36 if (!pDoc)
37 return nullptr;
38
39 assert(sTag.empty() || sTitle.empty()); // only one grouping at a time is allowed
40
41 std::shared_ptr<SwContentControl> pControl;
42 std::vector<OUString> vElementNames;
44 const size_t nLen = rManager.GetCount();
45 if (!pElementNames && rIndex > 0 && sName.empty() && sTag.empty() && sTitle.empty())
46 {
47 size_t i = static_cast<size_t>(rIndex);
48 // This is the normal get-by-index/getCount mode - no need for fancy filtering.
49 if (i < nLen)
50 pControl = rManager.Get(i)->GetContentControl().GetContentControl();
51 else
52 rIndex = nLen;
53 }
54 else
55 {
56 // loop through everything collecting names, filtering by Tag/Title
57 sal_Int32 nCounter = 0;
58 for (size_t i = 0; i < nLen; ++i)
59 {
60 pControl = rManager.Get(i)->GetContentControl().GetContentControl();
61 if (!sTag.empty() && sTag != pControl->GetTag())
62 {
63 pControl = nullptr;
64 continue;
65 }
66 if (!sTitle.empty() && sTitle != pControl->GetAlias())
67 {
68 pControl = nullptr;
69 continue;
70 }
71
72 // When treated as a name, consider the integer ID to be unsigned
73 const OUString sID = OUString::number(static_cast<sal_uInt32>(pControl->GetId()));
74 if (!sName.empty() && sName != sID)
75 {
76 pControl = nullptr;
77 continue;
78 }
79
80 if (pElementNames)
81 vElementNames.push_back(sID);
82
83 if (rIndex == nCounter || !sName.empty())
84 break;
85
86 pControl = nullptr;
87 ++nCounter;
88 }
89 rIndex = nCounter;
90 }
91 if (pElementNames)
92 *pElementNames = comphelper::containerToSequence(vElementNames);
93 return pControl;
94}
95
96namespace
97{
98class ContentControlsEnumWrapper : public EnumerationHelper_BASE
99{
100 uno::Reference<container::XIndexAccess> mxIndexAccess;
101 sal_Int32 mnIndex;
102
103public:
104 explicit ContentControlsEnumWrapper(uno::Reference<container::XIndexAccess> xIndexAccess)
105 : mxIndexAccess(std::move(xIndexAccess))
106 , mnIndex(0)
107 {
108 }
109
110 sal_Bool SAL_CALL hasMoreElements() override { return (mnIndex < mxIndexAccess->getCount()); }
111
112 uno::Any SAL_CALL nextElement() override
113 {
114 if (mnIndex < mxIndexAccess->getCount())
115 {
116 return mxIndexAccess->getByIndex(mnIndex++);
117 }
118 throw container::NoSuchElementException();
119 }
120};
121
122class ContentControlCollectionHelper
123 : public ::cppu::WeakImplHelper<container::XNameAccess, container::XIndexAccess,
124 container::XEnumerationAccess>
125{
126private:
127 uno::Reference<XHelperInterface> mxParent;
128 uno::Reference<uno::XComponentContext> mxContext;
129 uno::Reference<text::XTextDocument> mxTextDocument;
130 const OUString m_sTag;
131 const OUString m_sTitle;
132 std::shared_ptr<SwContentControl> m_pCache;
133
134public:
136 ContentControlCollectionHelper(uno::Reference<ov::XHelperInterface> xParent,
137 uno::Reference<uno::XComponentContext> xContext,
138 uno::Reference<text::XTextDocument> xTextDocument,
139 const OUString& rTag, const OUString& rTitle)
140
141 : mxParent(std::move(xParent))
142 , mxContext(std::move(xContext))
143 , mxTextDocument(std::move(xTextDocument))
144 , m_sTag(rTag)
145 , m_sTitle(rTitle)
146 {
147 }
148
149 // XIndexAccess
150 sal_Int32 SAL_CALL getCount() override
151 {
152 sal_Int32 nCount = SAL_MAX_INT32;
153 lcl_getContentControl(u"", m_sTag, m_sTitle, nCount, mxTextDocument);
154 return nCount == SAL_MAX_INT32 || nCount < 0 ? 0 : nCount;
155 }
156
157 uno::Any SAL_CALL getByIndex(sal_Int32 Index) override
158 {
159 m_pCache = lcl_getContentControl(u"", m_sTag, m_sTitle, Index, mxTextDocument);
160 if (!m_pCache)
161 throw lang::IndexOutOfBoundsException();
162
163 return uno::Any(uno::Reference<word::XContentControl>(
164 new SwVbaContentControl(mxParent, mxContext, mxTextDocument, m_pCache)));
165 }
166
167 // XNameAccess
168 uno::Sequence<OUString> SAL_CALL getElementNames() override
169 {
170 sal_Int32 nCount = SAL_MAX_INT32;
171 uno::Sequence<OUString> aSeq;
172 lcl_getContentControl(u"", m_sTag, m_sTitle, nCount, mxTextDocument, &aSeq);
173 return aSeq;
174 }
175
176 uno::Any SAL_CALL getByName(const OUString& aName) override
177 {
178 if (!hasByName(aName))
179 throw container::NoSuchElementException();
180
181 return uno::Any(uno::Reference<word::XContentControl>(
182 new SwVbaContentControl(mxParent, mxContext, mxTextDocument, m_pCache)));
183 }
184
185 sal_Bool SAL_CALL hasByName(const OUString& aName) override
186 {
187 sal_Int32 nCount = -1;
188 m_pCache = lcl_getContentControl(aName, m_sTag, m_sTitle, nCount, mxTextDocument);
189 return m_pCache != nullptr;
190 }
191
192 // XElementAccess
193 uno::Type SAL_CALL getElementType() override
194 {
196 }
197
198 sal_Bool SAL_CALL hasElements() override { return getCount() != 0; }
199
200 // XEnumerationAccess
201 uno::Reference<container::XEnumeration> SAL_CALL createEnumeration() override
202 {
203 return new ContentControlsEnumWrapper(this);
204 }
205};
206}
207
218SwVbaContentControls::SwVbaContentControls(const uno::Reference<XHelperInterface>& xParent,
219 const uno::Reference<uno::XComponentContext>& xContext,
220 const uno::Reference<text::XTextDocument>& xTextDocument,
221 const OUString& rTag, const OUString& rTitle)
223 xParent, xContext,
224 uno::Reference<container::XIndexAccess>(
225 new ContentControlCollectionHelper(xParent, xContext, xTextDocument, rTag, rTitle)))
226{
227}
228
229// uno::Reference<ooo::vba::word::XContentControl> SwVbaContentControls::Add(const uno::Any& Range,
230// sal_Int32 Type)
231// {
232// sw::mark::IFieldmark* pFieldmark = nullptr;
233// switch (Type)
234// {
235// case ooo::vba::word::WdFieldType::wdFieldFormCheckBox:
236// break;
237// case ooo::vba::word::WdFieldType::wdFieldFormDropDown:
238// break;
239// case ooo::vba::word::WdFieldType::wdFieldFormTextInput:
240// default:;
241// }
242//
243// return uno::Reference<ooo::vba::word::XContentControl>(
244// new SwVbaContentControl(mxParent, mxContext, m_xTextDocument, pFieldmark));
245// }
246
247// XEnumerationAccess
249{
251}
252
253uno::Reference<container::XEnumeration> SwVbaContentControls::createEnumeration()
254{
255 return new ContentControlsEnumWrapper(m_xIndexAccess);
256}
257
259
260OUString SwVbaContentControls::getServiceImplName() { return "SwVbaContentControls"; }
261
263{
264 static uno::Sequence<OUString> const sNames{ "ooo.vba.word.ContentControls" };
265 return sNames;
266}
267
268/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
struct _ADOIndex Index
unotools::WeakReference< AnimationNode > mxParent
css::uno::Reference< css::container::XIndexAccess > m_xIndexAccess
Knows all the text content controls in the document.
SwTextContentControl * Get(size_t nIndex)
SwDoc * GetDoc()
returns Doc. But be careful!
Definition: docsh.hxx:204
Definition: doc.hxx:197
::SwContentControlManager & GetContentControlManager()
Definition: doc.cxx:142
const std::shared_ptr< SwContentControl > & GetContentControl() const
const SwFormatContentControl & GetContentControl() const
Definition: txatbase.hxx:220
css::uno::Any createCollectionObject(const css::uno::Any &aSource) override
css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration() override
css::uno::Sequence< OUString > getServiceNames() override
OUString getServiceImplName() override
css::uno::Type SAL_CALL getElementType() override
SwVbaContentControls(const css::uno::Reference< ov::XHelperInterface > &xParent, const css::uno::Reference< css::uno::XComponentContext > &xContext, const css::uno::Reference< css::text::XTextDocument > &xTextDocument, const OUString &rTag, const OUString &rTitle)
Content Controls can be accessed and filtered in many different ways.
css::uno::Type const & get()
int nCount
OUString m_sTitle
uno::Reference< uno::XComponentContext > mxContext
FilterCache * m_pCache
OUString sName
Sequence< sal_Int8 > aSeq
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Reference
int i
SwDocShell * getDocShell(const uno::Reference< frame::XModel > &xModel)
sal_uInt32 mnIndex
#define SAL_MAX_INT32
unsigned char sal_Bool
::cppu::WeakImplHelper< css::container::XEnumeration > EnumerationHelper_BASE
static std::shared_ptr< SwContentControl > lcl_getContentControl(std::u16string_view sName, std::u16string_view sTag, std::u16string_view sTitle, sal_Int32 &rIndex, const uno::Reference< text::XTextDocument > &xTextDocument, uno::Sequence< OUString > *pElementNames=nullptr)