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