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