diff options
Diffstat (limited to 'toolkit/source/layout/core/timer.cxx')
-rw-r--r-- | toolkit/source/layout/core/timer.cxx | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/toolkit/source/layout/core/timer.cxx b/toolkit/source/layout/core/timer.cxx new file mode 100644 index 000000000000..0da0f2c2abee --- /dev/null +++ b/toolkit/source/layout/core/timer.cxx @@ -0,0 +1,152 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile$ + * + * $Revision$ + * + * 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 "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 ); +} + +} |