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