207d3f0035d57c6823e841663f4563dd7e04e988
[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
133 void PushButton::OnSelectedImageSet()
134 {
135   Actor& selectedImage = GetSelectedImage();
136
137   selectedImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS );
138 }
139
140 void PushButton::OnBackgroundImageSet()
141 {
142   Actor& backgroundImage = GetBackgroundImage();
143
144   backgroundImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS );
145 }
146
147 void PushButton::OnSelectedBackgroundImageSet()
148 {
149   Actor& selectedBackgroundImage = GetSelectedBackgroundImage();
150
151   selectedBackgroundImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS );
152 }
153
154 void PushButton::OnDisabledImageSet()
155 {
156   Actor& disabledImage = GetDisabledImage();
157
158   disabledImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS );
159 }
160
161 void PushButton::OnDisabledBackgroundImageSet()
162 {
163   Actor& disabledBackgroundImage = GetDisabledBackgroundImage();
164
165   disabledBackgroundImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS );
166 }
167
168 bool PushButton::OnSelected()
169 {
170   Actor& buttonImage = GetButtonImage();
171   Actor& selectedImage = GetSelectedImage();
172   Actor& selectedBackgroundImage = GetSelectedBackgroundImage();
173
174   PaintState paintState = GetPaintState();
175
176   switch( paintState )
177   {
178     case UnselectedState:
179     {
180       FadeOutImage( buttonImage );
181       FadeInImage( selectedBackgroundImage );
182       FadeInImage( selectedImage );
183       StartTransitionAnimation();
184       break;
185     }
186     case SelectedState:
187     {
188       FadeOutImage( selectedBackgroundImage );
189       FadeOutImage( selectedImage );
190       FadeInImage( buttonImage );
191       StartTransitionAnimation();
192       break;
193     }
194     case UnselectedSelectedTransition:
195     {
196       float opacity = 1.f;
197       if( selectedImage )
198       {
199         opacity = selectedImage.GetCurrentOpacity();
200       }
201
202       StopTransitionAnimation( false );
203       FadeOutImage( selectedBackgroundImage, opacity );
204       FadeOutImage( selectedImage, opacity );
205       FadeInImage( buttonImage, 1.f - opacity );
206       StartTransitionAnimation();
207       break;
208     }
209     case SelectedUnselectedTransition:
210     {
211       float opacity = 0.f;
212       if( selectedImage )
213       {
214         opacity = selectedImage.GetCurrentOpacity();
215       }
216
217       StopTransitionAnimation( false );
218       FadeOutImage( buttonImage, 1.f - opacity );
219       FadeInImage( selectedBackgroundImage, opacity );
220       FadeInImage( selectedImage, opacity );
221       StartTransitionAnimation();
222       break;
223     }
224     case DisabledUnselectedTransition:
225     {
226       StopTransitionAnimation();
227       FadeOutImage( buttonImage );
228       FadeInImage( selectedBackgroundImage );
229       FadeInImage( selectedImage );
230       StartTransitionAnimation();
231       break;
232     }
233     case DisabledSelectedTransition:
234     {
235       StopTransitionAnimation();
236       FadeOutImage( selectedBackgroundImage );
237       FadeOutImage( selectedImage );
238       FadeInImage( buttonImage );
239       StartTransitionAnimation();
240       break;
241     }
242     default:
243     {
244       break;
245     }
246   }
247
248   if( mTransitionAnimation )
249   {
250     return true;
251   }
252
253   return false;
254 }
255
256 bool PushButton::OnDisabled()
257 {
258   Actor& buttonImage = GetButtonImage();
259   Actor& selectedImage = GetSelectedImage();
260   Actor& selectedBackgroundImage = GetSelectedBackgroundImage();
261   Actor& backgroundImage = GetBackgroundImage();
262   Actor& disabledImage = GetDisabledImage();
263   Actor& disabledSelectedImage = GetDisabledSelectedImage();
264   Actor& disabledBackgroundImage = GetDisabledBackgroundImage();
265
266   PaintState paintState = GetPaintState();
267
268   switch( paintState )
269   {
270     case UnselectedState:
271     {
272       FadeOutImage( backgroundImage );
273       FadeOutImage( buttonImage );
274       FadeInImage( disabledBackgroundImage );
275       FadeInImage( disabledImage );
276       StartTransitionAnimation();
277       break;
278     }
279     case SelectedState:
280     {
281       FadeOutImage( backgroundImage );
282       FadeOutImage( selectedBackgroundImage );
283       FadeOutImage( selectedImage );
284       FadeInImage( disabledBackgroundImage );
285       FadeInImage( disabledSelectedImage );
286       StartTransitionAnimation();
287       break;
288     }
289     case DisabledUnselectedState:
290     {
291       FadeOutImage( disabledBackgroundImage );
292       FadeOutImage( disabledImage );
293       FadeInImage( backgroundImage );
294       FadeInImage( buttonImage );
295       StartTransitionAnimation();
296       break;
297     }
298     case DisabledSelectedState:
299     {
300       FadeOutImage( disabledBackgroundImage );
301       FadeOutImage( disabledSelectedImage );
302       FadeInImage( backgroundImage );
303       FadeInImage( selectedBackgroundImage );
304       FadeInImage( selectedImage );
305       StartTransitionAnimation();
306       break;
307     }
308     case UnselectedSelectedTransition:
309     {
310       float opacity = 1.f;
311       if( selectedImage )
312       {
313         opacity = selectedImage.GetCurrentOpacity();
314       }
315
316       StopTransitionAnimation();
317       FadeOutImage( backgroundImage );
318       FadeOutImage( selectedBackgroundImage, opacity );
319       FadeOutImage( selectedImage, opacity );
320       FadeInImage( disabledBackgroundImage );
321       FadeInImage( disabledSelectedImage );
322       StartTransitionAnimation();
323       break;
324     }
325     case SelectedUnselectedTransition:
326     {
327       float opacity = 1.f;
328       if( buttonImage )
329       {
330         opacity = buttonImage.GetCurrentOpacity();
331       }
332
333       StopTransitionAnimation();
334       FadeOutImage( backgroundImage );
335       FadeOutImage( buttonImage, opacity );
336       FadeInImage( disabledBackgroundImage );
337       FadeInImage( disabledImage );
338       StartTransitionAnimation();
339       break;
340     }
341     case UnselectedDisabledTransition:
342     {
343       float opacity = 1.f;
344       if( disabledImage )
345       {
346         opacity = disabledImage.GetCurrentOpacity();
347       }
348
349       StopTransitionAnimation( false );
350       FadeOutImage( disabledBackgroundImage, opacity );
351       FadeOutImage( disabledImage, opacity );
352       FadeInImage( backgroundImage, 1.f - opacity );
353       FadeInImage( buttonImage, 1.f - opacity );
354       StartTransitionAnimation();
355       break;
356     }
357     case DisabledUnselectedTransition:
358     {
359       float opacity = 1.f;
360       if( buttonImage )
361       {
362         opacity = buttonImage.GetCurrentOpacity();
363       }
364
365       StopTransitionAnimation( false );
366       FadeOutImage( backgroundImage, opacity );
367       FadeOutImage( buttonImage, opacity );
368       FadeInImage( disabledBackgroundImage, 1.f - opacity );
369       FadeInImage( disabledImage, 1.f - opacity );
370       StartTransitionAnimation();
371       break;
372     }
373     case SelectedDisabledTransition:
374     {
375       float opacity = 1.f;
376       if( disabledSelectedImage )
377       {
378         opacity = disabledSelectedImage.GetCurrentOpacity();
379       }
380
381       StopTransitionAnimation( false );
382       FadeOutImage( disabledBackgroundImage, opacity );
383       FadeOutImage( disabledSelectedImage, opacity );
384       FadeInImage( backgroundImage, 1.f - opacity );
385       FadeInImage( selectedBackgroundImage, 1.f - opacity );
386       FadeInImage( selectedImage, 1.f - opacity );
387       StartTransitionAnimation();
388       break;
389     }
390     case DisabledSelectedTransition:
391     {
392       float opacity = 1.f;
393       if( selectedImage )
394       {
395         opacity = selectedImage.GetCurrentOpacity();
396       }
397
398       StopTransitionAnimation( false );
399       FadeOutImage( backgroundImage, opacity );
400       FadeOutImage( selectedBackgroundImage, opacity );
401       FadeOutImage( selectedImage, opacity );
402       FadeInImage( disabledBackgroundImage, 1.f - opacity );
403       FadeInImage( disabledSelectedImage, 1.f - opacity );
404       StartTransitionAnimation();
405       break;
406     }
407   }
408
409   if( mTransitionAnimation )
410   {
411     return true;
412   }
413
414   return false;
415 }
416
417 bool PushButton::OnPressed()
418 {
419   Actor& buttonImage = GetButtonImage();
420   Actor& selectedImage = GetSelectedImage();
421   Actor& selectedBackgroundImage = GetSelectedBackgroundImage();
422
423   PaintState paintState = GetPaintState();
424
425   switch( paintState )
426   {
427     case UnselectedState:
428     {
429       FadeOutImage( buttonImage );
430       FadeInImage( selectedBackgroundImage );
431       FadeInImage( selectedImage );
432       StartTransitionAnimation();
433       break;
434     }
435     case SelectedUnselectedTransition:
436     {
437       float opacity = 1.f;
438       if( buttonImage )
439       {
440         opacity = buttonImage.GetCurrentOpacity();
441       }
442
443       StopTransitionAnimation( false );
444       FadeOutImage( buttonImage, opacity );
445       FadeInImage( selectedBackgroundImage, 1.f - opacity );
446       FadeInImage( selectedImage, 1.f - opacity );
447       StartTransitionAnimation();
448       break;
449     }
450     case DisabledUnselectedTransition:
451     {
452       float opacity = 1.f;
453       if( buttonImage )
454       {
455         opacity = buttonImage.GetCurrentOpacity();
456       }
457
458       StopTransitionAnimation();
459       FadeOutImage( buttonImage, opacity );
460       FadeInImage( selectedBackgroundImage );
461       FadeInImage( selectedImage );
462       StartTransitionAnimation();
463       break;
464     }
465     default:
466       break;
467   }
468
469   if( mTransitionAnimation )
470   {
471     return true;
472   }
473
474   return false;
475 }
476
477 bool PushButton::OnReleased()
478 {
479   Actor& buttonImage = GetButtonImage();
480   Actor& selectedImage = GetSelectedImage();
481   Actor& selectedBackgroundImage = GetSelectedBackgroundImage();
482
483   PaintState paintState = GetPaintState();
484
485   switch( paintState )
486   {
487     case SelectedState:
488     {
489       FadeOutImage( selectedBackgroundImage );
490       FadeOutImage( selectedImage );
491       FadeInImage( buttonImage );
492       StartTransitionAnimation();
493       break;
494     }
495     case UnselectedSelectedTransition:
496     {
497       float opacity = 1.f;
498       if( selectedImage )
499       {
500         opacity = selectedImage.GetCurrentOpacity();
501       }
502
503       StopTransitionAnimation( false );
504       FadeOutImage( selectedBackgroundImage, opacity );
505       FadeOutImage( selectedImage, opacity );
506       FadeInImage( buttonImage, 1.f - opacity );
507       StartTransitionAnimation();
508       break;
509     }
510     case DisabledSelectedTransition:
511     {
512       float opacity = 1.f;
513       if( selectedImage )
514       {
515         opacity = selectedImage.GetCurrentOpacity();
516       }
517
518       StopTransitionAnimation();
519       FadeOutImage( selectedBackgroundImage, opacity );
520       FadeOutImage( selectedImage, opacity );
521       FadeInImage( buttonImage );
522       StartTransitionAnimation();
523       break;
524     }
525     default:
526     {
527       break;
528     }
529   }
530
531   if( mTransitionAnimation )
532   {
533     return true;
534   }
535
536   return false;
537 }
538
539 void PushButton::StopAllAnimations()
540 {
541   StopTransitionAnimation();
542 }
543
544 void PushButton::OnControlSizeSet( const Vector3& targetSize )
545 {
546   if( targetSize != mSize )
547   {
548     mSize = targetSize;
549
550     Actor& label = GetLabel();
551
552     if( label )
553     {
554       label.SetSize( mSize );
555     }
556   }
557 }
558
559 Vector3 PushButton::GetNaturalSize()
560 {
561   Vector3 size = Control::GetNaturalSize();
562
563   const bool widthIsZero = EqualsZero( size.width );
564   const bool heightIsZero = EqualsZero( size.height );
565
566   if( widthIsZero || heightIsZero )
567   {
568     // If background and background not scale9 try get size from that
569     ImageActor imageActor = FindImageActor( GetButtonImage() );
570     if( imageActor && imageActor.GetStyle() != ImageActor::STYLE_NINE_PATCH )
571     {
572       Vector3 imageSize = imageActor.GetNaturalSize();
573
574       if( widthIsZero )
575       {
576         size.width = imageSize.width;
577       }
578
579       if( heightIsZero )
580       {
581         size.height = imageSize.height;
582       }
583     }
584
585     ImageActor backgroundImageActor = FindImageActor( GetBackgroundImage() );
586     if( backgroundImageActor && backgroundImageActor.GetStyle() != ImageActor::STYLE_NINE_PATCH )
587     {
588       Vector3 imageSize = backgroundImageActor.GetNaturalSize();
589
590       if( widthIsZero )
591       {
592         size.width = std::max( size.width, imageSize.width );
593       }
594
595       if( heightIsZero )
596       {
597         size.height = std::max( size.height, imageSize.height );
598       }
599     }
600
601     // If label, test against it's size
602     Toolkit::TextView textView = Toolkit::TextView::DownCast( GetLabel() );
603     if( textView )
604     {
605       Vector3 textViewSize = textView.GetNaturalSize();
606
607       if( widthIsZero )
608       {
609         size.width = std::max( size.width, textViewSize.width + TEXT_PADDING * 2.0f );
610       }
611
612       if( heightIsZero )
613       {
614         size.height = std::max( size.height, textViewSize.height + TEXT_PADDING * 2.0f );
615       }
616     }
617   }
618
619   return size;
620 }
621
622 void PushButton::StartTransitionAnimation()
623 {
624   if( mTransitionAnimation )
625   {
626     mTransitionAnimation.FinishedSignal().Connect( this, &PushButton::TransitionAnimationFinished );
627     mTransitionAnimation.Play();
628   }
629 }
630
631 void PushButton::StopTransitionAnimation( bool remove )
632 {
633   if( mTransitionAnimation )
634   {
635     mTransitionAnimation.Clear();
636     mTransitionAnimation.Reset();
637   }
638
639   if( remove )
640   {
641     UpdatePaintTransitionState();
642   }
643 }
644
645 void PushButton::FadeInImage( Actor& image, float opacity, Vector3 scale )
646 {
647   if( image )
648   {
649     image.SetOpacity( opacity );
650     image.SetScale( scale );
651
652     if( !mTransitionAnimation )
653     {
654       mTransitionAnimation = Dali::Animation::New( GetAnimationTime() );
655     }
656
657     mTransitionAnimation.AnimateTo( Property( image, Actor::Property::COLOR_ALPHA ), 1.f );
658   }
659 }
660
661 void PushButton::FadeOutImage( Actor& image, float opacity, Vector3 scale )
662 {
663   if( image )
664   {
665     image.SetOpacity( opacity );
666     image.SetScale( scale );
667
668     if( !mTransitionAnimation )
669     {
670       mTransitionAnimation = Dali::Animation::New( GetAnimationTime() );
671     }
672
673     mTransitionAnimation.AnimateTo( Property( image, Actor::Property::COLOR_ALPHA ), 0.f );
674   }
675 }
676
677 void PushButton::TransitionAnimationFinished( Dali::Animation& source )
678 {
679   StopTransitionAnimation();
680 }
681
682 } // namespace Internal
683
684 } // namespace Toolkit
685
686 } // namespace Dali