30beba45345a94d41905e76f3c982dfe49f6bb48
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / layouting / layout-controller-impl.cpp
1 /*
2  * Copyright (c) 2018 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 #include <dali/public-api/common/stage.h>
18 #include <dali/public-api/actors/layer.h>
19 #include <dali-toolkit/internal/layouting/layout-controller-impl.h>
20 #include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
21 #include <dali-toolkit/public-api/controls/control.h>
22 #include <dali-toolkit/public-api/controls/control-impl.h>
23 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
24 #include <dali-toolkit/internal/layouting/layout-controller-debug.h>
25
26 using namespace Dali;
27
28 #if defined(DEBUG_ENABLED)
29 static Debug::Filter* gLogFilter = Debug::Filter::New( Debug::Concise, false, "LOG_LAYOUT" );
30 #endif
31
32 namespace Dali
33 {
34 namespace Toolkit
35 {
36 namespace Internal
37 {
38
39 LayoutController::LayoutController()
40 : mLayoutRequested(false)
41 {
42 }
43
44 LayoutController::~LayoutController()
45 {
46 }
47
48 void LayoutController::Initialize()
49 {
50 }
51
52 void LayoutController::RequestLayout( LayoutBase& layoutBase )
53 {
54   DALI_LOG_INFO( gLogFilter, Debug::Concise, "LayoutController::RequestLayout\n" );
55   mLayoutRequested = true;
56
57   // Go up the tree and mark all parents to relayout
58   LayoutParent* layoutParent = layoutBase.GetParent();
59   if( layoutParent )
60   {
61     LayoutGroup& layoutGroup = static_cast< LayoutGroup& >( *layoutParent );
62     if( ! layoutGroup.IsLayoutRequested() )
63     {
64       layoutGroup.RequestLayout();
65     }
66   }
67 }
68
69 void LayoutController::Process()
70 {
71   // Perform the full process.
72
73   if( mLayoutRequested )
74   {
75     mLayoutRequested = false;
76
77     // If window size has changed, expect stage to have already been updated
78     Stage stage = Stage::GetCurrent();
79     auto stageWidth  = stage.GetSize().width;
80     auto stageHeight = stage.GetSize().height;
81
82     auto widthSpec = MeasureSpec( stageWidth, MeasureSpec::Mode::EXACTLY );
83     auto heightSpec = MeasureSpec( stageHeight, MeasureSpec::Mode::EXACTLY );
84
85     // Test how to perform a measure on each control.
86     MeasureHierarchy( stage.GetRootLayer(), widthSpec, heightSpec );
87
88     LAYOUT_DEBUG_MEASURE_STATES( stage.GetRootLayer() );
89     PerformLayout( stage.GetRootLayer(), 0, 0, stageWidth, stageHeight );
90
91     LAYOUT_DEBUG_AFTER_LAYOUT( stage.GetRootLayer() );
92   }
93 }
94
95 void LayoutController::MeasureHierarchy( Actor root, MeasureSpec widthSpec, MeasureSpec heightSpec )
96 {
97   // Does this actor have a layout?
98   // Yes - measure the layout. It will call this method again for each of it's children.
99   // No - recurse through actor children.
100   //
101   // If in a leaf actor with no layout, it's natural size is bubbled back up.
102   //
103   // What happens if nothing in the tree has a layout?
104
105   Toolkit::Control control = Toolkit::Control::DownCast( root );
106   if( control )
107   {
108     Internal::Control& controlImpl = GetImplementation( control );
109     Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl );
110     LayoutBasePtr layout = controlDataImpl.GetLayout();
111
112     if( layout )
113     {
114       layout->Measure( widthSpec, heightSpec );
115     }
116   }
117   else
118   {
119     // Depth first descent through actor children
120     for( unsigned int i = 0, count = root.GetChildCount(); i < count; ++i )
121     {
122       Actor child = root.GetChildAt( i );
123       MeasureHierarchy( child, widthSpec, heightSpec );
124     }
125   }
126 }
127
128 void LayoutController::PerformLayout( Actor root, int left, int top, int right, int bottom )
129 {
130   Toolkit::Control control = Toolkit::Control::DownCast( root );
131   if( control )
132   {
133     Internal::Control& controlImpl = GetImplementation( control );
134     Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl );
135     LayoutBasePtr layout = controlDataImpl.GetLayout();
136
137     if( layout )
138     {
139       layout->Layout( left, top, right, bottom );
140     }
141   }
142   else
143   {
144     // Depth first descent through actor children
145     for( unsigned int i = 0, count = root.GetChildCount(); i < count; ++i )
146     {
147       Actor child = root.GetChildAt( i );
148       PerformLayout( child, left, top, right, bottom );
149     }
150   }
151 }
152
153
154 } // namespace Internal
155 } // namespace Toolkit
156 } // namespace Dali