xref: /aoo42x/main/svx/source/unodraw/unoshcol.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 #include <com/sun/star/document/EventObject.hpp>
31 
32 #include "svx/unoshcol.hxx"
33 #include <svx/unoprov.hxx>
34 #include <comphelper/serviceinfohelper.hxx>
35 
36 using namespace ::cppu;
37 using namespace ::com::sun::star;
38 using namespace ::com::sun::star::uno;
39 using namespace ::com::sun::star::lang;
40 using namespace ::com::sun::star::container;
41 using namespace ::com::sun::star::drawing;
42 
43 /***********************************************************************
44 *                                                                      *
45 ***********************************************************************/
46 SvxShapeCollection::SvxShapeCollection() throw()
47 : maShapeContainer( maMutex ), mrBHelper( maMutex )
48 {
49 }
50 
51 //----------------------------------------------------------------------
52 SvxShapeCollection::~SvxShapeCollection() throw()
53 {
54 }
55 
56 
57 //----------------------------------------------------------------------
58 Reference< uno::XInterface > SvxShapeCollection_NewInstance() throw()
59 {
60 	Reference< drawing::XShapes > xShapes( new SvxShapeCollection() );
61 	Reference< uno::XInterface > xRef( xShapes, UNO_QUERY );
62 	return xRef;
63 }
64 
65 // XInterface
66 void SvxShapeCollection::release() throw()
67 {
68 	uno::Reference< uno::XInterface > x( xDelegator );
69 	if (! x.is())
70 	{
71 		if (osl_decrementInterlockedCount( &m_refCount ) == 0)
72 		{
73 			if (! mrBHelper.bDisposed)
74 			{
75 				uno::Reference< uno::XInterface > xHoldAlive( (uno::XWeak*)this );
76 				// First dispose
77 				try
78 				{
79 					dispose();
80 				}
81 				catch(::com::sun::star::uno::Exception&)
82 				{
83 					// release should not throw exceptions
84 				}
85 
86 				// only the alive ref holds the object
87 				OSL_ASSERT( m_refCount == 1 );
88 				// destroy the object if xHoldAlive decrement the refcount to 0
89 				return;
90 			}
91 		}
92 		// restore the reference count
93 		osl_incrementInterlockedCount( &m_refCount );
94 	}
95 	OWeakAggObject::release();
96 }
97 
98 // XComponent
99 void SvxShapeCollection::disposing() throw()
100 {
101 	maShapeContainer.clear();
102 }
103 
104 // XComponent
105 void SvxShapeCollection::dispose()
106 	throw(::com::sun::star::uno::RuntimeException)
107 {
108 	// An frequently programming error is to release the last
109 	// reference to this object in the disposing message.
110 	// Make it rubust, hold a self Reference.
111 	uno::Reference< lang::XComponent > xSelf( this );
112 
113 	// Guard dispose against multible threading
114 	// Remark: It is an error to call dispose more than once
115 	sal_Bool bDoDispose = sal_False;
116 	{
117 	osl::MutexGuard aGuard( mrBHelper.rMutex );
118 	if( !mrBHelper.bDisposed && !mrBHelper.bInDispose )
119 	{
120 		// only one call go into this section
121 		mrBHelper.bInDispose = sal_True;
122 		bDoDispose = sal_True;
123 	}
124 	}
125 
126 	// Do not hold the mutex because we are broadcasting
127 	if( bDoDispose )
128 	{
129 		// Create an event with this as sender
130 		try
131 		{
132 			uno::Reference< uno::XInterface > xSource( uno::Reference< uno::XInterface >::query( (lang::XComponent *)this ) );
133 			document::EventObject aEvt;
134 			aEvt.Source = xSource;
135 			// inform all listeners to release this object
136 			// The listener container are automaticly cleared
137 			mrBHelper.aLC.disposeAndClear( aEvt );
138 			// notify subclasses to do their dispose
139 			disposing();
140 		}
141 		catch(::com::sun::star::uno::Exception& e)
142 		{
143 			// catch exception and throw again but signal that
144 			// the object was disposed. Dispose should be called
145 			// only once.
146 			mrBHelper.bDisposed = sal_True;
147 			mrBHelper.bInDispose = sal_False;
148 			throw e;
149 		}
150 
151 		// the values bDispose and bInDisposing must set in this order.
152 		// No multithread call overcome the "!rBHelper.bDisposed && !rBHelper.bInDispose" guard.
153 		mrBHelper.bDisposed = sal_True;
154 		mrBHelper.bInDispose = sal_False;
155 	}
156 	else
157 	{
158 		// in a multithreaded environment, it can't be avoided, that dispose is called twice.
159 		// However this condition is traced, because it MAY indicate an error.
160 		OSL_TRACE( "OComponentHelper::dispose() - dispose called twice" );
161 	}
162 }
163 
164 // XComponent
165 void SAL_CALL SvxShapeCollection::addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw(::com::sun::star::uno::RuntimeException)
166 {
167 	mrBHelper.addListener( ::getCppuType( &aListener ) , aListener );
168 }
169 
170 // XComponent
171 void SAL_CALL SvxShapeCollection::removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw(::com::sun::star::uno::RuntimeException)
172 {
173 	mrBHelper.removeListener( ::getCppuType( &aListener ) , aListener );
174 }
175 
176 // XShapes
177 //----------------------------------------------------------------------
178 void SAL_CALL SvxShapeCollection::add( const Reference< drawing::XShape >& xShape ) throw( uno::RuntimeException )
179 {
180 	maShapeContainer.addInterface( xShape );
181 }
182 
183 //----------------------------------------------------------------------
184 void SAL_CALL SvxShapeCollection::remove( const uno::Reference< drawing::XShape >& xShape ) throw( uno::RuntimeException )
185 {
186 	maShapeContainer.removeInterface( xShape );
187 }
188 
189 //----------------------------------------------------------------------
190 sal_Int32 SAL_CALL SvxShapeCollection::getCount() throw( uno::RuntimeException )
191 {
192 	return maShapeContainer.getLength();
193 }
194 
195 //----------------------------------------------------------------------
196 uno::Any SAL_CALL SvxShapeCollection::getByIndex( sal_Int32 Index )
197 	throw( lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException )
198 {
199 	if( Index < 0 || Index >= getCount() )
200 		throw lang::IndexOutOfBoundsException();
201 
202 	uno::Sequence< Reference< uno::XInterface> > xElements( maShapeContainer.getElements() );
203 
204 
205 	return uno::makeAny( Reference< XShape>(static_cast< drawing::XShape* >( xElements.getArray()[Index].get())) );
206 }
207 
208 // XElementAccess
209 
210 //----------------------------------------------------------------------
211 uno::Type SAL_CALL SvxShapeCollection::getElementType() throw( uno::RuntimeException )
212 {
213 	return ::getCppuType(( const Reference< drawing::XShape >*)0);
214 }
215 
216 //----------------------------------------------------------------------
217 sal_Bool SAL_CALL SvxShapeCollection::hasElements() throw( uno::RuntimeException )
218 {
219 	return getCount() != 0;
220 }
221 
222 //----------------------------------------------------------------------
223 // XServiceInfo
224 //----------------------------------------------------------------------
225 ::rtl::OUString SAL_CALL SvxShapeCollection::getImplementationName()
226 	throw( uno::RuntimeException )
227 {
228 	return getImplementationName_Static();
229 }
230 
231 ::rtl::OUString SvxShapeCollection::getImplementationName_Static()
232 {
233 	return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.SvxShapeCollection") );
234 }
235 
236 sal_Bool SAL_CALL SvxShapeCollection::supportsService( const ::rtl::OUString& ServiceName )
237 	throw( uno::RuntimeException )
238 {
239 	return comphelper::ServiceInfoHelper::supportsService( ServiceName, getSupportedServiceNames() );
240 }
241 
242 uno::Sequence< ::rtl::OUString > SAL_CALL SvxShapeCollection::getSupportedServiceNames() throw( uno::RuntimeException )
243 {
244 	return getSupportedServiceNames_Static();
245 }
246 
247 uno::Sequence< ::rtl::OUString > SvxShapeCollection::getSupportedServiceNames_Static()
248 {
249 	uno::Sequence< ::rtl::OUString > aSeq(2);
250 	aSeq.getArray()[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.Shapes") );
251 	aSeq.getArray()[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.ShapeCollection") );
252 	return aSeq;
253 }
254 
255 Reference< XInterface > SAL_CALL SvxShapeCollection_createInstance( const Reference< ::com::sun::star::lang::XMultiServiceFactory >& )
256 {
257 	return *( new SvxShapeCollection() );
258 }
259