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