1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #include "timer.hxx" 25 26 #include <vector> 27 #include <list> 28 #include <vcl/timer.hxx> 29 #include <com/sun/star/awt/XLayoutContainer.hpp> 30 31 namespace layoutimpl 32 { 33 using namespace ::com::sun::star; 34 35 class AllocateTimer : public Timer 36 { 37 typedef std::list< uno::Reference< awt::XLayoutContainer > > ContainerList; 38 ContainerList mxContainers; 39 uno::Reference< awt::XLayoutContainer > mxLastAdded; 40 41 public: 42 AllocateTimer() 43 { 44 // timer set to 0 -- just process it as soon as it gets idle 45 SetTimeout( 0 ); 46 } 47 48 static inline bool isParentOf( uno::Reference< awt::XLayoutContainer > xParent, 49 uno::Reference< awt::XLayoutContainer > xWidget ) 50 { 51 while ( xWidget.is() ) 52 { 53 if ( xWidget == xParent ) 54 return true; 55 xWidget = uno::Reference< awt::XLayoutContainer >( xWidget->getParent(), uno::UNO_QUERY ); 56 } 57 return false; 58 } 59 60 static inline void eraseChildren( ContainerList::iterator &it, ContainerList &list ) 61 { 62 ContainerList::iterator jt = list.begin(); 63 while ( jt != list.end() ) 64 { 65 if ( it != jt && isParentOf( *it, *jt ) ) 66 jt = list.erase( jt ); 67 else 68 jt++; 69 } 70 } 71 72 static inline bool isContainerDamaged( uno::Reference< awt::XLayoutContainer > xContainer ) 73 { 74 uno::Reference< awt::XLayoutConstrains > xConstrains( xContainer, uno::UNO_QUERY ); 75 awt::Size lastReq( xContainer->getRequestedSize() ); 76 awt::Size curReq( xConstrains->getMinimumSize() ); 77 return lastReq.Width != curReq.Width || lastReq.Height != curReq.Height; 78 } 79 80 void add( const uno::Reference< awt::XLayoutContainer > &xContainer ) 81 { 82 // small optimization 83 if ( mxLastAdded == xContainer ) 84 return; 85 mxLastAdded = xContainer; 86 87 mxContainers.push_back( xContainer ); 88 } 89 90 virtual void Timeout() 91 { 92 mxLastAdded = uno::Reference< awt::XLayoutContainer >(); 93 94 // 1. remove duplications and children 95 for ( ContainerList::iterator it = mxContainers.begin(); 96 it != mxContainers.end(); it++ ) 97 eraseChildren( it, mxContainers ); 98 99 // 2. check damage extent 100 for ( ContainerList::iterator it = mxContainers.begin(); 101 it != mxContainers.end(); it++ ) 102 { 103 uno::Reference< awt::XLayoutContainer > xContainer = *it; 104 while ( xContainer->getParent().is() && isContainerDamaged( xContainer ) ) 105 { 106 xContainer = uno::Reference< awt::XLayoutContainer >( 107 xContainer->getParent(), uno::UNO_QUERY ); 108 } 109 110 if ( *it != xContainer ) 111 { 112 // 2.2 replace it with parent 113 *it = xContainer; 114 115 // 2.3 remove children of new parent 116 eraseChildren( it, mxContainers ); 117 } 118 } 119 120 // 3. force re-calculations 121 for ( ContainerList::iterator it = mxContainers.begin(); 122 it != mxContainers.end(); it++ ) 123 (*it)->allocateArea( (*it)->getAllocatedArea() ); 124 } 125 }; 126 127 static void AddResizeTimeout( const uno::Reference< awt::XLayoutContainer > &xCont ) 128 { 129 static AllocateTimer timer; 130 timer.add( xCont ); 131 timer.Start(); 132 } 133 134 LayoutUnit::LayoutUnit() : LayoutUnit_Base() 135 { 136 } 137 138 void SAL_CALL LayoutUnit::queueResize( const uno::Reference< awt::XLayoutContainer > &xContainer ) 139 throw( uno::RuntimeException ) 140 { 141 AddResizeTimeout( xContainer ); 142 } 143 144 } 145