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