[Tizen][ATSPI] Accessibility initial implementation
[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/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 #include <dali-toolkit/public-api/accessibility-manager/accessibility-manager.h>
35
36 // INTERNAL INCLUDES
37 #include <dali-toolkit/public-api/align-enumerations.h>
38 #include <dali-toolkit/public-api/controls/control.h>
39 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
40 #include <dali-toolkit/public-api/styling/style-manager.h>
41 #include <dali-toolkit/public-api/visuals/color-visual-properties.h>
42 #include <dali-toolkit/public-api/visuals/visual-properties.h>
43 #include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
44 #include <dali-toolkit/devel-api/controls/control-devel.h>
45 #include <dali-toolkit/devel-api/focus-manager/keyinput-focus-manager.h>
46 #include <dali-toolkit/devel-api/visuals/color-visual-properties-devel.h>
47 #include <dali-toolkit/internal/styling/style-manager-impl.h>
48 #include <dali-toolkit/internal/visuals/color/color-visual.h>
49 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
50 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
51 #include <dali/devel-api/actors/actor-devel.h>
52
53 namespace Dali
54 {
55
56 namespace Toolkit
57 {
58
59 namespace Internal
60 {
61
62 namespace
63 {
64
65 #if defined(DEBUG_ENABLED)
66 Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
67 #endif
68
69 /**
70  * @brief Replace the background visual if it's a color visual with the renderIfTransparent property set as required.
71  * @param[in] controlImpl The control implementation
72  * @param[in] renderIfTransaparent Whether we should render if the color is transparent
73  */
74 void ChangeBackgroundColorVisual( Control& controlImpl, bool renderIfTransparent )
75 {
76   Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl );
77
78   Toolkit::Visual::Base backgroundVisual = controlDataImpl.GetVisual( Toolkit::Control::Property::BACKGROUND );
79   if( backgroundVisual )
80   {
81     Property::Map map;
82     backgroundVisual.CreatePropertyMap( map );
83     Property::Value* typeValue = map.Find( Toolkit::Visual::Property::TYPE );
84     if( typeValue && typeValue->Get< int >() == Toolkit::Visual::COLOR )
85     {
86       // Only change it if it's a color visual
87       map[ Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT ] = renderIfTransparent;
88       controlImpl.SetBackground( map );
89     }
90   }
91 }
92
93 /**
94  * @brief Creates a clipping renderer if required.
95  * (EG. If no renders exist and clipping is enabled).
96  * @param[in] controlImpl The control implementation.
97  */
98 void CreateClippingRenderer( Control& controlImpl )
99 {
100   // We want to add a transparent background if we do not have one for clipping.
101   Actor self( controlImpl.Self() );
102   int clippingMode = ClippingMode::DISABLED;
103   if( self.GetProperty( Actor::Property::CLIPPING_MODE ).Get( clippingMode ) )
104   {
105     switch( clippingMode )
106     {
107       case ClippingMode::CLIP_CHILDREN:
108       {
109         if( self.GetRendererCount() == 0u )
110         {
111           Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl );
112           if( controlDataImpl.mVisuals.Empty() )
113           {
114             controlImpl.SetBackgroundColor( Color::TRANSPARENT );
115           }
116           else
117           {
118             // We have visuals, check if we've set the background and re-create it to
119             // render even if transparent (only if it's a color visual)
120             ChangeBackgroundColorVisual( controlImpl, true );
121           }
122         }
123         break;
124       }
125
126       case ClippingMode::DISABLED:
127       case ClippingMode::CLIP_TO_BOUNDING_BOX:
128       {
129         // If we have a background visual, check if it's a color visual and remove the render if transparent flag
130         ChangeBackgroundColorVisual( controlImpl, false );
131         break;
132       }
133     }
134   }
135 }
136
137 /**
138  * @brief Sets Control::Property::BACKGROUND visual
139  * @param[in] controlImpl The control implementation
140  * @param[in] visual The control background visual
141  * @param[in] size The current size
142  */
143 void SetBackgroundVisual( Control::Impl& controlImpl, Toolkit::Visual::Base& visual, const Vector2& size )
144 {
145   Property::Map transformMap = Property::Map();
146
147   Vector2 newSize( 0.f, 0.f );
148   newSize.width = size.width + ( controlImpl.mPadding.start + controlImpl.mPadding.end );
149   newSize.height = size.height + ( controlImpl.mPadding.top + controlImpl.mPadding.bottom );
150
151   if( ( controlImpl.mMargin.start != 0 ) ||
152       ( controlImpl.mMargin.end != 0 ) ||
153       ( controlImpl.mMargin.top != 0 ) ||
154       ( controlImpl.mMargin.bottom != 0 ) )
155   {
156     transformMap.Add( Toolkit::Visual::Transform::Property::SIZE, newSize )
157                 .Add( Toolkit::Visual::Transform::Property::SIZE_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) )
158                 .Add( Toolkit::Visual::Transform::Property::OFFSET, Vector2( controlImpl.mMargin.start, controlImpl.mMargin.top ) )
159                 .Add( Toolkit::Visual::Transform::Property::OFFSET_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) )
160                 .Add( Toolkit::Visual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN )
161                 .Add( Toolkit::Visual::Transform::Property::ANCHOR_POINT, Toolkit::Align::TOP_BEGIN );
162   }
163   else if( ( controlImpl.mPadding.start != 0 ) ||
164            ( controlImpl.mPadding.end != 0 ) ||
165            ( controlImpl.mPadding.top != 0 ) ||
166            ( controlImpl.mPadding.bottom != 0 ) )
167   {
168     transformMap.Add( Toolkit::Visual::Transform::Property::SIZE, newSize )
169                 .Add( Toolkit::Visual::Transform::Property::SIZE_POLICY, Vector2( Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE ) )
170                 .Add( Toolkit::Visual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN )
171                 .Add( Toolkit::Visual::Transform::Property::ANCHOR_POINT, Toolkit::Align::TOP_BEGIN );
172   }
173
174   visual.SetTransformAndSize( transformMap, newSize ); // Send an empty map as we do not want to modify the visual's set transform
175 }
176
177 } // unnamed namespace
178
179
180 Toolkit::Control Control::New()
181 {
182   // Create the implementation, temporarily owned on stack
183   IntrusivePtr<Control> controlImpl = new Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) );
184
185   // Pass ownership to handle
186   Toolkit::Control handle( *controlImpl );
187
188   // Second-phase init of the implementation
189   // This can only be done after the CustomActor connection has been made...
190   controlImpl->Initialize();
191
192   return handle;
193 }
194
195 void Control::SetStyleName( const std::string& styleName )
196 {
197   if( styleName != mImpl->mStyleName )
198   {
199     mImpl->mStyleName = styleName;
200
201     // Apply new style, if stylemanager is available
202     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
203     if( styleManager )
204     {
205       GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
206     }
207   }
208 }
209
210 const std::string& Control::GetStyleName() const
211 {
212   return mImpl->mStyleName;
213 }
214
215 void Control::SetBackgroundColor( const Vector4& color )
216 {
217   mImpl->mBackgroundColor = color;
218   Property::Map map;
219   map[ Toolkit::Visual::Property::TYPE ] = Toolkit::Visual::COLOR;
220   map[ Toolkit::ColorVisual::Property::MIX_COLOR ] = color;
221
222   int clippingMode = ClippingMode::DISABLED;
223   if( ( Self().GetProperty( Actor::Property::CLIPPING_MODE ).Get( clippingMode ) ) &&
224       ( clippingMode == ClippingMode::CLIP_CHILDREN ) )
225   {
226     // If clipping-mode is set to CLIP_CHILDREN, then force visual to add the render even if transparent
227     map[ Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT ] = true;
228   }
229
230   SetBackground( map );
231 }
232
233 Vector4 Control::GetBackgroundColor() const
234 {
235   return mImpl->mBackgroundColor;
236 }
237
238 void Control::SetBackground( const Property::Map& map )
239 {
240   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( map );
241   visual.SetName("background");
242   if( visual )
243   {
244     mImpl->RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND );
245
246     // Trigger a size negotiation request that may be needed by the new visual to relayout its contents.
247     RelayoutRequest();
248   }
249 }
250
251 void Control::SetBackgroundImage( Image image )
252 {
253   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( image );
254   if( visual )
255   {
256     mImpl->RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND );
257   }
258 }
259
260 void Control::ClearBackground()
261 {
262    mImpl->UnregisterVisual( Toolkit::Control::Property::BACKGROUND );
263    mImpl->mBackgroundColor = Color::TRANSPARENT;
264
265    // Trigger a size negotiation request that may be needed when unregistering a visual.
266    RelayoutRequest();
267 }
268
269 void Control::EnableGestureDetection(Gesture::Type type)
270 {
271   if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
272   {
273     mImpl->mPinchGestureDetector = PinchGestureDetector::New();
274     mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
275     mImpl->mPinchGestureDetector.Attach(Self());
276   }
277
278   if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
279   {
280     mImpl->mPanGestureDetector = PanGestureDetector::New();
281     mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
282     mImpl->mPanGestureDetector.Attach(Self());
283   }
284
285   if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
286   {
287     mImpl->mTapGestureDetector = TapGestureDetector::New();
288     mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
289     mImpl->mTapGestureDetector.Attach(Self());
290   }
291
292   if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
293   {
294     mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
295     mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
296     mImpl->mLongPressGestureDetector.Attach(Self());
297   }
298 }
299
300 void Control::DisableGestureDetection(Gesture::Type type)
301 {
302   if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
303   {
304     mImpl->mPinchGestureDetector.Detach(Self());
305     mImpl->mPinchGestureDetector.Reset();
306   }
307
308   if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
309   {
310     mImpl->mPanGestureDetector.Detach(Self());
311     mImpl->mPanGestureDetector.Reset();
312   }
313
314   if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
315   {
316     mImpl->mTapGestureDetector.Detach(Self());
317     mImpl->mTapGestureDetector.Reset();
318   }
319
320   if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
321   {
322     mImpl->mLongPressGestureDetector.Detach(Self());
323     mImpl->mLongPressGestureDetector.Reset();
324   }
325 }
326
327 PinchGestureDetector Control::GetPinchGestureDetector() const
328 {
329   return mImpl->mPinchGestureDetector;
330 }
331
332 PanGestureDetector Control::GetPanGestureDetector() const
333 {
334   return mImpl->mPanGestureDetector;
335 }
336
337 TapGestureDetector Control::GetTapGestureDetector() const
338 {
339   return mImpl->mTapGestureDetector;
340 }
341
342 LongPressGestureDetector Control::GetLongPressGestureDetector() const
343 {
344   return mImpl->mLongPressGestureDetector;
345 }
346
347 void Control::SetKeyboardNavigationSupport(bool isSupported)
348 {
349   mImpl->mIsKeyboardNavigationSupported = isSupported;
350 }
351
352 bool Control::IsKeyboardNavigationSupported()
353 {
354   return mImpl->mIsKeyboardNavigationSupported;
355 }
356
357 void Control::SetKeyInputFocus()
358 {
359   if( Self().OnStage() )
360   {
361     Toolkit::KeyInputFocusManager::Get().SetFocus(Toolkit::Control::DownCast(Self()));
362   }
363 }
364
365 bool Control::HasKeyInputFocus()
366 {
367   bool result = false;
368   if( Self().OnStage() )
369   {
370     Toolkit::Control control = Toolkit::KeyInputFocusManager::Get().GetCurrentFocusControl();
371     if( Self() == control )
372     {
373       result = true;
374     }
375   }
376   return result;
377 }
378
379 void Control::ClearKeyInputFocus()
380 {
381   if( Self().OnStage() )
382   {
383     Toolkit::KeyInputFocusManager::Get().RemoveFocus(Toolkit::Control::DownCast(Self()));
384   }
385 }
386
387 void Control::SetAsKeyboardFocusGroup(bool isFocusGroup)
388 {
389   mImpl->mIsKeyboardFocusGroup = isFocusGroup;
390
391   // The following line will be removed when the deprecated API in KeyboardFocusManager is deleted
392   Toolkit::KeyboardFocusManager::Get().SetAsFocusGroup(Self(), isFocusGroup);
393 }
394
395 bool Control::IsKeyboardFocusGroup()
396 {
397   return Toolkit::KeyboardFocusManager::Get().IsFocusGroup(Self());
398 }
399
400 void Control::AccessibilityActivate()
401 {
402   // Inform deriving classes
403   OnAccessibilityActivated();
404 }
405
406 void Control::KeyboardEnter()
407 {
408   // Inform deriving classes
409   OnKeyboardEnter();
410 }
411
412 bool Control::OnAccessibilityActivated()
413 {
414   return false; // Accessibility activation is not handled by default
415 }
416
417 bool Control::OnKeyboardEnter()
418 {
419   return false; // Keyboard enter is not handled by default
420 }
421
422 bool Control::OnAccessibilityPan(PanGesture gesture)
423 {
424   return false; // Accessibility pan gesture is not handled by default
425 }
426
427 bool Control::OnAccessibilityTouch(const TouchEvent& touchEvent)
428 {
429   return false; // Accessibility touch event is not handled by default
430 }
431
432 bool Control::OnAccessibilityValueChange(bool isIncrease)
433 {
434   return false; // Accessibility value change action is not handled by default
435 }
436
437 bool Control::OnAccessibilityZoom()
438 {
439   return false; // Accessibility zoom action is not handled by default
440 }
441
442 Actor Control::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
443 {
444   return Actor();
445 }
446
447 void Control::OnKeyboardFocusChangeCommitted(Actor commitedFocusableActor)
448 {
449 }
450
451 Toolkit::Control::KeyEventSignalType& Control::KeyEventSignal()
452 {
453   return mImpl->mKeyEventSignal;
454 }
455
456 Toolkit::Control::KeyInputFocusSignalType& Control::KeyInputFocusGainedSignal()
457 {
458   return mImpl->mKeyInputFocusGainedSignal;
459 }
460
461 Toolkit::Control::KeyInputFocusSignalType& Control::KeyInputFocusLostSignal()
462 {
463   return mImpl->mKeyInputFocusLostSignal;
464 }
465
466 bool Control::EmitKeyEventSignal( const KeyEvent& event )
467 {
468   // Guard against destruction during signal emission
469   Dali::Toolkit::Control handle( GetOwner() );
470
471   bool consumed = false;
472
473   // signals are allocated dynamically when someone connects
474   if ( !mImpl->mKeyEventSignal.Empty() )
475   {
476     consumed = mImpl->mKeyEventSignal.Emit( handle, event );
477   }
478
479   if (!consumed)
480   {
481     // Notification for derived classes
482     consumed = OnKeyEvent(event);
483   }
484
485   return consumed;
486 }
487
488 Control::Control( ControlBehaviour behaviourFlags )
489 : CustomActorImpl( static_cast< ActorFlags >( behaviourFlags ) ),
490   mImpl(new Impl(*this))
491 {
492   mImpl->mFlags = behaviourFlags;
493   SetAccessibilityConstructor(
494       []( Dali::Actor actor )
495           -> std::unique_ptr< Dali::Accessibility::Accessible > {
496         return std::unique_ptr< Dali::Accessibility::Accessible >(
497             new AccessibleImpl( actor,
498                                 Dali::Accessibility::Role::RedundantObject ) );
499       } );
500 }
501
502 Control::~Control()
503 {
504   delete mImpl;
505 }
506
507 void Control::Initialize()
508 {
509   // Call deriving classes so initialised before styling is applied to them.
510   OnInitialize();
511
512   if( (mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS) ||
513       !(mImpl->mFlags & DISABLE_STYLE_CHANGE_SIGNALS) )
514   {
515     Toolkit::StyleManager styleManager = StyleManager::Get();
516
517     // if stylemanager is available
518     if( styleManager )
519     {
520       StyleManager& styleManagerImpl = GetImpl( styleManager );
521
522       // Register for style changes
523       styleManagerImpl.ControlStyleChangeSignal().Connect( this, &Control::OnStyleChange );
524
525       // Apply the current style
526       styleManagerImpl.ApplyThemeStyleAtInit( Toolkit::Control( GetOwner() ) );
527     }
528   }
529
530   if( mImpl->mFlags & REQUIRES_KEYBOARD_NAVIGATION_SUPPORT )
531   {
532     SetKeyboardNavigationSupport( true );
533   }
534
535   Dali::TypeInfo type;
536   Self().GetTypeInfo( type );
537   auto type_name = type.GetName();
538   AccessibilitySetAttribute( "t", type_name );
539 }
540
541 void Control::OnInitialize()
542 {
543 }
544
545 void Control::OnControlChildAdd( Actor& child )
546 {
547 }
548
549 void Control::OnControlChildRemove( Actor& child )
550 {
551 }
552
553 void Control::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
554 {
555   // By default the control is only interested in theme (not font) changes
556   if( styleManager && change == StyleChange::THEME_CHANGE )
557   {
558     GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
559     RelayoutRequest();
560   }
561 }
562
563 void Control::OnPinch(const PinchGesture& pinch)
564 {
565   if( !( mImpl->mStartingPinchScale ) )
566   {
567     // lazy allocate
568     mImpl->mStartingPinchScale = new Vector3;
569   }
570
571   if( pinch.state == Gesture::Started )
572   {
573     *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale();
574   }
575
576   Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale );
577 }
578
579 void Control::OnPan( const PanGesture& pan )
580 {
581 }
582
583 void Control::OnTap(const TapGesture& tap)
584 {
585 }
586
587 void Control::OnLongPress( const LongPressGesture& longPress )
588 {
589 }
590
591 void Control::EmitKeyInputFocusSignal( bool focusGained )
592 {
593   Dali::Toolkit::Control handle( GetOwner() );
594
595   if ( focusGained )
596   {
597     // signals are allocated dynamically when someone connects
598     if ( !mImpl->mKeyInputFocusGainedSignal.Empty() )
599     {
600       mImpl->mKeyInputFocusGainedSignal.Emit( handle );
601     }
602   }
603   else
604   {
605     // signals are allocated dynamically when someone connects
606     if ( !mImpl->mKeyInputFocusLostSignal.Empty() )
607     {
608       mImpl->mKeyInputFocusLostSignal.Emit( handle );
609     }
610   }
611 }
612
613 void Control::OnStageConnection( int depth )
614 {
615   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageConnection number of registered visuals(%d)\n",  mImpl->mVisuals.Size() );
616
617   Actor self( Self() );
618
619   for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++)
620   {
621     // Check whether the visual is empty and enabled
622     if( (*iter)->visual && (*iter)->enabled )
623     {
624       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::OnStageConnection Setting visual(%d) on stage\n", (*iter)->index );
625       Toolkit::GetImplementation((*iter)->visual).SetOnStage( self );
626     }
627   }
628
629   // The clipping renderer is only created if required.
630   CreateClippingRenderer( *this );
631 }
632
633 void Control::OnStageDisconnection()
634 {
635   mImpl->OnStageDisconnection();
636 }
637
638 void Control::OnKeyInputFocusGained()
639 {
640   EmitKeyInputFocusSignal( true );
641 }
642
643 void Control::OnKeyInputFocusLost()
644 {
645   EmitKeyInputFocusSignal( false );
646 }
647
648 void Control::OnChildAdd(Actor& child)
649 {
650   // Notify derived classes.
651   OnControlChildAdd( child );
652 }
653
654 void Control::OnChildRemove(Actor& child)
655 {
656   // Notify derived classes.
657   OnControlChildRemove( child );
658 }
659
660 void Control::OnPropertySet( Property::Index index, Property::Value propertyValue )
661 {
662   // If the clipping mode has been set, we may need to create a renderer.
663   // Only do this if we are already on-stage as the OnStageConnection will handle the off-stage clipping controls.
664   if( ( index == Actor::Property::CLIPPING_MODE ) && Self().OnStage() )
665   {
666     // Note: This method will handle whether creation of the renderer is required.
667     CreateClippingRenderer( *this );
668   }
669 }
670
671 void Control::OnSizeSet(const Vector3& targetSize)
672 {
673   Toolkit::Visual::Base visual = mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
674   if( visual )
675   {
676     Vector2 size( targetSize );
677     SetBackgroundVisual( *mImpl, visual, size );
678
679   }
680 }
681
682 void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
683 {
684   // @todo size negotiate background to new size, animate as well?
685 }
686
687 bool Control::OnTouchEvent(const TouchEvent& event)
688 {
689   return false; // Do not consume
690 }
691
692 bool Control::OnHoverEvent(const HoverEvent& event)
693 {
694   return false; // Do not consume
695 }
696
697 bool Control::OnKeyEvent(const KeyEvent& event)
698 {
699   return false; // Do not consume
700 }
701
702 bool Control::OnWheelEvent(const WheelEvent& event)
703 {
704   return false; // Do not consume
705 }
706
707 void Control::OnRelayout( const Vector2& size, RelayoutContainer& container )
708 {
709   for( unsigned int i = 0, numChildren = Self().GetChildCount(); i < numChildren; ++i )
710   {
711     Actor child = Self().GetChildAt( i );
712     Vector2 newChildSize( size );
713
714     // When set the padding or margin on the control, child should be resized and repositioned.
715     if( ( mImpl->mPadding.start != 0 ) || ( mImpl->mPadding.end != 0 ) || ( mImpl->mPadding.top != 0 ) || ( mImpl->mPadding.bottom != 0 ) ||
716         ( mImpl->mMargin.start != 0 ) || ( mImpl->mMargin.end != 0 ) || ( mImpl->mMargin.top != 0 ) || ( mImpl->mMargin.bottom != 0 ) )
717     {
718       Extents padding = mImpl->mPadding;
719
720       Dali::CustomActor ownerActor(GetOwner());
721       Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>( ownerActor.GetProperty( Dali::Actor::Property::LAYOUT_DIRECTION ).Get<int>() );
722
723       if( Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection )
724       {
725         std::swap( padding.start, padding.end );
726       }
727
728       newChildSize.width = size.width - ( padding.start + padding.end );
729       newChildSize.height = size.height - ( padding.top + padding.bottom );
730
731       // Cannot use childs Position property as it can already have padding and margin applied on it,
732       // so we end up cumulatively applying them over and over again.
733       Vector2 childOffset( 0.f, 0.f );
734       childOffset.x += ( mImpl->mMargin.start + padding.start );
735       childOffset.y += ( mImpl->mMargin.top + padding.top );
736
737       child.SetPosition( childOffset.x, childOffset.y );
738     }
739
740     container.Add( child, newChildSize );
741   }
742
743   Toolkit::Visual::Base visual = mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
744   if( visual )
745   {
746     SetBackgroundVisual( *mImpl, visual, size );
747   }
748 }
749
750 void Control::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
751 {
752 }
753
754 Vector3 Control::GetNaturalSize()
755 {
756   Toolkit::Visual::Base visual = mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
757   if( visual )
758   {
759     Vector2 naturalSize;
760     visual.GetNaturalSize( naturalSize );
761     naturalSize.width += ( mImpl->mPadding.start + mImpl->mPadding.end );
762     naturalSize.height += ( mImpl->mPadding.top + mImpl->mPadding.bottom );
763     return Vector3( naturalSize );
764   }
765   return Vector3::ZERO;
766 }
767
768 float Control::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
769 {
770   return CalculateChildSizeBase( child, dimension );
771 }
772
773 float Control::GetHeightForWidth( float width )
774 {
775   return GetHeightForWidthBase( width );
776 }
777
778 float Control::GetWidthForHeight( float height )
779 {
780   return GetWidthForHeightBase( height );
781 }
782
783 bool Control::RelayoutDependentOnChildren( Dimension::Type dimension )
784 {
785   return RelayoutDependentOnChildrenBase( dimension );
786 }
787
788 void Control::OnCalculateRelayoutSize( Dimension::Type dimension )
789 {
790 }
791
792 void Control::OnLayoutNegotiated( float size, Dimension::Type dimension )
793 {
794 }
795
796 void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
797 {
798   mImpl->SignalConnected( slotObserver, callback );
799 }
800
801 void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
802 {
803   mImpl->SignalDisconnected( slotObserver, callback );
804 }
805
806 Control& GetImplementation( Dali::Toolkit::Control& handle )
807 {
808   CustomActorImpl& customInterface = handle.GetImplementation();
809   // downcast to control
810   Control& impl = dynamic_cast< Internal::Control& >( customInterface );
811   return impl;
812 }
813
814 const Control& GetImplementation( const Dali::Toolkit::Control& handle )
815 {
816   const CustomActorImpl& customInterface = handle.GetImplementation();
817   // downcast to control
818   const Control& impl = dynamic_cast< const Internal::Control& >( customInterface );
819   return impl;
820 }
821
822 Toolkit::Control::AccessibilityActivateSignalType &Control::AccessibilityActivateSignal()
823 {
824   return mImpl->mAccessibilityActivateSignal;
825 }
826
827 Dali::Accessibility::Accessible *Control::GetAccessibilityObject(Dali::Actor actor)
828 {
829   if( actor )
830   {
831     auto q = Dali::Toolkit::Control::DownCast( actor );
832     if( q )
833     {
834       auto q2 = static_cast< Internal::Control* >( &q.GetImplementation() );
835       if( !q2->mImpl->accessibilityObject )
836         q2->mImpl->accessibilityObject =
837             q2->mImpl->accessibilityConstructor( actor );
838       return q2->mImpl->accessibilityObject.get();
839     }
840   }
841   return nullptr;
842 }
843
844 void Control::SetAccessibilityConstructor(
845     std::function< std::unique_ptr< Dali::Accessibility::Accessible >( Dali::Actor ) >
846         constructor )
847 {
848   mImpl->accessibilityConstructor = constructor;
849 }
850
851 std::string Control::AccessibleImpl::GetName() { return self.GetName(); }
852 std::string Control::AccessibleImpl::GetDescription() { return ""; }
853 Dali::Accessibility::Accessible* Control::AccessibleImpl::GetParent()
854 {
855   return Dali::Accessibility::Accessible::Get( self.GetParent() );
856 }
857 size_t Control::AccessibleImpl::GetChildCount() { return self.GetChildCount(); }
858 Dali::Accessibility::Accessible*
859 Control::AccessibleImpl::GetChildAtIndex( size_t index )
860 {
861   return Dali::Accessibility::Accessible::Get(
862       self.GetChildAt( static_cast< unsigned int >( index ) ) );
863 }
864 size_t Control::AccessibleImpl::GetIndexInParent()
865 {
866   auto s = self;
867   auto parent = s.GetParent();
868   if( !parent )
869     throw Dali::Accessibility::AccessibleError(
870         "can't call GetIndexInParent on object '" + GetAddress().ToString() +
871         "' without parent" );
872   auto count = parent.GetChildCount();
873   for( auto i = 0u; i < count; ++i )
874   {
875     auto c = parent.GetChildAt( i );
876     if( c == s )
877       return i;
878   }
879   throw Dali::Accessibility::AccessibleError(
880       "object '" + GetAddress().ToString() + "' isn't child of it's parent" );
881 }
882
883 Dali::Accessibility::Role Control::AccessibleImpl::GetRole() { return role; }
884
885 void Control::AccessibilitySetAttribute( const std::string& key,
886                                          const std::string value )
887 {
888   return mImpl->AccessibilitySetAttribute( key, value );
889 }
890
891 std::string Control::AccessibilityGetAttribute( const std::string& key )
892 {
893   return mImpl->AccessibilityGetAttribute( key );
894 }
895
896 void Control::AccessibilityEraseAttribute( std::string& key )
897 {
898   return mImpl->AccessibilityEraseAttribute( key );
899 }
900
901 bool Control::AccessibleImpl::CalculateIsVisible() const
902 {
903   auto parent = self.GetParent();
904   if( parent )
905   {
906     auto p = Accessible::Get( parent );
907     auto p2 = dynamic_cast< AccessibleImpl* >( p );
908     if( p2 && !p2->CalculateIsVisible() )
909       return false;
910   }
911   auto stage = Stage::GetCurrent();
912   if( stage && self.OnStage() )
913   {
914     auto position =
915         self.GetProperty( Dali::DevelActor::Property::SCREEN_POSITION )
916             .Get< Vector2 >();
917     auto size = stage.GetSize();
918     if( position.x >= 0 && position.x < size.x )
919       return true;
920   }
921   return false;
922 }
923
924 Dali::Accessibility::States Control::AccessibleImpl::CalculateStates()
925 {
926   Dali::Accessibility::States s;
927   s[Dali::Accessibility::State::Highlightable] = true;
928   s[Dali::Accessibility::State::Enabled] = true;
929   s[Dali::Accessibility::State::Sensitive] = true;
930   if( self.IsVisible() )
931     s[Dali::Accessibility::State::Showing] = true;
932   if( modal )
933   {
934     s[Dali::Accessibility::State::Modal] = true;
935   }
936   s[Dali::Accessibility::State::Visible] = CalculateIsVisible();
937   auto am = Toolkit::AccessibilityManager::Get();
938   if( self == am.GetCurrentFocusActor() )
939     s[Dali::Accessibility::State::Highlighted] = true;
940   return s;
941 }
942
943 Dali::Accessibility::States Control::AccessibleImpl::GetStates()
944 {
945   return CalculateStates();
946 }
947
948 Dali::Accessibility::Attributes Control::AccessibleImpl::GetAttributes()
949 {
950   std::unordered_map< std::string, std::string > attribute_map;
951   auto q = Dali::Toolkit::Control::DownCast( self );
952   auto w =
953       q.GetProperty( Dali::Toolkit::Control::Property::ACCESSIBILITY_ATTRIBUTES );
954   auto z = w.GetMap();
955
956   if( z )
957   {
958     auto map_size = z->Count();
959
960     for( unsigned int i = 0; i < map_size; i++ )
961     {
962       auto map_key = z->GetKeyAt( i );
963       if( map_key.type == Property::Key::STRING )
964       {
965         std::string map_value;
966         if( z->GetValue( i ).Get( map_value ) )
967         {
968           attribute_map.emplace( std::move( map_key.stringKey ),
969                                  std::move( map_value ) );
970         }
971       }
972     }
973   }
974
975   return attribute_map;
976 }
977
978 Dali::Accessibility::ComponentLayer Control::AccessibleImpl::GetLayer()
979 {
980   return Dali::Accessibility::ComponentLayer::Window;
981 }
982
983 Dali::Accessibility::Rectangle
984 Control::AccessibleImpl::GetExtents( Dali::Accessibility::CoordType ctype )
985 {
986   Vector2 screenPosition =
987       self.GetProperty( Dali::DevelActor::Property::SCREEN_POSITION )
988           .Get< Vector2 >();
989   Vector3 size = self.GetCurrentSize() * self.GetCurrentWorldScale();
990   bool positionUsesAnchorPoint =
991       self.GetProperty( Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
992           .Get< bool >();
993   Vector3 anchorPointOffSet =
994       size * ( positionUsesAnchorPoint ? self.GetCurrentAnchorPoint()
995                                        : AnchorPoint::TOP_LEFT );
996   Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x,
997                               screenPosition.y - anchorPointOffSet.y );
998
999   return {Dali::Accessibility::Point( (int)position.x, (int)position.y ),
1000           Dali::Accessibility::Size( (int)size.x, (int)size.y )};
1001 }
1002
1003 int Control::AccessibleImpl::GetMdiZOrder() { return 0; }
1004 bool Control::AccessibleImpl::GrabFocus() { return false; }
1005 double Control::AccessibleImpl::GetAlpha() { return 0; }
1006 bool Control::AccessibleImpl::SetExtents( Dali::Accessibility::Rectangle rect,
1007                                           Dali::Accessibility::CoordType ctype )
1008 {
1009   return false;
1010 }
1011 bool Control::AccessibleImpl::GrabHighlight()
1012 {
1013   auto am = Toolkit::AccessibilityManager::Get();
1014   auto old = am.GetCurrentFocusActor();
1015   if( old != self )
1016   {
1017     if( old )
1018     {
1019       auto c = dynamic_cast< Dali::Accessibility::Component* >(
1020           GetAccessibilityObject( old ) );
1021       if( c )
1022         c->ClearHighlight();
1023     }
1024     return am.SetCurrentFocusActor( self );
1025   }
1026   return false;
1027 }
1028 bool Control::AccessibleImpl::ClearHighlight()
1029 {
1030   auto am = Toolkit::AccessibilityManager::Get();
1031   if( am.GetCurrentFocusActor() == self )
1032   {
1033     am.ClearFocus();
1034     return true;
1035   }
1036   return false;
1037 }
1038 int Control::AccessibleImpl::GetHighlightIndex() { return 0; }
1039
1040 std::string Control::AccessibleImpl::GetActionName( size_t index )
1041 {
1042   if( index >= GetActionCount() )
1043     throw Dali::Accessibility::AccessibleError(
1044         "index " + std::to_string( index ) + " is too large for action count " +
1045         std::to_string( GetActionCount() ) );
1046    Dali::TypeInfo type;
1047   self.GetTypeInfo( type );
1048   if( !type )
1049     throw Dali::Accessibility::AccessibleError(
1050         "GetActionName failed for object '" + GetAddress().ToString() +
1051         "' due to the lack of TypeInfo." );
1052   return type.GetActionName( index );
1053 }
1054 std::string Control::AccessibleImpl::GetLocalizedActionName( size_t index )
1055 {
1056   // TODO: add localization
1057   return GetActionName( index );
1058 }
1059 std::string Control::AccessibleImpl::GetActionDescription( size_t index )
1060 {
1061   if( index >= GetActionCount() )
1062     throw Dali::Accessibility::AccessibleError(
1063         "index " + std::to_string( index ) + " is too large for action count " +
1064         std::to_string( GetActionCount() ) );
1065    return "";
1066 }
1067 size_t Control::AccessibleImpl::GetActionCount()
1068 {
1069    Dali::TypeInfo type;
1070   self.GetTypeInfo( type );
1071   if( !type )
1072     throw Dali::Accessibility::AccessibleError(
1073         "GetActionCount failed for object '" + GetAddress().ToString() +
1074         "' due to the lack of TypeInfo." );
1075    return type.GetActionCount();
1076 }
1077 std::string Control::AccessibleImpl::GetActionKeyBinding( size_t index )
1078 {
1079   if( index >= GetActionCount() )
1080     throw Dali::Accessibility::AccessibleError(
1081         "index " + std::to_string( index ) + " is too large for action count " +
1082         std::to_string( GetActionCount() ) );
1083    return "";
1084 }
1085 bool Control::AccessibleImpl::DoAction( size_t index )
1086 {
1087   std::string actionName = GetActionName( index );
1088   return self.DoAction( actionName, {} );
1089 }
1090
1091 } // namespace Internal
1092
1093 } // namespace Toolkit
1094
1095 } // namespace Dali