Merge "Add new layouting support for TextLabel and ImageView." into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / layouting / absolute-layout-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 //CLASS HEADER
18 #include <dali-toolkit/internal/layouting/absolute-layout-impl.h>
19
20 //INTERNAL HEADERS
21 #include <dali/integration-api/debug.h>
22 #include <dali/public-api/common/extents.h>
23 #include <dali/public-api/actors/actor.h>
24 #include <dali-toolkit/devel-api/layouting/layout-item.h>
25 #include <dali-toolkit/public-api/controls/control-impl.h>
26 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
27
28 namespace
29 {
30 #if defined(DEBUG_ENABLED)
31 static Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_LAYOUT" );
32 #endif
33 }
34
35 namespace Dali
36 {
37 namespace Toolkit
38 {
39 namespace Internal
40 {
41
42 AbsoluteLayoutPtr AbsoluteLayout::New()
43 {
44   AbsoluteLayoutPtr layout( new AbsoluteLayout() );
45   return layout;
46 }
47
48 AbsoluteLayout::AbsoluteLayout()
49 : LayoutGroup()
50 {
51 }
52
53 AbsoluteLayout::~AbsoluteLayout()
54 {
55 }
56
57 void AbsoluteLayout::OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec )
58 {
59 #if defined(DEBUG_ENABLED)
60   auto actor = Actor::DownCast(GetOwner());
61
62   std::ostringstream oss;
63   oss << "AbsoluteLayout::OnMeasure  ";
64   if( actor )
65   {
66     oss << "Actor Id:" << actor.GetId() << " Name:" << actor.GetName() << "  ";
67   }
68   oss << "widthMeasureSpec:" << widthMeasureSpec << " heightMeasureSpec:" << heightMeasureSpec << std::endl;
69   DALI_LOG_INFO( gLogFilter, Debug::Concise, oss.str().c_str() );
70 #endif
71
72   LayoutLength totalHeight( 0 );
73   LayoutLength totalWidth( 0 );
74
75   struct
76   {
77     MeasuredSize::State widthState;
78     MeasuredSize::State heightState;
79   } childState = { MeasuredSize::State::MEASURED_SIZE_OK, MeasuredSize::State::MEASURED_SIZE_OK };
80
81   auto minPosition = Vector3( Vector3::ZERO );
82   auto maxPosition = Vector3( Vector3::ZERO );
83
84   // measure children
85   for( unsigned int i=0; i<GetChildCount(); ++i )
86   {
87     auto childLayout = GetChildAt( i );
88     if( childLayout )
89     {
90       auto childOwner = childLayout->GetOwner();
91
92       // Get size of child
93       MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec );
94       auto childWidth = childLayout->GetMeasuredWidth();
95       auto childHeight = childLayout->GetMeasuredHeight();
96
97       // Determine the width and height needed by the children using their given position and size.
98       // Children could overlap so find the left most and right most child.
99       auto childPosition = childOwner.GetProperty< Vector3 >( Actor::Property::POSITION );
100       minPosition.x = std::min( minPosition.x, childPosition.x );
101       maxPosition.x = std::max( maxPosition.x, childPosition.x + childWidth );
102       // Children could overlap so find the highest and lowest child.
103       minPosition.y = std::min( minPosition.y, childPosition.y );
104       maxPosition.y = std::max( maxPosition.y, childPosition.y + childHeight );
105
106       // Store current width and height needed to contain all children.
107       totalWidth = maxPosition.x - minPosition.x;
108       totalHeight = maxPosition.y - minPosition.y;
109       DALI_LOG_INFO( gLogFilter, Debug::Concise, "AbsoluteLayout::OnMeasure child width(%f) height(%f) \n", (float)totalWidth, (float)totalHeight  );
110
111       if( childLayout->GetMeasuredWidthAndState().GetState() == MeasuredSize::State::MEASURED_SIZE_TOO_SMALL )
112       {
113         childState.widthState = MeasuredSize::State::MEASURED_SIZE_TOO_SMALL;
114       }
115       if( childLayout->GetMeasuredHeightAndState().GetState() == MeasuredSize::State::MEASURED_SIZE_TOO_SMALL )
116       {
117         childState.heightState = MeasuredSize::State::MEASURED_SIZE_TOO_SMALL;
118       }
119     }
120   }
121
122   MeasuredSize widthSizeAndState = ResolveSizeAndState( totalWidth, widthMeasureSpec, MeasuredSize::State::MEASURED_SIZE_OK);
123   MeasuredSize heightSizeAndState = ResolveSizeAndState( totalHeight, heightMeasureSpec, MeasuredSize::State::MEASURED_SIZE_OK);
124   totalWidth = widthSizeAndState.GetSize();
125   totalHeight = heightSizeAndState.GetSize();
126
127   // Ensure layout respects it's given minimum size
128   totalWidth = std::max( totalWidth, GetSuggestedMinimumWidth() );
129   totalHeight = std::max( totalHeight, GetSuggestedMinimumHeight() );
130
131   widthSizeAndState.SetState( childState.widthState );
132   heightSizeAndState.SetState( childState.heightState );
133
134   SetMeasuredDimensions( ResolveSizeAndState( totalWidth, widthMeasureSpec, childState.widthState ),
135                          ResolveSizeAndState( totalHeight, heightMeasureSpec, childState.heightState ) );
136
137 }
138
139 void AbsoluteLayout::OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
140 {
141   // Absolute layout positions it's children at their Actor positions.
142   // Children could overlap or spill outside the parent, as is the nature of absolute positions.
143   auto count = GetChildCount();
144
145   for( unsigned int i = 0; i < count; i++)
146   {
147     LayoutItemPtr childLayout = GetChildAt( i );
148     if( childLayout != nullptr )
149     {
150       auto childOwner = childLayout->GetOwner();
151       auto childWidth = childLayout->GetMeasuredWidth();
152       auto childHeight = childLayout->GetMeasuredHeight();
153
154       auto childPosition = childOwner.GetProperty< Vector3 >( Actor::Property::POSITION );
155
156       auto childTop = childPosition.y;
157       auto childLeft = childPosition.x;
158
159       childLayout->Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight );
160     }
161   }
162 }
163
164 } // namespace Internal
165 } // namespace Toolkit
166 } // namespace Dali