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