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