Merge remote-tracking branch 'origin/tizen' into new_text
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / buttons / 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 "button-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/events/touch-event.h>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/public-api/object/type-registry-helper.h>
25 #include <dali/public-api/actors/image-actor.h>
26 #include <dali/public-api/scripting/scripting.h>
27
28 // INTERNAL INCLUDES
29
30 namespace Dali
31 {
32
33 namespace Toolkit
34 {
35
36 namespace Internal
37 {
38
39 namespace
40 {
41
42 BaseHandle Create()
43 {
44   // empty handle as we cannot create button (but type registered for clicked signal)
45   return BaseHandle();
46 }
47
48 // Setup properties, signals and actions using the type-registry.
49 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Button, Toolkit::Control, Create );
50
51 DALI_PROPERTY_REGISTRATION( Button, "disabled",                     BOOLEAN, DISABLED                     )
52 DALI_PROPERTY_REGISTRATION( Button, "auto-repeating",               BOOLEAN, AUTO_REPEATING               )
53 DALI_PROPERTY_REGISTRATION( Button, "initial-auto-repeating-delay", FLOAT,   INITIAL_AUTO_REPEATING_DELAY )
54 DALI_PROPERTY_REGISTRATION( Button, "next-auto-repeating-delay",    FLOAT,   NEXT_AUTO_REPEATING_DELAY    )
55 DALI_PROPERTY_REGISTRATION( Button, "togglable",                    BOOLEAN, TOGGLABLE                    )
56 DALI_PROPERTY_REGISTRATION( Button, "selected",                     BOOLEAN, SELECTED                     )
57 DALI_PROPERTY_REGISTRATION( Button, "normal-state-actor",           MAP,     NORMAL_STATE_ACTOR           )
58 DALI_PROPERTY_REGISTRATION( Button, "selected-state-actor",         MAP,     SELECTED_STATE_ACTOR         )
59 DALI_PROPERTY_REGISTRATION( Button, "disabled-state-actor",         MAP,     DISABLED_STATE_ACTOR         )
60 DALI_PROPERTY_REGISTRATION( Button, "label-actor",                  MAP,     LABEL_ACTOR                  )
61
62 DALI_SIGNAL_REGISTRATION(   Button, "pressed",                               SIGNAL_PRESSED               )
63 DALI_SIGNAL_REGISTRATION(   Button, "released",                              SIGNAL_RELEASED              )
64 DALI_SIGNAL_REGISTRATION(   Button, "clicked",                               SIGNAL_CLICKED               )
65 DALI_SIGNAL_REGISTRATION(   Button, "state-changed",                         SIGNAL_STATE_CHANGED         )
66
67 DALI_ACTION_REGISTRATION(   Button, "button-click",                          ACTION_BUTTON_CLICK          )
68
69 DALI_TYPE_REGISTRATION_END()
70
71 const unsigned int INITIAL_AUTOREPEATING_DELAY( 0.15f );
72 const unsigned int NEXT_AUTOREPEATING_DELAY( 0.05f );
73
74 } // unnamed namespace
75
76 Button::Button()
77 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ),
78   mAutoRepeatingTimer(),
79   mDisabled( false ),
80   mAutoRepeating( false ),
81   mTogglableButton( false ),
82   mSelected( false ),
83   mInitialAutoRepeatingDelay( INITIAL_AUTOREPEATING_DELAY ),
84   mNextAutoRepeatingDelay( NEXT_AUTOREPEATING_DELAY ),
85   mAnimationTime( 0.0f ),
86   mClickActionPerforming( false ),
87   mState( ButtonUp )
88 {
89 }
90
91 Button::~Button()
92 {
93   if( mAutoRepeatingTimer )
94   {
95     mAutoRepeatingTimer.Reset();
96   }
97 }
98
99 void Button::SetDisabled( bool disabled )
100 {
101   if( disabled != mDisabled )
102   {
103     mDisabled = disabled;
104
105     OnDisabled( mDisabled );
106   }
107 }
108
109 bool Button::IsDisabled() const
110 {
111   return mDisabled;
112 }
113
114 void Button::SetAutoRepeating( bool autoRepeating )
115 {
116   mAutoRepeating = autoRepeating;
117
118   // An autorepeating button can't be a togglable button.
119   if( autoRepeating )
120   {
121     mTogglableButton = false;
122
123     if( mSelected )
124     {
125       // Emit a signal is not wanted, only change the appearance.
126       OnSelected( false );
127
128       mSelected = false;
129
130       RelayoutRequest();
131     }
132   }
133 }
134
135 bool Button::IsAutoRepeating() const
136 {
137   return mAutoRepeating;
138 }
139
140 void Button::SetInitialAutoRepeatingDelay( float initialAutoRepeatingDelay )
141 {
142   DALI_ASSERT_ALWAYS( initialAutoRepeatingDelay > 0.f );
143   mInitialAutoRepeatingDelay = initialAutoRepeatingDelay;
144 }
145
146 float Button::GetInitialAutoRepeatingDelay() const
147 {
148   return mInitialAutoRepeatingDelay;
149 }
150
151 void Button::SetNextAutoRepeatingDelay( float nextAutoRepeatingDelay )
152 {
153   DALI_ASSERT_ALWAYS( nextAutoRepeatingDelay > 0.f );
154   mNextAutoRepeatingDelay = nextAutoRepeatingDelay;
155 }
156
157 float Button::GetNextAutoRepeatingDelay() const
158 {
159   return mNextAutoRepeatingDelay;
160 }
161
162 void Button::SetTogglableButton( bool togglable )
163 {
164   mTogglableButton = togglable;
165
166   // A togglable button can't be an autorepeating button.
167   if( togglable )
168   {
169     mAutoRepeating = false;
170   }
171 }
172
173 bool Button::IsTogglableButton() const
174 {
175   return mTogglableButton;
176 }
177
178 void Button::SetSelected( bool selected )
179 {
180   if( !mDisabled && mTogglableButton && ( selected != mSelected ) )
181   {
182     // Notifies the derived class the button has been selected.
183     OnSelected( selected );
184
185     mSelected = selected;
186
187     Toolkit::Button handle( GetOwner() );
188
189     // Emit signal.
190     mStateChangedSignal.Emit( handle );
191
192     RelayoutRequest();
193   }
194 }
195
196 bool Button::IsSelected() const
197 {
198   return mTogglableButton && mSelected;
199 }
200
201 void Button::SetAnimationTime( float animationTime )
202 {
203   mAnimationTime = animationTime;
204 }
205
206 float Button::GetAnimationTime() const
207 {
208   return mAnimationTime;
209 }
210
211 void Button::SetLabel( const std::string& label )
212 {
213 }
214
215 void Button::SetLabel( Actor label )
216 {
217   if( mLabel != label )
218   {
219     if( mLabel && mLabel.GetParent() )
220     {
221       mLabel.GetParent().Remove( mLabel );
222     }
223
224     mLabel = label;
225
226     OnLabelSet();
227
228     RelayoutRequest();
229   }
230 }
231
232 Actor Button::GetLabel() const
233 {
234   return mLabel;
235 }
236
237 Actor& Button::GetLabel()
238 {
239   return mLabel;
240 }
241
242 Actor Button::GetButtonImage() const
243 {
244   return mButtonContent;
245 }
246
247 Actor& Button::GetButtonImage()
248 {
249   return mButtonContent;
250 }
251
252 Actor Button::GetSelectedImage() const
253 {
254   return mSelectedContent;
255 }
256
257 Actor& Button::GetSelectedImage()
258 {
259   return mSelectedContent;
260 }
261
262 Actor Button::GetBackgroundImage() const
263 {
264   return mBackgroundContent;
265 }
266
267 Actor& Button::GetBackgroundImage()
268 {
269   return mBackgroundContent;
270 }
271
272 Actor Button::GetDisabledImage() const
273 {
274   return mDisabledContent;
275 }
276
277 Actor& Button::GetDisabledImage()
278 {
279   return mDisabledContent;
280 }
281
282 Actor Button::GetDisabledSelectedImage() const
283 {
284   return mDisabledSelectedContent;
285 }
286
287 Actor& Button::GetDisabledSelectedImage()
288 {
289   return mDisabledSelectedContent;
290 }
291
292 Actor Button::GetDisabledBackgroundImage() const
293 {
294   return mDisabledBackgroundContent;
295 }
296
297 Actor& Button::GetDisabledBackgroundImage()
298 {
299   return mDisabledBackgroundContent;
300 }
301
302 bool Button::DoAction( BaseObject* object, const std::string& actionName, const PropertyValueContainer& attributes )
303 {
304   bool ret = false;
305
306   Dali::BaseHandle handle( object );
307
308   Toolkit::Button button = Toolkit::Button::DownCast( handle );
309
310   DALI_ASSERT_ALWAYS( button );
311
312   if( 0 == strcmp( actionName.c_str(), ACTION_BUTTON_CLICK ) )
313   {
314     GetImplementation( button ).DoClickAction( attributes );
315     ret = true;
316   }
317
318   return ret;
319 }
320
321 void Button::DoClickAction( const PropertyValueContainer& attributes )
322 {
323   // Prevents the button signals from doing a recursive loop by sending an action
324   // and re-emitting the signals.
325   if( !mClickActionPerforming )
326   {
327     mClickActionPerforming = true;
328     OnButtonDown();
329     mState = ButtonDown;
330     OnButtonUp();
331     mClickActionPerforming = false;
332   }
333 }
334
335 void Button::OnButtonStageDisconnection()
336 {
337   if( ButtonDown == mState )
338   {
339     if( !mTogglableButton )
340     {
341       Toolkit::Button handle( GetOwner() );
342
343       // Notifies the derived class the button has been released.
344       OnReleased();
345
346       if( mAutoRepeating )
347       {
348         mAutoRepeatingTimer.Reset();
349       }
350     }
351   }
352 }
353
354 void Button::OnButtonDown()
355 {
356   if( !mTogglableButton )
357   {
358     Toolkit::Button handle( GetOwner() );
359
360     // Notifies the derived class the button has been pressed.
361     OnPressed();
362
363     if( mAutoRepeating )
364     {
365       SetUpTimer( mInitialAutoRepeatingDelay );
366     }
367
368     //Emit signal.
369     mPressedSignal.Emit( handle );
370   }
371 }
372
373 void Button::OnButtonUp()
374 {
375   if( ButtonDown == mState )
376   {
377     if( mTogglableButton )
378     {
379       SetSelected( !mSelected );
380     }
381     else
382     {
383       // Notifies the derived class the button has been clicked.
384       OnReleased();
385       OnClicked();
386
387       if( mAutoRepeating )
388       {
389         mAutoRepeatingTimer.Reset();
390       }
391
392       Toolkit::Button handle( GetOwner() );
393
394       //Emit signal.
395       mReleasedSignal.Emit( handle );
396       mClickedSignal.Emit( handle );
397     }
398   }
399 }
400
401 void Button::OnTouchPointLeave()
402 {
403   if( ButtonDown == mState )
404   {
405     if( !mTogglableButton )
406     {
407       Toolkit::Button handle( GetOwner() );
408
409       // Notifies the derived class the button has been released.
410       OnReleased();
411
412       if( mAutoRepeating )
413       {
414         mAutoRepeatingTimer.Reset();
415       }
416
417       //Emit signal.
418       mReleasedSignal.Emit( handle );
419     }
420   }
421 }
422
423 void Button::OnTouchPointInterrupted()
424 {
425   OnTouchPointLeave();
426 }
427
428 Toolkit::Button::ButtonSignalType& Button::PressedSignal()
429 {
430   return mPressedSignal;
431 }
432
433 Toolkit::Button::ButtonSignalType& Button::ReleasedSignal()
434 {
435   return mReleasedSignal;
436 }
437
438 Toolkit::Button::ButtonSignalType& Button::ClickedSignal()
439 {
440   return mClickedSignal;
441 }
442
443 Toolkit::Button::ButtonSignalType& Button::StateChangedSignal()
444 {
445   return mStateChangedSignal;
446 }
447
448 bool Button::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
449 {
450   Dali::BaseHandle handle( object );
451
452   bool connected( true );
453   Toolkit::Button button = Toolkit::Button::DownCast( handle );
454
455   if( 0 == strcmp( signalName.c_str(), SIGNAL_PRESSED ) )
456   {
457     button.PressedSignal().Connect( tracker, functor );
458   }
459   else if( 0 == strcmp( signalName.c_str(), SIGNAL_RELEASED ) )
460   {
461     button.ReleasedSignal().Connect( tracker, functor );
462   }
463   else if( 0 == strcmp( signalName.c_str(), SIGNAL_CLICKED ) )
464   {
465     button.ClickedSignal().Connect( tracker, functor );
466   }
467   else if( 0 == strcmp( signalName.c_str(), SIGNAL_STATE_CHANGED ) )
468   {
469     button.StateChangedSignal().Connect( tracker, functor );
470   }
471   else
472   {
473     // signalName does not match any signal
474     connected = false;
475   }
476
477   return connected;
478 }
479
480 bool Button::OnTouchEvent(const TouchEvent& event)
481 {
482   // Only events are processed when the button is not disabled and the touch event has only
483   // one touch point.
484   if( ( !mDisabled ) && ( 1 == event.GetPointCount() ) )
485   {
486     switch( event.GetPoint(0).state )
487     {
488       case TouchPoint::Down:
489       {
490         OnButtonDown(); // Notification for derived classes.
491
492         // Sets the button state to ButtonDown.
493         mState = ButtonDown;
494         break;
495       }
496       case TouchPoint::Up:
497       {
498         OnButtonUp(); // Notification for derived classes.
499
500         // Sets the button state to ButtonUp.
501         mState = ButtonUp;
502         break;
503       }
504       case TouchPoint::Interrupted:
505       {
506         OnTouchPointInterrupted(); // Notification for derived classes.
507
508         // Sets the button state to the default (ButtonUp).
509         mState = ButtonUp;
510         break;
511       }
512       case TouchPoint::Leave:
513       {
514         OnTouchPointLeave(); // Notification for derived classes.
515
516         // Sets the button state to the default (ButtonUp).
517         mState = ButtonUp;
518         break;
519       }
520       case TouchPoint::Motion:
521       case TouchPoint::Stationary: // FALLTHROUGH
522       {
523         // Nothing to do
524         break;
525       }
526       default:
527       {
528         DALI_ASSERT_ALWAYS( !"Point status unhandled." );
529         break;
530       }
531     }
532   }
533   else if( 1 < event.GetPointCount() )
534   {
535     OnTouchPointLeave(); // Notification for derived classes.
536
537     // Sets the button state to the default (ButtonUp).
538     mState = ButtonUp;
539   }
540
541   return false;
542 }
543
544 void Button::OnInitialize()
545 {
546   Actor self = Self();
547
548   mTapDetector = TapGestureDetector::New();
549   mTapDetector.Attach( self );
550   mTapDetector.DetectedSignal().Connect(this, &Button::OnTap);
551
552   OnButtonInitialize();
553
554   self.SetKeyboardFocusable( true );
555 }
556
557 void Button::OnActivated()
558 {
559   // When the button is activated, it performs the click action
560   PropertyValueContainer attributes;
561   DoClickAction( attributes );
562 }
563
564 void Button::OnTap(Actor actor, const TapGesture& tap)
565 {
566   // Do nothing.
567 }
568
569 void Button::SetUpTimer( float delay )
570 {
571   mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
572   mAutoRepeatingTimer.TickSignal().Connect( this, &Button::AutoRepeatingSlot );
573   mAutoRepeatingTimer.Start();
574 }
575
576 bool Button::AutoRepeatingSlot()
577 {
578   bool consumed = false;
579   if( !mDisabled )
580   {
581     // Restart the autorepeat timer.
582     SetUpTimer( mNextAutoRepeatingDelay );
583
584     Toolkit::Button handle( GetOwner() );
585
586     // Notifies the derived class the button has been pressed.
587     OnPressed();
588
589     //Emit signal.
590     consumed = mReleasedSignal.Emit( handle );
591     consumed |= mClickedSignal.Emit( handle );
592     consumed |= mPressedSignal.Emit( handle );
593  }
594
595   return consumed;
596 }
597
598 void Button::OnControlStageDisconnection()
599 {
600   OnButtonStageDisconnection(); // Notification for derived classes.
601   mState = ButtonUp;
602 }
603
604 Button::ButtonState Button::GetState()
605 {
606   return mState;
607 }
608
609 void Button::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
610 {
611   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
612
613   if ( button )
614   {
615     switch ( index )
616     {
617       case Toolkit::Button::Property::DISABLED:
618       {
619         GetImplementation( button ).SetDisabled( value.Get<bool>() );
620         break;
621       }
622
623       case Toolkit::Button::Property::AUTO_REPEATING:
624       {
625         GetImplementation( button ).SetAutoRepeating( value.Get< bool >() );
626         break;
627       }
628
629       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
630       {
631         GetImplementation( button ).SetInitialAutoRepeatingDelay( value.Get< float >() );
632         break;
633       }
634
635       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
636       {
637         GetImplementation( button ).SetNextAutoRepeatingDelay( value.Get< float >() );
638         break;
639       }
640
641       case Toolkit::Button::Property::TOGGLABLE:
642       {
643         GetImplementation( button ).SetTogglableButton( value.Get< bool >() );
644         break;
645       }
646
647       case Toolkit::Button::Property::SELECTED:
648       {
649         GetImplementation( button ).SetSelected( value.Get< bool >() );
650         break;
651       }
652
653       case Toolkit::Button::Property::NORMAL_STATE_ACTOR:
654       {
655         GetImplementation( button ).SetButtonImage( Scripting::NewActor( value.Get< Property::Map >() ) );
656         break;
657       }
658
659       case Toolkit::Button::Property::SELECTED_STATE_ACTOR:
660       {
661         GetImplementation( button ).SetSelectedImage( Scripting::NewActor( value.Get< Property::Map >() ) );
662         break;
663       }
664
665       case Toolkit::Button::Property::DISABLED_STATE_ACTOR:
666       {
667         GetImplementation( button ).SetDisabledImage( Scripting::NewActor( value.Get< Property::Map >() ) );
668         break;
669       }
670
671       case Toolkit::Button::Property::LABEL_ACTOR:
672       {
673         GetImplementation( button ).SetLabel( Scripting::NewActor( value.Get< Property::Map >() ) );
674         break;
675       }
676     }
677   }
678 }
679
680 Property::Value Button::GetProperty( BaseObject* object, Property::Index propertyIndex )
681 {
682   Property::Value value;
683
684   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
685
686   if ( button )
687   {
688     switch ( propertyIndex )
689     {
690       case Toolkit::Button::Property::DISABLED:
691       {
692         value = GetImplementation( button ).mDisabled;
693         break;
694       }
695
696       case Toolkit::Button::Property::AUTO_REPEATING:
697       {
698         value = GetImplementation( button ).mAutoRepeating;
699         break;
700       }
701
702       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
703       {
704         value = GetImplementation( button ).mInitialAutoRepeatingDelay;
705         break;
706       }
707
708       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
709       {
710         value = GetImplementation( button ).mNextAutoRepeatingDelay;
711         break;
712       }
713
714       case Toolkit::Button::Property::TOGGLABLE:
715       {
716         value = GetImplementation( button ).mTogglableButton;
717         break;
718       }
719
720       case Toolkit::Button::Property::SELECTED:
721       {
722         value = GetImplementation( button ).mSelected;
723         break;
724       }
725
726       case Toolkit::Button::Property::NORMAL_STATE_ACTOR:
727       {
728         Property::Map map;
729         Scripting::CreatePropertyMap( GetImplementation( button ).mButtonContent, map );
730         value = map;
731         break;
732       }
733
734       case Toolkit::Button::Property::SELECTED_STATE_ACTOR:
735       {
736         Property::Map map;
737         Scripting::CreatePropertyMap( GetImplementation( button ).mSelectedContent, map );
738         value = map;
739         break;
740       }
741
742       case Toolkit::Button::Property::DISABLED_STATE_ACTOR:
743       {
744         Property::Map map;
745         Scripting::CreatePropertyMap( GetImplementation( button ).mDisabledContent, map );
746         value = map;
747         break;
748       }
749
750       case Toolkit::Button::Property::LABEL_ACTOR:
751       {
752         Property::Map map;
753         Scripting::CreatePropertyMap( GetImplementation( button ).mLabel, map );
754         value = map;
755         break;
756       }
757     }
758   }
759
760   return value;
761 }
762
763 } // namespace Internal
764
765 } // namespace Toolkit
766
767 } // namespace Dali