Removed OnButton virtual functions and simplified RadioButton logic
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / buttons / button-impl.cpp
1 /*
2  * Copyright (c) 2016 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 <cstring> // for strcmp
23 #include <dali/devel-api/scripting/enum-helper.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/public-api/events/touch-data.h>
26 #include <dali/public-api/images/resource-image.h>
27 #include <dali/public-api/object/type-registry.h>
28 #include <dali/public-api/object/type-registry-helper.h>
29 #include <dali/public-api/size-negotiation/relayout-container.h>
30 #include <dali/devel-api/scripting/scripting.h>
31
32 // INTERNAL INCLUDES
33 #include <dali-toolkit/public-api/controls/text-controls/text-label.h>
34 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
35 #include <dali-toolkit/public-api/visuals/color-visual-properties.h>
36 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
37 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
38 #include <dali-toolkit/devel-api/align-enums.h>
39 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
40 #include <dali-toolkit/devel-api/visual-factory/devel-visual-properties.h>
41 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
42
43
44 #if defined(DEBUG_ENABLED)
45     Debug::Filter* gLogButtonFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_BUTTON_CONTROL");
46 #endif
47
48 namespace Dali
49 {
50
51 namespace Toolkit
52 {
53
54 namespace Internal
55 {
56
57 namespace
58 {
59
60 BaseHandle Create()
61 {
62   // empty handle as we cannot create button (but type registered for clicked signal)
63   return BaseHandle();
64 }
65
66 // Setup properties, signals and actions using the type-registry.
67 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Button, Toolkit::Control, Create )
68
69 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabled",                           BOOLEAN, DISABLED                              )
70 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "autoRepeating",                      BOOLEAN, AUTO_REPEATING                        )
71 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "initialAutoRepeatingDelay",          FLOAT,   INITIAL_AUTO_REPEATING_DELAY          )
72 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "nextAutoRepeatingDelay",             FLOAT,   NEXT_AUTO_REPEATING_DELAY             )
73 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "togglable",                          BOOLEAN, TOGGLABLE                             )
74 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selected",                           BOOLEAN, SELECTED                              )
75 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "unselectedStateImage",               MAP,     UNSELECTED_STATE_IMAGE                ) // Deprecated property
76 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selectedStateImage",                 MAP,     SELECTED_STATE_IMAGE                  ) // Deprecated property
77 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabledStateImage",                 MAP,     DISABLED_STATE_IMAGE                  ) // Deprecated property
78 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "unselectedColor",                    VECTOR4, UNSELECTED_COLOR                      ) // Deprecated property
79 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selectedColor",                      VECTOR4, SELECTED_COLOR                        ) // Deprecated property
80 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "label",                              MAP,     LABEL                                 )
81 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "labelText",                          STRING,  LABEL_TEXT                            ) // Deprecated property
82 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "unselectedVisual",                   MAP,     UNSELECTED_VISUAL                     )
83 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selectedVisual",                     MAP,     SELECTED_VISUAL                       )
84 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabledSelectedVisual",             MAP,     DISABLED_SELECTED_VISUAL              )
85 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabledUnselectedVisual",           MAP,     DISABLED_UNSELECTED_VISUAL            )
86 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "unselectedBackgroundVisual",         MAP,     UNSELECTED_BACKGROUND_VISUAL          )
87 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "selectedBackgroundVisual",           MAP,     SELECTED_BACKGROUND_VISUAL            )
88 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabledUnselectedBackgroundVisual", MAP,     DISABLED_UNSELECTED_BACKGROUND_VISUAL )
89 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "disabledSelectedBackgroundVisual",   MAP,     DISABLED_SELECTED_BACKGROUND_VISUAL   )
90 DALI_PROPERTY_REGISTRATION( Toolkit, Button, "labelRelativeAlignment",             STRING,  LABEL_RELATIVE_ALIGNMENT              )
91
92 // Signals:
93 DALI_SIGNAL_REGISTRATION(   Toolkit, Button, "pressed",                               SIGNAL_PRESSED               )
94 DALI_SIGNAL_REGISTRATION(   Toolkit, Button, "released",                              SIGNAL_RELEASED              )
95 DALI_SIGNAL_REGISTRATION(   Toolkit, Button, "clicked",                               SIGNAL_CLICKED               )
96 DALI_SIGNAL_REGISTRATION(   Toolkit, Button, "stateChanged",                          SIGNAL_STATE_CHANGED         )
97
98 // Actions:
99 DALI_ACTION_REGISTRATION(   Toolkit, Button, "buttonClick",                           ACTION_BUTTON_CLICK          )
100
101 DALI_TYPE_REGISTRATION_END()
102
103 DALI_ENUM_TO_STRING_TABLE_BEGIN( ALIGNMENT )
104 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::Internal::Button, BEGIN )
105 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::Internal::Button, END )
106 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::Internal::Button, TOP )
107 DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::Internal::Button, BOTTOM )
108 DALI_ENUM_TO_STRING_TABLE_END( ALIGNMENT )
109
110 const Scripting::StringEnum ALIGNMENT_STRING_TABLE[] =
111 {
112   { "BEGIN",  Button::BEGIN   },
113   { "END",    Button::END     },
114   { "TOP",    Button::TOP     },
115   { "BOTTOM", Button::BOTTOM  },
116 };
117
118 const unsigned int ALIGNMENT_STRING_TABLE_COUNT = sizeof( ALIGNMENT_STRING_TABLE ) / sizeof( ALIGNMENT_STRING_TABLE[0] );
119
120 const Property::Index GET_VISUAL_INDEX_FOR_STATE[][Button::STATE_COUNT] =
121 {
122   { Toolkit::Button::Property::UNSELECTED_BACKGROUND_VISUAL, Toolkit::Button::Property::UNSELECTED_VISUAL },
123   { Toolkit::Button::Property::SELECTED_BACKGROUND_VISUAL, Toolkit::Button::Property::SELECTED_VISUAL  },
124   { Toolkit::Button::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL, Toolkit::Button::Property::DISABLED_UNSELECTED_VISUAL },
125   { Toolkit::Button::Property::DISABLED_SELECTED_BACKGROUND_VISUAL, Toolkit::Button::Property::DISABLED_SELECTED_VISUAL }
126 };
127
128 } // unnamed namespace
129
130 Button::Button()
131 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
132   mAutoRepeatingTimer(),
133   mTextLabelAlignment( END ),
134   mAutoRepeating( false ),
135   mTogglableButton( false ),
136   mInitialAutoRepeatingDelay( 0.0f ),
137   mNextAutoRepeatingDelay( 0.0f ),
138   mAnimationTime( 0.0f ),
139   mButtonPressedState( UNPRESSED ),
140   mButtonState( UNSELECTED_STATE ),
141   mPreviousButtonState( mButtonState ),
142   mClickActionPerforming( false )
143 {
144 }
145
146 Button::~Button()
147 {
148 }
149
150 void Button::SetAutoRepeating( bool autoRepeating )
151 {
152   mAutoRepeating = autoRepeating;
153
154   // An autorepeating button can't be a togglable button.
155   if( autoRepeating )
156   {
157     mTogglableButton = false;
158
159     if( IsSelected() )
160     {
161       SetSelected( false );
162     }
163   }
164 }
165
166 bool Button::IsAutoRepeating() const
167 {
168   return mAutoRepeating;
169 }
170
171 void Button::SetInitialAutoRepeatingDelay( float initialAutoRepeatingDelay )
172 {
173   DALI_ASSERT_DEBUG( initialAutoRepeatingDelay > 0.f );
174   mInitialAutoRepeatingDelay = initialAutoRepeatingDelay;
175 }
176
177 float Button::GetInitialAutoRepeatingDelay() const
178 {
179   return mInitialAutoRepeatingDelay;
180 }
181
182 void Button::SetNextAutoRepeatingDelay( float nextAutoRepeatingDelay )
183 {
184   DALI_ASSERT_DEBUG( nextAutoRepeatingDelay > 0.f );
185   mNextAutoRepeatingDelay = nextAutoRepeatingDelay;
186 }
187
188 float Button::GetNextAutoRepeatingDelay() const
189 {
190   return mNextAutoRepeatingDelay;
191 }
192
193 void Button::SetTogglableButton( bool togglable )
194 {
195   mTogglableButton = togglable;
196
197   // A toggle button can't be an autorepeating button.
198   if( togglable )
199   {
200     mAutoRepeating = false;
201   }
202 }
203
204 bool Button::IsTogglableButton() const
205 {
206   return mTogglableButton;
207 }
208
209 void Button::SetSelected( bool selected )
210 {
211   if( mTogglableButton )
212   {
213     DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetSelected (%s)\n", (selected?"true":"false") );
214
215     if ( selected && ( mButtonState != SELECTED_STATE ) )
216     {
217       ChangeState( SELECTED_STATE );
218     }
219     else if ( !selected && ( mButtonState != UNSELECTED_STATE ) )
220     {
221       ChangeState( UNSELECTED_STATE );
222     }
223   }
224 }
225
226 void Button::SetDisabled( bool disabled )
227 {
228   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetDisabled(%s) state(%d)\n", (disabled)?"disabled":"active", mButtonState );
229
230   if ( disabled )
231   {
232     if ( mButtonState == SELECTED_STATE )
233     {
234       ChangeState( DISABLED_SELECTED_STATE );
235     }
236     else if ( mButtonState == UNSELECTED_STATE )
237     {
238       ChangeState( DISABLED_UNSELECTED_STATE );
239     }
240   }
241   else
242   {
243     if ( mButtonState == DISABLED_SELECTED_STATE )
244     {
245       ChangeState( SELECTED_STATE );
246     }
247     else if ( mButtonState == DISABLED_UNSELECTED_STATE )
248     {
249       ChangeState( UNSELECTED_STATE );
250     }
251   }
252 }
253
254 bool Button::IsDisabled() const
255 {
256   return ( mButtonState == DISABLED_SELECTED_STATE || mButtonState == DISABLED_UNSELECTED_STATE ) ;
257 }
258
259 bool Button::ValidateState( State requestedState )
260 {
261   /*  Below tables shows allowed state transitions
262    *  Match rows in first column to following columns, if true then transition allowed.
263    *  eg UNSELECTED_STATE to DISABLED_UNSELECTED_STATE is true so state transition allowed.
264    *
265                                                              to| UNSELECTED_STATE | SELECTED_STATE | DISABLED_UNSELECTED_STATE | DISABLED_SELECTED_STATE |*/
266                                  /* from*/
267   bool transitionTable[4][4] = { /* UNSELECTED_STATE*/         {      false,            true,               true,                   false         },
268                                  /* SELECTED_STATE*/           {      true,             false,              false,                  true          },
269                                  /* DISABLED_UNSELECTED_STATE*/{      true,             true,               false,                  false         },
270                                  /* DISABLED_SELECTED_STATE*/  {      false,            true,               false,                  false         }
271                                };
272
273   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::ValidateState ReuestedState:%d, CurrentState:%d, result:%s\n",
274                  requestedState, mButtonState, (transitionTable[mButtonState][requestedState])?"change-accepted":"change-denied");
275
276   return transitionTable[mButtonState][requestedState];
277 }
278
279 void Button::PerformFunctionOnVisualsInState( void(Button::*functionPtr)( Property::Index visualIndex), State state )
280 {
281   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::PerformFunctionOnVisualsInState BACKROUND visual(%d) for state (%d)\n",
282                  GET_VISUAL_INDEX_FOR_STATE[state][BACKGROUND], state );
283   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::PerformFunctionOnVisualsInState FOREGROUND visuals(%d)  for state (%d)\n",
284                  GET_VISUAL_INDEX_FOR_STATE[state][FOREGROUND], state );
285
286   (this->*functionPtr)( GET_VISUAL_INDEX_FOR_STATE[state][BACKGROUND] );
287   (this->*functionPtr)( GET_VISUAL_INDEX_FOR_STATE[state][FOREGROUND] );
288
289   RelayoutRequest();
290 }
291
292 void Button::ChangeState( State requestedState )
293 {
294   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::ChangeState ReuestedState(%d)\n", requestedState );
295
296   // Validate State before changing
297   if ( !ValidateState( requestedState ))
298   {
299     DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::ChangeState ReuestedState(%d) not validated\n", requestedState );
300     return;
301   }
302
303   // If not on stage the button could have still been set to selected so update state/
304   mPreviousButtonState = mButtonState; // Store previous state for visual removal (used when animations ended)
305   mButtonState = requestedState; // Update current state
306
307   if ( Self().OnStage() )
308   {
309     OnStateChange( mButtonState ); // Notify derived buttons
310     PerformFunctionOnVisualsInState( &Button::SelectRequiredVisual, mButtonState );
311     // If animation supported then visual removal should be performed after any transition animation has completed.
312     PerformFunctionOnVisualsInState( &Button::OnButtonVisualRemoval, mPreviousButtonState ); // Derived button can override OnButtonVisualRemoval
313   }
314
315   Toolkit::Button handle( GetOwner() );
316   // Emit signal.
317   mStateChangedSignal.Emit( handle );
318 }
319
320 bool Button::IsSelected() const
321 {
322   bool selected = ( mButtonState == SELECTED_STATE ) || ( mButtonState == DISABLED_SELECTED_STATE );
323   return mTogglableButton && selected;
324 }
325
326 void Button::SetLabelText( const std::string& label )
327 {
328   Property::Map labelProperty;
329   labelProperty.Insert( "text", label );
330   SetupLabel( labelProperty );
331 }
332
333 std::string Button::GetLabelText() const
334 {
335   Toolkit::TextLabel label = Dali::Toolkit::TextLabel::DownCast( mLabel );
336   if( label )
337   {
338     return label.GetProperty<std::string>( Dali::Toolkit::TextLabel::Property::TEXT );
339   }
340   return std::string();
341 }
342
343 void Button::SetupLabel( const Property::Map& properties )
344 {
345   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "SetupLabel\n");
346
347   // If we don't have a label yet, create one.
348   if( !mLabel )
349   {
350     // If we don't have a label, create one and set it up.
351     // Note: The label text is set from the passed in property map after creation.
352     mLabel = Toolkit::TextLabel::New();
353     mLabel.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
354     mLabel.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
355     mLabel.SetParentOrigin( ParentOrigin::TOP_LEFT );
356     mLabel.SetAnchorPoint( AnchorPoint::TOP_LEFT );
357
358     // todo DEBUG
359     mLabel.SetProperty( Toolkit::Control::Property::BACKGROUND, Dali::Property::Map()
360                         .Add( Toolkit::Visual::Property::TYPE, Dali::Toolkit::Visual::COLOR )
361                         .Add( Toolkit::ColorVisual::Property::MIX_COLOR, Color::RED )
362                       );
363
364     ResizePolicy::Type policy = Self().GetResizePolicy(  Dimension::ALL_DIMENSIONS );
365     if ( policy == ResizePolicy::USE_NATURAL_SIZE || policy == ResizePolicy::FIT_TO_CHILDREN  )
366     {
367       mLabel.SetResizePolicy(ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
368     }
369     else
370     {
371       // todo Can't set Text Label to USE_ASSIGNED_SIZE as causes a relayout in it whilst doing a relayout = error
372      //mLabel.SetResizePolicy(ResizePolicy::USE_ASSIGNED_SIZE, Dimension::ALL_DIMENSIONS );
373     }
374     Self().Add( mLabel );
375   }
376
377   // Set any properties specified for the label by iterating through all property key-value pairs.
378   for( unsigned int i = 0, mapCount = properties.Count(); i < mapCount; ++i )
379   {
380     const StringValuePair& propertyPair( properties.GetPair( i ) );
381
382     // Convert the property string to a property index.
383     Property::Index setPropertyIndex = mLabel.GetPropertyIndex( propertyPair.first );
384     if( setPropertyIndex != Property::INVALID_INDEX )
385     {
386       // If the conversion worked, we have a valid property index,
387       // Set the property to the new value.
388       mLabel.SetProperty( setPropertyIndex, propertyPair.second );
389     }
390   }
391
392   RelayoutRequest();
393 }
394
395 void Button::SetLabelAlignment( Button::Align labelAlignment)
396 {
397   mTextLabelAlignment = labelAlignment;
398   RelayoutRequest();
399 }
400
401 Button::Align Button::GetLabelAlignment()
402 {
403   return mTextLabelAlignment;
404 }
405
406 void Button::CreateVisualsForComponent( Property::Index index, const Property::Value& value, const float visualDepth )
407 {
408   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "CreateVisualsForComponent index(%d)\n", index );
409   Toolkit::VisualFactory visualFactory = Toolkit::VisualFactory::Get();
410   Toolkit::Visual::Base buttonVisual;
411
412   std::string imageUrl;
413   if( value.Get( imageUrl ) )
414   {
415     DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "CreateVisualsForComponent Using image URL(%d)\n", index );
416     if ( !imageUrl.empty() )
417     {
418       buttonVisual = visualFactory.CreateVisual(  imageUrl, ImageDimensions()  );
419     }
420   }
421   else
422   {
423     // if its not a string then get a Property::Map from the property if possible.
424     Property::Map *map = value.GetMap();
425     if( map && !map->Empty()  ) // Empty map results in current visual removal.
426     {
427       DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "CreateVisualsForComponent Using Map(%d)\n", index );
428       buttonVisual = visualFactory.CreateVisual( *map );
429     }
430   }
431
432   if ( buttonVisual )
433   {
434     DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "RegisterVisual index(%d)\n", index );
435     buttonVisual.SetDepthIndex( visualDepth );
436     // Background Visuals take full size of control
437     RegisterVisual( index, buttonVisual, false );
438   }
439   else
440   {
441     UnregisterVisual( index );
442     DALI_LOG_INFO( gLogButtonFilter, Debug::General, "Button visual not created or empty map provided (clearing visual).(%d)\n", index);
443   }
444 }
445
446 bool Button::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
447 {
448   bool ret = false;
449
450   Dali::BaseHandle handle( object );
451
452   Toolkit::Button button = Toolkit::Button::DownCast( handle );
453
454   DALI_ASSERT_DEBUG( button );
455
456   if( 0 == strcmp( actionName.c_str(), ACTION_BUTTON_CLICK ) )
457   {
458     ret = GetImplementation( button ).DoClickAction( attributes );
459   }
460
461   return ret;
462 }
463
464 bool Button::DoClickAction( const Property::Map& attributes )
465 {
466   // Prevents the button signals from doing a recursive loop by sending an action
467   // and re-emitting the signals.
468   if( !mClickActionPerforming )
469   {
470     mClickActionPerforming = true;
471     ButtonDown();
472     if ( !mTogglableButton )
473     {
474       mButtonPressedState = DEPRESSED;
475     }
476     ButtonUp();
477     mClickActionPerforming = false;
478
479     return true;
480   }
481
482   return false;
483 }
484
485 void Button::ButtonDown()
486 {
487   if( mTogglableButton )
488   {
489     if ( mButtonState != SELECTED_STATE )
490     {
491       SetSelected( true );
492       mButtonPressedState = TOGGLE_DEPRESSED;
493     }
494     else
495     {
496       mButtonPressedState = DEPRESSED;
497     }
498   }
499   else
500   {
501     Pressed();
502     mButtonPressedState = DEPRESSED;
503     if( mAutoRepeating )
504     {
505        SetUpTimer( mInitialAutoRepeatingDelay );
506     }
507   }
508
509   // The pressed signal should be emitted regardless of toggle mode.
510   Toolkit::Button handle( GetOwner() );
511   mPressedSignal.Emit( handle );
512 }
513
514 void Button::ButtonUp()
515 {
516   if( DEPRESSED == mButtonPressedState )
517   {
518     bool validButtonAction = false;
519
520     if( mTogglableButton ) // Button up will change state
521     {
522       OnToggleReleased(); // Derived toggle buttons can override this to provide custom behaviour
523     }
524     else
525     {
526       Released(); // Button up will result in unselected state
527       if( mAutoRepeating )
528       {
529         mAutoRepeatingTimer.Reset();
530       }
531       validButtonAction = true;
532     }
533
534     if ( validButtonAction )
535     {
536       // The clicked and released signals should be emitted regardless of toggle mode.
537       Toolkit::Button handle( GetOwner() );
538       mReleasedSignal.Emit( handle );
539       mClickedSignal.Emit( handle );
540     }
541   }
542 }
543
544 bool Button::OnToggleReleased()
545 {
546   SetSelected( !IsSelected() );
547   mButtonPressedState = UNPRESSED;
548   return true;
549 }
550
551
552 void Button::OnTouchPointLeave()
553 {
554   if( DEPRESSED == mButtonPressedState )
555   {
556     if( !mTogglableButton )
557     {
558       Released();
559
560       if( mAutoRepeating )
561       {
562         mAutoRepeatingTimer.Reset();
563       }
564     }
565
566     mButtonPressedState = UNPRESSED;
567
568     // The released signal should be emitted regardless of toggle mode.
569     Toolkit::Button handle( GetOwner() );
570     mReleasedSignal.Emit( handle );
571   }
572 }
573
574 void Button::OnTouchPointInterrupted()
575 {
576   OnTouchPointLeave();
577 }
578
579 Toolkit::Button::ButtonSignalType& Button::PressedSignal()
580 {
581   return mPressedSignal;
582 }
583
584 Toolkit::Button::ButtonSignalType& Button::ReleasedSignal()
585 {
586   return mReleasedSignal;
587 }
588
589 Toolkit::Button::ButtonSignalType& Button::ClickedSignal()
590 {
591   return mClickedSignal;
592 }
593
594 Toolkit::Button::ButtonSignalType& Button::StateChangedSignal()
595 {
596   return mStateChangedSignal;
597 }
598
599 bool Button::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
600 {
601   Dali::BaseHandle handle( object );
602
603   bool connected( true );
604   Toolkit::Button button = Toolkit::Button::DownCast( handle );
605
606   if( 0 == strcmp( signalName.c_str(), SIGNAL_PRESSED ) )
607   {
608     button.PressedSignal().Connect( tracker, functor );
609   }
610   else if( 0 == strcmp( signalName.c_str(), SIGNAL_RELEASED ) )
611   {
612     button.ReleasedSignal().Connect( tracker, functor );
613   }
614   else if( 0 == strcmp( signalName.c_str(), SIGNAL_CLICKED ) )
615   {
616     button.ClickedSignal().Connect( tracker, functor );
617   }
618   else if( 0 == strcmp( signalName.c_str(), SIGNAL_STATE_CHANGED ) )
619   {
620     button.StateChangedSignal().Connect( tracker, functor );
621   }
622   else
623   {
624     // signalName does not match any signal
625     connected = false;
626   }
627
628   return connected;
629 }
630
631 void Button::OnInitialize()
632 {
633   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::OnInitialize\n" );
634
635   Actor self = Self();
636
637   mTapDetector = TapGestureDetector::New();
638   mTapDetector.Attach( self );
639   mTapDetector.DetectedSignal().Connect(this, &Button::OnTap);
640
641   self.SetKeyboardFocusable( true );
642
643   self.TouchSignal().Connect( this, &Button::OnTouch );
644 }
645
646 bool Button::OnAccessibilityActivated()
647 {
648   return OnKeyboardEnter();
649 }
650
651 bool Button::OnTouch( Actor actor, const TouchData& touch )
652 {
653
654   // Only events are processed when the button is not disabled and the touch event has only
655   // one touch point.
656
657   if( !IsDisabled() && ( 1 == touch.GetPointCount() ) )
658   {
659     switch( touch.GetState( 0 ) )
660     {
661       case PointState::DOWN:
662       {
663         ButtonDown();
664         break;
665       }
666       case PointState::UP:
667       {
668         ButtonUp();
669         break;
670       }
671       case PointState::INTERRUPTED:
672       {
673         OnTouchPointInterrupted();
674         break;
675       }
676       case PointState::LEAVE:
677       {
678         OnTouchPointLeave();
679         break;
680       }
681       case PointState::MOTION:
682       case PointState::STATIONARY: // FALLTHROUGH
683       {
684         // Nothing to do
685         break;
686       }
687     }
688   }
689   else if( 1 < touch.GetPointCount() )
690   {
691     OnTouchPointLeave(); // Notification for derived classes.
692
693     // Sets the button state to the default
694     mButtonPressedState = UNPRESSED;
695   }
696
697   return false;
698 }
699
700 bool Button::OnKeyboardEnter()
701 {
702   // When the enter key is pressed, or button is activated, the click action is performed.
703   Property::Map attributes;
704   bool ret = DoClickAction( attributes );
705
706   return ret;
707 }
708
709 void Button::OnStageDisconnection()
710 {
711   if( DEPRESSED == mButtonPressedState )
712   {
713     if( !mTogglableButton )
714     {
715       Released();
716
717       if( mAutoRepeating )
718       {
719         mAutoRepeatingTimer.Reset();
720       }
721     }
722   }
723
724   mButtonPressedState = UNPRESSED;
725
726   Control::OnStageDisconnection(); // Visuals will be set off stage
727 }
728
729 void Button::OnStageConnection( int depth )
730 {
731   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::OnStageConnection ptr(%p) \n", this );
732   PerformFunctionOnVisualsInState( &Button::SelectRequiredVisual, mButtonState );
733   Control::OnStageConnection( depth ); // Enabled visuals will be put on stage
734
735 }
736
737 Vector3 Button::GetNaturalSize()
738 {
739   Vector3 size = Vector3::ZERO;
740
741   bool horizontalAlignment = mTextLabelAlignment == BEGIN || mTextLabelAlignment == END; // label and visual side by side
742
743   // Get natural size of foreground ( largest of the possible visuals )
744   Size largestForegroundVisual;
745   Size labelSize;
746
747   for ( int state = Button::UNSELECTED_STATE; state < Button::STATE_COUNT; state++)
748   {
749     Toolkit::Visual::Base visual = GetVisual( GET_VISUAL_INDEX_FOR_STATE[state][FOREGROUND] );
750     Size visualSize;
751     if ( visual )
752     {
753       visual.GetNaturalSize( visualSize );
754       largestForegroundVisual.width = std::max(largestForegroundVisual.width, visualSize.width );
755       largestForegroundVisual.height = std::max(largestForegroundVisual.height, visualSize.height );
756     }
757   }
758
759   // Get horizontal padding total
760   if ( largestForegroundVisual.width > 0 )  // if visual exists
761   {
762     size.width += largestForegroundVisual.width + mForegroundPadding.left + mForegroundPadding.right;
763   }
764   // Get vertical padding total
765   if ( largestForegroundVisual.height > 0 )
766   {
767     size.height += largestForegroundVisual.height + mForegroundPadding.top + mForegroundPadding.bottom;
768   }
769
770   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetNaturalSize visual Size(%f,%f)\n",
771                  largestForegroundVisual.width, largestForegroundVisual.height );
772
773   // Get natural size of label
774   if ( mLabel )
775   {
776     labelSize = Vector2( mLabel.GetNaturalSize());
777
778     DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetNaturalSize labelSize(%f,%f) padding(%f,%f)\n",
779                    labelSize.width, labelSize.height, mLabelPadding.left + mLabelPadding.right, mLabelPadding.top + mLabelPadding.bottom);
780
781     labelSize.width += mLabelPadding.left + mLabelPadding.right;
782     labelSize.height += mLabelPadding.top + mLabelPadding.bottom;
783
784     // Add label size to height or width depending on alignment position
785     if ( horizontalAlignment )
786     {
787       size.width += labelSize.width;
788       size.height = std::max(size.height, labelSize.height );
789     }
790     else
791     {
792       size.height += labelSize.height;
793       size.width = std::max(size.width, labelSize.width );
794     }
795   }
796
797   if( size.width < 1 && size.height < 1 )
798   {
799     // if no image or label then use Control's natural size
800     DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetNaturalSize Using control natural size\n");
801     size = Control::GetNaturalSize();
802   }
803
804   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "Button GetNaturalSize (%f,%f)\n", size.width, size.height );
805
806   return size;
807 }
808
809 void Button::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
810 {
811   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnSetResizePolicy\n");
812
813   if ( policy != ResizePolicy::USE_NATURAL_SIZE || policy != ResizePolicy::FIT_TO_CHILDREN  )
814   {
815     if ( mLabel )
816     {
817       // todo Can't set Text Label to USE_ASSIGNED_SIZE as causes a relayout in it whilst doing a relayout = error
818       //mLabel.SetResizePolicy(ResizePolicy::USE_ASSIGNED_SIZE, Dimension::ALL_DIMENSIONS );
819     }
820   }
821
822   RelayoutRequest();
823 }
824
825 void Button::OnRelayout( const Vector2& size, RelayoutContainer& container )
826 {
827   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout targetSize(%f,%f) ptr(%p) state[%d]\n", size.width, size.height, this, mButtonState );
828
829   Toolkit::Visual::Base currentVisual = GetVisual( GET_VISUAL_INDEX_FOR_STATE[mButtonState][FOREGROUND] );
830
831   Toolkit::Visual::Base currentBackGroundVisual = GetVisual( GET_VISUAL_INDEX_FOR_STATE[mButtonState][BACKGROUND] );
832
833   // Sizes and padding set to zero, if not present then values will no effect calculations.
834   Vector2 visualPosition = Vector2::ZERO;
835   Vector2 labelPosition = Vector2::ZERO;
836   Size visualSize = Size::ZERO;
837   Padding foregroundVisualPadding = Padding(0.0f, 0.0f, 0.0f, 0.0f );
838   Padding labelVisualPadding = Padding(0.0f, 0.0f, 0.0f, 0.0f );
839
840   if ( mLabel )
841   {
842     DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Label padding setting padding:%f,%f,%f,%f\n", mLabelPadding.y, mLabelPadding.x, mLabelPadding.width,mLabelPadding.height );
843     labelVisualPadding = mLabelPadding;
844   }
845
846   if ( currentVisual )
847   {
848     DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Foreground Visual setting padding:%f,%f,%f,%f\n", mForegroundPadding.y, mForegroundPadding.x, mForegroundPadding.width,mForegroundPadding.height );
849     currentVisual.GetNaturalSize( visualSize );
850     foregroundVisualPadding = mForegroundPadding;
851   }
852
853   Toolkit::Align::Type visualAnchorPoint = Toolkit::Align::TOP_BEGIN;
854
855   Vector2 visualAndPaddingSize = Vector2( ( foregroundVisualPadding.x + visualSize.width + foregroundVisualPadding.y ),
856                                           ( foregroundVisualPadding.width + visualSize.height + foregroundVisualPadding.height ));
857
858   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout visualAndPaddingSize(%f,%f)\n", visualAndPaddingSize.width, visualAndPaddingSize.height);
859
860   switch ( mTextLabelAlignment )
861   {
862     case BEGIN :
863     {
864       visualAnchorPoint = Toolkit::Align::TOP_END;
865       visualPosition.x = foregroundVisualPadding.right;
866       visualPosition.y = foregroundVisualPadding.top;
867
868       labelPosition.x = labelVisualPadding.x;
869       labelPosition.y = labelVisualPadding.top;
870       break;
871     }
872     case END :
873     {
874       visualAnchorPoint = Toolkit::Align::TOP_BEGIN;
875       visualPosition.x = foregroundVisualPadding.left;
876       visualPosition.y = foregroundVisualPadding.top;
877
878       labelPosition.x = visualAndPaddingSize.width + labelVisualPadding.x;
879       labelPosition.y = labelVisualPadding.top;
880       break;
881     }
882     case TOP :
883     {
884       visualAnchorPoint = Toolkit::Align::BOTTOM_END;
885       visualPosition.x = foregroundVisualPadding.left;
886       visualPosition.y = foregroundVisualPadding.bottom;
887
888       labelPosition.x = labelVisualPadding.left;
889       labelPosition.y = labelVisualPadding.top;
890       break;
891     }
892     case BOTTOM :
893     {
894       visualAnchorPoint = Toolkit::Align::TOP_END;
895       visualPosition.x = foregroundVisualPadding.left;
896       visualPosition.y = foregroundVisualPadding.top;
897
898       labelPosition.x = labelVisualPadding.left;
899       labelPosition.y = visualAndPaddingSize.height + labelVisualPadding.top;
900       break;
901     }
902   }
903
904   if ( currentBackGroundVisual )
905   {
906     DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Setting visual bakcground size to(%f,%f)\n", size.width, size.height);
907
908     Property::Map visualTransform;
909
910     visualTransform.Add( Toolkit::DevelVisual::Transform::Property::SIZE, size )
911                    .Add( Toolkit::DevelVisual::Transform::Property::OFFSET_SIZE_MODE, Vector4( 0.0f, 0.0f, 1.0f, 1.0f) );  // Use relative size
912
913     currentBackGroundVisual.SetTransformAndSize( visualTransform, size );
914   }
915
916   if ( currentVisual )
917   {
918       DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Setting visual size to(%f,%f)\n", visualSize.width, visualSize.height);
919
920       currentVisual.SetProperty( Toolkit::Visual::DevelProperty::TRANSFORM,
921                                  Dali::Property::Map()
922                                  .Add( Toolkit::Visual::DevelProperty::Transform::Property::SIZE, visualSize )
923                                  .Add( Toolkit::Visual::DevelProperty::Transform::Property::OFFSET, visualPosition )
924                                  .Add( Toolkit::Visual::DevelProperty::Transform::Property::OFFSET_SIZE_MODE, Vector4(1.0f, 1.0f, 1.0f,1.0f) )
925                                  .Add( Toolkit::Visual::DevelProperty::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN )
926                                  .Add( Toolkit::Visual::DevelProperty::Transform::Property::ANCHOR_POINT, visualAnchorPoint )
927                                 );
928   }
929
930   if ( mLabel )
931   {
932     // When Text visual size can be set, determine the size here.
933     // Text Visual should take all space available after foreground visual size and all padding is considered.
934     // Remaining Space priority, Foreground padding, foreground visual, Text padding then Text visual.
935
936     Size remainingSpaceForText = Size::ZERO;
937     remainingSpaceForText.width = size.width - visualAndPaddingSize.width - labelVisualPadding.x - labelVisualPadding.y;
938     remainingSpaceForText.height = size.height - visualAndPaddingSize.height - labelVisualPadding.width - labelVisualPadding.height;
939
940     if ( !currentVisual )
941     {
942       DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Only Text\n");
943
944       // Center Text if no foreground visual
945       Size labelNaturalSize = Vector2( mLabel.GetNaturalSize() );
946
947       // A Text visual will take up all the remainingSpaceForText, for now TextLabel natural size needed for positioning.
948       labelPosition.x = labelVisualPadding.left + remainingSpaceForText.width*0.5 - labelNaturalSize.width *0.5;
949       labelPosition.y = labelVisualPadding.height + remainingSpaceForText.height*0.5 - labelNaturalSize.height *0.5;
950     }
951
952     DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout text Size(%f,%f) text Position(%f,%f) \n", remainingSpaceForText.width, remainingSpaceForText.height, labelPosition.x, labelPosition.y);
953
954     mLabel.SetPosition( labelPosition.x, labelPosition.y );
955     container.Add( mLabel, remainingSpaceForText ); // Currently a TextLabel is used and size can not be set here.
956   }
957
958   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout << \n");
959 }
960
961 void Button::OnTap(Actor actor, const TapGesture& tap)
962 {
963   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnTap\n" );
964 }
965
966 void Button::SetUpTimer( float delay )
967 {
968   mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
969   mAutoRepeatingTimer.TickSignal().Connect( this, &Button::AutoRepeatingSlot );
970   mAutoRepeatingTimer.Start();
971 }
972
973 bool Button::AutoRepeatingSlot()
974 {
975   bool consumed = false;
976   if( !IsDisabled() )
977   {
978     // Restart the autorepeat timer.
979     SetUpTimer( mNextAutoRepeatingDelay );
980
981     Pressed();
982
983     Toolkit::Button handle( GetOwner() );
984
985     //Emit signal.
986     consumed = mReleasedSignal.Emit( handle );
987     consumed = mClickedSignal.Emit( handle );
988     consumed |= mPressedSignal.Emit( handle );
989  }
990
991   return consumed;
992 }
993
994 void Button::Pressed()
995 {
996   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::Pressed\n" );
997
998   if( mButtonState == UNSELECTED_STATE )
999   {
1000     ChangeState( SELECTED_STATE );
1001     OnPressed();  // Notifies the derived class the button has been pressed.
1002   }
1003 }
1004
1005 void Button::Released()
1006 {
1007   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::Released\n" );
1008
1009   if( mButtonState == SELECTED_STATE && !mTogglableButton )
1010   {
1011     ChangeState( UNSELECTED_STATE );
1012     OnReleased(); //    // Notifies the derived class the button has been released.
1013   }
1014   mButtonPressedState = UNPRESSED;
1015 }
1016
1017 void Button::SelectRequiredVisual( Property::Index visualIndex )
1018 {
1019   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SelectRequiredVisual index(%d) state(%d)\n", visualIndex, mButtonState );
1020
1021   EnableVisual( visualIndex, true );
1022 }
1023
1024 void Button::RemoveVisual( Property::Index visualIndex )
1025 {
1026   // Use OnButtonVisualRemoval if want button developer to have the option to override removal.
1027   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::RemoveVisual index(%d) state(%d)\n", visualIndex, mButtonState );
1028
1029   Toolkit::Visual::Base visual = GetVisual( visualIndex );
1030
1031   if( visual )
1032   {
1033     EnableVisual( visualIndex, false );
1034   }
1035 }
1036
1037 void Button::OnButtonVisualRemoval( Property::Index visualIndex )
1038 {
1039   // Derived Buttons can over ride this to prevent default removal.
1040   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::OnButtonVisualRemoval index(%d)\n", visualIndex );
1041   RemoveVisual( visualIndex );
1042 }
1043
1044 void Button::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
1045 {
1046   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1047
1048   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetProperty index[%d]\n", index );
1049
1050   if ( button )
1051   {
1052     switch ( index )
1053     {
1054       case Toolkit::Button::Property::DISABLED:
1055       {
1056         GetImplementation( button ).SetDisabled( value.Get< bool >() );
1057         break;
1058       }
1059
1060       case Toolkit::Button::Property::AUTO_REPEATING:
1061       {
1062         GetImplementation( button ).SetAutoRepeating( value.Get< bool >() );
1063         break;
1064       }
1065
1066       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1067       {
1068         GetImplementation( button ).SetInitialAutoRepeatingDelay( value.Get< float >() );
1069         break;
1070       }
1071
1072       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1073       {
1074         GetImplementation( button ).SetNextAutoRepeatingDelay( value.Get< float >() );
1075         break;
1076       }
1077
1078       case Toolkit::Button::Property::TOGGLABLE:
1079       {
1080         GetImplementation( button ).SetTogglableButton( value.Get< bool >() );
1081         break;
1082       }
1083
1084       case Toolkit::Button::Property::SELECTED:
1085       {
1086         GetImplementation( button ).SetSelected( value.Get< bool >() );
1087         break;
1088       }
1089
1090       case Toolkit::Button::Property::UNSELECTED_STATE_IMAGE: // Legacy Tizen 3.0
1091       {
1092         GetImplementation( button ).CreateVisualsForComponent( Toolkit::Button::Property::UNSELECTED_VISUAL, value, DepthIndex::CONTENT );
1093         break;
1094       }
1095       case Toolkit::Button::Property::DISABLED_STATE_IMAGE:  // Legacy Tizen 3.0
1096       {
1097         GetImplementation( button ).CreateVisualsForComponent( Toolkit::Button::Property::DISABLED_UNSELECTED_VISUAL, value, DepthIndex::CONTENT );
1098         break;
1099       }
1100       case Toolkit::Button::Property::SELECTED_STATE_IMAGE:  // Legacy Tizen 3.0
1101       {
1102         GetImplementation( button ).CreateVisualsForComponent( Toolkit::Button::Property::SELECTED_VISUAL, value, DepthIndex::CONTENT );
1103         break;
1104       }
1105       case Toolkit::Button::Property::UNSELECTED_VISUAL:
1106       case Toolkit::Button::Property::SELECTED_VISUAL:
1107       case Toolkit::Button::Property::DISABLED_SELECTED_VISUAL:
1108       case Toolkit::Button::Property::DISABLED_UNSELECTED_VISUAL:
1109       {
1110         GetImplementation( button ).CreateVisualsForComponent( index, value, DepthIndex::CONTENT );
1111         break;
1112       }
1113
1114       case Toolkit::Button::Property::UNSELECTED_BACKGROUND_VISUAL:
1115       case Toolkit::Button::Property::SELECTED_BACKGROUND_VISUAL:
1116       case Toolkit::Button::Property::DISABLED_SELECTED_BACKGROUND_VISUAL:
1117       case Toolkit::Button::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL:
1118       {
1119         GetImplementation( button ).CreateVisualsForComponent( index , value, DepthIndex::BACKGROUND);
1120         break;
1121       }
1122
1123       case Toolkit::Button::Property::UNSELECTED_COLOR:
1124       {
1125         DALI_LOG_WARNING("[%s] Using deprecated Property Button::Property::UNSELECTED_COLOR instead use Button::Property::UNSELECTED_BACKGROUND_VISUAL\n", __FUNCTION__);
1126         GetImplementation( button ).SetColor( value.Get< Vector4 >(), Toolkit::Button::Property::UNSELECTED_BACKGROUND_VISUAL );
1127         break;
1128       }
1129
1130       case Toolkit::Button::Property::SELECTED_COLOR:
1131       {
1132         DALI_LOG_WARNING("[%s] Using deprecated Property Button::Property::SELECTED_COLOR instead use Button::Property::SELECTED_BACKGROUND_VISUAL\n", __FUNCTION__);
1133         GetImplementation( button ).SetColor( value.Get< Vector4 >(), Toolkit::Button::Property::SELECTED_BACKGROUND_VISUAL );
1134         break;
1135       }
1136
1137       case Toolkit::Button::Property::LABEL_TEXT:
1138       {
1139         DALI_LOG_WARNING("[%s] Using deprecated Property Button::Property::LABEL_TEXT instead use Button::Property::LABEL\n", __FUNCTION__);
1140         Property::Map labelTextProperty;
1141         labelTextProperty.Insert( "text", value.Get< std::string >() );
1142         GetImplementation( button ).SetupLabel( labelTextProperty );
1143         break;
1144       }
1145
1146       case Toolkit::Button::Property::LABEL:
1147       {
1148         // Get a Property::Map from the property if possible.
1149         Property::Map setPropertyMap;
1150         if( value.Get( setPropertyMap ) )
1151         {
1152           GetImplementation( button ).SetupLabel( setPropertyMap );
1153         }
1154         break;
1155       }
1156
1157       case Toolkit::Button::Property::LABEL_RELATIVE_ALIGNMENT:
1158       {
1159         Button::Align labelAlignment(END);
1160         Scripting::GetEnumeration< Button::Align> ( value.Get< std::string >().c_str(),
1161                                                     ALIGNMENT_TABLE, ALIGNMENT_TABLE_COUNT,
1162                                                     labelAlignment );
1163
1164         GetImplementation( button ).SetLabelAlignment( labelAlignment );
1165         break;
1166       }
1167     }
1168   }
1169 }
1170
1171 Property::Value Button::GetProperty( BaseObject* object, Property::Index propertyIndex )
1172 {
1173   Property::Value value;
1174
1175   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1176
1177   if ( button )
1178   {
1179     switch ( propertyIndex )
1180     {
1181       case Toolkit::Button::Property::DISABLED:
1182       {
1183         value = GetImplementation( button ).IsDisabled();
1184         break;
1185       }
1186
1187       case Toolkit::Button::Property::AUTO_REPEATING:
1188       {
1189         value = GetImplementation( button ).mAutoRepeating;
1190         break;
1191       }
1192
1193       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1194       {
1195         value = GetImplementation( button ).mInitialAutoRepeatingDelay;
1196         break;
1197       }
1198
1199       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1200       {
1201         value = GetImplementation( button ).mNextAutoRepeatingDelay;
1202         break;
1203       }
1204
1205       case Toolkit::Button::Property::TOGGLABLE:
1206       {
1207         value = GetImplementation( button ).mTogglableButton;
1208         break;
1209       }
1210
1211       case Toolkit::Button::Property::SELECTED:
1212       {
1213         value = GetImplementation( button ).IsSelected();
1214         break;
1215       }
1216
1217       case Toolkit::Button::Property::UNSELECTED_STATE_IMAGE:
1218       {
1219         value = GetImplementation( button ).GetUrlForImageVisual( Toolkit::Button::Property::UNSELECTED_VISUAL );
1220         break;
1221       }
1222
1223       case Toolkit::Button::Property::SELECTED_STATE_IMAGE:
1224       {
1225         value = GetImplementation( button ).GetUrlForImageVisual( Toolkit::Button::Property::SELECTED_VISUAL );
1226         break;
1227       }
1228
1229       case Toolkit::Button::Property::DISABLED_STATE_IMAGE:
1230       {
1231         value = GetImplementation( button ).GetUrlForImageVisual( Toolkit::Button::Property::DISABLED_UNSELECTED_VISUAL );
1232         break;
1233       }
1234
1235       case Toolkit::Button::Property::UNSELECTED_COLOR:
1236       {
1237         value = GetImplementation( button ).GetUnselectedColor();
1238         break;
1239       }
1240
1241       case Toolkit::Button::Property::SELECTED_COLOR:
1242       {
1243         value = GetImplementation( button ).GetSelectedColor();
1244         break;
1245       }
1246
1247       case Toolkit::Button::Property::LABEL_TEXT:
1248       {
1249         value = GetImplementation( button ).GetLabelText();
1250         break;
1251       }
1252
1253       case Toolkit::Button::Property::LABEL:
1254       {
1255         Property::Map emptyMap;
1256         value = emptyMap;
1257         break;
1258       }
1259
1260       case Toolkit::Button::Property::LABEL_STRUT_LENGTH:
1261       {
1262         value = GetImplementation( button ).GetLabelStrutLength();
1263         break;
1264       }
1265
1266       case Toolkit::Button::Property::LABEL_RELATIVE_ALIGNMENT:
1267       {
1268         const char* alignment = Scripting::GetEnumerationName< Button::Align >( GetImplementation( button ).GetLabelAlignment(),
1269                                                                                 ALIGNMENT_STRING_TABLE,
1270                                                                                 ALIGNMENT_STRING_TABLE_COUNT );
1271         if( alignment )
1272         {
1273           value = std::string( alignment );
1274         }
1275
1276         break;
1277       }
1278     }
1279   }
1280
1281   return value;
1282 }
1283
1284 void Button::SetLabelPadding( const Padding& padding)
1285 {
1286   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetLabelPadding padding(%f,%f,%f,%f)\n", padding.left, padding.right, padding.bottom, padding.top );
1287   mLabelPadding = Padding( padding.left, padding.right, padding.bottom, padding.top );
1288   RelayoutRequest();
1289 }
1290
1291 Padding Button::GetLabelPadding()
1292 {
1293   return mLabelPadding;
1294 }
1295
1296 void Button::SetForegroundPadding( const Padding& padding)
1297 {
1298   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetForegroundPadding padding(%f,%f,%f,%f)\n", padding.left, padding.right, padding.bottom, padding.top );
1299   mForegroundPadding = Padding( padding.left, padding.right, padding.bottom, padding.top );
1300   RelayoutRequest();
1301 }
1302
1303 Padding Button::GetForegroundPadding()
1304 {
1305   return mForegroundPadding;
1306 }
1307
1308 ////////////////////////////////////////////////////////////////////////
1309 // Legacy functions from Tizen 2.4 and 3.0
1310
1311 // Legacy code needed whilst Color can be set by direct Property setting ( deprecated ) instead of setting a Visual
1312 void Button::SetColor( const Vector4& color, Property::Index visualIndex )
1313 {
1314   if ( visualIndex == Toolkit::Button::Property::SELECTED_BACKGROUND_VISUAL )
1315   {
1316     mSelectedColor = color;
1317   }
1318   else
1319   {
1320     mUnselectedColor = color;
1321   }
1322
1323   Property::Map map;
1324   map[ Toolkit::Visual::Property::TYPE ] = Toolkit::Visual::COLOR;
1325   map[ Toolkit::ColorVisual::Property::MIX_COLOR ] = color;
1326
1327   CreateVisualsForComponent( visualIndex, map, DepthIndex::BACKGROUND );
1328 }
1329
1330 const Vector4 Button::GetUnselectedColor() const
1331 {
1332   return mUnselectedColor;
1333 }
1334
1335 const Vector4 Button::GetSelectedColor() const
1336 {
1337   return mSelectedColor;
1338 }
1339
1340 void Button::SetAnimationTime( float animationTime )
1341 {
1342   // Used by depreciated API
1343   mAnimationTime = animationTime;
1344 }
1345
1346 float Button::GetAnimationTime() const
1347 {
1348   // Used by depreciated API
1349   return mAnimationTime;
1350 }
1351
1352 void Button::SetLabel( Actor label )
1353 {
1354   if ( label )
1355   {
1356     Property::Value value ="";
1357     value = label.GetProperty(Toolkit::TextLabel::Property::TEXT);
1358
1359     SetLabelText( value.Get<std::string>() );
1360   }
1361 }
1362
1363 void Button::SetUnselectedImage( const std::string& filename )
1364 {
1365   if( !filename.empty() )
1366   {
1367     CreateVisualsForComponent( Toolkit::Button::Property::UNSELECTED_VISUAL, filename, DepthIndex::CONTENT );
1368   }
1369 }
1370
1371 void Button::SetBackgroundImage( const std::string& filename )
1372 {
1373   if( !filename.empty() )
1374   {
1375     CreateVisualsForComponent( Toolkit::Button::Property::UNSELECTED_BACKGROUND_VISUAL, filename, DepthIndex::BACKGROUND );
1376   }
1377 }
1378
1379 void Button::SetSelectedImage( const std::string& filename )
1380 {
1381   if( !filename.empty() )
1382   {
1383     CreateVisualsForComponent( Toolkit::Button::Property::SELECTED_VISUAL, filename, DepthIndex::CONTENT );
1384   }
1385 }
1386
1387 void Button::SetSelectedBackgroundImage( const std::string& filename )
1388 {
1389   if( !filename.empty() )
1390   {
1391     CreateVisualsForComponent( Toolkit::Button::Property::SELECTED_BACKGROUND_VISUAL, filename, DepthIndex::BACKGROUND );
1392   }
1393 }
1394
1395 void Button::SetDisabledBackgroundImage( const std::string& filename )
1396 {
1397   if( !filename.empty() )
1398   {
1399     CreateVisualsForComponent( Toolkit::Button::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL, filename, DepthIndex::BACKGROUND );
1400   }
1401 }
1402
1403 void Button::SetDisabledImage( const std::string& filename )
1404 {
1405   if( !filename.empty() )
1406   {
1407     CreateVisualsForComponent( Toolkit::Button::Property::DISABLED_UNSELECTED_VISUAL, filename, DepthIndex::CONTENT );
1408   }
1409 }
1410
1411 void Button::SetDisabledSelectedImage( const std::string& filename )
1412 {
1413   if( !filename.empty() )
1414   {
1415     CreateVisualsForComponent( Toolkit::Button::Property::DISABLED_SELECTED_VISUAL, filename, DepthIndex::CONTENT );
1416   }
1417 }
1418
1419 std::string Button::GetUrlForImageVisual( Property::Index index )
1420 {
1421   Toolkit::Visual::Base visual = GetVisual( index );
1422   std::string result;
1423
1424   if ( visual )
1425   {
1426     Dali::Property::Map retreivedMap;
1427     visual.CreatePropertyMap( retreivedMap );
1428     Property::Value* value = retreivedMap.Find(  Toolkit::ImageVisual::Property::URL,  Property::STRING );
1429     if ( value )
1430     {
1431       result = value->Get<std::string>();
1432     }
1433   }
1434
1435   return result;
1436 }
1437
1438 // Below functions DEPRECATED_1_0.50 - Return empty Actors
1439
1440 Actor Button::GetButtonImage() const
1441 {
1442   DALI_LOG_WARNING("Button::GetButtonImage @DEPRECATED_1_0.50 Returning empty Actor \n");
1443   return Actor();;
1444 }
1445
1446 Actor Button::GetSelectedImage() const
1447 {
1448   DALI_LOG_WARNING("Button::GetSelectedImage @DEPRECATED_1_0.50 Returning empty Actor \n");
1449   return Actor();
1450 }
1451
1452 } // namespace Internal
1453
1454 } // namespace Toolkit
1455
1456 } // namespace Dali