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