a2cb95da4d153954472ac9c79c739866fa73d8dc
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / buttons / push-button-impl.cpp
1 /*
2  * Copyright (c) 2014 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 // CLASS HEADER
19 #include "push-button-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/actors/image-actor.h>
23 #include <dali/public-api/object/type-registry.h>
24
25 // INTERNAL INCLUDES
26 #include <dali-toolkit/public-api/controls/text-view/text-view.h>
27
28 namespace Dali
29 {
30
31 namespace Toolkit
32 {
33
34 namespace Internal
35 {
36
37 namespace
38 {
39
40 const float TEXT_PADDING = 12.0f;
41 const float ANIMATION_TIME( 0.2f );
42
43 BaseHandle Create()
44 {
45   return Toolkit::PushButton::New();
46 }
47
48 TypeRegistration typeRegistration( typeid(Toolkit::PushButton), typeid(Toolkit::Button), Create );
49
50 } // unnamed namespace
51
52 namespace
53 {
54
55 /**
56  * Find the first image actor in the actor hierarchy
57  */
58 ImageActor FindImageActor( Actor root )
59 {
60   ImageActor imageActor = ImageActor::DownCast( root );
61   if( !imageActor && root )
62   {
63     for( unsigned int i = 0, numChildren = root.GetChildCount(); i < numChildren; ++i )
64     {
65       ImageActor childImageActor = FindImageActor( root.GetChildAt( i ) );
66       if( childImageActor )
67       {
68         return childImageActor;
69       }
70     }
71   }
72
73   return imageActor;
74 }
75
76 } // unnamed namespace
77
78 Dali::Toolkit::PushButton PushButton::New()
79 {
80   // Create the implementation, temporarily owned on stack
81   IntrusivePtr< PushButton > internalPushButton = new PushButton();
82
83   // Pass ownership to CustomActor
84   Dali::Toolkit::PushButton pushButton( *internalPushButton );
85
86   // Second-phase init of the implementation
87   // This can only be done after the CustomActor connection has been made...
88   internalPushButton->Initialize();
89
90   return pushButton;
91 }
92
93 PushButton::PushButton()
94 : Button(),
95   mSize()
96 {
97   SetAnimationTime( ANIMATION_TIME );
98 }
99
100 PushButton::~PushButton()
101 {
102 }
103
104 void PushButton::OnButtonInitialize()
105 {
106   // Push button requires the Leave event.
107   Actor self = Self();
108   self.SetLeaveRequired( true );
109
110   // Set resize policy to natural size so that buttons will resize to background images
111   self.SetResizePolicy( USE_NATURAL_SIZE, ALL_DIMENSIONS );
112 }
113
114 void PushButton::OnLabelSet()
115 {
116   Actor& label = GetLabel();
117
118   if( label )
119   {
120     label.SetAnchorPoint( AnchorPoint::CENTER );
121     label.SetParentOrigin( ParentOrigin::CENTER );
122     label.SetSize( mSize );
123   }
124 }
125
126 void PushButton::OnButtonImageSet()
127 {
128   Actor& buttonImage = GetButtonImage();
129
130   buttonImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS );
131
132   buttonImage.RelayoutRequestTree();
133
134   RelayoutRequest();
135 }
136
137 void PushButton::OnSelectedImageSet()
138 {
139   Actor& selectedImage = GetSelectedImage();
140
141   selectedImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS );
142
143   selectedImage.RelayoutRequestTree();
144
145   RelayoutRequest();
146 }
147
148 void PushButton::OnBackgroundImageSet()
149 {
150   Actor& backgroundImage = GetBackgroundImage();
151
152   backgroundImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS );
153
154   backgroundImage.RelayoutRequestTree();
155
156   RelayoutRequest();
157 }
158
159 void PushButton::OnSelectedBackgroundImageSet()
160 {
161   Actor& selectedBackgroundImage = GetSelectedBackgroundImage();
162
163   selectedBackgroundImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS );
164 }
165
166 void PushButton::OnDisabledImageSet()
167 {
168   Actor& disabledImage = GetDisabledImage();
169
170   disabledImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS );
171
172   disabledImage.RelayoutRequestTree();
173
174   RelayoutRequest();
175 }
176
177 void PushButton::OnDisabledBackgroundImageSet()
178 {
179   Actor& disabledBackgroundImage = GetDisabledBackgroundImage();
180
181   disabledBackgroundImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS );
182
183   disabledBackgroundImage.RelayoutRequestTree();
184
185   RelayoutRequest();
186 }
187
188 bool PushButton::OnSelected()
189 {
190   Actor& buttonImage = GetButtonImage();
191   Actor& selectedImage = GetSelectedImage();
192   Actor& selectedBackgroundImage = GetSelectedBackgroundImage();
193
194   PaintState paintState = GetPaintState();
195
196   switch( paintState )
197   {
198     case UnselectedState:
199     {
200       FadeOutImage( buttonImage );
201       FadeInImage( selectedBackgroundImage );
202       FadeInImage( selectedImage );
203       StartTransitionAnimation();
204       break;
205     }
206     case SelectedState:
207     {
208       FadeOutImage( selectedBackgroundImage );
209       FadeOutImage( selectedImage );
210       FadeInImage( buttonImage );
211       StartTransitionAnimation();
212       break;
213     }
214     case UnselectedSelectedTransition:
215     {
216       float opacity = 1.f;
217       if( selectedImage )
218       {
219         opacity = selectedImage.GetCurrentOpacity();
220       }
221
222       StopTransitionAnimation( false );
223       FadeOutImage( selectedBackgroundImage, opacity );
224       FadeOutImage( selectedImage, opacity );
225       FadeInImage( buttonImage, 1.f - opacity );
226       StartTransitionAnimation();
227       break;
228     }
229     case SelectedUnselectedTransition:
230     {
231       float opacity = 0.f;
232       if( selectedImage )
233       {
234         opacity = selectedImage.GetCurrentOpacity();
235       }
236
237       StopTransitionAnimation( false );
238       FadeOutImage( buttonImage, 1.f - opacity );
239       FadeInImage( selectedBackgroundImage, opacity );
240       FadeInImage( selectedImage, opacity );
241       StartTransitionAnimation();
242       break;
243     }
244     case DisabledUnselectedTransition:
245     {
246       StopTransitionAnimation();
247       FadeOutImage( buttonImage );
248       FadeInImage( selectedBackgroundImage );
249       FadeInImage( selectedImage );
250       StartTransitionAnimation();
251       break;
252     }
253     case DisabledSelectedTransition:
254     {
255       StopTransitionAnimation();
256       FadeOutImage( selectedBackgroundImage );
257       FadeOutImage( selectedImage );
258       FadeInImage( buttonImage );
259       StartTransitionAnimation();
260       break;
261     }
262     default:
263     {
264       break;
265     }
266   }
267
268   if( mTransitionAnimation )
269   {
270     return true;
271   }
272
273   return false;
274 }
275
276 bool PushButton::OnDisabled()
277 {
278   Actor& buttonImage = GetButtonImage();
279   Actor& selectedImage = GetSelectedImage();
280   Actor& selectedBackgroundImage = GetSelectedBackgroundImage();
281   Actor& backgroundImage = GetBackgroundImage();
282   Actor& disabledImage = GetDisabledImage();
283   Actor& disabledSelectedImage = GetDisabledSelectedImage();
284   Actor& disabledBackgroundImage = GetDisabledBackgroundImage();
285
286   PaintState paintState = GetPaintState();
287
288   switch( paintState )
289   {
290     case UnselectedState:
291     {
292       FadeOutImage( backgroundImage );
293       FadeOutImage( buttonImage );
294       FadeInImage( disabledBackgroundImage );
295       FadeInImage( disabledImage );
296       StartTransitionAnimation();
297       break;
298     }
299     case SelectedState:
300     {
301       FadeOutImage( backgroundImage );
302       FadeOutImage( selectedBackgroundImage );
303       FadeOutImage( selectedImage );
304       FadeInImage( disabledBackgroundImage );
305       FadeInImage( disabledSelectedImage );
306       StartTransitionAnimation();
307       break;
308     }
309     case DisabledUnselectedState:
310     {
311       FadeOutImage( disabledBackgroundImage );
312       FadeOutImage( disabledImage );
313       FadeInImage( backgroundImage );
314       FadeInImage( buttonImage );
315       StartTransitionAnimation();
316       break;
317     }
318     case DisabledSelectedState:
319     {
320       FadeOutImage( disabledBackgroundImage );
321       FadeOutImage( disabledSelectedImage );
322       FadeInImage( backgroundImage );
323       FadeInImage( selectedBackgroundImage );
324       FadeInImage( selectedImage );
325       StartTransitionAnimation();
326       break;
327     }
328     case UnselectedSelectedTransition:
329     {
330       float opacity = 1.f;
331       if( selectedImage )
332       {
333         opacity = selectedImage.GetCurrentOpacity();
334       }
335
336       StopTransitionAnimation();
337       FadeOutImage( backgroundImage );
338       FadeOutImage( selectedBackgroundImage, opacity );
339       FadeOutImage( selectedImage, opacity );
340       FadeInImage( disabledBackgroundImage );
341       FadeInImage( disabledSelectedImage );
342       StartTransitionAnimation();
343       break;
344     }
345     case SelectedUnselectedTransition:
346     {
347       float opacity = 1.f;
348       if( buttonImage )
349       {
350         opacity = buttonImage.GetCurrentOpacity();
351       }
352
353       StopTransitionAnimation();
354       FadeOutImage( backgroundImage );
355       FadeOutImage( buttonImage, opacity );
356       FadeInImage( disabledBackgroundImage );
357       FadeInImage( disabledImage );
358       StartTransitionAnimation();
359       break;
360     }
361     case UnselectedDisabledTransition:
362     {
363       float opacity = 1.f;
364       if( disabledImage )
365       {
366         opacity = disabledImage.GetCurrentOpacity();
367       }
368
369       StopTransitionAnimation( false );
370       FadeOutImage( disabledBackgroundImage, opacity );
371       FadeOutImage( disabledImage, opacity );
372       FadeInImage( backgroundImage, 1.f - opacity );
373       FadeInImage( buttonImage, 1.f - opacity );
374       StartTransitionAnimation();
375       break;
376     }
377     case DisabledUnselectedTransition:
378     {
379       float opacity = 1.f;
380       if( buttonImage )
381       {
382         opacity = buttonImage.GetCurrentOpacity();
383       }
384
385       StopTransitionAnimation( false );
386       FadeOutImage( backgroundImage, opacity );
387       FadeOutImage( buttonImage, opacity );
388       FadeInImage( disabledBackgroundImage, 1.f - opacity );
389       FadeInImage( disabledImage, 1.f - opacity );
390       StartTransitionAnimation();
391       break;
392     }
393     case SelectedDisabledTransition:
394     {
395       float opacity = 1.f;
396       if( disabledSelectedImage )
397       {
398         opacity = disabledSelectedImage.GetCurrentOpacity();
399       }
400
401       StopTransitionAnimation( false );
402       FadeOutImage( disabledBackgroundImage, opacity );
403       FadeOutImage( disabledSelectedImage, opacity );
404       FadeInImage( backgroundImage, 1.f - opacity );
405       FadeInImage( selectedBackgroundImage, 1.f - opacity );
406       FadeInImage( selectedImage, 1.f - opacity );
407       StartTransitionAnimation();
408       break;
409     }
410     case DisabledSelectedTransition:
411     {
412       float opacity = 1.f;
413       if( selectedImage )
414       {
415         opacity = selectedImage.GetCurrentOpacity();
416       }
417
418       StopTransitionAnimation( false );
419       FadeOutImage( backgroundImage, opacity );
420       FadeOutImage( selectedBackgroundImage, opacity );
421       FadeOutImage( selectedImage, opacity );
422       FadeInImage( disabledBackgroundImage, 1.f - opacity );
423       FadeInImage( disabledSelectedImage, 1.f - opacity );
424       StartTransitionAnimation();
425       break;
426     }
427   }
428
429   if( mTransitionAnimation )
430   {
431     return true;
432   }
433
434   return false;
435 }
436
437 bool PushButton::OnPressed()
438 {
439   Actor& buttonImage = GetButtonImage();
440   Actor& selectedImage = GetSelectedImage();
441   Actor& selectedBackgroundImage = GetSelectedBackgroundImage();
442
443   PaintState paintState = GetPaintState();
444
445   switch( paintState )
446   {
447     case UnselectedState:
448     {
449       FadeOutImage( buttonImage );
450       FadeInImage( selectedBackgroundImage );
451       FadeInImage( selectedImage );
452       StartTransitionAnimation();
453       break;
454     }
455     case SelectedUnselectedTransition:
456     {
457       float opacity = 1.f;
458       if( buttonImage )
459       {
460         opacity = buttonImage.GetCurrentOpacity();
461       }
462
463       StopTransitionAnimation( false );
464       FadeOutImage( buttonImage, opacity );
465       FadeInImage( selectedBackgroundImage, 1.f - opacity );
466       FadeInImage( selectedImage, 1.f - opacity );
467       StartTransitionAnimation();
468       break;
469     }
470     case DisabledUnselectedTransition:
471     {
472       float opacity = 1.f;
473       if( buttonImage )
474       {
475         opacity = buttonImage.GetCurrentOpacity();
476       }
477
478       StopTransitionAnimation();
479       FadeOutImage( buttonImage, opacity );
480       FadeInImage( selectedBackgroundImage );
481       FadeInImage( selectedImage );
482       StartTransitionAnimation();
483       break;
484     }
485     default:
486       break;
487   }
488
489   if( mTransitionAnimation )
490   {
491     return true;
492   }
493
494   return false;
495 }
496
497 bool PushButton::OnReleased()
498 {
499   Actor& buttonImage = GetButtonImage();
500   Actor& selectedImage = GetSelectedImage();
501   Actor& selectedBackgroundImage = GetSelectedBackgroundImage();
502
503   PaintState paintState = GetPaintState();
504
505   switch( paintState )
506   {
507     case SelectedState:
508     {
509       FadeOutImage( selectedBackgroundImage );
510       FadeOutImage( selectedImage );
511       FadeInImage( buttonImage );
512       StartTransitionAnimation();
513       break;
514     }
515     case UnselectedSelectedTransition:
516     {
517       float opacity = 1.f;
518       if( selectedImage )
519       {
520         opacity = selectedImage.GetCurrentOpacity();
521       }
522
523       StopTransitionAnimation( false );
524       FadeOutImage( selectedBackgroundImage, opacity );
525       FadeOutImage( selectedImage, opacity );
526       FadeInImage( buttonImage, 1.f - opacity );
527       StartTransitionAnimation();
528       break;
529     }
530     case DisabledSelectedTransition:
531     {
532       float opacity = 1.f;
533       if( selectedImage )
534       {
535         opacity = selectedImage.GetCurrentOpacity();
536       }
537
538       StopTransitionAnimation();
539       FadeOutImage( selectedBackgroundImage, opacity );
540       FadeOutImage( selectedImage, opacity );
541       FadeInImage( buttonImage );
542       StartTransitionAnimation();
543       break;
544     }
545     default:
546     {
547       break;
548     }
549   }
550
551   if( mTransitionAnimation )
552   {
553     return true;
554   }
555
556   return false;
557 }
558
559 void PushButton::StopAllAnimations()
560 {
561   StopTransitionAnimation();
562 }
563
564 void PushButton::OnControlSizeSet( const Vector3& targetSize )
565 {
566   if( targetSize != mSize )
567   {
568     mSize = targetSize;
569
570     Actor& label = GetLabel();
571
572     if( label )
573     {
574       label.SetSize( mSize );
575     }
576   }
577 }
578
579 Vector3 PushButton::GetNaturalSize()
580 {
581   Vector3 size;
582
583   // If background and background not scale9 try get size from that
584   ImageActor imageActor = FindImageActor( GetButtonImage() );
585   if( imageActor && imageActor.GetStyle() != ImageActor::STYLE_NINE_PATCH )
586   {
587     size.width = imageActor.GetRelayoutSize( WIDTH );
588     size.height = imageActor.GetRelayoutSize( HEIGHT );
589   }
590
591   ImageActor backgroundImageActor = FindImageActor( GetBackgroundImage() );
592   if( backgroundImageActor && backgroundImageActor.GetStyle() != ImageActor::STYLE_NINE_PATCH )
593   {
594     size.width = std::max( size.width, backgroundImageActor.GetRelayoutSize( WIDTH ) );
595     size.height = std::max( size.height, backgroundImageActor.GetRelayoutSize( HEIGHT ) );
596   }
597
598   // If label, test against it's size
599   Toolkit::TextView textView = Toolkit::TextView::DownCast( GetLabel() );
600   if( textView )
601   {
602     Vector3 textViewSize = textView.GetNaturalSize();
603
604     size.width = std::max( size.width, textViewSize.width + TEXT_PADDING * 2.0f );
605     size.height = std::max( size.height, textViewSize.height + TEXT_PADDING * 2.0f );
606   }
607
608   return size;
609 }
610
611 void PushButton::StartTransitionAnimation()
612 {
613   if( mTransitionAnimation )
614   {
615     mTransitionAnimation.FinishedSignal().Connect( this, &PushButton::TransitionAnimationFinished );
616     mTransitionAnimation.Play();
617   }
618 }
619
620 void PushButton::StopTransitionAnimation( bool remove )
621 {
622   if( mTransitionAnimation )
623   {
624     mTransitionAnimation.Clear();
625     mTransitionAnimation.Reset();
626   }
627
628   if( remove )
629   {
630     UpdatePaintTransitionState();
631   }
632 }
633
634 void PushButton::FadeInImage( Actor& image, float opacity, Vector3 scale )
635 {
636   if( image )
637   {
638     image.SetOpacity( opacity );
639     image.SetScale( scale );
640
641     if( !mTransitionAnimation )
642     {
643       mTransitionAnimation = Dali::Animation::New( GetAnimationTime() );
644     }
645
646     mTransitionAnimation.AnimateTo( Property( image, Actor::Property::COLOR_ALPHA ), 1.f );
647   }
648 }
649
650 void PushButton::FadeOutImage( Actor& image, float opacity, Vector3 scale )
651 {
652   if( image )
653   {
654     image.SetOpacity( opacity );
655     image.SetScale( scale );
656
657     if( !mTransitionAnimation )
658     {
659       mTransitionAnimation = Dali::Animation::New( GetAnimationTime() );
660     }
661
662     mTransitionAnimation.AnimateTo( Property( image, Actor::Property::COLOR_ALPHA ), 0.f );
663   }
664 }
665
666 void PushButton::TransitionAnimationFinished( Dali::Animation& source )
667 {
668   StopTransitionAnimation();
669 }
670
671 } // namespace Internal
672
673 } // namespace Toolkit
674
675 } // namespace Dali