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