Line data Source code
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 :
21 : #include <set>
22 : #include <com/sun/star/lang/XServiceInfo.hpp>
23 : #include <com/sun/star/container/XNameContainer.hpp>
24 : #include <com/sun/star/drawing/PointSequence.hpp>
25 : #include <svl/style.hxx>
26 :
27 : #include <cppuhelper/implbase2.hxx>
28 : #include <cppuhelper/supportsservice.hxx>
29 : #include <svl/itempool.hxx>
30 : #include <svl/itemset.hxx>
31 : #include <svl/lstner.hxx>
32 : #include <svx/xlnedit.hxx>
33 : #include <svx/xlnstit.hxx>
34 : #include <svx/svdmodel.hxx>
35 : #include <svx/xdef.hxx>
36 : #include <svx/xflhtit.hxx>
37 :
38 : #include <vector>
39 : #include <osl/mutex.hxx>
40 : #include <vcl/svapp.hxx>
41 :
42 :
43 : #include "svx/unofill.hxx"
44 :
45 : #include "svx/unoapi.hxx"
46 :
47 : using namespace ::com::sun::star;
48 : using namespace ::cppu;
49 :
50 : typedef std::vector< SfxItemSet* > ItemPoolVector;
51 :
52 : class SvxUnoMarkerTable : public WeakImplHelper2< container::XNameContainer, lang::XServiceInfo >,
53 : public SfxListener
54 : {
55 : private:
56 : SdrModel* mpModel;
57 : SfxItemPool* mpModelPool;
58 :
59 : ItemPoolVector maItemSetVector;
60 :
61 : public:
62 : explicit SvxUnoMarkerTable( SdrModel* pModel ) throw();
63 : virtual ~SvxUnoMarkerTable() throw();
64 :
65 : void dispose();
66 :
67 : // SfxListener
68 : virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) throw () SAL_OVERRIDE;
69 :
70 : void SAL_CALL ImplInsertByName( const OUString& aName, const uno::Any& aElement );
71 :
72 : // XServiceInfo
73 : virtual OUString SAL_CALL getImplementationName( ) throw( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
74 : virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw( uno::RuntimeException, std::exception) SAL_OVERRIDE;
75 : virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw( uno::RuntimeException, std::exception) SAL_OVERRIDE;
76 :
77 : // XNameContainer
78 : virtual void SAL_CALL insertByName( const OUString& aName, const uno::Any& aElement ) throw( lang::IllegalArgumentException, container::ElementExistException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE;
79 : virtual void SAL_CALL removeByName( const OUString& Name ) throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE;
80 :
81 : // XNameReplace
82 : virtual void SAL_CALL replaceByName( const OUString& aName, const uno::Any& aElement ) throw( lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE;
83 :
84 : // XNameAccess
85 : virtual uno::Any SAL_CALL getByName( const OUString& aName ) throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE;
86 : virtual uno::Sequence< OUString > SAL_CALL getElementNames( ) throw( uno::RuntimeException, std::exception) SAL_OVERRIDE;
87 : virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) throw( uno::RuntimeException, std::exception) SAL_OVERRIDE;
88 :
89 : // XElementAccess
90 : virtual uno::Type SAL_CALL getElementType( ) throw( uno::RuntimeException, std::exception) SAL_OVERRIDE;
91 : virtual sal_Bool SAL_CALL hasElements( ) throw( uno::RuntimeException, std::exception) SAL_OVERRIDE;
92 : };
93 :
94 297 : SvxUnoMarkerTable::SvxUnoMarkerTable( SdrModel* pModel ) throw()
95 : : mpModel( pModel ),
96 297 : mpModelPool( pModel ? &pModel->GetItemPool() : nullptr )
97 : {
98 297 : if( pModel )
99 297 : StartListening( *pModel );
100 297 : }
101 :
102 828 : SvxUnoMarkerTable::~SvxUnoMarkerTable() throw()
103 : {
104 276 : if( mpModel )
105 276 : EndListening( *mpModel );
106 276 : dispose();
107 552 : }
108 :
109 553 : void SvxUnoMarkerTable::dispose()
110 : {
111 553 : ItemPoolVector::iterator aIter = maItemSetVector.begin();
112 553 : const ItemPoolVector::iterator aEnd = maItemSetVector.end();
113 :
114 1246 : while( aIter != aEnd )
115 : {
116 140 : delete (*aIter++);
117 : }
118 :
119 553 : maItemSetVector.clear();
120 553 : }
121 :
122 : // SfxListener
123 27363 : void SvxUnoMarkerTable::Notify( SfxBroadcaster&, const SfxHint& rHint ) throw()
124 : {
125 27363 : const SdrHint* pSdrHint = dynamic_cast<const SdrHint*>(&rHint);
126 :
127 27363 : if( pSdrHint && HINT_MODELCLEARED == pSdrHint->GetKind() )
128 233 : dispose();
129 27363 : }
130 :
131 0 : sal_Bool SAL_CALL SvxUnoMarkerTable::supportsService( const OUString& ServiceName ) throw(uno::RuntimeException, std::exception)
132 : {
133 0 : return cppu::supportsService(this, ServiceName);
134 : }
135 :
136 0 : OUString SAL_CALL SvxUnoMarkerTable::getImplementationName() throw( uno::RuntimeException, std::exception )
137 : {
138 0 : return OUString("SvxUnoMarkerTable");
139 : }
140 :
141 0 : uno::Sequence< OUString > SAL_CALL SvxUnoMarkerTable::getSupportedServiceNames( )
142 : throw( uno::RuntimeException, std::exception )
143 : {
144 0 : uno::Sequence< OUString > aSNS( 1 );
145 0 : aSNS.getArray()[0] = "com.sun.star.drawing.MarkerTable";
146 0 : return aSNS;
147 : }
148 :
149 152 : void SAL_CALL SvxUnoMarkerTable::ImplInsertByName( const OUString& aName, const uno::Any& aElement )
150 : {
151 152 : SfxItemSet* mpInSet = new SfxItemSet( *mpModelPool, XATTR_LINESTART, XATTR_LINEEND );
152 152 : maItemSetVector.push_back( mpInSet );
153 :
154 152 : XLineEndItem aEndMarker;
155 152 : aEndMarker.SetName( aName );
156 152 : aEndMarker.PutValue( aElement );
157 :
158 152 : mpInSet->Put( aEndMarker, XATTR_LINEEND );
159 :
160 304 : XLineStartItem aStartMarker;
161 152 : aStartMarker.SetName( aName );
162 152 : aStartMarker.PutValue( aElement );
163 :
164 304 : mpInSet->Put( aStartMarker, XATTR_LINESTART );
165 152 : }
166 :
167 : // XNameContainer
168 108 : void SAL_CALL SvxUnoMarkerTable::insertByName( const OUString& aApiName, const uno::Any& aElement )
169 : throw( lang::IllegalArgumentException, container::ElementExistException, lang::WrappedTargetException, uno::RuntimeException, std::exception )
170 : {
171 108 : SolarMutexGuard aGuard;
172 :
173 108 : if( hasByName( aApiName ) )
174 0 : throw container::ElementExistException();
175 :
176 216 : OUString aName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aApiName);
177 :
178 216 : ImplInsertByName( aName, aElement );
179 108 : }
180 :
181 44 : void SAL_CALL SvxUnoMarkerTable::removeByName( const OUString& aApiName )
182 : throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception)
183 : {
184 44 : SolarMutexGuard aGuard;
185 :
186 : // a little quickfix for 2.0 to let applications clear api
187 : // created items that are not used
188 44 : if ( aApiName == "~clear~" )
189 : {
190 44 : dispose();
191 44 : return;
192 : }
193 :
194 0 : OUString Name = SvxUnogetInternalNameForItem(XATTR_LINEEND, aApiName);
195 :
196 0 : ItemPoolVector::iterator aIter = maItemSetVector.begin();
197 0 : const ItemPoolVector::iterator aEnd = maItemSetVector.end();
198 :
199 0 : const OUString aSearchName( Name );
200 :
201 0 : while( aIter != aEnd )
202 : {
203 0 : const NameOrIndex *pItem = static_cast<const NameOrIndex *>(&((*aIter)->Get( XATTR_LINEEND ) ));
204 0 : if( pItem->GetName() == aSearchName )
205 : {
206 0 : delete (*aIter);
207 0 : maItemSetVector.erase( aIter );
208 0 : return;
209 : }
210 0 : ++aIter;
211 : }
212 :
213 0 : if( !hasByName( Name ) )
214 0 : throw container::NoSuchElementException();
215 : }
216 :
217 : // XNameReplace
218 44 : void SAL_CALL SvxUnoMarkerTable::replaceByName( const OUString& aApiName, const uno::Any& aElement )
219 : throw( lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception )
220 : {
221 44 : SolarMutexGuard aGuard;
222 :
223 88 : OUString aName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aApiName);
224 :
225 44 : ItemPoolVector::iterator aIter = maItemSetVector.begin();
226 44 : const ItemPoolVector::iterator aEnd = maItemSetVector.end();
227 :
228 88 : const OUString aSearchName( aName );
229 :
230 88 : while( aIter != aEnd )
231 : {
232 0 : const NameOrIndex *pItem = static_cast<const NameOrIndex *>(&((*aIter)->Get( XATTR_LINEEND ) ));
233 0 : if( pItem->GetName() == aSearchName )
234 : {
235 0 : XLineEndItem aEndMarker;
236 0 : aEndMarker.SetName( aSearchName );
237 0 : if( !aEndMarker.PutValue( aElement ) )
238 0 : throw lang::IllegalArgumentException();
239 :
240 0 : (*aIter)->Put( aEndMarker, XATTR_LINEEND );
241 :
242 0 : XLineStartItem aStartMarker;
243 0 : aStartMarker.SetName( aSearchName );
244 0 : aStartMarker.PutValue( aElement );
245 :
246 0 : (*aIter)->Put( aStartMarker, XATTR_LINESTART );
247 44 : return;
248 : }
249 0 : ++aIter;
250 : }
251 :
252 : // if it is not in our own sets, modify the pool!
253 44 : bool bFound = false;
254 :
255 : sal_uInt32 nSurrogate;
256 44 : const sal_uInt32 nStartCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINESTART ) : 0;
257 88 : for( nSurrogate = 0; nSurrogate < nStartCount; nSurrogate++ )
258 : {
259 88 : NameOrIndex *pItem = const_cast<NameOrIndex*>(static_cast<const NameOrIndex*>(mpModelPool->GetItem2( XATTR_LINESTART, nSurrogate)));
260 88 : if( pItem && pItem->GetName() == aSearchName )
261 : {
262 44 : pItem->PutValue( aElement );
263 44 : bFound = true;
264 44 : break;
265 : }
266 : }
267 :
268 44 : const sal_uInt32 nEndCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINEEND ) : 0;
269 88 : for( nSurrogate = 0; nSurrogate < nEndCount; nSurrogate++ )
270 : {
271 88 : NameOrIndex *pItem = const_cast<NameOrIndex*>(static_cast<const NameOrIndex*>(mpModelPool->GetItem2( XATTR_LINEEND, nSurrogate)));
272 88 : if( pItem && pItem->GetName() == aSearchName )
273 : {
274 44 : pItem->PutValue( aElement );
275 44 : bFound = true;
276 44 : break;
277 : }
278 : }
279 :
280 44 : if( bFound )
281 44 : ImplInsertByName( aName, aElement );
282 : else
283 44 : throw container::NoSuchElementException();
284 : }
285 :
286 19 : static bool getByNameFromPool( const OUString& rSearchName, SfxItemPool* pPool, sal_uInt16 nWhich, uno::Any& rAny )
287 : {
288 19 : const sal_uInt32 nSurrogateCount = pPool ? pPool->GetItemCount2( nWhich ) : 0;
289 37 : for( sal_uInt32 nSurrogate = 0; nSurrogate < nSurrogateCount; nSurrogate++ )
290 : {
291 37 : const NameOrIndex *pItem = static_cast<const NameOrIndex*>(pPool->GetItem2( nWhich, nSurrogate ));
292 :
293 37 : if( pItem && pItem->GetName() == rSearchName )
294 : {
295 19 : pItem->QueryValue( rAny, 0 );
296 19 : return true;
297 : }
298 : }
299 :
300 0 : return false;
301 : }
302 :
303 : // XNameAccess
304 19 : uno::Any SAL_CALL SvxUnoMarkerTable::getByName( const OUString& aApiName )
305 : throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception)
306 : {
307 19 : SolarMutexGuard aGuard;
308 :
309 38 : OUString aName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aApiName);
310 :
311 19 : uno::Any aAny;
312 :
313 19 : if (mpModelPool && !aName.isEmpty())
314 : {
315 : do
316 : {
317 19 : if (getByNameFromPool(aName, mpModelPool, XATTR_LINESTART, aAny))
318 19 : break;
319 :
320 0 : if (getByNameFromPool(aName, mpModelPool, XATTR_LINEEND, aAny))
321 0 : break;
322 :
323 0 : throw container::NoSuchElementException();
324 : }
325 : while(false);
326 : }
327 :
328 38 : return aAny;
329 : }
330 :
331 34 : static void createNamesForPool( SfxItemPool* pPool, sal_uInt16 nWhich, std::set< OUString >& rNameSet )
332 : {
333 34 : const sal_uInt32 nSuroCount = pPool->GetItemCount2( nWhich );
334 :
335 103 : for(sal_uInt32 nSurrogate = 0; nSurrogate < nSuroCount; ++nSurrogate)
336 : {
337 69 : const NameOrIndex* pItem = static_cast<const NameOrIndex*>(pPool->GetItem2( nWhich, nSurrogate ));
338 :
339 69 : if( pItem == NULL || pItem->GetName().isEmpty() )
340 31 : continue;
341 :
342 38 : OUString aName = SvxUnogetApiNameForItem(XATTR_LINEEND, pItem->GetName());
343 38 : rNameSet.insert( aName );
344 38 : }
345 34 : }
346 :
347 17 : uno::Sequence< OUString > SAL_CALL SvxUnoMarkerTable::getElementNames()
348 : throw( uno::RuntimeException, std::exception )
349 : {
350 17 : SolarMutexGuard aGuard;
351 :
352 34 : std::set< OUString > aNameSet;
353 :
354 : // search model pool for line starts
355 17 : createNamesForPool( mpModelPool, XATTR_LINESTART, aNameSet );
356 :
357 : // search model pool for line ends
358 17 : createNamesForPool( mpModelPool, XATTR_LINEEND, aNameSet );
359 :
360 17 : uno::Sequence< OUString > aSeq( aNameSet.size() );
361 17 : OUString* pNames = aSeq.getArray();
362 :
363 17 : std::set< OUString >::iterator aIter( aNameSet.begin() );
364 17 : const std::set< OUString >::iterator aEnd( aNameSet.end() );
365 :
366 53 : while( aIter != aEnd )
367 : {
368 19 : *pNames++ = *aIter++;
369 : }
370 :
371 34 : return aSeq;
372 : }
373 :
374 386 : sal_Bool SAL_CALL SvxUnoMarkerTable::hasByName( const OUString& aName )
375 : throw( uno::RuntimeException, std::exception )
376 : {
377 386 : SolarMutexGuard aGuard;
378 :
379 386 : if( aName.isEmpty() )
380 0 : return sal_False;
381 :
382 772 : OUString aSearchName;
383 :
384 : const NameOrIndex *pItem;
385 :
386 386 : aSearchName = SvxUnogetInternalNameForItem(XATTR_LINESTART, aName);
387 386 : sal_uInt32 nStartCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINESTART ) : 0;
388 : sal_uInt32 nSurrogate;
389 801 : for( nSurrogate = 0; nSurrogate < nStartCount; nSurrogate++ )
390 : {
391 551 : pItem = static_cast<const NameOrIndex*>(mpModelPool->GetItem2( XATTR_LINESTART, nSurrogate));
392 551 : if( pItem && pItem->GetName() == aSearchName )
393 136 : return sal_True;
394 : }
395 :
396 250 : aSearchName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aName);
397 250 : sal_uInt32 nEndCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINEEND ) : 0;
398 603 : for( nSurrogate = 0; nSurrogate < nEndCount; nSurrogate++ )
399 : {
400 353 : pItem = static_cast<const NameOrIndex*>(mpModelPool->GetItem2( XATTR_LINEEND, nSurrogate));
401 353 : if( pItem && pItem->GetName() == aSearchName )
402 0 : return sal_True;
403 : }
404 :
405 636 : return sal_False;
406 : }
407 :
408 : // XElementAccess
409 0 : uno::Type SAL_CALL SvxUnoMarkerTable::getElementType( )
410 : throw( uno::RuntimeException, std::exception )
411 : {
412 0 : return cppu::UnoType<drawing::PointSequence>::get();
413 : }
414 :
415 386 : sal_Bool SAL_CALL SvxUnoMarkerTable::hasElements( )
416 : throw( uno::RuntimeException, std::exception )
417 : {
418 386 : SolarMutexGuard aGuard;
419 :
420 : const NameOrIndex *pItem;
421 :
422 386 : const sal_uInt32 nStartCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINESTART ) : 0;
423 : sal_uInt32 nSurrogate;
424 401 : for( nSurrogate = 0; nSurrogate < nStartCount; nSurrogate++ )
425 : {
426 32 : pItem = static_cast<const NameOrIndex*>(mpModelPool->GetItem2( XATTR_LINESTART, nSurrogate));
427 32 : if( pItem && !pItem->GetName().isEmpty() )
428 17 : return sal_True;
429 : }
430 :
431 369 : const sal_uInt32 nEndCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINEEND ) : 0;
432 369 : for( nSurrogate = 0; nSurrogate < nEndCount; nSurrogate++ )
433 : {
434 0 : pItem = static_cast<const NameOrIndex*>(mpModelPool->GetItem2( XATTR_LINEEND, nSurrogate));
435 0 : if( pItem && !pItem->GetName().isEmpty() )
436 0 : return sal_True;
437 : }
438 :
439 369 : return sal_False;
440 : }
441 :
442 : /**
443 : * Create a hatchtable
444 : */
445 297 : uno::Reference< uno::XInterface > SAL_CALL SvxUnoMarkerTable_createInstance( SdrModel* pModel )
446 : {
447 297 : return *new SvxUnoMarkerTable(pModel);
448 435 : }
449 :
450 :
451 :
452 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|