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