xref: /trunk/main/svx/source/unodraw/unomtabl.cxx (revision cdf0e10c)
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