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