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