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