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