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