[dali_1.2.22] Merge branch '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   Self().SetProperty( Toolkit::Button::Property::LABEL, label );
352 }
353
354 std::string Button::GetLabelText() const
355 {
356   Property::Value value = Self().GetProperty( Toolkit::Button::Property::LABEL );
357
358   Property::Map *labelProperty = value.GetMap();
359
360   std::string textLabel;
361
362   if ( labelProperty )
363   {
364     Property::Value* value = labelProperty->Find( Toolkit::TextVisual::Property::TEXT );
365     value->Get( textLabel );
366   }
367
368   return textLabel;
369 }
370
371 void Button::MergeWithExistingLabelProperties( const Property::Map& inMap, Property::Map& outMap )
372 {
373   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "MergeLabelProperties with %d properties\n", inMap.Count() );
374
375   /**
376    * Properties for the Label visual could be from a style sheet but after being set the "TEXT" property could be set.
377    * Hence would need to create the Text Visual with the complete merged set of properties.
378    *
379    * 1) Find Label Visual
380    * 2) Retrieve current properties ( settings )
381    * 3) Merge with new properties ( settings )
382    * 4) Return new merged map
383    */
384   Toolkit::Visual::Base visual = GetVisual( Toolkit::Button::Property::LABEL );
385   if ( visual )
386   {
387     DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "MergeLabelProperties Visual already exists, retrieving existing map\n");
388     visual.CreatePropertyMap( outMap );
389     DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "MergeLabelProperties retrieved %d properties\n", outMap.Count() );
390   }
391
392   outMap.Merge( inMap );
393
394   // Store if a text string has been supplied.
395
396   mTextStringSetFlag = MapContainsTextString( outMap );
397
398   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "MergeLabelProperties now has %d properties\n", outMap.Count() );
399 }
400
401 void Button::SetLabelAlignment( Button::Align labelAlignment)
402 {
403   mTextLabelAlignment = labelAlignment;
404   RelayoutRequest();
405 }
406
407 Button::Align Button::GetLabelAlignment()
408 {
409   return mTextLabelAlignment;
410 }
411
412 /**
413  * Create Visual for given index from a property map or url.
414  * 1) Check if value passed in is a url and create visual
415  * 2) Create visual from map if step (1) is false
416  * 3) Register visual with control with false for enable flag. Button will later enable visual when needed ( Button::SelectRequiredVisual )
417  * 4) Unregister visual if empty map was provided. This is the method to remove a visual
418  */
419
420 void Button::CreateVisualsForComponent( Property::Index index, const Property::Value& value, const float visualDepth )
421 {
422   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "CreateVisualsForComponent index(%d)\n", index );
423   Toolkit::VisualFactory visualFactory = Toolkit::VisualFactory::Get();
424   Toolkit::Visual::Base buttonVisual;
425
426   std::string imageUrl;
427   if( value.Get( imageUrl ) )
428   {
429     DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "CreateVisualsForComponent Using image URL(%d)\n", index );
430     if ( !imageUrl.empty() )
431     {
432       DALI_ASSERT_DEBUG( index != Toolkit::Button::Property::LABEL && "Creating a Image Visual instead of Text Visual " );
433       buttonVisual = visualFactory.CreateVisual(  imageUrl, ImageDimensions()  );
434     }
435   }
436   else
437   {
438     // if its not a string then get a Property::Map from the property if possible.
439     Property::Map *map = value.GetMap();
440     if( map && !map->Empty()  ) // Empty map results in current visual removal.
441     {
442       DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "CreateVisualsForComponent Using Map(%d)\n", index );
443       buttonVisual = visualFactory.CreateVisual( *map );
444     }
445   }
446
447   if ( buttonVisual )
448   {
449     DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "CreateVisualsForComponent RegisterVisual index(%d) enabled(%s)\n",
450                    index, IsVisualEnabled( index )?"true":"false" );
451     buttonVisual.SetDepthIndex( visualDepth );
452     RegisterVisual( index, buttonVisual, IsVisualEnabled( index ) );
453   }
454   else
455   {
456     UnregisterVisual( index );
457     DALI_LOG_INFO( gLogButtonFilter, Debug::General, "CreateVisualsForComponent Visual not created or empty map (clearing visual).(%d)\n", index);
458   }
459   PerformFunctionOnVisualsInState( &Button::SelectRequiredVisual, mButtonState );
460 }
461
462 bool Button::GetPropertyMapForVisual( Property::Index visualIndex, Property::Map& retreivedMap ) const
463 {
464   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetPropertyMapForVisual visual(%d)\n", visualIndex);
465   bool success = false;
466   Toolkit::Visual::Base visual = GetVisual( visualIndex );
467   if ( visual )
468   {
469     visual.CreatePropertyMap( retreivedMap );
470     success = true;
471   }
472   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetPropertyMapForVisual %s\n", success?"Success":"Failure");
473   return success;
474 }
475
476 bool Button::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
477 {
478   bool ret = false;
479
480   Dali::BaseHandle handle( object );
481
482   Toolkit::Button button = Toolkit::Button::DownCast( handle );
483
484   DALI_ASSERT_DEBUG( button );
485
486   if( 0 == strcmp( actionName.c_str(), ACTION_BUTTON_CLICK ) )
487   {
488     ret = GetImplementation( button ).DoClickAction( attributes );
489   }
490
491   return ret;
492 }
493
494 bool Button::DoClickAction( const Property::Map& attributes )
495 {
496   // Prevents the button signals from doing a recursive loop by sending an action
497   // and re-emitting the signals.
498   if( !mClickActionPerforming )
499   {
500     mClickActionPerforming = true;
501     ButtonDown();
502     if ( !mTogglableButton )
503     {
504       mButtonPressedState = DEPRESSED;
505     }
506     ButtonUp();
507     mClickActionPerforming = false;
508
509     return true;
510   }
511
512   return false;
513 }
514
515 void Button::ButtonDown()
516 {
517   if( mTogglableButton )
518   {
519     if ( mButtonState != SELECTED_STATE )
520     {
521       SetSelected( true );
522       mButtonPressedState = TOGGLE_DEPRESSED;
523     }
524     else
525     {
526       mButtonPressedState = DEPRESSED;
527     }
528   }
529   else
530   {
531     Pressed();
532     mButtonPressedState = DEPRESSED;
533     if( mAutoRepeating )
534     {
535        SetUpTimer( mInitialAutoRepeatingDelay );
536     }
537   }
538
539   // The pressed signal should be emitted regardless of toggle mode.
540   Toolkit::Button handle( GetOwner() );
541   mPressedSignal.Emit( handle );
542 }
543
544 void Button::ButtonUp()
545 {
546   bool emitSignalsForPressAndReleaseAction = false;
547
548   if( DEPRESSED == mButtonPressedState )
549   {
550     if( mTogglableButton ) // Button up will change state
551     {
552       emitSignalsForPressAndReleaseAction = OnToggleReleased(); // Derived toggle buttons can override this to provide custom behaviour
553     }
554     else
555     {
556       Released(); // Button up will result in unselected state
557       if( mAutoRepeating )
558       {
559         mAutoRepeatingTimer.Reset();
560       }
561       emitSignalsForPressAndReleaseAction = true;
562     }
563   }
564   else if ( TOGGLE_DEPRESSED == mButtonPressedState )
565   {
566     emitSignalsForPressAndReleaseAction = true; // toggle released after being pressed, a click
567   }
568
569   if ( emitSignalsForPressAndReleaseAction )
570   {
571     // The clicked and released signals should be emitted regardless of toggle mode.
572     Toolkit::Button handle( GetOwner() );
573     mReleasedSignal.Emit( handle );
574     mClickedSignal.Emit( handle );
575   }
576 }
577
578 bool Button::OnToggleReleased()
579 {
580   SetSelected( !IsSelected() );
581   mButtonPressedState = UNPRESSED;
582   return true;
583 }
584
585
586 void Button::OnTouchPointLeave()
587 {
588   if( DEPRESSED == mButtonPressedState )
589   {
590     if( !mTogglableButton )
591     {
592       Released();
593
594       if( mAutoRepeating )
595       {
596         mAutoRepeatingTimer.Reset();
597       }
598     }
599
600     mButtonPressedState = UNPRESSED;
601
602     // The released signal should be emitted regardless of toggle mode.
603     Toolkit::Button handle( GetOwner() );
604     mReleasedSignal.Emit( handle );
605   }
606 }
607
608 void Button::OnTouchPointInterrupted()
609 {
610   OnTouchPointLeave();
611 }
612
613 Toolkit::Button::ButtonSignalType& Button::PressedSignal()
614 {
615   return mPressedSignal;
616 }
617
618 Toolkit::Button::ButtonSignalType& Button::ReleasedSignal()
619 {
620   return mReleasedSignal;
621 }
622
623 Toolkit::Button::ButtonSignalType& Button::ClickedSignal()
624 {
625   return mClickedSignal;
626 }
627
628 Toolkit::Button::ButtonSignalType& Button::StateChangedSignal()
629 {
630   return mStateChangedSignal;
631 }
632
633 bool Button::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
634 {
635   Dali::BaseHandle handle( object );
636
637   bool connected( true );
638   Toolkit::Button button = Toolkit::Button::DownCast( handle );
639
640   if( 0 == strcmp( signalName.c_str(), SIGNAL_PRESSED ) )
641   {
642     button.PressedSignal().Connect( tracker, functor );
643   }
644   else if( 0 == strcmp( signalName.c_str(), SIGNAL_RELEASED ) )
645   {
646     button.ReleasedSignal().Connect( tracker, functor );
647   }
648   else if( 0 == strcmp( signalName.c_str(), SIGNAL_CLICKED ) )
649   {
650     button.ClickedSignal().Connect( tracker, functor );
651   }
652   else if( 0 == strcmp( signalName.c_str(), SIGNAL_STATE_CHANGED ) )
653   {
654     button.StateChangedSignal().Connect( tracker, functor );
655   }
656   else
657   {
658     // signalName does not match any signal
659     connected = false;
660   }
661
662   return connected;
663 }
664
665 void Button::OnInitialize()
666 {
667   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::OnInitialize\n" );
668
669   Actor self = Self();
670
671   mTapDetector = TapGestureDetector::New();
672   mTapDetector.Attach( self );
673   mTapDetector.DetectedSignal().Connect(this, &Button::OnTap);
674
675   self.SetKeyboardFocusable( true );
676
677   self.TouchSignal().Connect( this, &Button::OnTouch );
678 }
679
680 bool Button::OnAccessibilityActivated()
681 {
682   return OnKeyboardEnter();
683 }
684
685 bool Button::OnTouch( Actor actor, const TouchData& touch )
686 {
687
688   // Only events are processed when the button is not disabled and the touch event has only
689   // one touch point.
690
691   if( !IsDisabled() && ( 1 == touch.GetPointCount() ) )
692   {
693     switch( touch.GetState( 0 ) )
694     {
695       case PointState::DOWN:
696       {
697         ButtonDown();
698         break;
699       }
700       case PointState::UP:
701       {
702         ButtonUp();
703         break;
704       }
705       case PointState::INTERRUPTED:
706       {
707         OnTouchPointInterrupted();
708         break;
709       }
710       case PointState::LEAVE:
711       {
712         OnTouchPointLeave();
713         break;
714       }
715       case PointState::MOTION:
716       case PointState::STATIONARY: // FALLTHROUGH
717       {
718         // Nothing to do
719         break;
720       }
721     }
722   }
723   else if( 1 < touch.GetPointCount() )
724   {
725     OnTouchPointLeave(); // Notification for derived classes.
726
727     // Sets the button state to the default
728     mButtonPressedState = UNPRESSED;
729   }
730
731   return false;
732 }
733
734 bool Button::OnKeyboardEnter()
735 {
736   // When the enter key is pressed, or button is activated, the click action is performed.
737   Property::Map attributes;
738   bool ret = DoClickAction( attributes );
739
740   return ret;
741 }
742
743 void Button::OnStageDisconnection()
744 {
745   if( DEPRESSED == mButtonPressedState )
746   {
747     if( !mTogglableButton )
748     {
749       Released();
750
751       if( mAutoRepeating )
752       {
753         mAutoRepeatingTimer.Reset();
754       }
755     }
756   }
757
758   mButtonPressedState = UNPRESSED;
759
760   Control::OnStageDisconnection(); // Visuals will be set off stage
761 }
762
763 void Button::OnStageConnection( int depth )
764 {
765   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::OnStageConnection ptr(%p) \n", this );
766   PerformFunctionOnVisualsInState( &Button::OnButtonVisualRemoval, mPreviousButtonState );
767   SelectRequiredVisual( Toolkit::Button::Property::LABEL );
768   PerformFunctionOnVisualsInState( &Button::SelectRequiredVisual, mButtonState );
769   Control::OnStageConnection( depth ); // Enabled visuals will be put on stage
770 }
771
772 Vector3 Button::GetNaturalSize()
773 {
774   Vector3 size = Vector3::ZERO;
775
776   bool horizontalAlignment = mTextLabelAlignment == BEGIN || mTextLabelAlignment == END; // label and visual side by side
777
778   // Get natural size of foreground ( largest of the possible visuals )
779   Size largestProvidedVisual;
780   Size labelSize = Size::ZERO;
781
782   bool foreGroundVisualUsed = false;
783
784   for ( int state = Button::UNSELECTED_STATE; state < Button::STATE_COUNT; state++ )
785   {
786     Toolkit::Visual::Base visual = GetVisual( GET_VISUAL_INDEX_FOR_STATE[state][FOREGROUND] );
787     Size visualSize;
788     if ( visual )
789     {
790       visual.GetNaturalSize( visualSize );
791       largestProvidedVisual.width = std::max(largestProvidedVisual.width, visualSize.width );
792       largestProvidedVisual.height = std::max(largestProvidedVisual.height, visualSize.height );
793       foreGroundVisualUsed = true;
794     }
795   }
796
797   if ( !foreGroundVisualUsed ) // If foreground visual not supplied then use the background visual to calculate Natural size
798   {
799     for ( int state = Button::UNSELECTED_STATE; state < Button::STATE_COUNT; state++ )
800     {
801       Toolkit::Visual::Base visual = GetVisual( GET_VISUAL_INDEX_FOR_STATE[state][BACKGROUND] );
802       Size visualSize;
803       if ( visual )
804       {
805         visual.GetNaturalSize( visualSize );
806         largestProvidedVisual.width = std::max(largestProvidedVisual.width, visualSize.width );
807         largestProvidedVisual.height = std::max(largestProvidedVisual.height, visualSize.height );
808       }
809     }
810   }
811
812   // Get horizontal padding total
813   if ( largestProvidedVisual.width > 0 )  // if visual exists
814   {
815     size.width += largestProvidedVisual.width + mForegroundPadding.left + mForegroundPadding.right;
816   }
817   // Get vertical padding total
818   if ( largestProvidedVisual.height > 0 )
819   {
820     size.height += largestProvidedVisual.height + mForegroundPadding.top + mForegroundPadding.bottom;
821   }
822
823   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetNaturalSize visual Size(%f,%f)\n",
824                  largestProvidedVisual.width, largestProvidedVisual.height );
825
826   // Get natural size of label if text has been set
827   if ( mTextStringSetFlag )
828   {
829     Toolkit::Visual::Base visual = GetVisual( Toolkit::Button::Property::LABEL );
830
831     if ( visual )
832     {
833       visual.GetNaturalSize( labelSize );
834
835       DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetNaturalSize labelSize(%f,%f) padding(%f,%f)\n",
836                      labelSize.width, labelSize.height, mLabelPadding.left + mLabelPadding.right, mLabelPadding.top + mLabelPadding.bottom);
837
838       labelSize.width += mLabelPadding.left + mLabelPadding.right;
839       labelSize.height += mLabelPadding.top + mLabelPadding.bottom;
840
841       // Add label size to height or width depending on alignment position
842       if ( horizontalAlignment )
843       {
844         size.width += labelSize.width;
845         size.height = std::max(size.height, labelSize.height );
846       }
847       else
848       {
849         size.height += labelSize.height;
850         size.width = std::max(size.width, labelSize.width );
851       }
852     }
853   }
854
855   if( size.width < 1 && size.height < 1 )
856   {
857     // if no image or label then use Control's natural size
858     DALI_LOG_INFO( gLogButtonFilter, Debug::General, "GetNaturalSize Using control natural size\n");
859     size = Control::GetNaturalSize();
860   }
861
862   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "Button GetNaturalSize (%f,%f)\n", size.width, size.height );
863
864   return size;
865 }
866
867 void Button::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
868 {
869   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnSetResizePolicy\n");
870   RelayoutRequest();
871 }
872
873 /**
874  * Visuals are sized and positioned in this function.
875  * Whilst the control has it's size negotiated it has to size it's visuals explicitly here.
876  */
877
878 void Button::OnRelayout( const Vector2& size, RelayoutContainer& container )
879 {
880   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout targetSize(%f,%f) ptr(%p) state[%d]\n", size.width, size.height, this, mButtonState );
881
882   Toolkit::Visual::Base currentVisual = GetVisual( GET_VISUAL_INDEX_FOR_STATE[mButtonState][FOREGROUND] );
883
884   Toolkit::Visual::Base currentBackGroundVisual = GetVisual( GET_VISUAL_INDEX_FOR_STATE[mButtonState][BACKGROUND] );
885
886   // Sizes and padding set to zero, if not present then values will no effect calculations.
887   Vector2 visualPosition = Vector2::ZERO;
888   Vector2 labelPosition = Vector2::ZERO;
889   Size visualSize = Size::ZERO;
890   Padding foregroundVisualPadding = Padding(0.0f, 0.0f, 0.0f, 0.0f );
891   Padding labelVisualPadding = Padding(0.0f, 0.0f, 0.0f, 0.0f );
892
893   if ( mTextStringSetFlag )
894   {
895     DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Label padding setting padding:%f,%f,%f,%f\n", mLabelPadding.y, mLabelPadding.x, mLabelPadding.width,mLabelPadding.height );
896     labelVisualPadding = mLabelPadding;
897   }
898
899   if ( currentVisual )
900   {
901     DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Foreground Visual setting padding:%f,%f,%f,%f\n", mForegroundPadding.y, mForegroundPadding.x, mForegroundPadding.width,mForegroundPadding.height );
902     currentVisual.GetNaturalSize( visualSize );
903     foregroundVisualPadding = mForegroundPadding;
904   }
905
906   Toolkit::Align::Type visualAnchorPoint = Toolkit::Align::TOP_BEGIN;
907
908   Vector2 visualAndPaddingSize = Vector2( ( foregroundVisualPadding.x + visualSize.width + foregroundVisualPadding.y ),
909                                           ( foregroundVisualPadding.width + visualSize.height + foregroundVisualPadding.height ));
910
911   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout visualAndPaddingSize(%f,%f)\n", visualAndPaddingSize.width, visualAndPaddingSize.height);
912
913   // Text Visual should take all space available after foreground visual size and all padding is considered.
914   // Remaining Space priority, Foreground padding, foreground visual, Text padding then Text visual.
915   Size remainingSpaceForText = Size::ZERO;
916
917   switch ( mTextLabelAlignment )
918   {
919     case BEGIN :
920     {
921       visualAnchorPoint = Toolkit::Align::TOP_END;
922       visualPosition.x = foregroundVisualPadding.right;
923       visualPosition.y = foregroundVisualPadding.top;
924
925       labelPosition.x = labelVisualPadding.x;
926       labelPosition.y = labelVisualPadding.top;
927
928       remainingSpaceForText.width = size.width - visualAndPaddingSize.width - labelVisualPadding.x - labelVisualPadding.y;
929       remainingSpaceForText.height = size.height - labelVisualPadding.top - labelVisualPadding.bottom;
930       break;
931     }
932     case END :
933     {
934       visualAnchorPoint = Toolkit::Align::TOP_BEGIN;
935       visualPosition.x = foregroundVisualPadding.left;
936       visualPosition.y = foregroundVisualPadding.top;
937
938       labelPosition.x = visualAndPaddingSize.width + labelVisualPadding.x;
939       labelPosition.y = labelVisualPadding.top;
940
941       remainingSpaceForText.width = size.width - visualAndPaddingSize.width - labelVisualPadding.x - labelVisualPadding.y;
942       remainingSpaceForText.height = size.height - labelVisualPadding.top - labelVisualPadding.bottom;
943       break;
944     }
945     case TOP :
946     {
947       visualAnchorPoint = Toolkit::Align::BOTTOM_END;
948       visualPosition.x = foregroundVisualPadding.left;
949       visualPosition.y = foregroundVisualPadding.bottom;
950
951       labelPosition.x = labelVisualPadding.left;
952       labelPosition.y = labelVisualPadding.top;
953
954       remainingSpaceForText.width = size.width - labelVisualPadding.x - labelVisualPadding.y;
955       remainingSpaceForText.height = size.height - visualAndPaddingSize.height - labelVisualPadding.top - labelVisualPadding.bottom;
956
957       break;
958     }
959     case BOTTOM :
960     {
961       visualAnchorPoint = Toolkit::Align::TOP_END;
962       visualPosition.x = foregroundVisualPadding.left;
963       visualPosition.y = foregroundVisualPadding.top;
964
965       labelPosition.x = labelVisualPadding.left;
966       labelPosition.y = visualAndPaddingSize.height + labelVisualPadding.top;
967
968       remainingSpaceForText.width = size.width - labelVisualPadding.x - labelVisualPadding.y;
969       remainingSpaceForText.height = size.height - visualAndPaddingSize.height - labelVisualPadding.top - labelVisualPadding.bottom;
970
971       break;
972     }
973   }
974
975   if ( currentBackGroundVisual )
976   {
977     DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Setting visual background size to(%f,%f)\n", size.width, size.height);
978
979     Property::Map visualTransform;
980
981     visualTransform.Add( Toolkit::DevelVisual::Transform::Property::SIZE, size )
982                    .Add( Toolkit::DevelVisual::Transform::Property::OFFSET_SIZE_MODE, Vector4( 0.0f, 0.0f, 1.0f, 1.0f) );  // Use relative size
983
984     currentBackGroundVisual.SetTransformAndSize( visualTransform, size );
985   }
986
987   if ( currentVisual )
988   {
989     DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Setting visual size to(%f,%f)\n", visualSize.width, visualSize.height);
990
991     Property::Map visualTransform;
992
993     visualTransform.Add( Toolkit::DevelVisual::Transform::Property::SIZE, visualSize )
994                    .Add( Toolkit::DevelVisual::Transform::Property::OFFSET, visualPosition )
995                    .Add( Toolkit::DevelVisual::Transform::Property::OFFSET_SIZE_MODE, Vector4( 1.0f, 1.0f, 1.0f, 1.0f) )  // Use absolute size
996                    .Add( Toolkit::DevelVisual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN )
997                    .Add( Toolkit::DevelVisual::Transform::Property::ANCHOR_POINT, visualAnchorPoint );
998
999     currentVisual.SetTransformAndSize( visualTransform, size );
1000   }
1001
1002   if ( mTextStringSetFlag )
1003   {
1004     Toolkit::Visual::Base textVisual = GetVisual( Toolkit::Button::Property::LABEL ); // No need to search for Label visual if no text set.
1005
1006     if ( textVisual )
1007     {
1008       if ( !currentVisual )
1009       {
1010         DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Only Text\n");
1011         labelPosition.x = labelVisualPadding.left;
1012         labelPosition.y = labelVisualPadding.height;
1013       }
1014
1015       Vector2 preSize = Vector2( static_cast< int >( remainingSpaceForText.x ), static_cast< int >( remainingSpaceForText.y ));
1016
1017       DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout text Size(%f,%f) text Position(%f,%f) \n", remainingSpaceForText.width, remainingSpaceForText.height, labelPosition.x, labelPosition.y);
1018
1019       DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout text Size -- (%f,%f) text Position(%f,%f) \n", preSize.width, preSize.height, labelPosition.x, labelPosition.y);
1020
1021
1022       Property::Map textVisualTransform;
1023       textVisualTransform.Add( Toolkit::DevelVisual::Transform::Property::SIZE, preSize )
1024                          .Add( Toolkit::DevelVisual::Transform::Property::OFFSET, labelPosition )
1025                          .Add( Toolkit::DevelVisual::Transform::Property::OFFSET_SIZE_MODE, Vector4( 1.0f, 1.0f, 1.0f,1.0f ) ) // Use absolute size
1026                          .Add( Toolkit::DevelVisual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN )
1027                          .Add( Toolkit::DevelVisual::Transform::Property::ANCHOR_POINT, visualAnchorPoint );
1028
1029       textVisual.SetTransformAndSize( textVisualTransform, size );
1030     }
1031   }
1032
1033   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout selected (%s) \n", IsSelected()?"yes":"no" );
1034
1035   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout << \n");
1036 }
1037
1038 void Button::OnTap(Actor actor, const TapGesture& tap)
1039 {
1040   // Prevents Parent getting a tap event
1041 }
1042
1043 void Button::SetUpTimer( float delay )
1044 {
1045   mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
1046   mAutoRepeatingTimer.TickSignal().Connect( this, &Button::AutoRepeatingSlot );
1047   mAutoRepeatingTimer.Start();
1048 }
1049
1050 bool Button::AutoRepeatingSlot()
1051 {
1052   bool consumed = false;
1053   if( !IsDisabled() )
1054   {
1055     // Restart the autorepeat timer.
1056     SetUpTimer( mNextAutoRepeatingDelay );
1057
1058     Pressed();
1059
1060     Toolkit::Button handle( GetOwner() );
1061
1062     //Emit signal.
1063     consumed = mReleasedSignal.Emit( handle );
1064     consumed = mClickedSignal.Emit( handle );
1065     consumed |= mPressedSignal.Emit( handle );
1066  }
1067
1068   return consumed;
1069 }
1070
1071 void Button::Pressed()
1072 {
1073   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::Pressed\n" );
1074
1075   if( mButtonState == UNSELECTED_STATE )
1076   {
1077     ChangeState( SELECTED_STATE );
1078     OnPressed();  // Notifies the derived class the button has been pressed.
1079   }
1080 }
1081
1082 void Button::Released()
1083 {
1084   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::Released\n" );
1085
1086   if( mButtonState == SELECTED_STATE && !mTogglableButton )
1087   {
1088     ChangeState( UNSELECTED_STATE );
1089     OnReleased(); //    // Notifies the derived class the button has been released.
1090   }
1091   mButtonPressedState = UNPRESSED;
1092 }
1093
1094 void Button::SelectRequiredVisual( Property::Index visualIndex )
1095 {
1096   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SelectRequiredVisual index(%d) state(%d)\n", visualIndex, mButtonState );
1097
1098   EnableVisual( visualIndex, true );
1099 }
1100
1101 void Button::RemoveVisual( Property::Index visualIndex )
1102 {
1103   // Use OnButtonVisualRemoval if want button developer to have the option to override removal.
1104   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::RemoveVisual index(%d) state(%d)\n", visualIndex, mButtonState );
1105
1106   Toolkit::Visual::Base visual = GetVisual( visualIndex );
1107
1108   if( visual )
1109   {
1110     EnableVisual( visualIndex, false );
1111   }
1112 }
1113
1114 void Button::OnButtonVisualRemoval( Property::Index visualIndex )
1115 {
1116   // Derived Buttons can over ride this to prevent default removal.
1117   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::OnButtonVisualRemoval index(%d)\n", visualIndex );
1118   RemoveVisual( visualIndex );
1119 }
1120
1121 void Button::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
1122 {
1123   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1124
1125   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetProperty index[%d]\n", index );
1126
1127   if ( button )
1128   {
1129     switch ( index )
1130     {
1131       case Toolkit::Button::Property::DISABLED:
1132       {
1133         GetImplementation( button ).SetDisabled( value.Get< bool >() );
1134         break;
1135       }
1136
1137       case Toolkit::Button::Property::AUTO_REPEATING:
1138       {
1139         GetImplementation( button ).SetAutoRepeating( value.Get< bool >() );
1140         break;
1141       }
1142
1143       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1144       {
1145         GetImplementation( button ).SetInitialAutoRepeatingDelay( value.Get< float >() );
1146         break;
1147       }
1148
1149       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1150       {
1151         GetImplementation( button ).SetNextAutoRepeatingDelay( value.Get< float >() );
1152         break;
1153       }
1154
1155       case Toolkit::Button::Property::TOGGLABLE:
1156       {
1157         GetImplementation( button ).SetTogglableButton( value.Get< bool >() );
1158         break;
1159       }
1160
1161       case Toolkit::Button::Property::SELECTED:
1162       {
1163         GetImplementation( button ).SetSelected( value.Get< bool >() );
1164         break;
1165       }
1166
1167       case Toolkit::Button::Property::UNSELECTED_STATE_IMAGE: // Legacy Tizen 3.0
1168       {
1169         GetImplementation( button ).CreateVisualsForComponent( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL, value, DepthIndex::BACKGROUND );
1170         break;
1171       }
1172       case Toolkit::Button::Property::DISABLED_STATE_IMAGE:  // Legacy Tizen 3.0
1173       {
1174         GetImplementation( button ).CreateVisualsForComponent( Toolkit::DevelButton::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL, value, DepthIndex::BACKGROUND );
1175         break;
1176       }
1177       case Toolkit::Button::Property::SELECTED_STATE_IMAGE:  // Legacy Tizen 3.0
1178       {
1179         GetImplementation( button ).CreateVisualsForComponent( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL, value, DepthIndex::BACKGROUND );
1180         break;
1181       }
1182       case Toolkit::DevelButton::Property::UNSELECTED_VISUAL:
1183       case Toolkit::DevelButton::Property::SELECTED_VISUAL:
1184       case Toolkit::DevelButton::Property::DISABLED_SELECTED_VISUAL:
1185       case Toolkit::DevelButton::Property::DISABLED_UNSELECTED_VISUAL:
1186       {
1187         GetImplementation( button ).CreateVisualsForComponent( index, value, DepthIndex::CONTENT );
1188         break;
1189       }
1190
1191       case Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL:
1192       case Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL:
1193       case Toolkit::DevelButton::Property::DISABLED_SELECTED_BACKGROUND_VISUAL:
1194       case Toolkit::DevelButton::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL:
1195       {
1196         GetImplementation( button ).CreateVisualsForComponent( index , value, DepthIndex::BACKGROUND);
1197         break;
1198       }
1199
1200       case Toolkit::Button::Property::UNSELECTED_COLOR:
1201       {
1202         DALI_LOG_WARNING("[%s] Using deprecated Property Button::Property::UNSELECTED_COLOR instead use Button::Property::UNSELECTED_BACKGROUND_VISUAL\n", __FUNCTION__);
1203         GetImplementation( button ).SetColor( value.Get< Vector4 >(), Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL );
1204         break;
1205       }
1206
1207       case Toolkit::Button::Property::SELECTED_COLOR:
1208       {
1209         DALI_LOG_WARNING("[%s] Using deprecated Property Button::Property::SELECTED_COLOR instead use Button::Property::SELECTED_BACKGROUND_VISUAL\n", __FUNCTION__);
1210         GetImplementation( button ).SetColor( value.Get< Vector4 >(), Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL );
1211         break;
1212       }
1213
1214       case Toolkit::Button::Property::LABEL_TEXT:
1215       {
1216         DALI_LOG_WARNING("[%s] Using deprecated Property Button::Property::LABEL_TEXT instead use Button::Property::LABEL\n", __FUNCTION__);
1217         GetImplementation( button ).SetLabelText(value.Get< std::string >() );
1218         break;
1219       }
1220
1221       case Toolkit::Button::Property::LABEL:
1222       {
1223         Property::Map outTextVisualProperties;
1224         std::string textString;
1225
1226         if ( value.Get( textString ) )
1227         {
1228           DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetProperty Setting TextVisual with string[%s]\n", textString.c_str() );
1229
1230           Property::Map setPropertyMap;
1231           setPropertyMap.Add( Toolkit::Visual::Property::TYPE, Toolkit::DevelVisual::TEXT)
1232                         .Add( Toolkit::TextVisual::Property::TEXT, textString );
1233
1234           GetImplementation( button ).MergeWithExistingLabelProperties( setPropertyMap, outTextVisualProperties );
1235         }
1236         else
1237         {
1238           // Get a Property::Map from the property if possible.
1239           Property::Map* setPropertyMap = value.GetMap();
1240           if( setPropertyMap )
1241           {
1242             GetImplementation( button ).MergeWithExistingLabelProperties( *setPropertyMap, outTextVisualProperties );
1243           }
1244         }
1245
1246         if( !outTextVisualProperties.Empty() )
1247         {
1248           GetImplementation( button ).CreateVisualsForComponent( index, outTextVisualProperties, DepthIndex::CONTENT );
1249           GetImplementation( button ).RelayoutRequest();
1250         }
1251         break;
1252       }
1253
1254       case Toolkit::DevelButton::Property::LABEL_RELATIVE_ALIGNMENT:
1255       {
1256         Button::Align labelAlignment(END);
1257         Scripting::GetEnumeration< Button::Align> ( value.Get< std::string >().c_str(),
1258                                                     ALIGNMENT_TABLE, ALIGNMENT_TABLE_COUNT,
1259                                                     labelAlignment );
1260
1261         GetImplementation( button ).SetLabelAlignment( labelAlignment );
1262         GetImplementation( button ).RelayoutRequest();
1263         break;
1264       }
1265
1266       case Toolkit::DevelButton::Property::LABEL_PADDING:
1267       {
1268         Vector4 padding ( value.Get< Vector4 >() );
1269         GetImplementation( button ).SetLabelPadding( Padding( padding.x, padding.y, padding.z, padding.w ) );
1270         break;
1271       }
1272
1273       case Toolkit::DevelButton::Property::VISUAL_PADDING:
1274       {
1275         Vector4 padding ( value.Get< Vector4 >() );
1276         GetImplementation( button ).SetForegroundPadding( Padding( padding.x, padding.y, padding.z, padding.w ) );
1277         GetImplementation( button ).RelayoutRequest();
1278         break;
1279       }
1280     }
1281   }
1282 }
1283
1284 Property::Value Button::GetProperty( BaseObject* object, Property::Index propertyIndex )
1285 {
1286   Property::Value value;
1287
1288   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1289
1290   if ( button )
1291   {
1292     switch ( propertyIndex )
1293     {
1294       case Toolkit::Button::Property::DISABLED:
1295       {
1296         value = GetImplementation( button ).IsDisabled();
1297         break;
1298       }
1299
1300       case Toolkit::Button::Property::AUTO_REPEATING:
1301       {
1302         value = GetImplementation( button ).mAutoRepeating;
1303         break;
1304       }
1305
1306       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1307       {
1308         value = GetImplementation( button ).mInitialAutoRepeatingDelay;
1309         break;
1310       }
1311
1312       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1313       {
1314         value = GetImplementation( button ).mNextAutoRepeatingDelay;
1315         break;
1316       }
1317
1318       case Toolkit::Button::Property::TOGGLABLE:
1319       {
1320         value = GetImplementation( button ).mTogglableButton;
1321         break;
1322       }
1323
1324       case Toolkit::Button::Property::SELECTED:
1325       {
1326         value = GetImplementation( button ).IsSelected();
1327         break;
1328       }
1329
1330       case Toolkit::Button::Property::UNSELECTED_STATE_IMAGE:
1331       {
1332         value = GetImplementation( button ).GetUrlForImageVisual( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL );
1333         break;
1334       }
1335
1336       case Toolkit::Button::Property::SELECTED_STATE_IMAGE:
1337       {
1338         value = GetImplementation( button ).GetUrlForImageVisual( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL );
1339         break;
1340       }
1341
1342       case Toolkit::Button::Property::DISABLED_STATE_IMAGE:
1343       {
1344         value = GetImplementation( button ).GetUrlForImageVisual( Toolkit::DevelButton::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL );
1345         break;
1346       }
1347
1348       case Toolkit::DevelButton::Property::UNSELECTED_VISUAL:
1349       case Toolkit::DevelButton::Property::SELECTED_VISUAL:
1350       case Toolkit::DevelButton::Property::DISABLED_SELECTED_VISUAL:
1351       case Toolkit::DevelButton::Property::DISABLED_UNSELECTED_VISUAL:
1352       case Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL:
1353       case Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL:
1354       case Toolkit::DevelButton::Property::DISABLED_SELECTED_BACKGROUND_VISUAL:
1355       case Toolkit::DevelButton::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL:
1356       case Toolkit::Button::Property::LABEL:
1357       {
1358         Property::Map visualProperty;
1359         if ( GetImplementation( button ).GetPropertyMapForVisual( propertyIndex, visualProperty ) )
1360         {
1361           value = visualProperty;
1362         }
1363         break;
1364       }
1365
1366       case Toolkit::Button::Property::UNSELECTED_COLOR:
1367       {
1368         value = GetImplementation( button ).GetUnselectedColor();
1369         break;
1370       }
1371
1372       case Toolkit::Button::Property::SELECTED_COLOR:
1373       {
1374         value = GetImplementation( button ).GetSelectedColor();
1375         break;
1376       }
1377
1378       case Toolkit::Button::Property::LABEL_TEXT:
1379       {
1380         value = GetImplementation( button ).GetLabelText();
1381         break;
1382       }
1383
1384       case Toolkit::DevelButton::Property::LABEL_RELATIVE_ALIGNMENT:
1385       {
1386         const char* alignment = Scripting::GetEnumerationName< Button::Align >( GetImplementation( button ).GetLabelAlignment(),
1387                                                                                 ALIGNMENT_STRING_TABLE,
1388                                                                                 ALIGNMENT_STRING_TABLE_COUNT );
1389         if( alignment )
1390         {
1391           value = std::string( alignment );
1392         }
1393
1394         break;
1395       }
1396
1397       case Toolkit::DevelButton::Property::LABEL_PADDING:
1398       {
1399         Padding padding = GetImplementation( button ).GetLabelPadding();
1400         value = Vector4( padding.x, padding.y, padding.top, padding.bottom);
1401         break;
1402       }
1403
1404       case Toolkit::DevelButton::Property::VISUAL_PADDING:
1405       {
1406         Padding padding = GetImplementation( button ).GetForegroundPadding();
1407         value = Vector4( padding.x, padding.y, padding.top, padding.bottom);
1408       }
1409     }
1410   }
1411
1412   return value;
1413 }
1414
1415 void Button::SetLabelPadding( const Padding& padding)
1416 {
1417   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetLabelPadding padding(%f,%f,%f,%f)\n", padding.left, padding.right, padding.bottom, padding.top );
1418   mLabelPadding = Padding( padding.left, padding.right, padding.bottom, padding.top );
1419   RelayoutRequest();
1420 }
1421
1422 Padding Button::GetLabelPadding()
1423 {
1424   return mLabelPadding;
1425 }
1426
1427 void Button::SetForegroundPadding( const Padding& padding)
1428 {
1429   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetForegroundPadding padding(%f,%f,%f,%f)\n", padding.left, padding.right, padding.bottom, padding.top );
1430   mForegroundPadding = Padding( padding.left, padding.right, padding.bottom, padding.top );
1431   RelayoutRequest();
1432 }
1433
1434 Padding Button::GetForegroundPadding()
1435 {
1436   return mForegroundPadding;
1437 }
1438
1439 ////////////////////////////////////////////////////////////////////////
1440 // Legacy functions from Tizen 2.4 and 3.0
1441
1442 // Legacy code needed whilst Color can be set by direct Property setting ( deprecated ) instead of setting a Visual
1443 void Button::SetColor( const Vector4& color, Property::Index visualIndex )
1444 {
1445   if ( visualIndex == Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL )
1446   {
1447     mSelectedColor = color;
1448   }
1449   else
1450   {
1451     mUnselectedColor = color;
1452   }
1453
1454   Property::Map map;
1455   map[ Toolkit::Visual::Property::TYPE ] = Toolkit::Visual::COLOR;
1456   map[ Toolkit::ColorVisual::Property::MIX_COLOR ] = color;
1457
1458   CreateVisualsForComponent( visualIndex, map, DepthIndex::BACKGROUND );
1459 }
1460
1461 const Vector4 Button::GetUnselectedColor() const
1462 {
1463   return mUnselectedColor;
1464 }
1465
1466 const Vector4 Button::GetSelectedColor() const
1467 {
1468   return mSelectedColor;
1469 }
1470
1471 void Button::SetAnimationTime( float animationTime )
1472 {
1473   // Used by deprecated API
1474   mAnimationTime = animationTime;
1475 }
1476
1477 float Button::GetAnimationTime() const
1478 {
1479   // Used by deprecated API
1480   return mAnimationTime;
1481 }
1482
1483 void Button::SetLabel( Actor label )
1484 {
1485   if ( label )
1486   {
1487     Property::Value value ="";
1488     value = label.GetProperty(Toolkit::TextLabel::Property::TEXT);
1489
1490     SetLabelText( value.Get<std::string>() );
1491   }
1492 }
1493
1494 void Button::SetUnselectedImage( const std::string& filename )
1495 {
1496   SetBackgroundImage( filename );
1497 }
1498
1499 void Button::SetBackgroundImage( const std::string& filename )
1500 {
1501   if( !filename.empty() )
1502   {
1503     CreateVisualsForComponent( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL, filename, DepthIndex::BACKGROUND );
1504   }
1505   else
1506   {
1507     UnregisterVisual( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL );
1508   }
1509 }
1510
1511 void Button::SetSelectedImage( const std::string& filename )
1512 {
1513     SetSelectedBackgroundImage( filename );
1514 }
1515
1516 void Button::SetSelectedBackgroundImage( const std::string& filename )
1517 {
1518   if( !filename.empty() )
1519   {
1520     CreateVisualsForComponent( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL, filename, DepthIndex::BACKGROUND );
1521   }
1522   else
1523   {
1524     UnregisterVisual( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL );
1525   }
1526 }
1527
1528 void Button::SetDisabledBackgroundImage( const std::string& filename )
1529 {
1530   if( !filename.empty() )
1531   {
1532     CreateVisualsForComponent( Toolkit::DevelButton::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL, filename, DepthIndex::BACKGROUND );
1533   }
1534 }
1535
1536 void Button::SetDisabledImage( const std::string& filename )
1537 {
1538   if( !filename.empty() )
1539   {
1540     CreateVisualsForComponent( Toolkit::DevelButton::Property::DISABLED_UNSELECTED_VISUAL, filename, DepthIndex::CONTENT );
1541   }
1542 }
1543
1544 void Button::SetDisabledSelectedImage( const std::string& filename )
1545 {
1546   if( !filename.empty() )
1547   {
1548     CreateVisualsForComponent( Toolkit::DevelButton::Property::DISABLED_SELECTED_VISUAL, filename, DepthIndex::CONTENT );
1549   }
1550 }
1551
1552 // Used by Deprecated Properties which don't use the Visual Property maps for setting and getting
1553 std::string Button::GetUrlForImageVisual( const Property::Index index ) const
1554 {
1555   Toolkit::Visual::Base visual = GetVisual( index );
1556   std::string result;
1557
1558   if ( visual )
1559   {
1560     Dali::Property::Map retreivedMap;
1561     visual.CreatePropertyMap( retreivedMap );
1562     Property::Value* value = retreivedMap.Find(  Toolkit::ImageVisual::Property::URL,  Property::STRING );
1563     if ( value )
1564     {
1565       result = value->Get<std::string>();
1566     }
1567   }
1568
1569   return result;
1570 }
1571
1572 // Below functions DEPRECATED_1_0.50 - Return empty Actors
1573
1574 namespace
1575 {
1576 std::string GetUrlFromImage( Image& image )
1577 {
1578   ResourceImage resourceImage = ResourceImage::DownCast( image );
1579
1580   std::string imageUrl;
1581
1582   if ( resourceImage )
1583   {
1584     imageUrl = resourceImage.GetUrl();
1585   }
1586   return imageUrl;
1587 }
1588
1589 } // namespace
1590
1591
1592 void Button::SetButtonImage( Image image )
1593 {
1594   DALI_LOG_WARNING("Button::SetButtonImage @DEPRECATED_1_0.50\n");
1595   SetUnselectedImage( GetUrlFromImage( image ) );
1596 }
1597
1598 void Button::SetSelectedImage( Image image )
1599 {
1600   DALI_LOG_WARNING("Button::SetSelectedImage @DEPRECATED_1_0.50\n");
1601   SetSelectedImage( GetUrlFromImage( image ) );
1602 }
1603
1604 Actor Button::GetButtonImage() const
1605 {
1606   DALI_LOG_WARNING("Button::GetButtonImage @DEPRECATED_1_0.50\n");
1607   Actor imageView = Toolkit::ImageView::New( GetUrlForImageVisual( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL ) );
1608
1609   return imageView;
1610 }
1611
1612 Actor Button::GetSelectedImage() const
1613 {
1614   DALI_LOG_WARNING("Button::GetSelectedImage @DEPRECATED_1_0.50\n");
1615   Actor imageView = Toolkit::ImageView::New( GetUrlForImageVisual( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL ) );
1616
1617   return imageView;
1618 }
1619
1620 } // namespace Internal
1621
1622 } // namespace Toolkit
1623
1624 } // namespace Dali