xref: /trunk/main/toolkit/source/layout/core/timer.cxx (revision b0724fc6)
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