Merge "use string_view to avoid string copy" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / control / control-data-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 "control-data-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali-toolkit/public-api/dali-toolkit-common.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/devel-api/object/handle-devel.h>
25 #include <dali/devel-api/scripting/enum-helper.h>
26 #include <dali/devel-api/scripting/scripting.h>
27 #include <dali/integration-api/debug.h>
28 #include <dali/public-api/object/type-registry-helper.h>
29 #include <dali/integration-api/adaptor-framework/adaptor.h>
30 #include <dali/devel-api/common/stage.h>
31 #include <dali-toolkit/public-api/controls/control.h>
32 #include <dali/public-api/object/object-registry.h>
33 #include <dali/devel-api/adaptor-framework/accessibility.h>
34 #include <dali-toolkit/public-api/controls/control-impl.h>
35 #include <dali/devel-api/actors/actor-devel.h>
36 #include <cstring>
37 #include <limits>
38
39 // INTERNAL INCLUDES
40 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
41 #include <dali-toolkit/public-api/visuals/image-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/controls/control-wrapper-impl.h>
46 #include <dali-toolkit/internal/styling/style-manager-impl.h>
47 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
48 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
49 #include <dali-toolkit/public-api/controls/image-view/image-view.h>
50
51 namespace
52 {
53   const std::string READING_INFO_TYPE_NAME = "name";
54   const std::string READING_INFO_TYPE_ROLE = "role";
55   const std::string READING_INFO_TYPE_DESCRIPTION = "description";
56   const std::string READING_INFO_TYPE_STATE = "state";
57   const std::string READING_INFO_TYPE_ATTRIBUTE_NAME = "reading_info_type";
58   const std::string READING_INFO_TYPE_SEPARATOR = "|";
59 }
60
61 namespace Dali
62 {
63
64 namespace Toolkit
65 {
66
67 namespace Internal
68 {
69
70 extern const Dali::Scripting::StringEnum ControlStateTable[];
71 extern const unsigned int ControlStateTableCount;
72
73
74 // Not static or anonymous - shared with other translation units
75 const Scripting::StringEnum ControlStateTable[] = {
76   { "NORMAL",   Toolkit::DevelControl::NORMAL   },
77   { "FOCUSED",  Toolkit::DevelControl::FOCUSED  },
78   { "DISABLED", Toolkit::DevelControl::DISABLED },
79 };
80 const unsigned int ControlStateTableCount = sizeof( ControlStateTable ) / sizeof( ControlStateTable[0] );
81
82
83
84 namespace
85 {
86
87 #if defined(DEBUG_ENABLED)
88 Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_CONTROL_VISUALS");
89 #endif
90
91
92 template<typename T>
93 void Remove( Dictionary<T>& keyValues, const std::string& name )
94 {
95   keyValues.Remove(name);
96 }
97
98 void Remove( DictionaryKeys& keys, const std::string& name )
99 {
100   DictionaryKeys::iterator iter = std::find( keys.begin(), keys.end(), name );
101   if( iter != keys.end())
102   {
103     keys.erase(iter);
104   }
105 }
106
107 /**
108  *  Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
109  */
110 bool FindVisual( Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
111 {
112   for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
113   {
114     if ( (*iter)->index ==  targetIndex )
115     {
116       return true;
117     }
118   }
119   return false;
120 }
121
122 /**
123  *  Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
124  */
125 bool FindVisual( std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
126 {
127   for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
128   {
129     Toolkit::Visual::Base visual = (*iter)->visual;
130     if( visual && visual.GetName() == visualName )
131     {
132       return true;
133     }
134   }
135   return false;
136 }
137
138 void FindChangableVisuals( Dictionary<Property::Map>& stateVisualsToAdd,
139                            Dictionary<Property::Map>& stateVisualsToChange,
140                            DictionaryKeys& stateVisualsToRemove)
141 {
142   DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove;
143
144   for( DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin();
145        iter != copyOfStateVisualsToRemove.end(); ++iter )
146   {
147     const std::string& visualName = (*iter);
148     Property::Map* toMap = stateVisualsToAdd.Find( visualName );
149     if( toMap )
150     {
151       stateVisualsToChange.Add( visualName, *toMap );
152       stateVisualsToAdd.Remove( visualName );
153       Remove( stateVisualsToRemove, visualName );
154     }
155   }
156 }
157
158 Toolkit::Visual::Base GetVisualByName(
159   const RegisteredVisualContainer& visuals,
160   const std::string& visualName )
161 {
162   Toolkit::Visual::Base visualHandle;
163
164   RegisteredVisualContainer::Iterator iter;
165   for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
166   {
167     Toolkit::Visual::Base visual = (*iter)->visual;
168     if( visual && visual.GetName() == visualName )
169     {
170       visualHandle = visual;
171       break;
172     }
173   }
174   return visualHandle;
175 }
176
177 Toolkit::Visual::Base GetVisualByIndex(
178   const RegisteredVisualContainer& visuals,
179   Property::Index                  index)
180 {
181   Toolkit::Visual::Base visualHandle;
182
183   RegisteredVisualContainer::Iterator iter;
184   for(iter = visuals.Begin(); iter != visuals.End(); iter++)
185   {
186     if((*iter)->index == index)
187     {
188       visualHandle = (*iter)->visual;
189       break;
190     }
191   }
192   return visualHandle;
193 }
194
195 /**
196  * Move visual from source to destination container
197  */
198 void MoveVisual( RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source, RegisteredVisualContainer& destination )
199 {
200    Toolkit::Visual::Base visual = (*sourceIter)->visual;
201    if( visual )
202    {
203      RegisteredVisual* rv = source.Release( sourceIter );
204      destination.PushBack( rv );
205    }
206 }
207
208 /**
209  * Performs actions as requested using the action name.
210  * @param[in] object The object on which to perform the action.
211  * @param[in] actionName The action to perform.
212  * @param[in] attributes The attributes with which to perfrom this action.
213  * @return true if action has been accepted by this control
214  */
215 const char* ACTION_ACCESSIBILITY_ACTIVATED         = "accessibilityActivated";
216 const char* ACTION_ACCESSIBILITY_READING_CANCELLED = "ReadingCancelled";
217 const char* ACTION_ACCESSIBILITY_READING_PAUSED    = "ReadingPaused";
218 const char* ACTION_ACCESSIBILITY_READING_RESUMED   = "ReadingResumed";
219 const char* ACTION_ACCESSIBILITY_READING_SKIPPED   = "ReadingSkipped";
220 const char* ACTION_ACCESSIBILITY_READING_STOPPED   = "ReadingStopped";
221
222 static bool DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
223 {
224   bool ret = true;
225
226   Dali::BaseHandle handle( object );
227
228   Toolkit::Control control = Toolkit::Control::DownCast( handle );
229
230   DALI_ASSERT_ALWAYS( control );
231
232   if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_ACTIVATED ) ||
233      actionName == "activate" )
234   {
235     // if cast succeeds there is an implementation so no need to check
236     if( !DevelControl::AccessibilityActivateSignal( control ).Empty() )
237       DevelControl::AccessibilityActivateSignal( control ).Emit();
238     else ret = Internal::GetImplementation( control ).OnAccessibilityActivated();
239   }
240   else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_SKIPPED ) )
241   {
242     // if cast succeeds there is an implementation so no need to check
243     if( !DevelControl::AccessibilityReadingSkippedSignal( control ).Empty() )
244       DevelControl::AccessibilityReadingSkippedSignal( control ).Emit();
245   }
246   else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_PAUSED ) )
247   {
248     // if cast succeeds there is an implementation so no need to check
249     if( !DevelControl::AccessibilityReadingPausedSignal( control ).Empty() )
250       DevelControl::AccessibilityReadingPausedSignal( control ).Emit();
251   }
252   else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_RESUMED ) )
253   {
254     // if cast succeeds there is an implementation so no need to check
255     if( !DevelControl::AccessibilityReadingResumedSignal( control ).Empty() )
256       DevelControl::AccessibilityReadingResumedSignal( control ).Emit();
257   }
258   else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_CANCELLED ) )
259   {
260     // if cast succeeds there is an implementation so no need to check
261     if( !DevelControl::AccessibilityReadingCancelledSignal( control ).Empty() )
262       DevelControl::AccessibilityReadingCancelledSignal( control ).Emit();
263   }
264   else if( 0 == strcmp( actionName.c_str(), ACTION_ACCESSIBILITY_READING_STOPPED ) )
265   {
266     // if cast succeeds there is an implementation so no need to check
267     if(!DevelControl::AccessibilityReadingStoppedSignal( control ).Empty())
268       DevelControl::AccessibilityReadingStoppedSignal( control ).Emit();
269   } else
270   {
271     ret = false;
272   }
273   return ret;
274 }
275
276 /**
277  * Connects a callback function with the object's signals.
278  * @param[in] object The object providing the signal.
279  * @param[in] tracker Used to disconnect the signal.
280  * @param[in] signalName The signal to connect to.
281  * @param[in] functor A newly allocated FunctorDelegate.
282  * @return True if the signal was connected.
283  * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
284  */
285 const char* SIGNAL_KEY_EVENT = "keyEvent";
286 const char* SIGNAL_KEY_INPUT_FOCUS_GAINED = "keyInputFocusGained";
287 const char* SIGNAL_KEY_INPUT_FOCUS_LOST = "keyInputFocusLost";
288 const char* SIGNAL_TAPPED = "tapped";
289 const char* SIGNAL_PANNED = "panned";
290 const char* SIGNAL_PINCHED = "pinched";
291 const char* SIGNAL_LONG_PRESSED = "longPressed";
292 const char* SIGNAL_GET_NAME = "getName";
293 const char* SIGNAL_GET_DESCRIPTION = "getDescription";
294 const char* SIGNAL_DO_GESTURE = "doGesture";
295 static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
296 {
297   Dali::BaseHandle handle( object );
298
299   bool connected( false );
300   Toolkit::Control control = Toolkit::Control::DownCast( handle );
301   if ( control )
302   {
303     Internal::Control& controlImpl( Internal::GetImplementation( control ) );
304     connected = true;
305
306     if ( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_EVENT ) )
307     {
308       controlImpl.KeyEventSignal().Connect( tracker, functor );
309     }
310     else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_GAINED ) )
311     {
312       controlImpl.KeyInputFocusGainedSignal().Connect( tracker, functor );
313     }
314     else if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_INPUT_FOCUS_LOST ) )
315     {
316       controlImpl.KeyInputFocusLostSignal().Connect( tracker, functor );
317     }
318     else if( 0 == strcmp( signalName.c_str(), SIGNAL_TAPPED ) )
319     {
320       controlImpl.EnableGestureDetection( GestureType::TAP );
321       controlImpl.GetTapGestureDetector().DetectedSignal().Connect( tracker, functor );
322     }
323     else if( 0 == strcmp( signalName.c_str(), SIGNAL_PANNED ) )
324     {
325       controlImpl.EnableGestureDetection( GestureType::PAN );
326       controlImpl.GetPanGestureDetector().DetectedSignal().Connect( tracker, functor );
327     }
328     else if( 0 == strcmp( signalName.c_str(), SIGNAL_PINCHED ) )
329     {
330       controlImpl.EnableGestureDetection( GestureType::PINCH );
331       controlImpl.GetPinchGestureDetector().DetectedSignal().Connect( tracker, functor );
332     }
333     else if( 0 == strcmp( signalName.c_str(), SIGNAL_LONG_PRESSED ) )
334     {
335       controlImpl.EnableGestureDetection( GestureType::LONG_PRESS );
336       controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect( tracker, functor );
337     }
338     else if( 0 == strcmp( signalName.c_str(), SIGNAL_GET_NAME ) )
339     {
340       DevelControl::AccessibilityGetNameSignal( control ).Connect( tracker, functor );
341     }
342     else if( 0 == strcmp( signalName.c_str(), SIGNAL_GET_DESCRIPTION ) )
343     {
344       DevelControl::AccessibilityGetDescriptionSignal( control ).Connect( tracker, functor );
345     }
346     else if( 0 == strcmp( signalName.c_str(), SIGNAL_DO_GESTURE ) )
347     {
348       DevelControl::AccessibilityDoGestureSignal( control ).Connect( tracker, functor );
349     }
350
351   }
352   return connected;
353 }
354
355 /**
356  * Creates control through type registry
357  */
358 BaseHandle Create()
359 {
360   return Internal::Control::New();
361 }
362 // Setup signals and actions using the type-registry.
363 DALI_TYPE_REGISTRATION_BEGIN( Control, CustomActor, Create );
364
365 // Note: Properties are registered separately below.
366
367 SignalConnectorType registerSignal1( typeRegistration, SIGNAL_KEY_EVENT, &DoConnectSignal );
368 SignalConnectorType registerSignal2( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_GAINED, &DoConnectSignal );
369 SignalConnectorType registerSignal3( typeRegistration, SIGNAL_KEY_INPUT_FOCUS_LOST, &DoConnectSignal );
370 SignalConnectorType registerSignal4( typeRegistration, SIGNAL_TAPPED, &DoConnectSignal );
371 SignalConnectorType registerSignal5( typeRegistration, SIGNAL_PANNED, &DoConnectSignal );
372 SignalConnectorType registerSignal6( typeRegistration, SIGNAL_PINCHED, &DoConnectSignal );
373 SignalConnectorType registerSignal7( typeRegistration, SIGNAL_LONG_PRESSED, &DoConnectSignal );
374 SignalConnectorType registerSignal8( typeRegistration, SIGNAL_GET_NAME, &DoConnectSignal );
375 SignalConnectorType registerSignal9( typeRegistration, SIGNAL_GET_DESCRIPTION, &DoConnectSignal );
376 SignalConnectorType registerSignal10( typeRegistration, SIGNAL_DO_GESTURE, &DoConnectSignal );
377
378 TypeAction registerAction1( typeRegistration, "activate", &DoAction );
379 TypeAction registerAction2( typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &DoAction );
380 TypeAction registerAction3( typeRegistration, ACTION_ACCESSIBILITY_READING_SKIPPED, &DoAction );
381 TypeAction registerAction4( typeRegistration, ACTION_ACCESSIBILITY_READING_CANCELLED, &DoAction );
382 TypeAction registerAction5( typeRegistration, ACTION_ACCESSIBILITY_READING_STOPPED, &DoAction );
383 TypeAction registerAction6( typeRegistration, ACTION_ACCESSIBILITY_READING_PAUSED, &DoAction );
384 TypeAction registerAction7( typeRegistration, ACTION_ACCESSIBILITY_READING_RESUMED, &DoAction );
385
386 DALI_TYPE_REGISTRATION_END()
387
388 /**
389  * @brief Iterate through given container and setOffScene any visual found
390  *
391  * @param[in] container Container of visuals
392  * @param[in] parent Parent actor to remove visuals from
393  */
394 void SetVisualsOffScene( const RegisteredVisualContainer& container, Actor parent )
395 {
396   for( auto iter = container.Begin(), end = container.End() ; iter!= end; iter++)
397   {
398     if( (*iter)->visual )
399     {
400       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::SetOffScene Setting visual(%d) off stage\n", (*iter)->index );
401       Toolkit::GetImplementation((*iter)->visual).SetOffScene( parent );
402     }
403   }
404 }
405
406 } // unnamed namespace
407
408
409 // Properties registered without macro to use specific member variables.
410 const PropertyRegistration Control::Impl::PROPERTY_1( typeRegistration, "styleName",              Toolkit::Control::Property::STYLE_NAME,                   Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
411 const PropertyRegistration Control::Impl::PROPERTY_4( typeRegistration, "keyInputFocus",          Toolkit::Control::Property::KEY_INPUT_FOCUS,              Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
412 const PropertyRegistration Control::Impl::PROPERTY_5( typeRegistration, "background",             Toolkit::Control::Property::BACKGROUND,                   Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
413 const PropertyRegistration Control::Impl::PROPERTY_6( typeRegistration, "margin",                 Toolkit::Control::Property::MARGIN,                       Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
414 const PropertyRegistration Control::Impl::PROPERTY_7( typeRegistration, "padding",                Toolkit::Control::Property::PADDING,                      Property::EXTENTS, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
415 const PropertyRegistration Control::Impl::PROPERTY_8( typeRegistration, "tooltip",                Toolkit::DevelControl::Property::TOOLTIP,                 Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
416 const PropertyRegistration Control::Impl::PROPERTY_9( typeRegistration, "state",                  Toolkit::DevelControl::Property::STATE,                   Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
417 const PropertyRegistration Control::Impl::PROPERTY_10( typeRegistration, "subState",               Toolkit::DevelControl::Property::SUB_STATE,               Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
418 const PropertyRegistration Control::Impl::PROPERTY_11( typeRegistration, "leftFocusableActorId",   Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
419 const PropertyRegistration Control::Impl::PROPERTY_12( typeRegistration, "rightFocusableActorId", Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID,Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
420 const PropertyRegistration Control::Impl::PROPERTY_13( typeRegistration, "upFocusableActorId",    Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID,   Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
421 const PropertyRegistration Control::Impl::PROPERTY_14( typeRegistration, "downFocusableActorId",  Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID, Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
422 const PropertyRegistration Control::Impl::PROPERTY_15( typeRegistration, "shadow",                Toolkit::DevelControl::Property::SHADOW,                  Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
423 const PropertyRegistration Control::Impl::PROPERTY_16( typeRegistration, "accessibilityAttributes",         Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES,         Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
424 const PropertyRegistration Control::Impl::PROPERTY_17( typeRegistration, "accessibilityName",              Toolkit::DevelControl::Property::ACCESSIBILITY_NAME,               Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
425 const PropertyRegistration Control::Impl::PROPERTY_18( typeRegistration, "accessibilityDescription",       Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION,         Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
426 const PropertyRegistration Control::Impl::PROPERTY_19( typeRegistration, "accessibilityTranslationDomain", Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN, Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
427 const PropertyRegistration Control::Impl::PROPERTY_20( typeRegistration, "accessibilityRole",              Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE,               Property::INTEGER, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
428 const PropertyRegistration Control::Impl::PROPERTY_21( typeRegistration, "accessibilityHighlightable",     Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE,      Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
429 const PropertyRegistration Control::Impl::PROPERTY_22( typeRegistration, "accessibilityAnimated",          Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED,      Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
430
431 Control::Impl::Impl( Control& controlImpl )
432 : mControlImpl( controlImpl ),
433   mState( Toolkit::DevelControl::NORMAL ),
434   mSubStateName(""),
435   mLeftFocusableActorId( -1 ),
436   mRightFocusableActorId( -1 ),
437   mUpFocusableActorId( -1 ),
438   mDownFocusableActorId( -1 ),
439   mStyleName(""),
440   mBackgroundColor(Color::TRANSPARENT),
441   mStartingPinchScale(nullptr),
442   mMargin( 0, 0, 0, 0 ),
443   mPadding( 0, 0, 0, 0 ),
444   mKeyEventSignal(),
445   mKeyInputFocusGainedSignal(),
446   mKeyInputFocusLostSignal(),
447   mResourceReadySignal(),
448   mVisualEventSignal(),
449   mAccessibilityGetNameSignal(),
450   mAccessibilityGetDescriptionSignal(),
451   mAccessibilityDoGestureSignal(),
452   mPinchGestureDetector(),
453   mPanGestureDetector(),
454   mTapGestureDetector(),
455   mLongPressGestureDetector(),
456   mTooltip( NULL ),
457   mInputMethodContext(),
458   mIdleCallback(nullptr),
459   mFlags( Control::ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
460   mIsKeyboardNavigationSupported( false ),
461   mIsKeyboardFocusGroup( false ),
462   mIsEmittingResourceReadySignal(false),
463   mNeedToEmitResourceReady(false)
464 {
465   Dali::Accessibility::Accessible::RegisterControlAccessibilityGetter(
466       []( Dali::Actor actor ) -> Dali::Accessibility::Accessible* {
467         return Control::Impl::GetAccessibilityObject( actor );
468       } );
469
470   accessibilityConstructor =  []( Dali::Actor actor ) -> std::unique_ptr< Dali::Accessibility::Accessible > {
471         return std::unique_ptr< Dali::Accessibility::Accessible >( new AccessibleImpl( actor,
472                                 Dali::Accessibility::Role::UNKNOWN ) );
473       };
474
475   size_t len = static_cast<size_t>(Dali::Accessibility::RelationType::MAX_COUNT);
476   mAccessibilityRelations.reserve(len);
477   for (auto i = 0u; i < len; ++i)
478   {
479     mAccessibilityRelations.push_back({});
480   }
481 }
482
483 Control::Impl::~Impl()
484 {
485   for( auto&& iter : mVisuals )
486   {
487     StopObservingVisual( iter->visual );
488   }
489
490   for( auto&& iter : mRemoveVisuals )
491   {
492     StopObservingVisual( iter->visual );
493   }
494
495   AccessibilityDeregister();
496   // All gesture detectors will be destroyed so no need to disconnect.
497   delete mStartingPinchScale;
498
499   if(mIdleCallback && Adaptor::IsAvailable())
500   {
501     // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
502     Adaptor::Get().RemoveIdle(mIdleCallback);
503   }
504 }
505
506 Control::Impl& Control::Impl::Get( Internal::Control& internalControl )
507 {
508   return *internalControl.mImpl;
509 }
510
511 const Control::Impl& Control::Impl::Get( const Internal::Control& internalControl )
512 {
513   return *internalControl.mImpl;
514 }
515
516 // Gesture Detection Methods
517 void Control::Impl::PinchDetected(Actor actor, const PinchGesture& pinch)
518 {
519   mControlImpl.OnPinch(pinch);
520 }
521
522 void Control::Impl::PanDetected(Actor actor, const PanGesture& pan)
523 {
524   mControlImpl.OnPan(pan);
525 }
526
527 void Control::Impl::TapDetected(Actor actor, const TapGesture& tap)
528 {
529   mControlImpl.OnTap(tap);
530 }
531
532 void Control::Impl::LongPressDetected(Actor actor, const LongPressGesture& longPress)
533 {
534   mControlImpl.OnLongPress(longPress);
535 }
536
537 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual )
538 {
539   RegisterVisual( index, visual, VisualState::ENABLED, DepthIndexValue::NOT_SET );
540 }
541
542 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, int depthIndex )
543 {
544   RegisterVisual( index, visual, VisualState::ENABLED, DepthIndexValue::SET, depthIndex );
545 }
546
547 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled )
548 {
549   RegisterVisual( index, visual, ( enabled ? VisualState::ENABLED : VisualState::DISABLED ), DepthIndexValue::NOT_SET );
550 }
551
552 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, bool enabled, int depthIndex )
553 {
554   RegisterVisual( index, visual, ( enabled ? VisualState::ENABLED : VisualState::DISABLED ), DepthIndexValue::SET, depthIndex );
555 }
556
557 void Control::Impl::RegisterVisual( Property::Index index, Toolkit::Visual::Base& visual, VisualState::Type enabled, DepthIndexValue::Type depthIndexValueSet, int depthIndex )
558 {
559   DALI_LOG_INFO( gLogFilter, Debug::Concise, "RegisterVisual:%d \n", index );
560
561   bool visualReplaced ( false );
562   Actor self = mControlImpl.Self();
563
564   // Set the depth index, if not set by caller this will be either the current visual depth, max depth of all visuals
565   // or zero.
566   int requiredDepthIndex = visual.GetDepthIndex();
567
568   if( depthIndexValueSet == DepthIndexValue::SET )
569   {
570     requiredDepthIndex = depthIndex;
571   }
572
573   // Visual replacement, existing visual should only be removed from stage when replacement ready.
574   if( !mVisuals.Empty() )
575   {
576     RegisteredVisualContainer::Iterator registeredVisualsiter;
577     // Check if visual (index) is already registered, this is the current visual.
578     if( FindVisual( index, mVisuals, registeredVisualsiter ) )
579     {
580       Toolkit::Visual::Base& currentRegisteredVisual = (*registeredVisualsiter)->visual;
581       if( currentRegisteredVisual )
582       {
583         // Store current visual depth index as may need to set the replacement visual to same depth
584         const int currentDepthIndex = (*registeredVisualsiter)->visual.GetDepthIndex();
585
586         // No longer required to know if the replaced visual's resources are ready
587         StopObservingVisual( currentRegisteredVisual );
588
589         // If control staged and visual enabled then visuals will be swapped once ready
590         if(  self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) && enabled )
591         {
592           // Check if visual is currently in the process of being replaced ( is in removal container )
593           RegisteredVisualContainer::Iterator visualQueuedForRemoval;
594           if ( FindVisual( index, mRemoveVisuals, visualQueuedForRemoval ) )
595           {
596             // Visual with same index is already in removal container so current visual pending
597             // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
598             Toolkit::GetImplementation( currentRegisteredVisual ).SetOffScene( self );
599             mVisuals.Erase( registeredVisualsiter );
600           }
601           else
602           {
603             // current visual not already in removal container so add now.
604             DALI_LOG_INFO( gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %d \n", index );
605             MoveVisual( registeredVisualsiter, mVisuals, mRemoveVisuals );
606           }
607         }
608         else
609         {
610           // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
611           mVisuals.Erase( registeredVisualsiter );
612         }
613
614         // If we've not set the depth-index value and the new visual does not have a depth index applied to it, then use the previously set depth-index for this index
615         if( ( depthIndexValueSet == DepthIndexValue::NOT_SET ) &&
616             ( visual.GetDepthIndex() == 0 ) )
617         {
618           requiredDepthIndex = currentDepthIndex;
619         }
620       }
621
622       visualReplaced = true;
623     }
624   }
625
626   // If not set, set the name of the visual to the same name as the control's property.
627   // ( If the control has been type registered )
628   if( visual.GetName().empty() )
629   {
630     // returns empty string if index is not found as long as index is not -1
631     std::string visualName = self.GetPropertyName( index );
632     if( !visualName.empty() )
633     {
634       DALI_LOG_INFO( gLogFilter, Debug::Concise, "Setting visual name for property %d to %s\n",
635                      index, visualName.c_str() );
636       visual.SetName( visualName );
637     }
638   }
639
640   if( !visualReplaced ) // New registration entry
641   {
642     // If we've not set the depth-index value, we have more than one visual and the visual does not have a depth index, then set it to be the highest
643     if( ( depthIndexValueSet == DepthIndexValue::NOT_SET ) &&
644         ( mVisuals.Size() > 0 ) &&
645         ( visual.GetDepthIndex() == 0 ) )
646     {
647       int maxDepthIndex = std::numeric_limits< int >::min();
648
649       RegisteredVisualContainer::ConstIterator iter;
650       const RegisteredVisualContainer::ConstIterator endIter = mVisuals.End();
651       for ( iter = mVisuals.Begin(); iter != endIter; iter++ )
652       {
653         const int visualDepthIndex = (*iter)->visual.GetDepthIndex();
654         if ( visualDepthIndex > maxDepthIndex )
655         {
656           maxDepthIndex = visualDepthIndex;
657         }
658       }
659       ++maxDepthIndex; // Add one to the current maximum depth index so that our added visual appears on top
660       requiredDepthIndex = std::max( 0, maxDepthIndex ); // Start at zero if maxDepth index belongs to a background
661     }
662   }
663
664   if( visual )
665   {
666     // Set determined depth index
667     visual.SetDepthIndex( requiredDepthIndex );
668
669     // Monitor when the visual resources are ready
670     StartObservingVisual( visual );
671
672     DALI_LOG_INFO( gLogFilter, Debug::Concise, "New Visual registration index[%d] depth[%d]\n", index, requiredDepthIndex );
673     RegisteredVisual* newRegisteredVisual  = new RegisteredVisual( index, visual,
674                                              ( enabled == VisualState::ENABLED ? true : false ),
675                                              ( visualReplaced && enabled ) ) ;
676     mVisuals.PushBack( newRegisteredVisual );
677
678     Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
679     // Put on stage if enabled and the control is already on the stage
680     if( ( enabled == VisualState::ENABLED ) && self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) )
681     {
682       visualImpl.SetOnScene( self );
683     }
684     else if( visualImpl.IsResourceReady() ) // When not being staged, check if visual already 'ResourceReady' before it was Registered. ( Resource may have been loaded already )
685     {
686       ResourceReady( visualImpl );
687     }
688
689   }
690
691   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::RegisterVisual() Registered %s(%d), enabled:%s\n",  visual.GetName().c_str(), index, enabled?"true":"false" );
692 }
693
694 void Control::Impl::UnregisterVisual( Property::Index index )
695 {
696   RegisteredVisualContainer::Iterator iter;
697   if ( FindVisual( index, mVisuals, iter ) )
698   {
699     // stop observing visual
700     StopObservingVisual( (*iter)->visual );
701
702     Actor self( mControlImpl.Self() );
703     Toolkit::GetImplementation((*iter)->visual).SetOffScene( self );
704     (*iter)->visual.Reset();
705     mVisuals.Erase( iter );
706   }
707
708   if( FindVisual( index, mRemoveVisuals, iter ) )
709   {
710     Actor self( mControlImpl.Self() );
711     Toolkit::GetImplementation( (*iter)->visual ).SetOffScene( self );
712     (*iter)->pending = false;
713     (*iter)->visual.Reset();
714     mRemoveVisuals.Erase( iter );
715   }
716 }
717
718 Toolkit::Visual::Base Control::Impl::GetVisual( Property::Index index ) const
719 {
720   RegisteredVisualContainer::Iterator iter;
721   if ( FindVisual( index, mVisuals, iter ) )
722   {
723     return (*iter)->visual;
724   }
725
726   return Toolkit::Visual::Base();
727 }
728
729 void Control::Impl::EnableVisual( Property::Index index, bool enable )
730 {
731   DALI_LOG_INFO( gLogFilter, Debug::General, "Control::EnableVisual(%d, %s)\n", index, enable?"T":"F");
732
733   RegisteredVisualContainer::Iterator iter;
734   if ( FindVisual( index, mVisuals, iter ) )
735   {
736     if (  (*iter)->enabled == enable )
737     {
738       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Visual %s(%d) already %s\n", (*iter)->visual.GetName().c_str(), index, enable?"enabled":"disabled");
739       return;
740     }
741
742     (*iter)->enabled = enable;
743     Actor parentActor = mControlImpl.Self();
744     if ( mControlImpl.Self().GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) ) // If control not on Scene then Visual will be added when SceneConnection is called.
745     {
746       if ( enable )
747       {
748         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) on stage \n", (*iter)->visual.GetName().c_str(), index );
749         Toolkit::GetImplementation((*iter)->visual).SetOnScene( parentActor );
750       }
751       else
752       {
753         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::EnableVisual Setting %s(%d) off stage \n", (*iter)->visual.GetName().c_str(), index );
754         Toolkit::GetImplementation((*iter)->visual).SetOffScene( parentActor );  // No need to call if control not staged.
755       }
756     }
757   }
758   else
759   {
760     DALI_LOG_WARNING( "Control::EnableVisual(%d, %s) FAILED - NO SUCH VISUAL\n", index, enable?"T":"F" );
761   }
762 }
763
764 bool Control::Impl::IsVisualEnabled( Property::Index index ) const
765 {
766   RegisteredVisualContainer::Iterator iter;
767   if ( FindVisual( index, mVisuals, iter ) )
768   {
769     return (*iter)->enabled;
770   }
771   return false;
772 }
773
774 void Control::Impl::StopObservingVisual( Toolkit::Visual::Base& visual )
775 {
776   Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
777
778   // Stop observing the visual
779   visualImpl.RemoveEventObserver( *this );
780 }
781
782 void Control::Impl::StartObservingVisual( Toolkit::Visual::Base& visual)
783 {
784   Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
785
786   // start observing the visual for events
787   visualImpl.AddEventObserver( *this );
788 }
789
790 // Called by a Visual when it's resource is ready
791 void Control::Impl::ResourceReady( Visual::Base& object)
792 {
793   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::Impl::ResourceReady() replacements pending[%d]\n", mRemoveVisuals.Count() );
794
795   Actor self = mControlImpl.Self();
796
797   // A resource is ready, find resource in the registered visuals container and get its index
798   for( auto registeredIter = mVisuals.Begin(),  end = mVisuals.End(); registeredIter != end; ++registeredIter )
799   {
800     Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation( (*registeredIter)->visual );
801
802     if( &object == &registeredVisualImpl )
803     {
804       RegisteredVisualContainer::Iterator visualToRemoveIter;
805       // Find visual with the same index in the removal container
806       // Set if off stage as it's replacement is now ready.
807       // Remove if from removal list as now removed from stage.
808       // Set Pending flag on the ready visual to false as now ready.
809       if( FindVisual( (*registeredIter)->index, mRemoveVisuals, visualToRemoveIter ) )
810       {
811         (*registeredIter)->pending = false;
812         Toolkit::GetImplementation( (*visualToRemoveIter)->visual ).SetOffScene( self );
813         mRemoveVisuals.Erase( visualToRemoveIter );
814       }
815       break;
816     }
817   }
818
819   // A visual is ready so control may need relayouting if staged
820   if ( self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) )
821   {
822     mControlImpl.RelayoutRequest();
823   }
824
825   // Emit signal if all enabled visuals registered by the control are ready.
826   if( IsResourceReady() )
827   {
828     // Reset the flag
829     mNeedToEmitResourceReady = false;
830
831     EmitResourceReadySignal();
832   }
833 }
834
835 void Control::Impl::NotifyVisualEvent( Visual::Base& object, Property::Index signalId )
836 {
837   for( auto registeredIter = mVisuals.Begin(),  end = mVisuals.End(); registeredIter != end; ++registeredIter )
838   {
839     Internal::Visual::Base& registeredVisualImpl = Toolkit::GetImplementation( (*registeredIter)->visual );
840     if( &object == &registeredVisualImpl )
841     {
842       Dali::Toolkit::Control handle( mControlImpl.GetOwner() );
843       mVisualEventSignal.Emit( handle, (*registeredIter)->index, signalId );
844       break;
845     }
846   }
847 }
848
849 bool Control::Impl::IsResourceReady() const
850 {
851   // Iterate through and check all the enabled visuals are ready
852   for( auto visualIter = mVisuals.Begin();
853          visualIter != mVisuals.End(); ++visualIter )
854   {
855     const Toolkit::Visual::Base visual = (*visualIter)->visual;
856     const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
857
858     // one of the enabled visuals is not ready
859     if( !visualImpl.IsResourceReady() && (*visualIter)->enabled )
860     {
861       return false;
862     }
863   }
864   return true;
865 }
866
867 Toolkit::Visual::ResourceStatus Control::Impl::GetVisualResourceStatus( Property::Index index ) const
868 {
869   RegisteredVisualContainer::Iterator iter;
870   if ( FindVisual( index, mVisuals, iter ) )
871   {
872     const Toolkit::Visual::Base visual = (*iter)->visual;
873     const Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
874     return visualImpl.GetResourceStatus( );
875   }
876
877   return Toolkit::Visual::ResourceStatus::PREPARING;
878 }
879
880
881
882 void Control::Impl::AddTransitions( Dali::Animation& animation,
883                                     const Toolkit::TransitionData& handle,
884                                     bool createAnimation )
885 {
886   // Setup a Transition from TransitionData.
887   const Internal::TransitionData& transitionData = Toolkit::GetImplementation( handle );
888   TransitionData::Iterator end = transitionData.End();
889   for( TransitionData::Iterator iter = transitionData.Begin() ;
890        iter != end; ++iter )
891   {
892     TransitionData::Animator* animator = (*iter);
893
894     Toolkit::Visual::Base visual = GetVisualByName( mVisuals, animator->objectName );
895
896     if( visual )
897     {
898 #if defined(DEBUG_ENABLED)
899       Dali::TypeInfo typeInfo;
900       ControlWrapper* controlWrapperImpl = dynamic_cast<ControlWrapper*>(&mControlImpl);
901       if( controlWrapperImpl )
902       {
903         typeInfo = controlWrapperImpl->GetTypeInfo();
904       }
905
906       DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Found %s visual for %s\n",
907                      visual.GetName().c_str(), typeInfo?typeInfo.GetName().c_str():"Unknown" );
908 #endif
909       Internal::Visual::Base& visualImpl = Toolkit::GetImplementation( visual );
910       visualImpl.AnimateProperty( animation, *animator );
911     }
912     else
913     {
914       DALI_LOG_INFO( gLogFilter, Debug::Concise, "CreateTransition: Could not find visual. Trying actors");
915       // Otherwise, try any actor children of control (Including the control)
916       Actor child = mControlImpl.Self().FindChildByName( animator->objectName );
917       if( child )
918       {
919         Property::Index propertyIndex = child.GetPropertyIndex( animator->propertyKey );
920         if( propertyIndex != Property::INVALID_INDEX )
921         {
922           if( animator->animate == false )
923           {
924             if( animator->targetValue.GetType() != Property::NONE )
925             {
926               child.SetProperty( propertyIndex, animator->targetValue );
927             }
928           }
929           else // animate the property
930           {
931             if( animator->initialValue.GetType() != Property::NONE )
932             {
933               child.SetProperty( propertyIndex, animator->initialValue );
934             }
935
936             if( createAnimation && !animation )
937             {
938               animation = Dali::Animation::New( 0.1f );
939             }
940
941             animation.AnimateTo( Property( child, propertyIndex ),
942                                  animator->targetValue,
943                                  animator->alphaFunction,
944                                  TimePeriod( animator->timePeriodDelay,
945                                              animator->timePeriodDuration ) );
946           }
947         }
948       }
949     }
950   }
951 }
952
953 Dali::Animation Control::Impl::CreateTransition( const Toolkit::TransitionData& transitionData )
954 {
955   Dali::Animation transition;
956
957   if( transitionData.Count() > 0 )
958   {
959     AddTransitions( transition, transitionData, true );
960   }
961   return transition;
962 }
963
964
965
966 void Control::Impl::DoAction( Dali::Property::Index visualIndex, Dali::Property::Index actionId, const Dali::Property::Value attributes )
967 {
968   RegisteredVisualContainer::Iterator iter;
969   if ( FindVisual( visualIndex, mVisuals, iter ) )
970   {
971     Toolkit::GetImplementation((*iter)->visual).DoAction( actionId, attributes );
972   }
973 }
974
975 void Control::Impl::AppendAccessibilityAttribute( const std::string& key,
976                                                const std::string value )
977 {
978   Property::Value* val = mAccessibilityAttributes.Find( key );
979   if( val )
980   {
981     mAccessibilityAttributes[key] = Property::Value( value );
982   }
983   else
984   {
985     mAccessibilityAttributes.Insert( key, value );
986   }
987 }
988
989 void Control::Impl::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
990 {
991   Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
992
993   if ( control )
994   {
995     Control& controlImpl( GetImplementation( control ) );
996
997     switch ( index )
998     {
999       case Toolkit::Control::Property::STYLE_NAME:
1000       {
1001         controlImpl.SetStyleName( value.Get< std::string >() );
1002         break;
1003       }
1004
1005       case Toolkit::DevelControl::Property::STATE:
1006       {
1007         bool withTransitions=true;
1008         const Property::Value* valuePtr=&value;
1009         const Property::Map* map = value.GetMap();
1010         if(map)
1011         {
1012           Property::Value* value2 = map->Find("withTransitions");
1013           if( value2 )
1014           {
1015             withTransitions = value2->Get<bool>();
1016           }
1017
1018           valuePtr = map->Find("state");
1019         }
1020
1021         if( valuePtr )
1022         {
1023           Toolkit::DevelControl::State state( controlImpl.mImpl->mState );
1024           if( Scripting::GetEnumerationProperty< Toolkit::DevelControl::State >( *valuePtr, ControlStateTable, ControlStateTableCount, state ) )
1025           {
1026             controlImpl.mImpl->SetState( state, withTransitions );
1027           }
1028         }
1029       }
1030       break;
1031
1032       case Toolkit::DevelControl::Property::SUB_STATE:
1033       {
1034         std::string subState;
1035         if( value.Get( subState ) )
1036         {
1037           controlImpl.mImpl->SetSubState( subState );
1038         }
1039       }
1040       break;
1041
1042       case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1043       {
1044         int focusId;
1045         if( value.Get( focusId ) )
1046         {
1047           controlImpl.mImpl->mLeftFocusableActorId = focusId;
1048         }
1049       }
1050       break;
1051
1052       case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1053       {
1054         int focusId;
1055         if( value.Get( focusId ) )
1056         {
1057           controlImpl.mImpl->mRightFocusableActorId = focusId;
1058         }
1059       }
1060       break;
1061
1062       case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1063       {
1064         std::string name;
1065         if( value.Get( name ) )
1066         {
1067           controlImpl.mImpl->mAccessibilityName = name;
1068           controlImpl.mImpl->mAccessibilityNameSet = true;
1069         }
1070         else
1071         {
1072           controlImpl.mImpl->mAccessibilityNameSet = false;
1073         }
1074       }
1075       break;
1076
1077       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1078       {
1079         std::string txt;
1080         if( value.Get( txt ) )
1081         {
1082           controlImpl.mImpl->mAccessibilityDescription = txt;
1083           controlImpl.mImpl->mAccessibilityDescriptionSet = true;
1084         }
1085         else
1086         {
1087           controlImpl.mImpl->mAccessibilityDescriptionSet = false;
1088         }
1089       }
1090       break;
1091
1092       case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1093       {
1094         std::string txt;
1095         if( value.Get( txt ) )
1096         {
1097           controlImpl.mImpl->mAccessibilityTranslationDomain = txt;
1098           controlImpl.mImpl->mAccessibilityTranslationDomainSet = true;
1099         }
1100         else
1101         {
1102           controlImpl.mImpl->mAccessibilityTranslationDomainSet = false;
1103         }
1104       }
1105       break;
1106
1107       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1108       {
1109         bool highlightable;
1110         if( value.Get( highlightable ) )
1111         {
1112           controlImpl.mImpl->mAccessibilityHighlightable = highlightable;
1113           controlImpl.mImpl->mAccessibilityHighlightableSet = true;
1114         }
1115         else
1116         {
1117           controlImpl.mImpl->mAccessibilityHighlightableSet = false;
1118         }
1119       }
1120       break;
1121
1122       case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1123       {
1124         Dali::Accessibility::Role val;
1125         if( value.Get( val ) )
1126         {
1127           controlImpl.mImpl->mAccessibilityRole = val;
1128         }
1129       }
1130       break;
1131
1132       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1133       {
1134         int focusId;
1135         if( value.Get( focusId ) )
1136         {
1137           controlImpl.mImpl->mUpFocusableActorId = focusId;
1138         }
1139       }
1140       break;
1141
1142       case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1143       {
1144         int focusId;
1145         if( value.Get( focusId ) )
1146         {
1147           controlImpl.mImpl->mDownFocusableActorId = focusId;
1148         }
1149       }
1150       break;
1151
1152       case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1153       {
1154         if ( value.Get< bool >() )
1155         {
1156           controlImpl.SetKeyInputFocus();
1157         }
1158         else
1159         {
1160           controlImpl.ClearKeyInputFocus();
1161         }
1162         break;
1163       }
1164
1165       case Toolkit::Control::Property::BACKGROUND:
1166       {
1167         std::string url;
1168         Vector4 color;
1169         const Property::Map* map = value.GetMap();
1170         if( map && !map->Empty() )
1171         {
1172           controlImpl.SetBackground( *map );
1173         }
1174         else if( value.Get( url ) )
1175         {
1176           // don't know the size to load
1177           Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( url, ImageDimensions() );
1178           if( visual )
1179           {
1180             controlImpl.mImpl->RegisterVisual( Toolkit::Control::Property::BACKGROUND, visual, DepthIndex::BACKGROUND );
1181           }
1182         }
1183         else if( value.Get( color ) )
1184         {
1185           controlImpl.SetBackgroundColor(color);
1186         }
1187         else
1188         {
1189           // The background is an empty property map, so we should clear the background
1190           controlImpl.ClearBackground();
1191         }
1192         break;
1193       }
1194
1195       case Toolkit::Control::Property::MARGIN:
1196       {
1197         Extents margin;
1198         if( value.Get( margin ) )
1199         {
1200           controlImpl.mImpl->SetMargin( margin );
1201         }
1202         break;
1203       }
1204
1205       case Toolkit::Control::Property::PADDING:
1206       {
1207         Extents padding;
1208         if( value.Get( padding ) )
1209         {
1210           controlImpl.mImpl->SetPadding( padding );
1211         }
1212         break;
1213       }
1214
1215       case Toolkit::DevelControl::Property::TOOLTIP:
1216       {
1217         TooltipPtr& tooltipPtr = controlImpl.mImpl->mTooltip;
1218         if( ! tooltipPtr )
1219         {
1220           tooltipPtr = Tooltip::New( control );
1221         }
1222         tooltipPtr->SetProperties( value );
1223         break;
1224       }
1225
1226       case Toolkit::DevelControl::Property::SHADOW:
1227       {
1228         const Property::Map* map = value.GetMap();
1229         if( map && !map->Empty() )
1230         {
1231           controlImpl.mImpl->SetShadow( *map );
1232         }
1233         else
1234         {
1235           // The shadow is an empty property map, so we should clear the shadow
1236           controlImpl.mImpl->ClearShadow();
1237         }
1238         break;
1239       }
1240
1241       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1242       {
1243         const Property::Map* map = value.GetMap();
1244         if( map && !map->Empty() )
1245         {
1246           controlImpl.mImpl->mAccessibilityAttributes = *map;
1247         }
1248         break;
1249       }
1250
1251       case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1252       {
1253         bool animated;
1254         if( value.Get( animated ) )
1255         {
1256           controlImpl.mImpl->mAccessibilityAnimated = animated;
1257         }
1258         break;
1259       }
1260     }
1261   }
1262 }
1263
1264 Property::Value Control::Impl::GetProperty( BaseObject* object, Property::Index index )
1265 {
1266   Property::Value value;
1267
1268   Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
1269
1270   if ( control )
1271   {
1272     Control& controlImpl( GetImplementation( control ) );
1273
1274     switch ( index )
1275     {
1276       case Toolkit::Control::Property::STYLE_NAME:
1277       {
1278         value = controlImpl.GetStyleName();
1279         break;
1280       }
1281
1282       case Toolkit::DevelControl::Property::STATE:
1283       {
1284         value = controlImpl.mImpl->mState;
1285         break;
1286       }
1287
1288       case Toolkit::DevelControl::Property::SUB_STATE:
1289       {
1290         value = controlImpl.mImpl->mSubStateName;
1291         break;
1292       }
1293
1294       case Toolkit::DevelControl::Property::LEFT_FOCUSABLE_ACTOR_ID:
1295       {
1296         value = controlImpl.mImpl->mLeftFocusableActorId;
1297         break;
1298       }
1299
1300       case Toolkit::DevelControl::Property::RIGHT_FOCUSABLE_ACTOR_ID:
1301       {
1302         value = controlImpl.mImpl->mRightFocusableActorId;
1303         break;
1304       }
1305
1306       case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
1307       {
1308         if (controlImpl.mImpl->mAccessibilityNameSet)
1309         {
1310           value = controlImpl.mImpl->mAccessibilityName;
1311         }
1312         break;
1313       }
1314
1315       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
1316       {
1317         if (controlImpl.mImpl->mAccessibilityDescriptionSet)
1318         {
1319           value = controlImpl.mImpl->mAccessibilityDescription;
1320         }
1321         break;
1322       }
1323
1324       case Toolkit::DevelControl::Property::ACCESSIBILITY_TRANSLATION_DOMAIN:
1325       {
1326         if (controlImpl.mImpl->mAccessibilityTranslationDomainSet)
1327         {
1328           value = controlImpl.mImpl->mAccessibilityTranslationDomain;
1329         }
1330         break;
1331       }
1332
1333       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
1334       {
1335         if (controlImpl.mImpl->mAccessibilityHighlightableSet)
1336         {
1337           value = controlImpl.mImpl->mAccessibilityHighlightable;
1338         }
1339         break;
1340       }
1341
1342       case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
1343       {
1344         value = Property::Value(controlImpl.mImpl->mAccessibilityRole);
1345         break;
1346       }
1347
1348       case Toolkit::DevelControl::Property::UP_FOCUSABLE_ACTOR_ID:
1349       {
1350         value = controlImpl.mImpl->mUpFocusableActorId;
1351         break;
1352       }
1353
1354       case Toolkit::DevelControl::Property::DOWN_FOCUSABLE_ACTOR_ID:
1355       {
1356         value = controlImpl.mImpl->mDownFocusableActorId;
1357         break;
1358       }
1359
1360       case Toolkit::Control::Property::KEY_INPUT_FOCUS:
1361       {
1362         value = controlImpl.HasKeyInputFocus();
1363         break;
1364       }
1365
1366       case Toolkit::Control::Property::BACKGROUND:
1367       {
1368         Property::Map map;
1369         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual( Toolkit::Control::Property::BACKGROUND );
1370         if( visual )
1371         {
1372           visual.CreatePropertyMap( map );
1373         }
1374
1375         value = map;
1376         break;
1377       }
1378
1379       case Toolkit::Control::Property::MARGIN:
1380       {
1381         value = controlImpl.mImpl->GetMargin();
1382         break;
1383       }
1384
1385       case Toolkit::Control::Property::PADDING:
1386       {
1387         value = controlImpl.mImpl->GetPadding();
1388         break;
1389       }
1390
1391       case Toolkit::DevelControl::Property::TOOLTIP:
1392       {
1393         Property::Map map;
1394         if( controlImpl.mImpl->mTooltip )
1395         {
1396           controlImpl.mImpl->mTooltip->CreatePropertyMap( map );
1397         }
1398         value = map;
1399         break;
1400       }
1401
1402       case Toolkit::DevelControl::Property::SHADOW:
1403       {
1404         Property::Map map;
1405         Toolkit::Visual::Base visual = controlImpl.mImpl->GetVisual( Toolkit::DevelControl::Property::SHADOW );
1406         if( visual )
1407         {
1408           visual.CreatePropertyMap( map );
1409         }
1410
1411         value = map;
1412         break;
1413       }
1414
1415       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
1416       {
1417         value = controlImpl.mImpl->mAccessibilityAttributes;
1418         break;
1419       }
1420
1421       case Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED:
1422       {
1423         value = controlImpl.mImpl->mAccessibilityAnimated;
1424         break;
1425       }
1426     }
1427   }
1428
1429   return value;
1430 }
1431
1432 void Control::Impl::RemoveAccessibilityAttribute( const std::string& key )
1433 {
1434   Property::Value* val = mAccessibilityAttributes.Find( key );
1435   if( val )
1436     mAccessibilityAttributes[key] = Property::Value();
1437 }
1438
1439 void Control::Impl::ClearAccessibilityAttributes()
1440 {
1441   mAccessibilityAttributes.Clear();
1442 }
1443
1444 void Control::Impl::SetAccessibilityReadingInfoType( const Dali::Accessibility::ReadingInfoTypes types )
1445 {
1446   std::string value;
1447   if ( types[ Dali::Accessibility::ReadingInfoType::NAME ] )
1448   {
1449     value += READING_INFO_TYPE_NAME;
1450   }
1451   if ( types[ Dali::Accessibility::ReadingInfoType::ROLE ] )
1452   {
1453     if( !value.empty() )
1454     {
1455       value += READING_INFO_TYPE_SEPARATOR;
1456     }
1457     value += READING_INFO_TYPE_ROLE;
1458   }
1459   if ( types[ Dali::Accessibility::ReadingInfoType::DESCRIPTION ] )
1460   {
1461     if( !value.empty() )
1462     {
1463       value += READING_INFO_TYPE_SEPARATOR;
1464     }
1465     value += READING_INFO_TYPE_DESCRIPTION;
1466   }
1467   if ( types[ Dali::Accessibility::ReadingInfoType::STATE ] )
1468   {
1469     if( !value.empty() )
1470     {
1471       value += READING_INFO_TYPE_SEPARATOR;
1472     }
1473     value += READING_INFO_TYPE_STATE;
1474   }
1475   AppendAccessibilityAttribute( READING_INFO_TYPE_ATTRIBUTE_NAME, value );
1476 }
1477
1478 Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
1479 {
1480   std::string value;
1481   auto place = mAccessibilityAttributes.Find( READING_INFO_TYPE_ATTRIBUTE_NAME );
1482   if( place )
1483   {
1484     place->Get( value );
1485   }
1486
1487   if ( value.empty() )
1488   {
1489     return {};
1490   }
1491
1492   Dali::Accessibility::ReadingInfoTypes types;
1493
1494   if ( value.find( READING_INFO_TYPE_NAME ) != std::string::npos )
1495   {
1496     types[ Dali::Accessibility::ReadingInfoType::NAME ] = true;
1497   }
1498   if ( value.find( READING_INFO_TYPE_ROLE ) != std::string::npos )
1499   {
1500     types[ Dali::Accessibility::ReadingInfoType::ROLE ] = true;
1501   }
1502   if ( value.find( READING_INFO_TYPE_DESCRIPTION ) != std::string::npos )
1503   {
1504     types[ Dali::Accessibility::ReadingInfoType::DESCRIPTION ] = true;
1505   }
1506   if ( value.find( READING_INFO_TYPE_STATE ) != std::string::npos )
1507   {
1508     types[ Dali::Accessibility::ReadingInfoType::STATE ] = true;
1509   }
1510
1511   return types;
1512 }
1513
1514 void  Control::Impl::CopyInstancedProperties( RegisteredVisualContainer& visuals, Dictionary<Property::Map>& instancedProperties )
1515 {
1516   for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter!= visuals.End(); iter++)
1517   {
1518     if( (*iter)->visual )
1519     {
1520       Property::Map instanceMap;
1521       Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap);
1522       instancedProperties.Add( (*iter)->visual.GetName(), instanceMap );
1523     }
1524   }
1525 }
1526
1527
1528 void Control::Impl::RemoveVisual( RegisteredVisualContainer& visuals, const std::string& visualName )
1529 {
1530   Actor self( mControlImpl.Self() );
1531
1532   for ( RegisteredVisualContainer::Iterator visualIter = visuals.Begin();
1533         visualIter != visuals.End(); ++visualIter )
1534   {
1535     Toolkit::Visual::Base visual = (*visualIter)->visual;
1536     if( visual && visual.GetName() == visualName )
1537     {
1538       Toolkit::GetImplementation(visual).SetOffScene( self );
1539       (*visualIter)->visual.Reset();
1540       visuals.Erase( visualIter );
1541       break;
1542     }
1543   }
1544 }
1545
1546 void Control::Impl::RemoveVisuals( RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals )
1547 {
1548   Actor self( mControlImpl.Self() );
1549   for( DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter )
1550   {
1551     const std::string visualName = *iter;
1552     RemoveVisual( visuals, visualName );
1553   }
1554 }
1555
1556 void Control::Impl::RecreateChangedVisuals( Dictionary<Property::Map>& stateVisualsToChange,
1557                              Dictionary<Property::Map>& instancedProperties )
1558 {
1559   Dali::CustomActor handle( mControlImpl.GetOwner() );
1560   for( Dictionary<Property::Map>::iterator iter = stateVisualsToChange.Begin();
1561        iter != stateVisualsToChange.End(); ++iter )
1562   {
1563     const std::string& visualName = (*iter).key;
1564     const Property::Map& toMap = (*iter).entry;
1565
1566     Actor self = mControlImpl.Self();
1567     RegisteredVisualContainer::Iterator registeredVisualsiter;
1568     // Check if visual (visualName) is already registered, this is the current visual.
1569     if(FindVisual(visualName, mVisuals, registeredVisualsiter))
1570     {
1571       Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
1572       if(visual)
1573       {
1574         // No longer required to know if the replaced visual's resources are ready
1575         StopObservingVisual(visual);
1576
1577         // If control staged then visuals will be swapped once ready
1578         if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1579         {
1580           // Check if visual is currently in the process of being replaced ( is in removal container )
1581           RegisteredVisualContainer::Iterator visualQueuedForRemoval;
1582           if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
1583           {
1584             // Visual with same visual name is already in removal container so current visual pending
1585             // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
1586             Toolkit::GetImplementation(visual).SetOffScene(self);
1587             (*registeredVisualsiter)->visual.Reset();
1588             mVisuals.Erase(registeredVisualsiter);
1589           }
1590           else
1591           {
1592             // current visual not already in removal container so add now.
1593             DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
1594             MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
1595           }
1596         }
1597         else
1598         {
1599           // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
1600           (*registeredVisualsiter)->visual.Reset();
1601           mVisuals.Erase(registeredVisualsiter);
1602         }
1603       }
1604
1605       const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
1606       Style::ApplyVisual(handle, visualName, toMap, instancedMap);
1607     }
1608   }
1609 }
1610
1611 void Control::Impl::ReplaceStateVisualsAndProperties( const StylePtr oldState, const StylePtr newState, const std::string& subState )
1612 {
1613   // Collect all old visual names
1614   DictionaryKeys stateVisualsToRemove;
1615   if( oldState )
1616   {
1617     oldState->visuals.GetKeys( stateVisualsToRemove );
1618     if( ! subState.empty() )
1619     {
1620       const StylePtr* oldSubState = oldState->subStates.FindConst(subState);
1621       if( oldSubState )
1622       {
1623         DictionaryKeys subStateVisualsToRemove;
1624         (*oldSubState)->visuals.GetKeys( subStateVisualsToRemove );
1625         Merge( stateVisualsToRemove, subStateVisualsToRemove );
1626       }
1627     }
1628   }
1629
1630   // Collect all new visual properties
1631   Dictionary<Property::Map> stateVisualsToAdd;
1632   if( newState )
1633   {
1634     stateVisualsToAdd = newState->visuals;
1635     if( ! subState.empty() )
1636     {
1637       const StylePtr* newSubState = newState->subStates.FindConst(subState);
1638       if( newSubState )
1639       {
1640         stateVisualsToAdd.Merge( (*newSubState)->visuals );
1641       }
1642     }
1643   }
1644
1645   // If a name is in both add/remove, move it to change list.
1646   Dictionary<Property::Map> stateVisualsToChange;
1647   FindChangableVisuals( stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove);
1648
1649   // Copy instanced properties (e.g. text label) of current visuals
1650   Dictionary<Property::Map> instancedProperties;
1651   CopyInstancedProperties( mVisuals, instancedProperties );
1652
1653   // For each visual in remove list, remove from mVisuals
1654   RemoveVisuals( mVisuals, stateVisualsToRemove );
1655
1656   // For each visual in add list, create and add to mVisuals
1657   Dali::CustomActor handle( mControlImpl.GetOwner() );
1658   Style::ApplyVisuals( handle, stateVisualsToAdd, instancedProperties );
1659
1660   // For each visual in change list, if it requires a new visual,
1661   // remove old visual, create and add to mVisuals
1662   RecreateChangedVisuals( stateVisualsToChange, instancedProperties );
1663 }
1664
1665 void Control::Impl::SetState( DevelControl::State newState, bool withTransitions )
1666 {
1667   DevelControl::State oldState = mState;
1668   Dali::CustomActor handle( mControlImpl.GetOwner() );
1669   DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n",
1670                 (mState == DevelControl::NORMAL ? "NORMAL" :(
1671                   mState == DevelControl::FOCUSED ?"FOCUSED" : (
1672                     mState == DevelControl::DISABLED?"DISABLED":"NONE" ))));
1673
1674   if( mState != newState )
1675   {
1676     // If mState was Disabled, and new state is Focused, should probably
1677     // store that fact, e.g. in another property that FocusManager can access.
1678     mState = newState;
1679
1680     // Trigger state change and transitions
1681     // Apply new style, if stylemanager is available
1682     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1683     if( styleManager )
1684     {
1685       const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
1686
1687       if( stylePtr )
1688       {
1689         std::string oldStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( oldState, ControlStateTable, ControlStateTableCount );
1690         std::string newStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( newState, ControlStateTable, ControlStateTableCount );
1691
1692         const StylePtr* newStateStyle = stylePtr->subStates.Find( newStateName );
1693         const StylePtr* oldStateStyle = stylePtr->subStates.Find( oldStateName );
1694         if( oldStateStyle && newStateStyle )
1695         {
1696           // Only change if both state styles exist
1697           ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, mSubStateName );
1698         }
1699       }
1700     }
1701   }
1702 }
1703
1704 void Control::Impl::SetSubState( const std::string& subStateName, bool withTransitions )
1705 {
1706   if( mSubStateName != subStateName )
1707   {
1708     // Get existing sub-state visuals, and unregister them
1709     Dali::CustomActor handle( mControlImpl.GetOwner() );
1710
1711     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
1712     if( styleManager )
1713     {
1714       const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) );
1715       if( stylePtr )
1716       {
1717         // Stringify state
1718         std::string stateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( mState, ControlStateTable, ControlStateTableCount );
1719
1720         const StylePtr* state = stylePtr->subStates.Find( stateName );
1721         if( state )
1722         {
1723           StylePtr stateStyle(*state);
1724
1725           const StylePtr* newStateStyle = stateStyle->subStates.Find( subStateName );
1726           const StylePtr* oldStateStyle = stateStyle->subStates.Find( mSubStateName );
1727           if( oldStateStyle && newStateStyle )
1728           {
1729             std::string empty;
1730             ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, empty );
1731           }
1732         }
1733       }
1734     }
1735
1736     mSubStateName = subStateName;
1737   }
1738 }
1739
1740 void Control::Impl::OnSceneDisconnection()
1741 {
1742   Actor self = mControlImpl.Self();
1743
1744   // Any visuals set for replacement but not yet ready should still be registered.
1745   // Reason: If a request was made to register a new visual but the control removed from scene before visual was ready
1746   // then when this control appears back on stage it should use that new visual.
1747
1748   // Iterate through all registered visuals and set off scene
1749   SetVisualsOffScene( mVisuals, self );
1750
1751   // Visuals pending replacement can now be taken out of the removal list and set off scene
1752   // Iterate through all replacement visuals and add to a move queue then set off scene
1753   for( auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++ )
1754   {
1755     Toolkit::GetImplementation((*removalIter)->visual).SetOffScene( self );
1756   }
1757
1758   for( auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++ )
1759   {
1760     (*replacedIter)->pending = false;
1761   }
1762
1763   mRemoveVisuals.Clear();
1764 }
1765
1766 void Control::Impl::SetMargin( Extents margin )
1767 {
1768   mControlImpl.mImpl->mMargin = margin;
1769
1770   // Trigger a size negotiation request that may be needed when setting a margin.
1771   mControlImpl.RelayoutRequest();
1772 }
1773
1774 Extents Control::Impl::GetMargin() const
1775 {
1776   return mControlImpl.mImpl->mMargin;
1777 }
1778
1779 void Control::Impl::SetPadding( Extents padding )
1780 {
1781   mControlImpl.mImpl->mPadding = padding;
1782
1783   // Trigger a size negotiation request that may be needed when setting a padding.
1784   mControlImpl.RelayoutRequest();
1785 }
1786
1787 Extents Control::Impl::GetPadding() const
1788 {
1789   return mControlImpl.mImpl->mPadding;
1790 }
1791
1792 void Control::Impl::SetInputMethodContext( InputMethodContext& inputMethodContext )
1793 {
1794   mInputMethodContext = inputMethodContext;
1795 }
1796
1797 bool Control::Impl::FilterKeyEvent( const KeyEvent& event )
1798 {
1799   bool consumed ( false );
1800
1801   if ( mInputMethodContext )
1802   {
1803     consumed = mInputMethodContext.FilterEventKey( event );
1804   }
1805   return consumed;
1806 }
1807
1808 DevelControl::VisualEventSignalType& Control::Impl::VisualEventSignal()
1809 {
1810   return mVisualEventSignal;
1811 }
1812
1813 void Control::Impl::SetShadow( const Property::Map& map )
1814 {
1815   Toolkit::Visual::Base visual = Toolkit::VisualFactory::Get().CreateVisual( map );
1816   visual.SetName("shadow");
1817
1818   if( visual )
1819   {
1820     mControlImpl.mImpl->RegisterVisual( Toolkit::DevelControl::Property::SHADOW, visual, DepthIndex::BACKGROUND_EFFECT );
1821
1822     mControlImpl.RelayoutRequest();
1823   }
1824 }
1825
1826 void Control::Impl::ClearShadow()
1827 {
1828    mControlImpl.mImpl->UnregisterVisual( Toolkit::DevelControl::Property::SHADOW );
1829
1830    // Trigger a size negotiation request that may be needed when unregistering a visual.
1831    mControlImpl.RelayoutRequest();
1832 }
1833
1834 Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
1835 {
1836   Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
1837   if(visual)
1838   {
1839     Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
1840     return visualImpl.GetPropertyObject(visualPropertyKey);
1841   }
1842
1843   Handle handle;
1844   return Dali::Property(handle, Property::INVALID_INDEX);
1845 }
1846
1847 void Control::Impl::EmitResourceReadySignal()
1848 {
1849   if(!mIsEmittingResourceReadySignal)
1850   {
1851     // Guard against calls to emit the signal during the callback
1852     mIsEmittingResourceReadySignal = true;
1853
1854     // If the signal handler changes visual, it may become ready during this call & therefore this method will
1855     // get called again recursively. If so, mNeedToEmitResourceReady is set below, and we act on it after that secondary
1856     // invocation has completed by notifying in an Idle callback to prevent further recursion.
1857     Dali::Toolkit::Control handle(mControlImpl.GetOwner());
1858     mResourceReadySignal.Emit(handle);
1859
1860     if(mNeedToEmitResourceReady)
1861     {
1862       // Add idler to emit the signal again
1863       if(!mIdleCallback)
1864       {
1865         // The callback manager takes the ownership of the callback object.
1866         mIdleCallback = MakeCallback( this, &Control::Impl::OnIdleCallback);
1867         Adaptor::Get().AddIdle(mIdleCallback, false);
1868       }
1869     }
1870
1871     mIsEmittingResourceReadySignal = false;
1872   }
1873   else
1874   {
1875     mNeedToEmitResourceReady = true;
1876   }
1877 }
1878
1879 void Control::Impl::OnIdleCallback()
1880 {
1881   if(mNeedToEmitResourceReady)
1882   {
1883     // Reset the flag
1884     mNeedToEmitResourceReady = false;
1885
1886     // A visual is ready so control may need relayouting if staged
1887     if(mControlImpl.Self().GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
1888     {
1889       mControlImpl.RelayoutRequest();
1890     }
1891
1892     EmitResourceReadySignal();
1893   }
1894
1895   // Set the pointer to null as the callback manager deletes the callback after execute it.
1896   mIdleCallback = nullptr;
1897 }
1898
1899 Dali::Accessibility::Accessible *Control::Impl::GetAccessibilityObject()
1900 {
1901   if( !accessibilityObject )
1902     accessibilityObject = accessibilityConstructor( mControlImpl.Self() );
1903   return accessibilityObject.get();
1904 }
1905
1906 Dali::Accessibility::Accessible *Control::Impl::GetAccessibilityObject(Dali::Actor actor)
1907 {
1908   if( actor )
1909   {
1910     auto q = Dali::Toolkit::Control::DownCast( actor );
1911     if( q )
1912     {
1913       auto q2 = static_cast< Internal::Control* >( &q.GetImplementation() );
1914       return q2->mImpl->GetAccessibilityObject();
1915     }
1916   }
1917   return nullptr;
1918 }
1919
1920 Control::Impl::AccessibleImpl::AccessibleImpl(Dali::Actor self, Dali::Accessibility::Role role, bool modal)
1921   : self(self), modal(modal)
1922 {
1923   auto control = Dali::Toolkit::Control::DownCast(self);
1924
1925   Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
1926   Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
1927   if( controlImpl.mAccessibilityRole == Dali::Accessibility::Role::UNKNOWN )
1928     controlImpl.mAccessibilityRole = role;
1929
1930   self.PropertySetSignal().Connect(&controlImpl, [this, &controlImpl](Dali::Handle &handle, Dali::Property::Index index, Dali::Property::Value value)
1931   {
1932     if (this->self != Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
1933     {
1934       return;
1935     }
1936
1937     if (index == DevelControl::Property::ACCESSIBILITY_NAME
1938       || (index == GetNamePropertyIndex() && !controlImpl.mAccessibilityNameSet))
1939     {
1940       if (controlImpl.mAccessibilityGetNameSignal.Empty())
1941       {
1942         Emit(Dali::Accessibility::ObjectPropertyChangeEvent::NAME);
1943       }
1944     }
1945
1946     if (index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION
1947       || (index == GetDescriptionPropertyIndex() && !controlImpl.mAccessibilityDescriptionSet))
1948     {
1949       if (controlImpl.mAccessibilityGetDescriptionSignal.Empty())
1950       {
1951         Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
1952       }
1953     }
1954   });
1955 }
1956
1957 std::string Control::Impl::AccessibleImpl::GetName()
1958 {
1959   auto control = Dali::Toolkit::Control::DownCast(self);
1960
1961   Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
1962   Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
1963
1964   if (!controlImpl.mAccessibilityGetNameSignal.Empty()) {
1965       std::string ret;
1966       controlImpl.mAccessibilityGetNameSignal.Emit(ret);
1967       return ret;
1968   }
1969
1970   if (controlImpl.mAccessibilityNameSet)
1971     return controlImpl.mAccessibilityName;
1972
1973   if (auto raw = GetNameRaw(); !raw.empty())
1974     return raw;
1975
1976   return self.GetProperty< std::string >( Actor::Property::NAME );
1977 }
1978
1979 std::string Control::Impl::AccessibleImpl::GetNameRaw()
1980 {
1981   return {};
1982 }
1983
1984 std::string Control::Impl::AccessibleImpl::GetDescription()
1985 {
1986   auto control = Dali::Toolkit::Control::DownCast(self);
1987
1988   Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
1989   Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
1990
1991   if (!controlImpl.mAccessibilityGetDescriptionSignal.Empty()) {
1992       std::string ret;
1993       controlImpl.mAccessibilityGetDescriptionSignal.Emit(ret);
1994       return ret;
1995   }
1996
1997   if (controlImpl.mAccessibilityDescriptionSet)
1998     return controlImpl.mAccessibilityDescription;
1999
2000   return GetDescriptionRaw();
2001 }
2002
2003 std::string Control::Impl::AccessibleImpl::GetDescriptionRaw()
2004 {
2005   return "";
2006 }
2007
2008 Dali::Accessibility::Accessible* Control::Impl::AccessibleImpl::GetParent()
2009 {
2010   return Dali::Accessibility::Accessible::Get( self.GetParent() );
2011 }
2012
2013 size_t Control::Impl::AccessibleImpl::GetChildCount()
2014 {
2015   return self.GetChildCount();
2016 }
2017
2018 Dali::Accessibility::Accessible* Control::Impl::AccessibleImpl::GetChildAtIndex( size_t index )
2019 {
2020   return Dali::Accessibility::Accessible::Get( self.GetChildAt( static_cast< unsigned int >( index ) ) );
2021 }
2022
2023 size_t Control::Impl::AccessibleImpl::GetIndexInParent()
2024 {
2025   auto s = self;
2026   auto parent = s.GetParent();
2027   DALI_ASSERT_ALWAYS( parent && "can't call GetIndexInParent on object without parent" );
2028   auto count = parent.GetChildCount();
2029   for( auto i = 0u; i < count; ++i )
2030   {
2031     auto c = parent.GetChildAt( i );
2032     if( c == s )
2033       return i;
2034   }
2035   DALI_ASSERT_ALWAYS( false && "object isn't child of it's parent" );
2036   return static_cast<size_t>(-1);
2037 }
2038
2039 Dali::Accessibility::Role Control::Impl::AccessibleImpl::GetRole()
2040 {
2041   return self.GetProperty<Dali::Accessibility::Role>( Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE );
2042 }
2043
2044 Dali::Accessibility::States Control::Impl::AccessibleImpl::CalculateStates()
2045 {
2046   Dali::Accessibility::States s;
2047   s[Dali::Accessibility::State::FOCUSABLE] = self.GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE );
2048   s[Dali::Accessibility::State::FOCUSED] = Toolkit::KeyboardFocusManager::Get().GetCurrentFocusActor() == self;
2049   if(self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE ).GetType() == Property::NONE )
2050     s[Dali::Accessibility::State::HIGHLIGHTABLE] = false;
2051   else
2052     s[Dali::Accessibility::State::HIGHLIGHTABLE] = self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE ).Get< bool >();
2053   s[Dali::Accessibility::State::HIGHLIGHTED] = GetCurrentlyHighlightedActor() == self;
2054   s[Dali::Accessibility::State::ENABLED] = true;
2055   s[Dali::Accessibility::State::SENSITIVE] = true;
2056   s[Dali::Accessibility::State::ANIMATED] = self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED ).Get< bool >();
2057   s[Dali::Accessibility::State::VISIBLE] = true;
2058   if( modal )
2059   {
2060     s[Dali::Accessibility::State::MODAL] = true;
2061   }
2062   s[Dali::Accessibility::State::SHOWING] = !self.GetProperty( Dali::DevelActor::Property::CULLED ).Get< bool >()
2063                                          && self.GetCurrentProperty< bool >( Actor::Property::VISIBLE );
2064
2065   s[Dali::Accessibility::State::DEFUNCT] = !self.GetProperty( Dali::DevelActor::Property::CONNECTED_TO_SCENE ).Get< bool >();
2066   return s;
2067 }
2068
2069 Dali::Accessibility::States Control::Impl::AccessibleImpl::GetStates()
2070 {
2071   return CalculateStates();
2072 }
2073
2074 Dali::Accessibility::Attributes Control::Impl::AccessibleImpl::GetAttributes()
2075 {
2076   std::unordered_map< std::string, std::string > attribute_map;
2077   auto q = Dali::Toolkit::Control::DownCast( self );
2078   auto w =
2079       q.GetProperty( Dali::Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES );
2080   auto z = w.GetMap();
2081
2082   if( z )
2083   {
2084     auto map_size = z->Count();
2085
2086     for( unsigned int i = 0; i < map_size; i++ )
2087     {
2088       auto map_key = z->GetKeyAt( i );
2089       if( map_key.type == Property::Key::STRING )
2090       {
2091         std::string map_value;
2092         if( z->GetValue( i ).Get( map_value ) )
2093         {
2094           attribute_map.emplace( std::move( map_key.stringKey ),
2095                                  std::move( map_value ) );
2096         }
2097       }
2098     }
2099   }
2100
2101   return attribute_map;
2102 }
2103
2104 Dali::Accessibility::ComponentLayer Control::Impl::AccessibleImpl::GetLayer()
2105 {
2106   return Dali::Accessibility::ComponentLayer::WINDOW;
2107 }
2108
2109 Dali::Rect<> Control::Impl::AccessibleImpl::GetExtents( Dali::Accessibility::CoordType ctype )
2110 {
2111   Vector2 screenPosition =
2112       self.GetProperty( Dali::DevelActor::Property::SCREEN_POSITION )
2113           .Get< Vector2 >();
2114   auto size = self.GetCurrentProperty< Vector3 >( Actor::Property::SIZE ) * self.GetCurrentProperty< Vector3 >( Actor::Property::WORLD_SCALE );
2115   bool positionUsesAnchorPoint =
2116       self.GetProperty( Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
2117           .Get< bool >();
2118   Vector3 anchorPointOffSet =
2119       size * ( positionUsesAnchorPoint ? self.GetCurrentProperty< Vector3 >( Actor::Property::ANCHOR_POINT )
2120                                        : AnchorPoint::TOP_LEFT );
2121   Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x,
2122                               screenPosition.y - anchorPointOffSet.y );
2123
2124   return { position.x, position.y, size.x, size.y };
2125 }
2126
2127 int16_t Control::Impl::AccessibleImpl::GetMdiZOrder() { return 0; }
2128 double Control::Impl::AccessibleImpl::GetAlpha() { return 0; }
2129
2130 bool Control::Impl::AccessibleImpl::GrabFocus()
2131 {
2132   return Toolkit::KeyboardFocusManager::Get().SetCurrentFocusActor( self );
2133 }
2134
2135 const char* const FOCUS_BORDER_IMAGE_PATH = DALI_IMAGE_DIR "keyboard_focus.9.png";
2136
2137 static Dali::Actor CreateHighlightIndicatorActor()
2138 {
2139   // Create the default if it hasn't been set and one that's shared by all the
2140   // keyboard focusable actors const char* const FOCUS_BORDER_IMAGE_PATH =
2141   // DALI_IMAGE_DIR "keyboard_focus.9.png";
2142   auto actor = Toolkit::ImageView::New( FOCUS_BORDER_IMAGE_PATH );
2143   actor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
2144   DevelControl::AppendAccessibilityAttribute( actor, "highlight", "" );
2145   actor.SetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED, true);
2146   actor.SetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE, false );
2147
2148   return actor;
2149 }
2150
2151 bool Control::Impl::AccessibleImpl::GrabHighlight()
2152 {
2153   auto old = GetCurrentlyHighlightedActor();
2154
2155   if( !Dali::Accessibility::IsUp() )
2156       return false;
2157   if( self == old )
2158     return true;
2159   if( old )
2160   {
2161     auto c = dynamic_cast< Dali::Accessibility::Component* >( GetAccessibilityObject( old ) );
2162     if( c )
2163       c->ClearHighlight();
2164   }
2165   auto highlight = GetHighlightActor();
2166   if ( !highlight )
2167   {
2168     highlight = CreateHighlightIndicatorActor();
2169     SetHighlightActor( highlight );
2170   }
2171   highlight.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
2172   highlight.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER );
2173   highlight.SetProperty( Actor::Property::POSITION_Z, 1.0f );
2174   highlight.SetProperty( Actor::Property::POSITION, Vector2( 0.0f, 0.0f ));
2175
2176   EnsureSelfVisible();
2177   self.Add( highlight );
2178   SetCurrentlyHighlightedActor( self );
2179   EmitHighlighted( true );
2180
2181   return true;
2182 }
2183
2184
2185
2186 bool Control::Impl::AccessibleImpl::ClearHighlight()
2187 {
2188   if( !Dali::Accessibility::IsUp() )
2189     return false;
2190   if( GetCurrentlyHighlightedActor() == self )
2191   {
2192     self.Remove( GetHighlightActor() );
2193     SetCurrentlyHighlightedActor( {} );
2194     EmitHighlighted( false );
2195     return true;
2196   }
2197   return false;
2198 }
2199
2200 std::string Control::Impl::AccessibleImpl::GetActionName( size_t index )
2201 {
2202   if ( index >= GetActionCount() ) return "";
2203   Dali::TypeInfo type;
2204   self.GetTypeInfo( type );
2205   DALI_ASSERT_ALWAYS( type && "no TypeInfo object" );
2206   return type.GetActionName( index );
2207 }
2208 std::string Control::Impl::AccessibleImpl::GetLocalizedActionName( size_t index )
2209 {
2210   // TODO: add localization
2211   return GetActionName( index );
2212 }
2213 std::string Control::Impl::AccessibleImpl::GetActionDescription( size_t index )
2214 {
2215   return "";
2216 }
2217 size_t Control::Impl::AccessibleImpl::GetActionCount()
2218 {
2219   Dali::TypeInfo type;
2220   self.GetTypeInfo( type );
2221   DALI_ASSERT_ALWAYS( type && "no TypeInfo object" );
2222   return type.GetActionCount();
2223 }
2224 std::string Control::Impl::AccessibleImpl::GetActionKeyBinding( size_t index )
2225 {
2226   return "";
2227 }
2228 bool Control::Impl::AccessibleImpl::DoAction( size_t index )
2229 {
2230   std::string actionName = GetActionName( index );
2231   return self.DoAction( actionName, {} );
2232 }
2233 bool Control::Impl::AccessibleImpl::DoAction(const std::string& name)
2234 {
2235   return self.DoAction( name, {} );
2236 }
2237
2238 bool Control::Impl::AccessibleImpl::DoGesture(const Dali::Accessibility::GestureInfo &gestureInfo)
2239 {
2240   auto control = Dali::Toolkit::Control::DownCast(self);
2241
2242   Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
2243   Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
2244
2245   if (!controlImpl.mAccessibilityDoGestureSignal.Empty()) {
2246       auto ret = std::make_pair(gestureInfo, false);
2247       controlImpl.mAccessibilityDoGestureSignal.Emit(ret);
2248       return ret.second;
2249   }
2250
2251   return false;
2252 }
2253
2254 std::vector<Dali::Accessibility::Relation> Control::Impl::AccessibleImpl::GetRelationSet()
2255 {
2256   auto control = Dali::Toolkit::Control::DownCast(self);
2257
2258   Internal::Control& internalControl = Toolkit::Internal::GetImplementation( control );
2259   Internal::Control::Impl& controlImpl = Internal::Control::Impl::Get( internalControl );
2260
2261   std::vector<Dali::Accessibility::Relation> ret;
2262
2263   auto &v = controlImpl.mAccessibilityRelations;
2264   for (auto i = 0u; i < v.size(); ++i)
2265   {
2266     if ( v[i].empty() )
2267       continue;
2268
2269     ret.emplace_back( Accessibility::Relation{ static_cast<Accessibility::RelationType>(i), v[i] } );
2270   }
2271
2272   return ret;
2273 }
2274
2275 void Control::Impl::AccessibleImpl::EnsureChildVisible(Actor child)
2276 {
2277 }
2278
2279 void Control::Impl::AccessibleImpl::EnsureSelfVisible()
2280 {
2281   auto parent = dynamic_cast<Control::Impl::AccessibleImpl*>(GetParent());
2282   if (parent)
2283   {
2284     parent->EnsureChildVisible(self);
2285   }
2286 }
2287
2288 Property::Index Control::Impl::AccessibleImpl::GetNamePropertyIndex()
2289 {
2290   return Actor::Property::NAME;
2291 }
2292
2293 Property::Index Control::Impl::AccessibleImpl::GetDescriptionPropertyIndex()
2294 {
2295   return Property::INVALID_INDEX;
2296 }
2297
2298 void Control::Impl::PositionOrSizeChangedCallback( PropertyNotification &p )
2299 {
2300   auto self = Dali::Actor::DownCast(p.GetTarget());
2301   if (Dali::Accessibility::IsUp() && !self.GetProperty( Toolkit::DevelControl::Property::ACCESSIBILITY_ANIMATED ).Get< bool >())
2302   {
2303     auto extents = DevelActor::CalculateScreenExtents( self );
2304     Dali::Accessibility::Accessible::Get( self )->EmitBoundsChanged( extents );
2305   }
2306 }
2307
2308 void Control::Impl::CulledChangedCallback( PropertyNotification &p)
2309 {
2310   if (Dali::Accessibility::IsUp())
2311   {
2312     auto self = Dali::Actor::DownCast(p.GetTarget());
2313     Dali::Accessibility::Accessible::Get(self)->EmitShowing( !self.GetProperty( DevelActor::Property::CULLED ).Get<bool>() );
2314   }
2315 }
2316
2317 void Control::Impl::AccessibilityRegister()
2318 {
2319   if (!accessibilityNotificationSet)
2320   {
2321     accessibilityNotificationPosition = mControlImpl.Self().AddPropertyNotification( Actor::Property::POSITION, StepCondition( 0.01f ) );
2322     accessibilityNotificationPosition.SetNotifyMode( PropertyNotification::NOTIFY_ON_CHANGED );
2323     accessibilityNotificationPosition.NotifySignal().Connect( &Control::Impl::PositionOrSizeChangedCallback );
2324
2325     accessibilityNotificationSize = mControlImpl.Self().AddPropertyNotification( Actor::Property::SIZE, StepCondition( 0.01f ) );
2326     accessibilityNotificationSize.SetNotifyMode( PropertyNotification::NOTIFY_ON_CHANGED );
2327     accessibilityNotificationSize.NotifySignal().Connect( &Control::Impl::PositionOrSizeChangedCallback );
2328
2329     accessibilityNotificationCulled = mControlImpl.Self().AddPropertyNotification( DevelActor::Property::CULLED, LessThanCondition( 0.5f ) );
2330     accessibilityNotificationCulled.SetNotifyMode( PropertyNotification::NOTIFY_ON_CHANGED );
2331     accessibilityNotificationCulled.NotifySignal().Connect( &Control::Impl::CulledChangedCallback );
2332
2333     accessibilityNotificationSet = true;
2334   }
2335 }
2336
2337 void Control::Impl::AccessibilityDeregister()
2338 {
2339   if (accessibilityNotificationSet)
2340   {
2341     accessibilityNotificationPosition = {};
2342     accessibilityNotificationSize = {};
2343     accessibilityNotificationCulled = {};
2344     accessibilityNotificationSet = false;
2345   }
2346 }
2347
2348 } // namespace Internal
2349
2350 } // namespace Toolkit
2351
2352 } // namespace Dali