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