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