Merge "Changes after Custom actor impl extension, cleanup, extension and test cases...
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / public-api / controls / control-impl.cpp
1 /*
2  * Copyright (c) 2015 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/actors/image-actor.h>
26 #include <dali/devel-api/actors/mesh-actor.h>
27 #include <dali/public-api/animation/constraint.h>
28 #include <dali/public-api/animation/constraints.h>
29 #include <dali/devel-api/geometry/mesh.h>
30 #include <dali/public-api/object/type-registry.h>
31 #include <dali/devel-api/object/type-registry-helper.h>
32 #include <dali/devel-api/scripting/scripting.h>
33 #include <dali/public-api/size-negotiation/relayout-container.h>
34 #include <dali/integration-api/debug.h>
35
36 // INTERNAL INCLUDES
37 #include <dali-toolkit/public-api/focus-manager/keyinput-focus-manager.h>
38 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
39 #include <dali-toolkit/public-api/controls/control.h>
40 #include <dali-toolkit/devel-api/styling/style-manager.h>
41 #include <dali-toolkit/internal/styling/style-manager-impl.h>
42
43 namespace Dali
44 {
45
46 namespace Toolkit
47 {
48
49 namespace
50 {
51
52 const float BACKGROUND_ACTOR_Z_POSITION( -0.1f );
53
54 BaseHandle Create()
55 {
56   return Internal::Control::New();
57 }
58
59 // Setup signals and actions using the type-registry.
60 DALI_TYPE_REGISTRATION_BEGIN( Control, CustomActor, Create );
61
62 // Note: Properties are registered separately below.
63
64 DALI_SIGNAL_REGISTRATION( Toolkit, Control, "key-event",              SIGNAL_KEY_EVENT              )
65 DALI_SIGNAL_REGISTRATION( Toolkit, Control, "key-input-focus-gained", SIGNAL_KEY_INPUT_FOCUS_GAINED )
66 DALI_SIGNAL_REGISTRATION( Toolkit, Control, "key-input-focus-lost",   SIGNAL_KEY_INPUT_FOCUS_LOST   )
67 DALI_SIGNAL_REGISTRATION( Toolkit, Control, "tapped",                 SIGNAL_TAPPED                 )
68 DALI_SIGNAL_REGISTRATION( Toolkit, Control, "panned",                 SIGNAL_PANNED                 )
69 DALI_SIGNAL_REGISTRATION( Toolkit, Control, "pinched",                SIGNAL_PINCHED                )
70 DALI_SIGNAL_REGISTRATION( Toolkit, Control, "long-pressed",           SIGNAL_LONG_PRESSED           )
71
72 DALI_ACTION_REGISTRATION( Toolkit, Control, "control-activated",      ACTION_CONTROL_ACTIVATED      )
73
74 DALI_TYPE_REGISTRATION_END()
75
76 /**
77  * Structure which holds information about the background of a control
78  */
79 struct Background
80 {
81   Actor actor;   ///< Either a MeshActor or an ImageActor
82   Vector4 color; ///< The color of the actor.
83
84   /**
85    * Constructor
86    */
87   Background()
88   : actor(),
89     color( Color::WHITE )
90   {
91   }
92 };
93
94 /**
95  * Creates a white coloured Mesh.
96  */
97 Mesh CreateMesh()
98 {
99   Vector3 white( Color::WHITE );
100
101   MeshData meshData;
102
103   // Create vertices with a white color (actual color is set by actor color)
104   MeshData::VertexContainer vertices(4);
105   vertices[ 0 ] = MeshData::Vertex( Vector3( -0.5f, -0.5f, 0.0f ), Vector2::ZERO, white );
106   vertices[ 1 ] = MeshData::Vertex( Vector3(  0.5f, -0.5f, 0.0f ), Vector2::ZERO, white );
107   vertices[ 2 ] = MeshData::Vertex( Vector3( -0.5f,  0.5f, 0.0f ), Vector2::ZERO, white );
108   vertices[ 3 ] = MeshData::Vertex( Vector3(  0.5f,  0.5f, 0.0f ), Vector2::ZERO, white );
109
110   // Specify all the faces
111   MeshData::FaceIndices faces;
112   faces.reserve( 6 ); // 2 triangles in Quad
113   faces.push_back( 0 ); faces.push_back( 3 ); faces.push_back( 1 );
114   faces.push_back( 0 ); faces.push_back( 2 ); faces.push_back( 3 );
115
116   // Create the mesh data from the vertices and faces
117   meshData.SetMaterial( Material::New( "ControlMaterial" ) );
118   meshData.SetVertices( vertices );
119   meshData.SetFaceIndices( faces );
120   meshData.SetHasColor( true );
121
122   return Mesh::New( meshData );
123 }
124
125 /**
126  * Sets all the required properties for the background actor.
127  *
128  * @param[in]  actor              The actor to set the properties on.
129  * @param[in]  color              The required color of the actor.
130  */
131 void SetupBackgroundActor( Actor actor, const Vector4& color )
132 {
133   actor.SetColor( color );
134   actor.SetPositionInheritanceMode( USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
135   actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
136   actor.SetZ( BACKGROUND_ACTOR_Z_POSITION );
137   actor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
138 }
139
140 /**
141  * Sets all the required properties for the background actor.
142  *
143  * @param[in]  actor              The actor to set the properties on.
144  * @param[in]  constrainingIndex  The property index to constrain the parent's size on.
145  * @param[in]  color              The required color of the actor.
146  */
147 void SetupBackgroundActorConstrained( Actor actor, Property::Index constrainingIndex, const Vector4& color )
148 {
149   actor.SetColor( color );
150   actor.SetPositionInheritanceMode( USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
151   actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
152   actor.SetZ( BACKGROUND_ACTOR_Z_POSITION );
153
154   Constraint constraint = Constraint::New<Vector3>( actor,
155                                                     constrainingIndex,
156                                                     EqualToConstraint() );
157   constraint.AddSource( ParentSource( Actor::Property::SIZE ) );
158   constraint.Apply();
159 }
160
161 } // unnamed namespace
162
163 namespace Internal
164 {
165
166 class Control::Impl : public ConnectionTracker
167 {
168 public:
169
170   // Construction & Destruction
171   Impl(Control& controlImpl)
172   : mControlImpl( controlImpl ),
173     mStyleName(""),
174     mBackground( NULL ),
175     mStartingPinchScale( NULL ),
176     mKeyEventSignal(),
177     mPinchGestureDetector(),
178     mPanGestureDetector(),
179     mTapGestureDetector(),
180     mLongPressGestureDetector(),
181     mFlags( Control::ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ),
182     mIsKeyboardNavigationSupported( false ),
183     mIsKeyboardFocusGroup( false )
184   {
185   }
186
187   ~Impl()
188   {
189     // All gesture detectors will be destroyed so no need to disconnect.
190     delete mBackground;
191     delete mStartingPinchScale;
192   }
193
194   // Gesture Detection Methods
195
196   void PinchDetected(Actor actor, const PinchGesture& pinch)
197   {
198     mControlImpl.OnPinch(pinch);
199   }
200
201   void PanDetected(Actor actor, const PanGesture& pan)
202   {
203     mControlImpl.OnPan(pan);
204   }
205
206   void TapDetected(Actor actor, const TapGesture& tap)
207   {
208     mControlImpl.OnTap(tap);
209   }
210
211   void LongPressDetected(Actor actor, const LongPressGesture& longPress)
212   {
213     mControlImpl.OnLongPress(longPress);
214   }
215
216   // Background Methods
217
218   /**
219    * Only creates an instance of the background if we actually use it.
220    * @return A reference to the Background structure.
221    */
222   Background& GetBackground()
223   {
224     if ( !mBackground )
225     {
226       mBackground = new Background;
227     }
228     return *mBackground;
229   }
230
231   // Properties
232
233   /**
234    * Called when a property of an object of this type is set.
235    * @param[in] object The object whose property is set.
236    * @param[in] index The property index.
237    * @param[in] value The new property value.
238    */
239   static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
240   {
241     Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
242
243     if ( control )
244     {
245       Control& controlImpl( GetImplementation( control ) );
246
247       switch ( index )
248       {
249         case Toolkit::Control::Property::STYLE_NAME:
250         {
251           controlImpl.SetStyleName( value.Get< std::string >() );
252           break;
253         }
254
255         case Toolkit::Control::Property::BACKGROUND_COLOR:
256         {
257           controlImpl.SetBackgroundColor( value.Get< Vector4 >() );
258           break;
259         }
260
261         case Toolkit::Control::Property::BACKGROUND_IMAGE:
262         {
263           if ( value.HasKey( "image" ) )
264           {
265             Property::Map imageMap = value.GetValue( "image" ).Get< Property::Map >();
266             Image image = Scripting::NewImage( imageMap );
267
268             if ( image )
269             {
270               controlImpl.SetBackgroundImage( image );
271             }
272           }
273           else if ( value.Get< Property::Map >().Empty() )
274           {
275             // An empty map means the background is no longer required
276             controlImpl.ClearBackground();
277           }
278           break;
279         }
280
281         case Toolkit::Control::Property::KEY_INPUT_FOCUS:
282         {
283           if ( value.Get< bool >() )
284           {
285             controlImpl.SetKeyInputFocus();
286           }
287           else
288           {
289             controlImpl.ClearKeyInputFocus();
290           }
291           break;
292         }
293       }
294     }
295   }
296
297   /**
298    * Called to retrieve a property of an object of this type.
299    * @param[in] object The object whose property is to be retrieved.
300    * @param[in] index The property index.
301    * @return The current value of the property.
302    */
303   static Property::Value GetProperty( BaseObject* object, Property::Index index )
304   {
305     Property::Value value;
306
307     Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
308
309     if ( control )
310     {
311       Control& controlImpl( GetImplementation( control ) );
312
313       switch ( index )
314       {
315         case Toolkit::Control::Property::STYLE_NAME:
316         {
317           value = controlImpl.GetStyleName();
318           break;
319         }
320
321         case Toolkit::Control::Property::BACKGROUND_COLOR:
322         {
323           value = controlImpl.GetBackgroundColor();
324           break;
325         }
326
327         case Toolkit::Control::Property::BACKGROUND_IMAGE:
328         {
329           Property::Map map;
330
331           Background* back = controlImpl.mImpl->mBackground;
332           if( back )
333           {
334             ImageActor imageActor = ImageActor::DownCast( back->actor );
335             if ( imageActor )
336             {
337               Image image = imageActor.GetImage();
338               Property::Map imageMap;
339               Scripting::CreatePropertyMap( image, imageMap );
340               map[ "image" ] = imageMap;
341             }
342           }
343
344           value = map;
345           break;
346         }
347
348         case Toolkit::Control::Property::KEY_INPUT_FOCUS:
349         {
350           value = controlImpl.HasKeyInputFocus();
351           break;
352         }
353       }
354     }
355
356     return value;
357   }
358
359   // Data
360
361   Control& mControlImpl;
362   std::string mStyleName;
363   Background* mBackground;           ///< Only create the background if we use it
364   Vector3* mStartingPinchScale;      ///< The scale when a pinch gesture starts, TODO: consider removing this
365   Toolkit::Control::KeyEventSignalType mKeyEventSignal;
366   Toolkit::Control::KeyInputFocusSignalType mKeyInputFocusGainedSignal;
367   Toolkit::Control::KeyInputFocusSignalType mKeyInputFocusLostSignal;
368
369   // Gesture Detection
370   PinchGestureDetector mPinchGestureDetector;
371   PanGestureDetector mPanGestureDetector;
372   TapGestureDetector mTapGestureDetector;
373   LongPressGestureDetector mLongPressGestureDetector;
374
375   ControlBehaviour mFlags :CONTROL_BEHAVIOUR_FLAG_COUNT;    ///< Flags passed in from constructor.
376   bool mIsKeyboardNavigationSupported :1;  ///< Stores whether keyboard navigation is supported by the control.
377   bool mIsKeyboardFocusGroup :1;           ///< Stores whether the control is a focus group.
378
379   // Properties - these need to be members of Internal::Control::Impl as they need to function within this class.
380   static PropertyRegistration PROPERTY_1;
381   static PropertyRegistration PROPERTY_2;
382   static PropertyRegistration PROPERTY_3;
383   static PropertyRegistration PROPERTY_4;
384 };
385
386 // Properties registered without macro to use specific member variables.
387 PropertyRegistration Control::Impl::PROPERTY_1( typeRegistration, "style-name",       Toolkit::Control::Property::STYLE_NAME,       Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
388 PropertyRegistration Control::Impl::PROPERTY_2( typeRegistration, "background-color", Toolkit::Control::Property::BACKGROUND_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
389 PropertyRegistration Control::Impl::PROPERTY_3( typeRegistration, "background-image", Toolkit::Control::Property::BACKGROUND_IMAGE, Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
390 PropertyRegistration Control::Impl::PROPERTY_4( typeRegistration, "key-input-focus",  Toolkit::Control::Property::KEY_INPUT_FOCUS,  Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
391
392 Toolkit::Control Control::New()
393 {
394   // Create the implementation, temporarily owned on stack
395   IntrusivePtr<Control> controlImpl = new Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) );
396
397   // Pass ownership to handle
398   Toolkit::Control handle( *controlImpl );
399
400   // Second-phase init of the implementation
401   // This can only be done after the CustomActor connection has been made...
402   controlImpl->Initialize();
403
404   return handle;
405 }
406
407 Control::~Control()
408 {
409   delete mImpl;
410 }
411
412 void Control::SetKeyInputFocus()
413 {
414   if( Self().OnStage() )
415   {
416     Toolkit::KeyInputFocusManager::Get().SetFocus(Toolkit::Control::DownCast(Self()));
417   }
418 }
419
420 bool Control::HasKeyInputFocus()
421 {
422   bool result = false;
423   if( Self().OnStage() )
424   {
425     result = Toolkit::KeyInputFocusManager::Get().IsKeyboardListener(Toolkit::Control::DownCast(Self()));
426   }
427   return result;
428 }
429
430 void Control::ClearKeyInputFocus()
431 {
432   if( Self().OnStage() )
433   {
434     Toolkit::KeyInputFocusManager::Get().RemoveFocus(Toolkit::Control::DownCast(Self()));
435   }
436 }
437
438 PinchGestureDetector Control::GetPinchGestureDetector() const
439 {
440   return mImpl->mPinchGestureDetector;
441 }
442
443 PanGestureDetector Control::GetPanGestureDetector() const
444 {
445   return mImpl->mPanGestureDetector;
446 }
447
448 TapGestureDetector Control::GetTapGestureDetector() const
449 {
450   return mImpl->mTapGestureDetector;
451 }
452
453 LongPressGestureDetector Control::GetLongPressGestureDetector() const
454 {
455   return mImpl->mLongPressGestureDetector;
456 }
457
458 void Control::SetStyleName( const std::string& styleName )
459 {
460   if( styleName != mImpl->mStyleName )
461   {
462     mImpl->mStyleName = styleName;
463
464     // Apply new style
465     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
466     GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
467   }
468 }
469
470 const std::string& Control::GetStyleName() const
471 {
472   return mImpl->mStyleName;
473 }
474
475 void Control::SetBackgroundColor( const Vector4& color )
476 {
477   Background& background( mImpl->GetBackground() );
478
479   if ( background.actor )
480   {
481     // Just set the actor color
482     background.actor.SetColor( color );
483   }
484   else
485   {
486     // Create Mesh Actor
487     MeshActor meshActor = MeshActor::New( CreateMesh() );
488
489     SetupBackgroundActorConstrained( meshActor, Actor::Property::SCALE, color );
490
491     // Set the background actor before adding so that we do not inform deriving classes
492     background.actor = meshActor;
493     Self().Add( meshActor );
494   }
495
496   background.color = color;
497 }
498
499 Vector4 Control::GetBackgroundColor() const
500 {
501   if ( mImpl->mBackground )
502   {
503     return mImpl->mBackground->color;
504   }
505   return Color::TRANSPARENT;
506 }
507
508 void Control::SetBackgroundImage( Image image )
509 {
510   Background& background( mImpl->GetBackground() );
511
512   if ( background.actor )
513   {
514     // Remove Current actor, unset AFTER removal so that we do not inform deriving classes
515     Self().Remove( background.actor );
516     background.actor.Reset();
517   }
518
519   ImageActor imageActor = ImageActor::New( image );
520   SetupBackgroundActor( imageActor, background.color );
521
522   // Set the background actor before adding so that we do not inform derived classes
523   background.actor = imageActor;
524   Self().Add( imageActor );
525 }
526
527 void Control::ClearBackground()
528 {
529   if ( mImpl->mBackground )
530   {
531     Background& background( mImpl->GetBackground() );
532     Self().Remove( background.actor );
533
534     delete mImpl->mBackground;
535     mImpl->mBackground = NULL;
536   }
537 }
538
539 void Control::SetKeyboardNavigationSupport(bool isSupported)
540 {
541   mImpl->mIsKeyboardNavigationSupported = isSupported;
542 }
543
544 bool Control::IsKeyboardNavigationSupported()
545 {
546   return mImpl->mIsKeyboardNavigationSupported;
547 }
548
549 void Control::Activate()
550 {
551   // Inform deriving classes
552   OnAccessibilityActivated();
553 }
554
555 void Control::OnAccessibilityActivated()
556 {
557 }
558
559 bool Control::OnAccessibilityPan(PanGesture gesture)
560 {
561   return false; // Accessibility pan gesture is not handled by default
562 }
563
564 bool Control::OnAccessibilityTouch(const TouchEvent& touchEvent)
565 {
566   return false; // Accessibility touch event is not handled by default
567 }
568
569 bool Control::OnAccessibilityValueChange(bool isIncrease)
570 {
571   return false; // Accessibility value change action is not handled by default
572 }
573
574 void Control::SetAsKeyboardFocusGroup(bool isFocusGroup)
575 {
576   mImpl->mIsKeyboardFocusGroup = isFocusGroup;
577
578   // The following line will be removed when the deprecated API in KeyboardFocusManager is deleted
579   Toolkit::KeyboardFocusManager::Get().SetAsFocusGroup(Self(), isFocusGroup);
580 }
581
582 bool Control::IsKeyboardFocusGroup()
583 {
584   return Toolkit::KeyboardFocusManager::Get().IsFocusGroup(Self());
585 }
586
587 Actor Control::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
588 {
589   return Actor();
590 }
591
592 void Control::OnKeyboardFocusChangeCommitted(Actor commitedFocusableActor)
593 {
594 }
595
596 bool Control::DoAction(BaseObject* object, const std::string& actionName, const PropertyValueContainer& attributes)
597 {
598   bool ret = false;
599
600   if( object && ( 0 == strcmp( actionName.c_str(), ACTION_CONTROL_ACTIVATED ) ) )
601   {
602     Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
603     if( control )
604     {
605       // if cast succeeds there is an implementation so no need to check
606       GetImplementation( control ).OnAccessibilityActivated();
607     }
608   }
609
610   return ret;
611 }
612
613 bool Control::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
614 {
615   Dali::BaseHandle handle( object );
616
617   bool connected( false );
618   Toolkit::Control control = Toolkit::Control::DownCast( handle );
619   if ( control )
620   {
621     Control& controlImpl( GetImplementation( control ) );
622     connected = true;
623
624     if ( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_EVENT ) )
625     {
626       controlImpl.KeyEventSignal().Connect( tracker, functor );
627     }
628     else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED ) )
629     {
630       controlImpl.KeyInputFocusGainedSignal().Connect( tracker, functor );
631     }
632     else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST ) )
633     {
634       controlImpl.KeyInputFocusLostSignal().Connect( tracker, functor );
635     }
636     else if( 0 == strcmp( signalName.c_str(), SIGNAL_TAPPED ) )
637     {
638       controlImpl.EnableGestureDetection( Gesture::Tap );
639       controlImpl.GetTapGestureDetector().DetectedSignal().Connect( tracker, functor );
640     }
641     else if( 0 == strcmp( signalName.c_str(), SIGNAL_PANNED ) )
642     {
643       controlImpl.EnableGestureDetection( Gesture::Pan );
644       controlImpl.GetPanGestureDetector().DetectedSignal().Connect( tracker, functor );
645     }
646     else if( 0 == strcmp( signalName.c_str(), SIGNAL_PINCHED ) )
647     {
648       controlImpl.EnableGestureDetection( Gesture::Pinch );
649       controlImpl.GetPinchGestureDetector().DetectedSignal().Connect( tracker, functor );
650     }
651     else if( 0 == strcmp( signalName.c_str(), SIGNAL_LONG_PRESSED ) )
652     {
653       controlImpl.EnableGestureDetection( Gesture::LongPress );
654       controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect( tracker, functor );
655     }
656     else
657     {
658       // signalName does not match any signal
659       connected = false;
660     }
661   }
662   return connected;
663 }
664
665 Toolkit::Control::KeyEventSignalType& Control::KeyEventSignal()
666 {
667   return mImpl->mKeyEventSignal;
668 }
669
670 Toolkit::Control::KeyInputFocusSignalType& Control:: KeyInputFocusGainedSignal()
671 {
672   return mImpl->mKeyInputFocusGainedSignal;
673 }
674
675 Toolkit::Control::KeyInputFocusSignalType& Control:: KeyInputFocusLostSignal()
676 {
677   return mImpl->mKeyInputFocusLostSignal;
678 }
679
680 bool Control::EmitKeyEventSignal( const KeyEvent& event )
681 {
682   // Guard against destruction during signal emission
683   Dali::Toolkit::Control handle( GetOwner() );
684
685   bool consumed = false;
686
687   // signals are allocated dynamically when someone connects
688   if ( !mImpl->mKeyEventSignal.Empty() )
689   {
690     consumed = mImpl->mKeyEventSignal.Emit( handle, event );
691   }
692
693   if (!consumed)
694   {
695     // Notification for derived classes
696     consumed = OnKeyEvent(event);
697   }
698
699   return consumed;
700 }
701
702 Control::Control( ControlBehaviour behaviourFlags )
703 : CustomActorImpl( static_cast< ActorFlags >( behaviourFlags ) ),
704   mImpl(new Impl(*this))
705 {
706   mImpl->mFlags = behaviourFlags;
707 }
708
709 void Control::Initialize()
710 {
711   if( mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS )
712   {
713     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
714
715     // Register for style changes
716     styleManager.StyleChangeSignal().Connect( this, &Control::OnStyleChange );
717
718     // SetTheme
719     GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
720   }
721
722   if( mImpl->mFlags & REQUIRES_KEYBOARD_NAVIGATION_SUPPORT )
723   {
724     SetKeyboardNavigationSupport( true );
725   }
726
727   // Calling deriving classes
728   OnInitialize();
729 }
730
731 void Control::EnableGestureDetection(Gesture::Type type)
732 {
733   if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
734   {
735     mImpl->mPinchGestureDetector = PinchGestureDetector::New();
736     mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
737     mImpl->mPinchGestureDetector.Attach(Self());
738   }
739
740   if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
741   {
742     mImpl->mPanGestureDetector = PanGestureDetector::New();
743     mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
744     mImpl->mPanGestureDetector.Attach(Self());
745   }
746
747   if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
748   {
749     mImpl->mTapGestureDetector = TapGestureDetector::New();
750     mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
751     mImpl->mTapGestureDetector.Attach(Self());
752   }
753
754   if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
755   {
756     mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
757     mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
758     mImpl->mLongPressGestureDetector.Attach(Self());
759   }
760 }
761
762 void Control::DisableGestureDetection(Gesture::Type type)
763 {
764   if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
765   {
766     mImpl->mPinchGestureDetector.Detach(Self());
767     mImpl->mPinchGestureDetector.Reset();
768   }
769
770   if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
771   {
772     mImpl->mPanGestureDetector.Detach(Self());
773     mImpl->mPanGestureDetector.Reset();
774   }
775
776   if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
777   {
778     mImpl->mTapGestureDetector.Detach(Self());
779     mImpl->mTapGestureDetector.Reset();
780   }
781
782   if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
783   {
784     mImpl->mLongPressGestureDetector.Detach(Self());
785     mImpl->mLongPressGestureDetector.Reset();
786   }
787 }
788
789 void Control::OnInitialize()
790 {
791 }
792
793 void Control::OnControlStageConnection()
794 {
795 }
796
797 void Control::OnControlStageDisconnection()
798 {
799 }
800
801 void Control::OnControlChildAdd( Actor& child )
802 {
803 }
804
805 void Control::OnControlChildRemove( Actor& child )
806 {
807 }
808
809 void Control::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
810 {
811   // By default the control is only interested in theme (not font) changes
812   if( change == StyleChange::THEME_CHANGE )
813   {
814     GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
815   }
816 }
817
818 void Control::OnPinch(const PinchGesture& pinch)
819 {
820   if( !( mImpl->mStartingPinchScale ) )
821   {
822     // lazy allocate
823     mImpl->mStartingPinchScale = new Vector3;
824   }
825
826   if( pinch.state == Gesture::Started )
827   {
828     *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale();
829   }
830
831   Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale );
832 }
833
834 void Control::OnPan( const PanGesture& pan )
835 {
836 }
837
838 void Control::OnTap(const TapGesture& tap)
839 {
840 }
841
842 void Control::OnLongPress( const LongPressGesture& longPress )
843 {
844 }
845
846 void Control::OnControlSizeSet( const Vector3& size )
847 {
848 }
849
850 void Control::EmitKeyInputFocusSignal( bool focusGained )
851 {
852   Dali::Toolkit::Control handle( GetOwner() );
853
854   if ( focusGained )
855   {
856      // signals are allocated dynamically when someone connects
857      if ( !mImpl->mKeyInputFocusGainedSignal.Empty() )
858      {
859       mImpl->mKeyInputFocusGainedSignal.Emit( handle );
860      }
861   }
862   else
863   {
864     // signals are allocated dynamically when someone connects
865     if ( !mImpl->mKeyInputFocusLostSignal.Empty() )
866     {
867       mImpl->mKeyInputFocusLostSignal.Emit( handle );
868     }
869   }
870 }
871
872 void Control::OnKeyInputFocusGained()
873 {
874   EmitKeyInputFocusSignal( true );
875 }
876
877 void Control::OnKeyInputFocusLost()
878 {
879   EmitKeyInputFocusSignal( false );
880 }
881
882 void Control::OnStageConnection()
883 {
884   // Notify derived classes.
885   OnControlStageConnection();
886 }
887
888 void Control::OnStageDisconnection()
889 {
890   // Notify derived classes
891   OnControlStageDisconnection();
892 }
893
894 void Control::OnChildAdd(Actor& child)
895 {
896   // If this is the background actor, then we do not want to relayout or inform deriving classes
897   if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
898   {
899     return;
900   }
901
902   // Notify derived classes.
903   OnControlChildAdd( child );
904 }
905
906 void Control::OnChildRemove(Actor& child)
907 {
908   // If this is the background actor, then we do not want to relayout or inform deriving classes
909   if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
910   {
911     return;
912   }
913
914   // Notify derived classes.
915   OnControlChildRemove( child );
916 }
917
918 void Control::OnSizeSet(const Vector3& targetSize)
919 {
920   // Background is resized through size negotiation
921
922   // Notify derived classes.
923   OnControlSizeSet( targetSize );
924 }
925
926 void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
927 {
928   // @todo size negotiate background to new size, animate as well?
929 }
930
931 bool Control::OnTouchEvent(const TouchEvent& event)
932 {
933   return false; // Do not consume
934 }
935
936 bool Control::OnHoverEvent(const HoverEvent& event)
937 {
938   return false; // Do not consume
939 }
940
941 bool Control::OnKeyEvent(const KeyEvent& event)
942 {
943   return false; // Do not consume
944 }
945
946 bool Control::OnMouseWheelEvent(const MouseWheelEvent& event)
947 {
948   return false; // Do not consume
949 }
950
951 void Control::OnRelayout( const Vector2& size, RelayoutContainer& container )
952 {
953   for( unsigned int i = 0, numChildren = Self().GetChildCount(); i < numChildren; ++i )
954   {
955     container.Add( Self().GetChildAt( i ), size );
956   }
957 }
958
959 void Control::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
960 {
961 }
962
963 Vector3 Control::GetNaturalSize()
964 {
965   if( mImpl->mBackground )
966   {
967     Actor actor = mImpl->mBackground->actor;
968     if( actor )
969     {
970       return actor.GetNaturalSize();
971     }
972   }
973   return Vector3();
974 }
975
976 float Control::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
977 {
978   return CalculateChildSizeBase( child, dimension );
979 }
980
981 float Control::GetHeightForWidth( float width )
982 {
983   if( mImpl->mBackground )
984   {
985     Actor actor = mImpl->mBackground->actor;
986     if( actor )
987     {
988       return actor.GetHeightForWidth( width );
989     }
990   }
991   return GetHeightForWidthBase( width );
992 }
993
994 float Control::GetWidthForHeight( float height )
995 {
996   if( mImpl->mBackground )
997   {
998     Actor actor = mImpl->mBackground->actor;
999     if( actor )
1000     {
1001       return actor.GetWidthForHeight( height );
1002     }
1003   }
1004   return GetWidthForHeightBase( height );
1005 }
1006
1007 bool Control::RelayoutDependentOnChildren( Dimension::Type dimension )
1008 {
1009   return RelayoutDependentOnChildrenBase( dimension );
1010 }
1011
1012 void Control::OnCalculateRelayoutSize( Dimension::Type dimension )
1013 {
1014 }
1015
1016 void Control::OnLayoutNegotiated( float size, Dimension::Type dimension )
1017 {
1018 }
1019
1020 void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
1021 {
1022   mImpl->SignalConnected( slotObserver, callback );
1023 }
1024
1025 void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
1026 {
1027   mImpl->SignalDisconnected( slotObserver, callback );
1028 }
1029
1030 Control& GetImplementation( Dali::Toolkit::Control& handle )
1031 {
1032   CustomActorImpl& customInterface = handle.GetImplementation();
1033   // downcast to control
1034   Control& impl = dynamic_cast< Internal::Control& >( customInterface );
1035   return impl;
1036 }
1037
1038 const Control& GetImplementation( const Dali::Toolkit::Control& handle )
1039 {
1040   const CustomActorImpl& customInterface = handle.GetImplementation();
1041   // downcast to control
1042   const Control& impl = dynamic_cast< const Internal::Control& >( customInterface );
1043   return impl;
1044 }
1045
1046 } // namespace Internal
1047
1048 } // namespace Toolkit
1049
1050 } // namespace Dali