2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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
8 // http://floralicense.org/license/
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.
19 #include "relayout-controller-impl.h"
25 #include <dali/integration-api/debug.h>
29 #include "dali-toolkit/public-api/controls/control.h"
30 #include "dali-toolkit/public-api/controls/control-impl.h"
31 #include "dali-toolkit/public-api/controls/text-view/text-view.h"
39 typedef std::pair< Control, Vector2 > ControlSizePair;
40 typedef std::stack< ControlSizePair > ControlStack;
47 #if defined(DEBUG_ENABLED)
49 Integration::Log::Filter* gLogFilter( Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_CONTROLLER") );
52 * Prints out all the children of the given actor when debug is enabled.
54 * @param[in] actor The actor whose children to print.
55 * @param[in] level The number of " | " to put in front of the children.
57 void PrintChildren( Actor actor, int level )
59 std::ostringstream output;
61 for ( int t = 0; t < level; ++t )
66 output << actor.GetTypeName();
68 output << " - Pos: " << actor.GetCurrentPosition() << " Size: " << actor.GetCurrentSize() << ",";
70 output << " (" << actor.GetObjectPtr() << ")" << std::endl;
72 DALI_LOG_INFO( gLogFilter, Debug::Verbose, output.str().c_str() );
75 unsigned int numChildren = actor.GetChildCount();
76 for( unsigned int i=0; i<numChildren; ++i )
78 PrintChildren( actor.GetChildAt(i), level );
84 * Prints the entire hierarchy of the scene.
88 if ( gLogFilter->IsEnabledFor( Debug::Verbose ) )
90 PrintChildren( Stage().GetCurrent().GetRootLayer(), 0 );
94 #define PRINT_HIERARCHY PrintHierarchy()
96 #else // defined(DEBUG_ENABLED)
98 #define PRINT_HIERARCHY
100 #endif // defined(DEBUG_ENABLED)
103 * Sets the target to source if the individual elements of source are NOT zero.
105 * @param[out] target The Vector2 elements to set if the source Vector2 elements are not 0.
106 * @param[in] source The Vector2 elements that are to be set to the target Vector2.
108 void SetIfNotZero( Vector2& target, const Vector2& source )
110 // Only set the width if it is non zero.
111 if ( !EqualsZero( source.width ) )
113 target.width = source.width;
116 // Only set the height if it is non zero.
117 if ( !EqualsZero( source.height ) )
119 target.height = source.height;
124 * Finds controls in the hierarchy of actor. It descends the tree if the actor has more Actors.
125 * If it is a control, it no longer descends the tree.
127 * @param[in] actor The actor in which controls should be found.
128 * @param[in] size The size that this actor and its children should be.
130 void FindControls( Actor actor, ControlStack& controls, Vector2 size )
132 Control control( Control::DownCast( actor ) );
135 // If the control size has been set by the application / control, then we should try and honour that.
136 Vector2 controlSetSize( control.GetImplementation().GetSizeSet() );
138 // Only set the width and height if they are non zero.
139 SetIfNotZero( size, controlSetSize );
141 controls.push( ControlSizePair( control, size ) );
145 unsigned int numChildren = actor.GetChildCount();
146 for( unsigned int i=numChildren; i>0; --i )
148 FindControls( actor.GetChildAt(i-1), controls, size );
154 * Pushes the controls in the container, to the stack.
156 * @param[in,out] controlStack The stack to push controls to.
157 * @param[in] container The container to push controls from.
159 void PushToStack( ControlStack& controlStack, const ActorSizeContainer& container )
161 for ( ActorSizeContainer::const_reverse_iterator iter = container.rbegin(), endIter = container.rend(); iter != endIter; ++iter )
163 FindControls( iter->first, controlStack, iter->second );
167 } // unnamed namespace
169 RelayoutControllerImpl::~RelayoutControllerImpl()
173 void RelayoutControllerImpl::Request()
175 //TODO use Relayout Request to set up logic to optimize relayout of the actors/controls in the scene
177 if( !mRelayoutConnection )
179 Stage stage = Stage::GetCurrent();
180 stage.EventProcessingFinishedSignal().Connect( this, &RelayoutControllerImpl::Relayout );
181 mRelayoutConnection = true;
185 void RelayoutControllerImpl::Relayout()
189 // 1. Finds all top-level controls from the root actor and allocate them the size of the stage
190 // These controls are paired with the stage size and added to the stack.
191 ControlStack controlStack;
192 FindControls( Stage().GetCurrent().GetRootLayer(), controlStack, Stage::GetCurrent().GetSize() );
194 // 2. Iterate through the stack until it's empty.
195 while ( !controlStack.empty() )
197 ControlSizePair pair ( controlStack.top() );
198 Control control ( pair.first );
199 Vector2 size ( pair.second );
202 DALI_LOG_INFO( gLogFilter, Debug::General, "Allocating %p (%.2f, %.2f)\n", control.GetObjectPtr(), size.width, size.height );
204 // 3. Negotiate the size with the current control. Pass it an empty container which the control
205 // has to fill with all the actors it has not done any size negotiation for.
206 ActorSizeContainer container;
207 control.GetImplementation().NegotiateSize( size, container );
209 // 4. Push the controls from the actors in the container to the stack.
210 PushToStack( controlStack, container );
213 //Disconnect so that we relayout only when requested to do so.
217 void RelayoutControllerImpl::Disconnect()
219 if( mRelayoutConnection )
221 Stage stage = Stage::GetCurrent();
222 stage.EventProcessingFinishedSignal().Disconnect( this, &RelayoutControllerImpl::Relayout );
223 mRelayoutConnection = false;
227 RelayoutControllerImpl::RelayoutControllerImpl()
228 : mRelayoutConnection( false )
232 } // namespace Internal
234 } // namespace Toolkit