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