c5e078fe52f0ce1c6e04be6e9df83fa1cecbee70
[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 Flora License, Version 1.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://floralicense.org/license/
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 // CLASS HEADER
18
19 #include "push-button-impl.h"
20
21 // EXTERNAL INCLUDES
22
23 #include <algorithm>
24
25 // INTERNAL INCLUDES
26
27 #include "push-button-default-painter-impl.h"
28
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 using namespace Dali;
44
45 BaseHandle Create()
46 {
47   return Toolkit::PushButton::New();
48 }
49
50 TypeRegistration typeRegistration( typeid(Toolkit::PushButton), typeid(Toolkit::Button), Create );
51
52 SignalConnectorType signalConnector1( typeRegistration, Toolkit::PushButton::SIGNAL_TOGGLED , &PushButton::DoConnectSignal );
53 SignalConnectorType signalConnector2( typeRegistration, Toolkit::PushButton::SIGNAL_PRESSED , &PushButton::DoConnectSignal );
54 SignalConnectorType signalConnector3( typeRegistration, Toolkit::PushButton::SIGNAL_RELEASED, &PushButton::DoConnectSignal );
55
56 TypeAction action1( typeRegistration, Toolkit::PushButton::ACTION_PUSH_BUTTON_CLICK, &PushButton::DoAction );
57
58 }
59
60
61 namespace
62 {
63   const unsigned int INITIAL_AUTOREPEATING_DELAY( 0.15f );
64   const unsigned int NEXT_AUTOREPEATING_DELAY( 0.05f );
65
66   // Helper function used to cast a ButtonPainter to PushButtonDefaultPainter
67   PushButtonDefaultPainterPtr GetPushButtonPainter( Dali::Toolkit::Internal::ButtonPainterPtr painter )
68   {
69     return static_cast<PushButtonDefaultPainter*>( painter.Get() );
70   }
71 } // namespace
72
73 Dali::Toolkit::PushButton PushButton::New()
74 {
75   // Create the implementation, temporarily owned on stack
76   IntrusivePtr< PushButton > internalPushButton = new PushButton();
77
78   // Pass ownership to CustomActor
79   Dali::Toolkit::PushButton pushButton( *internalPushButton );
80
81   // Second-phase init of the implementation
82   // This can only be done after the CustomActor connection has been made...
83   internalPushButton->Initialize();
84
85   return pushButton;
86 }
87
88 void PushButton::SetAutoRepeating( bool autoRepeating )
89 {
90   mAutoRepeating = autoRepeating;
91
92   // An autorepeating button can't be a toggle button.
93   if( autoRepeating )
94   {
95     mToggleButton = false;
96     if( mToggled )
97     {
98       // Emit a signal is not wanted, only change the appearance.
99       Toolkit::PushButton handle( GetOwner() );
100       GetPushButtonPainter( mPainter )->Toggled( handle );
101       mToggled = false;
102     }
103   }
104
105   // Notifies the painter.
106   GetPushButtonPainter( mPainter )->SetAutoRepeating( mAutoRepeating );
107 }
108
109 bool PushButton::IsAutoRepeating() const
110 {
111   return mAutoRepeating;
112 }
113
114 void PushButton::SetInitialAutoRepeatingDelay( float initialAutoRepeatingDelay )
115 {
116   DALI_ASSERT_ALWAYS( initialAutoRepeatingDelay > 0.f );
117   mInitialAutoRepeatingDelay = initialAutoRepeatingDelay;
118 }
119
120 float PushButton::GetInitialAutoRepeatingDelay() const
121 {
122   return mInitialAutoRepeatingDelay;
123 }
124
125 void PushButton::SetNextAutoRepeatingDelay( float nextAutoRepeatingDelay )
126 {
127   DALI_ASSERT_ALWAYS( nextAutoRepeatingDelay > 0.f );
128   mNextAutoRepeatingDelay = nextAutoRepeatingDelay;
129 }
130
131 float PushButton::GetNextAutoRepeatingDelay() const
132 {
133   return mNextAutoRepeatingDelay;
134 }
135
136 void PushButton::SetToggleButton( bool toggle )
137 {
138   mToggleButton = toggle;
139
140   // A toggle button can't be an autorepeating button.
141   if( toggle )
142   {
143     mAutoRepeating = false;
144
145     // Notifies the painter.
146     GetPushButtonPainter( mPainter )->SetAutoRepeating( mAutoRepeating );
147   }
148 }
149
150 bool PushButton::IsToggleButton() const
151 {
152   return mToggleButton;
153 }
154
155 void PushButton::SetToggled( bool toggle )
156 {
157   if( !mDimmed && mToggleButton && ( toggle != mToggled ) )
158   {
159     mToggled = toggle;
160
161     Toolkit::PushButton handle( GetOwner() );
162
163     // Notifies the painter the button has been toggled.
164     GetPushButtonPainter( mPainter )->Toggled( handle );
165
166     // Emit signal.
167     mToggledSignalV2.Emit( handle, mToggled );
168   }
169 }
170
171 bool PushButton::IsToggled() const
172 {
173   return mToggleButton && mToggled;
174 }
175
176 void PushButton::SetButtonImage( Image image )
177 {
178   SetButtonImage( ImageActor::New( image ) );
179 }
180
181 void PushButton::SetButtonImage( Actor image )
182 {
183   Toolkit::PushButton handle( GetOwner() );
184   GetPushButtonPainter( mPainter )->SetButtonImage( handle, image );
185 }
186
187 Actor& PushButton::GetButtonImage()
188 {
189   return mButtonImage;
190 }
191
192 Actor PushButton::GetButtonImage() const
193 {
194   return mButtonImage;
195 }
196
197 void PushButton::SetBackgroundImage( Image image )
198 {
199   SetBackgroundImage( ImageActor::New( image ) );
200 }
201
202 void PushButton::SetBackgroundImage( Actor image )
203 {
204   Toolkit::PushButton handle( GetOwner() );
205   GetPushButtonPainter( mPainter )->SetBackgroundImage( handle, image );
206 }
207
208 Actor& PushButton::GetBackgroundImage()
209 {
210   return mBackgroundImage;
211 }
212
213 Actor PushButton::GetBackgroundImage() const
214 {
215   return mBackgroundImage;
216 }
217
218 void PushButton::SetPressedImage( Image image )
219 {
220   SetPressedImage( ImageActor::New( image ) );
221 }
222
223 void PushButton::SetPressedImage( Actor image )
224 {
225   Toolkit::PushButton handle( GetOwner() );
226   GetPushButtonPainter( mPainter )->SetPressedImage( handle, image );
227 }
228
229 Actor& PushButton::GetPressedImage()
230 {
231   return mPressedImage;
232 }
233
234 Actor PushButton::GetPressedImage() const
235 {
236   return mPressedImage;
237 }
238
239 void PushButton::SetDimmedBackgroundImage( Image image )
240 {
241   SetDimmedBackgroundImage( ImageActor::New( image ) );
242 }
243
244 void PushButton::SetDimmedBackgroundImage( Actor image )
245 {
246   Toolkit::PushButton handle( GetOwner() );
247   GetPushButtonPainter( mPainter )->SetDimmedBackgroundImage( handle, image );
248 }
249
250 Actor& PushButton::GetDimmedBackgroundImage()
251 {
252   return mDimmedBackgroundImage;
253 }
254
255 Actor PushButton::GetDimmedBackgroundImage() const
256 {
257   return mDimmedBackgroundImage;
258 }
259
260 void PushButton::SetDimmedImage( Image image )
261 {
262   SetDimmedImage( ImageActor::New( image ) );
263 }
264
265 void PushButton::SetDimmedImage( Actor image )
266 {
267   Toolkit::PushButton handle( GetOwner() );
268   GetPushButtonPainter( mPainter )->SetDimmedImage( handle, image );
269 }
270
271 Actor& PushButton::GetDimmedImage()
272 {
273   return mDimmedImage;
274 }
275
276 Actor PushButton::GetDimmedImage() const
277 {
278   return mDimmedImage;
279 }
280
281 void PushButton::SetLabelText( const std::string& text )
282 {
283   Toolkit::TextView textView ( Toolkit::TextView::New( text ) );
284   textView.SetWidthExceedPolicy( Toolkit::TextView::ShrinkToFit ); // Make sure our text always fits inside the button
285   SetLabelText( textView );
286 }
287
288 void PushButton::SetLabelText( Actor text )
289 {
290   Toolkit::PushButton handle( GetOwner() );
291   GetPushButtonPainter( mPainter )->SetLabelText( handle, text );
292 }
293
294 Actor& PushButton::GetLabel()
295 {
296   return mLabel;
297 }
298
299 Actor PushButton::GetLabelText() const
300 {
301   return mLabel;
302 }
303
304 Actor& PushButton::GetFadeOutBackgroundImage()
305 {
306   return mFadeOutBackgroundImage;
307 }
308
309 Actor& PushButton::GetFadeOutButtonImage()
310 {
311   return mFadeOutButtonImage;
312 }
313
314 Toolkit::PushButton::ToggledSignalV2& PushButton::ToggledSignal()
315 {
316   return mToggledSignalV2;
317 }
318
319 Toolkit::PushButton::PressedSignalV2& PushButton::PressedSignal()
320 {
321   return mPressedSignalV2;
322 }
323
324 Toolkit::PushButton::ReleasedSignalV2& PushButton::ReleasedSignal()
325 {
326   return mReleasedSignalV2;
327 }
328
329 bool PushButton::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
330 {
331   Dali::BaseHandle handle( object );
332
333   bool connected( true );
334   Toolkit::PushButton button = Toolkit::PushButton::DownCast(handle);
335
336   if( Toolkit::PushButton::SIGNAL_TOGGLED == signalName )
337   {
338     button.ToggledSignal().Connect( tracker, functor );
339   }
340   else if( Toolkit::PushButton::SIGNAL_PRESSED == signalName )
341   {
342     button.PressedSignal().Connect( tracker, functor );
343   }
344   else if( Toolkit::PushButton::SIGNAL_RELEASED == signalName )
345   {
346     button.ReleasedSignal().Connect( tracker, functor );
347   }
348   else
349   {
350     // signalName does not match any signal
351     connected = false;
352   }
353
354   return connected;
355 }
356
357 void PushButton::OnButtonInitialize()
358 {
359   // Push button requires the Leave event.
360   Actor root = Self();
361   root.SetLeaveRequired( true );
362 }
363
364 void PushButton::OnButtonDown()
365 {
366   if( !mToggleButton )
367   {
368     Toolkit::PushButton handle( GetOwner() );
369
370     // Notifies the painter the button has been pressed.
371     GetPushButtonPainter( mPainter )->Pressed( handle );
372
373     if( mAutoRepeating )
374     {
375       SetUpTimer( mInitialAutoRepeatingDelay );
376     }
377
378     //Emit signal.
379     mPressedSignalV2.Emit( handle );
380   }
381 }
382
383 void PushButton::OnButtonUp()
384 {
385   if( ButtonDown == mState )
386   {
387     if( mToggleButton )
388     {
389       mToggled = !mToggled;
390
391       Toolkit::PushButton handle( GetOwner() );
392
393       // Notifies the painter the button has been toggled.
394       GetPushButtonPainter( mPainter )->Toggled( handle );
395
396       //Emit signal.
397       mToggledSignalV2.Emit( handle, mToggled );
398     }
399     else
400     {
401       Toolkit::PushButton handle( GetOwner() );
402
403       // Notifies the painter the button has been clicked.
404       GetPushButtonPainter( mPainter )->Released( handle );
405       GetPushButtonPainter( mPainter )->Clicked( handle );
406
407       if( mAutoRepeating )
408       {
409         mAutoRepeatingTimer.Reset();
410       }
411
412       //Emit signal.
413       mReleasedSignalV2.Emit( handle );
414       mClickedSignalV2.Emit( handle );
415     }
416   }
417 }
418
419 void PushButton::OnTouchPointLeave()
420 {
421   if( ButtonDown == mState )
422   {
423     if( !mToggleButton )
424     {
425       Toolkit::PushButton handle( GetOwner() );
426
427       // Notifies the painter the button has been released.
428       GetPushButtonPainter( mPainter )->Released( handle );
429
430       if( mAutoRepeating )
431       {
432         mAutoRepeatingTimer.Reset();
433       }
434
435       //Emit signal.
436       mReleasedSignalV2.Emit( handle );
437     }
438   }
439 }
440
441 void PushButton::OnTouchPointInterrupted()
442 {
443   OnTouchPointLeave();
444 }
445
446 void PushButton::OnAnimationTimeSet( float animationTime )
447 {
448   GetPushButtonPainter( mPainter )->SetAnimationTime( animationTime );
449 }
450
451 float PushButton::OnAnimationTimeRequested() const
452 {
453   return GetPushButtonPainter( mPainter )->GetAnimationTime();
454 }
455
456 PushButton::PushButton()
457 : Button(),
458   mAutoRepeating( false ),
459   mInitialAutoRepeatingDelay( INITIAL_AUTOREPEATING_DELAY ),
460   mNextAutoRepeatingDelay( NEXT_AUTOREPEATING_DELAY ),
461   mToggleButton( false ),
462   mAutoRepeatingTimer(),
463   mToggled( false ),
464   mClickActionPerforming(false)
465 {
466   // Creates specific painter.
467   mPainter = PushButtonDefaultPainterPtr( new PushButtonDefaultPainter() );
468 }
469
470 PushButton::~PushButton()
471 {
472   if( mAutoRepeatingTimer )
473   {
474     mAutoRepeatingTimer.Reset();
475   }
476
477   mPainter = NULL;
478 }
479
480 void PushButton::SetUpTimer( float delay )
481 {
482   mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
483   mAutoRepeatingTimer.TickSignal().Connect( this, &PushButton::AutoRepeatingSlot );
484   mAutoRepeatingTimer.Start();
485 }
486
487 bool PushButton::AutoRepeatingSlot()
488 {
489   bool consumed = false;
490   if( !mDimmed )
491   {
492     // Restart the autorepeat timer.
493     SetUpTimer( mNextAutoRepeatingDelay );
494
495     Toolkit::PushButton handle( GetOwner() );
496
497     // Notifies the painter the button has been pressed.
498     GetPushButtonPainter( mPainter )->Pressed( handle );
499
500     //Emit signal.
501     consumed = mReleasedSignalV2.Emit( handle );
502     consumed |= mClickedSignalV2.Emit( handle );
503     consumed |= mPressedSignalV2.Emit( handle );
504  }
505
506   return consumed;
507 }
508
509 void PushButton::OnActivated()
510 {
511   // When the button is activated, it performs the click action
512   std::vector<Property::Value> attributes;
513   DoClickAction(attributes);
514 }
515
516 void PushButton::DoClickAction(const PropertyValueContainer& attributes)
517 {
518   // Prevents the button signals from doing a recursive loop by sending an action
519   // and re-emitting the signals.
520   if(!mClickActionPerforming)
521   {
522     mClickActionPerforming = true;
523     OnButtonDown();
524     mState = ButtonDown;
525     OnButtonUp();
526     mClickActionPerforming = false;
527   }
528 }
529
530 bool PushButton::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
531 {
532   bool ret = false;
533
534   Dali::BaseHandle handle(object);
535
536   Toolkit::PushButton button = Toolkit::PushButton::DownCast(handle);
537
538   DALI_ASSERT_ALWAYS(button);
539
540   if(Toolkit::PushButton::ACTION_PUSH_BUTTON_CLICK == actionName)
541   {
542     GetImplementation(button).DoClickAction(attributes);
543     ret = true;
544   }
545
546   return ret;
547 }
548
549 } // namespace Internal
550
551 } // namespace Toolkit
552
553 } // namespace Dali