Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <com/sun/star/document/EventObject.hpp>
21 : #include <com/sun/star/drawing/XShapes.hpp>
22 : #include <com/sun/star/lang/XComponent.hpp>
23 : #include <com/sun/star/lang/XServiceInfo.hpp>
24 : #include <com/sun/star/uno/XComponentContext.hpp>
25 :
26 : #include <cppuhelper/implbase3.hxx>
27 : #include <cppuhelper/interfacecontainer.hxx>
28 : #include <cppuhelper/supportsservice.hxx>
29 : #include <osl/mutex.hxx>
30 : #include <rtl/ref.hxx>
31 : #include <svx/unoprov.hxx>
32 :
33 : using namespace ::com::sun::star;
34 : using namespace ::com::sun::star::uno;
35 :
36 : namespace {
37 :
38 90 : class SvxShapeCollectionMutex
39 : {
40 : public:
41 : ::osl::Mutex maMutex;
42 : };
43 :
44 : class SvxShapeCollection :
45 : public cppu::WeakAggImplHelper3<drawing::XShapes, lang::XServiceInfo, lang::XComponent>,
46 : public SvxShapeCollectionMutex
47 : {
48 : private:
49 : cppu::OInterfaceContainerHelper maShapeContainer;
50 :
51 : cppu::OBroadcastHelper mrBHelper;
52 :
53 : void disposing() throw();
54 :
55 : public:
56 : SvxShapeCollection() throw();
57 : virtual ~SvxShapeCollection() throw();
58 :
59 : // XInterface
60 : virtual void SAL_CALL release() throw() SAL_OVERRIDE;
61 :
62 : // XComponent
63 : virtual void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
64 : virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
65 : virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
66 :
67 : // XIndexAccess
68 : virtual sal_Int32 SAL_CALL getCount() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE ;
69 : virtual ::com::sun::star::uno::Any SAL_CALL getByIndex( sal_Int32 Index ) throw(::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
70 :
71 : // XElementAccess
72 : virtual ::com::sun::star::uno::Type SAL_CALL getElementType() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
73 : virtual sal_Bool SAL_CALL hasElements() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
74 :
75 : // XShapes
76 : virtual void SAL_CALL add( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape ) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
77 : virtual void SAL_CALL remove( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape ) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
78 :
79 : // XServiceInfo
80 : virtual OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
81 : virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
82 : virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
83 : };
84 :
85 49 : SvxShapeCollection::SvxShapeCollection() throw()
86 49 : : maShapeContainer( maMutex ), mrBHelper( maMutex )
87 : {
88 49 : }
89 :
90 :
91 82 : SvxShapeCollection::~SvxShapeCollection() throw()
92 : {
93 82 : }
94 :
95 : // XInterface
96 428 : void SvxShapeCollection::release() throw()
97 : {
98 428 : uno::Reference< uno::XInterface > x( xDelegator );
99 428 : if (! x.is())
100 : {
101 428 : if (osl_atomic_decrement( &m_refCount ) == 0)
102 : {
103 81 : if (! mrBHelper.bDisposed)
104 : {
105 40 : uno::Reference< uno::XInterface > xHoldAlive( static_cast<uno::XWeak*>(this) );
106 : // First dispose
107 : try
108 : {
109 40 : dispose();
110 : }
111 0 : catch(::com::sun::star::uno::Exception&)
112 : {
113 : // release should not throw exceptions
114 : }
115 :
116 : // only the alive ref holds the object
117 : OSL_ASSERT( m_refCount == 1 );
118 : // destroy the object if xHoldAlive decrement the refcount to 0
119 468 : return;
120 : }
121 : }
122 : // restore the reference count
123 388 : osl_atomic_increment( &m_refCount );
124 : }
125 388 : OWeakAggObject::release();
126 : }
127 :
128 : // XComponent
129 41 : void SvxShapeCollection::disposing() throw()
130 : {
131 41 : maShapeContainer.clear();
132 41 : }
133 :
134 : // XComponent
135 41 : void SvxShapeCollection::dispose()
136 : throw(::com::sun::star::uno::RuntimeException, std::exception)
137 : {
138 : // An frequently programming error is to release the last
139 : // reference to this object in the disposing message.
140 : // Make it rubust, hold a self Reference.
141 41 : uno::Reference< lang::XComponent > xSelf( this );
142 :
143 : // Guard dispose against multible threading
144 : // Remark: It is an error to call dispose more than once
145 41 : bool bDoDispose = false;
146 : {
147 41 : osl::MutexGuard aGuard( mrBHelper.rMutex );
148 41 : if( !mrBHelper.bDisposed && !mrBHelper.bInDispose )
149 : {
150 : // only one call go into this section
151 41 : mrBHelper.bInDispose = sal_True;
152 41 : bDoDispose = true;
153 41 : }
154 : }
155 :
156 : // Do not hold the mutex because we are broadcasting
157 41 : if( bDoDispose )
158 : {
159 : // Create an event with this as sender
160 : try
161 : {
162 41 : uno::Reference< uno::XInterface > xSource( uno::Reference< uno::XInterface >::query( static_cast<lang::XComponent *>(this) ) );
163 82 : document::EventObject aEvt;
164 41 : aEvt.Source = xSource;
165 : // inform all listeners to release this object
166 : // The listener container are automatically cleared
167 41 : mrBHelper.aLC.disposeAndClear( aEvt );
168 : // notify subclasses to do their dispose
169 82 : disposing();
170 : }
171 0 : catch(const ::com::sun::star::uno::Exception&)
172 : {
173 : // catch exception and throw again but signal that
174 : // the object was disposed. Dispose should be called
175 : // only once.
176 0 : mrBHelper.bDisposed = sal_True;
177 0 : mrBHelper.bInDispose = sal_False;
178 0 : throw;
179 : }
180 :
181 : // the values bDispose and bInDisposing must set in this order.
182 : // No multithread call overcome the "!rBHelper.bDisposed && !rBHelper.bInDispose" guard.
183 41 : mrBHelper.bDisposed = sal_True;
184 41 : mrBHelper.bInDispose = sal_False;
185 : }
186 : else
187 : {
188 : // in a multithreaded environment, it can't be avoided, that dispose is called twice.
189 : // However this condition is traced, because it MAY indicate an error.
190 : OSL_TRACE( "OComponentHelper::dispose() - dispose called twice" );
191 41 : }
192 41 : }
193 :
194 : // XComponent
195 15 : void SAL_CALL SvxShapeCollection::addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw(::com::sun::star::uno::RuntimeException, std::exception)
196 : {
197 15 : mrBHelper.addListener( cppu::UnoType<decltype(aListener)>::get() , aListener );
198 15 : }
199 :
200 : // XComponent
201 0 : void SAL_CALL SvxShapeCollection::removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw(::com::sun::star::uno::RuntimeException, std::exception)
202 : {
203 0 : mrBHelper.removeListener( cppu::UnoType<decltype(aListener)>::get() , aListener );
204 0 : }
205 :
206 : // XShapes
207 :
208 145 : void SAL_CALL SvxShapeCollection::add( const Reference< drawing::XShape >& xShape ) throw( uno::RuntimeException, std::exception )
209 : {
210 145 : maShapeContainer.addInterface( xShape );
211 145 : }
212 :
213 :
214 1 : void SAL_CALL SvxShapeCollection::remove( const uno::Reference< drawing::XShape >& xShape ) throw( uno::RuntimeException, std::exception )
215 : {
216 1 : maShapeContainer.removeInterface( xShape );
217 1 : }
218 :
219 :
220 162 : sal_Int32 SAL_CALL SvxShapeCollection::getCount() throw( uno::RuntimeException, std::exception )
221 : {
222 162 : return maShapeContainer.getLength();
223 : }
224 :
225 :
226 125 : uno::Any SAL_CALL SvxShapeCollection::getByIndex( sal_Int32 Index )
227 : throw( lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException, std::exception )
228 : {
229 125 : if( Index < 0 || Index >= getCount() )
230 1 : throw lang::IndexOutOfBoundsException();
231 :
232 124 : uno::Sequence< Reference< uno::XInterface> > xElements( maShapeContainer.getElements() );
233 :
234 :
235 124 : return uno::makeAny( Reference< drawing::XShape>(static_cast< drawing::XShape* >( xElements.getArray()[Index].get())) );
236 : }
237 :
238 : // XElementAccess
239 1 : uno::Type SAL_CALL SvxShapeCollection::getElementType() throw( uno::RuntimeException, std::exception )
240 : {
241 1 : return cppu::UnoType<drawing::XShape>::get();
242 : }
243 :
244 1 : sal_Bool SAL_CALL SvxShapeCollection::hasElements() throw( uno::RuntimeException, std::exception )
245 : {
246 1 : return getCount() != 0;
247 : }
248 :
249 : // XServiceInfo
250 4 : OUString SAL_CALL SvxShapeCollection::getImplementationName()
251 : throw( uno::RuntimeException, std::exception )
252 : {
253 4 : return OUString("com.sun.star.drawing.SvxShapeCollection");
254 : }
255 :
256 0 : sal_Bool SAL_CALL SvxShapeCollection::supportsService( const OUString& ServiceName )
257 : throw( uno::RuntimeException, std::exception )
258 : {
259 0 : return cppu::supportsService( this, ServiceName);
260 : }
261 :
262 1 : uno::Sequence< OUString > SAL_CALL SvxShapeCollection::getSupportedServiceNames() throw( uno::RuntimeException, std::exception )
263 : {
264 1 : uno::Sequence< OUString > aSeq(2);
265 1 : aSeq.getArray()[0] = "com.sun.star.drawing.Shapes";
266 1 : aSeq.getArray()[1] = "com.sun.star.drawing.ShapeCollection";
267 1 : return aSeq;
268 : }
269 :
270 : }
271 :
272 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
273 49 : com_sun_star_drawing_SvxShapeCollection_get_implementation(
274 : css::uno::XComponentContext *,
275 : css::uno::Sequence<css::uno::Any> const &)
276 : {
277 49 : return cppu::acquire(new SvxShapeCollection);
278 : }
279 :
280 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|