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