1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "timer.hxx" 29 30 #include <vector> 31 #include <list> 32 #include <vcl/timer.hxx> 33 #include <com/sun/star/awt/XLayoutContainer.hpp> 34 35 namespace layoutimpl 36 { 37 using namespace ::com::sun::star; 38 39 class AllocateTimer : public Timer 40 { 41 typedef std::list< uno::Reference< awt::XLayoutContainer > > ContainerList; 42 ContainerList mxContainers; 43 uno::Reference< awt::XLayoutContainer > mxLastAdded; 44 45 public: 46 AllocateTimer() 47 { 48 // timer set to 0 -- just process it as soon as it gets idle 49 SetTimeout( 0 ); 50 } 51 52 static inline bool isParentOf( uno::Reference< awt::XLayoutContainer > xParent, 53 uno::Reference< awt::XLayoutContainer > xWidget ) 54 { 55 while ( xWidget.is() ) 56 { 57 if ( xWidget == xParent ) 58 return true; 59 xWidget = uno::Reference< awt::XLayoutContainer >( xWidget->getParent(), uno::UNO_QUERY ); 60 } 61 return false; 62 } 63 64 static inline void eraseChildren( ContainerList::iterator &it, ContainerList &list ) 65 { 66 ContainerList::iterator jt = list.begin(); 67 while ( jt != list.end() ) 68 { 69 if ( it != jt && isParentOf( *it, *jt ) ) 70 jt = list.erase( jt ); 71 else 72 jt++; 73 } 74 } 75 76 static inline bool isContainerDamaged( uno::Reference< awt::XLayoutContainer > xContainer ) 77 { 78 uno::Reference< awt::XLayoutConstrains > xConstrains( xContainer, uno::UNO_QUERY ); 79 awt::Size lastReq( xContainer->getRequestedSize() ); 80 awt::Size curReq( xConstrains->getMinimumSize() ); 81 return lastReq.Width != curReq.Width || lastReq.Height != curReq.Height; 82 } 83 84 void add( const uno::Reference< awt::XLayoutContainer > &xContainer ) 85 { 86 // small optimization 87 if ( mxLastAdded == xContainer ) 88 return; 89 mxLastAdded = xContainer; 90 91 mxContainers.push_back( xContainer ); 92 } 93 94 virtual void Timeout() 95 { 96 mxLastAdded = uno::Reference< awt::XLayoutContainer >(); 97 98 // 1. remove duplications and children 99 for ( ContainerList::iterator it = mxContainers.begin(); 100 it != mxContainers.end(); it++ ) 101 eraseChildren( it, mxContainers ); 102 103 // 2. check damage extent 104 for ( ContainerList::iterator it = mxContainers.begin(); 105 it != mxContainers.end(); it++ ) 106 { 107 uno::Reference< awt::XLayoutContainer > xContainer = *it; 108 while ( xContainer->getParent().is() && isContainerDamaged( xContainer ) ) 109 { 110 xContainer = uno::Reference< awt::XLayoutContainer >( 111 xContainer->getParent(), uno::UNO_QUERY ); 112 } 113 114 if ( *it != xContainer ) 115 { 116 // 2.2 replace it with parent 117 *it = xContainer; 118 119 // 2.3 remove children of new parent 120 eraseChildren( it, mxContainers ); 121 } 122 } 123 124 // 3. force re-calculations 125 for ( ContainerList::iterator it = mxContainers.begin(); 126 it != mxContainers.end(); it++ ) 127 (*it)->allocateArea( (*it)->getAllocatedArea() ); 128 } 129 }; 130 131 static void AddResizeTimeout( const uno::Reference< awt::XLayoutContainer > &xCont ) 132 { 133 static AllocateTimer timer; 134 timer.add( xCont ); 135 timer.Start(); 136 } 137 138 LayoutUnit::LayoutUnit() : LayoutUnit_Base() 139 { 140 } 141 142 void SAL_CALL LayoutUnit::queueResize( const uno::Reference< awt::XLayoutContainer > &xContainer ) 143 throw( uno::RuntimeException ) 144 { 145 AddResizeTimeout( xContainer ); 146 } 147 148 } 149