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:
AllocateTimer()42 AllocateTimer()
43 {
44 // timer set to 0 -- just process it as soon as it gets idle
45 SetTimeout( 0 );
46 }
47
isParentOf(uno::Reference<awt::XLayoutContainer> xParent,uno::Reference<awt::XLayoutContainer> xWidget)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
eraseChildren(ContainerList::iterator & it,ContainerList & list)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
isContainerDamaged(uno::Reference<awt::XLayoutContainer> xContainer)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
add(const uno::Reference<awt::XLayoutContainer> & xContainer)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
Timeout()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
AddResizeTimeout(const uno::Reference<awt::XLayoutContainer> & xCont)127 static void AddResizeTimeout( const uno::Reference< awt::XLayoutContainer > &xCont )
128 {
129 static AllocateTimer timer;
130 timer.add( xCont );
131 timer.Start();
132 }
133
LayoutUnit()134 LayoutUnit::LayoutUnit() : LayoutUnit_Base()
135 {
136 }
137
queueResize(const uno::Reference<awt::XLayoutContainer> & xContainer)138 void SAL_CALL LayoutUnit::queueResize( const uno::Reference< awt::XLayoutContainer > &xContainer )
139 throw( uno::RuntimeException )
140 {
141 AddResizeTimeout( xContainer );
142 }
143
144 }
145