summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Lohmann [pl] <Philipp.Lohmann@Sun.COM>2010-04-01 16:51:09 +0200
committerPhilipp Lohmann [pl] <Philipp.Lohmann@Sun.COM>2010-04-01 16:51:09 +0200
commitff9196d0581845f8e7cb686bf93930676ba301fe (patch)
tree82ccaa087cf88460ab2ccd8868b97ecf1ffac2f6
parent96c1ee636435baf4ea84e7bffd9acb0bc0e9b787 (diff)
gozer1: #161853# provide access to Window class and WindowArranger through XPropertySet
-rw-r--r--vcl/inc/vcl/arrange.hxx11
-rw-r--r--vcl/inc/vcl/window.hxx44
-rw-r--r--vcl/inc/vcl/wpropset.hxx66
-rw-r--r--vcl/prj/d.lst4
-rw-r--r--vcl/source/window/arrange.cxx62
-rw-r--r--vcl/source/window/makefile.mk1
-rw-r--r--vcl/source/window/window4.cxx150
-rw-r--r--vcl/source/window/wpropset.cxx345
8 files changed, 581 insertions, 102 deletions
diff --git a/vcl/inc/vcl/arrange.hxx b/vcl/inc/vcl/arrange.hxx
index 72e33f3c4bf8..24775995b013 100644
--- a/vcl/inc/vcl/arrange.hxx
+++ b/vcl/inc/vcl/arrange.hxx
@@ -104,6 +104,8 @@ namespace vcl
Rectangle m_aManagedArea;
long m_nOuterBorder;
+ rtl::OUString m_aIdentifier;
+
virtual Element* getElement( size_t i_nIndex ) = 0;
const Element* getConstElement( size_t i_nIndex ) const
{ return const_cast<WindowArranger*>(this)->getElement( i_nIndex ); }
@@ -149,6 +151,9 @@ namespace vcl
virtual bool isVisible() const; // true if any element is visible
+ virtual com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > getProperties() const;
+ virtual void setProperties( const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& );
+
sal_Int32 getExpandPriority( size_t i_nIndex ) const
{
const Element* pEle = getConstElement( i_nIndex );
@@ -195,6 +200,12 @@ namespace vcl
m_nOuterBorder = i_nBorder;
resize();
}
+
+ const rtl::OUString getIdentifier() const
+ { return m_aIdentifier; }
+
+ void setIdentifier( const rtl::OUString& i_rId )
+ { m_aIdentifier = i_rId; }
};
class VCL_DLLPUBLIC RowOrColumn : public WindowArranger
diff --git a/vcl/inc/vcl/window.hxx b/vcl/inc/vcl/window.hxx
index c757a20aece9..9516350527df 100644
--- a/vcl/inc/vcl/window.hxx
+++ b/vcl/inc/vcl/window.hxx
@@ -99,6 +99,13 @@ namespace accessibility {
namespace com {
namespace sun {
namespace star {
+namespace beans {
+ class PropertyValue;
+}}}}
+
+namespace com {
+namespace sun {
+namespace star {
namespace rendering {
class XCanvas;
class XSpriteCanvas;
@@ -1156,15 +1163,11 @@ public:
// ExtImpl
// layouting
- boost::shared_ptr< vcl::WindowArranger > getLayout();
+ boost::shared_ptr< vcl::WindowArranger > getLayout();
/* add a child Window
addWindow will do the following things
- insert the passed window into the child list (equivalent to i_pWin->SetParent( this ))
- - assign a name to the passed window for identification purposes
- the name is basically free style, only the '/' character must not be used as it is
- used for concatenation to form hierarchical names
- caution: the last non empty token repsctive to '/' will be the actual name used
- mark the window as "owned", meaning that the added Window will be destroyed by
the parent's desctructor.
This means: do not pass in member windows or stack objects here. Do not cause
@@ -1172,7 +1175,7 @@ public:
to avoid ownership pass i_bTakeOwnership as "false"
*/
- void addWindow( Window* i_pWin, const rtl::OUString& i_rName, bool i_bTakeOwnership = true );
+ void addWindow( Window* i_pWin, bool i_bTakeOwnership = true );
/* remove a child Window
the remove window functions will
@@ -1181,20 +1184,31 @@ public:
caution: ownership passes to the new parent or the caller, if the new parent was NULL
*/
Window* removeWindow( Window* i_pWin, Window* i_pNewParent = NULL );
- /* removeWindow by name will only work for direct children. if i_rName
- is a hierachical name, the last non empty token will be used to get the child window
+
+ /* return the identifier of this window
+ */
+ const rtl::OUString& getIdentifier() const;
+ /* set an identifier
+ identifiers have only loosely defined rules per se
+ in context of Window they must be unique over the window
+ hierarchy you'd like to find them again using the findWindow method
*/
- Window* removeWindow( const rtl::OUString& i_rName, Window* i_pNewParent = NULL );
+ void setIdentifier( const rtl::OUString& );
- /* find a child window by name
- the name passed here can be hierarchical to find descendants in any depth
- path delimiter is '/'
+ /* returns the first found descendant that matches
+ the passed identifier or NULL
*/
- Window* findWindow( const rtl::OUString& i_rName ) const;
+ Window* findWindow( const rtl::OUString& ) const;
- /* return the name of this window
+ /* get/set properties
+ this will contain window properties (like visible, enabled)
+ as well as properties of derived classes (e.g. text of Edit fields)
*/
- const rtl::OUString& getName() const;
+ virtual com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > getProperties() const;
+ /*
+ */
+ virtual void setProperties( const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& );
+
};
diff --git a/vcl/inc/vcl/wpropset.hxx b/vcl/inc/vcl/wpropset.hxx
new file mode 100644
index 000000000000..409b629496e6
--- /dev/null
+++ b/vcl/inc/vcl/wpropset.hxx
@@ -0,0 +1,66 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef VCL_WPROPSET_HXX
+#define VCL_WPROPSET_HXX
+
+#include "vcl/dllapi.h"
+
+#include "tools/link.hxx"
+#include "vcl/arrange.hxx"
+
+#include "com/sun/star/beans/XPropertySet.hpp"
+
+class VclWindowEvent;
+
+namespace vcl
+{
+ class WindowPropertySetData;
+ class WindowPropertySetListener;
+
+ class VCL_DLLPUBLIC WindowPropertySet
+ {
+ WindowPropertySetData* mpImpl;
+
+ void addWindowToSet( Window* );
+ void addLayoutToSet( const boost::shared_ptr<WindowArranger>& );
+ void setupProperties();
+
+ DECL_LINK( ChildEventListener, VclWindowEvent* );
+
+ void propertyChange( const com::sun::star::beans::PropertyChangeEvent& );
+ friend class vcl::WindowPropertySetListener;
+
+ public:
+ WindowPropertySet( Window* i_pTopWindow, bool i_bTakeOwnership );
+ ~WindowPropertySet();
+
+ com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > getPropertySet() const;
+ };
+}
+
+#endif
diff --git a/vcl/prj/d.lst b/vcl/prj/d.lst
index 8345b155ce58..0f429d0f5ec6 100644
--- a/vcl/prj/d.lst
+++ b/vcl/prj/d.lst
@@ -153,4 +153,6 @@ mkdir: %_DEST%\inc%_EXT%\vcl
..\inc\vcl\ppdparser.hxx %_DEST%\inc%_EXT%\vcl\ppdparser.hxx
..\inc\vcl\helper.hxx %_DEST%\inc%_EXT%\vcl\helper.hxx
..\inc\vcl\strhelper.hxx %_DEST%\inc%_EXT%\vcl\strhelper.hxx
-..\inc\vcl\lazydelete.hxx %_DEST%\inc%_EXT%\vcl\lazydelete.hxx \ No newline at end of file
+..\inc\vcl\lazydelete.hxx %_DEST%\inc%_EXT%\vcl\lazydelete.hxx
+..\inc\vcl\arrange.hxx %_DEST%\inc%_EXT%\vcl\arrange.hxx
+..\inc\vcl\wpropset.hxx %_DEST%\inc%_EXT%\vcl\wpropset.hxx \ No newline at end of file
diff --git a/vcl/source/window/arrange.cxx b/vcl/source/window/arrange.cxx
index 64db5426dc5b..2a01758220ed 100644
--- a/vcl/source/window/arrange.cxx
+++ b/vcl/source/window/arrange.cxx
@@ -35,9 +35,13 @@
#include "vcl/svdata.hxx"
#include "vcl/svapp.hxx"
+#include "com/sun/star/beans/PropertyValue.hpp"
+#include "com/sun/star/awt/Rectangle.hpp"
+
#include "osl/diagnose.h"
using namespace vcl;
+using namespace com::sun::star;
// ----------------------------------------
// vcl::WindowArranger
@@ -206,6 +210,64 @@ void WindowArranger::Element::setPosSize( const Point& i_rPos, const Size& i_rSi
m_pChild->setManagedArea( Rectangle( aPoint, aSize ) );
}
+uno::Sequence< beans::PropertyValue > WindowArranger::getProperties() const
+{
+ uno::Sequence< beans::PropertyValue > aRet( 3 );
+ aRet[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OuterBorder" ) );
+ aRet[0].Value = uno::makeAny( sal_Int32( getBorderValue( m_nOuterBorder ) ) );
+ aRet[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ManagedArea" ) );
+ awt::Rectangle aArea( m_aManagedArea.getX(), m_aManagedArea.getY(), m_aManagedArea.getWidth(), m_aManagedArea.getHeight() );
+ aRet[1].Value = uno::makeAny( aArea );
+ aRet[2].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Visible" ) );
+ aRet[2].Value = uno::makeAny( sal_Bool( isVisible() ) );
+ return aRet;
+}
+
+void WindowArranger::setProperties( const uno::Sequence< beans::PropertyValue >& i_rProps )
+{
+ const beans::PropertyValue* pProps = i_rProps.getConstArray();
+ bool bResize = false;
+ for( sal_Int32 i = 0; i < i_rProps.getLength(); i++ )
+ {
+ if( pProps[i].Name.equalsAscii( "OuterBorder" ) )
+ {
+ sal_Int32 nVal = 0;
+ if( pProps[i].Value >>= nVal )
+ {
+ if( getBorderValue( m_nOuterBorder ) != nVal )
+ {
+ m_nOuterBorder = nVal;
+ bResize = true;
+ }
+ }
+ }
+ else if( pProps[i].Name.equalsAscii( "ManagedArea" ) )
+ {
+ awt::Rectangle aArea( 0, 0, 0, 0 );
+ if( pProps[i].Value >>= aArea )
+ {
+ m_aManagedArea.setX( aArea.X );
+ m_aManagedArea.setY( aArea.Y );
+ m_aManagedArea.setWidth( aArea.Width );
+ m_aManagedArea.setHeight( aArea.Height );
+ bResize = true;
+ }
+ }
+ else if( pProps[i].Name.equalsAscii( "Visible" ) )
+ {
+ sal_Bool bVal = sal_False;
+ if( pProps[i].Value >>= bVal )
+ {
+ show( bVal, false );
+ bResize = true;
+ }
+ }
+ }
+ if( bResize )
+ resize();
+}
+
+
// ----------------------------------------
// vcl::RowOrColumn
//-----------------------------------------
diff --git a/vcl/source/window/makefile.mk b/vcl/source/window/makefile.mk
index e74623ad0a03..3614e166537c 100644
--- a/vcl/source/window/makefile.mk
+++ b/vcl/source/window/makefile.mk
@@ -90,6 +90,7 @@ SLOFILES= \
$(SLO)$/window2.obj \
$(SLO)$/window3.obj \
$(SLO)$/window4.obj \
+ $(SLO)$/wpropset.obj \
$(SLO)$/wrkwin.obj
# --- Targets ------------------------------------------------------
diff --git a/vcl/source/window/window4.cxx b/vcl/source/window/window4.cxx
index 587a99376943..577a573c2015 100644
--- a/vcl/source/window/window4.cxx
+++ b/vcl/source/window/window4.cxx
@@ -29,9 +29,15 @@
#include "vcl/window.hxx"
#include "vcl/window.h"
+#include "vcl/svdata.hxx"
#include "vcl/arrange.hxx"
+#include "com/sun/star/beans/PropertyValue.hpp"
+
#include <map>
+#include <vector>
+
+using namespace com::sun::star;
namespace vcl
{
@@ -45,60 +51,8 @@ namespace vcl
boost::shared_ptr< WindowArranger > mxLayout;
bool mbOwnedByParent;
- rtl::OUString maName;
- std::map< rtl::OUString, Window* > maNameToWindow;
- std::map< Window*, rtl::OUString > maWindowToName;
-
- void insertName( const rtl::OUString& i_rName, Window* i_pWin );
- void removeWindow( Window* );
- Window* findName( const rtl::OUString& ) const;
+ rtl::OUString maIdentifier;
};
-
- void ExtWindowImpl::insertName( const rtl::OUString& i_rName, Window* i_pWin )
- {
- OSL_ENSURE( maNameToWindow.find( i_rName ) == maNameToWindow.end(), "duplicate named window inserted" );
- maNameToWindow[ i_rName ] = i_pWin;
- maWindowToName[ i_pWin ] = i_rName;
- }
-
- void ExtWindowImpl::removeWindow( Window* i_pWin )
- {
- std::map< Window*, rtl::OUString >::iterator it = maWindowToName.find( i_pWin );
- if( it != maWindowToName.end() )
- {
- maNameToWindow.erase( it->second );
- maWindowToName.erase( it );
- }
- }
-
- Window* ExtWindowImpl::findName( const rtl::OUString& i_rName ) const
- {
- std::map< rtl::OUString, Window* >::const_iterator it = maNameToWindow.find( i_rName );
- return it != maNameToWindow.end() ? it->second : NULL;
- }
-}
-
-static rtl::OUString getLastNameToken( const rtl::OUString& i_rName )
-{
- sal_Int32 nIndex = i_rName.lastIndexOf( sal_Unicode('/') );
- if( nIndex != -1 )
- {
- // if this is not an empty token, that is the name
- if( nIndex < i_rName.getLength()-1 )
- return i_rName.copy( nIndex+1 );
- // we need to search backward
- const sal_Unicode* pStr = i_rName.getStr();
- while( nIndex >= 0 && pStr[nIndex] == '/' )
- nIndex--;
- if( nIndex < 0 ) // give up
- return rtl::OUString();
- // search backward to next '/' or beginning
- sal_Int32 nBeginIndex = nIndex-1;
- while( nBeginIndex >= 0 && pStr[nBeginIndex] != '/' )
- nBeginIndex--;
- return i_rName.copy( nBeginIndex+1, nIndex-nBeginIndex );
- }
- return rtl::OUString( i_rName );
}
void Window::ImplDeleteOwnedChildren()
@@ -163,7 +117,7 @@ boost::shared_ptr< vcl::WindowArranger > Window::getLayout()
return xRet;
}
-void Window::addWindow( Window* i_pWin, const rtl::OUString& i_rName, bool i_bTakeOwnership )
+void Window::addWindow( Window* i_pWin, bool i_bTakeOwnership )
{
vcl::ExtWindowImpl* pImpl = ImplGetExtWindowImpl();
if( pImpl && i_pWin )
@@ -173,11 +127,6 @@ void Window::addWindow( Window* i_pWin, const rtl::OUString& i_rName, bool i_bTa
{
i_pWin->SetParent( this );
pChildImpl->mbOwnedByParent = i_bTakeOwnership;
- rtl::OUString aName( getLastNameToken( i_rName ) );
- if( aName.getLength() )
- {
- pImpl->insertName( aName, i_pWin );
- }
}
}
}
@@ -195,7 +144,6 @@ Window* Window::removeWindow( Window* i_pWin, Window* i_pNewParent )
{
if( ! i_pNewParent )
pChildImpl->mbOwnedByParent = false;
- pImpl->removeWindow( i_pWin );
i_pWin->SetParent( i_pNewParent );
pRet = i_pWin;
}
@@ -204,43 +152,73 @@ Window* Window::removeWindow( Window* i_pWin, Window* i_pNewParent )
return pRet;
}
-Window* Window::removeWindow( const rtl::OUString& i_rName, Window* i_pNewParent )
+Window* Window::findWindow( const rtl::OUString& i_rIdentifier ) const
{
- Window* pRet = NULL;
- vcl::ExtWindowImpl* pImpl = ImplGetExtWindowImpl();
- if( pImpl )
+ if( getIdentifier() == i_rIdentifier )
+ return const_cast<Window*>(this);
+
+ Window* pChild = mpWindowImpl->mpFirstChild;
+ while ( pChild )
{
- rtl::OUString aName( getLastNameToken( i_rName ) );
- pRet = pImpl->findName( aName );
- pRet = removeWindow( pRet, i_pNewParent );
+ Window* pResult = pChild->findWindow( i_rIdentifier );
+ if( pResult )
+ return pResult;
+ pChild = pChild->mpWindowImpl->mpNext;
}
- return pRet;
+
+ return NULL;
+}
+
+const rtl::OUString& Window::getIdentifier() const
+{
+ static rtl::OUString aEmptyStr;
+
+ return (mpWindowImpl && mpWindowImpl->mpExtImpl) ? mpWindowImpl->mpExtImpl->maIdentifier : aEmptyStr;
}
-Window* Window::findWindow( const rtl::OUString& i_rName ) const
+void Window::setIdentifier( const rtl::OUString& i_rIdentifier )
{
vcl::ExtWindowImpl* pImpl = ImplGetExtWindowImpl();
- Window* pSearch = const_cast<Window*>(this);
if( pImpl )
+ pImpl->maIdentifier = i_rIdentifier;
+}
+
+void Window::setProperties( const uno::Sequence< beans::PropertyValue >& i_rProps )
+{
+ const beans::PropertyValue* pVals = i_rProps.getConstArray();
+ for( sal_Int32 i = 0; i < i_rProps.getLength(); i++ )
{
- sal_Int32 nIndex = 0;
- while( nIndex && pSearch )
+ if( pVals[i].Name.equalsAscii( "Enabled" ) )
{
- rtl::OUString aName( i_rName.getToken( 0, '/', nIndex ) );
- if( aName.getLength() )
- {
- pSearch = pImpl->findName( aName );
- if( pSearch )
- {
- pImpl = pSearch->ImplGetExtWindowImpl();
- if( ! pImpl )
- pSearch = NULL;
- }
- }
+ sal_Bool bVal = sal_True;
+ if( pVals[i].Value >>= bVal )
+ Enable( bVal );
+ }
+ else if( pVals[i].Name.equalsAscii( "Visible" ) )
+ {
+ sal_Bool bVal = sal_True;
+ if( pVals[i].Value >>= bVal )
+ Show( bVal );
+ }
+ else if( pVals[i].Name.equalsAscii( "Text" ) )
+ {
+ rtl::OUString aText;
+ if( pVals[i].Value >>= aText )
+ SetText( aText );
}
}
- else
- pSearch = NULL;
- return pSearch != this ? pSearch : NULL;
+}
+
+uno::Sequence< beans::PropertyValue > Window::getProperties() const
+{
+ uno::Sequence< beans::PropertyValue > aProps( 3 );
+ aProps[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Enabled" ) );
+ aProps[0].Value = uno::makeAny( sal_Bool( IsEnabled() ) );
+ aProps[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Visible" ) );
+ aProps[1].Value = uno::makeAny( sal_Bool( IsVisible() ) );
+ aProps[2].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Text" ) );
+ aProps[2].Value = uno::makeAny( rtl::OUString( GetText() ) );
+
+ return aProps;
}
diff --git a/vcl/source/window/wpropset.cxx b/vcl/source/window/wpropset.cxx
new file mode 100644
index 000000000000..98c8a5b1dcfb
--- /dev/null
+++ b/vcl/source/window/wpropset.cxx
@@ -0,0 +1,345 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_vcl.hxx"
+
+#include "vcl/wpropset.hxx"
+#include "vcl/window.hxx"
+#include "vcl/vclevent.hxx"
+#include "vcl/svdata.hxx"
+
+#include "com/sun/star/lang/XMultiServiceFactory.hpp"
+#include "com/sun/star/beans/PropertyValue.hpp"
+#include "com/sun/star/beans/PropertyAttribute.hpp"
+#include "com/sun/star/beans/XPropertySet.hpp"
+#include "com/sun/star/beans/XPropertyContainer.hpp"
+#include "com/sun/star/beans/XPropertyAccess.hpp"
+
+#include "cppuhelper/basemutex.hxx"
+#include "cppuhelper/compbase1.hxx"
+
+#include <map>
+
+using namespace vcl;
+using namespace com::sun::star;
+
+/*
+
+TODO:
+- release solarmutex during outside UNO calls
+- in ChildEventListener protect against reentry by using PostUserEvent
+
+*/
+
+class vcl::WindowPropertySetListener :
+ public cppu::BaseMutex,
+ public cppu::WeakComponentImplHelper1< com::sun::star::beans::XPropertyChangeListener >,
+ private boost::noncopyable
+{
+ WindowPropertySet* mpParent;
+ bool mbSuspended;
+public:
+ WindowPropertySetListener( WindowPropertySet* pParent )
+ : cppu::WeakComponentImplHelper1< com::sun::star::beans::XPropertyChangeListener >( m_aMutex )
+ , mpParent( pParent )
+ , mbSuspended( false )
+ {}
+
+ virtual ~WindowPropertySetListener()
+ {
+ }
+
+ virtual void SAL_CALL disposing( const lang::EventObject& ) throw()
+ {
+ }
+
+ virtual void SAL_CALL propertyChange( const beans::PropertyChangeEvent& i_rEvent ) throw()
+ {
+ if( ! mbSuspended )
+ mpParent->propertyChange( i_rEvent );
+ }
+
+ void suspend( bool i_bSuspended )
+ {
+ mbSuspended = i_bSuspended;
+ }
+};
+
+class vcl::WindowPropertySetData
+{
+public:
+
+ struct PropertyMapEntry
+ {
+ Window* mpWindow;
+ boost::shared_ptr<WindowArranger> mpLayout;
+ uno::Sequence< beans::PropertyValue > maSavedValues;
+
+ PropertyMapEntry( Window* i_pWindow = NULL,
+ const boost::shared_ptr<WindowArranger>& i_pLayout = boost::shared_ptr<WindowArranger>() )
+ : mpWindow( i_pWindow )
+ , mpLayout( i_pLayout )
+ {}
+
+ uno::Sequence< beans::PropertyValue > getProperties() const
+ {
+ if( mpWindow )
+ return mpWindow->getProperties();
+ else if( mpLayout.get() )
+ return mpLayout->getProperties();
+ return uno::Sequence< beans::PropertyValue >();
+ }
+
+ void setProperties( const uno::Sequence< beans::PropertyValue >& i_rProps ) const
+ {
+ if( mpWindow )
+ mpWindow->setProperties( i_rProps );
+ else if( mpLayout.get() )
+ mpLayout->setProperties( i_rProps );
+ }
+ };
+
+ Window* mpTopWindow;
+ bool mbOwner;
+ std::map< rtl::OUString, PropertyMapEntry > maProperties;
+ uno::Reference< beans::XPropertySet > mxPropSet;
+ uno::Reference< beans::XPropertyAccess > mxPropSetAccess;
+ uno::Reference< beans::XPropertyChangeListener > mxListener;
+ vcl::WindowPropertySetListener* mpListener;
+
+ WindowPropertySetData()
+ : mpTopWindow( NULL )
+ , mbOwner( false )
+ , mpListener( NULL )
+ {}
+
+ ~WindowPropertySetData()
+ {
+ // release layouters, possibly interface properties before destroying
+ // the involved parent to be on the safe side
+ maProperties.clear();
+ if( mbOwner )
+ delete mpTopWindow;
+ }
+};
+
+static rtl::OUString getIdentifiedPropertyName( const rtl::OUString& i_rIdentifier, const rtl::OUString& i_rName )
+{
+ rtl::OUStringBuffer aBuf( i_rIdentifier.getLength() + 1 + i_rName.getLength() );
+ aBuf.append( i_rIdentifier );
+ aBuf.append( sal_Unicode( '#' ) );
+ aBuf.append( i_rName );
+ return aBuf.makeStringAndClear();
+}
+
+static void spliceIdentifiedPropertyName( const rtl::OUString& i_rIdentifiedPropName,
+ rtl::OUString& o_rIdentifier,
+ rtl::OUString& o_rPropName )
+{
+ sal_Int32 nIndex = 0;
+ o_rIdentifier = i_rIdentifiedPropName.getToken( 0, sal_Unicode( '#' ), nIndex );
+ if( nIndex != -1 )
+ o_rPropName = i_rIdentifiedPropName.copy( nIndex );
+ else
+ o_rPropName = rtl::OUString();
+}
+
+WindowPropertySet::WindowPropertySet( Window* i_pTopWindow, bool i_bTakeOwnership )
+: mpImpl( new vcl::WindowPropertySetData )
+{
+ mpImpl->mpTopWindow = i_pTopWindow;
+ mpImpl->mbOwner = i_bTakeOwnership;
+
+ mpImpl->mpTopWindow->AddChildEventListener( LINK( this, WindowPropertySet, ChildEventListener ) );
+
+ mpImpl->mxPropSet = uno::Reference< beans::XPropertySet >(
+ ImplGetSVData()->maAppData.mxMSF->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.PropertyBag" ) ) ),
+ uno::UNO_QUERY );
+ OSL_ENSURE( mpImpl->mxPropSet.is(), "could not create instance of com.sun.star.beans.PropertyBag" );
+ mpImpl->mxPropSetAccess = uno::Reference< beans::XPropertyAccess >( mpImpl->mxPropSet, uno::UNO_QUERY );
+ OSL_ENSURE( mpImpl->mxPropSet.is(), "could not query XPropertyAccess interface" );
+ if( ! mpImpl->mxPropSetAccess.is() )
+ mpImpl->mxPropSet.clear();
+
+ addWindowToSet( i_pTopWindow );
+
+ setupProperties();
+
+ if( mpImpl->mxPropSet.is() )
+ {
+ mpImpl->mxListener.set( mpImpl->mpListener = new WindowPropertySetListener( this ) );
+ }
+}
+
+WindowPropertySet::~WindowPropertySet()
+{
+ mpImpl->mpTopWindow->RemoveChildEventListener( LINK( this, WindowPropertySet, ChildEventListener ) );
+
+ delete mpImpl;
+ mpImpl = NULL;
+}
+
+uno::Reference< beans::XPropertySet > WindowPropertySet::getPropertySet() const
+{
+ return mpImpl->mxPropSet;
+}
+
+void WindowPropertySet::addLayoutToSet( const boost::shared_ptr< WindowArranger >& i_pLayout )
+{
+ if( i_pLayout.get() )
+ {
+ if( i_pLayout->getIdentifier().getLength() )
+ {
+ WindowPropertySetData::PropertyMapEntry& rEntry = mpImpl->maProperties[ i_pLayout->getIdentifier() ];
+ OSL_ENSURE( rEntry.mpWindow == 0 && rEntry.mpLayout.get() == 0, "inserted layout has duplicate name" );
+ rEntry.mpWindow = NULL;
+ rEntry.mpLayout = i_pLayout;
+ rEntry.maSavedValues = i_pLayout->getProperties();
+ }
+ // insert child layouts
+ size_t nChildren = i_pLayout->countElements();
+ for( size_t i = 0; i < nChildren; i++ )
+ addLayoutToSet( i_pLayout->getChild( i ) );
+ }
+}
+
+void WindowPropertySet::addWindowToSet( Window* i_pWindow )
+{
+ if( i_pWindow->getIdentifier().getLength() ) // no name, no properties
+ {
+ WindowPropertySetData::PropertyMapEntry& rEntry = mpImpl->maProperties[ i_pWindow->getIdentifier() ];
+ OSL_ENSURE( rEntry.mpWindow == 0 && rEntry.mpLayout.get() == 0, "inserted window has duplicate name" );
+ rEntry.mpWindow = i_pWindow;
+ rEntry.mpLayout.reset();
+ rEntry.maSavedValues = i_pWindow->getProperties();
+ }
+ addLayoutToSet( i_pWindow->getLayout() );
+
+ Window* pWin = i_pWindow->GetWindow( WINDOW_FIRSTCHILD );
+ while( pWin )
+ {
+ addWindowToSet( pWin );
+ pWin = pWin->GetWindow( WINDOW_NEXT );
+ }
+}
+
+void WindowPropertySet::setupProperties()
+{
+ uno::Reference< beans::XPropertyContainer > xCont( mpImpl->mxPropSet, uno::UNO_QUERY );
+ OSL_ENSURE( xCont.is(), "could not get XPropertyContainer interface" );
+ if( ! xCont.is() )
+ return;
+
+ for( std::map< rtl::OUString, WindowPropertySetData::PropertyMapEntry >::iterator it
+ = mpImpl->maProperties.begin(); it != mpImpl->maProperties.end(); ++it )
+ {
+ uno::Sequence< beans::PropertyValue > aOutsideValues( it->second.maSavedValues );
+ beans::PropertyValue* pVal = aOutsideValues.getArray();
+ for( sal_Int32 i = 0; i < aOutsideValues.getLength(); i++ )
+ {
+ pVal[i].Name = getIdentifiedPropertyName( it->first, pVal[i].Name );
+ xCont->addProperty( pVal[i].Name,
+ beans::PropertyAttribute::BOUND | beans:: PropertyAttribute::CONSTRAINED,
+ pVal[i].Value
+ );
+ }
+ }
+}
+
+void WindowPropertySet::propertyChange( const beans::PropertyChangeEvent& i_rEvent )
+{
+ rtl::OUString aIdentifier, aProperty;
+ spliceIdentifiedPropertyName( i_rEvent.PropertyName, aIdentifier, aProperty );
+ std::map< rtl::OUString, WindowPropertySetData::PropertyMapEntry >::iterator it =
+ mpImpl->maProperties.find( aIdentifier );
+ if( it != mpImpl->maProperties.end() )
+ {
+ uno::Sequence< beans::PropertyValue > aSet( 1 );
+ aSet[0].Name = aProperty;
+ aSet[0].Value = i_rEvent.NewValue;
+ it->second.setProperties( aSet );
+ }
+}
+
+IMPL_LINK( vcl::WindowPropertySet, ChildEventListener, VclWindowEvent*, pEvent )
+{
+ // find window in our properties
+ std::map< rtl::OUString, WindowPropertySetData::PropertyMapEntry >::iterator it
+ = mpImpl->maProperties.find( pEvent->GetWindow()->getIdentifier() );
+ if( it != mpImpl->maProperties.end() ) // this is valid, some unnamed child may have sent an event
+ {
+ ULONG nId = pEvent->GetId();
+ // check if anything interesting happened
+ if(
+ // general windowy things
+ nId == VCLEVENT_WINDOW_SHOW ||
+ nId == VCLEVENT_WINDOW_HIDE ||
+ nId == VCLEVENT_WINDOW_ENABLED ||
+ nId == VCLEVENT_WINDOW_DISABLED ||
+ // button thingies
+ nId == VCLEVENT_BUTTON_CLICK ||
+ nId == VCLEVENT_PUSHBUTTON_TOGGLE ||
+ nId == VCLEVENT_RADIOBUTTON_TOGGLE ||
+ nId == VCLEVENT_CHECKBOX_TOGGLE ||
+ // listbox
+ nId == VCLEVENT_LISTBOX_SELECT ||
+ // edit
+ nId == VCLEVENT_EDIT_MODIFY
+ )
+ {
+ WindowPropertySetData::PropertyMapEntry& rEntry = it->second;
+ // collect changes
+ uno::Sequence< beans::PropertyValue > aNewProps( rEntry.getProperties() );
+ uno::Sequence< beans::PropertyValue > aNewPropsOut( aNewProps );
+
+ // translate to identified properties
+ beans::PropertyValue* pValues = aNewPropsOut.getArray();
+ for( sal_Int32 i = 0; i < aNewPropsOut.getLength(); i++ )
+ pValues[i].Name = getIdentifiedPropertyName( it->first, pValues[i].Name );
+
+ // broadcast changes
+ bool bWasVeto = false;
+ mpImpl->mpListener->suspend( true );
+ try
+ {
+ mpImpl->mxPropSetAccess->setPropertyValues( aNewPropsOut );
+ }
+ catch( beans::PropertyVetoException& )
+ {
+ bWasVeto = true;
+ }
+ mpImpl->mpListener->suspend( false );
+
+ if( ! bWasVeto ) // changes accepted ?
+ rEntry.maSavedValues = rEntry.getProperties();
+ else // no, reset
+ rEntry.setProperties( rEntry.maSavedValues );
+ }
+ }
+
+ return 0;
+}