diff options
author | Noel Power <noel.power@novell.com> | 2011-03-22 16:07:51 +0000 |
---|---|---|
committer | Noel Power <noel.power@novell.com> | 2011-03-22 16:12:02 +0000 |
commit | bf8ae88d9c3bf9ad11370c1f1d173fba1728005e (patch) | |
tree | 2429725a1a1e9ab6235d4efe0c8310885e580547 /toolkit/source | |
parent | f564a83b187d2527262f5fa62726eb9b2401c12b (diff) |
fix basic userform operation
re-instate the global containee list
Diffstat (limited to 'toolkit/source')
-rw-r--r-- | toolkit/source/controls/controlmodelcontainerbase.cxx | 85 | ||||
-rw-r--r-- | toolkit/source/controls/dialogcontrol.cxx | 81 |
2 files changed, 165 insertions, 1 deletions
diff --git a/toolkit/source/controls/controlmodelcontainerbase.cxx b/toolkit/source/controls/controlmodelcontainerbase.cxx index 07b208588835..3c7c51caeee2 100644 --- a/toolkit/source/controls/controlmodelcontainerbase.cxx +++ b/toolkit/source/controls/controlmodelcontainerbase.cxx @@ -495,7 +495,20 @@ void ControlModelContainerBase::replaceByName( const ::rtl::OUString& aName, con UnoControlModelHolderList::iterator aElementPos = ImplFindElement( aName ); if ( maModels.end() == aElementPos ) lcl_throwNoSuchElementException(); - + // Dialog behaviour is to have all containee names unique ( MSO Userform is the same ) + // With container controls you could have constructed an existing hierachy and are now + // add this to an existing container, in this case a name nested in the containment + // hierachy of the added control could contain a name clash, if we have access to the + // list of global names then recursively check for previously existing names ( we need + // to do this obviously before the 'this' objects container is updated + Reference< XNameContainer > xAllChildren( getPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ) ), UNO_QUERY ); + if ( xAllChildren.is() ) + { + // remove old control ( and children ) from global list of containees + updateUserFormChildren( xAllChildren, aName, Remove, uno::Reference< XControlModel >() ); + // Add new control ( and containees if they exist ) + updateUserFormChildren( xAllChildren, aName, Insert, xNewModel ); + } // stop listening at the old model stopControlListening( aElementPos->first ); Reference< XControlModel > xReplaced( aElementPos->first ); @@ -582,6 +595,17 @@ void ControlModelContainerBase::insertByName( const ::rtl::OUString& aName, cons if ( maModels.end() != aElementPos ) lcl_throwElementExistException(); + // Dialog behaviour is to have all containee names unique ( MSO Userform is the same ) + // With container controls you could have constructed an existing hierachy and are now + // add this to an existing container, in this case a name nested in the containment + // hierachy of the added control could contain a name clash, if we have access to the + // list of global names then we need to recursively check for previously existing + // names ( we need to do this obviously before the 'this' objects container is updated + // remove old control ( and children ) from global list of containees + Reference< XNameContainer > xAllChildren( getPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ) ), UNO_QUERY ); + + if ( xAllChildren.is() ) + updateUserFormChildren( xAllChildren, aName, Insert, xM ); maModels.push_back( UnoControlModelHolder( xM, aName ) ); mbGroupsUpToDate = sal_False; startControlListening( xM ); @@ -604,6 +628,15 @@ void ControlModelContainerBase::removeByName( const ::rtl::OUString& aName ) thr if ( maModels.end() == aElementPos ) lcl_throwNoSuchElementException(); + // Dialog behaviour is to have all containee names unique ( MSO Userform is the same ) + // With container controls you could have constructed an existing hierachy and are now + // removing this control from an existing container, in this case all nested names in + // the containment hierachy of the control to be removed need to be removed from the global + // names cache ( we need to do this obviously before the 'this' objects container is updated ) + Reference< XNameContainer > xAllChildren( getPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ) ), UNO_QUERY ); + if ( xAllChildren.is() ) + updateUserFormChildren( xAllChildren, aName, Remove, uno::Reference< XControlModel >() ); + ContainerEvent aEvent; aEvent.Source = *this; aEvent.Element <<= aElementPos->first; @@ -1858,3 +1891,53 @@ uno::Reference< graphic::XGraphic > ControlContainerBase::Impl_getGraphicFromURL return absoluteURL; } +void +ControlModelContainerBase::updateUserFormChildren( const Reference< XNameContainer >& xAllChildren, const rtl::OUString& aName, ChildOperation Operation, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >& xTarget ) throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException) +{ + if ( Operation < Insert || Operation > Remove ) + throw IllegalArgumentException(); + + if ( xAllChildren.is() ) + { + if ( Operation == Remove ) + { + Reference< XControlModel > xOldModel( xAllChildren->getByName( aName ), UNO_QUERY ); + xAllChildren->removeByName( aName ); + + Reference< XNameContainer > xChildContainer( xOldModel, UNO_QUERY ); + if ( xChildContainer.is() ) + { + Reference< XPropertySet > xProps( xChildContainer, UNO_QUERY ); + // container control is being removed from this container, reset the + // global list of containees + if ( xProps.is() ) + xProps->setPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ), uno::makeAny( uno::Reference< XNameContainer >() ) ); + Sequence< rtl::OUString > aChildNames = xChildContainer->getElementNames(); + for ( sal_Int32 index=0; index< aChildNames.getLength(); ++index ) + updateUserFormChildren( xAllChildren, aChildNames[ index ], Operation, Reference< XControlModel > () ); + } + } + else if ( Operation == Insert ) + { + xAllChildren->insertByName( aName, uno::makeAny( xTarget ) ); + Reference< XNameContainer > xChildContainer( xTarget, UNO_QUERY ); + if ( xChildContainer.is() ) + { + // container control is being added from this container, reset the + // global list of containees to point to the correct global list + Reference< XPropertySet > xProps( xChildContainer, UNO_QUERY ); + if ( xProps.is() ) + xProps->setPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ), uno::makeAny( xAllChildren ) ); + Sequence< rtl::OUString > aChildNames = xChildContainer->getElementNames(); + for ( sal_Int32 index=0; index< aChildNames.getLength(); ++index ) + { + Reference< XControlModel > xChildTarget( xChildContainer->getByName( aChildNames[ index ] ), UNO_QUERY ); + updateUserFormChildren( xAllChildren, aChildNames[ index ], Operation, xChildTarget ); + } + } + } + } + else + throw IllegalArgumentException(); +} + diff --git a/toolkit/source/controls/dialogcontrol.cxx b/toolkit/source/controls/dialogcontrol.cxx index 85bcf95062eb..9c444a1617c6 100644 --- a/toolkit/source/controls/dialogcontrol.cxx +++ b/toolkit/source/controls/dialogcontrol.cxx @@ -53,6 +53,8 @@ #include <vcl/graph.hxx> #include <vcl/image.hxx> #include <map> +#include <boost/unordered_map.hpp> +#include <cppuhelper/implbase1.hxx> #include <algorithm> #include <functional> #include "tools/urlobj.hxx" @@ -70,6 +72,82 @@ using namespace ::com::sun::star::util; #define PROPERTY_IMAGEURL ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ImageURL" )) #define PROPERTY_GRAPHIC ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Graphic" )) // + +// we probably will need both a hash of control models and hash of controls +// => use some template magic + +typedef ::cppu::WeakImplHelper1< container::XNameContainer > SimpleNameContainer_BASE; + +template< typename T > +class SimpleNamedThingContainer : public SimpleNameContainer_BASE +{ + typedef boost::unordered_map< rtl::OUString, Reference< T >, ::rtl::OUStringHash, + ::std::equal_to< ::rtl::OUString > > NamedThingsHash; + NamedThingsHash things; + ::osl::Mutex m_aMutex; +public: + // ::com::sun::star::container::XNameContainer, XNameReplace, XNameAccess + virtual void SAL_CALL replaceByName( const ::rtl::OUString& aName, const Any& aElement ) throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !hasByName( aName ) ) + throw NoSuchElementException(); + Reference< T > xElement; + if ( ! ( aElement >>= xElement ) ) + throw IllegalArgumentException(); + things[ aName ] = xElement; + } + virtual Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !hasByName( aName ) ) + throw NoSuchElementException(); + return uno::makeAny( things[ aName ] ); + } + virtual Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw(RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + Sequence< ::rtl::OUString > aResult( things.size() ); + typename NamedThingsHash::iterator it = things.begin(); + typename NamedThingsHash::iterator it_end = things.end(); + rtl::OUString* pName = aResult.getArray(); + for (; it != it_end; ++it, ++pName ) + *pName = it->first; + return aResult; + } + virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw(RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + return ( things.find( aName ) != things.end() ); + } + virtual void SAL_CALL insertByName( const ::rtl::OUString& aName, const Any& aElement ) throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( hasByName( aName ) ) + throw ElementExistException(); + Reference< T > xElement; + if ( ! ( aElement >>= xElement ) ) + throw IllegalArgumentException(); + things[ aName ] = xElement; + } + virtual void SAL_CALL removeByName( const ::rtl::OUString& aName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( !hasByName( aName ) ) + throw NoSuchElementException(); + things.erase( things.find( aName ) ); + } + virtual Type SAL_CALL getElementType( ) throw (RuntimeException) + { + return T::static_type( NULL ); + } + virtual ::sal_Bool SAL_CALL hasElements( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + return ( things.size() > 0 ); + } +}; + ////HELPER ::rtl::OUString getPhysicalLocation( const ::com::sun::star::uno::Any& rbase, const ::com::sun::star::uno::Any& rUrl ); @@ -99,6 +177,9 @@ UnoControlDialogModel::UnoControlDialogModel( const Reference< XMultiServiceFact aBool <<= (sal_Bool) sal_True; ImplRegisterProperty( BASEPROPERTY_MOVEABLE, aBool ); ImplRegisterProperty( BASEPROPERTY_CLOSEABLE, aBool ); + // #TODO separate class for 'UserForm' ( instead of re-using Dialog ? ) + uno::Reference< XNameContainer > xNameCont = new SimpleNamedThingContainer< XControlModel >(); + ImplRegisterProperty( BASEPROPERTY_USERFORMCONTAINEES, uno::makeAny( xNameCont ) ); } UnoControlDialogModel::UnoControlDialogModel( const UnoControlDialogModel& rModel ) |