Kaydet (Commit) bf8ae88d authored tarafından Noel Power's avatar Noel Power

fix basic userform operation

re-instate the global containee list
üst f564a83b
......@@ -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 );
......
......@@ -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();
}
......@@ -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 )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment