[dali_1.3.47] Merge branch 'devel/master'
[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-toolkit/devel-api/visuals/image-visual-properties-devel.h>
21 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
22 #include <dali-toolkit/devel-api/controls/control-devel.h>
23 #include <dali-toolkit/devel-api/layouting/linear-layout.h>
24 #include <dali-toolkit/devel-api/layouting/grid.h>
25
26 #include <dali/integration-api/debug.h>
27
28 using namespace Dali;
29 using namespace Dali::Toolkit;
30
31 namespace
32 {
33 const char* const TITLE = "Animation Example";
34
35 // Button file names
36 const char* LTR_IMAGE( DEMO_IMAGE_DIR "icon-play.png" );
37 const char* LTR_SELECTED_IMAGE( DEMO_IMAGE_DIR "icon-play-selected.png" );
38
39 const char* RTL_IMAGE( DEMO_IMAGE_DIR "icon-reverse.png" );
40 const char* RTL_SELECTED_IMAGE( DEMO_IMAGE_DIR "icon-reverse-selected.png" );
41
42 const char* ROTATE_CLOCKWISE_IMAGE( DEMO_IMAGE_DIR "icon-reset.png" );
43 const char* ROTATE_CLOCKWISE_SELECTED_IMAGE( DEMO_IMAGE_DIR "icon-reset-selected.png" );
44
45 const char* GRID_IMAGE( DEMO_IMAGE_DIR "icon-item-view-layout-grid.png" );
46 const char* GRID_SELECTED_IMAGE( DEMO_IMAGE_DIR "icon-item-view-layout-grid-selected.png" );
47
48 // Child image filenames
49 const char* IMAGE_PATH[] = {
50   DEMO_IMAGE_DIR "application-icon-101.png",
51   DEMO_IMAGE_DIR "application-icon-102.png",
52   DEMO_IMAGE_DIR "application-icon-103.png",
53   DEMO_IMAGE_DIR "application-icon-104.png"
54 };
55
56 #if defined(DEBUG_ENABLED)
57 Debug::Filter* gLayoutFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_LAYOUT" );
58 #endif
59
60 const unsigned int NUMBER_OF_RESOURCES = sizeof(IMAGE_PATH) / sizeof(char*);
61
62 // Helper function to create ImageViews with given filename and size.
63 void CreateChildImageView( ImageView& imageView, int index, Size size )
64 {
65   imageView = ImageView::New();
66   Property::Map imagePropertyMap;
67   imagePropertyMap[ Toolkit::Visual::Property::TYPE ] = Toolkit::Visual::IMAGE;
68   imagePropertyMap[ Toolkit::ImageVisual::Property::URL ] = IMAGE_PATH[ index ];
69   imagePropertyMap[ ImageVisual::Property::DESIRED_WIDTH ] = size.width;
70   imagePropertyMap[ ImageVisual::Property::DESIRED_HEIGHT ] = size.height;
71   imageView.SetProperty( Toolkit::ImageView::Property::IMAGE, imagePropertyMap );
72   std::string name = "ImageView";
73   name.append( 1, '0' + index );
74   imageView.SetName( name );
75   imageView.SetAnchorPoint( AnchorPoint::TOP_LEFT );
76   imageView.SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS );
77 }
78
79 LayoutTransitionData CreateOnSetLayoutTransition( Control& parent, std::vector< Toolkit::ImageView >& children )
80 {
81   auto layoutTransitionData = LayoutTransitionData::New();
82   Property::Map map;
83   map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::COLOR_ALPHA;
84   map[ LayoutTransitionData::AnimatorKey::INITIAL_VALUE ] = 0.5f;
85   map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = 1.0f;
86   map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
87     .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "EASE_IN_OUT" )
88     .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
89       .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.25f )
90       .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f ) );
91
92   // Apply to parent only
93   layoutTransitionData.AddPropertyAnimator( parent, map );
94
95   for( size_t i = 0; i < children.size(); i++ )
96   {
97     Property::Map map;
98     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SIZE;
99     map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Vector3( 100.0f * 1.2f, 100.0f * 1.2f, 0 );
100     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
101       .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "SIN" )
102       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
103         .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.5f + 0.1f * i)
104         .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.25f ) );
105     layoutTransitionData.AddPropertyAnimator( children[i], map );
106   }
107
108   return layoutTransitionData;
109 }
110
111 LayoutTransitionData CreateOnChildAddTransition( Control& parent, ImageView& child )
112 {
113   auto layoutTransitionData = LayoutTransitionData::New();
114
115   // Want the parent to resize itself instantly so children will position themselves correctly when the parent is added to stage first time
116   Property::Map map;
117   map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SIZE;
118   map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
119     .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR")
120     .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
121       .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
122       .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
123   layoutTransitionData.AddPropertyAnimator( parent, map );
124
125   // New child is growing
126   {
127     Property::Map map;
128     map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SIZE;
129     map["initialValue"] = Vector3( 0.0f, 0.0f, 0 );
130     map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Vector3( 100.0f, 100.0f, 0 );
131     map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
132       .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR")
133       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
134         .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
135         .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f ) );
136     layoutTransitionData.AddPropertyAnimator( child, map );
137   }
138
139   // Want new children instantly appear in their positions
140   {
141     Property::Map map;
142     map[ LayoutTransitionData::AnimatorKey::PROPERTY] = Actor::Property::POSITION;
143     map[ LayoutTransitionData::AnimatorKey::ANIMATOR] = Property::Map()
144       .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR")
145       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
146          .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
147          .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
148     layoutTransitionData.AddPropertyAnimator( child, map );
149   }
150
151   return layoutTransitionData;
152 }
153
154 LayoutTransitionData CreateOnChildRemoveTransition(std::vector< Toolkit::ImageView >& images)
155 {
156   auto layoutTransitionData = LayoutTransitionData::New();
157   // Apply animation to remaining children
158   for (unsigned int i = 0; i < images.size(); i++)
159   {
160     {
161       Property::Map map;
162       map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = "position";
163       map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
164         .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "SIN")
165         .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
166            .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f)
167            .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f));
168       layoutTransitionData.AddPropertyAnimator( images[i], map );
169     }
170   }
171
172   return layoutTransitionData;
173 }
174
175 void CreateChildImageViewAndAdd( Control& container, int index, std::vector< Toolkit::ImageView >& images )
176 {
177   Toolkit::ImageView imageView;
178   CreateChildImageView( imageView, index, Size( 100.0f, 100.0f ) );
179   auto layout = DevelControl::GetLayout( container );
180   layout.SetTransitionData( LayoutTransitionData::ON_CHILD_ADD, CreateOnChildAddTransition( container, imageView ) );
181
182   container.Add( imageView );
183   images.push_back( imageView );
184 }
185
186 }  // namespace
187
188 namespace Demo
189 {
190
191 AnimationExample::AnimationExample()
192 : Example( TITLE ),
193   mGridSet( false )
194 {
195 }
196
197 void AnimationExample::Create()
198 {
199   DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "AnimationExample::Create\n");
200   auto stage = Stage::GetCurrent();
201
202   mRemoveButton = PushButton::New();
203   mRemoveButton.SetProperty( PushButton::Property::UNSELECTED_ICON, RTL_IMAGE );
204   mRemoveButton.SetProperty( PushButton::Property::SELECTED_ICON, RTL_SELECTED_IMAGE );
205   mRemoveButton.ClickedSignal().Connect( this, &AnimationExample::OnRemoveClicked );
206   mRemoveButton.SetParentOrigin( Vector3( 0.2f, 1.0f, 0.5f ) );
207   mRemoveButton.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
208   mRemoveButton.SetSize( 75, 75 );
209   stage.Add( mRemoveButton );
210
211   mAddButton = PushButton::New();
212   mAddButton.SetProperty( PushButton::Property::UNSELECTED_ICON, LTR_IMAGE );
213   mAddButton.SetProperty( PushButton::Property::SELECTED_ICON, LTR_SELECTED_IMAGE );
214   mAddButton.ClickedSignal().Connect( this, &AnimationExample::OnAddClicked );
215   mAddButton.SetParentOrigin( Vector3( 0.4f, 1.0f, 0.5f ) );
216   mAddButton.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
217   mAddButton.SetSize( 75, 75 );
218   stage.Add( mAddButton );
219
220   mSelectGridButton = Toolkit::PushButton::New();
221   mSelectGridButton.SetProperty( PushButton::Property::UNSELECTED_ICON, GRID_IMAGE );
222   mSelectGridButton.SetProperty( PushButton::Property::SELECTED_ICON, GRID_SELECTED_IMAGE );
223   mSelectGridButton.ClickedSignal().Connect( this, &AnimationExample::OnSelectGridClicked );
224   mSelectGridButton.SetParentOrigin( Vector3( 0.6f, 1.0f, 0.5f ) );
225   mSelectGridButton.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
226   mSelectGridButton.SetSize( 75, 75 );
227   stage.Add( mSelectGridButton );
228
229   mShakeButton = PushButton::New();
230   mShakeButton.SetProperty( PushButton::Property::UNSELECTED_ICON, ROTATE_CLOCKWISE_IMAGE );
231   mShakeButton.SetProperty( PushButton::Property::SELECTED_ICON, ROTATE_CLOCKWISE_SELECTED_IMAGE );
232   mShakeButton.ClickedSignal().Connect( this, &AnimationExample::OnChangeClicked );
233   mShakeButton.SetParentOrigin( Vector3( 0.8f, 1.0f, 0.5f ) );
234   mShakeButton.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER );
235   mShakeButton.SetSize( 75, 75 );
236   stage.Add( mShakeButton );
237
238   // Create a linear layout
239   mAnimationContainer = Control::New();
240   mAnimationContainer.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
241   mAnimationContainer.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
242   mAnimationContainer.SetProperty( Actor::Property::LAYOUT_DIRECTION, LayoutDirection::LEFT_TO_RIGHT );
243   mAnimationContainer.SetParentOrigin( ParentOrigin::CENTER );
244   mAnimationContainer.SetAnchorPoint( AnchorPoint::CENTER );
245   mAnimationContainer.SetName( "AnimationExample" );
246   mAnimationContainer.SetProperty( Toolkit::Control::Property::PADDING, Extents( 0.0f, 0.0f, 45.0f, 75.0f) );
247
248   mHorizontalLayout = LinearLayout::New();
249   mHorizontalLayout.SetOrientation( LinearLayout::Orientation::HORIZONTAL );
250   mHorizontalLayout.SetAlignment( LinearLayout::Alignment::CENTER_HORIZONTAL | LinearLayout::Alignment::CENTER_VERTICAL );
251   mHorizontalLayout.SetAnimateLayout(true);
252   DevelControl::SetLayout( mAnimationContainer, mHorizontalLayout );
253
254   mGridLayout = Grid::New();
255   mGridLayout.SetAnimateLayout(true);
256   mGridLayout.SetNumberOfColumns(2);
257
258   CreateChildImageViewAndAdd( mAnimationContainer, 0, mImages );
259   stage.Add( mAnimationContainer );
260 }
261
262 // Remove controls added by this example from stage
263 void AnimationExample::Remove()
264 {
265   if ( mAnimationContainer )
266   {
267     UnparentAndReset( mRemoveButton );
268     UnparentAndReset( mAddButton );
269     UnparentAndReset( mSelectGridButton );
270     UnparentAndReset( mShakeButton );
271     UnparentAndReset( mAnimationContainer);
272     mImages.clear();
273   }
274 }
275
276 bool AnimationExample::OnRemoveClicked( Button button )
277 {
278   DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "AnimationExample::OnRemoveClicked\n");
279
280   if (mImages.size() > 1)
281   {
282     auto layout = DevelControl::GetLayout( mAnimationContainer );
283     layout.SetTransitionData(LayoutTransitionData::ON_CHILD_REMOVE, CreateOnChildRemoveTransition( mImages ) );
284
285     ImageView imageView = mImages.back();
286     mAnimationContainer.Remove( imageView );
287     mImages.pop_back();
288   }
289   return true;
290 }
291
292 // Change layout by setting new layout, triggers set layout transition
293 bool AnimationExample::OnSelectGridClicked( Button button )
294 {
295   DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "AnimationExample::OnRotateClicked\n");
296
297   if ( !mGridSet )
298   {
299     mGridLayout.SetTransitionData( LayoutTransitionData::ON_OWNER_SET, CreateOnSetLayoutTransition( mAnimationContainer, mImages ) );
300     DevelControl::SetLayout( mAnimationContainer, mGridLayout );
301   }
302   else
303   {
304     mHorizontalLayout.SetTransitionData( LayoutTransitionData::ON_OWNER_SET, CreateOnSetLayoutTransition( mAnimationContainer, mImages ) );
305     DevelControl::SetLayout( mAnimationContainer, mHorizontalLayout );
306   }
307
308   mGridSet = !mGridSet;
309   return true;
310 }
311
312 bool AnimationExample::OnAddClicked( Button button )
313 {
314   if (mImages.size() < 4)
315   {
316     CreateChildImageViewAndAdd( mAnimationContainer, mImages.size(), mImages );
317   }
318   return true;
319 }
320
321 bool AnimationExample::OnChangeClicked( Button button )
322 {
323   if ( !mGridSet )
324   {
325     auto layout = LinearLayout::DownCast( DevelControl::GetLayout( mAnimationContainer ) );
326     layout.SetAlignment( LinearLayout::Alignment::CENTER_HORIZONTAL | LinearLayout::Alignment::CENTER_VERTICAL );
327     if ( layout.GetOrientation() == LinearLayout::Orientation::VERTICAL )
328     {
329       layout.SetOrientation( LinearLayout::Orientation::HORIZONTAL );
330     }
331     else
332     {
333       layout.SetOrientation( LinearLayout::Orientation::VERTICAL );
334     }
335   }
336   else
337   {
338     auto layout = Grid::DownCast( DevelControl::GetLayout( mAnimationContainer ) );
339     if ( layout.GetNumberOfColumns() == 2 )
340     {
341       layout.SetNumberOfColumns(3);
342     }
343     else
344     {
345       layout.SetNumberOfColumns(2);
346     }
347   }
348   return true;
349 }
350
351 } // namespace Demo