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