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 : 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 466 : SvxUnoMarkerTable::SvxUnoMarkerTable( SdrModel* pModel ) throw()
95 : : mpModel( pModel ),
96 466 : mpModelPool( pModel ? &pModel->GetItemPool() : (SfxItemPool*)NULL )
97 : {
98 466 : if( pModel )
99 466 : StartListening( *pModel );
100 466 : }
101 :
102 1320 : SvxUnoMarkerTable::~SvxUnoMarkerTable() throw()
103 : {
104 440 : if( mpModel )
105 440 : EndListening( *mpModel );
106 440 : dispose();
107 880 : }
108 :
109 874 : void SvxUnoMarkerTable::dispose()
110 : {
111 874 : ItemPoolVector::iterator aIter = maItemSetVector.begin();
112 874 : const ItemPoolVector::iterator aEnd = maItemSetVector.end();
113 :
114 1906 : while( aIter != aEnd )
115 : {
116 158 : delete (*aIter++);
117 : }
118 :
119 874 : maItemSetVector.clear();
120 874 : }
121 :
122 : // SfxListener
123 30668 : void SvxUnoMarkerTable::Notify( SfxBroadcaster&, const SfxHint& rHint ) throw()
124 : {
125 30668 : const SdrHint* pSdrHint = dynamic_cast<const SdrHint*>(&rHint);
126 :
127 30668 : if( pSdrHint && HINT_MODELCLEARED == pSdrHint->GetKind() )
128 398 : dispose();
129 30668 : }
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 158 : void SAL_CALL SvxUnoMarkerTable::ImplInsertByName( const OUString& aName, const uno::Any& aElement )
150 : {
151 158 : SfxItemSet* mpInSet = new SfxItemSet( *mpModelPool, XATTR_LINESTART, XATTR_LINEEND );
152 158 : maItemSetVector.push_back( mpInSet );
153 :
154 158 : XLineEndItem aEndMarker;
155 158 : aEndMarker.SetName( aName );
156 158 : aEndMarker.PutValue( aElement );
157 :
158 158 : mpInSet->Put( aEndMarker, XATTR_LINEEND );
159 :
160 316 : XLineStartItem aStartMarker;
161 158 : aStartMarker.SetName( aName );
162 158 : aStartMarker.PutValue( aElement );
163 :
164 316 : mpInSet->Put( aStartMarker, XATTR_LINESTART );
165 158 : }
166 :
167 : // XNameContainer
168 122 : 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 122 : SolarMutexGuard aGuard;
172 :
173 122 : if( hasByName( aApiName ) )
174 0 : throw container::ElementExistException();
175 :
176 244 : OUString aName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aApiName);
177 :
178 244 : ImplInsertByName( aName, aElement );
179 122 : }
180 :
181 36 : void SAL_CALL SvxUnoMarkerTable::removeByName( const OUString& aApiName )
182 : throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception)
183 : {
184 36 : SolarMutexGuard aGuard;
185 :
186 : // a little quickfix for 2.0 to let applications clear api
187 : // created items that are not used
188 36 : if ( aApiName == "~clear~" )
189 : {
190 36 : dispose();
191 36 : 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 : const NameOrIndex *pItem;
200 0 : const OUString aSearchName( Name );
201 :
202 0 : while( aIter != aEnd )
203 : {
204 0 : pItem = static_cast<const NameOrIndex *>(&((*aIter)->Get( XATTR_LINEEND ) ));
205 0 : if( pItem->GetName() == aSearchName )
206 : {
207 0 : delete (*aIter);
208 0 : maItemSetVector.erase( aIter );
209 0 : return;
210 : }
211 0 : ++aIter;
212 : }
213 :
214 0 : if( !hasByName( Name ) )
215 0 : throw container::NoSuchElementException();
216 : }
217 :
218 : // XNameReplace
219 36 : void SAL_CALL SvxUnoMarkerTable::replaceByName( const OUString& aApiName, const uno::Any& aElement )
220 : throw( lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception )
221 : {
222 36 : SolarMutexGuard aGuard;
223 :
224 72 : OUString aName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aApiName);
225 :
226 36 : ItemPoolVector::iterator aIter = maItemSetVector.begin();
227 36 : const ItemPoolVector::iterator aEnd = maItemSetVector.end();
228 :
229 72 : const OUString aSearchName( aName );
230 :
231 72 : while( aIter != aEnd )
232 : {
233 0 : const NameOrIndex *pItem = static_cast<const NameOrIndex *>(&((*aIter)->Get( XATTR_LINEEND ) ));
234 0 : if( pItem->GetName() == aSearchName )
235 : {
236 0 : XLineEndItem aEndMarker;
237 0 : aEndMarker.SetName( aSearchName );
238 0 : if( !aEndMarker.PutValue( aElement ) )
239 0 : throw lang::IllegalArgumentException();
240 :
241 0 : (*aIter)->Put( aEndMarker, XATTR_LINEEND );
242 :
243 0 : XLineStartItem aStartMarker;
244 0 : aStartMarker.SetName( aSearchName );
245 0 : aStartMarker.PutValue( aElement );
246 :
247 0 : (*aIter)->Put( aStartMarker, XATTR_LINESTART );
248 36 : return;
249 : }
250 0 : ++aIter;
251 : }
252 :
253 : // if it is not in our own sets, modify the pool!
254 36 : bool bFound = false;
255 :
256 : sal_uInt32 nSurrogate;
257 36 : const sal_uInt32 nStartCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINESTART ) : 0;
258 72 : for( nSurrogate = 0; nSurrogate < nStartCount; nSurrogate++ )
259 : {
260 72 : NameOrIndex *pItem = const_cast<NameOrIndex*>(static_cast<const NameOrIndex*>(mpModelPool->GetItem2( XATTR_LINESTART, nSurrogate)));
261 72 : if( pItem && pItem->GetName() == aSearchName )
262 : {
263 36 : pItem->PutValue( aElement );
264 36 : bFound = true;
265 36 : break;
266 : }
267 : }
268 :
269 36 : const sal_uInt32 nEndCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINEEND ) : 0;
270 72 : for( nSurrogate = 0; nSurrogate < nEndCount; nSurrogate++ )
271 : {
272 72 : NameOrIndex *pItem = const_cast<NameOrIndex*>(static_cast<const NameOrIndex*>(mpModelPool->GetItem2( XATTR_LINEEND, nSurrogate)));
273 72 : if( pItem && pItem->GetName() == aSearchName )
274 : {
275 36 : pItem->PutValue( aElement );
276 36 : bFound = true;
277 36 : break;
278 : }
279 : }
280 :
281 36 : if( bFound )
282 36 : ImplInsertByName( aName, aElement );
283 : else
284 36 : throw container::NoSuchElementException();
285 : }
286 :
287 24 : static bool getByNameFromPool( const OUString& rSearchName, SfxItemPool* pPool, sal_uInt16 nWhich, uno::Any& rAny )
288 : {
289 : const NameOrIndex *pItem;
290 24 : const sal_uInt32 nSurrogateCount = pPool ? pPool->GetItemCount2( nWhich ) : 0;
291 46 : for( sal_uInt32 nSurrogate = 0; nSurrogate < nSurrogateCount; nSurrogate++ )
292 : {
293 46 : pItem = static_cast<const NameOrIndex*>(pPool->GetItem2( nWhich, nSurrogate ));
294 :
295 46 : if( pItem && pItem->GetName() == rSearchName )
296 : {
297 24 : pItem->QueryValue( rAny, 0 );
298 24 : return true;
299 : }
300 : }
301 :
302 0 : return false;
303 : }
304 :
305 : // XNameAccess
306 24 : uno::Any SAL_CALL SvxUnoMarkerTable::getByName( const OUString& aApiName )
307 : throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception)
308 : {
309 24 : SolarMutexGuard aGuard;
310 :
311 48 : OUString aName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aApiName);
312 :
313 24 : uno::Any aAny;
314 :
315 24 : if (mpModelPool && !aName.isEmpty())
316 : {
317 : do
318 : {
319 24 : if (getByNameFromPool(aName, mpModelPool, XATTR_LINESTART, aAny))
320 24 : break;
321 :
322 0 : if (getByNameFromPool(aName, mpModelPool, XATTR_LINEEND, aAny))
323 0 : break;
324 :
325 0 : throw container::NoSuchElementException();
326 : }
327 : while(false);
328 : }
329 :
330 48 : return aAny;
331 : }
332 :
333 48 : static void createNamesForPool( SfxItemPool* pPool, sal_uInt16 nWhich, std::set< OUString >& rNameSet )
334 : {
335 48 : const sal_uInt32 nSuroCount = pPool->GetItemCount2( nWhich );
336 :
337 142 : for(sal_uInt32 nSurrogate = 0; nSurrogate < nSuroCount; ++nSurrogate)
338 : {
339 94 : const NameOrIndex* pItem = static_cast<const NameOrIndex*>(pPool->GetItem2( nWhich, nSurrogate ));
340 :
341 94 : if( pItem == NULL || pItem->GetName().isEmpty() )
342 46 : continue;
343 :
344 48 : OUString aName = SvxUnogetApiNameForItem(XATTR_LINEEND, pItem->GetName());
345 48 : rNameSet.insert( aName );
346 48 : }
347 48 : }
348 :
349 24 : uno::Sequence< OUString > SAL_CALL SvxUnoMarkerTable::getElementNames()
350 : throw( uno::RuntimeException, std::exception )
351 : {
352 24 : SolarMutexGuard aGuard;
353 :
354 48 : std::set< OUString > aNameSet;
355 :
356 : // search model pool for line starts
357 24 : createNamesForPool( mpModelPool, XATTR_LINESTART, aNameSet );
358 :
359 : // search model pool for line ends
360 24 : createNamesForPool( mpModelPool, XATTR_LINEEND, aNameSet );
361 :
362 24 : uno::Sequence< OUString > aSeq( aNameSet.size() );
363 24 : OUString* pNames = aSeq.getArray();
364 :
365 24 : std::set< OUString >::iterator aIter( aNameSet.begin() );
366 24 : const std::set< OUString >::iterator aEnd( aNameSet.end() );
367 :
368 72 : while( aIter != aEnd )
369 : {
370 24 : *pNames++ = *aIter++;
371 : }
372 :
373 48 : return aSeq;
374 : }
375 :
376 530 : sal_Bool SAL_CALL SvxUnoMarkerTable::hasByName( const OUString& aName )
377 : throw( uno::RuntimeException, std::exception )
378 : {
379 530 : SolarMutexGuard aGuard;
380 :
381 530 : if( aName.isEmpty() )
382 0 : return sal_False;
383 :
384 1060 : OUString aSearchName;
385 :
386 : const NameOrIndex *pItem;
387 :
388 530 : aSearchName = SvxUnogetInternalNameForItem(XATTR_LINESTART, aName);
389 530 : sal_uInt32 nStartCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINESTART ) : 0;
390 : sal_uInt32 nSurrogate;
391 668 : for( nSurrogate = 0; nSurrogate < nStartCount; nSurrogate++ )
392 : {
393 358 : pItem = static_cast<const NameOrIndex*>(mpModelPool->GetItem2( XATTR_LINESTART, nSurrogate));
394 358 : if( pItem && pItem->GetName() == aSearchName )
395 220 : return sal_True;
396 : }
397 :
398 310 : aSearchName = SvxUnogetInternalNameForItem(XATTR_LINEEND, aName);
399 310 : sal_uInt32 nEndCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINEEND ) : 0;
400 388 : for( nSurrogate = 0; nSurrogate < nEndCount; nSurrogate++ )
401 : {
402 78 : pItem = static_cast<const NameOrIndex*>(mpModelPool->GetItem2( XATTR_LINEEND, nSurrogate));
403 78 : if( pItem && pItem->GetName() == aSearchName )
404 0 : return sal_True;
405 : }
406 :
407 840 : return sal_False;
408 : }
409 :
410 : // XElementAccess
411 0 : uno::Type SAL_CALL SvxUnoMarkerTable::getElementType( )
412 : throw( uno::RuntimeException, std::exception )
413 : {
414 0 : return ::getCppuType((const drawing::PointSequence*)0);
415 : }
416 :
417 674 : sal_Bool SAL_CALL SvxUnoMarkerTable::hasElements( )
418 : throw( uno::RuntimeException, std::exception )
419 : {
420 674 : SolarMutexGuard aGuard;
421 :
422 : const NameOrIndex *pItem;
423 :
424 674 : const sal_uInt32 nStartCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINESTART ) : 0;
425 : sal_uInt32 nSurrogate;
426 696 : for( nSurrogate = 0; nSurrogate < nStartCount; nSurrogate++ )
427 : {
428 46 : pItem = static_cast<const NameOrIndex*>(mpModelPool->GetItem2( XATTR_LINESTART, nSurrogate));
429 46 : if( pItem && !pItem->GetName().isEmpty() )
430 24 : return sal_True;
431 : }
432 :
433 650 : const sal_uInt32 nEndCount = mpModelPool ? mpModelPool->GetItemCount2( XATTR_LINEEND ) : 0;
434 650 : for( nSurrogate = 0; nSurrogate < nEndCount; nSurrogate++ )
435 : {
436 0 : pItem = static_cast<const NameOrIndex*>(mpModelPool->GetItem2( XATTR_LINEEND, nSurrogate));
437 0 : if( pItem && !pItem->GetName().isEmpty() )
438 0 : return sal_True;
439 : }
440 :
441 650 : return sal_False;
442 : }
443 :
444 : /**
445 : * Create a hatchtable
446 : */
447 466 : uno::Reference< uno::XInterface > SAL_CALL SvxUnoMarkerTable_createInstance( SdrModel* pModel )
448 : {
449 466 : return *new SvxUnoMarkerTable(pModel);
450 651 : }
451 :
452 :
453 :
454 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|