Changes required after Visual parent-origin & anchor-point defaults change
[platform/core/uifw/dali-demo.git] / examples / visual-transitions / beat-control-impl.cpp
1 /*
2  * Copyright (c) 2017 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 #include "beat-control-impl.h"
18 #include <dali-toolkit/dali-toolkit.h>
19 #include <dali/public-api/object/type-registry-helper.h>
20 #include <dali-toolkit/devel-api/controls/control-devel.h>
21 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
22 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
23
24 using namespace Dali; // Needed for macros
25 using namespace Dali::Toolkit;
26
27 namespace Demo
28 {
29 namespace Internal
30 {
31
32 namespace
33 {
34
35 const int BOUNCE_ANIMATION_RUNNING(0x0001);
36 const int FADE_ANIMATION_RUNNING  (0x0002);
37 const int X_ANIMATION_RUNNING     (0x0004);
38 const int Y_ANIMATION_RUNNING     (0x0008);
39
40
41 Dali::BaseHandle Create()
42 {
43   return Demo::BeatControl::New();
44 }
45
46 DALI_TYPE_REGISTRATION_BEGIN( BeatControl, Dali::Toolkit::Control, Create );
47
48 DALI_PROPERTY_REGISTRATION( Demo, BeatControl, "bounceTransition", STRING, BOUNCE_TRANSITION );
49 DALI_PROPERTY_REGISTRATION( Demo, BeatControl, "leftTransition", STRING, LEFT_TRANSITION );
50 DALI_PROPERTY_REGISTRATION( Demo, BeatControl, "upTransition", STRING, UP_TRANSITION );
51 DALI_PROPERTY_REGISTRATION( Demo, BeatControl, "fadeTransition", STRING, FADE_TRANSITION );
52 DALI_PROPERTY_REGISTRATION( Demo, BeatControl, "beatVisual", MAP, BEAT_VISUAL );
53 DALI_TYPE_REGISTRATION_END();
54
55
56 Toolkit::TransitionData ConvertPropertyToTransition( const Property::Value& value )
57 {
58   Toolkit::TransitionData transitionData;
59
60   const Property::Array* array = value.GetArray();
61   if( array )
62   {
63     transitionData = Toolkit::TransitionData::New( *array );
64   }
65   else
66   {
67     const Property::Map* map = value.GetMap();
68     if( map )
69     {
70       transitionData = Toolkit::TransitionData::New( *map );
71     }
72   }
73   return transitionData;
74 }
75
76 } // anonymous namespace
77
78
79 Internal::BeatControl::BeatControl()
80 : Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ),
81   mTransformSize(1.0f, 1.0f),
82   mTransformOrigin(Align::CENTER),
83   mTransformAnchorPoint(Align::CENTER),
84   mAnimationPlaying(0)
85 {
86 }
87
88 Internal::BeatControl::~BeatControl()
89 {
90 }
91
92 Demo::BeatControl Internal::BeatControl::New()
93 {
94   IntrusivePtr<Internal::BeatControl> impl = new Internal::BeatControl();
95   Demo::BeatControl handle = Demo::BeatControl( *impl );
96   impl->Initialize();
97   return handle;
98 }
99
100
101 void BeatControl::StartBounceAnimation()
102 {
103   if( mAnimation )
104   {
105     mAnimation.Stop();
106     mAnimation.FinishedSignal().Disconnect( this, &BeatControl::OnBounceAnimationFinished );
107     OnBounceAnimationFinished(mAnimation);
108   }
109
110   mAnimation = DevelControl::CreateTransition( *this, mBounceTransition );
111   mAnimation.FinishedSignal().Connect( this, &BeatControl::OnBounceAnimationFinished );
112   mAnimation.Play();
113   mAnimationPlaying |= BOUNCE_ANIMATION_RUNNING;
114 }
115
116
117 void BeatControl::StartXAnimation()
118 {
119   if( mXAnimation )
120   {
121     mXAnimation.Stop();
122     mXAnimation.FinishedSignal().Disconnect( this, &BeatControl::OnXAnimationFinished );
123     OnXAnimationFinished(mXAnimation);
124   }
125
126   mXAnimation = DevelControl::CreateTransition( *this, mLeftTransition );
127   mXAnimation.FinishedSignal().Connect( this, &BeatControl::OnXAnimationFinished );
128   mXAnimation.Play();
129   mAnimationPlaying |= X_ANIMATION_RUNNING;
130 }
131
132 void BeatControl::StartYAnimation()
133 {
134   if( mYAnimation )
135   {
136     mYAnimation.Stop();
137     mYAnimation.FinishedSignal().Disconnect( this, &BeatControl::OnYAnimationFinished );
138     OnYAnimationFinished(mYAnimation);
139   }
140
141   mYAnimation = DevelControl::CreateTransition( *this, mUpTransition );
142   mYAnimation.FinishedSignal().Connect( this, &BeatControl::OnYAnimationFinished );
143   mYAnimation.Play();
144   mAnimationPlaying |= Y_ANIMATION_RUNNING;
145 }
146
147 void BeatControl::StartFadeAnimation()
148 {
149   if( mFadeAnimation )
150   {
151     mFadeAnimation.Stop();
152     mFadeAnimation.FinishedSignal().Disconnect( this, &BeatControl::OnFadeAnimationFinished );
153     OnFadeAnimationFinished(mFadeAnimation);
154   }
155
156   mFadeAnimation = DevelControl::CreateTransition( *this, mFadeTransition );
157   mFadeAnimation.FinishedSignal().Connect( this, &BeatControl::OnFadeAnimationFinished );
158   mFadeAnimation.Play();
159   mAnimationPlaying |= FADE_ANIMATION_RUNNING;
160 }
161
162 void BeatControl::OnBounceAnimationFinished( Animation& src )
163 {
164   mAnimationPlaying &= ~BOUNCE_ANIMATION_RUNNING;
165 }
166 void BeatControl::OnXAnimationFinished( Animation& src )
167 {
168   mAnimationPlaying &= ~X_ANIMATION_RUNNING;
169 }
170 void BeatControl::OnYAnimationFinished( Animation& src )
171 {
172   mAnimationPlaying &= ~Y_ANIMATION_RUNNING;
173 }
174 void BeatControl::OnFadeAnimationFinished( Animation& src )
175 {
176   mAnimationPlaying &= ~FADE_ANIMATION_RUNNING;
177 }
178
179 void BeatControl::OnInitialize()
180 {
181   Actor self = Self();
182 }
183
184 void BeatControl::OnStageConnection( int depth )
185 {
186   Control::OnStageConnection( depth );
187 }
188
189 void BeatControl::OnStageDisconnection()
190 {
191   Control::OnStageDisconnection();
192 }
193
194 void BeatControl::OnSizeSet( const Vector3& targetSize )
195 {
196   Control::OnSizeSet( targetSize );
197   RelayoutVisuals( Vector2( targetSize ) );
198 }
199
200 void BeatControl::OnRelayout( const Vector2& targetSize, RelayoutContainer& container )
201 {
202   RelayoutVisuals( targetSize );
203 }
204
205 void BeatControl::RelayoutVisuals( const Vector2& targetSize )
206 {
207   if( mVisual )
208   {
209     if( (mAnimationPlaying & (X_ANIMATION_RUNNING | Y_ANIMATION_RUNNING)) == 0)
210     {
211       Vector2 size( targetSize );
212       Property::Map transformMap;
213       // Make the visual half the size of the control, but leave
214       // origin and anchor point at center, position is relative, but Zer0
215       transformMap[ DevelVisual::Transform::Property::SIZE ] = mTransformSize;
216       transformMap[ DevelVisual::Transform::Property::ORIGIN ] = mTransformOrigin;
217       transformMap[ DevelVisual::Transform::Property::ANCHOR_POINT ] = mTransformAnchorPoint;
218       mVisual.SetTransformAndSize( transformMap, size );
219     }
220   }
221 }
222
223 Vector3 BeatControl::GetNaturalSize()
224 {
225   if( mVisual )
226   {
227     Vector2 naturalSize;
228     mVisual.GetNaturalSize(naturalSize);
229     return Vector3(naturalSize);
230   }
231   return Vector3::ZERO;
232 }
233
234 void BeatControl::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
235 {
236   // Chain up.
237   Control::OnStyleChange( styleManager, change );
238 }
239
240
241 ///////////////////////////////////////////////////////////
242 //
243 // Properties
244 //
245
246 void BeatControl::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
247 {
248   Demo::BeatControl beatControl = Demo::BeatControl::DownCast( Dali::BaseHandle( object ) );
249
250   if( beatControl )
251   {
252     BeatControl& impl = GetImpl( beatControl );
253     Actor self = impl.Self();
254     switch ( index )
255     {
256       case Demo::BeatControl::Property::BEAT_VISUAL:
257       {
258         bool sizeAndPositionOnly = false;
259
260         // Determine if a transform.size property exists in the map, and
261         // save it.
262         Property::Map* map = value.GetMap();
263         if( map )
264         {
265           Property::Value* value = map->Find( DevelVisual::Property::TRANSFORM, "transform" );
266           if( value )
267           {
268             Property::Map* transformMap = value->GetMap();
269             if( transformMap )
270             {
271               // We'll increment this whenever SIZE, ORIGIN or ANCHOR_POINT's are modified as we won't need to create a new visual if only these properties are used
272               // If there are more properties in the transform map, then we need to create a new visual
273               unsigned int sizeAndPositionPropertyCount = 0;
274
275               Property::Value* sizeValue = transformMap->Find( DevelVisual::Transform::Property::SIZE, "size" );
276               if( sizeValue )
277               {
278                 sizeValue->Get( impl.mTransformSize );
279                 ++sizeAndPositionPropertyCount;
280               }
281
282               Property::Value* originValue = transformMap->Find( DevelVisual::Transform::Property::ORIGIN, "origin" );
283               if( originValue )
284               {
285                 int intValue = 0;
286                 if( originValue->Get( intValue ) )
287                 {
288                   impl.mTransformOrigin = static_cast< Toolkit::Align::Type >( intValue );
289                   ++sizeAndPositionPropertyCount;
290                 }
291               }
292
293               Property::Value* anchorPointValue = transformMap->Find( DevelVisual::Transform::Property::ANCHOR_POINT, "anchorPoint" );
294               if( anchorPointValue )
295               {
296                 int intValue = 0;
297                 if( anchorPointValue->Get( intValue ) )
298                 {
299                   impl.mTransformAnchorPoint = static_cast< Toolkit::Align::Type >( intValue );
300                   ++sizeAndPositionPropertyCount;
301                 }
302               }
303
304               // If the only properties that the application is overriding are the size and the position properties, then we do not need to create another visual.
305               if( map->Count() == 1 && transformMap->Count() == sizeAndPositionPropertyCount )
306               {
307                 sizeAndPositionOnly = true;
308               }
309             }
310           }
311           if( ! sizeAndPositionOnly )
312           {
313             // Only register a visual if there is more than just a size setting
314             impl.mVisual = Toolkit::VisualFactory::Get().CreateVisual( *map );
315             DevelControl::RegisterVisual( impl, Demo::BeatControl::Property::BEAT_VISUAL, impl.mVisual );
316
317             // We have registered a new visual: must trigger size negotiation
318             // in order to call SetTransformAndSize on the visual with the right size:
319             impl.RelayoutRequest();
320           }
321         }
322         break;
323       }
324       case Demo::BeatControl::Property::BOUNCE_TRANSITION:
325       {
326         impl.mBounceTransition = ConvertPropertyToTransition( value );
327         break;
328       }
329       case Demo::BeatControl::Property::LEFT_TRANSITION:
330       {
331         impl.mLeftTransition = ConvertPropertyToTransition( value );
332         break;
333       }
334       case Demo::BeatControl::Property::UP_TRANSITION:
335       {
336         impl.mUpTransition = ConvertPropertyToTransition( value );
337         break;
338       }
339       case Demo::BeatControl::Property::FADE_TRANSITION:
340       {
341         impl.mFadeTransition = ConvertPropertyToTransition( value );
342         break;
343       }
344     }
345   }
346 }
347
348 Property::Value BeatControl::GetProperty( BaseObject* object, Property::Index propertyIndex )
349 {
350   Property::Value value;
351
352   Demo::BeatControl beatControl = Demo::BeatControl::DownCast( Dali::BaseHandle( object ) );
353
354   if ( beatControl )
355   {
356     BeatControl& impl = GetImpl( beatControl );
357     switch ( propertyIndex )
358     {
359       case Demo::BeatControl::Property::BEAT_VISUAL:
360       {
361         if( impl.mVisual )
362         {
363           Property::Map map;
364           impl.mVisual.CreatePropertyMap(map);
365           value = map;
366         }
367         break;
368       }
369       case Demo::BeatControl::Property::BOUNCE_TRANSITION:
370       case Demo::BeatControl::Property::LEFT_TRANSITION:
371       case Demo::BeatControl::Property::UP_TRANSITION:
372       case Demo::BeatControl::Property::FADE_TRANSITION:
373       default:
374         break;
375     }
376   }
377
378   return value;
379 }
380
381
382 } // Internal
383 } // Demo