Merge "Disable pixel alignment while scrolling the text" 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/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   // signals are allocated dynamically when someone connects
469   if ( !mImpl->mKeyEventSignal.Empty() )
470   {
471     consumed = mImpl->mKeyEventSignal.Emit( handle, event );
472   }
473
474   if (!consumed)
475   {
476     // Notification for derived classes
477     consumed = OnKeyEvent(event);
478   }
479
480   return consumed;
481 }
482
483 Control::Control( ControlBehaviour behaviourFlags )
484 : CustomActorImpl( static_cast< ActorFlags >( behaviourFlags ) ),
485   mImpl(new Impl(*this))
486 {
487   mImpl->mFlags = behaviourFlags;
488 }
489
490 Control::~Control()
491 {
492   delete mImpl;
493 }
494
495 void Control::Initialize()
496 {
497   // Call deriving classes so initialised before styling is applied to them.
498   OnInitialize();
499
500   if( (mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS) ||
501       !(mImpl->mFlags & DISABLE_STYLE_CHANGE_SIGNALS) )
502   {
503     Toolkit::StyleManager styleManager = StyleManager::Get();
504
505     // if stylemanager is available
506     if( styleManager )
507     {
508       StyleManager& styleManagerImpl = GetImpl( styleManager );
509
510       // Register for style changes
511       styleManagerImpl.ControlStyleChangeSignal().Connect( this, &Control::OnStyleChange );
512
513       // Apply the current style
514       styleManagerImpl.ApplyThemeStyleAtInit( Toolkit::Control( GetOwner() ) );
515     }
516   }
517
518   if( mImpl->mFlags & REQUIRES_KEYBOARD_NAVIGATION_SUPPORT )
519   {
520     SetKeyboardNavigationSupport( true );
521   }
522 }
523
524 void Control::OnInitialize()
525 {
526 }
527
528 void Control::OnControlChildAdd( Actor& child )
529 {
530 }
531
532 void Control::OnControlChildRemove( Actor& child )
533 {
534 }
535
536 void Control::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
537 {
538   // By default the control is only interested in theme (not font) changes
539   if( styleManager && change == StyleChange::THEME_CHANGE )
540   {
541     GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
542     RelayoutRequest();
543   }
544 }
545
546 void Control::OnPinch(const PinchGesture& pinch)
547 {
548   if( !( mImpl->mStartingPinchScale ) )
549   {
550     // lazy allocate
551     mImpl->mStartingPinchScale = new Vector3;
552   }
553
554   if( pinch.state == Gesture::Started )
555   {
556     *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale();
557   }
558
559   Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale );
560 }
561
562 void Control::OnPan( const PanGesture& pan )
563 {
564 }
565
566 void Control::OnTap(const TapGesture& tap)
567 {
568 }
569
570 void Control::OnLongPress( const LongPressGesture& longPress )
571 {
572 }
573
574 void Control::EmitKeyInputFocusSignal( bool focusGained )
575 {
576   Dali::Toolkit::Control handle( GetOwner() );
577
578   if ( focusGained )
579   {
580     // signals are allocated dynamically when someone connects
581     if ( !mImpl->mKeyInputFocusGainedSignal.Empty() )
582     {
583       mImpl->mKeyInputFocusGainedSignal.Emit( handle );
584     }
585   }
586   else
587   {
588     // signals are allocated dynamically when someone connects
589     if ( !mImpl->mKeyInputFocusLostSignal.Empty() )
590     {
591       mImpl->mKeyInputFocusLostSignal.Emit( handle );
592     }
593   }
594 }
595
596 void Control::OnStageConnection( int depth )
597 {
598   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageConnection number of registered visuals(%d)\n",  mImpl->mVisuals.Size() );
599
600   Actor self( Self() );
601
602   for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++)
603   {
604     // Check whether the visual is empty and enabled
605     if( (*iter)->visual && (*iter)->enabled )
606     {
607       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageConnection Setting visual(%d) on stage\n", (*iter)->index );
608       Toolkit::GetImplementation((*iter)->visual).SetOnStage( self );
609     }
610   }
611
612   // The clipping renderer is only created if required.
613   CreateClippingRenderer( *this );
614 }
615
616 void Control::OnStageDisconnection()
617 {
618   mImpl->OnStageDisconnection();
619 }
620
621 void Control::OnKeyInputFocusGained()
622 {
623   EmitKeyInputFocusSignal( true );
624 }
625
626 void Control::OnKeyInputFocusLost()
627 {
628   EmitKeyInputFocusSignal( false );
629 }
630
631 void Control::OnChildAdd(Actor& child)
632 {
633   // Notify derived classes.
634   OnControlChildAdd( child );
635 }
636
637 void Control::OnChildRemove(Actor& child)
638 {
639   // Notify derived classes.
640   OnControlChildRemove( child );
641 }
642
643 void Control::OnPropertySet( Property::Index index, Property::Value propertyValue )
644 {
645   // If the clipping mode has been set, we may need to create a renderer.
646   // Only do this if we are already on-stage as the OnStageConnection will handle the off-stage clipping controls.
647   if( ( index == Actor::Property::CLIPPING_MODE ) && Self().OnStage() )
648   {
649     // Note: This method will handle whether creation of the renderer is required.
650     CreateClippingRenderer( *this );
651   }
652 }
653
654 void Control::OnSizeSet(const Vector3& targetSize)
655 {
656   Toolkit::Visual::Base visual = mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
657   if( visual )
658   {
659     Vector2 size( targetSize );
660     SetBackgroundVisual( *mImpl, visual, size );
661
662   }
663 }
664
665 void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
666 {
667   // @todo size negotiate background to new size, animate as well?
668 }
669
670 bool Control::OnTouchEvent(const TouchEvent& event)
671 {
672   return false; // Do not consume
673 }
674
675 bool Control::OnHoverEvent(const HoverEvent& event)
676 {
677   return false; // Do not consume
678 }
679
680 bool Control::OnKeyEvent(const KeyEvent& event)
681 {
682   return false; // Do not consume
683 }
684
685 bool Control::OnWheelEvent(const WheelEvent& event)
686 {
687   return false; // Do not consume
688 }
689
690 void Control::OnRelayout( const Vector2& size, RelayoutContainer& container )
691 {
692   for( unsigned int i = 0, numChildren = Self().GetChildCount(); i < numChildren; ++i )
693   {
694     Actor child = Self().GetChildAt( i );
695     Vector2 newChildSize( size );
696
697     // When set the padding or margin on the control, child should be resized and repositioned.
698     if( ( mImpl->mPadding.start != 0 ) || ( mImpl->mPadding.end != 0 ) || ( mImpl->mPadding.top != 0 ) || ( mImpl->mPadding.bottom != 0 ) ||
699         ( mImpl->mMargin.start != 0 ) || ( mImpl->mMargin.end != 0 ) || ( mImpl->mMargin.top != 0 ) || ( mImpl->mMargin.bottom != 0 ) )
700     {
701       Extents padding = mImpl->mPadding;
702
703       Dali::CustomActor ownerActor(GetOwner());
704       Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>( ownerActor.GetProperty( Dali::Actor::Property::LAYOUT_DIRECTION ).Get<int>() );
705
706       if( Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection )
707       {
708         std::swap( padding.start, padding.end );
709       }
710
711       newChildSize.width = size.width - ( padding.start + padding.end );
712       newChildSize.height = size.height - ( padding.top + padding.bottom );
713
714       // Cannot use childs Position property as it can already have padding and margin applied on it,
715       // so we end up cumulatively applying them over and over again.
716       Vector2 childOffset( 0.f, 0.f );
717       childOffset.x += ( mImpl->mMargin.start + padding.start );
718       childOffset.y += ( mImpl->mMargin.top + padding.top );
719
720       child.SetPosition( childOffset.x, childOffset.y );
721     }
722
723     container.Add( child, newChildSize );
724   }
725
726   Toolkit::Visual::Base visual = mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
727   if( visual )
728   {
729     SetBackgroundVisual( *mImpl, visual, size );
730   }
731 }
732
733 void Control::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
734 {
735 }
736
737 Vector3 Control::GetNaturalSize()
738 {
739   Toolkit::Visual::Base visual = mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
740   if( visual )
741   {
742     Vector2 naturalSize;
743     visual.GetNaturalSize( naturalSize );
744     naturalSize.width += ( mImpl->mPadding.start + mImpl->mPadding.end );
745     naturalSize.height += ( mImpl->mPadding.top + mImpl->mPadding.bottom );
746     return Vector3( naturalSize );
747   }
748   return Vector3::ZERO;
749 }
750
751 float Control::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
752 {
753   return CalculateChildSizeBase( child, dimension );
754 }
755
756 float Control::GetHeightForWidth( float width )
757 {
758   return GetHeightForWidthBase( width );
759 }
760
761 float Control::GetWidthForHeight( float height )
762 {
763   return GetWidthForHeightBase( height );
764 }
765
766 bool Control::RelayoutDependentOnChildren( Dimension::Type dimension )
767 {
768   return RelayoutDependentOnChildrenBase( dimension );
769 }
770
771 void Control::OnCalculateRelayoutSize( Dimension::Type dimension )
772 {
773 }
774
775 void Control::OnLayoutNegotiated( float size, Dimension::Type dimension )
776 {
777 }
778
779 void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
780 {
781   mImpl->SignalConnected( slotObserver, callback );
782 }
783
784 void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
785 {
786   mImpl->SignalDisconnected( slotObserver, callback );
787 }
788
789 Control& GetImplementation( Dali::Toolkit::Control& handle )
790 {
791   CustomActorImpl& customInterface = handle.GetImplementation();
792   // downcast to control
793   Control& impl = dynamic_cast< Internal::Control& >( customInterface );
794   return impl;
795 }
796
797 const Control& GetImplementation( const Dali::Toolkit::Control& handle )
798 {
799   const CustomActorImpl& customInterface = handle.GetImplementation();
800   // downcast to control
801   const Control& impl = dynamic_cast< const Internal::Control& >( customInterface );
802   return impl;
803 }
804
805 } // namespace Internal
806
807 } // namespace Toolkit
808
809 } // namespace Dali