Refractor ImfManager to InputMethodContext
[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/object/type-registry-helper.h>
28 #include <dali/public-api/size-negotiation/relayout-container.h>
29 #include <dali/devel-api/scripting/scripting.h>
30 #include <dali/integration-api/debug.h>
31
32 // INTERNAL INCLUDES
33 #include <dali-toolkit/public-api/align-enumerations.h>
34 #include <dali-toolkit/public-api/controls/control.h>
35 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
36 #include <dali-toolkit/public-api/styling/style-manager.h>
37 #include <dali-toolkit/public-api/visuals/color-visual-properties.h>
38 #include <dali-toolkit/public-api/visuals/visual-properties.h>
39 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
40 #include <dali-toolkit/devel-api/controls/control-devel.h>
41 #include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
42 #include <dali-toolkit/devel-api/visuals/color-visual-properties-devel.h>
43 #include <dali-toolkit/internal/styling/style-manager-impl.h>
44 #include <dali-toolkit/internal/visuals/color/color-visual.h>
45 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
46 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
47
48 namespace Dali
49 {
50
51 namespace Toolkit
52 {
53
54 namespace Internal
55 {
56
57 namespace
58 {
59
60 #if defined(DEBUG_ENABLED)
61 Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
62 #endif
63
64 /**
65  * @brief Replace the background visual if it's a color visual with the renderIfTransparent property set as required.
66  * @param[in] controlImpl The control implementation
67  * @param[in] renderIfTransaparent Whether we should render if the color is transparent
68  */
69 void ChangeBackgroundColorVisual( Control& controlImpl, bool renderIfTransparent )
70 {
71   Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl );
72
73   Toolkit::Visual::Base backgroundVisual = controlDataImpl.GetVisual( Toolkit::Control::Property::BACKGROUND );
74   if( backgroundVisual )
75   {
76     Property::Map map;
77     backgroundVisual.CreatePropertyMap( map );
78     Property::Value* typeValue = map.Find( Toolkit::Visual::Property::TYPE );
79     if( typeValue && typeValue->Get< int >() == Toolkit::Visual::COLOR )
80     {
81       // Only change it if it's a color visual
82       map[ Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT ] = renderIfTransparent;
83       controlImpl.SetBackground( map );
84     }
85   }
86 }
87
88 /**
89  * @brief Creates a clipping renderer if required.
90  * (EG. If no renders exist and clipping is enabled).
91  * @param[in] controlImpl The control implementation.
92  */
93 void CreateClippingRenderer( Control& controlImpl )
94 {
95   // We want to add a transparent background if we do not have one for clipping.
96   Actor self( controlImpl.Self() );
97   int clippingMode = ClippingMode::DISABLED;
98   if( self.GetProperty( Actor::Property::CLIPPING_MODE ).Get( clippingMode ) )
99   {
100     switch( clippingMode )
101     {
102       case ClippingMode::CLIP_CHILDREN:
103       {
104         if( self.GetRendererCount() == 0u )
105         {
106           Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl );
107           if( controlDataImpl.mVisuals.Empty() )
108           {
109             controlImpl.SetBackgroundColor( Color::TRANSPARENT );
110           }
111           else
112           {
113             // We have visuals, check if we've set the background and re-create it to
114             // render even if transparent (only if it's a color visual)
115             ChangeBackgroundColorVisual( controlImpl, true );
116           }
117         }
118         break;
119       }
120
121       case ClippingMode::DISABLED:
122       case ClippingMode::CLIP_TO_BOUNDING_BOX:
123       {
124         // If we have a background visual, check if it's a color visual and remove the render if transparent flag
125         ChangeBackgroundColorVisual( controlImpl, false );
126         break;
127       }
128     }
129   }
130 }
131
132 /**
133  * @brief Sets Control::Property::BACKGROUND visual
134  * @param[in] controlImpl The control implementation
135  * @param[in] visual The control background visual
136  * @param[in] size The current size
137  */
138 void SetBackgroundVisual( Control::Impl& controlImpl, Toolkit::Visual::Base& visual, const Vector2& size )
139 {
140   Property::Map transformMap = Property::Map();
141
142   Vector2 newSize( 0.f, 0.f );
143   newSize.width = size.width + ( controlImpl.mPadding.start + controlImpl.mPadding.end );
144   newSize.height = size.height + ( controlImpl.mPadding.top + controlImpl.mPadding.bottom );
145
146   if( ( controlImpl.mMargin.start != 0 ) ||
147       ( controlImpl.mMargin.end != 0 ) ||
148       ( controlImpl.mMargin.top != 0 ) ||
149       ( controlImpl.mMargin.bottom != 0 ) )
150   {
151     transformMap.Add( Toolkit::Visual::Transform::Property::SIZE, newSize )
152                 .Add( Toolkit::Visual::Transform::Property::SIZE_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) )
153                 .Add( Toolkit::Visual::Transform::Property::OFFSET, Vector2( controlImpl.mMargin.start, controlImpl.mMargin.top ) )
154                 .Add( Toolkit::Visual::Transform::Property::OFFSET_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) )
155                 .Add( Toolkit::Visual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN )
156                 .Add( Toolkit::Visual::Transform::Property::ANCHOR_POINT, Toolkit::Align::TOP_BEGIN );
157   }
158   else if( ( controlImpl.mPadding.start != 0 ) ||
159            ( controlImpl.mPadding.end != 0 ) ||
160            ( controlImpl.mPadding.top != 0 ) ||
161            ( controlImpl.mPadding.bottom != 0 ) )
162   {
163     transformMap.Add( Toolkit::Visual::Transform::Property::SIZE, newSize )
164                 .Add( Toolkit::Visual::Transform::Property::SIZE_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) )
165                 .Add( Toolkit::Visual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN )
166                 .Add( Toolkit::Visual::Transform::Property::ANCHOR_POINT, Toolkit::Align::TOP_BEGIN );
167   }
168
169   visual.SetTransformAndSize( transformMap, newSize ); // Send an empty map as we do not want to modify the visual's set transform
170 }
171
172 } // unnamed namespace
173
174
175 Toolkit::Control Control::New()
176 {
177   // Create the implementation, temporarily owned on stack
178   IntrusivePtr<Control> controlImpl = new Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) );
179
180   // Pass ownership to handle
181   Toolkit::Control handle( *controlImpl );
182
183   // Second-phase init of the implementation
184   // This can only be done after the CustomActor connection has been made...
185   controlImpl->Initialize();
186
187   return handle;
188 }
189
190 void Control::SetStyleName( const std::string& styleName )
191 {
192   if( styleName != mImpl->mStyleName )
193   {
194     mImpl->mStyleName = styleName;
195
196     // Apply new style, if stylemanager is available
197     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
198     if( styleManager )
199     {
200       GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
201     }
202   }
203 }
204
205 const std::string& Control::GetStyleName() const
206 {
207   return mImpl->mStyleName;
208 }
209
210 void Control::SetBackgroundColor( const Vector4& color )
211 {
212   mImpl->mBackgroundColor = color;
213   Property::Map map;
214   map[ Toolkit::Visual::Property::TYPE ] = Toolkit::Visual::COLOR;
215   map[ Toolkit::ColorVisual::Property::MIX_COLOR ] = color;
216
217   int clippingMode = ClippingMode::DISABLED;
218   if( ( Self().GetProperty( Actor::Property::CLIPPING_MODE ).Get( clippingMode ) ) &&
219       ( clippingMode == ClippingMode::CLIP_CHILDREN ) )
220   {
221     // If clipping-mode is set to CLIP_CHILDREN, then force visual to add the render even if transparent
222     map[ Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT ] = true;
223   }
224
225   SetBackground( map );
226 }
227
228 Vector4 Control::GetBackgroundColor() const
229 {
230   return mImpl->mBackgroundColor;
231 }
232
233 void Control::SetBackground( const Property::Map& map )
234 {
235   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( map );
236   visual.SetName("background");
237   if( visual )
238   {
239     mImpl->RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND );
240
241     // Trigger a size negotiation request that may be needed by the new visual to relayout its contents.
242     RelayoutRequest();
243   }
244 }
245
246 void Control::SetBackgroundImage( Image image )
247 {
248   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( image );
249   if( visual )
250   {
251     mImpl->RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND );
252   }
253 }
254
255 void Control::ClearBackground()
256 {
257    mImpl->UnregisterVisual( Toolkit::Control::Property::BACKGROUND );
258    mImpl->mBackgroundColor = Color::TRANSPARENT;
259
260    // Trigger a size negotiation request that may be needed when unregistering a visual.
261    RelayoutRequest();
262 }
263
264 void Control::EnableGestureDetection(Gesture::Type type)
265 {
266   if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
267   {
268     mImpl->mPinchGestureDetector = PinchGestureDetector::New();
269     mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
270     mImpl->mPinchGestureDetector.Attach(Self());
271   }
272
273   if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
274   {
275     mImpl->mPanGestureDetector = PanGestureDetector::New();
276     mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
277     mImpl->mPanGestureDetector.Attach(Self());
278   }
279
280   if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
281   {
282     mImpl->mTapGestureDetector = TapGestureDetector::New();
283     mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
284     mImpl->mTapGestureDetector.Attach(Self());
285   }
286
287   if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
288   {
289     mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
290     mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
291     mImpl->mLongPressGestureDetector.Attach(Self());
292   }
293 }
294
295 void Control::DisableGestureDetection(Gesture::Type type)
296 {
297   if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
298   {
299     mImpl->mPinchGestureDetector.Detach(Self());
300     mImpl->mPinchGestureDetector.Reset();
301   }
302
303   if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
304   {
305     mImpl->mPanGestureDetector.Detach(Self());
306     mImpl->mPanGestureDetector.Reset();
307   }
308
309   if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
310   {
311     mImpl->mTapGestureDetector.Detach(Self());
312     mImpl->mTapGestureDetector.Reset();
313   }
314
315   if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
316   {
317     mImpl->mLongPressGestureDetector.Detach(Self());
318     mImpl->mLongPressGestureDetector.Reset();
319   }
320 }
321
322 PinchGestureDetector Control::GetPinchGestureDetector() const
323 {
324   return mImpl->mPinchGestureDetector;
325 }
326
327 PanGestureDetector Control::GetPanGestureDetector() const
328 {
329   return mImpl->mPanGestureDetector;
330 }
331
332 TapGestureDetector Control::GetTapGestureDetector() const
333 {
334   return mImpl->mTapGestureDetector;
335 }
336
337 LongPressGestureDetector Control::GetLongPressGestureDetector() const
338 {
339   return mImpl->mLongPressGestureDetector;
340 }
341
342 void Control::SetKeyboardNavigationSupport(bool isSupported)
343 {
344   mImpl->mIsKeyboardNavigationSupported = isSupported;
345 }
346
347 bool Control::IsKeyboardNavigationSupported()
348 {
349   return mImpl->mIsKeyboardNavigationSupported;
350 }
351
352 void Control::SetKeyInputFocus()
353 {
354   if( Self().OnStage() )
355   {
356     Toolkit::KeyInputFocusManager::Get().SetFocus(Toolkit::Control::DownCast(Self()));
357   }
358 }
359
360 bool Control::HasKeyInputFocus()
361 {
362   bool result = false;
363   if( Self().OnStage() )
364   {
365     Toolkit::Control control = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl();
366     if( Self() == control )
367     {
368       result = true;
369     }
370   }
371   return result;
372 }
373
374 void Control::ClearKeyInputFocus()
375 {
376   if( Self().OnStage() )
377   {
378     Toolkit::KeyInputFocusManager::Get().RemoveFocus(Toolkit::Control::DownCast(Self()));
379   }
380 }
381
382 void Control::SetAsKeyboardFocusGroup(bool isFocusGroup)
383 {
384   mImpl->mIsKeyboardFocusGroup = isFocusGroup;
385
386   // The following line will be removed when the deprecated API in KeyboardFocusManager is deleted
387   Toolkit::KeyboardFocusManager::Get().SetAsFocusGroup(Self(), isFocusGroup);
388 }
389
390 bool Control::IsKeyboardFocusGroup()
391 {
392   return Toolkit::KeyboardFocusManager::Get().IsFocusGroup(Self());
393 }
394
395 void Control::AccessibilityActivate()
396 {
397   // Inform deriving classes
398   OnAccessibilityActivated();
399 }
400
401 void Control::KeyboardEnter()
402 {
403   // Inform deriving classes
404   OnKeyboardEnter();
405 }
406
407 bool Control::OnAccessibilityActivated()
408 {
409   return false; // Accessibility activation is not handled by default
410 }
411
412 bool Control::OnKeyboardEnter()
413 {
414   return false; // Keyboard enter is not handled by default
415 }
416
417 bool Control::OnAccessibilityPan(PanGesture gesture)
418 {
419   return false; // Accessibility pan gesture is not handled by default
420 }
421
422 bool Control::OnAccessibilityTouch(const TouchEvent& touchEvent)
423 {
424   return false; // Accessibility touch event is not handled by default
425 }
426
427 bool Control::OnAccessibilityValueChange(bool isIncrease)
428 {
429   return false; // Accessibility value change action is not handled by default
430 }
431
432 bool Control::OnAccessibilityZoom()
433 {
434   return false; // Accessibility zoom action is not handled by default
435 }
436
437 Actor Control::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
438 {
439   return Actor();
440 }
441
442 void Control::OnKeyboardFocusChangeCommitted(Actor commitedFocusableActor)
443 {
444 }
445
446 Toolkit::Control::KeyEventSignalType& Control::KeyEventSignal()
447 {
448   return mImpl->mKeyEventSignal;
449 }
450
451 Toolkit::Control::KeyInputFocusSignalType& Control::KeyInputFocusGainedSignal()
452 {
453   return mImpl->mKeyInputFocusGainedSignal;
454 }
455
456 Toolkit::Control::KeyInputFocusSignalType& Control::KeyInputFocusLostSignal()
457 {
458   return mImpl->mKeyInputFocusLostSignal;
459 }
460
461 bool Control::EmitKeyEventSignal( const KeyEvent& event )
462 {
463   // Guard against destruction during signal emission
464   Dali::Toolkit::Control handle( GetOwner() );
465
466   bool consumed = false;
467
468   consumed = mImpl->FilterKeyEvent( event );
469
470   // signals are allocated dynamically when someone connects
471   if ( !consumed && !mImpl->mKeyEventSignal.Empty() )
472   {
473     consumed = mImpl->mKeyEventSignal.Emit( handle, event );
474   }
475
476   if ( !consumed )
477   {
478     // Notification for derived classes
479     consumed = OnKeyEvent(event);
480   }
481
482   return consumed;
483 }
484
485 Control::Control( ControlBehaviour behaviourFlags )
486 : CustomActorImpl( static_cast< ActorFlags >( behaviourFlags ) ),
487   mImpl(new Impl(*this))
488 {
489   mImpl->mFlags = behaviourFlags;
490 }
491
492 Control::~Control()
493 {
494   delete mImpl;
495 }
496
497 void Control::Initialize()
498 {
499   // Call deriving classes so initialised before styling is applied to them.
500   OnInitialize();
501
502   if( (mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS) ||
503       !(mImpl->mFlags & DISABLE_STYLE_CHANGE_SIGNALS) )
504   {
505     Toolkit::StyleManager styleManager = StyleManager::Get();
506
507     // if stylemanager is available
508     if( styleManager )
509     {
510       StyleManager& styleManagerImpl = GetImpl( styleManager );
511
512       // Register for style changes
513       styleManagerImpl.ControlStyleChangeSignal().Connect( this, &Control::OnStyleChange );
514
515       // Apply the current style
516       styleManagerImpl.ApplyThemeStyleAtInit( Toolkit::Control( GetOwner() ) );
517     }
518   }
519
520   if( mImpl->mFlags & REQUIRES_KEYBOARD_NAVIGATION_SUPPORT )
521   {
522     SetKeyboardNavigationSupport( true );
523   }
524 }
525
526 void Control::OnInitialize()
527 {
528 }
529
530 void Control::OnControlChildAdd( Actor& child )
531 {
532 }
533
534 void Control::OnControlChildRemove( Actor& child )
535 {
536 }
537
538 void Control::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
539 {
540   // By default the control is only interested in theme (not font) changes
541   if( styleManager && change == StyleChange::THEME_CHANGE )
542   {
543     GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
544     RelayoutRequest();
545   }
546 }
547
548 void Control::OnPinch(const PinchGesture& pinch)
549 {
550   if( !( mImpl->mStartingPinchScale ) )
551   {
552     // lazy allocate
553     mImpl->mStartingPinchScale = new Vector3;
554   }
555
556   if( pinch.state == Gesture::Started )
557   {
558     *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale();
559   }
560
561   Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale );
562 }
563
564 void Control::OnPan( const PanGesture& pan )
565 {
566 }
567
568 void Control::OnTap(const TapGesture& tap)
569 {
570 }
571
572 void Control::OnLongPress( const LongPressGesture& longPress )
573 {
574 }
575
576 void Control::EmitKeyInputFocusSignal( bool focusGained )
577 {
578   Dali::Toolkit::Control handle( GetOwner() );
579
580   if ( focusGained )
581   {
582     // signals are allocated dynamically when someone connects
583     if ( !mImpl->mKeyInputFocusGainedSignal.Empty() )
584     {
585       mImpl->mKeyInputFocusGainedSignal.Emit( handle );
586     }
587   }
588   else
589   {
590     // signals are allocated dynamically when someone connects
591     if ( !mImpl->mKeyInputFocusLostSignal.Empty() )
592     {
593       mImpl->mKeyInputFocusLostSignal.Emit( handle );
594     }
595   }
596 }
597
598 void Control::OnStageConnection( int depth )
599 {
600   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageConnection number of registered visuals(%d)\n",  mImpl->mVisuals.Size() );
601
602   Actor self( Self() );
603
604   for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++)
605   {
606     // Check whether the visual is empty and enabled
607     if( (*iter)->visual && (*iter)->enabled )
608     {
609       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageConnection Setting visual(%d) on stage\n", (*iter)->index );
610       Toolkit::GetImplementation((*iter)->visual).SetOnStage( self );
611     }
612   }
613
614   // The clipping renderer is only created if required.
615   CreateClippingRenderer( *this );
616 }
617
618 void Control::OnStageDisconnection()
619 {
620   mImpl->OnStageDisconnection();
621 }
622
623 void Control::OnKeyInputFocusGained()
624 {
625   EmitKeyInputFocusSignal( true );
626 }
627
628 void Control::OnKeyInputFocusLost()
629 {
630   EmitKeyInputFocusSignal( false );
631 }
632
633 void Control::OnChildAdd(Actor& child)
634 {
635   // Notify derived classes.
636   OnControlChildAdd( child );
637 }
638
639 void Control::OnChildRemove(Actor& child)
640 {
641   // Notify derived classes.
642   OnControlChildRemove( child );
643 }
644
645 void Control::OnPropertySet( Property::Index index, Property::Value propertyValue )
646 {
647   // If the clipping mode has been set, we may need to create a renderer.
648   // Only do this if we are already on-stage as the OnStageConnection will handle the off-stage clipping controls.
649   if( ( index == Actor::Property::CLIPPING_MODE ) && Self().OnStage() )
650   {
651     // Note: This method will handle whether creation of the renderer is required.
652     CreateClippingRenderer( *this );
653   }
654 }
655
656 void Control::OnSizeSet(const Vector3& targetSize)
657 {
658   Toolkit::Visual::Base visual = mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
659   if( visual )
660   {
661     Vector2 size( targetSize );
662     SetBackgroundVisual( *mImpl, visual, size );
663
664   }
665 }
666
667 void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
668 {
669   // @todo size negotiate background to new size, animate as well?
670 }
671
672 bool Control::OnTouchEvent(const TouchEvent& event)
673 {
674   return false; // Do not consume
675 }
676
677 bool Control::OnHoverEvent(const HoverEvent& event)
678 {
679   return false; // Do not consume
680 }
681
682 bool Control::OnKeyEvent(const KeyEvent& event)
683 {
684   return false; // Do not consume
685 }
686
687 bool Control::OnWheelEvent(const WheelEvent& event)
688 {
689   return false; // Do not consume
690 }
691
692 void Control::OnRelayout( const Vector2& size, RelayoutContainer& container )
693 {
694   for( unsigned int i = 0, numChildren = Self().GetChildCount(); i < numChildren; ++i )
695   {
696     Actor child = Self().GetChildAt( i );
697     Vector2 newChildSize( size );
698
699     // When set the padding or margin on the control, child should be resized and repositioned.
700     if( ( mImpl->mPadding.start != 0 ) || ( mImpl->mPadding.end != 0 ) || ( mImpl->mPadding.top != 0 ) || ( mImpl->mPadding.bottom != 0 ) ||
701         ( mImpl->mMargin.start != 0 ) || ( mImpl->mMargin.end != 0 ) || ( mImpl->mMargin.top != 0 ) || ( mImpl->mMargin.bottom != 0 ) )
702     {
703       Extents padding = mImpl->mPadding;
704
705       Dali::CustomActor ownerActor(GetOwner());
706       Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>( ownerActor.GetProperty( Dali::Actor::Property::LAYOUT_DIRECTION ).Get<int>() );
707
708       if( Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection )
709       {
710         std::swap( padding.start, padding.end );
711       }
712
713       newChildSize.width = size.width - ( padding.start + padding.end );
714       newChildSize.height = size.height - ( padding.top + padding.bottom );
715
716       // Cannot use childs Position property as it can already have padding and margin applied on it,
717       // so we end up cumulatively applying them over and over again.
718       Vector2 childOffset( 0.f, 0.f );
719       childOffset.x += ( mImpl->mMargin.start + padding.start );
720       childOffset.y += ( mImpl->mMargin.top + padding.top );
721
722       child.SetPosition( childOffset.x, childOffset.y );
723     }
724
725     container.Add( child, newChildSize );
726   }
727
728   Toolkit::Visual::Base visual = mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
729   if( visual )
730   {
731     SetBackgroundVisual( *mImpl, visual, size );
732   }
733 }
734
735 void Control::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
736 {
737 }
738
739 Vector3 Control::GetNaturalSize()
740 {
741   Toolkit::Visual::Base visual = mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
742   if( visual )
743   {
744     Vector2 naturalSize;
745     visual.GetNaturalSize( naturalSize );
746     naturalSize.width += ( mImpl->mPadding.start + mImpl->mPadding.end );
747     naturalSize.height += ( mImpl->mPadding.top + mImpl->mPadding.bottom );
748     return Vector3( naturalSize );
749   }
750   return Vector3::ZERO;
751 }
752
753 float Control::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
754 {
755   return CalculateChildSizeBase( child, dimension );
756 }
757
758 float Control::GetHeightForWidth( float width )
759 {
760   return GetHeightForWidthBase( width );
761 }
762
763 float Control::GetWidthForHeight( float height )
764 {
765   return GetWidthForHeightBase( height );
766 }
767
768 bool Control::RelayoutDependentOnChildren( Dimension::Type dimension )
769 {
770   return RelayoutDependentOnChildrenBase( dimension );
771 }
772
773 void Control::OnCalculateRelayoutSize( Dimension::Type dimension )
774 {
775 }
776
777 void Control::OnLayoutNegotiated( float size, Dimension::Type dimension )
778 {
779 }
780
781 void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
782 {
783   mImpl->SignalConnected( slotObserver, callback );
784 }
785
786 void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
787 {
788   mImpl->SignalDisconnected( slotObserver, callback );
789 }
790
791 Control& GetImplementation( Dali::Toolkit::Control& handle )
792 {
793   CustomActorImpl& customInterface = handle.GetImplementation();
794   // downcast to control
795   Control& impl = dynamic_cast< Internal::Control& >( customInterface );
796   return impl;
797 }
798
799 const Control& GetImplementation( const Dali::Toolkit::Control& handle )
800 {
801   const CustomActorImpl& customInterface = handle.GetImplementation();
802   // downcast to control
803   const Control& impl = dynamic_cast< const Internal::Control& >( customInterface );
804   return impl;
805 }
806
807 } // namespace Internal
808
809 } // namespace Toolkit
810
811 } // namespace Dali