blob: a31108786551223f3cf59e7985625f946450a37f [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"
#include <com/sun/star/document/EventObject.hpp>
#include "svx/unoshcol.hxx"
#include <svx/unoprov.hxx>
#include <comphelper/serviceinfohelper.hxx>
using namespace ::cppu;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::drawing;
/***********************************************************************
* *
***********************************************************************/
SvxShapeCollection::SvxShapeCollection() throw()
: maShapeContainer( maMutex ), mrBHelper( maMutex )
{
}
//----------------------------------------------------------------------
SvxShapeCollection::~SvxShapeCollection() throw()
{
}
//----------------------------------------------------------------------
Reference< uno::XInterface > SvxShapeCollection_NewInstance() throw()
{
Reference< drawing::XShapes > xShapes( new SvxShapeCollection() );
Reference< uno::XInterface > xRef( xShapes, UNO_QUERY );
return xRef;
}
// XInterface
void SvxShapeCollection::release() throw()
{
uno::Reference< uno::XInterface > x( xDelegator );
if (! x.is())
{
if (osl_decrementInterlockedCount( &m_refCount ) == 0)
{
if (! mrBHelper.bDisposed)
{
uno::Reference< uno::XInterface > xHoldAlive( (uno::XWeak*)this );
// First dispose
try
{
dispose();
}
catch(::com::sun::star::uno::Exception&)
{
// release should not throw exceptions
}
// only the alive ref holds the object
OSL_ASSERT( m_refCount == 1 );
// destroy the object if xHoldAlive decrement the refcount to 0
return;
}
}
// restore the reference count
osl_incrementInterlockedCount( &m_refCount );
}
OWeakAggObject::release();
}
// XComponent
void SvxShapeCollection::disposing() throw()
{
maShapeContainer.clear();
}
// XComponent
void SvxShapeCollection::dispose()
throw(::com::sun::star::uno::RuntimeException)
{
// An frequently programming error is to release the last
// reference to this object in the disposing message.
// Make it rubust, hold a self Reference.
uno::Reference< lang::XComponent > xSelf( this );
// Guard dispose against multible threading
// Remark: It is an error to call dispose more than once
sal_Bool bDoDispose = sal_False;
{
osl::MutexGuard aGuard( mrBHelper.rMutex );
if( !mrBHelper.bDisposed && !mrBHelper.bInDispose )
{
// only one call go into this section
mrBHelper.bInDispose = sal_True;
bDoDispose = sal_True;
}
}
// Do not hold the mutex because we are broadcasting
if( bDoDispose )
{
// Create an event with this as sender
try
{
uno::Reference< uno::XInterface > xSource( uno::Reference< uno::XInterface >::query( (lang::XComponent *)this ) );
document::EventObject aEvt;
aEvt.Source = xSource;
// inform all listeners to release this object
// The listener container are automaticly cleared
mrBHelper.aLC.disposeAndClear( aEvt );
// notify subclasses to do their dispose
disposing();
}
catch(::com::sun::star::uno::Exception& e)
{
// catch exception and throw again but signal that
// the object was disposed. Dispose should be called
// only once.
mrBHelper.bDisposed = sal_True;
mrBHelper.bInDispose = sal_False;
throw e;
}
// the values bDispose and bInDisposing must set in this order.
// No multithread call overcome the "!rBHelper.bDisposed && !rBHelper.bInDispose" guard.
mrBHelper.bDisposed = sal_True;
mrBHelper.bInDispose = sal_False;
}
else
{
// in a multithreaded environment, it can't be avoided, that dispose is called twice.
// However this condition is traced, because it MAY indicate an error.
OSL_TRACE( "OComponentHelper::dispose() - dispose called twice" );
}
}
// XComponent
void SAL_CALL SvxShapeCollection::addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw(::com::sun::star::uno::RuntimeException)
{
mrBHelper.addListener( ::getCppuType( &aListener ) , aListener );
}
// XComponent
void SAL_CALL SvxShapeCollection::removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener >& aListener ) throw(::com::sun::star::uno::RuntimeException)
{
mrBHelper.removeListener( ::getCppuType( &aListener ) , aListener );
}
// XShapes
//----------------------------------------------------------------------
void SAL_CALL SvxShapeCollection::add( const Reference< drawing::XShape >& xShape ) throw( uno::RuntimeException )
{
maShapeContainer.addInterface( xShape );
}
//----------------------------------------------------------------------
void SAL_CALL SvxShapeCollection::remove( const uno::Reference< drawing::XShape >& xShape ) throw( uno::RuntimeException )
{
maShapeContainer.removeInterface( xShape );
}
//----------------------------------------------------------------------
sal_Int32 SAL_CALL SvxShapeCollection::getCount() throw( uno::RuntimeException )
{
return maShapeContainer.getLength();
}
//----------------------------------------------------------------------
uno::Any SAL_CALL SvxShapeCollection::getByIndex( sal_Int32 Index )
throw( lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException )
{
if( Index < 0 || Index >= getCount() )
throw lang::IndexOutOfBoundsException();
uno::Sequence< Reference< uno::XInterface> > xElements( maShapeContainer.getElements() );
return uno::makeAny( Reference< XShape>(static_cast< drawing::XShape* >( xElements.getArray()[Index].get())) );
}
// XElementAccess
//----------------------------------------------------------------------
uno::Type SAL_CALL SvxShapeCollection::getElementType() throw( uno::RuntimeException )
{
return ::getCppuType(( const Reference< drawing::XShape >*)0);
}
//----------------------------------------------------------------------
sal_Bool SAL_CALL SvxShapeCollection::hasElements() throw( uno::RuntimeException )
{
return getCount() != 0;
}
//----------------------------------------------------------------------
// XServiceInfo
//----------------------------------------------------------------------
::rtl::OUString SAL_CALL SvxShapeCollection::getImplementationName()
throw( uno::RuntimeException )
{
return getImplementationName_Static();
}
::rtl::OUString SvxShapeCollection::getImplementationName_Static()
{
return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.SvxShapeCollection") );
}
sal_Bool SAL_CALL SvxShapeCollection::supportsService( const ::rtl::OUString& ServiceName )
throw( uno::RuntimeException )
{
return comphelper::ServiceInfoHelper::supportsService( ServiceName, getSupportedServiceNames() );
}
uno::Sequence< ::rtl::OUString > SAL_CALL SvxShapeCollection::getSupportedServiceNames() throw( uno::RuntimeException )
{
return getSupportedServiceNames_Static();
}
uno::Sequence< ::rtl::OUString > SvxShapeCollection::getSupportedServiceNames_Static()
{
uno::Sequence< ::rtl::OUString > aSeq(2);
aSeq.getArray()[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.Shapes") );
aSeq.getArray()[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.ShapeCollection") );
return aSeq;
}
Reference< XInterface > SAL_CALL SvxShapeCollection_createInstance( const Reference< ::com::sun::star::lang::XMultiServiceFactory >& )
{
return *( new SvxShapeCollection() );
}