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