3b2c0a906e291aab1d744469ec1143b125498fd8
[platform/core/uifw/dali-demo.git] / examples / layouting / animation-example.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
18 #include <string>
19 #include "animation-example.h"
20 #include <dali/devel-api/actors/actor-devel.h>
21 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
22 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
23 #include <dali-toolkit/devel-api/controls/control-devel.h>
24 #include <dali-toolkit/devel-api/layouting/linear-layout.h>
25 #include <dali-toolkit/devel-api/layouting/grid.h>
26 #include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
27
28 #include <dali/integration-api/debug.h>
29
30 using namespace Dali;
31 using namespace Dali::Toolkit;
32
33 namespace
34 {
35 const char* const TITLE = "Animation Example";
36
37 // Button file names
38 const char* LTR_IMAGE( DEMO_IMAGE_DIR "icon-play.png" );
39 const char* LTR_SELECTED_IMAGE( DEMO_IMAGE_DIR "icon-play-selected.png" );
40
41 const char* RTL_IMAGE( DEMO_IMAGE_DIR "icon-reverse.png" );
42 const char* RTL_SELECTED_IMAGE( DEMO_IMAGE_DIR "icon-reverse-selected.png" );
43
44 const char* ROTATE_CLOCKWISE_IMAGE( DEMO_IMAGE_DIR "icon-reset.png" );
45 const char* ROTATE_CLOCKWISE_SELECTED_IMAGE( DEMO_IMAGE_DIR "icon-reset-selected.png" );
46
47 const char* GRID_IMAGE( DEMO_IMAGE_DIR "icon-item-view-layout-grid.png" );
48 const char* GRID_SELECTED_IMAGE( DEMO_IMAGE_DIR "icon-item-view-layout-grid-selected.png" );
49
50 // Child image filenames
51 const char* IMAGE_PATH[] = {
52   DEMO_IMAGE_DIR "application-icon-101.png",
53   DEMO_IMAGE_DIR "application-icon-102.png",
54   DEMO_IMAGE_DIR "application-icon-103.png",
55   DEMO_IMAGE_DIR "application-icon-104.png"
56 };
57
58 #if defined(DEBUG_ENABLED)
59 Debug::Filter* gLayoutFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_LAYOUT" );
60 #endif
61
62 const unsigned int NUMBER_OF_RESOURCES = sizeof(IMAGE_PATH) / sizeof(char*);
63
64 // Helper function
65 void CreateChild( ImageView& child, int index, Size size )
66 {
67   child = ImageView::New();
68   Property::Map imagePropertyMap;
69   imagePropertyMap[ Visual::Property::TYPE ] = Toolkit::Visual::IMAGE;
70   imagePropertyMap[ ImageVisual::Property::URL ] = IMAGE_PATH[ index ];
71   imagePropertyMap[ ImageVisual::Property::DESIRED_WIDTH ] = size.width;
72   imagePropertyMap[ ImageVisual::Property::DESIRED_HEIGHT ] = size.height;
73   imagePropertyMap[ ImageVisual::Property::FITTING_MODE ] = FittingMode::SCALE_TO_FILL;
74   child.SetProperty( Toolkit::ImageView::Property::IMAGE, imagePropertyMap );
75   std::string name = "ImageView";
76   name.append( 1, '0' + index );
77   child.SetName( name );
78   child.SetAnchorPoint( AnchorPoint::CENTER );
79   child.SetProperty( DevelActor::Property::POSITION_USES_ANCHOR_POINT, false );
80 }
81
82 // Create set layout transition. A parent opacity increases 'ease in out' from semi-transparent to fully opaque and children pulse in order
83 LayoutTransitionData CreateOnSetLayoutTransition( Control& container )
84 {
85   auto layoutTransitionData = LayoutTransitionData::New();
86   Property::Map map;
87   map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::COLOR_ALPHA;
88   map[ LayoutTransitionData::AnimatorKey::INITIAL_VALUE ] = 0.5f;
89   map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = 1.0f;
90   map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
91     .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, AlphaFunction::EASE_IN_OUT )
92     .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
93       .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.25f )
94       .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f ) );
95
96   // Apply to parent only
97   layoutTransitionData.AddPropertyAnimator( container, map );
98
99   // Reset scale after possible focus animation
100   {
101     Property::Map map;
102     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SCALE;
103     map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Vector3::ONE;
104     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
105       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
106         .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f)
107         .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f));
108     layoutTransitionData.AddPropertyAnimator( Actor(), map );
109   }
110
111   // Children pulses in/out
112   for( size_t i = 0; i < container.GetChildCount(); i++ )
113   {
114     Property::Map map;
115     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SIZE;
116     map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Vector3( 100.0f * 1.2f, 100.0f * 1.2f, 0 );
117     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
118       .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, AlphaFunction::SIN )
119       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
120         .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.5f + 0.1f * i)
121         .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.25f ) );
122     layoutTransitionData.AddPropertyAnimator( container.GetChildAt( i ), map );
123   }
124
125   // Children move
126   {
127     Property::Map map;
128     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::POSITION;
129     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
130       .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, AlphaFunction::LINEAR )
131       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
132          .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
133          .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f ) );
134     layoutTransitionData.AddPropertyAnimator( Actor(), map );
135   }
136
137   return layoutTransitionData;
138 }
139
140 // Create add child transition. An added child grows from (0, 0) to its full size and instantly appears in its position
141 LayoutTransitionData CreateOnChildAddTransition( Control& parent )
142 {
143   auto layoutTransitionData = LayoutTransitionData::New();
144
145   // Want the parent to resize itself instantly so children will position themselves correctly when the parent is added to stage first time
146   Property::Map map;
147   map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SIZE;
148   map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
149     .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, AlphaFunction::LINEAR )
150     .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
151       .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
152       .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
153   layoutTransitionData.AddPropertyAnimator( parent, map );
154
155   // Reset scale after possible focus animation
156   {
157     Property::Map map;
158     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SCALE;
159     map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Vector3::ONE;
160     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
161       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
162         .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f)
163         .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f));
164     layoutTransitionData.AddPropertyAnimator( Actor(), map );
165   }
166
167   // New child is growing
168   {
169     Property::Map map;
170     map[ LayoutTransitionData::AnimatorKey::CONDITION ] = LayoutTransitionData::Condition::ON_ADD;
171     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SCALE;
172     map[ LayoutTransitionData::AnimatorKey::INITIAL_VALUE ] = Vector3::ZERO;
173     map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Vector3::ONE;
174     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
175       .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, AlphaFunction::LINEAR )
176       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
177         .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
178         .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f ) );
179     layoutTransitionData.AddPropertyAnimator( Actor(), map );
180   }
181
182   // Want new children instantly appear in their positions
183   {
184     Property::Map map;
185     map[ LayoutTransitionData::AnimatorKey::CONDITION ] = LayoutTransitionData::Condition::ON_ADD;
186     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::POSITION;
187     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
188       .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, AlphaFunction::LINEAR )
189       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
190          .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
191          .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
192     layoutTransitionData.AddPropertyAnimator( Actor(), map );
193   }
194
195   // Other just move
196   {
197     Property::Map map;
198     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::POSITION;
199     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
200       .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, AlphaFunction::LINEAR )
201       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
202          .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
203          .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f ) );
204     layoutTransitionData.AddPropertyAnimator( Actor(), map );
205   }
206
207   return layoutTransitionData;
208 }
209
210 // Create remove child transition. Remaining children shake around their positions
211 LayoutTransitionData CreateOnChildRemoveTransition( Control& container )
212 {
213   auto layoutTransitionData = LayoutTransitionData::New();
214
215   // Reset scale after possible focus animation
216   {
217     Property::Map map;
218     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SCALE;
219     map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Vector3::ONE;
220     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
221       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
222         .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f)
223         .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f));
224     layoutTransitionData.AddPropertyAnimator( Actor(), map );
225   }
226
227   // Apply animation to remaining children - sin shaking
228   {
229     Property::Map map;
230     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::POSITION;
231     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
232       .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, AlphaFunction::SIN )
233       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
234         .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f)
235         .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f));
236     layoutTransitionData.AddPropertyAnimator( Actor(), map );
237   }
238
239   // Add a linear to reduce a linear to half
240   {
241     Property::Map map;
242     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::POSITION;
243     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
244       .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, AlphaFunction::LINEAR )
245       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
246          .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f)
247          .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f));
248     layoutTransitionData.AddPropertyAnimator( Actor(), map );
249   }
250
251   return layoutTransitionData;
252 }
253
254 // Create child focus transition. A focus gained child grows 120% and focus lost child gets its original size back
255 LayoutTransitionData CreateOnChildFocusTransition( Control& parent, bool affectsSiblings )
256 {
257   auto layoutTransitionData = LayoutTransitionData::New();
258
259   // Focus gain child animation
260   {
261     Property::Map map;
262     map[ LayoutTransitionData::AnimatorKey::CONDITION ] = LayoutTransitionData::Condition::ON_FOCUS_GAINED;
263     map[ LayoutTransitionData::AnimatorKey::AFFECTS_SIBLINGS ] = affectsSiblings;
264     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SCALE;
265     map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Vector3( 1.2f, 1.2f, 1.0f );
266     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
267       .Add( LayoutTransitionData::AnimatorKey::TYPE, LayoutTransitionData::Animator::ANIMATE_TO )
268       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
269         .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
270         .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f ) );
271     layoutTransitionData.AddPropertyAnimator( Actor(), map );
272   }
273
274   // Focus lost child animation
275   {
276     Property::Map map;
277     map[ LayoutTransitionData::AnimatorKey::CONDITION ] = LayoutTransitionData::Condition::ON_FOCUS_LOST;
278     map[ LayoutTransitionData::AnimatorKey::AFFECTS_SIBLINGS ] = affectsSiblings;
279     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SCALE;
280     map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Vector3( 1.0f, 1.0f, 1.0f );
281     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
282       .Add( LayoutTransitionData::AnimatorKey::TYPE, LayoutTransitionData::Animator::ANIMATE_TO )
283       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
284         .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
285         .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f ) );
286     layoutTransitionData.AddPropertyAnimator( Actor(), map );
287   }
288
289   // Linear children positioning
290   {
291     Property::Map map;
292     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::POSITION;
293     map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Property::Value();
294     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
295       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
296          .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
297          .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f ) );
298     layoutTransitionData.AddPropertyAnimator( Actor(), map );
299   }
300
301   return layoutTransitionData;
302 }
303
304 // An example of custom default transition, ease in for position animation, ease out for size animation
305 LayoutTransitionData CreateCustomDefaultTransition( Control& control )
306 {
307   auto layoutTransitionData = LayoutTransitionData::New();
308   // Resets control scale after possible focus animation
309   {
310     Property::Map map;
311     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SCALE;
312     map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Vector3::ONE;
313     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
314       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
315         .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
316         .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
317     layoutTransitionData.AddPropertyAnimator( control, map );
318   }
319
320   // Moves control ease in
321   {
322     Property::Map map;
323     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::POSITION;
324     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
325       .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, AlphaFunction::EASE_IN )
326       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
327         .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
328         .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f ) );
329     layoutTransitionData.AddPropertyAnimator( control, map );
330   }
331
332   // Sizes control ease out
333   {
334     Property::Map map;
335     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SIZE;
336     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
337       .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, AlphaFunction::EASE_OUT )
338       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
339         .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
340         .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f ) );
341     layoutTransitionData.AddPropertyAnimator( control, map );
342   }
343
344   return layoutTransitionData;
345 }
346
347 bool OnImageTouchCallback( Actor actor, const TouchData& event )
348 {
349   KeyInputFocusManager manager = KeyInputFocusManager::Get();
350   manager.SetFocus( Control::DownCast( actor ) );
351   return true;
352 }
353
354 void CreateChildAndAdd( Demo::AnimationExample& animationExample, Control& container )
355 {
356   Toolkit::ImageView imageView;
357   CreateChild( imageView, container.GetChildCount(), Size( 100.0f, 100.0f ) );
358   imageView.TouchSignal().Connect( &animationExample, &OnImageTouchCallback );
359   container.Add( imageView );
360
361   DevelControl::GetLayout( imageView ).SetTransitionData( Toolkit::LayoutTransitionData::ON_LAYOUT_CHANGE, CreateCustomDefaultTransition( imageView ) );
362 }
363
364 }  // namespace
365
366 namespace Demo
367 {
368
369 AnimationExample::AnimationExample()
370 : Example( TITLE ),
371   mGridSet( false )
372 {
373 }
374
375 void AnimationExample::Create()
376 {
377   DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "AnimationExample::Create\n");
378   auto stage = Stage::GetCurrent();
379
380   mRemoveButton = PushButton::New();
381   mRemoveButton.SetProperty( PushButton::Property::UNSELECTED_ICON, RTL_IMAGE );
382   mRemoveButton.SetProperty( PushButton::Property::SELECTED_ICON, RTL_SELECTED_IMAGE );
383   mRemoveButton.ClickedSignal().Connect( this, &AnimationExample::OnRemoveClicked );
384   mRemoveButton.SetParentOrigin( Vector3( 0.2f, 1.0f, 0.5f ) );
385   mRemoveButton.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
386   mRemoveButton.SetSize( 75, 75 );
387   stage.Add( mRemoveButton );
388
389   mAddButton = PushButton::New();
390   mAddButton.SetProperty( PushButton::Property::UNSELECTED_ICON, LTR_IMAGE );
391   mAddButton.SetProperty( PushButton::Property::SELECTED_ICON, LTR_SELECTED_IMAGE );
392   mAddButton.ClickedSignal().Connect( this, &AnimationExample::OnAddClicked );
393   mAddButton.SetParentOrigin( Vector3( 0.4f, 1.0f, 0.5f ) );
394   mAddButton.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
395   mAddButton.SetSize( 75, 75 );
396   stage.Add( mAddButton );
397
398   mSelectGridButton = Toolkit::PushButton::New();
399   mSelectGridButton.SetProperty( PushButton::Property::UNSELECTED_ICON, GRID_IMAGE );
400   mSelectGridButton.SetProperty( PushButton::Property::SELECTED_ICON, GRID_SELECTED_IMAGE );
401   mSelectGridButton.ClickedSignal().Connect( this, &AnimationExample::OnSelectGridClicked );
402   mSelectGridButton.SetParentOrigin( Vector3( 0.6f, 1.0f, 0.5f ) );
403   mSelectGridButton.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
404   mSelectGridButton.SetSize( 75, 75 );
405   stage.Add( mSelectGridButton );
406
407   mShakeButton = PushButton::New();
408   mShakeButton.SetProperty( PushButton::Property::UNSELECTED_ICON, ROTATE_CLOCKWISE_IMAGE );
409   mShakeButton.SetProperty( PushButton::Property::SELECTED_ICON, ROTATE_CLOCKWISE_SELECTED_IMAGE );
410   mShakeButton.ClickedSignal().Connect( this, &AnimationExample::OnChangeClicked );
411   mShakeButton.SetParentOrigin( Vector3( 0.8f, 1.0f, 0.5f ) );
412   mShakeButton.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
413   mShakeButton.SetSize( 75, 75 );
414   stage.Add( mShakeButton );
415
416   // Create a linear layout
417   mAnimationContainer = Control::New();
418   mAnimationContainer.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
419   mAnimationContainer.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
420   mAnimationContainer.SetProperty( Actor::Property::LAYOUT_DIRECTION, LayoutDirection::LEFT_TO_RIGHT );
421   mAnimationContainer.SetParentOrigin( ParentOrigin::CENTER );
422   mAnimationContainer.SetAnchorPoint( AnchorPoint::CENTER );
423   mAnimationContainer.SetName( "AnimationExample" );
424   mAnimationContainer.SetProperty( Toolkit::Control::Property::PADDING, Extents( 0.0f, 0.0f, 45.0f, 75.0f) );
425
426   mHorizontalLayout = LinearLayout::New();
427   mHorizontalLayout.SetOrientation( LinearLayout::Orientation::HORIZONTAL );
428   mHorizontalLayout.SetAlignment( LinearLayout::Alignment::CENTER_HORIZONTAL | LinearLayout::Alignment::CENTER_VERTICAL );
429   mHorizontalLayout.SetAnimateLayout(true);
430   mHorizontalLayout.SetTransitionData( LayoutTransitionData::ON_CHILD_FOCUS, CreateOnChildFocusTransition( mAnimationContainer, true ) );
431   mHorizontalLayout.SetTransitionData( LayoutTransitionData::ON_CHILD_REMOVE, CreateOnChildRemoveTransition( mAnimationContainer ) );
432   mHorizontalLayout.SetTransitionData( LayoutTransitionData::ON_CHILD_ADD, CreateOnChildAddTransition( mAnimationContainer ) );
433
434   DevelControl::SetLayout( mAnimationContainer, mHorizontalLayout );
435
436   mGridLayout = Grid::New();
437   mGridLayout.SetAnimateLayout( true );
438   mGridLayout.SetNumberOfColumns( 2 );
439   mGridLayout.SetTransitionData( LayoutTransitionData::ON_CHILD_FOCUS, CreateOnChildFocusTransition( mAnimationContainer, false ) );
440   mGridLayout.SetTransitionData( LayoutTransitionData::ON_CHILD_REMOVE, CreateOnChildRemoveTransition( mAnimationContainer ) );
441   mGridLayout.SetTransitionData( LayoutTransitionData::ON_CHILD_ADD, CreateOnChildAddTransition( mAnimationContainer ) );
442
443   CreateChildAndAdd( *this, mAnimationContainer );
444   stage.Add( mAnimationContainer );
445 }
446
447 // Remove controls added by this example from stage
448 void AnimationExample::Remove()
449 {
450   if ( mAnimationContainer )
451   {
452     UnparentAndReset( mRemoveButton );
453     UnparentAndReset( mAddButton );
454     UnparentAndReset( mSelectGridButton );
455     UnparentAndReset( mShakeButton );
456     UnparentAndReset( mAnimationContainer);
457   }
458 }
459
460 bool AnimationExample::OnRemoveClicked( Button button )
461 {
462   DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "AnimationExample::OnRemoveClicked\n");
463
464   if ( mAnimationContainer.GetChildCount() > 1 )
465   {
466     mAnimationContainer.Remove( mAnimationContainer.GetChildAt( mAnimationContainer.GetChildCount() - 1 ) );
467   }
468   return true;
469 }
470
471 // Change layout by setting new layout, triggers set layout transition
472 bool AnimationExample::OnSelectGridClicked( Button button )
473 {
474   DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "AnimationExample::OnRotateClicked\n");
475
476   if ( !mGridSet )
477   {
478     mGridLayout.SetTransitionData( LayoutTransitionData::ON_OWNER_SET, CreateOnSetLayoutTransition( mAnimationContainer ) );
479     DevelControl::SetLayout( mAnimationContainer, mGridLayout );
480   }
481   else
482   {
483     mHorizontalLayout.SetTransitionData( LayoutTransitionData::ON_OWNER_SET, CreateOnSetLayoutTransition( mAnimationContainer ) );
484     DevelControl::SetLayout( mAnimationContainer, mHorizontalLayout );
485   }
486
487   mGridSet = !mGridSet;
488   return true;
489 }
490
491 bool AnimationExample::OnAddClicked( Button button )
492 {
493   if( mAnimationContainer.GetChildCount() < 4 )
494   {
495     CreateChildAndAdd( *this, mAnimationContainer );
496   }
497   return true;
498 }
499
500 bool AnimationExample::OnChangeClicked( Button button )
501 {
502   if ( !mGridSet )
503   {
504     auto layout = LinearLayout::DownCast( DevelControl::GetLayout( mAnimationContainer ) );
505     layout.SetAlignment( LinearLayout::Alignment::CENTER_HORIZONTAL | LinearLayout::Alignment::CENTER_VERTICAL );
506     if ( layout.GetOrientation() == LinearLayout::Orientation::VERTICAL )
507     {
508       layout.SetOrientation( LinearLayout::Orientation::HORIZONTAL );
509     }
510     else
511     {
512       layout.SetOrientation( LinearLayout::Orientation::VERTICAL );
513     }
514   }
515   else
516   {
517     auto layout = Grid::DownCast( DevelControl::GetLayout( mAnimationContainer ) );
518     if ( layout.GetNumberOfColumns() == 2 )
519     {
520       layout.SetNumberOfColumns(3);
521     }
522     else
523     {
524       layout.SetNumberOfColumns(2);
525     }
526   }
527   return true;
528 }
529
530 } // namespace Demo