LibreOffice Module svx (master)  1
unomtabl.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  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <memory>
23 #include <set>
24 #include <com/sun/star/lang/XServiceInfo.hpp>
25 #include <com/sun/star/container/XNameContainer.hpp>
26 #include <com/sun/star/drawing/PointSequence.hpp>
27 #include <com/sun/star/util/XCancellable.hpp>
28 
29 #include <comphelper/sequence.hxx>
30 #include <cppuhelper/implbase.hxx>
32 #include <svl/itempool.hxx>
33 #include <svl/itemset.hxx>
34 #include <svl/lstner.hxx>
35 #include <svx/xlnedit.hxx>
36 #include <svx/xlnstit.hxx>
37 #include <svx/svdmodel.hxx>
38 #include <svx/xdef.hxx>
39 
40 #include <vector>
41 #include <vcl/svapp.hxx>
42 
43 
44 #include <svx/unofill.hxx>
45 
46 #include <svx/unoapi.hxx>
47 
48 using namespace ::com::sun::star;
49 using namespace ::cppu;
50 
51 typedef std::vector<std::unique_ptr<SfxItemSet>> ItemPoolVector;
52 
53 namespace {
54 
55 class SvxUnoMarkerTable
56  : public WeakImplHelper<
57  util::XCancellable,
58  container::XNameContainer,
59  lang::XServiceInfo>
60  , public SfxListener
61 {
62 private:
63  SdrModel* mpModel;
64  SfxItemPool* mpModelPool;
65 
66  ItemPoolVector maItemSetVector;
67 
68 public:
69  explicit SvxUnoMarkerTable( SdrModel* pModel ) noexcept;
70  virtual ~SvxUnoMarkerTable() noexcept override;
71 
72  void dispose();
73 
74  // SfxListener
75  virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) noexcept override;
76 
77  void ImplInsertByName( const OUString& aName, const uno::Any& aElement );
78 
79  // XServiceInfo
80  virtual OUString SAL_CALL getImplementationName( ) override;
81  virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
82  virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
83 
84  // XCancellable
85  virtual void SAL_CALL cancel() override;
86 
87  // XNameContainer
88  virtual void SAL_CALL insertByName( const OUString& aName, const uno::Any& aElement ) override;
89  virtual void SAL_CALL removeByName( const OUString& Name ) override;
90 
91  // XNameReplace
92  virtual void SAL_CALL replaceByName( const OUString& aName, const uno::Any& aElement ) override;
93 
94  // XNameAccess
95  virtual uno::Any SAL_CALL getByName( const OUString& aName ) override;
96  virtual uno::Sequence< OUString > SAL_CALL getElementNames( ) override;
97  virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override;
98 
99  // XElementAccess
100  virtual uno::Type SAL_CALL getElementType( ) override;
101  virtual sal_Bool SAL_CALL hasElements( ) override;
102 };
103 
104 }
105 
106 SvxUnoMarkerTable::SvxUnoMarkerTable( SdrModel* pModel ) noexcept
107 : mpModel( pModel ),
108  mpModelPool( pModel ? &pModel->GetItemPool() : nullptr )
109 {
110  if( pModel )
111  StartListening( *pModel );
112 }
113 
114 SvxUnoMarkerTable::~SvxUnoMarkerTable() noexcept
115 {
116  SolarMutexGuard aGuard;
117 
118  if( mpModel )
119  EndListening( *mpModel );
120  dispose();
121 }
122 
123 void SvxUnoMarkerTable::dispose()
124 {
125  maItemSetVector.clear();
126 }
127 
128 // SfxListener
129 void SvxUnoMarkerTable::Notify( SfxBroadcaster&, const SfxHint& rHint ) noexcept
130 {
131  if (rHint.GetId() == SfxHintId::ThisIsAnSdrHint)
132  {
133  const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint);
134  if( SdrHintKind::ModelCleared == pSdrHint->GetKind() )
135  dispose();
136  }
137 }
138 
139 sal_Bool SAL_CALL SvxUnoMarkerTable::supportsService( const OUString& ServiceName )
140 {
141  return cppu::supportsService(this, ServiceName);
142 }
143 
144 OUString SAL_CALL SvxUnoMarkerTable::getImplementationName()
145 {
146  return "SvxUnoMarkerTable";
147 }
148 
149 uno::Sequence< OUString > SAL_CALL SvxUnoMarkerTable::getSupportedServiceNames( )
150 {
151  uno::Sequence<OUString> aSNS { "com.sun.star.drawing.MarkerTable" };
152  return aSNS;
153 }
154 
155 void SvxUnoMarkerTable::ImplInsertByName( const OUString& aName, const uno::Any& aElement )
156 {
157  maItemSetVector.push_back(
158  std::make_unique<SfxItemSet>( *mpModelPool, svl::Items<XATTR_LINESTART, XATTR_LINEEND> ));
159  auto pInSet = maItemSetVector.back().get();
160 
161  XLineEndItem aEndMarker(XATTR_LINEEND);
162  aEndMarker.SetName( aName );
163  aEndMarker.PutValue( aElement, 0 );
164 
165  pInSet->Put( aEndMarker );
166 
167  XLineStartItem aStartMarker(XATTR_LINESTART);
168  aStartMarker.SetName( aName );
169  aStartMarker.PutValue( aElement, 0 );
170 
171  pInSet->Put( aStartMarker );
172 }
173 
174 // XNameContainer
175 void SAL_CALL SvxUnoMarkerTable::insertByName( const OUString& aApiName, const uno::Any& aElement )
176 {
177  SolarMutexGuard aGuard;
178 
179  if( hasByName( aApiName ) )
180  throw container::ElementExistException();
181 
182  OUString aName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aApiName);
183 
184  ImplInsertByName( aName, aElement );
185 }
186 
187 void SAL_CALL SvxUnoMarkerTable::cancel()
188 {
189  SolarMutexGuard aGuard;
190  // drop all items that are owned by this service and not the document
191  // (i.e. they are unused)
192  dispose();
193 }
194 
195 void SAL_CALL SvxUnoMarkerTable::removeByName( const OUString& aApiName )
196 {
197  SolarMutexGuard aGuard;
198 
199  OUString aName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aApiName);
200 
201  auto aIter = std::find_if(maItemSetVector.begin(), maItemSetVector.end(),
202  [&aName](const std::unique_ptr<SfxItemSet>& rpItem) {
203  const NameOrIndex *pItem = &(rpItem->Get( XATTR_LINEEND ) );
204  return pItem->GetName() == aName;
205  });
206  if (aIter != maItemSetVector.end())
207  {
208  maItemSetVector.erase( aIter );
209  return;
210  }
211 
212  if( !hasByName( aName ) )
213  throw container::NoSuchElementException();
214 }
215 
216 // XNameReplace
217 void SAL_CALL SvxUnoMarkerTable::replaceByName( const OUString& aApiName, const uno::Any& aElement )
218 {
219  SolarMutexGuard aGuard;
220 
221  const OUString aName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aApiName);
222 
223  auto aIter = std::find_if(maItemSetVector.begin(), maItemSetVector.end(),
224  [&aName](const std::unique_ptr<SfxItemSet>& rpItem) {
225  const NameOrIndex *pItem = &(rpItem->Get( XATTR_LINEEND ) );
226  return pItem->GetName() == aName;
227  });
228  if (aIter != maItemSetVector.end())
229  {
230  XLineEndItem aEndMarker(XATTR_LINEEND);
231  aEndMarker.SetName( aName );
232  if( !aEndMarker.PutValue( aElement, 0 ) )
233  throw lang::IllegalArgumentException();
234 
235  (*aIter)->Put( aEndMarker );
236 
237  XLineStartItem aStartMarker(XATTR_LINESTART);
238  aStartMarker.SetName( aName );
239  aStartMarker.PutValue( aElement, 0 );
240 
241  (*aIter)->Put( aStartMarker );
242  return;
243  }
244 
245  // if it is not in our own sets, modify the pool!
246  bool bFound = false;
247 
248  if (mpModelPool)
249  for (const SfxPoolItem* p : mpModelPool->GetItemSurrogates(XATTR_LINESTART))
250  {
251  NameOrIndex *pItem = const_cast<NameOrIndex*>(static_cast<const NameOrIndex*>(p));
252  if( pItem && pItem->GetName() == aName )
253  {
254  pItem->PutValue( aElement, 0 );
255  bFound = true;
256  break;
257  }
258  }
259 
260  if (mpModelPool)
261  for (const SfxPoolItem* p : mpModelPool->GetItemSurrogates(XATTR_LINEEND))
262  {
263  NameOrIndex *pItem = const_cast<NameOrIndex*>(static_cast<const NameOrIndex*>(p));
264  if( pItem && pItem->GetName() == aName )
265  {
266  pItem->PutValue( aElement, 0 );
267  bFound = true;
268  break;
269  }
270  }
271 
272  if( !bFound )
273  throw container::NoSuchElementException();
274 
275  ImplInsertByName( aName, aElement );
276 }
277 
278 static bool getByNameFromPool( std::u16string_view rSearchName, SfxItemPool const * pPool, sal_uInt16 nWhich, uno::Any& rAny )
279 {
280  if (pPool)
281  for (const SfxPoolItem* p : pPool->GetItemSurrogates(nWhich))
282  {
283  const NameOrIndex *pItem = static_cast<const NameOrIndex*>(p);
284 
285  if( pItem && pItem->GetName() == rSearchName )
286  {
287  pItem->QueryValue( rAny );
288  return true;
289  }
290  }
291 
292  return false;
293 }
294 
295 // XNameAccess
296 uno::Any SAL_CALL SvxUnoMarkerTable::getByName( const OUString& aApiName )
297 {
298  SolarMutexGuard aGuard;
299 
300  OUString aName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aApiName);
301 
302  uno::Any aAny;
303 
304  if (mpModelPool && !aName.isEmpty())
305  {
306  do
307  {
308  if (getByNameFromPool(aName, mpModelPool, XATTR_LINESTART, aAny))
309  break;
310 
311  if (getByNameFromPool(aName, mpModelPool, XATTR_LINEEND, aAny))
312  break;
313 
314  throw container::NoSuchElementException();
315  }
316  while(false);
317  }
318 
319  return aAny;
320 }
321 
322 static void createNamesForPool( SfxItemPool const * pPool, sal_uInt16 nWhich, std::set< OUString >& rNameSet )
323 {
324  for (const SfxPoolItem* p : pPool->GetItemSurrogates(nWhich))
325  {
326  const NameOrIndex* pItem = static_cast<const NameOrIndex*>(p);
327 
328  if( pItem == nullptr || pItem->GetName().isEmpty() )
329  continue;
330 
331  OUString aName = SvxUnogetApiNameForItem(XATTR_LINEEND, pItem->GetName());
332  rNameSet.insert( aName );
333  }
334 }
335 
336 uno::Sequence< OUString > SAL_CALL SvxUnoMarkerTable::getElementNames()
337 {
338  SolarMutexGuard aGuard;
339 
340  std::set< OUString > aNameSet;
341 
342  // search model pool for line starts
343  createNamesForPool( mpModelPool, XATTR_LINESTART, aNameSet );
344 
345  // search model pool for line ends
346  createNamesForPool( mpModelPool, XATTR_LINEEND, aNameSet );
347 
348  return comphelper::containerToSequence(aNameSet);
349 }
350 
351 sal_Bool SAL_CALL SvxUnoMarkerTable::hasByName( const OUString& aName )
352 {
353  SolarMutexGuard aGuard;
354 
355  if( aName.isEmpty() )
356  return false;
357 
358  OUString aSearchName;
359 
360  const NameOrIndex *pItem;
361 
362  aSearchName = SvxUnogetInternalNameForItem(XATTR_LINESTART, aName);
363  if (mpModelPool)
364  for (const SfxPoolItem* p : mpModelPool->GetItemSurrogates(XATTR_LINESTART))
365  {
366  pItem = static_cast<const NameOrIndex*>(p);
367  if( pItem && pItem->GetName() == aSearchName )
368  return true;
369  }
370 
371  aSearchName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aName);
372  if (mpModelPool)
373  for (const SfxPoolItem* p : mpModelPool->GetItemSurrogates(XATTR_LINEEND))
374  {
375  pItem = static_cast<const NameOrIndex*>(p);
376  if( pItem && pItem->GetName() == aSearchName )
377  return true;
378  }
379 
380  return false;
381 }
382 
383 // XElementAccess
384 uno::Type SAL_CALL SvxUnoMarkerTable::getElementType( )
385 {
387 }
388 
389 sal_Bool SAL_CALL SvxUnoMarkerTable::hasElements( )
390 {
391  SolarMutexGuard aGuard;
392 
393  const NameOrIndex *pItem;
394 
395  if (mpModelPool)
396  for (const SfxPoolItem* p : mpModelPool->GetItemSurrogates(XATTR_LINESTART))
397  {
398  pItem = static_cast<const NameOrIndex*>(p);
399  if( pItem && !pItem->GetName().isEmpty() )
400  return true;
401  }
402 
403  if (mpModelPool)
404  for (const SfxPoolItem* p : mpModelPool->GetItemSurrogates(XATTR_LINEEND))
405  {
406  pItem = static_cast<const NameOrIndex*>(p);
407  if( pItem && !pItem->GetName().isEmpty() )
408  return true;
409  }
410 
411  return false;
412 }
413 
417 uno::Reference< uno::XInterface > SvxUnoMarkerTable_createInstance( SdrModel* pModel )
418 {
419  return *new SvxUnoMarkerTable(pModel);
420 }
421 
422 
423 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static bool getByNameFromPool(std::u16string_view rSearchName, SfxItemPool const *pPool, sal_uInt16 nWhich, uno::Any &rAny)
Definition: unomtabl.cxx:278
virtual bool PutValue(const css::uno::Any &rVal, sal_uInt8 nMemberId) override
constexpr TypedWhichId< XLineEndItem > XATTR_LINEEND(XATTR_LINE_FIRST+5)
SdrHintKind GetKind() const
Definition: svdmodel.hxx:127
constexpr TypedWhichId< XLineStartItem > XATTR_LINESTART(XATTR_LINE_FIRST+4)
uno::Reference< uno::XInterface > SvxUnoMarkerTable_createInstance(SdrModel *pModel)
Create a hatchtable.
Definition: unomtabl.cxx:417
OUString SvxUnogetApiNameForItem(const sal_uInt16 nWhich, const OUString &rInternalName)
if the given name is a predefined name for the current language it is replaced by the corresponding a...
Definition: unoprov.cxx:2006
OUString Name
static void createNamesForPool(SfxItemPool const *pPool, sal_uInt16 nWhich, std::set< OUString > &rNameSet)
Definition: unomtabl.cxx:322
std::vector< std::unique_ptr< SfxItemSet > > ItemPoolVector
Definition: unomtabl.cxx:51
OUString SvxUnogetInternalNameForItem(const sal_uInt16 nWhich, const OUString &rApiName)
if the given name is a predefined api name it is replaced by the predefined name for the current lang...
Definition: unoprov.cxx:2039
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
virtual css::uno::Type SAL_CALL getElementType() override
Definition: unomod.cxx:577
unsigned char sal_Bool
css::uno::Type const & get()
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: unomod.cxx:646
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: unomod.cxx:641
virtual OUString SAL_CALL getImplementationName() override
Definition: unomod.cxx:636
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
OUString aName
Item2Range GetItemSurrogates(sal_uInt16 nWhich) const
void * p
void Notify(SwFlyFrame *pFly, SwPageFrame *pOld, const SwRect &rOld, const SwRect *pOldPrt)
OUString const & GetName() const
Definition: xit.hxx:53
virtual bool QueryValue(css::uno::Any &rVal, sal_uInt8 nMemberId=0) const override
void dispose()
virtual sal_Bool SAL_CALL hasElements() override
Definition: unomod.cxx:582