LibreOffice Module svx (master)  1
unoshcol.cxx
Go to the documentation of this file.
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/IndexOutOfBoundsException.hpp>
23 #include <com/sun/star/lang/XComponent.hpp>
24 #include <com/sun/star/lang/XServiceInfo.hpp>
25 #include <com/sun/star/uno/XComponentContext.hpp>
26 
27 #include <cppuhelper/implbase3.hxx>
31 #include <osl/mutex.hxx>
32 #include <sal/log.hxx>
33 
34 using namespace ::com::sun::star;
35 using namespace ::com::sun::star::uno;
36 
37 namespace {
38 
39 class SvxShapeCollectionMutex
40 {
41 public:
42  ::osl::Mutex maMutex;
43 };
44 
45 class SvxShapeCollection :
46  public cppu::WeakAggImplHelper3<drawing::XShapes, lang::XServiceInfo, lang::XComponent>,
47  public SvxShapeCollectionMutex
48 {
49 private:
51 
52  cppu::OBroadcastHelper mrBHelper;
53 
54 public:
55  SvxShapeCollection() throw();
56 
57  // XInterface
58  virtual void SAL_CALL release() throw() override;
59 
60  // XComponent
61  virtual void SAL_CALL dispose() override;
62  virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override;
63  virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override;
64 
65  // XIndexAccess
66  virtual sal_Int32 SAL_CALL getCount() override ;
67  virtual css::uno::Any SAL_CALL getByIndex( sal_Int32 Index ) override;
68 
69  // XElementAccess
70  virtual css::uno::Type SAL_CALL getElementType() override;
71  virtual sal_Bool SAL_CALL hasElements() override;
72 
73  // XShapes
74  virtual void SAL_CALL add( const css::uno::Reference< css::drawing::XShape >& xShape ) override;
75  virtual void SAL_CALL remove( const css::uno::Reference< css::drawing::XShape >& xShape ) override;
76 
77  // XServiceInfo
78  virtual OUString SAL_CALL getImplementationName() override;
79  virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
80  virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
81 };
82 
83 SvxShapeCollection::SvxShapeCollection() throw()
84 : maShapeContainer( maMutex ), mrBHelper( maMutex )
85 {
86 }
87 
88 // XInterface
89 void SvxShapeCollection::release() throw()
90 {
91  uno::Reference< uno::XInterface > x( xDelegator );
92  if (! x.is())
93  {
94  if (osl_atomic_decrement( &m_refCount ) == 0)
95  {
96  if (! mrBHelper.bDisposed)
97  {
98  uno::Reference< uno::XInterface > xHoldAlive( static_cast<uno::XWeak*>(this) );
99  // First dispose
100  try
101  {
102  dispose();
103  }
104  catch(css::uno::Exception&)
105  {
106  // release should not throw exceptions
107  }
108 
109  // only the alive ref holds the object
110  OSL_ASSERT( m_refCount == 1 );
111  // destroy the object if xHoldAlive decrement the refcount to 0
112  return;
113  }
114  }
115  // restore the reference count
116  osl_atomic_increment( &m_refCount );
117  }
119 }
120 
121 // XComponent
122 void SvxShapeCollection::dispose()
123 {
124  // An frequently programming error is to release the last
125  // reference to this object in the disposing message.
126  // Make it robust, hold a self Reference.
127  uno::Reference< lang::XComponent > xSelf( this );
128 
129  // Guard dispose against multiple threading
130  // Remark: It is an error to call dispose more than once
131  bool bDoDispose = false;
132  {
133  osl::MutexGuard aGuard( mrBHelper.rMutex );
134  if( !mrBHelper.bDisposed && !mrBHelper.bInDispose )
135  {
136  // only one call go into this section
137  mrBHelper.bInDispose = true;
138  bDoDispose = true;
139  }
140  }
141 
142  // Do not hold the mutex because we are broadcasting
143  if( bDoDispose )
144  {
145  // Create an event with this as sender
146  try
147  {
148  uno::Reference< uno::XInterface > xSource( uno::Reference< uno::XInterface >::query( static_cast<lang::XComponent *>(this) ) );
149  document::EventObject aEvt;
150  aEvt.Source = xSource;
151  // inform all listeners to release this object
152  // The listener container are automatically cleared
153  mrBHelper.aLC.disposeAndClear( aEvt );
154  maShapeContainer.clear();
155  }
156  catch(const css::uno::Exception&)
157  {
158  // catch exception and throw again but signal that
159  // the object was disposed. Dispose should be called
160  // only once.
161  mrBHelper.bDisposed = true;
162  mrBHelper.bInDispose = false;
163  throw;
164  }
165 
166  // the values bDispose and bInDisposing must set in this order.
167  // No multithread call overcome the "!rBHelper.bDisposed && !rBHelper.bInDispose" guard.
168  mrBHelper.bDisposed = true;
169  mrBHelper.bInDispose = false;
170  }
171  else
172  {
173  // in a multithreaded environment, it can't be avoided, that dispose is called twice.
174  // However this condition is traced, because it MAY indicate an error.
175  SAL_INFO("svx", "dispose called twice" );
176  }
177 }
178 
179 // XComponent
180 void SAL_CALL SvxShapeCollection::addEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener )
181 {
182  mrBHelper.addListener( cppu::UnoType<decltype(aListener)>::get() , aListener );
183 }
184 
185 // XComponent
186 void SAL_CALL SvxShapeCollection::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener )
187 {
188  mrBHelper.removeListener( cppu::UnoType<decltype(aListener)>::get() , aListener );
189 }
190 
191 // XShapes
192 
193 void SAL_CALL SvxShapeCollection::add( const Reference< drawing::XShape >& xShape )
194 {
195  maShapeContainer.addInterface( xShape );
196 }
197 
198 
199 void SAL_CALL SvxShapeCollection::remove( const uno::Reference< drawing::XShape >& xShape )
200 {
201  maShapeContainer.removeInterface( xShape );
202 }
203 
204 
205 sal_Int32 SAL_CALL SvxShapeCollection::getCount()
206 {
207  return maShapeContainer.getLength();
208 }
209 
210 
211 uno::Any SAL_CALL SvxShapeCollection::getByIndex( sal_Int32 Index )
212 {
213  if( Index < 0 || Index >= getCount() )
214  throw lang::IndexOutOfBoundsException();
215 
216  std::vector< Reference< uno::XInterface> > aElements( maShapeContainer.getElements() );
217 
218 
219  return uno::makeAny( Reference< drawing::XShape>(static_cast< drawing::XShape* >( aElements[Index].get())) );
220 }
221 
222 // XElementAccess
223 uno::Type SAL_CALL SvxShapeCollection::getElementType()
224 {
226 }
227 
228 sal_Bool SAL_CALL SvxShapeCollection::hasElements()
229 {
230  return getCount() != 0;
231 }
232 
233 // XServiceInfo
234 OUString SAL_CALL SvxShapeCollection::getImplementationName()
235 {
236  return "com.sun.star.drawing.SvxShapeCollection";
237 }
238 
239 sal_Bool SAL_CALL SvxShapeCollection::supportsService( const OUString& ServiceName )
240 {
241  return cppu::supportsService( this, ServiceName);
242 }
243 
244 uno::Sequence< OUString > SAL_CALL SvxShapeCollection::getSupportedServiceNames()
245 {
246  return { "com.sun.star.drawing.Shapes", "com.sun.star.drawing.ShapeCollection" };
247 }
248 
249 }
250 
251 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
253  css::uno::XComponentContext *,
254  css::uno::Sequence<css::uno::Any> const &)
255 {
256  return cppu::acquire(new SvxShapeCollection);
257 }
258 
259 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Type
sal_Int32 addInterface(const css::uno::Reference< css::uno::XInterface > &rxIFace)
sal_Int32 removeInterface(const css::uno::Reference< css::uno::XInterface > &rxIFace)
float x
virtual void SAL_CALL release() SAL_OVERRIDE
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
void addListener(const keyType &key, const css::uno::Reference< css::uno::XInterface > &r)
::osl::Mutex maMutex
void removeListener(const keyType &key, const css::uno::Reference< css::uno::XInterface > &r)
unsigned char sal_Bool
css::uno::Type const & get()
std::vector< css::uno::Reference< css::uno::XInterface > > getElements() const
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_drawing_SvxShapeCollection_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
Definition: unoshcol.cxx:252
#define SAL_INFO(area, stream)
void dispose()
struct _ADOIndex Index