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