2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include "relayout-controller-impl.h"
23 #include <dali/public-api/actors/layer.h>
24 #include <dali/public-api/common/stage.h>
25 #include <dali/integration-api/debug.h>
27 #if defined(DEBUG_ENABLED)
29 #endif // defined(DEBUG_ENABLED)
32 #include <dali-toolkit/public-api/controls/text-view/text-view.h>
45 #if defined(DEBUG_ENABLED)
47 Integration::Log::Filter* gLogFilter( Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_CONTROLLER") );
50 * Prints out all the children of the given actor when debug is enabled.
52 * @param[in] actor The actor whose children to print.
53 * @param[in] level The number of " | " to put in front of the children.
55 void PrintChildren( Actor actor, int level )
57 std::ostringstream output;
59 for ( int t = 0; t < level; ++t )
64 output << actor.GetTypeName();
66 output << " - Pos: " << actor.GetCurrentPosition() << " Size: " << actor.GetCurrentSize() << ",";
68 output << " (" << actor.GetObjectPtr() << ")" << std::endl;
70 DALI_LOG_INFO( gLogFilter, Debug::Verbose, output.str().c_str() );
73 unsigned int numChildren = actor.GetChildCount();
74 for( unsigned int i=0; i<numChildren; ++i )
76 PrintChildren( actor.GetChildAt(i), level );
82 * Prints the entire hierarchy of the scene.
86 if ( gLogFilter->IsEnabledFor( Debug::Verbose ) )
88 PrintChildren( Stage().GetCurrent().GetRootLayer(), 0 );
92 #define PRINT_HIERARCHY PrintHierarchy()
94 #else // defined(DEBUG_ENABLED)
96 #define PRINT_HIERARCHY
98 #endif // defined(DEBUG_ENABLED)
101 * Sets the target to source if the individual elements of source are NOT zero.
103 * @param[out] target The Vector2 elements to set if the source Vector2 elements are not 0.
104 * @param[in] source The Vector2 elements that are to be set to the target Vector2.
106 void SetIfNotZero( Vector2& target, const Vector2& source )
108 // Only set the width if it is non zero.
109 if ( !EqualsZero( source.width ) )
111 target.width = source.width;
114 // Only set the height if it is non zero.
115 if ( !EqualsZero( source.height ) )
117 target.height = source.height;
122 * Finds controls in the hierarchy of actor. It descends the tree if the actor has more Actors.
123 * If it is a control, it no longer descends the tree.
125 * @param[in] actor The actor in which controls should be found.
126 * @param[in] size The size that this actor and its children should be.
128 void FindControls( Actor actor, ControlStack& controls, Vector2 size )
130 Toolkit::Control control( Toolkit::Control::DownCast( actor ) );
133 // If the control size has been set by the application / control, then we should try and honour that.
134 Vector2 controlSetSize( control.GetImplementation().GetSizeSet() );
136 // Only set the width and height if they are non zero.
137 SetIfNotZero( size, controlSetSize );
139 controls.push_back( ControlSizePair( control, size ) );
143 unsigned int numChildren = actor.GetChildCount();
144 for( unsigned int i=numChildren; i>0; --i )
146 FindControls( actor.GetChildAt(i-1), controls, size );
152 * Pushes the controls in the container, to the stack.
154 * @param[in,out] controlStack The stack to push controls to.
155 * @param[in] container The container to push controls from.
157 void PushToStack( ControlStack& controlStack, const ActorSizeContainer& container )
159 for ( ActorSizeContainer::const_reverse_iterator iter = container.rbegin(), endIter = container.rend(); iter != endIter; ++iter )
161 FindControls( iter->first, controlStack, iter->second );
165 } // unnamed namespace
167 RelayoutControllerImpl::RelayoutControllerImpl( bool& relayoutFlag )
168 : mRelayoutFlag( relayoutFlag ),
169 mRelayoutConnection( false )
171 // make space for 32 controls to avoid having to copy construct a lot in the beginning
172 mControlStack.reserve( 32 );
173 mSizecontainer.reserve( 32 );
176 RelayoutControllerImpl::~RelayoutControllerImpl()
180 void RelayoutControllerImpl::Request()
182 //TODO use Relayout Request to set up logic to optimize relayout of the actors/controls in the scene
184 if( !mRelayoutConnection )
186 Stage stage = Stage::GetCurrent();
187 stage.EventProcessingFinishedSignal().Connect( this, &RelayoutControllerImpl::Relayout );
188 mRelayoutConnection = true;
192 void RelayoutControllerImpl::Relayout()
194 // only do something when requested
197 // clear the flag as we're now doing the relayout
198 mRelayoutFlag = false;
201 mControlStack.clear(); // we do not release memory, just empty the container
203 // 1. Finds all top-level controls from the root actor and allocate them the size of the stage
204 // These controls are paired with the stage size and added to the stack.
205 FindControls( Stage().GetCurrent().GetRootLayer(), mControlStack, Stage::GetCurrent().GetSize() );
207 // 2. Iterate through the stack until it's empty.
208 while ( !mControlStack.empty() )
210 ControlSizePair pair ( mControlStack.back() );
211 Toolkit::Control control ( pair.first );
212 Vector2 size ( pair.second );
213 mControlStack.pop_back();
215 DALI_LOG_INFO( gLogFilter, Debug::General, "Allocating %p (%.2f, %.2f)\n", control.GetObjectPtr(), size.width, size.height );
217 mSizecontainer.clear();
218 // 3. Negotiate the size with the current control. Pass it an empty container which the control
219 // has to fill with all the actors it has not done any size negotiation for.
220 control.GetImplementation().NegotiateSize( size, mSizecontainer );
222 // 4. Push the controls from the actors in the container to the stack.
223 PushToStack( mControlStack, mSizecontainer );
226 // should not disconnect the signal as that causes some control size negotiations to not work correctly
227 // this algorithm needs more optimization as well
230 } // namespace Internal
232 } // namespace Toolkit