xref: /trunk/main/svx/source/unodraw/unoshcol.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 #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