c731c0dd5b6e6a1b10a25c22e88baada56588410
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / public-api / controls / control-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 <dali-toolkit/public-api/controls/control-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cstring> // for strcmp
23 #include <limits>
24 #include <stack>
25 #include <dali/public-api/animation/constraint.h>
26 #include <dali/public-api/animation/constraints.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/rendering/renderer.h>
30 #include <dali/public-api/size-negotiation/relayout-container.h>
31 #include <dali/devel-api/common/owner-container.h>
32 #include <dali/devel-api/object/handle-devel.h>
33 #include <dali/devel-api/scripting/scripting.h>
34 #include <dali/integration-api/debug.h>
35
36 // INTERNAL INCLUDES
37 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
38 #include <dali-toolkit/public-api/controls/control.h>
39 #include <dali-toolkit/public-api/styling/style-manager.h>
40 #include <dali-toolkit/public-api/visuals/color-visual-properties.h>
41 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
42 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
43 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
44 #include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
45 #include <dali-toolkit/internal/styling/style-manager-impl.h>
46 #include <dali-toolkit/internal/visuals/color/color-visual.h>
47 #include <dali-toolkit/internal/visuals/transition-data-impl.h>
48 #include <dali-toolkit/devel-api/align-enums.h>
49
50 namespace Dali
51 {
52
53 namespace Toolkit
54 {
55
56 namespace
57 {
58
59 #if defined(DEBUG_ENABLED)
60 Debug::Filter* gLogFilter = Debug::Filter::New( Debug::General, false, "LOG_CONTROL_VISUALS");
61 #endif
62
63 /**
64  * Struct used to store Visual within the control, index is a unique key for each visual.
65  */
66 struct RegisteredVisual
67 {
68   Property::Index index;
69   Toolkit::Visual::Base visual;
70   bool enabled;
71
72   RegisteredVisual( Property::Index aIndex, Toolkit::Visual::Base &aVisual, bool aEnabled) :
73                    index(aIndex), visual(aVisual), enabled(aEnabled) {}
74 };
75
76 struct HandleIndex
77 {
78   Handle handle; ///< a handle to the target object
79   Property::Index index; ///< The index of a property provided by the referenced object
80
81   HandleIndex( )
82   : handle(),
83     index( Property::INVALID_INDEX )
84   {
85   }
86
87   HandleIndex( Handle& handle, Property::Index index )
88   : handle( handle ),
89     index( index )
90   {
91   }
92 };
93
94
95 typedef Dali::OwnerContainer< RegisteredVisual* > RegisteredVisualContainer;
96
97 /**
98  *  Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
99  */
100 bool FindVisual( Property::Index targetIndex, RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
101 {
102   for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
103   {
104     if ( (*iter)->index ==  targetIndex )
105     {
106       return true;
107     }
108   }
109   return false;
110 }
111
112 HandleIndex GetVisualProperty(
113   Internal::Control& controlImpl,
114   RegisteredVisualContainer& visuals,
115   const std::string& visualName,
116   Property::Key propertyKey )
117 {
118 #if defined(DEBUG_ENABLED)
119   std::ostringstream oss;
120   oss << "Control::GetHandleIndex(" << visualName << ", " << propertyKey << ")" << std::endl;
121   DALI_LOG_INFO( gLogFilter, Debug::General, oss.str().c_str() );
122 #endif
123
124   // Find visualName in the control
125   RegisteredVisualContainer::Iterator iter;
126   for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
127   {
128     if ( (*iter)->visual.GetName() == visualName )
129     {
130       break;
131     }
132   }
133
134   // Does it's renderer have an associated property?
135   if( iter != visuals.End() )
136   {
137     Actor self = controlImpl.Self();
138     Property::Index index = DevelHandle::GetPropertyIndex( self, propertyKey );
139     if( index != Property::INVALID_INDEX )
140     {
141       // It's an actor property:
142       return HandleIndex( self, index );
143     }
144     else
145     {
146       // Check if it is a renderer property:
147       if( self.GetRendererCount() > 0 )
148       {
149         // @todo Need to use correct renderer index
150         Renderer renderer = self.GetRendererAt(0);
151         Property::Index index = DevelHandle::GetPropertyIndex( renderer, propertyKey );
152         if( index != Property::INVALID_INDEX )
153         {
154           // It's a renderer property:
155           return HandleIndex( renderer, index );
156         }
157       }
158       else
159       {
160         std::ostringstream oss;
161         oss << propertyKey;
162         DALI_LOG_WARNING( "Control::GetHandleIndex(%s, %s) No renderers\n", visualName.c_str(), oss.str().c_str() );
163       }
164     }
165   }
166   Handle handle;
167   return HandleIndex( handle, Property::INVALID_INDEX );
168 }
169
170 void SetDefaultTransform( Property::Map& propertyMap )
171 {
172   propertyMap.Clear();
173   propertyMap
174     .Add( Toolkit::DevelVisual::Transform::Property::OFFSET, Vector2(0.0f, 0.0f) )
175     .Add( Toolkit::DevelVisual::Transform::Property::SIZE, Vector2(1.0f, 1.0f) )
176     .Add( Toolkit::DevelVisual::Transform::Property::ORIGIN, Toolkit::Align::CENTER )
177     .Add( Toolkit::DevelVisual::Transform::Property::ANCHOR_POINT, Toolkit::Align::CENTER )
178     .Add( Toolkit::DevelVisual::Transform::Property::OFFSET_SIZE_MODE, Vector4::ZERO );
179 }
180
181 /**
182  * Creates control through type registry
183  */
184 BaseHandle Create()
185 {
186   return Internal::Control::New();
187 }
188
189 /**
190  * Performs actions as requested using the action name.
191  * @param[in] object The object on which to perform the action.
192  * @param[in] actionName The action to perform.
193  * @param[in] attributes The attributes with which to perfrom this action.
194  * @return true if action has been accepted by this control
195  */
196 const char* ACTION_ACCESSIBILITY_ACTIVATED = "accessibilityActivated";
197 static bool DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
198 {
199   bool ret = false;
200
201   if( object && ( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED ) ) )
202   {
203     Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
204     if( control )
205     {
206       // if cast succeeds there is an implementation so no need to check
207       ret = Internal::GetImplementation( control ).OnAccessibilityActivated();
208     }
209   }
210
211   return ret;
212 }
213
214 /**
215  * Connects a callback function with the object's signals.
216  * @param[in] object The object providing the signal.
217  * @param[in] tracker Used to disconnect the signal.
218  * @param[in] signalName The signal to connect to.
219  * @param[in] functor A newly allocated FunctorDelegate.
220  * @return True if the signal was connected.
221  * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
222  */
223 const char* SIGNAL_KEY_EVENT = "keyEvent";
224 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
225 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
226 const char* SIGNAL_TAPPED = "tapped";
227 const char* SIGNAL_PANNED = "panned";
228 const char* SIGNAL_PINCHED = "pinched";
229 const char* SIGNAL_LONG_PRESSED = "longPressed";
230 static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
231 {
232   Dali::BaseHandle handle( object );
233
234   bool connected( false );
235   Toolkit::Control control = Toolkit::Control::DownCast( handle );
236   if ( control )
237   {
238     Internal::Control& controlImpl( Internal::GetImplementation( control ) );
239     connected = true;
240
241     if ( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_EVENT ) )
242     {
243       controlImpl.KeyEventSignal().Connect( tracker, functor );
244     }
245     else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED ) )
246     {
247       controlImpl.KeyInputFocusGainedSignal().Connect( tracker, functor );
248     }
249     else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST ) )
250     {
251       controlImpl.KeyInputFocusLostSignal().Connect( tracker, functor );
252     }
253     else if( 0 == strcmp( signalName.c_str(), SIGNAL_TAPPED ) )
254     {
255       controlImpl.EnableGestureDetection( Gesture::Tap );
256       controlImpl.GetTapGestureDetector().DetectedSignal().Connect( tracker, functor );
257     }
258     else if( 0 == strcmp( signalName.c_str(), SIGNAL_PANNED ) )
259     {
260       controlImpl.EnableGestureDetection( Gesture::Pan );
261       controlImpl.GetPanGestureDetector().DetectedSignal().Connect( tracker, functor );
262     }
263     else if( 0 == strcmp( signalName.c_str(), SIGNAL_PINCHED ) )
264     {
265       controlImpl.EnableGestureDetection( Gesture::Pinch );
266       controlImpl.GetPinchGestureDetector().DetectedSignal().Connect( tracker, functor );
267     }
268     else if( 0 == strcmp( signalName.c_str(), SIGNAL_LONG_PRESSED ) )
269     {
270       controlImpl.EnableGestureDetection( Gesture::LongPress );
271       controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect( tracker, functor );
272     }
273   }
274   return connected;
275 }
276
277 // Setup signals and actions using the type-registry.
278 DALI_TYPE_REGISTRATION_BEGIN( Control, CustomActor, Create );
279
280 // Note: Properties are registered separately below.
281
282 SignalConnectorType registerSignal1( typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal );
283 SignalConnectorType registerSignal2( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal );
284 SignalConnectorType registerSignal3( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal );
285 SignalConnectorType registerSignal4( typeRegistration, SIGNAL_TAPPED, &DoConnectSignal );
286 SignalConnectorType registerSignal5( typeRegistration, SIGNAL_PANNED, &DoConnectSignal );
287 SignalConnectorType registerSignal6( typeRegistration, SIGNAL_PINCHED, &DoConnectSignal );
288 SignalConnectorType registerSignal7( typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal );
289
290 TypeAction registerAction( typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction );
291
292 DALI_TYPE_REGISTRATION_END()
293
294 } // unnamed namespace
295
296 namespace Internal
297 {
298
299 class Control::Impl : public ConnectionTracker
300 {
301 public:
302
303   // Construction & Destruction
304   Impl(Control& controlImpl)
305   : mControlImpl( controlImpl ),
306     mStyleName(""),
307     mBackgroundColor(Color::TRANSPARENT),
308     mStartingPinchScale( NULL ),
309     mKeyEventSignal(),
310     mPinchGestureDetector(),
311     mPanGestureDetector(),
312     mTapGestureDetector(),
313     mLongPressGestureDetector(),
314     mFlags( Control::ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
315     mIsKeyboardNavigationSupported( false ),
316     mIsKeyboardFocusGroup( false )
317   {
318   }
319
320   ~Impl()
321   {
322     // All gesture detectors will be destroyed so no need to disconnect.
323     delete mStartingPinchScale;
324   }
325
326   // Gesture Detection Methods
327
328   void PinchDetected(Actor actor, const PinchGesture& pinch)
329   {
330     mControlImpl.OnPinch(pinch);
331   }
332
333   void PanDetected(Actor actor, const PanGesture& pan)
334   {
335     mControlImpl.OnPan(pan);
336   }
337
338   void TapDetected(Actor actor, const TapGesture& tap)
339   {
340     mControlImpl.OnTap(tap);
341   }
342
343   void LongPressDetected(Actor actor, const LongPressGesture& longPress)
344   {
345     mControlImpl.OnLongPress(longPress);
346   }
347
348   // Properties
349
350   /**
351    * Called when a property of an object of this type is set.
352    * @param[in] object The object whose property is set.
353    * @param[in] index The property index.
354    * @param[in] value The new property value.
355    */
356   static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
357   {
358     Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
359
360     if ( control )
361     {
362       Control& controlImpl( GetImplementation( control ) );
363
364       switch ( index )
365       {
366         case Toolkit::Control::Property::STYLE_NAME:
367         {
368           controlImpl.SetStyleName( value.Get< std::string >() );
369           break;
370         }
371
372         case Toolkit::Control::Property::BACKGROUND_COLOR:
373         {
374           DALI_LOG_WARNING( "BACKGROUND_COLOR property is deprecated. Use BACKGROUND property instead\n" );
375           controlImpl.SetBackgroundColor( value.Get< Vector4 >() );
376           break;
377         }
378
379         case Toolkit::Control::Property::BACKGROUND_IMAGE:
380         {
381           DALI_LOG_WARNING( "BACKGROUND_IMAGE property is deprecated. Use BACKGROUND property instead\n" );
382           Image image = Scripting::NewImage( value );
383           if ( image )
384           {
385             controlImpl.SetBackgroundImage( image );
386           }
387           else
388           {
389             // An empty image means the background is no longer required
390             controlImpl.ClearBackground();
391           }
392           break;
393         }
394
395         case Toolkit::Control::Property::KEY_INPUT_FOCUS:
396         {
397           if ( value.Get< bool >() )
398           {
399             controlImpl.SetKeyInputFocus();
400           }
401           else
402           {
403             controlImpl.ClearKeyInputFocus();
404           }
405           break;
406         }
407
408         case Toolkit::Control::Property::BACKGROUND:
409         {
410           const Property::Map* map = value.GetMap();
411           if( map && !map->Empty() )
412           {
413             controlImpl.SetBackground( *map );
414           }
415           else
416           {
417             // The background is an empty property map, so we should clear the background
418             controlImpl.ClearBackground();
419           }
420           break;
421         }
422       }
423     }
424   }
425
426   /**
427    * Called to retrieve a property of an object of this type.
428    * @param[in] object The object whose property is to be retrieved.
429    * @param[in] index The property index.
430    * @return The current value of the property.
431    */
432   static Property::Value GetProperty( BaseObject* object, Property::Index index )
433   {
434     Property::Value value;
435
436     Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
437
438     if ( control )
439     {
440       Control& controlImpl( GetImplementation( control ) );
441
442       switch ( index )
443       {
444         case Toolkit::Control::Property::STYLE_NAME:
445         {
446           value = controlImpl.GetStyleName();
447           break;
448         }
449
450         case Toolkit::Control::Property::BACKGROUND_COLOR:
451         {
452           DALI_LOG_WARNING( "BACKGROUND_COLOR property is deprecated. Use BACKGROUND property instead\n" );
453           value = controlImpl.GetBackgroundColor();
454           break;
455         }
456
457         case Toolkit::Control::Property::BACKGROUND_IMAGE:
458         {
459           DALI_LOG_WARNING( "BACKGROUND_IMAGE property is deprecated. Use BACKGROUND property instead\n" );
460           Property::Map map;
461           Toolkit::Visual::Base visual = controlImpl.GetVisual( Toolkit::Control::Property::BACKGROUND );
462           if( visual )
463           {
464             visual.CreatePropertyMap( map );
465           }
466           value = map;
467           break;
468         }
469
470         case Toolkit::Control::Property::KEY_INPUT_FOCUS:
471         {
472           value = controlImpl.HasKeyInputFocus();
473           break;
474         }
475
476         case Toolkit::Control::Property::BACKGROUND:
477         {
478           Property::Map map;
479           Toolkit::Visual::Base visual = controlImpl.GetVisual( Toolkit::Control::Property::BACKGROUND );
480           if( visual )
481           {
482             visual.CreatePropertyMap( map );
483           }
484
485           value = map;
486           break;
487         }
488
489       }
490     }
491
492     return value;
493   }
494
495   // Data
496
497   Control& mControlImpl;
498   RegisteredVisualContainer mVisuals; // Stores visuals needed by the control, non trivial type so std::vector used.
499   std::string mStyleName;
500   Vector4 mBackgroundColor;                       ///< The color of the background visual
501   Vector3* mStartingPinchScale;      ///< The scale when a pinch gesture starts, TODO: consider removing this
502   Toolkit::Control::KeyEventSignalType mKeyEventSignal;
503   Toolkit::Control::KeyInputFocusSignalType mKeyInputFocusGainedSignal;
504   Toolkit::Control::KeyInputFocusSignalType mKeyInputFocusLostSignal;
505
506   // Gesture Detection
507   PinchGestureDetector mPinchGestureDetector;
508   PanGestureDetector mPanGestureDetector;
509   TapGestureDetector mTapGestureDetector;
510   LongPressGestureDetector mLongPressGestureDetector;
511
512   ControlBehaviour mFlags : CONTROL_BEHAVIOUR_FLAG_COUNT;    ///< Flags passed in from constructor.
513   bool mIsKeyboardNavigationSupported :1;  ///< Stores whether keyboard navigation is supported by the control.
514   bool mIsKeyboardFocusGroup :1;           ///< Stores whether the control is a focus group.
515
516   // Properties - these need to be members of Internal::Control::Impl as they need to function within this class.
517   static const PropertyRegistration PROPERTY_1;
518   static const PropertyRegistration PROPERTY_2;
519   static const PropertyRegistration PROPERTY_3;
520   static const PropertyRegistration PROPERTY_4;
521   static const PropertyRegistration PROPERTY_5;
522 };
523
524 // Properties registered without macro to use specific member variables.
525 const PropertyRegistration Control::Impl::PROPERTY_1( typeRegistration, "styleName",       Toolkit::Control::Property::STYLE_NAME,       Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
526 const PropertyRegistration Control::Impl::PROPERTY_2( typeRegistration, "backgroundColor", Toolkit::Control::Property::BACKGROUND_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
527 const PropertyRegistration Control::Impl::PROPERTY_3( typeRegistration, "backgroundImage", Toolkit::Control::Property::BACKGROUND_IMAGE, Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
528 const PropertyRegistration Control::Impl::PROPERTY_4( typeRegistration, "keyInputFocus",   Toolkit::Control::Property::KEY_INPUT_FOCUS,  Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
529 const PropertyRegistration Control::Impl::PROPERTY_5( typeRegistration, "background",      Toolkit::Control::Property::BACKGROUND,       Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
530
531 Toolkit::Control Control::New()
532 {
533   // Create the implementation, temporarily owned on stack
534   IntrusivePtr<Control> controlImpl = new Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) );
535
536   // Pass ownership to handle
537   Toolkit::Control handle( *controlImpl );
538
539   // Second-phase init of the implementation
540   // This can only be done after the CustomActor connection has been made...
541   controlImpl->Initialize();
542
543   return handle;
544 }
545
546 void Control::SetStyleName( const std::string& styleName )
547 {
548   if( styleName != mImpl->mStyleName )
549   {
550     mImpl->mStyleName = styleName;
551
552     // Apply new style, if stylemanager is available
553     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
554     if( styleManager )
555     {
556       GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
557     }
558   }
559 }
560
561 const std::string& Control::GetStyleName() const
562 {
563   return mImpl->mStyleName;
564 }
565
566 void Control::SetBackgroundColor( const Vector4& color )
567 {
568   mImpl->mBackgroundColor = color;
569   Property::Map map;
570   map[ Toolkit::DevelVisual::Property::TYPE ] = Toolkit::Visual::COLOR;
571   map[ Toolkit::ColorVisual::Property::MIX_COLOR ] = color;
572
573   SetBackground( map );
574 }
575
576 Vector4 Control::GetBackgroundColor() const
577 {
578   return mImpl->mBackgroundColor;
579 }
580
581 void Control::SetBackground( const Property::Map& map )
582 {
583   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( map );
584   if( visual )
585   {
586     RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual );
587     visual.SetDepthIndex( DepthIndex::BACKGROUND );
588
589     // Trigger a size negotiation request that may be needed by the new visual to relayout its contents.
590     RelayoutRequest();
591   }
592 }
593
594 void Control::SetBackgroundImage( Image image )
595 {
596   DALI_LOG_WARNING( "SetBackgroundImage is for the depreciated Property::BACKGROUND_IMAGE use SetBackground( const Property::Map& map )\n" );
597   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( image );
598   if( visual )
599   {
600     RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual );
601     visual.SetDepthIndex( DepthIndex::BACKGROUND );
602   }
603 }
604
605 void Control::ClearBackground()
606 {
607    UnregisterVisual( Toolkit::Control::Property::BACKGROUND );
608    mImpl->mBackgroundColor = Color::TRANSPARENT;
609
610    // Trigger a size negotiation request that may be needed when unregistering a visual.
611    RelayoutRequest();
612 }
613
614 void Control::EnableGestureDetection(Gesture::Type type)
615 {
616   if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
617   {
618     mImpl->mPinchGestureDetector = PinchGestureDetector::New();
619     mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
620     mImpl->mPinchGestureDetector.Attach(Self());
621   }
622
623   if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
624   {
625     mImpl->mPanGestureDetector = PanGestureDetector::New();
626     mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
627     mImpl->mPanGestureDetector.Attach(Self());
628   }
629
630   if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
631   {
632     mImpl->mTapGestureDetector = TapGestureDetector::New();
633     mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
634     mImpl->mTapGestureDetector.Attach(Self());
635   }
636
637   if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
638   {
639     mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
640     mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
641     mImpl->mLongPressGestureDetector.Attach(Self());
642   }
643 }
644
645 void Control::DisableGestureDetection(Gesture::Type type)
646 {
647   if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
648   {
649     mImpl->mPinchGestureDetector.Detach(Self());
650     mImpl->mPinchGestureDetector.Reset();
651   }
652
653   if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
654   {
655     mImpl->mPanGestureDetector.Detach(Self());
656     mImpl->mPanGestureDetector.Reset();
657   }
658
659   if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
660   {
661     mImpl->mTapGestureDetector.Detach(Self());
662     mImpl->mTapGestureDetector.Reset();
663   }
664
665   if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
666   {
667     mImpl->mLongPressGestureDetector.Detach(Self());
668     mImpl->mLongPressGestureDetector.Reset();
669   }
670 }
671
672 PinchGestureDetector Control::GetPinchGestureDetector() const
673 {
674   return mImpl->mPinchGestureDetector;
675 }
676
677 PanGestureDetector Control::GetPanGestureDetector() const
678 {
679   return mImpl->mPanGestureDetector;
680 }
681
682 TapGestureDetector Control::GetTapGestureDetector() const
683 {
684   return mImpl->mTapGestureDetector;
685 }
686
687 LongPressGestureDetector Control::GetLongPressGestureDetector() const
688 {
689   return mImpl->mLongPressGestureDetector;
690 }
691
692 void Control::SetKeyboardNavigationSupport(bool isSupported)
693 {
694   mImpl->mIsKeyboardNavigationSupported = isSupported;
695 }
696
697 bool Control::IsKeyboardNavigationSupported()
698 {
699   return mImpl->mIsKeyboardNavigationSupported;
700 }
701
702 void Control::SetKeyInputFocus()
703 {
704   if( Self().OnStage() )
705   {
706     Toolkit::KeyInputFocusManager::Get().SetFocus(Toolkit::Control::DownCast(Self()));
707   }
708 }
709
710 bool Control::HasKeyInputFocus()
711 {
712   bool result = false;
713   if( Self().OnStage() )
714   {
715     result = Toolkit::KeyInputFocusManager::Get().IsKeyboardListener(Toolkit::Control::DownCast(Self()));
716   }
717   return result;
718 }
719
720 void Control::ClearKeyInputFocus()
721 {
722   if( Self().OnStage() )
723   {
724     Toolkit::KeyInputFocusManager::Get().RemoveFocus(Toolkit::Control::DownCast(Self()));
725   }
726 }
727
728 void Control::SetAsKeyboardFocusGroup(bool isFocusGroup)
729 {
730   mImpl->mIsKeyboardFocusGroup = isFocusGroup;
731
732   // The following line will be removed when the deprecated API in KeyboardFocusManager is deleted
733   Toolkit::KeyboardFocusManager::Get().SetAsFocusGroup(Self(), isFocusGroup);
734 }
735
736 bool Control::IsKeyboardFocusGroup()
737 {
738   return Toolkit::KeyboardFocusManager::Get().IsFocusGroup(Self());
739 }
740
741 void Control::AccessibilityActivate()
742 {
743   // Inform deriving classes
744   OnAccessibilityActivated();
745 }
746
747 void Control::KeyboardEnter()
748 {
749   // Inform deriving classes
750   OnKeyboardEnter();
751 }
752
753 void Control::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual )
754 {
755   RegisterVisual( index, visual, true );
756 }
757
758 void Control::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled )
759 {
760   bool visualReplaced ( false );
761   Actor self = Self();
762
763   if( !mImpl->mVisuals.Empty() )
764   {
765     RegisteredVisualContainer::Iterator iter;
766     // Check if visual (index) is already registered.  Replace if so.
767     if ( FindVisual( index, mImpl->mVisuals, iter ) )
768     {
769       if( (*iter)->visual && self.OnStage() )
770       {
771         Toolkit::GetImplementation((*iter)->visual).SetOffStage( self );
772       }
773       (*iter)->visual = visual;
774       visualReplaced = true;
775     }
776   }
777
778   if( !visualReplaced ) // New registration entry
779   {
780     mImpl->mVisuals.PushBack( new RegisteredVisual( index, visual, enabled ) );
781   }
782
783   if( visual && self.OnStage() && enabled )
784   {
785     Toolkit::GetImplementation(visual).SetOnStage( self );
786   }
787 }
788
789 void Control::UnregisterVisual( Property::Index index )
790 {
791    RegisteredVisualContainer::Iterator iter;
792    if ( FindVisual( index, mImpl->mVisuals, iter ) )
793    {
794      Actor self( Self() );
795      Toolkit::GetImplementation((*iter)->visual).SetOffStage( self );
796      (*iter)->visual.Reset();
797      mImpl->mVisuals.Erase( iter );
798    }
799 }
800
801 Toolkit::Visual::Base Control::GetVisual( Property::Index index ) const
802 {
803   RegisteredVisualContainer::Iterator iter;
804   if ( FindVisual( index, mImpl->mVisuals, iter ) )
805   {
806     return (*iter)->visual;
807   }
808
809   return Toolkit::Visual::Base();
810 }
811
812 void Control::EnableVisual( Property::Index index, bool enable )
813 {
814   RegisteredVisualContainer::Iterator iter;
815   if ( FindVisual( index, mImpl->mVisuals, iter ) )
816   {
817     if (  (*iter)->enabled == enable )
818     {
819       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual Already enabled set (%s) \n", enable?"enabled":"disabled");
820       return;
821     }
822
823     (*iter)->enabled = enable;
824     Actor parentActor = Self();
825     if ( Self().OnStage() ) // If control not on Stage then Visual will be added when StageConnection is called.
826     {
827       if ( enable )
828       {
829         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting Visual(%d) on stage \n", index );
830         Toolkit::GetImplementation((*iter)->visual).SetOnStage( parentActor );
831       }
832       else
833       {
834         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting Visual(%d) off stage \n", index );
835         Toolkit::GetImplementation((*iter)->visual).SetOffStage( parentActor );  // No need to call if control not staged.
836       }
837     }
838   }
839 }
840
841 bool Control::IsVisualEnabled( Property::Index index ) const
842 {
843   RegisteredVisualContainer::Iterator iter;
844   if ( FindVisual( index, mImpl->mVisuals, iter ) )
845   {
846     return (*iter)->enabled;
847   }
848   return false;
849 }
850
851 Dali::Animation Control::CreateTransition( const Toolkit::TransitionData& handle )
852 {
853   Dali::Animation transition;
854   const Internal::TransitionData& transitionData = Toolkit::GetImplementation( handle );
855
856   if( transitionData.Count() > 0 )
857   {
858     // Setup a Transition from TransitionData.
859     TransitionData::Iterator end = transitionData.End();
860     for( TransitionData::Iterator iter = transitionData.Begin() ;
861          iter != end; ++iter )
862     {
863       TransitionData::Animator* animator = (*iter);
864       HandleIndex handleIndex;
865
866       // Attempt to find the object name as a child actor
867       Actor child = Self().FindChildByName( animator->objectName );
868       if( child )
869       {
870         Property::Index propertyIndex = DevelHandle::GetPropertyIndex( child, animator->propertyKey );
871         handleIndex = HandleIndex( child, propertyIndex );
872       }
873       else
874       {
875         handleIndex = GetVisualProperty( *this, mImpl->mVisuals,
876                                             animator->objectName,
877                                             animator->propertyKey );
878       }
879
880       if( handleIndex.handle && handleIndex.index != Property::INVALID_INDEX )
881       {
882         if( animator->animate == false )
883         {
884           if( animator->targetValue.GetType() != Property::NONE )
885           {
886             handleIndex.handle.SetProperty( handleIndex.index, animator->targetValue );
887           }
888         }
889         else
890         {
891           if( animator->initialValue.GetType() != Property::NONE )
892           {
893             handleIndex.handle.SetProperty( handleIndex.index, animator->initialValue );
894           }
895
896           if( ! transition )
897           {
898             // Create an animation with a default .1 second duration - the animators
899             // will automatically force it to the 'right' duration.
900             transition = Dali::Animation::New( 0.1f );
901           }
902
903           transition.AnimateTo( Property( handleIndex.handle, handleIndex.index ),
904                                 animator->targetValue,
905                                 animator->alphaFunction,
906                                 TimePeriod( animator->timePeriodDelay,
907                                             animator->timePeriodDuration ) );
908         }
909       }
910     }
911   }
912
913   return transition;
914 }
915
916 bool Control::OnAccessibilityActivated()
917 {
918   return false; // Accessibility activation is not handled by default
919 }
920
921 bool Control::OnKeyboardEnter()
922 {
923   return false; // Keyboard enter is not handled by default
924 }
925
926 bool Control::OnAccessibilityPan(PanGesture gesture)
927 {
928   return false; // Accessibility pan gesture is not handled by default
929 }
930
931 bool Control::OnAccessibilityTouch(const TouchEvent& touchEvent)
932 {
933   return false; // Accessibility touch event is not handled by default
934 }
935
936 bool Control::OnAccessibilityValueChange(bool isIncrease)
937 {
938   return false; // Accessibility value change action is not handled by default
939 }
940
941 bool Control::OnAccessibilityZoom()
942 {
943   return false; // Accessibility zoom action is not handled by default
944 }
945
946 Actor Control::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
947 {
948   return Actor();
949 }
950
951 void Control::OnKeyboardFocusChangeCommitted(Actor commitedFocusableActor)
952 {
953 }
954
955 Toolkit::Control::KeyEventSignalType& Control::KeyEventSignal()
956 {
957   return mImpl->mKeyEventSignal;
958 }
959
960 Toolkit::Control::KeyInputFocusSignalType& Control::KeyInputFocusGainedSignal()
961 {
962   return mImpl->mKeyInputFocusGainedSignal;
963 }
964
965 Toolkit::Control::KeyInputFocusSignalType& Control::KeyInputFocusLostSignal()
966 {
967   return mImpl->mKeyInputFocusLostSignal;
968 }
969
970 bool Control::EmitKeyEventSignal( const KeyEvent& event )
971 {
972   // Guard against destruction during signal emission
973   Dali::Toolkit::Control handle( GetOwner() );
974
975   bool consumed = false;
976
977   // signals are allocated dynamically when someone connects
978   if ( !mImpl->mKeyEventSignal.Empty() )
979   {
980     consumed = mImpl->mKeyEventSignal.Emit( handle, event );
981   }
982
983   if (!consumed)
984   {
985     // Notification for derived classes
986     consumed = OnKeyEvent(event);
987   }
988
989   return consumed;
990 }
991
992 Control::Control( ControlBehaviour behaviourFlags )
993 : CustomActorImpl( static_cast< ActorFlags >( behaviourFlags ) ),
994   mImpl(new Impl(*this))
995 {
996   mImpl->mFlags = behaviourFlags;
997 }
998
999 Control::~Control()
1000 {
1001   delete mImpl;
1002 }
1003
1004 void Control::Initialize()
1005 {
1006   // Call deriving classes so initialised before styling is applied to them.
1007   OnInitialize();
1008
1009   if( (mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS) ||
1010       !(mImpl->mFlags & DISABLE_STYLE_CHANGE_SIGNALS) )
1011   {
1012     Toolkit::StyleManager styleManager = StyleManager::Get();
1013
1014     // if stylemanager is available
1015     if( styleManager )
1016     {
1017       StyleManager& styleManagerImpl = GetImpl( styleManager );
1018
1019       // Register for style changes
1020       styleManagerImpl.ControlStyleChangeSignal().Connect( this, &Control::OnStyleChange );
1021
1022       // Apply the current style
1023       styleManagerImpl.ApplyThemeStyleAtInit( Toolkit::Control( GetOwner() ) );
1024     }
1025   }
1026
1027   if( mImpl->mFlags & REQUIRES_KEYBOARD_NAVIGATION_SUPPORT )
1028   {
1029     SetKeyboardNavigationSupport( true );
1030   }
1031 }
1032
1033 void Control::OnInitialize()
1034 {
1035 }
1036
1037 void Control::OnControlChildAdd( Actor& child )
1038 {
1039 }
1040
1041 void Control::OnControlChildRemove( Actor& child )
1042 {
1043 }
1044
1045 void Control::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
1046 {
1047   // By default the control is only interested in theme (not font) changes
1048   if( styleManager && change == StyleChange::THEME_CHANGE )
1049   {
1050     GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
1051   }
1052   RelayoutRequest();
1053 }
1054
1055 void Control::OnPinch(const PinchGesture& pinch)
1056 {
1057   if( !( mImpl->mStartingPinchScale ) )
1058   {
1059     // lazy allocate
1060     mImpl->mStartingPinchScale = new Vector3;
1061   }
1062
1063   if( pinch.state == Gesture::Started )
1064   {
1065     *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale();
1066   }
1067
1068   Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale );
1069 }
1070
1071 void Control::OnPan( const PanGesture& pan )
1072 {
1073 }
1074
1075 void Control::OnTap(const TapGesture& tap)
1076 {
1077 }
1078
1079 void Control::OnLongPress( const LongPressGesture& longPress )
1080 {
1081 }
1082
1083 void Control::EmitKeyInputFocusSignal( bool focusGained )
1084 {
1085   Dali::Toolkit::Control handle( GetOwner() );
1086
1087   if ( focusGained )
1088   {
1089     // signals are allocated dynamically when someone connects
1090     if ( !mImpl->mKeyInputFocusGainedSignal.Empty() )
1091     {
1092       mImpl->mKeyInputFocusGainedSignal.Emit( handle );
1093     }
1094   }
1095   else
1096   {
1097     // signals are allocated dynamically when someone connects
1098     if ( !mImpl->mKeyInputFocusLostSignal.Empty() )
1099     {
1100       mImpl->mKeyInputFocusLostSignal.Emit( handle );
1101     }
1102   }
1103 }
1104
1105 void Control::OnStageConnection( int depth )
1106 {
1107   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageConnection number of registered visuals(%d)\n",  mImpl->mVisuals.Size() );
1108
1109   for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++)
1110   {
1111     // Check whether the visual is empty and enabled
1112     if( (*iter)->visual && (*iter)->enabled )
1113     {
1114       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageConnection Setting visual(%d) on stage\n", (*iter)->index );
1115       Actor self( Self() );
1116       Toolkit::GetImplementation((*iter)->visual).SetOnStage( self );
1117     }
1118   }
1119 }
1120
1121 void Control::OnStageDisconnection()
1122 {
1123   for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++)
1124   {
1125     // Check whether the visual is empty
1126     if( (*iter)->visual )
1127     {
1128       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageDisconnection Setting visual(%d) off stage\n", (*iter)->index );
1129       Actor self( Self() );
1130       Toolkit::GetImplementation((*iter)->visual).SetOffStage( self );
1131     }
1132   }
1133 }
1134
1135 void Control::OnKeyInputFocusGained()
1136 {
1137   EmitKeyInputFocusSignal( true );
1138 }
1139
1140 void Control::OnKeyInputFocusLost()
1141 {
1142   EmitKeyInputFocusSignal( false );
1143 }
1144
1145 void Control::OnChildAdd(Actor& child)
1146 {
1147   // Notify derived classes.
1148   OnControlChildAdd( child );
1149 }
1150
1151 void Control::OnChildRemove(Actor& child)
1152 {
1153   // Notify derived classes.
1154   OnControlChildRemove( child );
1155 }
1156
1157 void Control::OnSizeSet(const Vector3& targetSize)
1158 {
1159   Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND );
1160   if( visual )
1161   {
1162     Vector2 size( targetSize );
1163     Property::Map transformMap;
1164     SetDefaultTransform( transformMap );
1165     visual.SetTransformAndSize( transformMap, size );
1166   }
1167 }
1168
1169 void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
1170 {
1171   // @todo size negotiate background to new size, animate as well?
1172 }
1173
1174 bool Control::OnTouchEvent(const TouchEvent& event)
1175 {
1176   return false; // Do not consume
1177 }
1178
1179 bool Control::OnHoverEvent(const HoverEvent& event)
1180 {
1181   return false; // Do not consume
1182 }
1183
1184 bool Control::OnKeyEvent(const KeyEvent& event)
1185 {
1186   return false; // Do not consume
1187 }
1188
1189 bool Control::OnWheelEvent(const WheelEvent& event)
1190 {
1191   return false; // Do not consume
1192 }
1193
1194 void Control::OnRelayout( const Vector2& size, RelayoutContainer& container )
1195 {
1196   for( unsigned int i = 0, numChildren = Self().GetChildCount(); i < numChildren; ++i )
1197   {
1198     container.Add( Self().GetChildAt( i ), size );
1199   }
1200
1201   Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND );
1202   if( visual )
1203   {
1204     Vector2 controlSize( size );
1205     Property::Map transformMap;
1206     SetDefaultTransform( transformMap );
1207     visual.SetTransformAndSize( transformMap, controlSize );
1208   }
1209 }
1210
1211 void Control::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1212 {
1213 }
1214
1215 Vector3 Control::GetNaturalSize()
1216 {
1217   Toolkit::Visual::Base visual = GetVisual( Toolkit::Control::Property::BACKGROUND );
1218   if( visual )
1219   {
1220     Vector2 naturalSize;
1221     visual.GetNaturalSize( naturalSize );
1222     return Vector3( naturalSize );
1223   }
1224   return Vector3::ZERO;
1225 }
1226
1227 float Control::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
1228 {
1229   return CalculateChildSizeBase( child, dimension );
1230 }
1231
1232 float Control::GetHeightForWidth( float width )
1233 {
1234   return GetHeightForWidthBase( width );
1235 }
1236
1237 float Control::GetWidthForHeight( float height )
1238 {
1239   return GetWidthForHeightBase( height );
1240 }
1241
1242 bool Control::RelayoutDependentOnChildren( Dimension::Type dimension )
1243 {
1244   return RelayoutDependentOnChildrenBase( dimension );
1245 }
1246
1247 void Control::OnCalculateRelayoutSize( Dimension::Type dimension )
1248 {
1249 }
1250
1251 void Control::OnLayoutNegotiated( float size, Dimension::Type dimension )
1252 {
1253 }
1254
1255 void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
1256 {
1257   mImpl->SignalConnected( slotObserver, callback );
1258 }
1259
1260 void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
1261 {
1262   mImpl->SignalDisconnected( slotObserver, callback );
1263 }
1264
1265 Control& GetImplementation( Dali::Toolkit::Control& handle )
1266 {
1267   CustomActorImpl& customInterface = handle.GetImplementation();
1268   // downcast to control
1269   Control& impl = dynamic_cast< Internal::Control& >( customInterface );
1270   return impl;
1271 }
1272
1273 const Control& GetImplementation( const Dali::Toolkit::Control& handle )
1274 {
1275   const CustomActorImpl& customInterface = handle.GetImplementation();
1276   // downcast to control
1277   const Control& impl = dynamic_cast< const Internal::Control& >( customInterface );
1278   return impl;
1279 }
1280
1281 } // namespace Internal
1282
1283 } // namespace Toolkit
1284
1285 } // namespace Dali