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