2 * Copyright (c) 2018 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.
17 #include <dali/integration-api/debug.h>
19 #include <dali/public-api/animation/animation.h>
20 #include <dali/public-api/object/base-handle.h>
21 #include <dali/public-api/object/type-registry-helper.h>
22 #include <dali-toolkit/public-api/controls/control.h>
23 #include <dali/devel-api/object/handle-devel.h>
24 #include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
25 #include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
26 #include <dali-toolkit/internal/layouting/layout-transition-data-impl.h>
27 #include <dali-toolkit/internal/layouting/layout-item-data-impl.h>
29 #include <dali/devel-api/scripting/enum-helper.h>
33 #if defined(DEBUG_ENABLED)
34 Debug::Filter* gLayoutFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_LAYOUT" );
38 const char* TOKEN_CONDITION("condition");
39 const char* TOKEN_PROPERTY("property");
40 const char* TOKEN_INITIAL_VALUE("initialValue");
41 const char* TOKEN_TARGET_VALUE("targetValue");
42 const char* TOKEN_ANIMATOR("animator");
43 const char* TOKEN_TYPE("type");
44 const char* TOKEN_NAME("name");
45 const char* TOKEN_TIME_PERIOD("timePeriod");
46 const char* TOKEN_DURATION("duration");
47 const char* TOKEN_DELAY("delay");
48 const char* TOKEN_ALPHA_FUNCTION("alphaFunction");
50 DALI_ENUM_TO_STRING_TABLE_BEGIN( ALPHA_FUNCTION_BUILTIN )
51 DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, LINEAR)
52 DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, REVERSE)
53 DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_IN)
54 DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_OUT)
55 DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_IN_OUT)
56 DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_IN_SQUARE)
57 DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_OUT_SQUARE)
58 DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_IN_SINE)
59 DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_OUT_SINE)
60 DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_IN_OUT_SINE)
61 DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_OUT_BACK)
62 DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, BOUNCE)
63 DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, SIN)
64 DALI_ENUM_TO_STRING_TABLE_END( ALPHA_FUNCTION_BUILTIN )
75 LayoutTransitionData::LayoutTransitionData()
79 LayoutTransitionData::~LayoutTransitionData()
83 LayoutTransitionDataPtr LayoutTransitionData::New()
85 LayoutTransitionDataPtr layoutAnimationData( new LayoutTransitionData() );
86 return layoutAnimationData;
89 LayoutTransitionData::PropertyAnimator::PropertyAnimator( )
92 , interpolation( Animation::Linear )
96 LayoutTransitionData::PropertyAnimator::PropertyAnimator( Actor actor, Property::Map map )
99 , interpolation( Animation::Linear )
103 LayoutTransitionData::PropertyAnimator::PropertyAnimator( Actor actor, Property::Map map, Path path, Vector3 forward )
106 , interpolation( Animation::Linear )
112 LayoutTransitionData::PropertyAnimator::PropertyAnimator( Actor actor, Property::Map map, KeyFrames keyFrames, Animation::Interpolation interpolation )
115 , keyFrames( keyFrames )
116 , interpolation( interpolation )
120 void LayoutTransitionData::AddPropertyAnimator( Actor actor, Property::Map map )
122 mPropertyAnimators.push_back( PropertyAnimator( actor, map ) );
125 void LayoutTransitionData::AddPropertyAnimator( Actor actor, Property::Map map, KeyFrames keyFrames, Animation::Interpolation interpolation )
127 mPropertyAnimators.push_back( PropertyAnimator( actor, map, keyFrames, interpolation ) );
130 void LayoutTransitionData::AddPropertyAnimator( Actor actor, Property::Map map, Path path, Vector3 forward )
132 mPropertyAnimators.push_back( PropertyAnimator( actor, map, path, forward ) );
135 bool LayoutTransitionData::ConvertToLayoutAnimator( const Property::Map& animatorMap, const PropertyAnimator& propertyAnimator, LayoutDataAnimator& layoutDataAnimator )
139 for ( size_t animatorMapIdx = 0; animatorMapIdx < animatorMap.Count(); ++animatorMapIdx )
141 const KeyValuePair pair( animatorMap.GetKeyValue( animatorMapIdx ) );
143 Property::Index indexKey = Property::INVALID_INDEX;
144 if ( pair.first.type == Property::Key::STRING )
146 const std::string& key(pair.first.stringKey);
147 if( key == TOKEN_TYPE )
149 indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::TYPE;
151 else if( key == TOKEN_NAME )
153 indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::NAME;
155 else if( key == TOKEN_TIME_PERIOD )
157 indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::TIME_PERIOD;
159 else if( key == TOKEN_ALPHA_FUNCTION )
161 indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION;
166 indexKey = pair.first.indexKey;
169 const Property::Value& value( pair.second );
171 if ( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION )
173 if ( value.GetType() == Property::ARRAY )
176 Vector4 controlPoints;
177 Property::Array *array = value.GetArray();
178 if ( array && array->Count() >= 4 )
180 for ( size_t vecIdx = 0; vecIdx < 4; ++vecIdx )
182 Property::Value& v = array->GetElementAt( vecIdx );
183 if ( v.GetType() == Property::FLOAT )
185 controlPoints[vecIdx] = v.Get<float>();
201 Vector2 controlPoint1( controlPoints.x, controlPoints.y );
202 Vector2 controlPoint2( controlPoints.z, controlPoints.w );
203 layoutDataAnimator.alphaFunction = AlphaFunction( controlPoint1, controlPoint2 );
210 else if ( value.GetType() == Property::VECTOR4 )
212 Vector4 controlPoints = value.Get<Vector4>();
213 Vector2 controlPoint1( controlPoints.x, controlPoints.y );
214 Vector2 controlPoint2( controlPoints.z, controlPoints.w );
215 layoutDataAnimator.alphaFunction = AlphaFunction( controlPoint1, controlPoint2 );
217 else if ( value.GetType() == Property::INTEGER )
219 layoutDataAnimator.alphaFunction = AlphaFunction( static_cast<AlphaFunction::BuiltinFunction>( value.Get<int>() ) );
221 else if ( value.GetType() == Property::STRING )
223 std::string alphaFunctionValue = value.Get<std::string>();
225 if ( alphaFunctionValue == "LINEAR" )
227 layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::LINEAR );
229 else if ( !alphaFunctionValue.compare( 0, 5, "EASE_" ) )
231 if ( alphaFunctionValue == "EASE_IN" )
233 layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_IN );
235 else if ( alphaFunctionValue == "EASE_OUT" )
237 layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_OUT );
239 else if ( !alphaFunctionValue.compare( 5, 3, "IN_" ) )
241 if ( !alphaFunctionValue.compare( 8, -1, "SQUARE" ) )
243 layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_IN_SQUARE );
245 else if ( !alphaFunctionValue.compare( 8, -1, "OUT" ) )
247 layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_IN_OUT );
249 else if ( !alphaFunctionValue.compare( 8, -1, "OUT_SINE" ) )
251 layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_IN_OUT_SINE );
253 else if ( !alphaFunctionValue.compare( 8, -1, "SINE" ) )
255 layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_IN_SINE );
258 else if ( !alphaFunctionValue.compare( 5, 4, "OUT_" ) )
260 if ( !alphaFunctionValue.compare( 9, -1, "SQUARE" ) )
262 layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_OUT_SQUARE );
264 else if ( !alphaFunctionValue.compare( 9, -1, "SINE" ) )
266 layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_OUT_SINE );
268 else if ( !alphaFunctionValue.compare( 9, -1, "BACK" ) )
270 layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_OUT_BACK );
274 else if ( alphaFunctionValue == "REVERSE" )
276 layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::REVERSE );
278 else if ( alphaFunctionValue == "BOUNCE" )
280 layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::BOUNCE );
282 else if ( alphaFunctionValue == "SIN" )
284 layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::SIN );
296 else if ( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::NAME )
298 if( value.GetType() == Property::STRING )
300 layoutDataAnimator.name = value.Get<std::string>();
303 else if ( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::TYPE )
305 if( value.GetType() == Property::STRING )
307 std::string animatorType = value.Get<std::string>();
308 if( animatorType == "ANIMATE_TO" )
310 layoutDataAnimator.animatorType = LayoutDataAnimator::AnimatorType::ANIMATE_TO;
312 else if( animatorType == "ANIMATE_BY" )
314 layoutDataAnimator.animatorType = LayoutDataAnimator::AnimatorType::ANIMATE_BY;
316 else if( animatorType == "ANIMATE_BETWEEN" )
318 layoutDataAnimator.animatorType = LayoutDataAnimator::AnimatorType::ANIMATE_BETWEEN;
319 layoutDataAnimator.keyFrames = propertyAnimator.keyFrames;
321 else if( animatorType == "ANIMATE_PATH" )
323 layoutDataAnimator.animatorType = LayoutDataAnimator::AnimatorType::ANIMATE_PATH;
324 layoutDataAnimator.path = propertyAnimator.path;
325 layoutDataAnimator.forward = propertyAnimator.forward;
329 else if ( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::TIME_PERIOD )
331 Property::Map timeMap = value.Get<Property::Map>();
332 for ( size_t timeMapIdx = 0; timeMapIdx < timeMap.Count(); ++timeMapIdx )
334 const KeyValuePair pair( timeMap.GetKeyValue( timeMapIdx ) );
335 indexKey = Property::INVALID_INDEX;
337 if ( pair.first.type == Property::Key::STRING)
339 const std::string& key( pair.first.stringKey );
340 if( key == TOKEN_DURATION )
342 indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::DURATION;
344 else if( key == TOKEN_DELAY )
346 indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::DELAY;
351 indexKey = pair.first.indexKey;
354 if ( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::DELAY )
356 layoutDataAnimator.timePeriod.delaySeconds = pair.second.Get<float>();
358 else if ( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::DURATION )
360 layoutDataAnimator.timePeriod.durationSeconds = pair.second.Get<float>();
369 bool LayoutTransitionData::ConvertToLayoutDataElement( const PropertyAnimator& propertyAnimator, LayoutDataElement& layoutDataElement, LayoutData& layoutData )
371 const Property::Map& map = propertyAnimator.map;
372 bool propertyFound = false;
374 for( unsigned int mapIdx = 0; mapIdx < map.Count(); ++mapIdx )
376 const KeyValuePair pair( map.GetKeyValue( mapIdx ) );
377 const Property::Value& value( pair.second );
378 Property::Index indexKey = Property::INVALID_INDEX;
380 if ( pair.first.type == Property::Key::STRING )
382 const std::string& key( pair.first.stringKey );
383 if ( key == TOKEN_CONDITION )
385 indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::CONDITION;
387 if ( key == TOKEN_PROPERTY )
389 indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::PROPERTY;
391 else if( key == TOKEN_INITIAL_VALUE )
393 indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::INITIAL_VALUE;
395 else if( key == TOKEN_TARGET_VALUE )
397 indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::TARGET_VALUE;
399 else if( key == TOKEN_ANIMATOR )
401 indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::ANIMATOR;
406 indexKey = pair.first.indexKey;
409 if( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::CONDITION )
411 layoutDataElement.condition = value.Get<int>();
413 else if( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::PROPERTY )
415 if( value.GetType() == Property::STRING )
417 Actor actor = Actor::DownCast( layoutDataElement.handle );
418 layoutDataElement.propertyIndex = DevelHandle::GetPropertyIndex( actor, Property::Key( value.Get<std::string>() ) );
422 layoutDataElement.propertyIndex = value.Get<int>();
424 propertyFound = true;
426 else if( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::INITIAL_VALUE )
428 layoutDataElement.initialValue = value;
430 else if( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::TARGET_VALUE )
432 layoutDataElement.targetValue = value;
434 else if( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::ANIMATOR )
436 if( value.GetType() == Property::STRING )
438 std::string animatorName = value.Get<std::string>();
439 if ( animatorName.empty() )
441 layoutDataElement.animatorIndex = 0;
445 auto animator = std::find_if( layoutData.layoutAnimatorArray.begin(), layoutData.layoutAnimatorArray.end(), [&animatorName](const LayoutDataAnimator& iter) {
446 return (iter.name == animatorName); } );
447 if( animator != layoutData.layoutAnimatorArray.end() )
449 layoutDataElement.animatorIndex = std::distance( layoutData.layoutAnimatorArray.begin(), animator );
453 else if ( value.GetType() == Property::MAP )
455 Property::Map animatorMap = value.Get< Property::Map >();
456 LayoutDataAnimator layoutDataAnimator;
457 if( ConvertToLayoutAnimator( animatorMap, propertyAnimator, layoutDataAnimator ) )
459 layoutData.layoutAnimatorArray.push_back( layoutDataAnimator );
460 layoutDataElement.animatorIndex = layoutData.layoutAnimatorArray.size()-1;
466 return propertyFound;
469 void LayoutTransitionData::ConvertChildrenAnimatorsToLayoutDataElements( Actor child, LayoutData& layoutData )
471 LayoutDataArray& layoutDataArray = layoutData.layoutDataArray;
472 // Add the children animators
473 for( const PropertyAnimator& iter : layoutData.childrenPropertyAnimators )
475 LayoutDataElement layoutDataElement;
476 layoutDataElement.handle = child;
477 layoutDataElement.positionDataIndex = layoutData.layoutPositionDataArray.size() - 1;
479 if( ConvertToLayoutDataElement( iter, layoutDataElement, layoutData ) )
481 switch ( layoutDataElement.condition )
483 case Dali::Toolkit::LayoutTransitionData::Condition::ON_ADD:
484 if ( layoutData.layoutTransition.layoutTransitionType != Dali::Toolkit::LayoutTransitionData::ON_CHILD_ADD
485 || layoutData.layoutTransition.gainedChild != child )
490 case Dali::Toolkit::LayoutTransitionData::Condition::ON_REMOVE:
491 if( layoutData.layoutTransition.layoutTransitionType != Dali::Toolkit::LayoutTransitionData::ON_CHILD_REMOVE
492 || layoutData.layoutTransition.lostChild != child )
497 case Dali::Toolkit::LayoutTransitionData::Condition::ON_FOCUS_GAINED:
498 if( layoutData.layoutTransition.layoutTransitionType != Dali::Toolkit::LayoutTransitionData::ON_CHILD_FOCUS
499 || layoutData.layoutTransition.gainedChild != child )
504 case Dali::Toolkit::LayoutTransitionData::Condition::ON_FOCUS_LOST:
505 if( layoutData.layoutTransition.layoutTransitionType != Dali::Toolkit::LayoutTransitionData::ON_CHILD_FOCUS
506 || layoutData.layoutTransition.lostChild != child )
515 layoutDataArray.push_back( layoutDataElement );
520 void LayoutTransitionData::ConvertToLayoutDataElements( Actor owner, LayoutData& layoutData )
522 LayoutDataArray& layoutDataArray = layoutData.layoutDataArray;
524 // Add the children animators
525 ConvertChildrenAnimatorsToLayoutDataElements( owner, layoutData );
527 // Add the transition animators
528 for( const PropertyAnimator& iter : mPropertyAnimators )
530 if( iter.handle == nullptr )
532 layoutData.childrenPropertyAnimators.push_back( iter );
536 LayoutDataElement layoutDataElement;
537 layoutDataElement.handle = iter.handle;
538 if( ConvertToLayoutDataElement( iter, layoutDataElement, layoutData ) )
540 layoutDataArray.push_back( layoutDataElement );
545 Dali::Toolkit::LayoutTransitionData::LayoutTransitionSignalType& LayoutTransitionData::FinishedSignal()
547 return mFinishedSignal;
550 void LayoutTransitionData::EmitSignalFinish( int layoutTransitionType )
552 if ( !mFinishedSignal.Empty() )
554 Dali::Toolkit::LayoutTransitionData handle( this );
555 mFinishedSignal.Emit( static_cast<Dali::Toolkit::LayoutTransitionData::Type>(layoutTransitionType), handle );
559 } // namespace Internal
560 } // namespace Toolkit