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