summaryrefslogtreecommitdiff
path: root/toolkit
diff options
context:
space:
mode:
authorKurt Zenker <kz@openoffice.org>2008-03-06 10:48:47 +0000
committerKurt Zenker <kz@openoffice.org>2008-03-06 10:48:47 +0000
commit672dde158f1a0b1d7e66d87fabc64cbf0a8b7182 (patch)
tree7818be7263bbe7ac29dcf70aa0137cda5496d4be /toolkit
parente17ddba9755523f757f624e58fdbc86fe3c07844 (diff)
INTEGRATION: CWS layout_DEV300 (1.1.2); FILE ADDED
2008/02/08 18:44:44 jcn 1.1.2.1: Initial toolkit import from ee9a2fcc29d7e2f01cc80ef7c13bf7bc7d55ae7e. layout/source/awt -> toolkit/source/awt layout/source/core -> toolkit/source/layout layout/source/wrapper -> toolkit/source/vclcompat layout/inc/layout -> toolkit/inc/layout layout/source/inc -> toolkit/inc/layout layout/workben -> toolkit/workben/layout That's ooo-build trunk r11539 @ ooh680-m5/src680-m245.
Diffstat (limited to 'toolkit')
-rw-r--r--toolkit/source/layout/flow.cxx176
-rw-r--r--toolkit/source/layout/flow.hxx65
-rw-r--r--toolkit/source/layout/import.cxx208
-rw-r--r--toolkit/source/layout/import.hxx283
-rw-r--r--toolkit/source/layout/proplist.hxx34
-rw-r--r--toolkit/source/layout/root.cxx329
-rw-r--r--toolkit/source/layout/root.hxx127
-rw-r--r--toolkit/source/layout/table.cxx326
-rw-r--r--toolkit/source/layout/table.hxx79
-rw-r--r--toolkit/source/layout/timer.cxx121
-rw-r--r--toolkit/source/layout/timer.hxx22
11 files changed, 1770 insertions, 0 deletions
diff --git a/toolkit/source/layout/flow.cxx b/toolkit/source/layout/flow.cxx
new file mode 100644
index 000000000000..c8573c82a4fa
--- /dev/null
+++ b/toolkit/source/layout/flow.cxx
@@ -0,0 +1,176 @@
+#include "flow.hxx"
+
+#include <sal/macros.h>
+
+namespace layoutimpl
+{
+
+using namespace css;
+
+bool Flow::ChildData::isVisible()
+{
+ return xChild.is();
+}
+
+Flow::Flow()
+ : Container()
+ , mnSpacing( 0 )
+ , mbHomogeneous( false )
+{
+ addProp( RTL_CONSTASCII_USTRINGPARAM( "Homogeneous" ),
+ ::getCppuType( static_cast< const sal_Bool* >( NULL ) ),
+ &mbHomogeneous );
+ addProp( RTL_CONSTASCII_USTRINGPARAM( "Spacing" ),
+ ::getCppuType( static_cast< const sal_Int32* >( NULL ) ),
+ &mnSpacing );
+}
+
+void SAL_CALL
+Flow::addChild( const uno::Reference< awt::XLayoutConstrains >& xChild )
+ throw (uno::RuntimeException, css::awt::MaxChildrenException)
+{
+ if ( xChild.is() )
+ {
+ ChildData *pData = new ChildData();
+ pData->xChild = xChild;
+ maChildren.push_back( pData );
+
+ setChildParent( xChild );
+ queueResize();
+ }
+}
+
+void SAL_CALL
+Flow::removeChild( const css::uno::Reference< css::awt::XLayoutConstrains >& xChild )
+ throw (css::uno::RuntimeException)
+{
+ for( std::list< ChildData * >::iterator it = maChildren.begin();
+ it != maChildren.end(); it++ )
+ {
+ if ( (*it)->xChild == xChild )
+ {
+ delete *it;
+ maChildren.erase( it );
+
+ unsetChildParent( xChild );
+ queueResize();
+ break;
+ }
+ }
+}
+
+css::uno::Sequence< css::uno::Reference < css::awt::XLayoutConstrains > > SAL_CALL
+Flow::getChildren()
+ throw (css::uno::RuntimeException)
+{
+ uno::Sequence< uno::Reference< awt::XLayoutConstrains > > children( maChildren.size() );
+ unsigned int i = 0;
+ for( std::list< ChildData * >::iterator it = maChildren.begin();
+ it != maChildren.end(); it++, i++ )
+ children[i] = (*it)->xChild;
+
+ return children;
+}
+
+uno::Reference< beans::XPropertySet > SAL_CALL
+Flow::getChildProperties( const uno::Reference< awt::XLayoutConstrains >& /*xChild*/ )
+ throw (uno::RuntimeException)
+{
+ return uno::Reference< beans::XPropertySet >();
+}
+
+css::awt::Size
+Flow::calculateSize( long nMaxWidth )
+{
+ long nNeedHeight = 0;
+
+ std::list<ChildData *>::const_iterator it;
+ mnEachWidth = 0;
+ // first pass, for homogeneous property
+ for (it = maChildren.begin(); it != maChildren.end(); it++)
+ {
+ if ( !(*it)->isVisible() )
+ continue;
+ (*it)->aRequisition = (*it)->xChild->getMinimumSize();
+ if ( mbHomogeneous )
+ mnEachWidth = SAL_MAX( mnEachWidth, (*it)->aRequisition.Width );
+ }
+
+ long nRowWidth = 0, nRowHeight = 0;
+ for (it = maChildren.begin(); it != maChildren.end(); it++)
+ {
+ if ( !(*it)->isVisible() )
+ continue;
+
+ awt::Size aChildSize = (*it)->aRequisition;
+ if ( mbHomogeneous )
+ aChildSize.Width = mnEachWidth;
+
+ if ( nMaxWidth && nRowWidth > 0 && nRowWidth + aChildSize.Width > nMaxWidth )
+ {
+ nRowWidth = 0;
+ nNeedHeight += nRowHeight;
+ nRowHeight = 0;
+ }
+ nRowHeight = SAL_MAX( nRowHeight, aChildSize.Height );
+ nRowWidth += aChildSize.Width;
+ }
+ nNeedHeight += nRowHeight;
+
+ return awt::Size( nRowWidth, nNeedHeight );
+}
+
+awt::Size SAL_CALL
+Flow::getMinimumSize() throw(uno::RuntimeException)
+{
+ return maRequisition = calculateSize( 0 );
+}
+
+sal_Bool SAL_CALL
+Flow::hasHeightForWidth()
+ throw(css::uno::RuntimeException)
+{
+ return true;
+}
+
+sal_Int32 SAL_CALL
+Flow::getHeightForWidth( sal_Int32 nWidth )
+ throw(css::uno::RuntimeException)
+{
+ return calculateSize( nWidth ).Height;
+}
+
+void SAL_CALL
+Flow::allocateArea( const css::awt::Rectangle &rArea )
+ throw (css::uno::RuntimeException)
+{
+ maAllocation = rArea;
+
+ std::list<ChildData *>::const_iterator it;
+ long nX = 0, nY = 0, nRowHeight = 0;
+ for (it = maChildren.begin(); it != maChildren.end(); it++)
+ {
+ ChildData *child = *it;
+ if ( !child->isVisible() )
+ continue;
+
+ awt::Size aChildSize( child->aRequisition );
+ if ( mbHomogeneous )
+ aChildSize.Width = mnEachWidth;
+
+ if ( nX > 0 && nX + aChildSize.Width > rArea.Width )
+ {
+ nX = 0;
+ nY += nRowHeight;
+ nRowHeight = 0;
+ }
+ nRowHeight = SAL_MAX( nRowHeight, aChildSize.Height );
+
+ allocateChildAt( child->xChild,
+ awt::Rectangle( rArea.X + nX, rArea.Y + nY, aChildSize.Width, aChildSize.Height ) );
+
+ nX += aChildSize.Width;
+ }
+}
+
+} // namespace layoutimpl
diff --git a/toolkit/source/layout/flow.hxx b/toolkit/source/layout/flow.hxx
new file mode 100644
index 000000000000..8e21e8659fea
--- /dev/null
+++ b/toolkit/source/layout/flow.hxx
@@ -0,0 +1,65 @@
+#ifndef CORE_FLOW_HXX
+#define CORE_FLOW_HXX
+
+#include "container.hxx"
+
+#include <list>
+
+namespace layoutimpl
+{
+
+class Flow : public Container
+{
+protected:
+ // Box properties (i.e. affect all children)
+ sal_Int32 mnSpacing;
+ sal_Bool mbHomogeneous;
+
+ // Children properties
+ struct ChildData
+ {
+ css::awt::Size aRequisition;
+ css::uno::Reference< css::awt::XLayoutConstrains > xChild;
+ css::uno::Reference< css::beans::XPropertySet > xProps;
+ bool isVisible();
+ };
+ std::list< ChildData * > maChildren;
+ long mnEachWidth; // on homogeneous, the width of every child
+
+public:
+ Flow();
+
+ // css::awt::XLayoutContainer
+ virtual void SAL_CALL addChild( const css::uno::Reference< css::awt::XLayoutConstrains >& Child )
+ throw (css::uno::RuntimeException, css::awt::MaxChildrenException);
+ virtual void SAL_CALL removeChild( const css::uno::Reference< css::awt::XLayoutConstrains >& Child )
+ throw (css::uno::RuntimeException);
+
+ virtual css::uno::Sequence< css::uno::Reference
+ < css::awt::XLayoutConstrains > > SAL_CALL getChildren()
+ throw (css::uno::RuntimeException);
+
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getChildProperties(
+ const css::uno::Reference< css::awt::XLayoutConstrains >& Child )
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL allocateArea( const css::awt::Rectangle &rArea )
+ throw (css::uno::RuntimeException);
+
+ virtual css::awt::Size SAL_CALL getMinimumSize()
+ throw(css::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL hasHeightForWidth()
+ throw(css::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL getHeightForWidth( sal_Int32 nWidth )
+ throw(css::uno::RuntimeException);
+
+PROPHELPER_SET_INFO
+
+private:
+ // shared between getMinimumSize() and getHeightForWidth()
+ css::awt::Size calculateSize( long nMaxWidth );
+};
+
+} // namespace layoutimpl
+
+#endif /*FLOW_CORE_HXX*/
diff --git a/toolkit/source/layout/import.cxx b/toolkit/source/layout/import.cxx
new file mode 100644
index 000000000000..ec0814babeb6
--- /dev/null
+++ b/toolkit/source/layout/import.cxx
@@ -0,0 +1,208 @@
+#include "import.hxx"
+
+#include <com/sun/star/awt/XButton.hpp>
+#include <com/sun/star/awt/XDialog2.hpp>
+#include <tools/debug.hxx>
+
+#include "root.hxx"
+#include "helper.hxx"
+#include "dialogbuttonhbox.hxx"
+
+
+#define XMLNS_LAYOUT_URI "http://openoffice.org/2007/layout"
+#define XMLNS_CONTAINER_URI "http://openoffice.org/2007/layout/container"
+
+namespace layoutimpl
+{
+using namespace css;
+
+using ::rtl::OUString;
+
+ElementBase::~ElementBase()
+SAL_THROW( () )
+{
+ //delete mpImport;
+ //mpImport = 0;
+}
+
+//** parser
+WidgetElement::WidgetElement ( sal_Int32 nUid, const OUString &rName,
+ uno::Reference <xml::input::XAttributes> const &attributes,
+ ElementBase *pParent,
+ ImportContext *pImport)
+SAL_THROW (())
+: ElementBase( nUid, rName, attributes, pParent, pImport )
+{
+ OUString name = rName.toAsciiLowerCase();
+
+ PropList aProps;
+ propsFromAttributes( attributes, aProps, pImport->XMLNS_LAYOUT_UID );
+
+ OUString aId;
+ findAndRemove( "id", aProps, aId );
+ OUString aLang;
+ findAndRemove( "xml-lang", aProps, aLang );
+
+ {
+//DEBUG
+ uno::Reference< awt::XLayoutConstrains > xParent;
+ if ( pParent )
+ xParent = ((WidgetElement *) pParent)->mpWidget->getPeer();
+
+
+ mpWidget = pImport->mrRoot.create( aId, name,
+ getAttributeProps( aProps ), uno::Reference< awt::XLayoutContainer >( xParent, uno::UNO_QUERY ) );
+
+ }
+
+ // TODO: handle with non-existing widgets
+
+ mpWidget->setProperties( aProps );
+
+ uno::Reference< awt::XDialog2 > xDialog( mpWidget->getPeer(), uno::UNO_QUERY );
+ if ( xDialog.is() )
+ {
+ OUString aTitle;
+ if ( findAndRemove( "title", aProps, aTitle ) )
+ xDialog->setTitle( aTitle );
+ } // DEBUG:
+ else if ( pParent == NULL )
+ {
+ DBG_ERROR( "Fatal error: top node isn't a dialog" );
+ }
+
+ bool bOrdering;
+ OUString aOrdering;
+ bOrdering = findAndRemove( "ordering", aProps, aOrdering );
+ if ( DialogButtonHBox *b = dynamic_cast<DialogButtonHBox *> ( mpWidget->getPeer().get() ) )
+ {
+ if ( bOrdering )
+ b->setOrdering ( aOrdering );
+ }
+
+#ifdef IMPORT_RADIOGROUP
+ bool bSetRadioGroup, bSetTitle;
+ OUString aRadioGroup, aTitle;
+ bSetRadioGroup = findAndRemove( "radiogroup", aProps, aRadioGroup );
+ bSetTitle = findAndRemove( "title", aProps, aTitle );
+
+ setProperties( mxPeer, aProps );
+
+ // we need to add radio buttons to the group after their properties are
+ // set, so we can check if they should be the one selected by default or not.
+ // And the state changed event isn't fired when changing properties.
+ if ( bSetRadioGroup )
+ {
+ static int i = 0;
+ i++;
+ uno::Reference< awt::XRadioButton > xRadio( mxPeer, uno::UNO_QUERY );
+ if ( xRadio.is() )
+ pImport->mxRadioGroups.addItem( aRadioGroup, xRadio );
+ }
+ if ( bSetTitle )
+ {
+ uno::Reference< awt::XDialog2 > xDialog( mxPeer, uno::UNO_QUERY );
+ if ( xDialog.is() )
+ xDialog->setTitle( aTitle );
+ }
+#endif
+}
+
+WidgetElement::~WidgetElement()
+{
+ //delete mpWidget;
+ //mpWidget = 0;
+}
+
+uno::Reference <xml::input::XElement>
+WidgetElement::startChildElement ( sal_Int32 nUid, OUString const &name,
+ uno::Reference <xml::input::XAttributes> const &attributes )
+ throw( xml::sax::SAXException, uno::RuntimeException )
+{
+ // Adding a child to the widget
+ WidgetElement *pChild = new WidgetElement ( nUid, name, attributes, this, mpImport );
+
+ if ( !mpWidget->addChild( pChild->mpWidget ) )
+ {
+ DBG_ERROR2( "ERROR: cannot add %s to container %s, container full", OUSTRING_CSTR( name ), OUSTRING_CSTR( getLocalName() ) );
+ throw xml::sax::SAXException();
+ }
+
+ PropList aProps;
+ propsFromAttributes( attributes, aProps, mpImport->XMLNS_CONTAINER_UID );
+ mpWidget->setChildProperties( pChild->mpWidget, aProps );
+
+ return pChild;
+}
+
+// Support Ivo Hinkelmann's move label/text/title attribute to CONTENT
+// transex3 hack.
+void SAL_CALL
+WidgetElement::characters( OUString const& rChars )
+ throw (css::xml::sax::SAXException, css::uno::RuntimeException)
+{
+ if ( mpWidget && rChars.trim().getLength() )
+ {
+ uno::Reference< awt::XDialog2 > xDialog( mpWidget->getPeer(), uno::UNO_QUERY );
+ uno::Reference< awt::XButton > xButton( mpWidget->getPeer(), uno::UNO_QUERY );
+ if ( xDialog.is() )
+ xDialog->setTitle( rChars );
+ else if ( xButton.is() )
+ mpWidget->setProperty( OUString::createFromAscii( "label" ), rChars );
+ else
+ mpWidget->setProperty( OUString::createFromAscii( "text" ), rChars );
+ }
+}
+// ---- ElementBase ----
+
+ElementBase::ElementBase( sal_Int32 nUid, OUString const & rLocalName,
+ uno::Reference< xml::input::XAttributes > const & xAttributes,
+ ElementBase* pParent,
+ ImportContext* pImport )
+SAL_THROW(())
+: mpImport( pImport )
+ , mpParent( pParent )
+ , mnUid( nUid )
+ , maLocalName( rLocalName )
+ , mxAttributes( xAttributes )
+{
+}
+
+// ---- ImportContext ----
+
+void ImportContext::startDocument(
+ uno::Reference< xml::input::XNamespaceMapping > const & xNamespaceMapping )
+ throw (xml::sax::SAXException, uno::RuntimeException)
+{
+ XMLNS_LAYOUT_UID = xNamespaceMapping->getUidByUri(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_LAYOUT_URI ) ) );
+ XMLNS_CONTAINER_UID = xNamespaceMapping->getUidByUri(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( XMLNS_CONTAINER_URI ) ) );
+}
+
+ToplevelElement::ToplevelElement (OUString const &rName,
+ uno::Reference <xml::input::XAttributes> const &xAttributes,
+ ImportContext *pImport)
+SAL_THROW(())
+: WidgetElement( 0, rName, xAttributes, NULL, pImport )
+{
+}
+
+ToplevelElement::~ToplevelElement()
+{
+}
+
+uno::Reference< xml::input::XElement > ImportContext::startRootElement(
+ sal_Int32 nUid, OUString const & rLocalName,
+ uno::Reference< xml::input::XAttributes > const & xAttributes )
+ throw (xml::sax::SAXException, uno::RuntimeException)
+{
+ if (XMLNS_LAYOUT_UID != nUid)
+ throw xml::sax::SAXException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "invalid namespace!" ) ),
+ uno::Reference< uno::XInterface >(), uno::Any() );
+ else
+ return new ToplevelElement( rLocalName, xAttributes, this );
+}
+
+} // namespace layoutimpl
diff --git a/toolkit/source/layout/import.hxx b/toolkit/source/layout/import.hxx
new file mode 100644
index 000000000000..e4b43ab78df3
--- /dev/null
+++ b/toolkit/source/layout/import.hxx
@@ -0,0 +1,283 @@
+#ifndef IMPORT_HXX
+#define IMPORT_HXX
+
+#include <map>
+#include <list>
+#include <hash_map>
+
+#include <com/sun/star/xml/input/XRoot.hpp>
+#include <cppuhelper/implbase1.hxx>
+
+namespace layoutimpl
+{
+class LayoutRoot;
+class LayoutWidget;
+namespace css = ::com::sun::star;
+
+/* blocks under IMPORT_RADIOGROUP are marked for deletion.
+ The use of it is to synchronize radio buttons into groups.
+ But toolkit doesn't fire toggle events when toggled from the code.
+ Another approach is to implement our own XRadioButton from our
+ internal toolkit. We could have some singleton where they would
+ register... We would need to add another attribute...
+*/
+
+#ifdef IMPORT_RADIOGROUP
+#include <com/sun/star/awt/XRadioButton.hpp>
+class RadioGroups
+{
+public:
+ RadioGroups()
+ {
+ }
+
+ void addItem( rtl::OUString id, css::uno::Reference< css::awt::XRadioButton > xRadio )
+ throw (css::uno::RuntimeException)
+ {
+ if ( ! xRadio.is() )
+ throw css::uno::RuntimeException();
+
+ css::uno::Reference< RadioGroup > group;
+ RadioGroupsMap::iterator it = mxRadioGroups.find( id );
+ if ( it == mxRadioGroups.end() )
+ {
+ group = css::uno::Reference< RadioGroup > ( new RadioGroup() );
+ mxRadioGroups [id] = group;
+ }
+ else
+ group = it->second;
+ group->addItem( xRadio );
+ }
+
+private:
+ class RadioGroup : public ::cppu::WeakImplHelper1< css::awt::XItemListener >
+ {
+ public:
+ RadioGroup()
+ {
+ }
+
+ void addItem( css::uno::Reference< css::awt::XRadioButton > xRadio )
+ {
+ if ( ! mxSelectedRadio.is() )
+ {
+ xRadio->setState( true );
+ mxSelectedRadio = xRadio;
+ }
+ else if ( xRadio->getState() )
+ {
+ mxSelectedRadio->setState( false );
+ mxSelectedRadio = xRadio;
+ }
+
+ xRadio->addItemListener( this );
+ mxRadios.push_back (xRadio);
+ }
+
+ private:
+ typedef std::list< css::uno::Reference< css::awt::XRadioButton > > RadioButtonsList;
+ RadioButtonsList mxRadios;
+ css::uno::Reference< css::awt::XRadioButton > mxSelectedRadio;
+
+ // awt::XItemListener
+ void itemStateChanged( const com::sun::star::awt::ItemEvent& e)
+ throw (css::uno::RuntimeException)
+ {
+ if ( e.Selected )
+ {
+ mxSelectedRadio->setState( false );
+ // the only radio button selected would be the one that fired the event
+ for( RadioButtonsList::iterator it = mxRadios.begin(); it != mxRadios.end(); it++ )
+ if ( (*it)->getState() )
+ {
+ mxSelectedRadio = *it;
+ break;
+ }
+ }
+ }
+
+ // lang::XEventListener
+ void SAL_CALL disposing( const css::lang::EventObject& )
+ throw (css::uno::RuntimeException)
+ {
+ }
+ };
+
+ // each RadioGroup will stay alive after RadioGroups die with the ImportContext
+ // because they are referenced by every XRadioButton through the listener
+ typedef std::map< rtl::OUString, css::uno::Reference< RadioGroup > > RadioGroupsMap;
+ RadioGroupsMap mxRadioGroups;
+};
+#endif
+
+#if 0
+// generator
+class Widget
+{
+public:
+ Widget( css::uno::Reference< css::awt::XToolkit > xToolkit,
+ css::uno::Reference< css::awt::XWindow > xToplevel,
+ rtl::OUString unoName, long attrbs );
+ virtual ~Widget();
+
+ virtual void setProperties( const PropList &rProps );
+
+ virtual bool addChild( Widget *pChild );
+ virtual void setChildProperties( Widget *pChild, const PropList &rProps );
+
+ inline css::uno::Reference< css::awt::XLayoutConstrains > getPeer()
+ { return mxWidget; }
+
+ inline css::uno::Reference< css::awt::XLayoutConstrains > getContainer()
+ { return mxContainer; }
+
+protected:
+ css::uno::Reference< css::awt::XLayoutConstrains > mxWidget;
+ css::uno::Reference< css::awt::XLayoutContainer > mxContainer;
+};
+
+class Root
+{
+public:
+ Root( css::uno::Reference< css::awt::XToolkit > xToolkit )
+ : mxToolkit( xToolkit ) {}
+ ~Root();
+
+ virtual Widget *create( rtl::OUString id, const rtl::OUString unoName, long attrbs );
+
+ css::uno::Reference< css::awt::XLayoutConstrains > getById( rtl::OUString id );
+ inline css::uno::Reference< css::awt::XLayoutConstrains > getToplevel();
+
+protected:
+ css::uno::Reference< css::awt::XToolkit > mxToolkit;
+ Widget *mpToplevel;
+
+ typedef std::hash_map< rtl::OUString, css::uno::Reference< css::awt::XLayoutConstrains >,
+ rtl::OUStringHash > ItemHash;
+ ItemHash maItems;
+};
+#endif
+
+// parser
+class ImportContext : public ::cppu::WeakImplHelper1< css::xml::input::XRoot >
+{
+public:
+ sal_Int32 XMLNS_LAYOUT_UID, XMLNS_CONTAINER_UID;
+ LayoutRoot &mrRoot; // switch to XNameContainer ref ?
+#ifdef IMPORT_RADIOGROUP
+ RadioGroups mxRadioGroups;
+#endif
+
+ inline ImportContext( LayoutRoot &rRoot ) SAL_THROW( () )
+ : mrRoot( rRoot ) {}
+ virtual ~ImportContext() {}
+
+ // XRoot
+ virtual void SAL_CALL startDocument(
+ css::uno::Reference< css::xml::input::XNamespaceMapping >
+ const & xNamespaceMapping )
+ throw (css::xml::sax::SAXException, css::uno::RuntimeException);
+ virtual void SAL_CALL endDocument()
+ throw (css::xml::sax::SAXException, css::uno::RuntimeException)
+ { /* ignore */ }
+ virtual void SAL_CALL processingInstruction(
+ ::rtl::OUString const & /* rTarget */, ::rtl::OUString const & /* rData */ )
+ throw (css::xml::sax::SAXException, css::uno::RuntimeException)
+ { /* ignore */ }
+ virtual void SAL_CALL setDocumentLocator(
+ css::uno::Reference< css::xml::sax::XLocator > const & /* xLocator */ )
+ throw (css::xml::sax::SAXException, css::uno::RuntimeException)
+ { /* ignore */ }
+ virtual css::uno::Reference< css::xml::input::XElement >
+ SAL_CALL startRootElement(
+ sal_Int32 nUid, ::rtl::OUString const & rLocalName,
+ css::uno::Reference<css::xml::input::XAttributes > const & xAttributes )
+ throw (css::xml::sax::SAXException, css::uno::RuntimeException);
+};
+
+class ElementBase : public ::cppu::WeakImplHelper1< css::xml::input::XElement >
+{
+protected:
+ ImportContext *mpImport;
+/* TODO: check if all this memebers are needed. */
+ ElementBase *mpParent;
+ sal_Int32 mnUid;
+
+ ::rtl::OUString maLocalName;
+ css::uno::Reference< css::xml::input::XAttributes > mxAttributes;
+public:
+ ElementBase(
+ sal_Int32 nUid, ::rtl::OUString const & rLocalName,
+ css::uno::Reference< css::xml::input::XAttributes > const & xAttributes,
+ ElementBase * pParent, ImportContext * pImport )
+ SAL_THROW( () );
+ virtual ~ElementBase() SAL_THROW(());
+
+ // XElement
+ virtual css::uno::Reference<css::xml::input::XElement> SAL_CALL getParent()
+ throw (css::uno::RuntimeException)
+ { return static_cast< css::xml::input::XElement * >( mpParent ); }
+ virtual ::rtl::OUString SAL_CALL getLocalName() throw (css::uno::RuntimeException)
+ { return maLocalName; }
+ virtual sal_Int32 SAL_CALL getUid() throw (css::uno::RuntimeException)
+ { return mnUid; }
+ virtual css::uno::Reference< css::xml::input::XAttributes >
+ SAL_CALL getAttributes() throw (css::uno::RuntimeException)
+ { return mxAttributes; }
+
+ virtual void SAL_CALL ignorableWhitespace(
+ ::rtl::OUString const & /* rWhitespaces */ )
+ throw (css::xml::sax::SAXException, css::uno::RuntimeException)
+ { /* ignore */ }
+ virtual void SAL_CALL characters( ::rtl::OUString const & /* rChars */ )
+ throw (css::xml::sax::SAXException, css::uno::RuntimeException)
+ { /* ignore */ }
+ virtual void SAL_CALL processingInstruction(
+ ::rtl::OUString const & /* Target */, ::rtl::OUString const & /* Data */ )
+ throw (css::xml::sax::SAXException, css::uno::RuntimeException)
+ { /* ignore */ }
+
+ virtual css::uno::Reference< css::xml::input::XElement >
+ SAL_CALL startChildElement(
+ sal_Int32 nUid, ::rtl::OUString const & rLocalName,
+ css::uno::Reference<css::xml::input::XAttributes > const & xAttributes )
+ throw (css::xml::sax::SAXException, css::uno::RuntimeException) = 0;
+ virtual void SAL_CALL endElement()
+ throw (css::xml::sax::SAXException, css::uno::RuntimeException)
+ { /* ignore */ }
+};
+
+class WidgetElement : public ElementBase
+{
+protected:
+ LayoutWidget *mpWidget;
+
+public:
+ WidgetElement( sal_Int32 nUid, rtl::OUString const &name,
+ css::uno::Reference< css::xml::input::XAttributes > const &attributes,
+ ElementBase *parent, ImportContext *import ) SAL_THROW (());
+
+ ~WidgetElement();
+
+
+ virtual css::uno::Reference< css::xml::input::XElement> SAL_CALL
+ startChildElement (sal_Int32 id, rtl::OUString const &name,
+ css::uno::Reference< css::xml::input::XAttributes > const &attributes)
+ throw( css::xml::sax::SAXException, css::uno::RuntimeException );
+ virtual void SAL_CALL characters( ::rtl::OUString const & /* rChars */ )
+ throw (css::xml::sax::SAXException, css::uno::RuntimeException);
+};
+
+class ToplevelElement : public WidgetElement
+{
+public:
+ ToplevelElement( rtl::OUString const &name,
+ css::uno::Reference< css::xml::input::XAttributes > const &attributes,
+ ImportContext *import ) SAL_THROW (());
+ ~ToplevelElement();
+};
+
+
+} // namespace layoutimpl
+
+#endif /* IMPORT_HXX */
diff --git a/toolkit/source/layout/proplist.hxx b/toolkit/source/layout/proplist.hxx
new file mode 100644
index 000000000000..551072181fbc
--- /dev/null
+++ b/toolkit/source/layout/proplist.hxx
@@ -0,0 +1,34 @@
+#ifndef CORE_PROPLIST_HXX
+#define CORE_PROPLIST_HXX
+
+#include <list>
+#include <com/sun/star/xml/input/XAttributes.hpp>
+
+#include <rtl/ustring.hxx>
+
+namespace layoutimpl
+{
+
+namespace css = ::com::sun::star;
+
+typedef std::list< std::pair< rtl::OUString, rtl::OUString > > PropList;
+
+void propsFromAttributes( const css::uno::Reference<css::xml::input::XAttributes> & xAttributes,
+ PropList &rProps, sal_Int32 nNamespace );
+
+void setProperties( css::uno::Reference< css::uno::XInterface > const& xPeer,
+ PropList const& rProps);
+
+void setProperty( css::uno::Reference< css::uno::XInterface > const& xPeer,
+ rtl::OUString const& attr, rtl::OUString const& value );
+
+long getAttributeProps( PropList &rProps );
+bool findAndRemove( const char *pAttr, PropList &rProps, rtl::OUString &rValue);
+
+}
+
+// Convert a rtl::OUString to a byte string.
+#define OUSTRING_CSTR( str ) \
+ rtl::OUStringToOString( str, RTL_TEXTENCODING_ASCII_US ).getStr()
+
+#endif // CORE_PROPLIST_HXX
diff --git a/toolkit/source/layout/root.cxx b/toolkit/source/layout/root.cxx
new file mode 100644
index 000000000000..47488a0213e8
--- /dev/null
+++ b/toolkit/source/layout/root.cxx
@@ -0,0 +1,329 @@
+#include "root.hxx"
+
+#include <assert.h>
+#include <com/sun/star/xml/sax/XParser.hpp>
+
+#include "helper.hxx"
+#include "import.hxx"
+#include "timer.hxx"
+#include "translate.hxx"
+
+namespace layoutimpl
+{
+
+using namespace css;
+using ::rtl::OUString;
+
+LayoutRoot::LayoutRoot( const uno::Reference< lang::XMultiServiceFactory >& xFactory )
+ : mbDisposed( sal_False )
+ , mxFactory( xFactory )
+ , mpListeners( NULL )
+ , mpToplevel( NULL )
+{
+ if ( !xFactory.is() )
+ throw uno::RuntimeException();
+ mxLayoutUnit = uno::Reference< awt::XLayoutUnit >( new LayoutUnit() );
+}
+
+LayoutRoot::~LayoutRoot()
+{
+// TODO: we want to delete the top level LayoutWidget...
+ ::osl::MutexGuard aGuard( maMutex );
+ if ( !mbDisposed )
+ {
+ try
+ {
+ m_refCount++; // inhibit multiple destruction
+ dispose();
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+}
+
+// XInitialization
+void SAL_CALL LayoutRoot::initialize( const uno::Sequence< uno::Any >& aArguments )
+ throw ( uno::Exception,
+ uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if ( mbDisposed )
+ throw lang::DisposedException();
+
+ if ( mxContainer.is() ) // only 1 init ...
+ throw uno::Exception();
+
+ if ( !aArguments.getLength() )
+ throw lang::IllegalArgumentException();
+
+ OSL_ENSURE( aArguments.getLength() == 1, "Wrong arg count\n" );
+
+ OUString aXMLName;
+ if ( !( aArguments[0] >>= aXMLName ) )
+ throw lang::IllegalArgumentException();
+
+ uno::Reference< xml::sax::XParser > xParser
+ ( mxFactory->createInstance(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.sax.Parser" ) ) ),
+ uno::UNO_QUERY );
+ OSL_ASSERT( xParser.is() );
+ if (! xParser.is())
+ {
+ throw uno::RuntimeException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "cannot create sax-parser component" ) ),
+ uno::Reference< uno::XInterface >() );
+ }
+
+ OUString aXMLFile = readRightTranslation( aXMLName );
+
+ uno::Reference< io::XInputStream > xStream = getFileAsStream( mxFactory,
+ aXMLFile );
+
+ // error handler, entity resolver omitted
+
+ // FIXME: quite possibly we want to pass this in ...
+ uno::Reference< awt::XToolkit > xToolkit;
+
+ mxToolkit = uno::Reference< awt::XToolkit >(
+ mxFactory->createInstance(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.Toolkit" ) ) ),
+ uno::UNO_QUERY );
+
+ if ( !mxToolkit.is() )
+ throw uno::RuntimeException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "failed to create toolkit!" ) ),
+ uno::Reference< uno::XInterface >() );
+
+ ImportContext *pCtx = new ImportContext( *this );
+
+ uno::Reference< xml::input::XRoot > xRoot( pCtx );
+ uno::Sequence < uno::Any > aArgs( 1 );
+ aArgs[0] <<= xRoot;
+ uno::Reference< xml::sax::XDocumentHandler > xDocHandler
+ (mxFactory->createInstanceWithArguments
+ ( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.input.SaxDocumentHandler" ) ),
+ aArgs ), uno::UNO_QUERY );
+
+ xParser->setDocumentHandler( xDocHandler );
+
+ xml::sax::InputSource source;
+ source.aInputStream = xStream;
+ source.sSystemId = OUString( RTL_CONSTASCII_USTRINGPARAM( "virtual file" ) );
+
+ xParser->parseStream( source );
+}
+
+// XLayoutContainer
+uno::Reference< awt::XLayoutContainer > LayoutRoot::getLayoutContainer() throw (uno::RuntimeException)
+{
+ return uno::Reference< awt::XLayoutContainer >();
+}
+
+// local helper ...
+void LayoutRoot::addItem( const OUString &rName,
+ const uno::Reference< awt::XLayoutConstrains > &xRef )
+{
+ maItems[ rName ] = xRef;
+}
+
+// XNameAccess
+uno::Any SAL_CALL LayoutRoot::getByName( const OUString &rName )
+ throw ( container::NoSuchElementException,
+ lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( maMutex );
+ if ( mbDisposed )
+ throw lang::DisposedException();
+
+ uno::Reference< awt::XLayoutConstrains > xItem;
+ ItemHash::iterator i = maItems.find( rName );
+ if ( i != maItems.end() )
+ xItem = i->second;
+ return uno::makeAny( xItem );
+}
+
+sal_Bool SAL_CALL LayoutRoot::hasByName( const OUString &rName )
+ throw (uno::RuntimeException)
+{
+ ::osl::MutexGuard aGuard( maMutex );
+ if ( mbDisposed ) throw lang::DisposedException();
+
+ ItemHash::iterator i = maItems.find( rName );
+ return i != maItems.end();
+}
+
+uno::Sequence< OUString > SAL_CALL LayoutRoot::getElementNames()
+ throw ( uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( maMutex );
+ if ( mbDisposed ) throw lang::DisposedException();
+
+ uno::Sequence< OUString > aNames( maItems.size() );
+ sal_Int32 nPos = 0;
+
+ for( ItemHash::const_iterator i = maItems.begin();
+ i != maItems.end(); i++ )
+ aNames[ nPos++ ] = i->first;
+
+ return aNames;
+}
+
+uno::Type SAL_CALL LayoutRoot::getElementType()
+ throw ( uno::RuntimeException )
+{
+ return getCppuType( ( const uno::Reference< awt::XLayoutConstrains >* )NULL );
+}
+
+sal_Bool SAL_CALL LayoutRoot::hasElements()
+ throw ( uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if ( mbDisposed ) throw lang::DisposedException();
+
+ return maItems.size() > 0;
+}
+
+// XComponent
+void SAL_CALL LayoutRoot::dispose()
+ throw ( uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if ( mbDisposed ) throw lang::DisposedException();
+
+ if ( mpListeners )
+ {
+
+ lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
+ mpListeners->disposeAndClear( aSource );
+ delete mpListeners;
+ mpListeners = NULL;
+ }
+
+ maItems.clear();
+ mbDisposed = sal_True;
+}
+
+void SAL_CALL LayoutRoot::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
+ throw ( uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if ( mbDisposed ) throw lang::DisposedException();
+
+ if ( !mpListeners )
+ mpListeners = new ::cppu::OInterfaceContainerHelper( maMutex );
+ mpListeners->addInterface( xListener );
+}
+
+void SAL_CALL LayoutRoot::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
+ throw ( uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( maMutex );
+
+ if ( mbDisposed ) throw lang::DisposedException();
+
+ if ( mpListeners )
+ mpListeners->removeInterface( xListener );
+}
+
+// builder
+
+LayoutWidget *LayoutRoot::create( OUString id, const OUString unoName, long attrbs,uno::Reference< awt::XLayoutContainer > xParent )
+{
+ LayoutWidget *pWidget = new LayoutWidget( mxToolkit, xParent, unoName, attrbs );
+ if ( !mpToplevel )
+ {
+ mpToplevel = pWidget;
+ mxWindow = uno::Reference< awt::XWindow >( pWidget->getPeer(), uno::UNO_QUERY );
+ mxContainer = pWidget->mxContainer;
+ }
+ if ( pWidget->mxContainer.is() )
+ pWidget->mxContainer->setLayoutUnit( mxLayoutUnit );
+ if ( id.getLength() )
+ maItems[ id ] = pWidget->getPeer();
+ return pWidget;
+}
+
+/*
+ uno::Reference< awt::XLayoutConstrains > LayoutRoot::getToplevel()
+ {
+ if ( mpToplevel )
+ return mpToplevel->getPeer();
+ return uno::Reference< awt::XLayoutConstrains > ();
+ }
+
+ uno::Reference< awt::XLayoutConstrains > LayoutRoot::getById( OUString id )
+ {
+ uno::Reference< awt::XLayoutConstrains > rRef = 0;
+ ItemHash::iterator i = maItems.find( id );
+ if ( i != maItems.end() )
+ rRef = i->second;
+ return rRef;
+ }
+*/
+
+LayoutWidget::LayoutWidget( uno::Reference< awt::XToolkit > xToolkit,
+ uno::Reference< awt::XLayoutContainer > xParent,
+ OUString unoName, long attrbs )
+{
+ while ( xParent.is() && !uno::Reference< awt::XWindow >( xParent, uno::UNO_QUERY ).is() )
+ {
+ uno::Reference< awt::XLayoutContainer > xContainer( xParent, uno::UNO_QUERY );
+ assert( xContainer.is() );
+ xParent = uno::Reference< awt::XLayoutContainer >( xContainer->getParent(), uno::UNO_QUERY );
+ }
+
+ mxWidget = createWidget( xToolkit, xParent, unoName, attrbs );
+ assert( mxWidget.is() );
+ mxContainer = uno::Reference< awt::XLayoutContainer >( mxWidget, uno::UNO_QUERY );
+}
+
+LayoutWidget::~LayoutWidget()
+{
+ /* should we dispose of the references...? */
+ // at least of its children... Or should root?
+}
+
+bool LayoutWidget::addChild( LayoutWidget *pChild )
+{
+ if ( !mxContainer.is() )
+ return false;
+
+ try
+ {
+ mxContainer->addChild( pChild->mxWidget );
+ }
+ catch( awt::MaxChildrenException ex )
+ {
+ return false;
+ }
+ return true;
+}
+
+void LayoutWidget::setProperties( PropList const& rProps )
+{
+ ::layoutimpl::setProperties( mxWidget, rProps );
+}
+
+void LayoutWidget::setProperty( OUString const& attr, OUString const& value )
+{
+ ::layoutimpl::setProperty( mxWidget, attr, value );
+}
+
+void LayoutWidget::setChildProperties( LayoutWidget *pChild,
+ PropList const& rProps )
+{
+ uno::Reference< beans::XPropertySet > xChildPeer;
+ xChildPeer = mxContainer->getChildProperties( pChild->mxWidget );
+
+ if ( xChildPeer.is() )
+ ::layoutimpl::setProperties( xChildPeer, rProps );
+}
+
+} // namespace layoutimpl
+
diff --git a/toolkit/source/layout/root.hxx b/toolkit/source/layout/root.hxx
new file mode 100644
index 000000000000..e87c880e4635
--- /dev/null
+++ b/toolkit/source/layout/root.hxx
@@ -0,0 +1,127 @@
+#ifndef CORE_ROOT_HXX
+#define CORE_ROOT_HXX
+
+#include <hash_map>
+
+#include <com/sun/star/awt/XLayoutRoot.hpp>
+#include <com/sun/star/awt/XToolkit.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <cppuhelper/implbase3.hxx>
+#include <cppuhelper/interfacecontainer.h>
+
+#include "proplist.hxx"
+
+namespace layoutimpl
+{
+
+namespace css = ::com::sun::star;
+
+css::uno::Reference< css::io::XInputStream >
+getFileAsStream( const css::uno::Reference< css::lang::XMultiServiceFactory > &xFactory,
+ const rtl::OUString &rName );
+
+/* Interface generation code -- to hook to a parser. */
+
+/*
+ TODO: (ricardo) I think we should cut on LayoutRoot, stripping out its widget
+ proxy interface (just make it return the root widget). Would even make it easier
+ if there was interest to support multiple toplevel widgets in the same file.
+
+ We also need to make sure the code gets diposed well... There is no need to keep
+ these objects around after initialization...
+*/
+
+
+class LayoutWidget;
+
+class LayoutRoot : public ::cppu::WeakImplHelper3<
+ css::awt::XLayoutRoot,
+ css::lang::XInitialization,
+ css::lang::XComponent>
+{
+protected:
+ ::osl::Mutex maMutex;
+
+ typedef std::hash_map< rtl::OUString,
+ css::uno::Reference< css::awt::XLayoutConstrains >,
+ ::rtl::OUStringHash > ItemHash;
+ ItemHash maItems;
+
+ sal_Bool mbDisposed;
+ css::uno::Reference< css::lang::XMultiServiceFactory > mxFactory;
+ ::cppu::OInterfaceContainerHelper *mpListeners;
+
+ css::uno::Reference< css::awt::XWindow > mxWindow;
+ css::uno::Reference< css::awt::XLayoutContainer > mxContainer;
+
+ css::uno::Reference< css::awt::XToolkit > mxToolkit;
+ LayoutWidget *mpToplevel;
+ css::uno::Reference< css::awt::XLayoutUnit > mxLayoutUnit;
+
+public:
+ LayoutRoot( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory );
+ virtual ~LayoutRoot();
+
+ void addItem( const rtl::OUString &rName,
+ const css::uno::Reference< css::awt::XLayoutConstrains > &xRef );
+
+ void setWindow( css::uno::Reference< css::awt::XLayoutConstrains > xPeer )
+ {
+ mxWindow = css::uno::Reference< css::awt::XWindow >( xPeer, css::uno::UNO_QUERY );
+ }
+
+ // get XLayoutContainer
+ virtual css::uno::Reference< css::awt::XLayoutContainer > getLayoutContainer() throw (css::uno::RuntimeException);
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) throw (css::uno::Exception, css::uno::RuntimeException);
+
+ // XNameAccess
+ virtual css::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (css::container::NoSuchElementException, css::lang::WrappedTargetException, css::uno::RuntimeException);
+ virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames() throw (css::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (css::uno::RuntimeException);
+ virtual css::uno::Type SAL_CALL getElementType() throw (css::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL hasElements() throw (css::uno::RuntimeException);
+
+ // XComponent
+ virtual void SAL_CALL dispose() throw (css::uno::RuntimeException);
+ virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) throw (css::uno::RuntimeException);
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) throw (css::uno::RuntimeException);
+
+ // generator
+ virtual LayoutWidget *create( rtl::OUString id, const rtl::OUString unoName, long attrbs, css::uno::Reference< css::awt::XLayoutContainer > xParent );
+};
+
+class LayoutWidget
+{
+ friend class LayoutRoot;
+
+public:
+ LayoutWidget() {}
+ LayoutWidget( css::uno::Reference< css::awt::XToolkit > xToolkit,
+ css::uno::Reference< css::awt::XLayoutContainer > xToplevel,
+ rtl::OUString unoName, long attrbs );
+ virtual ~LayoutWidget();
+
+ virtual void setProperties( const PropList &rProps );
+ virtual void setProperty( rtl::OUString const& attr, rtl::OUString const& value );
+
+ virtual bool addChild( LayoutWidget *pChild );
+ virtual void setChildProperties( LayoutWidget *pChild, const PropList &rProps );
+
+ inline css::uno::Reference< css::awt::XLayoutConstrains > getPeer()
+ { return mxWidget; }
+ inline css::uno::Reference< css::awt::XLayoutContainer > getContainer()
+ { return mxContainer; }
+
+protected:
+ css::uno::Reference< css::awt::XLayoutConstrains > mxWidget;
+ css::uno::Reference< css::awt::XLayoutContainer > mxContainer;
+};
+
+} // namespace layoutimpl
+
+#endif // CORE_ROOT_HXX
diff --git a/toolkit/source/layout/table.cxx b/toolkit/source/layout/table.cxx
new file mode 100644
index 000000000000..2cffbb8af399
--- /dev/null
+++ b/toolkit/source/layout/table.cxx
@@ -0,0 +1,326 @@
+#include <table.hxx>
+
+#include <sal/macros.h>
+#include <osl/mutex.hxx>
+#include <cppuhelper/propshlp.hxx>
+#include <cppuhelper/interfacecontainer.h>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <tools/debug.hxx>
+
+// fixed point precision for distributing error
+#define FIXED_PT 16
+
+namespace layoutimpl
+{
+
+using namespace com::sun::star;
+
+class TableChildProps : public PropHelper
+{
+public:
+ TableChildProps( Table::ChildData *pData )
+ {
+ addProp( RTL_CONSTASCII_USTRINGPARAM( "XExpand" ),
+ ::getCppuType( static_cast< const sal_Bool* >( NULL ) ),
+ &( pData->bExpand[ 0 ] ) );
+ addProp( RTL_CONSTASCII_USTRINGPARAM( "YExpand" ),
+ ::getCppuType( static_cast< const sal_Bool* >( NULL ) ),
+ &( pData->bExpand[ 1 ] ) );
+ addProp( RTL_CONSTASCII_USTRINGPARAM( "ColSpan" ),
+ ::getCppuType( static_cast< const sal_Int32* >( NULL ) ),
+ &( pData->nColSpan ) );
+ addProp( RTL_CONSTASCII_USTRINGPARAM( "RowSpan" ),
+ ::getCppuType( static_cast< const sal_Int32* >( NULL ) ),
+ &( pData->nRowSpan ) );
+ }
+ PROPHELPER_SET_INFO
+};
+
+bool Table::ChildData::isVisible()
+{
+ if ( !xChild.is() || nColSpan < 1 || nRowSpan < 1 )
+ return false;
+ return xChild.is();
+}
+
+Table::Table()
+ : Container()
+{
+ // another default value could be 0xffff for infinite columns( = 1 row )
+ mnColsLen = 1;
+ addProp( RTL_CONSTASCII_USTRINGPARAM( "Columns" ),
+ ::getCppuType( static_cast< const sal_Int32* >( NULL ) ),
+ &mnColsLen );
+}
+
+void SAL_CALL
+Table::addChild( const uno::Reference< awt::XLayoutConstrains >& xChild )
+ throw( uno::RuntimeException, awt::MaxChildrenException )
+{
+ if ( xChild.is() )
+ {
+ ChildData *pData = new ChildData();
+ pData->bExpand[ 0 ] = pData->bExpand[ 1 ] = true;
+ pData->nColSpan = pData->nRowSpan = 1;
+ pData->xChild = xChild;
+ maChildren.push_back( pData );
+
+ setChildParent( xChild );
+ queueResize();
+
+ // cause of flicker
+ allocateChildAt( xChild, awt::Rectangle( 0,0,0,0 ) );
+ }
+}
+
+void SAL_CALL
+Table::removeChild( const uno::Reference< awt::XLayoutConstrains >& xChild )
+ throw( uno::RuntimeException )
+{
+ for( std::list< ChildData * >::iterator it = maChildren.begin();
+ it != maChildren.end(); it++ )
+ {
+ if ( ( *it )->xChild == xChild )
+ {
+ delete *it;
+ maChildren.erase( it );
+
+ unsetChildParent( xChild );
+ queueResize();
+ break;
+ }
+ }
+ DBG_ERROR( "Table error: trying to remove child that doesn't exist" );
+}
+
+uno::Sequence< uno::Reference < awt::XLayoutConstrains > > SAL_CALL
+Table::getChildren()
+ throw( uno::RuntimeException )
+{
+ uno::Sequence< uno::Reference< awt::XLayoutConstrains > > children( maChildren.size() );
+ unsigned int i = 0;
+ for( std::list< ChildData * >::iterator it = maChildren.begin();
+ it != maChildren.end(); it++, i++ )
+ children[i] =( *it )->xChild;
+
+ return children;
+}
+
+uno::Reference< beans::XPropertySet > SAL_CALL
+Table::getChildProperties( const uno::Reference< awt::XLayoutConstrains >& xChild )
+ throw( uno::RuntimeException )
+{
+ std::list< ChildData * >::iterator iter;
+ for( iter = maChildren.begin(); iter != maChildren.end(); iter++ )
+ {
+ if ( ( *iter )->xChild == xChild )
+ {
+ if ( !( *iter )->xProps.is() )
+ {
+ // FIXME: make me safe !
+ PropHelper *pProps = new TableChildProps( *iter );
+ pProps->setChangeListener( this );
+( *iter )->xProps = pProps;
+ }
+ return( *iter )->xProps;
+ }
+ }
+ return uno::Reference< beans::XPropertySet >();
+}
+
+awt::Size SAL_CALL
+Table::getMinimumSize() throw( uno::RuntimeException )
+{
+ int nRowsLen = 0;
+
+ // 1. layout the table -- adjust to cope with row-spans...
+ {
+ // temporary 1D representation of the table
+ std::vector< ChildData *> aTable;
+
+ int col = 0, row = 0;
+ for( std::list<ChildData *>::iterator it = maChildren.begin();
+ it != maChildren.end(); it++ )
+ {
+ ChildData *child = *it;
+ if ( !child->isVisible() )
+ continue;
+
+ while ( col + SAL_MIN( child->nColSpan, mnColsLen ) > mnColsLen )
+ {
+ col = 0;
+ row++;
+
+ unsigned int i = col +( row*mnColsLen );
+ while ( aTable.size() > i && !aTable[ i ] )
+ i++;
+
+ col = i % mnColsLen;
+ row = i / mnColsLen;
+ }
+
+ child->nLeftCol = col;
+ child->nRightCol = SAL_MIN( col + child->nColSpan, mnColsLen );
+ child->nTopRow = row;
+ child->nBottomRow = row + child->nRowSpan;
+
+ col += child->nColSpan;
+
+ unsigned int start = child->nLeftCol +( child->nTopRow*mnColsLen );
+ unsigned int end =( child->nRightCol-1 ) +( ( child->nBottomRow-1 )*mnColsLen );
+ if ( aTable.size() < end+1 )
+ aTable.resize( end+1, NULL );
+ for( unsigned int i = start; i < end; i++ )
+ aTable[ i ] = child;
+
+ nRowsLen = SAL_MAX( nRowsLen, child->nBottomRow );
+ }
+ }
+
+ // 2. calculate columns/rows sizes
+ for( int g = 0; g < 2; g++ )
+ {
+ std::vector< GroupData > &aGroup = g == 0 ? maCols : maRows;
+
+ aGroup.clear();
+ aGroup.resize( g == 0 ? mnColsLen : nRowsLen );
+
+ // 2.1 base sizes on one-column/row children
+ for( std::list<ChildData *>::iterator it = maChildren.begin();
+ it != maChildren.end(); it++ )
+ {
+ ChildData *child = *it;
+ if ( !child->isVisible() )
+ continue;
+ const int nFirstAttach = g == 0 ? child->nLeftCol : child->nTopRow;
+ const int nLastAttach = g == 0 ? child->nRightCol : child->nBottomRow;
+
+ if ( nFirstAttach == nLastAttach-1 )
+ {
+ child->aRequisition = child->xChild->getMinimumSize();
+ int attach = nFirstAttach;
+ int child_size = g == 0 ? child->aRequisition.Width
+ : child->aRequisition.Height;
+ aGroup[ attach ].nSize = SAL_MAX( aGroup[ attach ].nSize, child_size );
+ if ( child->bExpand[ g ] )
+ aGroup[ attach ].bExpand = true;
+ }
+ }
+
+ // 2.2 make sure multiple-columns/rows children fit
+ for( std::list<ChildData *>::iterator it = maChildren.begin();
+ it != maChildren.end(); it++ )
+ {
+ ChildData *child = *it;
+ if ( !child->isVisible() )
+ continue;
+ const int nFirstAttach = g == 0 ? child->nLeftCol : child->nTopRow;
+ const int nLastAttach = g == 0 ? child->nRightCol : child->nBottomRow;
+
+ if ( nFirstAttach != nLastAttach-1 )
+ {
+ child->aRequisition = child->xChild->getMinimumSize();
+ int size = 0;
+ int expandables = 0;
+ for( int i = nFirstAttach; i < nLastAttach; i++ )
+ {
+ size += aGroup[ i ].nSize;
+ if ( aGroup[ i ].bExpand )
+ expandables++;
+ }
+
+ int child_size = g == 0 ? child->aRequisition.Width
+ : child->aRequisition.Height;
+ int extra = child_size - size;
+ if ( extra > 0 )
+ {
+ if ( expandables )
+ extra /= expandables;
+ else
+ extra /= nLastAttach - nFirstAttach;
+
+ for( int i = nFirstAttach; i < nLastAttach; i++ )
+ if ( expandables == 0 || aGroup[ i ].bExpand )
+ aGroup[ i ].nSize += extra;
+ }
+ }
+ }
+ }
+
+ // 3. Sum everything up
+ mnColExpandables =( mnRowExpandables = 0 );
+ maRequisition.Width =( maRequisition.Height = 0 );
+ for( std::vector<GroupData>::iterator it = maCols.begin();
+ it != maCols.end(); it++ )
+ {
+ maRequisition.Width += it->nSize;
+ if ( it->bExpand )
+ mnColExpandables++;
+ }
+ for( std::vector<GroupData>::iterator it = maRows.begin();
+ it != maRows.end(); it++ )
+ {
+ maRequisition.Height += it->nSize;
+ if ( it->bExpand )
+ mnRowExpandables++;
+ }
+
+ return maRequisition;
+}
+
+void SAL_CALL
+Table::allocateArea( const awt::Rectangle &rArea )
+ throw( uno::RuntimeException )
+{
+ maAllocation = rArea;
+ if ( maCols.size() == 0 || maRows.size() == 0 )
+ return;
+
+ int nExtraSize[ 2 ] = { SAL_MAX( rArea.Width - maRequisition.Width, 0 ),
+ SAL_MAX( rArea.Height - maRequisition.Height, 0 ) };
+ // split it
+ nExtraSize[ 0 ] /= mnColExpandables ? mnColExpandables : mnColsLen;
+ nExtraSize[ 1 ] /= mnRowExpandables ? mnRowExpandables : maRows.size();
+
+ for( std::list<ChildData *>::const_iterator it = maChildren.begin();
+ it != maChildren.end(); it++ )
+ {
+ ChildData *child = *it;
+ if ( !child->isVisible() )
+ continue;
+
+ awt::Rectangle rChildArea( rArea.X, rArea.Y, 0, 0 );
+
+ for( int g = 0; g < 2; g++ )
+ {
+ std::vector< GroupData > &aGroup = g == 0 ? maCols : maRows;
+ const int nFirstAttach = g == 0 ? child->nLeftCol : child->nTopRow;
+ const int nLastAttach = g == 0 ? child->nRightCol : child->nBottomRow;
+
+ for( int i = 0; i < nFirstAttach; i++ )
+ {
+ int gSize = aGroup[ i ].nSize;
+ if ( aGroup[ i ].bExpand )
+ gSize += nExtraSize[ g ];
+ if ( g == 0 )
+ rChildArea.X += gSize;
+ else
+ rChildArea.Y += gSize;
+ }
+ for( int i = nFirstAttach; i < nLastAttach; i++ )
+ {
+ int gSize = aGroup[ i ].nSize;
+ if ( aGroup[ i ].bExpand )
+ gSize += nExtraSize[ g ];
+ if ( g == 0 )
+ rChildArea.Width += gSize;
+ else
+ rChildArea.Height += gSize;
+ }
+ }
+
+ allocateChildAt( child->xChild, rChildArea );
+ }
+}
+
+} // namespace layoutimpl
diff --git a/toolkit/source/layout/table.hxx b/toolkit/source/layout/table.hxx
new file mode 100644
index 000000000000..1374de2d61e3
--- /dev/null
+++ b/toolkit/source/layout/table.hxx
@@ -0,0 +1,79 @@
+#ifndef TABLE_HXX
+#define TABLE_HXX
+
+#include "container.hxx"
+
+#include <list>
+
+namespace layoutimpl
+{
+
+class Table : public Container
+{
+ friend class TableChildProps;
+protected:
+ // Table properties
+ sal_Int32 mnColsLen;
+
+ // Children properties
+ struct ChildData
+ {
+ sal_Bool bExpand[ 2 ];
+ sal_Int32 nColSpan, nRowSpan;
+ css::awt::Size aRequisition;
+ css::uno::Reference< css::awt::XLayoutConstrains > xChild;
+ css::uno::Reference< css::beans::XPropertySet > xProps;
+ bool isVisible();
+
+ // automatically calculated
+ int nLeftCol, nRightCol, nTopRow, nBottomRow;
+ };
+ std::list< ChildData * > maChildren;
+
+ // a group of children; either a column or a row
+ struct GroupData
+ {
+ sal_Bool bExpand;
+ int nSize; // request size (width or height)
+ GroupData() : bExpand( false ), nSize( 0 ) {}
+ };
+ std::vector< GroupData > maCols, maRows;
+ int mnColExpandables, mnRowExpandables;
+
+public:
+ Table();
+
+ // css::awt::XLayoutContainer
+ virtual void SAL_CALL addChild( const css::uno::Reference< css::awt::XLayoutConstrains >& Child )
+ throw (css::uno::RuntimeException, css::awt::MaxChildrenException);
+ virtual void SAL_CALL removeChild( const css::uno::Reference< css::awt::XLayoutConstrains >& Child )
+ throw (css::uno::RuntimeException);
+
+ virtual css::uno::Sequence< css::uno::Reference
+ < css::awt::XLayoutConstrains > > SAL_CALL getChildren()
+ throw (css::uno::RuntimeException);
+
+ virtual css::uno::Reference< css::beans::XPropertySet > SAL_CALL getChildProperties(
+ const css::uno::Reference< css::awt::XLayoutConstrains >& Child )
+ throw (css::uno::RuntimeException);
+
+ virtual void SAL_CALL allocateArea( const css::awt::Rectangle &rArea )
+ throw (css::uno::RuntimeException);
+
+ virtual css::awt::Size SAL_CALL getMinimumSize()
+ throw(css::uno::RuntimeException);
+
+ // unimplemented:
+ virtual sal_Bool SAL_CALL hasHeightForWidth()
+ throw(css::uno::RuntimeException)
+ { return false; }
+ virtual sal_Int32 SAL_CALL getHeightForWidth( sal_Int32 /*nWidth*/ )
+ throw(css::uno::RuntimeException)
+ { return maRequisition.Height; }
+
+ PROPHELPER_SET_INFO
+};
+
+} // namespace layoutimpl
+
+#endif /*TABLE_HXX*/
diff --git a/toolkit/source/layout/timer.cxx b/toolkit/source/layout/timer.cxx
new file mode 100644
index 000000000000..496d206b900e
--- /dev/null
+++ b/toolkit/source/layout/timer.cxx
@@ -0,0 +1,121 @@
+#include "timer.hxx"
+
+#include <vector>
+#include <list>
+#include <vcl/timer.hxx>
+#include <com/sun/star/awt/XLayoutContainer.hpp>
+
+namespace layoutimpl
+{
+using namespace ::com::sun::star;
+
+class AllocateTimer : public Timer
+{
+ typedef std::list< uno::Reference< awt::XLayoutContainer > > ContainerList;
+ ContainerList mxContainers;
+ uno::Reference< awt::XLayoutContainer > mxLastAdded;
+
+public:
+ AllocateTimer()
+ {
+ // timer set to 0 -- just process it as soon as it gets idle
+ SetTimeout( 0 );
+ }
+
+ static inline bool isParentOf( uno::Reference< awt::XLayoutContainer > xParent,
+ uno::Reference< awt::XLayoutContainer > xWidget )
+ {
+ while ( xWidget.is() )
+ {
+ if ( xWidget == xParent )
+ return true;
+ xWidget = uno::Reference< awt::XLayoutContainer >( xWidget->getParent(), uno::UNO_QUERY );
+ }
+ return false;
+ }
+
+ static inline void eraseChildren( ContainerList::iterator &it, ContainerList &list )
+ {
+ ContainerList::iterator jt = list.begin();
+ while ( jt != list.end() )
+ {
+ if ( it != jt && isParentOf( *it, *jt ) )
+ jt = list.erase( jt );
+ else
+ jt++;
+ }
+ }
+
+ static inline bool isContainerDamaged( uno::Reference< awt::XLayoutContainer > xContainer )
+ {
+ uno::Reference< awt::XLayoutConstrains > xConstrains( xContainer, uno::UNO_QUERY );
+ awt::Size lastReq( xContainer->getRequestedSize() );
+ awt::Size curReq( xConstrains->getMinimumSize() );
+ return lastReq.Width != curReq.Width || lastReq.Height != curReq.Height;
+ }
+
+ void add( const uno::Reference< awt::XLayoutContainer > &xContainer )
+ {
+ // small optimization
+ if ( mxLastAdded == xContainer )
+ return;
+ mxLastAdded = xContainer;
+
+ mxContainers.push_back( xContainer );
+ }
+
+ virtual void Timeout()
+ {
+ mxLastAdded = uno::Reference< awt::XLayoutContainer >();
+
+ // 1. remove duplications and children
+ for( ContainerList::iterator it = mxContainers.begin();
+ it != mxContainers.end(); it++ )
+ eraseChildren( it, mxContainers );
+
+ // 2. check damage extent
+ for( ContainerList::iterator it = mxContainers.begin();
+ it != mxContainers.end(); it++ )
+ {
+ uno::Reference< awt::XLayoutContainer > xContainer = *it;
+ while ( xContainer->getParent().is() && isContainerDamaged( xContainer ) )
+ {
+ xContainer = uno::Reference< awt::XLayoutContainer >(
+ xContainer->getParent(), uno::UNO_QUERY );
+ }
+
+ if ( *it != xContainer )
+ {
+ // 2.2 replace it with parent
+ *it = xContainer;
+
+ // 2.3 remove children of new parent
+ eraseChildren( it, mxContainers );
+ }
+ }
+
+ // 3. force re-calculations
+ for( ContainerList::iterator it = mxContainers.begin();
+ it != mxContainers.end(); it++ )
+ (*it)->allocateArea( (*it)->getAllocatedArea() );
+ }
+};
+
+static void AddResizeTimeout( const uno::Reference< awt::XLayoutContainer > &xCont )
+{
+ static AllocateTimer timer;
+ timer.add( xCont );
+ timer.Start();
+}
+
+LayoutUnit::LayoutUnit() : LayoutUnit_Base()
+{
+}
+
+void SAL_CALL LayoutUnit::queueResize( const uno::Reference< awt::XLayoutContainer > &xContainer )
+ throw( uno::RuntimeException )
+{
+ AddResizeTimeout( xContainer );
+}
+
+}
diff --git a/toolkit/source/layout/timer.hxx b/toolkit/source/layout/timer.hxx
new file mode 100644
index 000000000000..d87528cbdcf3
--- /dev/null
+++ b/toolkit/source/layout/timer.hxx
@@ -0,0 +1,22 @@
+#ifndef CORE_TIMER_HXX
+#define CORE_TIMER_HXX
+
+#include <com/sun/star/awt/XLayoutUnit.hpp>
+#include <cppuhelper/implbase1.hxx>
+
+namespace layoutimpl
+{
+
+typedef ::cppu::WeakImplHelper1< com::sun::star::awt::XLayoutUnit > LayoutUnit_Base;
+
+class LayoutUnit : public LayoutUnit_Base
+{
+public:
+ LayoutUnit();
+ void SAL_CALL queueResize( const com::sun::star::uno::Reference< com::sun::star::awt::XLayoutContainer > &xContainer )
+ throw( com::sun::star::uno::RuntimeException );
+};
+
+}
+
+#endif /*CORE_TIMER_HXX*/