[Libreoffice-commits] .: toolkit/inc toolkit/source
Noel Power
noelp at kemper.freedesktop.org
Tue Mar 22 09:12:27 PDT 2011
toolkit/inc/toolkit/controls/controlmodelcontainerbase.hxx | 3
toolkit/source/controls/controlmodelcontainerbase.cxx | 85 ++++++++++++-
toolkit/source/controls/dialogcontrol.cxx | 81 ++++++++++++
3 files changed, 167 insertions(+), 2 deletions(-)
New commits:
commit e88065bbc3744a810633632e115237d128858eee
Author: Noel Power <noel.power at novell.com>
Date: Tue Mar 22 16:07:51 2011 +0000
fix basic userform operation
re-instate the global containee list
diff --git a/toolkit/inc/toolkit/controls/controlmodelcontainerbase.hxx b/toolkit/inc/toolkit/controls/controlmodelcontainerbase.hxx
index 6898f24..673f4d6 100644
--- a/toolkit/inc/toolkit/controls/controlmodelcontainerbase.hxx
+++ b/toolkit/inc/toolkit/controls/controlmodelcontainerbase.hxx
@@ -65,6 +65,7 @@ typedef ::cppu::AggImplInheritanceHelper8 < ControlModel_Base
class ControlModelContainerBase : public ControlModelContainer_IBase
{
public:
+ enum ChildOperation { Insert = 0, Remove };
// would like to make this typedef private, too, but the Forte 7 compiler does have
// problems with this .....
typedef ::std::pair< ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >, ::rtl::OUString >
@@ -97,13 +98,13 @@ protected:
sal_Int16 m_nTabPageId;
void Clone_Impl(ControlModelContainerBase& _rClone) const;
-
protected:
::com::sun::star::uno::Any ImplGetDefaultValue( sal_uInt16 nPropId ) const;
::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();
UnoControlModelHolderList::iterator ImplFindElement( const ::rtl::OUString& rName );
+ void updateUserFormChildren( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& xAllChildren, const rtl::OUString& aName, ChildOperation Operation, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel >& xTarget ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
public:
ControlModelContainerBase( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& i_factory );
ControlModelContainerBase( const ControlModelContainerBase& rModel );
diff --git a/toolkit/source/controls/controlmodelcontainerbase.cxx b/toolkit/source/controls/controlmodelcontainerbase.cxx
index a6afd56..02d7182 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 93aea99..f8d25d2 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 )
More information about the Libreoffice-commits
mailing list