Ensure Button Set and Get works with Image/Actor API
[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     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::SIZE_POLICY, Vector2( DevelVisual::Transform::Policy::ABSOLUTE, DevelVisual::Transform::Policy::ABSOLUTE ) );
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_POLICY, Vector2( DevelVisual::Transform::Policy::ABSOLUTE, DevelVisual::Transform::Policy::ABSOLUTE ) )
997                    .Add( Toolkit::DevelVisual::Transform::Property::SIZE_POLICY, Vector2( DevelVisual::Transform::Policy::ABSOLUTE, DevelVisual::Transform::Policy::ABSOLUTE ) )
998                    .Add( Toolkit::DevelVisual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN )
999                    .Add( Toolkit::DevelVisual::Transform::Property::ANCHOR_POINT, visualAnchorPoint );
1000
1001     currentVisual.SetTransformAndSize( visualTransform, size );
1002   }
1003
1004   if ( mTextStringSetFlag )
1005   {
1006     Toolkit::Visual::Base textVisual = GetVisual( Toolkit::Button::Property::LABEL ); // No need to search for Label visual if no text set.
1007
1008     if ( textVisual )
1009     {
1010       if ( !currentVisual )
1011       {
1012         DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout Only Text\n");
1013         labelPosition.x = labelVisualPadding.left;
1014         labelPosition.y = labelVisualPadding.height;
1015       }
1016
1017       Vector2 preSize = Vector2( static_cast< int >( remainingSpaceForText.x ), static_cast< int >( remainingSpaceForText.y ));
1018
1019       DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout text Size(%f,%f) text Position(%f,%f) \n", remainingSpaceForText.width, remainingSpaceForText.height, labelPosition.x, labelPosition.y);
1020
1021       DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout text Size -- (%f,%f) text Position(%f,%f) \n", preSize.width, preSize.height, labelPosition.x, labelPosition.y);
1022
1023
1024       Property::Map textVisualTransform;
1025       textVisualTransform.Add( Toolkit::DevelVisual::Transform::Property::SIZE, preSize )
1026                          .Add( Toolkit::DevelVisual::Transform::Property::OFFSET, labelPosition )
1027                          .Add( Toolkit::DevelVisual::Transform::Property::OFFSET_POLICY, Vector2( DevelVisual::Transform::Policy::ABSOLUTE, DevelVisual::Transform::Policy::ABSOLUTE ) )
1028                          .Add( Toolkit::DevelVisual::Transform::Property::SIZE_POLICY, Vector2( DevelVisual::Transform::Policy::ABSOLUTE, DevelVisual::Transform::Policy::ABSOLUTE ) )
1029                          .Add( Toolkit::DevelVisual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN )
1030                          .Add( Toolkit::DevelVisual::Transform::Property::ANCHOR_POINT, visualAnchorPoint );
1031
1032       textVisual.SetTransformAndSize( textVisualTransform, size );
1033     }
1034   }
1035
1036   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout selected (%s) \n", IsSelected()?"yes":"no" );
1037
1038   DALI_LOG_INFO( gLogButtonFilter, Debug::General, "OnRelayout << \n");
1039 }
1040
1041 void Button::OnTap(Actor actor, const TapGesture& tap)
1042 {
1043   // Prevents Parent getting a tap event
1044 }
1045
1046 void Button::SetUpTimer( float delay )
1047 {
1048   mAutoRepeatingTimer = Dali::Timer::New( static_cast<unsigned int>( 1000.f * delay ) );
1049   mAutoRepeatingTimer.TickSignal().Connect( this, &Button::AutoRepeatingSlot );
1050   mAutoRepeatingTimer.Start();
1051 }
1052
1053 bool Button::AutoRepeatingSlot()
1054 {
1055   bool consumed = false;
1056   if( !IsDisabled() )
1057   {
1058     // Restart the autorepeat timer.
1059     SetUpTimer( mNextAutoRepeatingDelay );
1060
1061     Pressed();
1062
1063     Toolkit::Button handle( GetOwner() );
1064
1065     //Emit signal.
1066     consumed = mReleasedSignal.Emit( handle );
1067     consumed = mClickedSignal.Emit( handle );
1068     consumed |= mPressedSignal.Emit( handle );
1069  }
1070
1071   return consumed;
1072 }
1073
1074 void Button::Pressed()
1075 {
1076   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::Pressed\n" );
1077
1078   if( mButtonState == UNSELECTED_STATE )
1079   {
1080     ChangeState( SELECTED_STATE );
1081     OnPressed();  // Notifies the derived class the button has been pressed.
1082   }
1083 }
1084
1085 void Button::Released()
1086 {
1087   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::Released\n" );
1088
1089   if( mButtonState == SELECTED_STATE && !mTogglableButton )
1090   {
1091     ChangeState( UNSELECTED_STATE );
1092     OnReleased(); //    // Notifies the derived class the button has been released.
1093   }
1094   mButtonPressedState = UNPRESSED;
1095 }
1096
1097 void Button::SelectRequiredVisual( Property::Index visualIndex )
1098 {
1099   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SelectRequiredVisual index(%d) state(%d)\n", visualIndex, mButtonState );
1100
1101   EnableVisual( visualIndex, true );
1102 }
1103
1104 void Button::RemoveVisual( Property::Index visualIndex )
1105 {
1106   // Use OnButtonVisualRemoval if want button developer to have the option to override removal.
1107   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::RemoveVisual index(%d) state(%d)\n", visualIndex, mButtonState );
1108
1109   Toolkit::Visual::Base visual = GetVisual( visualIndex );
1110
1111   if( visual )
1112   {
1113     EnableVisual( visualIndex, false );
1114   }
1115 }
1116
1117 void Button::OnButtonVisualRemoval( Property::Index visualIndex )
1118 {
1119   // Derived Buttons can over ride this to prevent default removal.
1120   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::OnButtonVisualRemoval index(%d)\n", visualIndex );
1121   RemoveVisual( visualIndex );
1122 }
1123
1124 void Button::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
1125 {
1126   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1127
1128   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetProperty index[%d]\n", index );
1129
1130   if ( button )
1131   {
1132     switch ( index )
1133     {
1134       case Toolkit::Button::Property::DISABLED:
1135       {
1136         GetImplementation( button ).SetDisabled( value.Get< bool >() );
1137         break;
1138       }
1139
1140       case Toolkit::Button::Property::AUTO_REPEATING:
1141       {
1142         GetImplementation( button ).SetAutoRepeating( value.Get< bool >() );
1143         break;
1144       }
1145
1146       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1147       {
1148         GetImplementation( button ).SetInitialAutoRepeatingDelay( value.Get< float >() );
1149         break;
1150       }
1151
1152       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1153       {
1154         GetImplementation( button ).SetNextAutoRepeatingDelay( value.Get< float >() );
1155         break;
1156       }
1157
1158       case Toolkit::Button::Property::TOGGLABLE:
1159       {
1160         GetImplementation( button ).SetTogglableButton( value.Get< bool >() );
1161         break;
1162       }
1163
1164       case Toolkit::Button::Property::SELECTED:
1165       {
1166         GetImplementation( button ).SetSelected( value.Get< bool >() );
1167         break;
1168       }
1169
1170       case Toolkit::Button::Property::UNSELECTED_STATE_IMAGE: // Legacy Tizen 3.0
1171       {
1172         GetImplementation( button ).CreateVisualsForComponent( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL, value, DepthIndex::BACKGROUND );
1173         break;
1174       }
1175       case Toolkit::Button::Property::DISABLED_STATE_IMAGE:  // Legacy Tizen 3.0
1176       {
1177         GetImplementation( button ).CreateVisualsForComponent( Toolkit::DevelButton::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL, value, DepthIndex::BACKGROUND );
1178         break;
1179       }
1180       case Toolkit::Button::Property::SELECTED_STATE_IMAGE:  // Legacy Tizen 3.0
1181       {
1182         GetImplementation( button ).CreateVisualsForComponent( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL, value, DepthIndex::BACKGROUND );
1183         break;
1184       }
1185       case Toolkit::DevelButton::Property::UNSELECTED_VISUAL:
1186       case Toolkit::DevelButton::Property::SELECTED_VISUAL:
1187       case Toolkit::DevelButton::Property::DISABLED_SELECTED_VISUAL:
1188       case Toolkit::DevelButton::Property::DISABLED_UNSELECTED_VISUAL:
1189       {
1190         GetImplementation( button ).CreateVisualsForComponent( index, value, DepthIndex::CONTENT );
1191         break;
1192       }
1193
1194       case Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL:
1195       case Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL:
1196       case Toolkit::DevelButton::Property::DISABLED_SELECTED_BACKGROUND_VISUAL:
1197       case Toolkit::DevelButton::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL:
1198       {
1199         GetImplementation( button ).CreateVisualsForComponent( index , value, DepthIndex::BACKGROUND);
1200         break;
1201       }
1202
1203       case Toolkit::Button::Property::UNSELECTED_COLOR:
1204       {
1205         DALI_LOG_WARNING("[%s] Using deprecated Property Button::Property::UNSELECTED_COLOR instead use Button::Property::UNSELECTED_BACKGROUND_VISUAL\n", __FUNCTION__);
1206         GetImplementation( button ).SetColor( value.Get< Vector4 >(), Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL );
1207         break;
1208       }
1209
1210       case Toolkit::Button::Property::SELECTED_COLOR:
1211       {
1212         DALI_LOG_WARNING("[%s] Using deprecated Property Button::Property::SELECTED_COLOR instead use Button::Property::SELECTED_BACKGROUND_VISUAL\n", __FUNCTION__);
1213         GetImplementation( button ).SetColor( value.Get< Vector4 >(), Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL );
1214         break;
1215       }
1216
1217       case Toolkit::Button::Property::LABEL_TEXT:
1218       {
1219         DALI_LOG_WARNING("[%s] Using deprecated Property Button::Property::LABEL_TEXT instead use Button::Property::LABEL\n", __FUNCTION__);
1220         GetImplementation( button ).SetLabelText(value.Get< std::string >() );
1221         break;
1222       }
1223
1224       case Toolkit::Button::Property::LABEL:
1225       {
1226         Property::Map outTextVisualProperties;
1227         std::string textString;
1228
1229         if ( value.Get( textString ) )
1230         {
1231           DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetProperty Setting TextVisual with string[%s]\n", textString.c_str() );
1232
1233           Property::Map setPropertyMap;
1234           setPropertyMap.Add( Toolkit::Visual::Property::TYPE, Toolkit::DevelVisual::TEXT )
1235                         .Add( Toolkit::TextVisual::Property::TEXT, textString );
1236
1237           GetImplementation( button ).MergeWithExistingLabelProperties( setPropertyMap, outTextVisualProperties );
1238         }
1239         else
1240         {
1241           // Get a Property::Map from the property if possible.
1242           Property::Map* setPropertyMap = value.GetMap();
1243           if( setPropertyMap )
1244           {
1245             TextVisual::ConvertStringKeysToIndexKeys( *setPropertyMap );
1246             GetImplementation( button ).MergeWithExistingLabelProperties( *setPropertyMap, outTextVisualProperties );
1247           }
1248         }
1249
1250         if( !outTextVisualProperties.Empty() )
1251         {
1252           GetImplementation( button ).CreateVisualsForComponent( index, outTextVisualProperties, DepthIndex::CONTENT );
1253           GetImplementation( button ).RelayoutRequest();
1254         }
1255         break;
1256       }
1257
1258       case Toolkit::DevelButton::Property::LABEL_RELATIVE_ALIGNMENT:
1259       {
1260         Button::Align labelAlignment(END);
1261         Scripting::GetEnumeration< Button::Align> ( value.Get< std::string >().c_str(),
1262                                                     ALIGNMENT_TABLE, ALIGNMENT_TABLE_COUNT,
1263                                                     labelAlignment );
1264
1265         GetImplementation( button ).SetLabelAlignment( labelAlignment );
1266         GetImplementation( button ).RelayoutRequest();
1267         break;
1268       }
1269
1270       case Toolkit::DevelButton::Property::LABEL_PADDING:
1271       {
1272         Vector4 padding ( value.Get< Vector4 >() );
1273         GetImplementation( button ).SetLabelPadding( Padding( padding.x, padding.y, padding.z, padding.w ) );
1274         break;
1275       }
1276
1277       case Toolkit::DevelButton::Property::VISUAL_PADDING:
1278       {
1279         Vector4 padding ( value.Get< Vector4 >() );
1280         GetImplementation( button ).SetForegroundPadding( Padding( padding.x, padding.y, padding.z, padding.w ) );
1281         GetImplementation( button ).RelayoutRequest();
1282         break;
1283       }
1284     }
1285   }
1286 }
1287
1288 Property::Value Button::GetProperty( BaseObject* object, Property::Index propertyIndex )
1289 {
1290   Property::Value value;
1291
1292   Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) );
1293
1294   if ( button )
1295   {
1296     switch ( propertyIndex )
1297     {
1298       case Toolkit::Button::Property::DISABLED:
1299       {
1300         value = GetImplementation( button ).IsDisabled();
1301         break;
1302       }
1303
1304       case Toolkit::Button::Property::AUTO_REPEATING:
1305       {
1306         value = GetImplementation( button ).mAutoRepeating;
1307         break;
1308       }
1309
1310       case Toolkit::Button::Property::INITIAL_AUTO_REPEATING_DELAY:
1311       {
1312         value = GetImplementation( button ).mInitialAutoRepeatingDelay;
1313         break;
1314       }
1315
1316       case Toolkit::Button::Property::NEXT_AUTO_REPEATING_DELAY:
1317       {
1318         value = GetImplementation( button ).mNextAutoRepeatingDelay;
1319         break;
1320       }
1321
1322       case Toolkit::Button::Property::TOGGLABLE:
1323       {
1324         value = GetImplementation( button ).mTogglableButton;
1325         break;
1326       }
1327
1328       case Toolkit::Button::Property::SELECTED:
1329       {
1330         value = GetImplementation( button ).IsSelected();
1331         break;
1332       }
1333
1334       case Toolkit::Button::Property::UNSELECTED_STATE_IMAGE:
1335       {
1336         value = GetImplementation( button ).GetUrlForImageVisual( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL );
1337         break;
1338       }
1339
1340       case Toolkit::Button::Property::SELECTED_STATE_IMAGE:
1341       {
1342         value = GetImplementation( button ).GetUrlForImageVisual( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL );
1343         break;
1344       }
1345
1346       case Toolkit::Button::Property::DISABLED_STATE_IMAGE:
1347       {
1348         value = GetImplementation( button ).GetUrlForImageVisual( Toolkit::DevelButton::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL );
1349         break;
1350       }
1351
1352       case Toolkit::DevelButton::Property::UNSELECTED_VISUAL:
1353       case Toolkit::DevelButton::Property::SELECTED_VISUAL:
1354       case Toolkit::DevelButton::Property::DISABLED_SELECTED_VISUAL:
1355       case Toolkit::DevelButton::Property::DISABLED_UNSELECTED_VISUAL:
1356       case Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL:
1357       case Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL:
1358       case Toolkit::DevelButton::Property::DISABLED_SELECTED_BACKGROUND_VISUAL:
1359       case Toolkit::DevelButton::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL:
1360       case Toolkit::Button::Property::LABEL:
1361       {
1362         Property::Map visualProperty;
1363         if ( GetImplementation( button ).GetPropertyMapForVisual( propertyIndex, visualProperty ) )
1364         {
1365           value = visualProperty;
1366         }
1367         break;
1368       }
1369
1370       case Toolkit::Button::Property::UNSELECTED_COLOR:
1371       {
1372         value = GetImplementation( button ).GetUnselectedColor();
1373         break;
1374       }
1375
1376       case Toolkit::Button::Property::SELECTED_COLOR:
1377       {
1378         value = GetImplementation( button ).GetSelectedColor();
1379         break;
1380       }
1381
1382       case Toolkit::Button::Property::LABEL_TEXT:
1383       {
1384         value = GetImplementation( button ).GetLabelText();
1385         break;
1386       }
1387
1388       case Toolkit::DevelButton::Property::LABEL_RELATIVE_ALIGNMENT:
1389       {
1390         const char* alignment = Scripting::GetEnumerationName< Button::Align >( GetImplementation( button ).GetLabelAlignment(),
1391                                                                                 ALIGNMENT_STRING_TABLE,
1392                                                                                 ALIGNMENT_STRING_TABLE_COUNT );
1393         if( alignment )
1394         {
1395           value = std::string( alignment );
1396         }
1397
1398         break;
1399       }
1400
1401       case Toolkit::DevelButton::Property::LABEL_PADDING:
1402       {
1403         Padding padding = GetImplementation( button ).GetLabelPadding();
1404         value = Vector4( padding.x, padding.y, padding.top, padding.bottom);
1405         break;
1406       }
1407
1408       case Toolkit::DevelButton::Property::VISUAL_PADDING:
1409       {
1410         Padding padding = GetImplementation( button ).GetForegroundPadding();
1411         value = Vector4( padding.x, padding.y, padding.top, padding.bottom);
1412       }
1413     }
1414   }
1415
1416   return value;
1417 }
1418
1419 void Button::SetLabelPadding( const Padding& padding)
1420 {
1421   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetLabelPadding padding(%f,%f,%f,%f)\n", padding.left, padding.right, padding.bottom, padding.top );
1422   mLabelPadding = Padding( padding.left, padding.right, padding.bottom, padding.top );
1423   RelayoutRequest();
1424 }
1425
1426 Padding Button::GetLabelPadding()
1427 {
1428   return mLabelPadding;
1429 }
1430
1431 void Button::SetForegroundPadding( const Padding& padding)
1432 {
1433   DALI_LOG_INFO( gLogButtonFilter, Debug::Verbose, "Button::SetForegroundPadding padding(%f,%f,%f,%f)\n", padding.left, padding.right, padding.bottom, padding.top );
1434   mForegroundPadding = Padding( padding.left, padding.right, padding.bottom, padding.top );
1435   RelayoutRequest();
1436 }
1437
1438 Padding Button::GetForegroundPadding()
1439 {
1440   return mForegroundPadding;
1441 }
1442
1443 ////////////////////////////////////////////////////////////////////////
1444 // Legacy functions from Tizen 2.4 and 3.0
1445
1446 // Legacy code needed whilst Color can be set by direct Property setting ( deprecated ) instead of setting a Visual
1447 void Button::SetColor( const Vector4& color, Property::Index visualIndex )
1448 {
1449   if ( visualIndex == Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL )
1450   {
1451     mSelectedColor = color;
1452   }
1453   else
1454   {
1455     mUnselectedColor = color;
1456   }
1457
1458   Property::Map map;
1459   map[ Toolkit::Visual::Property::TYPE ] = Toolkit::Visual::COLOR;
1460   map[ Toolkit::ColorVisual::Property::MIX_COLOR ] = color;
1461
1462   CreateVisualsForComponent( visualIndex, map, DepthIndex::BACKGROUND );
1463 }
1464
1465 const Vector4 Button::GetUnselectedColor() const
1466 {
1467   return mUnselectedColor;
1468 }
1469
1470 const Vector4 Button::GetSelectedColor() const
1471 {
1472   return mSelectedColor;
1473 }
1474
1475 void Button::SetAnimationTime( float animationTime )
1476 {
1477   // Used by deprecated API
1478   mAnimationTime = animationTime;
1479 }
1480
1481 float Button::GetAnimationTime() const
1482 {
1483   // Used by deprecated API
1484   return mAnimationTime;
1485 }
1486
1487 void Button::SetLabel( Actor label )
1488 {
1489   if ( label )
1490   {
1491     Property::Value value ="";
1492     value = label.GetProperty(Toolkit::TextLabel::Property::TEXT);
1493
1494     SetLabelText( value.Get<std::string>() );
1495   }
1496 }
1497
1498 void Button::SetUnselectedImage( const std::string& filename )
1499 {
1500   SetBackgroundImage( filename );
1501 }
1502
1503 void Button::SetBackgroundImage( const std::string& filename )
1504 {
1505   if( !filename.empty() )
1506   {
1507     CreateVisualsForComponent( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL, filename, DepthIndex::BACKGROUND );
1508   }
1509   else
1510   {
1511     UnregisterVisual( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL );
1512   }
1513 }
1514
1515 void Button::SetSelectedImage( const std::string& filename )
1516 {
1517     SetSelectedBackgroundImage( filename );
1518 }
1519
1520 void Button::SetSelectedBackgroundImage( const std::string& filename )
1521 {
1522   if( !filename.empty() )
1523   {
1524     CreateVisualsForComponent( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL, filename, DepthIndex::BACKGROUND );
1525   }
1526   else
1527   {
1528     UnregisterVisual( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL );
1529   }
1530 }
1531
1532 void Button::SetDisabledBackgroundImage( const std::string& filename )
1533 {
1534   if( !filename.empty() )
1535   {
1536     CreateVisualsForComponent( Toolkit::DevelButton::Property::DISABLED_UNSELECTED_BACKGROUND_VISUAL, filename, DepthIndex::BACKGROUND );
1537   }
1538 }
1539
1540 void Button::SetDisabledImage( const std::string& filename )
1541 {
1542   if( !filename.empty() )
1543   {
1544     CreateVisualsForComponent( Toolkit::DevelButton::Property::DISABLED_UNSELECTED_VISUAL, filename, DepthIndex::CONTENT );
1545   }
1546 }
1547
1548 void Button::SetDisabledSelectedImage( const std::string& filename )
1549 {
1550   if( !filename.empty() )
1551   {
1552     CreateVisualsForComponent( Toolkit::DevelButton::Property::DISABLED_SELECTED_VISUAL, filename, DepthIndex::CONTENT );
1553   }
1554 }
1555
1556 // Used by Deprecated Properties which don't use the Visual Property maps for setting and getting
1557 std::string Button::GetUrlForImageVisual( const Property::Index index ) const
1558 {
1559   Toolkit::Visual::Base visual = GetVisual( index );
1560   std::string result;
1561
1562   if ( visual )
1563   {
1564     Dali::Property::Map retreivedMap;
1565     visual.CreatePropertyMap( retreivedMap );
1566     Property::Value* value = retreivedMap.Find(  Toolkit::ImageVisual::Property::URL,  Property::STRING );
1567     if ( value )
1568     {
1569       result = value->Get<std::string>();
1570     }
1571   }
1572
1573   return result;
1574 }
1575
1576 // Below functions DEPRECATED_1_0.50 - Return empty Actors
1577
1578 namespace
1579 {
1580 std::string GetUrlFromImage( Image& image )
1581 {
1582   ResourceImage resourceImage = ResourceImage::DownCast( image );
1583
1584   std::string imageUrl;
1585
1586   if ( resourceImage )
1587   {
1588     imageUrl = resourceImage.GetUrl();
1589   }
1590   return imageUrl;
1591 }
1592
1593 } // namespace
1594
1595
1596 void Button::SetButtonImage( Image image )
1597 {
1598   DALI_LOG_WARNING("Button::SetButtonImage @DEPRECATED_1_0.50\n");
1599   SetUnselectedImage( GetUrlFromImage( image ) );
1600   mSetButtonImage = image;
1601 }
1602
1603 void Button::SetSelectedImage( Image image )
1604 {
1605   DALI_LOG_WARNING("Button::SetSelectedImage @DEPRECATED_1_0.50\n");
1606   SetSelectedImage( GetUrlFromImage( image ) );
1607   mSetSelectedImage = image;
1608 }
1609
1610 Actor Button::GetButtonImage() const
1611 {
1612   // When deprecated ImageView API removed then this button API can be removed too.
1613   DALI_LOG_WARNING("Button::GetButtonImage @DEPRECATED_1_0.50\n");
1614
1615   Actor imageView;
1616
1617   if ( mSetButtonImage )
1618   {
1619     imageView = Toolkit::ImageView::New( mSetButtonImage );
1620   }
1621   else
1622   {
1623     ResourceImage image = ResourceImage::New( GetUrlForImageVisual( Toolkit::DevelButton::Property::UNSELECTED_BACKGROUND_VISUAL ) );
1624     imageView = Toolkit::ImageView::New( image );
1625   }
1626
1627   return imageView;
1628 }
1629
1630 Actor Button::GetSelectedImage() const
1631 {
1632   // When deprecated ImageView API removed then this button API can be removed too.
1633   DALI_LOG_WARNING("Button::GetSelectedImage @DEPRECATED_1_0.50\n");
1634
1635   Actor imageView;
1636
1637   if ( mSetSelectedImage )
1638   {
1639     imageView = Toolkit::ImageView::New( mSetSelectedImage );
1640   }
1641   else
1642   {
1643     ResourceImage image = ResourceImage::New( GetUrlForImageVisual( Toolkit::DevelButton::Property::SELECTED_BACKGROUND_VISUAL ) );
1644     imageView = Toolkit::ImageView::New( image );
1645   }
1646   return imageView;
1647 }
1648
1649 } // namespace Internal
1650
1651 } // namespace Toolkit
1652
1653 } // namespace Dali