[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