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