Remove deprecated SetRemoveTime API
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / controls / relayout-controller-impl.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // FILE HEADER
19
20 #include "relayout-controller-impl.h"
21
22 // EXTERNAL INCLUDES
23 #include <dali/integration-api/debug.h>
24 #if defined(DEBUG_ENABLED)
25 #include <sstream>
26 #endif // defined(DEBUG_ENABLED)
27
28 // INTERNAL INCLUDES
29 #include <dali-toolkit/public-api/controls/text-view/text-view.h>
30
31 namespace Dali
32 {
33
34 namespace Toolkit
35 {
36
37 namespace Internal
38 {
39
40 namespace
41 {
42 #if defined(DEBUG_ENABLED)
43
44 Integration::Log::Filter* gLogFilter( Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_CONTROLLER") );
45
46 /**
47  * Prints out all the children of the given actor when debug is enabled.
48  *
49  * @param[in]  actor  The actor whose children to print.
50  * @param[in]  level  The number of " | " to put in front of the children.
51  */
52 void PrintChildren( Actor actor, int level )
53 {
54   std::ostringstream output;
55
56   for ( int t = 0; t < level; ++t )
57   {
58     output << " | ";
59   }
60
61   output << actor.GetTypeName();
62
63   output << " - Pos: " << actor.GetCurrentPosition() << " Size: " << actor.GetCurrentSize() << ",";
64
65   output << " (" << actor.GetObjectPtr() << ")" << std::endl;
66
67   DALI_LOG_INFO( gLogFilter, Debug::Verbose, output.str().c_str() );
68
69   ++level;
70   unsigned int numChildren = actor.GetChildCount();
71   for( unsigned int i=0; i<numChildren; ++i )
72   {
73     PrintChildren( actor.GetChildAt(i), level );
74   }
75   --level;
76 }
77
78 /**
79  * Prints the entire hierarchy of the scene.
80  */
81 void PrintHierarchy()
82 {
83   if ( gLogFilter->IsEnabledFor( Debug::Verbose ) )
84   {
85     PrintChildren( Stage().GetCurrent().GetRootLayer(), 0 );
86   }
87 }
88
89 #define PRINT_HIERARCHY PrintHierarchy()
90
91 #else // defined(DEBUG_ENABLED)
92
93 #define PRINT_HIERARCHY
94
95 #endif // defined(DEBUG_ENABLED)
96
97 /**
98  * Sets the target to source if the individual elements of source are NOT zero.
99  *
100  * @param[out]  target  The Vector2 elements to set if the source Vector2 elements are not 0.
101  * @param[in]   source  The Vector2 elements that are to be set to the target Vector2.
102  */
103 void SetIfNotZero( Vector2& target, const Vector2& source )
104 {
105   // Only set the width if it is non zero.
106   if ( !EqualsZero( source.width ) )
107   {
108     target.width  = source.width;
109   }
110
111   // Only set the height if it is non zero.
112   if ( !EqualsZero( source.height ) )
113   {
114     target.height = source.height;
115   }
116 }
117
118 /**
119  * Finds controls in the hierarchy of actor. It descends the tree if the actor has more Actors.
120  * If it is a control, it no longer descends the tree.
121  *
122  * @param[in]  actor  The actor in which controls should be found.
123  * @param[in]  size   The size that this actor and its children should be.
124  */
125 void FindControls( Actor actor, ControlStack& controls, Vector2 size )
126 {
127   Toolkit::Control control( Toolkit::Control::DownCast( actor ) );
128   if( control )
129   {
130     // If the control size has been set by the application / control, then we should try and honour that.
131     Vector2 controlSetSize( control.GetImplementation().GetSizeSet() );
132
133     // Only set the width and height if they are non zero.
134     SetIfNotZero( size, controlSetSize );
135
136     controls.push_back( ControlSizePair( control, size ) );
137   }
138   else
139   {
140     unsigned int numChildren = actor.GetChildCount();
141     for( unsigned int i=numChildren; i>0; --i )
142     {
143       FindControls( actor.GetChildAt(i-1), controls, size );
144     }
145   }
146 }
147
148 /**
149  * Pushes the controls in the container, to the stack.
150  *
151  * @param[in,out]  controlStack  The stack to push controls to.
152  * @param[in]      container     The container to push controls from.
153  */
154 void PushToStack( ControlStack& controlStack, const ActorSizeContainer& container )
155 {
156   for ( ActorSizeContainer::const_reverse_iterator iter = container.rbegin(), endIter = container.rend(); iter != endIter; ++iter )
157   {
158     FindControls( iter->first, controlStack, iter->second );
159   }
160 }
161
162 } // unnamed namespace
163
164 RelayoutControllerImpl::RelayoutControllerImpl( bool& relayoutFlag )
165 : mRelayoutFlag( relayoutFlag ),
166   mRelayoutConnection( false )
167 {
168   // make space for 32 controls to avoid having to copy construct a lot in the beginning
169   mControlStack.reserve( 32 );
170   mSizecontainer.reserve( 32 );
171 }
172
173 RelayoutControllerImpl::~RelayoutControllerImpl()
174 {
175 }
176
177 void RelayoutControllerImpl::Request()
178 {
179   //TODO use Relayout Request to set up logic to optimize relayout of the actors/controls in the scene
180
181   if( !mRelayoutConnection )
182   {
183     Stage stage = Stage::GetCurrent();
184     stage.EventProcessingFinishedSignal().Connect( this, &RelayoutControllerImpl::Relayout );
185     mRelayoutConnection = true;
186   }
187 }
188
189 void RelayoutControllerImpl::Relayout()
190 {
191   // only do something when requested
192   if( mRelayoutFlag )
193   {
194     // clear the flag as we're now doing the relayout
195     mRelayoutFlag = false;
196     PRINT_HIERARCHY;
197
198     mControlStack.clear(); // we do not release memory, just empty the container
199
200     // 1. Finds all top-level controls from the root actor and allocate them the size of the stage
201     //    These controls are paired with the stage size and added to the stack.
202     FindControls( Stage().GetCurrent().GetRootLayer(), mControlStack, Stage::GetCurrent().GetSize() );
203
204     // 2. Iterate through the stack until it's empty.
205     while ( !mControlStack.empty() )
206     {
207       ControlSizePair pair ( mControlStack.back() );
208       Toolkit::Control control ( pair.first );
209       Vector2 size ( pair.second );
210       mControlStack.pop_back();
211
212       DALI_LOG_INFO( gLogFilter, Debug::General, "Allocating %p (%.2f, %.2f)\n", control.GetObjectPtr(), size.width, size.height );
213
214       mSizecontainer.clear();
215       // 3. Negotiate the size with the current control. Pass it an empty container which the control
216       //    has to fill with all the actors it has not done any size negotiation for.
217       control.GetImplementation().NegotiateSize( size, mSizecontainer );
218
219       // 4. Push the controls from the actors in the container to the stack.
220       PushToStack( mControlStack, mSizecontainer );
221     }
222   }
223   // should not disconnect the signal as that causes some control size negotiations to not work correctly
224   // this algorithm needs more optimization as well
225 }
226
227 } // namespace Internal
228
229 } // namespace Toolkit
230
231 } // namespace Dali