Removal of unnecessary Actor-attachment classes, part I - event thread
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-impl.cpp
1 /*
2  * Copyright (c) 2015 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 <dali/internal/event/actors/actor-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <cmath>
23 #include <algorithm>
24 #include <cfloat>
25
26 // INTERNAL INCLUDES
27
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/math/vector2.h>
31 #include <dali/public-api/math/vector3.h>
32 #include <dali/public-api/math/radian.h>
33 #include <dali/public-api/object/type-registry.h>
34 #include <dali/devel-api/scripting/scripting.h>
35
36 #include <dali/internal/common/internal-constants.h>
37 #include <dali/internal/event/common/event-thread-services.h>
38 #include <dali/internal/event/render-tasks/render-task-impl.h>
39 #include <dali/internal/event/actors/camera-actor-impl.h>
40 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
41 #include <dali/internal/event/common/property-helper.h>
42 #include <dali/internal/event/common/stage-impl.h>
43 #include <dali/internal/event/common/type-info-impl.h>
44 #include <dali/internal/event/animation/constraint-impl.h>
45 #include <dali/internal/event/common/projection.h>
46 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
47 #include <dali/internal/update/common/animatable-property.h>
48 #include <dali/internal/update/nodes/node-messages.h>
49 #include <dali/internal/update/nodes/node-declarations.h>
50 #include <dali/internal/update/animation/scene-graph-constraint.h>
51 #include <dali/internal/event/events/actor-gesture-data.h>
52 #include <dali/internal/common/message.h>
53 #include <dali/integration-api/debug.h>
54
55 using Dali::Internal::SceneGraph::Node;
56 using Dali::Internal::SceneGraph::AnimatableProperty;
57 using Dali::Internal::SceneGraph::PropertyBase;
58
59 namespace Dali
60 {
61 namespace ResizePolicy
62 {
63
64 namespace
65 {
66 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
67 DALI_ENUM_TO_STRING( FIXED )
68 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
69 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
70 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
71 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
72 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
73 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
74 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
75 DALI_ENUM_TO_STRING_TABLE_END( Type )
76
77 } // unnamed namespace
78 } // ResizePolicy
79
80 namespace SizeScalePolicy
81 {
82 namespace
83 {
84 // Enumeration to / from string conversion tables
85 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
86 DALI_ENUM_TO_STRING( USE_SIZE_SET )
87 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
88 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
89 DALI_ENUM_TO_STRING_TABLE_END( Type )
90 } // unnamed namespace
91 } // SizeScalePolicy
92
93 namespace Internal
94 {
95
96 unsigned int Actor::mActorCounter = 0;
97
98 namespace
99 {
100 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
101 inline const Vector3& GetDefaultSizeModeFactor()
102 {
103   return Vector3::ONE;
104 }
105
106 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
107 inline const Vector2& GetDefaultPreferredSize()
108 {
109   return Vector2::ZERO;
110 }
111
112 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
113 inline const Vector2& GetDefaultDimensionPadding()
114 {
115   return Vector2::ZERO;
116 }
117
118 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
119
120 } // unnamed namespace
121
122 /**
123  * Struct to collect relayout variables
124  */
125 struct Actor::RelayoutData
126 {
127   RelayoutData()
128     : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
129   {
130     // Set size negotiation defaults
131     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
132     {
133       resizePolicies[ i ] = ResizePolicy::DEFAULT;
134       negotiatedDimensions[ i ] = 0.0f;
135       dimensionNegotiated[ i ] = false;
136       dimensionDirty[ i ] = false;
137       dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
138       dimensionPadding[ i ] = GetDefaultDimensionPadding();
139       minimumSize[ i ] = 0.0f;
140       maximumSize[ i ] = FLT_MAX;
141     }
142   }
143
144   ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ];      ///< Resize policies
145
146   Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ];  ///< A list of dimension dependencies
147
148   Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ];         ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
149
150   float negotiatedDimensions[ Dimension::DIMENSION_COUNT ];       ///< Storage for when a dimension is negotiated but before set on actor
151
152   float minimumSize[ Dimension::DIMENSION_COUNT ];                ///< The minimum size an actor can be
153   float maximumSize[ Dimension::DIMENSION_COUNT ];                ///< The maximum size an actor can be
154
155   bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ];         ///< Has the dimension been negotiated
156   bool dimensionDirty[ Dimension::DIMENSION_COUNT ];              ///< Flags indicating whether the layout dimension is dirty or not
157
158   Vector3 sizeModeFactor;                              ///< Factor of size used for certain SizeModes
159
160   Vector2 preferredSize;                               ///< The preferred size of the actor
161
162   SizeScalePolicy::Type sizeSetPolicy :3;            ///< Policy to apply when setting size. Enough room for the enum
163
164   bool relayoutEnabled :1;                   ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
165   bool insideRelayout :1;                    ///< Locking flag to prevent recursive relayouts on size set
166 };
167
168 namespace // unnamed namespace
169 {
170
171 // Properties
172
173 /**
174  * We want to discourage the use of property strings (minimize string comparisons),
175  * particularly for the default properties.
176  *              Name                Type   writable animatable constraint-input  enum for index-checking
177  */
178 DALI_PROPERTY_TABLE_BEGIN
179 DALI_PROPERTY( "parentOrigin",      VECTOR3,  true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN )
180 DALI_PROPERTY( "parentOriginX",     FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_X )
181 DALI_PROPERTY( "parentOriginY",     FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_Y )
182 DALI_PROPERTY( "parentOriginZ",     FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_Z )
183 DALI_PROPERTY( "anchorPoint",       VECTOR3,  true,  false, true,  Dali::Actor::Property::ANCHOR_POINT )
184 DALI_PROPERTY( "anchorPointX",      FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_X )
185 DALI_PROPERTY( "anchorPointY",      FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_Y )
186 DALI_PROPERTY( "anchorPointZ",      FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_Z )
187 DALI_PROPERTY( "size",              VECTOR3,  true,  true,  true,  Dali::Actor::Property::SIZE )
188 DALI_PROPERTY( "sizeWidth",         FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_WIDTH )
189 DALI_PROPERTY( "sizeHeight",        FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_HEIGHT )
190 DALI_PROPERTY( "sizeDepth",         FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_DEPTH )
191 DALI_PROPERTY( "position",          VECTOR3,  true,  true,  true,  Dali::Actor::Property::POSITION )
192 DALI_PROPERTY( "positionX",         FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_X )
193 DALI_PROPERTY( "positionY",         FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_Y )
194 DALI_PROPERTY( "positionZ",         FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_Z )
195 DALI_PROPERTY( "worldPosition",     VECTOR3,  false, false, true,  Dali::Actor::Property::WORLD_POSITION )
196 DALI_PROPERTY( "worldPositionX",    FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_X )
197 DALI_PROPERTY( "worldPositionY",    FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_Y )
198 DALI_PROPERTY( "worldPositionZ",    FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_Z )
199 DALI_PROPERTY( "orientation",       ROTATION, true,  true,  true,  Dali::Actor::Property::ORIENTATION )
200 DALI_PROPERTY( "worldOrientation",  ROTATION, false, false, true,  Dali::Actor::Property::WORLD_ORIENTATION )
201 DALI_PROPERTY( "scale",             VECTOR3,  true,  true,  true,  Dali::Actor::Property::SCALE )
202 DALI_PROPERTY( "scaleX",            FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_X )
203 DALI_PROPERTY( "scaleY",            FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_Y )
204 DALI_PROPERTY( "scaleZ",            FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_Z )
205 DALI_PROPERTY( "worldScale",        VECTOR3,  false, false, true,  Dali::Actor::Property::WORLD_SCALE )
206 DALI_PROPERTY( "visible",           BOOLEAN,  true,  true,  true,  Dali::Actor::Property::VISIBLE )
207 DALI_PROPERTY( "color",             VECTOR4,  true,  true,  true,  Dali::Actor::Property::COLOR )
208 DALI_PROPERTY( "colorRed",          FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_RED )
209 DALI_PROPERTY( "colorGreen",        FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_GREEN )
210 DALI_PROPERTY( "colorBlue",         FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_BLUE )
211 DALI_PROPERTY( "colorAlpha",        FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_ALPHA )
212 DALI_PROPERTY( "worldColor",        VECTOR4,  false, false, true,  Dali::Actor::Property::WORLD_COLOR )
213 DALI_PROPERTY( "worldMatrix",       MATRIX,   false, false, true,  Dali::Actor::Property::WORLD_MATRIX )
214 DALI_PROPERTY( "name",              STRING,   true,  false, false, Dali::Actor::Property::NAME )
215 DALI_PROPERTY( "sensitive",         BOOLEAN,  true,  false, false, Dali::Actor::Property::SENSITIVE )
216 DALI_PROPERTY( "leaveRequired",     BOOLEAN,  true,  false, false, Dali::Actor::Property::LEAVE_REQUIRED )
217 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true,  false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
218 DALI_PROPERTY( "inheritScale",      BOOLEAN,  true,  false, false, Dali::Actor::Property::INHERIT_SCALE )
219 DALI_PROPERTY( "colorMode",         STRING,   true,  false, false, Dali::Actor::Property::COLOR_MODE )
220 DALI_PROPERTY( "positionInheritance", STRING, true,  false, false, Dali::Actor::Property::POSITION_INHERITANCE )
221 DALI_PROPERTY( "drawMode",          STRING,   true,  false, false, Dali::Actor::Property::DRAW_MODE )
222 DALI_PROPERTY( "sizeModeFactor",    VECTOR3,  true,  false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
223 DALI_PROPERTY( "widthResizePolicy",  STRING,  true,  false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
224 DALI_PROPERTY( "heightResizePolicy",  STRING, true,  false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
225 DALI_PROPERTY( "sizeScalePolicy",   STRING,   true,  false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
226 DALI_PROPERTY( "widthForHeight",    BOOLEAN,  true,  false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
227 DALI_PROPERTY( "heightForWidth",    BOOLEAN,  true,  false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
228 DALI_PROPERTY( "padding",           VECTOR4,  true,  false, false, Dali::Actor::Property::PADDING )
229 DALI_PROPERTY( "minimumSize",       VECTOR2,  true,  false, false, Dali::Actor::Property::MINIMUM_SIZE )
230 DALI_PROPERTY( "maximumSize",       VECTOR2,  true,  false, false, Dali::Actor::Property::MAXIMUM_SIZE )
231 DALI_PROPERTY( "inheritPosition",   BOOLEAN,  true,  false, false, Dali::Actor::Property::INHERIT_POSITION )
232 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
233
234 // Signals
235
236 const char* const SIGNAL_TOUCHED = "touched";
237 const char* const SIGNAL_HOVERED = "hovered";
238 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
239 const char* const SIGNAL_ON_STAGE = "onStage";
240 const char* const SIGNAL_OFF_STAGE = "offStage";
241 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
242
243 // Actions
244
245 const char* const ACTION_SHOW = "show";
246 const char* const ACTION_HIDE = "hide";
247
248 BaseHandle CreateActor()
249 {
250   return Dali::Actor::New();
251 }
252
253 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
254
255 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
256 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
257 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
258 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
259 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
261
262 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
263 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
264
265 /**
266  * @brief Extract a given dimension from a Vector2
267  *
268  * @param[in] values The values to extract from
269  * @param[in] dimension The dimension to extract
270  * @return Return the value for the dimension
271  */
272 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
273 {
274   switch( dimension )
275   {
276     case Dimension::WIDTH:
277     {
278       return values.width;
279     }
280     case Dimension::HEIGHT:
281     {
282       return values.height;
283     }
284     default:
285     {
286       break;
287     }
288   }
289   return 0.0f;
290 }
291
292 /**
293  * @brief Extract a given dimension from a Vector3
294  *
295  * @param[in] values The values to extract from
296  * @param[in] dimension The dimension to extract
297  * @return Return the value for the dimension
298  */
299 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
300 {
301   return GetDimensionValue( values.GetVectorXY(), dimension );
302 }
303
304
305 } // unnamed namespace
306
307 ActorPtr Actor::New()
308 {
309   ActorPtr actor( new Actor( BASIC ) );
310
311   // Second-phase construction
312   actor->Initialize();
313
314   return actor;
315 }
316
317 const std::string& Actor::GetName() const
318 {
319   return mName;
320 }
321
322 void Actor::SetName( const std::string& name )
323 {
324   mName = name;
325
326   if( NULL != mNode )
327   {
328     // ATTENTION: string for debug purposes is not thread safe.
329     DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
330   }
331 }
332
333 unsigned int Actor::GetId() const
334 {
335   return mId;
336 }
337
338 bool Actor::OnStage() const
339 {
340   return mIsOnStage;
341 }
342
343 Dali::Layer Actor::GetLayer()
344 {
345   Dali::Layer layer;
346
347   // Short-circuit for Layer derived actors
348   if( mIsLayer )
349   {
350     layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
351   }
352
353   // Find the immediate Layer parent
354   for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
355   {
356     if( parent->IsLayer() )
357     {
358       layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
359     }
360   }
361
362   return layer;
363 }
364
365 void Actor::Add( Actor& child )
366 {
367   DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
368   DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
369
370   if( !mChildren )
371   {
372     mChildren = new ActorContainer;
373   }
374
375   Actor* const oldParent( child.mParent );
376
377   // child might already be ours
378   if( this != oldParent )
379   {
380     // if we already have parent, unparent us first
381     if( oldParent )
382     {
383       oldParent->Remove( child ); // This causes OnChildRemove callback
384
385       // Old parent may need to readjust to missing child
386       if( oldParent->RelayoutDependentOnChildren() )
387       {
388         oldParent->RelayoutRequest();
389       }
390     }
391
392     // Guard against Add() during previous OnChildRemove callback
393     if( !child.mParent )
394     {
395       // Do this first, since user callbacks from within SetParent() may need to remove child
396       mChildren->push_back( ActorPtr( &child ) );
397
398       // SetParent asserts that child can be added
399       child.SetParent( this );
400
401       // Notification for derived classes
402       OnChildAdd( child );
403
404       // Only put in a relayout request if there is a suitable dependency
405       if( RelayoutDependentOnChildren() )
406       {
407         RelayoutRequest();
408       }
409     }
410   }
411 }
412
413 void Actor::Remove( Actor& child )
414 {
415   if( (this == &child) || (!mChildren) )
416   {
417     // no children or removing itself
418     return;
419   }
420
421   ActorPtr removed;
422
423   // Find the child in mChildren, and unparent it
424   ActorIter end = mChildren->end();
425   for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
426   {
427     ActorPtr actor = (*iter);
428
429     if( actor.Get() == &child )
430     {
431       // Keep handle for OnChildRemove notification
432       removed = actor;
433
434       // Do this first, since user callbacks from within SetParent() may need to add the child
435       mChildren->erase( iter );
436
437       DALI_ASSERT_DEBUG( actor->GetParent() == this );
438       actor->SetParent( NULL );
439
440       break;
441     }
442   }
443
444   if( removed )
445   {
446     // Only put in a relayout request if there is a suitable dependency
447     if( RelayoutDependentOnChildren() )
448     {
449       RelayoutRequest();
450     }
451   }
452
453   // Notification for derived classes
454   OnChildRemove( child );
455 }
456
457 void Actor::Unparent()
458 {
459   if( mParent )
460   {
461     // Remove this actor from the parent. The remove will put a relayout request in for
462     // the parent if required
463     mParent->Remove( *this );
464     // mParent is now NULL!
465   }
466 }
467
468 unsigned int Actor::GetChildCount() const
469 {
470   return ( NULL != mChildren ) ? mChildren->size() : 0;
471 }
472
473 ActorPtr Actor::GetChildAt( unsigned int index ) const
474 {
475   DALI_ASSERT_ALWAYS( index < GetChildCount() );
476
477   return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
478 }
479
480 ActorPtr Actor::FindChildByName( const std::string& actorName )
481 {
482   ActorPtr child = 0;
483   if( actorName == mName )
484   {
485     child = this;
486   }
487   else if( mChildren )
488   {
489     ActorIter end = mChildren->end();
490     for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
491     {
492       child = (*iter)->FindChildByName( actorName );
493
494       if( child )
495       {
496         break;
497       }
498     }
499   }
500   return child;
501 }
502
503 ActorPtr Actor::FindChildById( const unsigned int id )
504 {
505   ActorPtr child = 0;
506   if( id == mId )
507   {
508     child = this;
509   }
510   else if( mChildren )
511   {
512     ActorIter end = mChildren->end();
513     for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
514     {
515       child = (*iter)->FindChildById( id );
516
517       if( child )
518       {
519         break;
520       }
521     }
522   }
523   return child;
524 }
525
526 void Actor::SetParentOrigin( const Vector3& origin )
527 {
528   if( NULL != mNode )
529   {
530     // mNode is being used in a separate thread; queue a message to set the value & base value
531     SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
532   }
533
534   // Cache for event-thread access
535   if( !mParentOrigin )
536   {
537     // not allocated, check if different from default
538     if( ParentOrigin::DEFAULT != origin )
539     {
540       mParentOrigin = new Vector3( origin );
541     }
542   }
543   else
544   {
545     // check if different from current costs more than just set
546     *mParentOrigin = origin;
547   }
548 }
549
550 void Actor::SetParentOriginX( float x )
551 {
552   const Vector3& current = GetCurrentParentOrigin();
553
554   SetParentOrigin( Vector3( x, current.y, current.z ) );
555 }
556
557 void Actor::SetParentOriginY( float y )
558 {
559   const Vector3& current = GetCurrentParentOrigin();
560
561   SetParentOrigin( Vector3( current.x, y, current.z ) );
562 }
563
564 void Actor::SetParentOriginZ( float z )
565 {
566   const Vector3& current = GetCurrentParentOrigin();
567
568   SetParentOrigin( Vector3( current.x, current.y, z ) );
569 }
570
571 const Vector3& Actor::GetCurrentParentOrigin() const
572 {
573   // Cached for event-thread access
574   return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
575 }
576
577 void Actor::SetAnchorPoint( const Vector3& anchor )
578 {
579   if( NULL != mNode )
580   {
581     // mNode is being used in a separate thread; queue a message to set the value & base value
582     SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
583   }
584
585   // Cache for event-thread access
586   if( !mAnchorPoint )
587   {
588     // not allocated, check if different from default
589     if( AnchorPoint::DEFAULT != anchor )
590     {
591       mAnchorPoint = new Vector3( anchor );
592     }
593   }
594   else
595   {
596     // check if different from current costs more than just set
597     *mAnchorPoint = anchor;
598   }
599 }
600
601 void Actor::SetAnchorPointX( float x )
602 {
603   const Vector3& current = GetCurrentAnchorPoint();
604
605   SetAnchorPoint( Vector3( x, current.y, current.z ) );
606 }
607
608 void Actor::SetAnchorPointY( float y )
609 {
610   const Vector3& current = GetCurrentAnchorPoint();
611
612   SetAnchorPoint( Vector3( current.x, y, current.z ) );
613 }
614
615 void Actor::SetAnchorPointZ( float z )
616 {
617   const Vector3& current = GetCurrentAnchorPoint();
618
619   SetAnchorPoint( Vector3( current.x, current.y, z ) );
620 }
621
622 const Vector3& Actor::GetCurrentAnchorPoint() const
623 {
624   // Cached for event-thread access
625   return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
626 }
627
628 void Actor::SetPosition( float x, float y )
629 {
630   SetPosition( Vector3( x, y, 0.0f ) );
631 }
632
633 void Actor::SetPosition( float x, float y, float z )
634 {
635   SetPosition( Vector3( x, y, z ) );
636 }
637
638 void Actor::SetPosition( const Vector3& position )
639 {
640   mTargetPosition = position;
641
642   if( NULL != mNode )
643   {
644     // mNode is being used in a separate thread; queue a message to set the value & base value
645     SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
646   }
647 }
648
649 void Actor::SetX( float x )
650 {
651   mTargetPosition.x = x;
652
653   if( NULL != mNode )
654   {
655     // mNode is being used in a separate thread; queue a message to set the value & base value
656     SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
657   }
658 }
659
660 void Actor::SetY( float y )
661 {
662   mTargetPosition.y = y;
663
664   if( NULL != mNode )
665   {
666     // mNode is being used in a separate thread; queue a message to set the value & base value
667     SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
668   }
669 }
670
671 void Actor::SetZ( float z )
672 {
673   mTargetPosition.z = z;
674
675   if( NULL != mNode )
676   {
677     // mNode is being used in a separate thread; queue a message to set the value & base value
678     SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
679   }
680 }
681
682 void Actor::TranslateBy( const Vector3& distance )
683 {
684   mTargetPosition += distance;
685
686   if( NULL != mNode )
687   {
688     // mNode is being used in a separate thread; queue a message to set the value & base value
689     SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
690   }
691 }
692
693 const Vector3& Actor::GetCurrentPosition() const
694 {
695   if( NULL != mNode )
696   {
697     // mNode is being used in a separate thread; copy the value from the previous update
698     return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
699   }
700
701   return Vector3::ZERO;
702 }
703
704 const Vector3& Actor::GetTargetPosition() const
705 {
706   return mTargetPosition;
707 }
708
709 const Vector3& Actor::GetCurrentWorldPosition() const
710 {
711   if( NULL != mNode )
712   {
713     // mNode is being used in a separate thread; copy the value from the previous update
714     return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
715   }
716
717   return Vector3::ZERO;
718 }
719
720 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
721 {
722   // this flag is not animatable so keep the value
723   mPositionInheritanceMode = mode;
724   if( NULL != mNode )
725   {
726     // mNode is being used in a separate thread; queue a message to set the value
727     SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
728   }
729 }
730
731 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
732 {
733   // Cached for event-thread access
734   return mPositionInheritanceMode;
735 }
736
737 void Actor::SetInheritPosition( bool inherit )
738 {
739   if( mInheritPosition != inherit && NULL != mNode )
740   {
741     // non animateable so keep local copy
742     mInheritPosition = inherit;
743     SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
744   }
745 }
746
747 bool Actor::IsPositionInherited() const
748 {
749   return mInheritPosition;
750 }
751
752 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
753 {
754   Vector3 normalizedAxis( axis.x, axis.y, axis.z );
755   normalizedAxis.Normalize();
756
757   Quaternion orientation( angle, normalizedAxis );
758
759   SetOrientation( orientation );
760 }
761
762 void Actor::SetOrientation( const Quaternion& orientation )
763 {
764   if( NULL != mNode )
765   {
766     // mNode is being used in a separate thread; queue a message to set the value & base value
767     SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
768   }
769 }
770
771 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
772 {
773   if( NULL != mNode )
774   {
775     // mNode is being used in a separate thread; queue a message to set the value & base value
776     SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, Quaternion(angle, axis) );
777   }
778 }
779
780 void Actor::RotateBy( const Quaternion& relativeRotation )
781 {
782   if( NULL != mNode )
783   {
784     // mNode is being used in a separate thread; queue a message to set the value & base value
785     SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
786   }
787 }
788
789 const Quaternion& Actor::GetCurrentOrientation() const
790 {
791   if( NULL != mNode )
792   {
793     // mNode is being used in a separate thread; copy the value from the previous update
794     return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
795   }
796
797   return Quaternion::IDENTITY;
798 }
799
800 const Quaternion& Actor::GetCurrentWorldOrientation() const
801 {
802   if( NULL != mNode )
803   {
804     // mNode is being used in a separate thread; copy the value from the previous update
805     return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
806   }
807
808   return Quaternion::IDENTITY;
809 }
810
811 void Actor::SetScale( float scale )
812 {
813   SetScale( Vector3( scale, scale, scale ) );
814 }
815
816 void Actor::SetScale( float x, float y, float z )
817 {
818   SetScale( Vector3( x, y, z ) );
819 }
820
821 void Actor::SetScale( const Vector3& scale )
822 {
823   if( NULL != mNode )
824   {
825     // mNode is being used in a separate thread; queue a message to set the value & base value
826     SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
827   }
828 }
829
830 void Actor::SetScaleX( float x )
831 {
832   if( NULL != mNode )
833   {
834     // mNode is being used in a separate thread; queue a message to set the value & base value
835     SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
836   }
837 }
838
839 void Actor::SetScaleY( float y )
840 {
841   if( NULL != mNode )
842   {
843     // mNode is being used in a separate thread; queue a message to set the value & base value
844     SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
845   }
846 }
847
848 void Actor::SetScaleZ( float z )
849 {
850   if( NULL != mNode )
851   {
852     // mNode is being used in a separate thread; queue a message to set the value & base value
853     SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
854   }
855 }
856
857 void Actor::ScaleBy(const Vector3& relativeScale)
858 {
859   if( NULL != mNode )
860   {
861     // mNode is being used in a separate thread; queue a message to set the value & base value
862     SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
863   }
864 }
865
866 const Vector3& Actor::GetCurrentScale() const
867 {
868   if( NULL != mNode )
869   {
870     // mNode is being used in a separate thread; copy the value from the previous update
871     return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
872   }
873
874   return Vector3::ONE;
875 }
876
877 const Vector3& Actor::GetCurrentWorldScale() const
878 {
879   if( NULL != mNode )
880   {
881     // mNode is being used in a separate thread; copy the value from the previous update
882     return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
883   }
884
885   return Vector3::ONE;
886 }
887
888 void Actor::SetInheritScale( bool inherit )
889 {
890
891   if( mInheritScale != inherit && NULL != mNode )
892   {
893     // non animateable so keep local copy
894     mInheritScale = inherit;
895     // mNode is being used in a separate thread; queue a message to set the value
896     SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
897   }
898 }
899
900 bool Actor::IsScaleInherited() const
901 {
902   return mInheritScale;
903 }
904
905 Matrix Actor::GetCurrentWorldMatrix() const
906 {
907   if( NULL != mNode )
908   {
909     return mNode->GetWorldMatrix(0);
910   }
911
912   return Matrix::IDENTITY;
913 }
914
915 void Actor::SetVisible( bool visible )
916 {
917   if( NULL != mNode )
918   {
919     // mNode is being used in a separate thread; queue a message to set the value & base value
920     SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
921   }
922 }
923
924 bool Actor::IsVisible() const
925 {
926   if( NULL != mNode )
927   {
928     // mNode is being used in a separate thread; copy the value from the previous update
929     return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
930   }
931
932   return true;
933 }
934
935 void Actor::SetOpacity( float opacity )
936 {
937   if( NULL != mNode )
938   {
939     // mNode is being used in a separate thread; queue a message to set the value & base value
940     SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
941   }
942 }
943
944 float Actor::GetCurrentOpacity() const
945 {
946   if( NULL != mNode )
947   {
948     // mNode is being used in a separate thread; copy the value from the previous update
949     return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
950   }
951
952   return 1.0f;
953 }
954
955 const Vector4& Actor::GetCurrentWorldColor() const
956 {
957   if( NULL != mNode )
958   {
959     return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
960   }
961
962   return Color::WHITE;
963 }
964
965 void Actor::SetColor( const Vector4& color )
966 {
967   if( NULL != mNode )
968   {
969     // mNode is being used in a separate thread; queue a message to set the value & base value
970     SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
971   }
972 }
973
974 void Actor::SetColorRed( float red )
975 {
976   if( NULL != mNode )
977   {
978     // mNode is being used in a separate thread; queue a message to set the value & base value
979     SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
980   }
981 }
982
983 void Actor::SetColorGreen( float green )
984 {
985   if( NULL != mNode )
986   {
987     // mNode is being used in a separate thread; queue a message to set the value & base value
988     SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
989   }
990 }
991
992 void Actor::SetColorBlue( float blue )
993 {
994   if( NULL != mNode )
995   {
996     // mNode is being used in a separate thread; queue a message to set the value & base value
997     SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
998   }
999 }
1000
1001 const Vector4& Actor::GetCurrentColor() const
1002 {
1003   if( NULL != mNode )
1004   {
1005     // mNode is being used in a separate thread; copy the value from the previous update
1006     return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1007   }
1008
1009   return Color::WHITE;
1010 }
1011
1012 void Actor::SetInheritOrientation( bool inherit )
1013 {
1014   if( mInheritOrientation != inherit && NULL != mNode)
1015   {
1016     // non animateable so keep local copy
1017     mInheritOrientation = inherit;
1018     // mNode is being used in a separate thread; queue a message to set the value
1019     SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1020   }
1021 }
1022
1023 bool Actor::IsOrientationInherited() const
1024 {
1025   return mInheritOrientation;
1026 }
1027
1028 void Actor::SetSizeModeFactor( const Vector3& factor )
1029 {
1030   EnsureRelayoutData();
1031
1032   mRelayoutData->sizeModeFactor = factor;
1033 }
1034
1035 const Vector3& Actor::GetSizeModeFactor() const
1036 {
1037   if ( mRelayoutData )
1038   {
1039     return mRelayoutData->sizeModeFactor;
1040   }
1041
1042   return GetDefaultSizeModeFactor();
1043 }
1044
1045 void Actor::SetColorMode( ColorMode colorMode )
1046 {
1047   // non animateable so keep local copy
1048   mColorMode = colorMode;
1049   if( NULL != mNode )
1050   {
1051     // mNode is being used in a separate thread; queue a message to set the value
1052     SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1053   }
1054 }
1055
1056 ColorMode Actor::GetColorMode() const
1057 {
1058   // we have cached copy
1059   return mColorMode;
1060 }
1061
1062 void Actor::SetSize( float width, float height )
1063 {
1064   SetSize( Vector2( width, height ) );
1065 }
1066
1067 void Actor::SetSize( float width, float height, float depth )
1068 {
1069   SetSize( Vector3( width, height, depth ) );
1070 }
1071
1072 void Actor::SetSize( const Vector2& size )
1073 {
1074   SetSize( Vector3( size.width, size.height, 0.f ) );
1075 }
1076
1077 void Actor::SetSizeInternal( const Vector2& size )
1078 {
1079   SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1080 }
1081
1082 void Actor::SetSize( const Vector3& size )
1083 {
1084   if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1085   {
1086     // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1087     SetPreferredSize( size.GetVectorXY() );
1088   }
1089   else
1090   {
1091     SetSizeInternal( size );
1092   }
1093 }
1094
1095 void Actor::SetSizeInternal( const Vector3& size )
1096 {
1097   // dont allow recursive loop
1098   DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1099   // check that we have a node AND the new size width, height or depth is at least a little bit different from the old one
1100   if( ( NULL != mNode )&&
1101       ( ( fabsf( mTargetSize.width - size.width  ) > Math::MACHINE_EPSILON_1 )||
1102         ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1103         ( fabsf( mTargetSize.depth - size.depth  ) > Math::MACHINE_EPSILON_1 ) ) )
1104   {
1105     mTargetSize = size;
1106
1107     // mNode is being used in a separate thread; queue a message to set the value & base value
1108     SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1109
1110     // Notification for derived classes
1111     mInsideOnSizeSet = true;
1112     OnSizeSet( mTargetSize );
1113     mInsideOnSizeSet = false;
1114
1115     // Raise a relayout request if the flag is not locked
1116     if( mRelayoutData && !mRelayoutData->insideRelayout )
1117     {
1118       RelayoutRequest();
1119     }
1120   }
1121 }
1122
1123 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1124 {
1125   mTargetSize = targetSize;
1126
1127   // Notify deriving classes
1128   OnSizeAnimation( animation, mTargetSize );
1129 }
1130
1131 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1132 {
1133   if ( Dali::Actor::Property::SIZE_WIDTH == property )
1134   {
1135     mTargetSize.width = targetSize;
1136   }
1137   else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1138   {
1139     mTargetSize.height = targetSize;
1140   }
1141   else if ( Dali::Actor::Property::SIZE_DEPTH == property )
1142   {
1143     mTargetSize.depth = targetSize;
1144   }
1145   // Notify deriving classes
1146   OnSizeAnimation( animation, mTargetSize );
1147 }
1148
1149 void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition )
1150 {
1151   mTargetPosition = targetPosition;
1152 }
1153
1154 void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property )
1155 {
1156   if ( Dali::Actor::Property::POSITION_X == property )
1157   {
1158     mTargetPosition.x = targetPosition;
1159   }
1160   else if ( Dali::Actor::Property::POSITION_Y == property )
1161   {
1162     mTargetPosition.y = targetPosition;
1163   }
1164   else if ( Dali::Actor::Property::POSITION_Z == property )
1165   {
1166     mTargetPosition.z = targetPosition;
1167   }
1168 }
1169
1170 void Actor::SetWidth( float width )
1171 {
1172   mTargetSize.width = width;
1173
1174   if( NULL != mNode )
1175   {
1176     // mNode is being used in a separate thread; queue a message to set the value & base value
1177     SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1178   }
1179 }
1180
1181 void Actor::SetHeight( float height )
1182 {
1183   mTargetSize.height = height;
1184
1185   if( NULL != mNode )
1186   {
1187     // mNode is being used in a separate thread; queue a message to set the value & base value
1188     SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1189   }
1190 }
1191
1192 void Actor::SetDepth( float depth )
1193 {
1194   mTargetSize.depth = depth;
1195
1196   if( NULL != mNode )
1197   {
1198     // mNode is being used in a separate thread; queue a message to set the value & base value
1199     SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1200   }
1201 }
1202
1203 const Vector3& Actor::GetTargetSize() const
1204 {
1205   return mTargetSize;
1206 }
1207
1208 const Vector3& Actor::GetCurrentSize() const
1209 {
1210   if( NULL != mNode )
1211   {
1212     // mNode is being used in a separate thread; copy the value from the previous update
1213     return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1214   }
1215
1216   return Vector3::ZERO;
1217 }
1218
1219 Vector3 Actor::GetNaturalSize() const
1220 {
1221   // It is up to deriving classes to return the appropriate natural size
1222   return Vector3( 0.0f, 0.0f, 0.0f );
1223 }
1224
1225 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1226 {
1227   EnsureRelayoutData();
1228
1229   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1230   {
1231     if( dimension & ( 1 << i ) )
1232     {
1233       mRelayoutData->resizePolicies[ i ] = policy;
1234     }
1235   }
1236
1237   if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1238   {
1239     if( dimension & Dimension::WIDTH )
1240     {
1241       SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1242     }
1243
1244     if( dimension & Dimension::HEIGHT )
1245     {
1246       SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1247     }
1248   }
1249
1250   // If calling SetResizePolicy, assume we want relayout enabled
1251   SetRelayoutEnabled( true );
1252
1253   OnSetResizePolicy( policy, dimension );
1254
1255   // Trigger relayout on this control
1256   RelayoutRequest();
1257 }
1258
1259 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1260 {
1261   if ( mRelayoutData )
1262   {
1263     // If more than one dimension is requested, just return the first one found
1264     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1265     {
1266       if( ( dimension & ( 1 << i ) ) )
1267       {
1268         return mRelayoutData->resizePolicies[ i ];
1269       }
1270     }
1271   }
1272
1273   return ResizePolicy::DEFAULT;
1274 }
1275
1276 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1277 {
1278   EnsureRelayoutData();
1279
1280   mRelayoutData->sizeSetPolicy = policy;
1281 }
1282
1283 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1284 {
1285   if ( mRelayoutData )
1286   {
1287     return mRelayoutData->sizeSetPolicy;
1288   }
1289
1290   return DEFAULT_SIZE_SCALE_POLICY;
1291 }
1292
1293 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1294 {
1295   EnsureRelayoutData();
1296
1297   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1298   {
1299     if( dimension & ( 1 << i ) )
1300     {
1301       mRelayoutData->dimensionDependencies[ i ] = dependency;
1302     }
1303   }
1304 }
1305
1306 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1307 {
1308   if ( mRelayoutData )
1309   {
1310     // If more than one dimension is requested, just return the first one found
1311     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1312     {
1313       if( ( dimension & ( 1 << i ) ) )
1314       {
1315         return mRelayoutData->dimensionDependencies[ i ];
1316       }
1317     }
1318   }
1319
1320   return Dimension::ALL_DIMENSIONS;   // Default
1321 }
1322
1323 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1324 {
1325   // If relayout data has not been allocated yet and the client is requesting
1326   // to disable it, do nothing
1327   if( mRelayoutData || relayoutEnabled )
1328   {
1329     EnsureRelayoutData();
1330
1331     mRelayoutData->relayoutEnabled = relayoutEnabled;
1332   }
1333 }
1334
1335 bool Actor::IsRelayoutEnabled() const
1336 {
1337   // Assume that if relayout data has not been allocated yet then
1338   // relayout is disabled
1339   return mRelayoutData && mRelayoutData->relayoutEnabled;
1340 }
1341
1342 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1343 {
1344   EnsureRelayoutData();
1345
1346   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1347   {
1348     if( dimension & ( 1 << i ) )
1349     {
1350       mRelayoutData->dimensionDirty[ i ] = dirty;
1351     }
1352   }
1353 }
1354
1355 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1356 {
1357   if ( mRelayoutData )
1358   {
1359     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1360     {
1361       if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1362       {
1363         return true;
1364       }
1365     }
1366   }
1367
1368   return false;
1369 }
1370
1371 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1372 {
1373   return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1374 }
1375
1376 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1377 {
1378   return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1379 }
1380
1381 unsigned int Actor::AddRenderer( Renderer& renderer )
1382 {
1383   if( !mRenderers )
1384   {
1385     mRenderers = new RendererContainer;
1386   }
1387
1388   unsigned int index = mRenderers->size();
1389   RendererPtr rendererPtr = RendererPtr( &renderer );
1390   mRenderers->push_back( rendererPtr );
1391   AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1392
1393   if( mIsOnStage)
1394   {
1395     rendererPtr->Connect();
1396   }
1397
1398   return index;
1399 }
1400
1401 unsigned int Actor::GetRendererCount() const
1402 {
1403   unsigned int rendererCount(0);
1404   if( mRenderers )
1405   {
1406     rendererCount = mRenderers->size();
1407   }
1408
1409   return rendererCount;
1410 }
1411
1412 RendererPtr Actor::GetRendererAt( unsigned int index )
1413 {
1414   RendererPtr renderer;
1415   if( index < GetRendererCount() )
1416   {
1417     renderer = ( *mRenderers )[ index ];
1418   }
1419
1420   return renderer;
1421 }
1422
1423 void Actor::RemoveRenderer( Renderer& renderer )
1424 {
1425   if( mRenderers )
1426   {
1427     RendererIter end = mRenderers->end();
1428     for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1429     {
1430       if( (*iter).Get() == &renderer )
1431       {
1432         mRenderers->erase( iter );
1433         RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1434         break;
1435       }
1436     }
1437   }
1438 }
1439
1440 void Actor::RemoveRenderer( unsigned int index )
1441 {
1442   if( index < GetRendererCount() )
1443   {
1444     RendererPtr renderer = ( *mRenderers )[ index ];
1445     RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1446     mRenderers->erase( mRenderers->begin()+index );
1447   }
1448 }
1449
1450 void Actor::SetOverlay( bool enable )
1451 {
1452   // Setting STENCIL will override OVERLAY_2D
1453   if( DrawMode::STENCIL != mDrawMode )
1454   {
1455     SetDrawMode( enable ? DrawMode::OVERLAY_2D : DrawMode::NORMAL );
1456   }
1457 }
1458
1459 bool Actor::IsOverlay() const
1460 {
1461   return ( DrawMode::OVERLAY_2D == mDrawMode );
1462 }
1463
1464 void Actor::SetDrawMode( DrawMode::Type drawMode )
1465 {
1466   // this flag is not animatable so keep the value
1467   mDrawMode = drawMode;
1468   if( NULL != mNode )
1469   {
1470     // mNode is being used in a separate thread; queue a message to set the value
1471     SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1472   }
1473 }
1474
1475 DrawMode::Type Actor::GetDrawMode() const
1476 {
1477   return mDrawMode;
1478 }
1479
1480 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1481 {
1482   // only valid when on-stage
1483   StagePtr stage = Stage::GetCurrent();
1484   if( stage && OnStage() )
1485   {
1486     const RenderTaskList& taskList = stage->GetRenderTaskList();
1487
1488     Vector2 converted( screenX, screenY );
1489
1490     // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1491     const int taskCount = taskList.GetTaskCount();
1492     for( int i = taskCount - 1; i >= 0; --i )
1493     {
1494       Dali::RenderTask task = taskList.GetTask( i );
1495       if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1496       {
1497         // found a task where this conversion was ok so return
1498         return true;
1499       }
1500     }
1501   }
1502   return false;
1503 }
1504
1505 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1506 {
1507   bool retval = false;
1508   // only valid when on-stage
1509   if( OnStage() )
1510   {
1511     CameraActor* camera = renderTask.GetCameraActor();
1512     if( camera )
1513     {
1514       Viewport viewport;
1515       renderTask.GetViewport( viewport );
1516
1517       // need to translate coordinates to render tasks coordinate space
1518       Vector2 converted( screenX, screenY );
1519       if( renderTask.TranslateCoordinates( converted ) )
1520       {
1521         retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1522       }
1523     }
1524   }
1525   return retval;
1526 }
1527
1528 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1529 {
1530   // Early-out if mNode is NULL
1531   if( !OnStage() )
1532   {
1533     return false;
1534   }
1535
1536   // Get the ModelView matrix
1537   Matrix modelView;
1538   Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1539
1540   // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1541   Matrix invertedMvp( false/*don't init*/);
1542   Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1543   bool success = invertedMvp.Invert();
1544
1545   // Convert to GL coordinates
1546   Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1547
1548   Vector4 nearPos;
1549   if( success )
1550   {
1551     success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1552   }
1553
1554   Vector4 farPos;
1555   if( success )
1556   {
1557     screenPos.z = 1.0f;
1558     success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1559   }
1560
1561   if( success )
1562   {
1563     Vector4 local;
1564     if( XyPlaneIntersect( nearPos, farPos, local ) )
1565     {
1566       Vector3 size = GetCurrentSize();
1567       localX = local.x + size.x * 0.5f;
1568       localY = local.y + size.y * 0.5f;
1569     }
1570     else
1571     {
1572       success = false;
1573     }
1574   }
1575
1576   return success;
1577 }
1578
1579 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1580 {
1581   /*
1582    http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1583
1584    Mathematical Formulation
1585
1586    Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1587
1588    ( p - c ) dot ( p - c ) = r^2
1589
1590    Given a ray with a point of origin 'o', and a direction vector 'd':
1591
1592    ray(t) = o + td, t >= 0
1593
1594    we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1595
1596    (o + td - c ) dot ( o + td - c ) = r^2
1597
1598    To solve for t we first expand the above into a more recognisable quadratic equation form
1599
1600    ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1601
1602    or
1603
1604    At2 + Bt + C = 0
1605
1606    where
1607
1608    A = d dot d
1609    B = 2( o - c ) dot d
1610    C = ( o - c ) dot ( o - c ) - r^2
1611
1612    which can be solved using a standard quadratic formula.
1613
1614    Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1615
1616    Practical Simplification
1617
1618    In a renderer, we often differentiate between world space and object space. In the object space
1619    of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1620    into object space, the mathematical solution presented above can be simplified significantly.
1621
1622    If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1623
1624    p dot p = r^2
1625
1626    and we can find the t at which the (transformed) ray intersects the sphere by
1627
1628    ( o + td ) dot ( o + td ) = r^2
1629
1630    According to the reasoning above, we expand the above quadratic equation into the general form
1631
1632    At2 + Bt + C = 0
1633
1634    which now has coefficients:
1635
1636    A = d dot d
1637    B = 2( d dot o )
1638    C = o dot o - r^2
1639    */
1640
1641   // Early out if mNode is NULL
1642   if( !mNode )
1643   {
1644     return false;
1645   }
1646
1647   BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1648
1649   // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1650   const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1651   Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1652
1653   // Compute the radius is not needed, square radius it's enough.
1654   const Vector3& size( mNode->GetSize( bufferIndex ) );
1655
1656   // Scale the sphere.
1657   const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1658
1659   const float width = size.width * scale.width;
1660   const float height = size.height * scale.height;
1661
1662   float squareSphereRadius = 0.5f * ( width * width + height * height );
1663
1664   float a = rayDir.Dot( rayDir );                                       // a
1665   float b2 = rayDir.Dot( rayOriginLocal );                              // b/2
1666   float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius;  // c
1667
1668   return ( b2 * b2 - a * c ) >= 0.f;
1669 }
1670
1671 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
1672 {
1673   bool hit = false;
1674
1675   if( OnStage() &&
1676   NULL != mNode )
1677   {
1678     // Transforms the ray to the local reference system.
1679     // Calculate the inverse of Model matrix
1680     Matrix invModelMatrix( false/*don't init*/);
1681
1682     BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1683     invModelMatrix = mNode->GetWorldMatrix(0);
1684     invModelMatrix.Invert();
1685
1686     Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1687     Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1688
1689     // Test with the actor's XY plane (Normal = 0 0 1 1).
1690
1691     float a = -rayOriginLocal.z;
1692     float b = rayDirLocal.z;
1693
1694     if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1695     {
1696       // Ray travels distance * rayDirLocal to intersect with plane.
1697       distance = a / b;
1698
1699       const Vector3& size = mNode->GetSize( bufferIndex );
1700
1701       hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1702       hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1703
1704       // Test with the actor's geometry.
1705       hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1706     }
1707   }
1708
1709   return hit;
1710 }
1711
1712 void Actor::SetLeaveRequired( bool required )
1713 {
1714   mLeaveRequired = required;
1715 }
1716
1717 bool Actor::GetLeaveRequired() const
1718 {
1719   return mLeaveRequired;
1720 }
1721
1722 void Actor::SetKeyboardFocusable( bool focusable )
1723 {
1724   mKeyboardFocusable = focusable;
1725 }
1726
1727 bool Actor::IsKeyboardFocusable() const
1728 {
1729   return mKeyboardFocusable;
1730 }
1731
1732 bool Actor::GetTouchRequired() const
1733 {
1734   return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
1735 }
1736
1737 bool Actor::GetHoverRequired() const
1738 {
1739   return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1740 }
1741
1742 bool Actor::GetWheelEventRequired() const
1743 {
1744   return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1745 }
1746
1747 bool Actor::IsHittable() const
1748 {
1749   return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1750 }
1751
1752 ActorGestureData& Actor::GetGestureData()
1753 {
1754   // Likely scenario is that once gesture-data is created for this actor, the actor will require
1755   // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1756   if( NULL == mGestureData )
1757   {
1758     mGestureData = new ActorGestureData;
1759   }
1760   return *mGestureData;
1761 }
1762
1763 bool Actor::IsGestureRequred( Gesture::Type type ) const
1764 {
1765   return mGestureData && mGestureData->IsGestureRequred( type );
1766 }
1767
1768 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
1769 {
1770   bool consumed = false;
1771
1772   if( !mTouchedSignal.Empty() )
1773   {
1774     Dali::Actor handle( this );
1775     consumed = mTouchedSignal.Emit( handle, event );
1776   }
1777
1778   if( !consumed )
1779   {
1780     // Notification for derived classes
1781     consumed = OnTouchEvent( event );
1782   }
1783
1784   return consumed;
1785 }
1786
1787 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1788 {
1789   bool consumed = false;
1790
1791   if( !mHoveredSignal.Empty() )
1792   {
1793     Dali::Actor handle( this );
1794     consumed = mHoveredSignal.Emit( handle, event );
1795   }
1796
1797   if( !consumed )
1798   {
1799     // Notification for derived classes
1800     consumed = OnHoverEvent( event );
1801   }
1802
1803   return consumed;
1804 }
1805
1806 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1807 {
1808   bool consumed = false;
1809
1810   if( !mWheelEventSignal.Empty() )
1811   {
1812     Dali::Actor handle( this );
1813     consumed = mWheelEventSignal.Emit( handle, event );
1814   }
1815
1816   if( !consumed )
1817   {
1818     // Notification for derived classes
1819     consumed = OnWheelEvent( event );
1820   }
1821
1822   return consumed;
1823 }
1824
1825 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1826 {
1827   return mTouchedSignal;
1828 }
1829
1830 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1831 {
1832   return mHoveredSignal;
1833 }
1834
1835 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1836 {
1837   return mWheelEventSignal;
1838 }
1839
1840 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1841 {
1842   return mOnStageSignal;
1843 }
1844
1845 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1846 {
1847   return mOffStageSignal;
1848 }
1849
1850 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1851 {
1852   return mOnRelayoutSignal;
1853 }
1854
1855 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1856 {
1857   bool connected( true );
1858   Actor* actor = dynamic_cast< Actor* >( object );
1859
1860   if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1861   {
1862     actor->TouchedSignal().Connect( tracker, functor );
1863   }
1864   else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1865   {
1866     actor->HoveredSignal().Connect( tracker, functor );
1867   }
1868   else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1869   {
1870     actor->WheelEventSignal().Connect( tracker, functor );
1871   }
1872   else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1873   {
1874     actor->OnStageSignal().Connect( tracker, functor );
1875   }
1876   else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1877   {
1878     actor->OffStageSignal().Connect( tracker, functor );
1879   }
1880   else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1881   {
1882     actor->OnRelayoutSignal().Connect( tracker, functor );
1883   }
1884   else
1885   {
1886     // signalName does not match any signal
1887     connected = false;
1888   }
1889
1890   return connected;
1891 }
1892
1893 Actor::Actor( DerivedType derivedType )
1894 : mParent( NULL ),
1895   mChildren( NULL ),
1896   mRenderers( NULL ),
1897   mNode( NULL ),
1898   mParentOrigin( NULL ),
1899   mAnchorPoint( NULL ),
1900   mRelayoutData( NULL ),
1901   mGestureData( NULL ),
1902   mTargetSize( 0.0f, 0.0f, 0.0f ),
1903   mName(),
1904   mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
1905   mDepth( 0u ),
1906   mIsRoot( ROOT_LAYER == derivedType ),
1907   mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1908   mIsOnStage( false ),
1909   mSensitive( true ),
1910   mLeaveRequired( false ),
1911   mKeyboardFocusable( false ),
1912   mDerivedRequiresTouch( false ),
1913   mDerivedRequiresHover( false ),
1914   mDerivedRequiresWheelEvent( false ),
1915   mOnStageSignalled( false ),
1916   mInsideOnSizeSet( false ),
1917   mInheritPosition( true ),
1918   mInheritOrientation( true ),
1919   mInheritScale( true ),
1920   mDrawMode( DrawMode::NORMAL ),
1921   mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
1922   mColorMode( Node::DEFAULT_COLOR_MODE )
1923 {
1924 }
1925
1926 void Actor::Initialize()
1927 {
1928   // Node creation
1929   SceneGraph::Node* node = CreateNode();
1930
1931   AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
1932   mNode = node; // Keep raw-pointer to Node
1933
1934   OnInitialize();
1935
1936   GetEventThreadServices().RegisterObject( this );
1937 }
1938
1939 Actor::~Actor()
1940 {
1941   // Remove mParent pointers from children even if we're destroying core,
1942   // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1943   if( mChildren )
1944   {
1945     ActorConstIter endIter = mChildren->end();
1946     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1947     {
1948       (*iter)->SetParent( NULL );
1949     }
1950   }
1951   delete mChildren;
1952   delete mRenderers;
1953
1954   // Guard to allow handle destruction after Core has been destroyed
1955   if( EventThreadServices::IsCoreRunning() )
1956   {
1957     if( NULL != mNode )
1958     {
1959       DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
1960       mNode = NULL; // Node is about to be destroyed
1961     }
1962
1963     GetEventThreadServices().UnregisterObject( this );
1964   }
1965
1966   // Cleanup optional gesture data
1967   delete mGestureData;
1968
1969   // Cleanup optional parent origin and anchor
1970   delete mParentOrigin;
1971   delete mAnchorPoint;
1972
1973   // Delete optional relayout data
1974   if( mRelayoutData )
1975   {
1976     delete mRelayoutData;
1977   }
1978 }
1979
1980 void Actor::ConnectToStage( unsigned int parentDepth )
1981 {
1982   // This container is used instead of walking the Actor hierarchy.
1983   // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
1984   ActorContainer connectionList;
1985
1986   // This stage is atomic i.e. not interrupted by user callbacks.
1987   RecursiveConnectToStage( connectionList, parentDepth + 1 );
1988
1989   // Notify applications about the newly connected actors.
1990   const ActorIter endIter = connectionList.end();
1991   for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
1992   {
1993     (*iter)->NotifyStageConnection();
1994   }
1995
1996   RelayoutRequest();
1997 }
1998
1999 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2000 {
2001   DALI_ASSERT_ALWAYS( !OnStage() );
2002
2003   mIsOnStage = true;
2004   mDepth = depth;
2005
2006   ConnectToSceneGraph();
2007
2008   // Notification for internal derived classes
2009   OnStageConnectionInternal();
2010
2011   // This stage is atomic; avoid emitting callbacks until all Actors are connected
2012   connectionList.push_back( ActorPtr( this ) );
2013
2014   // Recursively connect children
2015   if( mChildren )
2016   {
2017     ActorConstIter endIter = mChildren->end();
2018     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2019     {
2020       (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2021     }
2022   }
2023 }
2024
2025 /**
2026  * This method is called when the Actor is connected to the Stage.
2027  * The parent must have added its Node to the scene-graph.
2028  * The child must connect its Node to the parent's Node.
2029  * This is recursive; the child calls ConnectToStage() for its children.
2030  */
2031 void Actor::ConnectToSceneGraph()
2032 {
2033   DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2034
2035   if( NULL != mNode )
2036   {
2037     // Reparent Node in next Update
2038     ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2039   }
2040
2041   unsigned int rendererCount( GetRendererCount() );
2042   for( unsigned int i(0); i<rendererCount; ++i )
2043   {
2044     GetRendererAt(i)->Connect();
2045   }
2046
2047   // Request relayout on all actors that are added to the scenegraph
2048   RelayoutRequest();
2049
2050   // Notification for Object::Observers
2051   OnSceneObjectAdd();
2052 }
2053
2054 void Actor::NotifyStageConnection()
2055 {
2056   // Actors can be removed (in a callback), before the on-stage stage is reported.
2057   // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2058   if( OnStage() && !mOnStageSignalled )
2059   {
2060     // Notification for external (CustomActor) derived classes
2061     OnStageConnectionExternal( mDepth );
2062
2063     if( !mOnStageSignal.Empty() )
2064     {
2065       Dali::Actor handle( this );
2066       mOnStageSignal.Emit( handle );
2067     }
2068
2069     // Guard against Remove during callbacks
2070     if( OnStage() )
2071     {
2072       mOnStageSignalled = true; // signal required next time Actor is removed
2073     }
2074   }
2075 }
2076
2077 void Actor::DisconnectFromStage()
2078 {
2079   // This container is used instead of walking the Actor hierachy.
2080   // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2081   ActorContainer disconnectionList;
2082
2083   // This stage is atomic i.e. not interrupted by user callbacks
2084   RecursiveDisconnectFromStage( disconnectionList );
2085
2086   // Notify applications about the newly disconnected actors.
2087   const ActorIter endIter = disconnectionList.end();
2088   for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2089   {
2090     (*iter)->NotifyStageDisconnection();
2091   }
2092 }
2093
2094 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2095 {
2096   DALI_ASSERT_ALWAYS( OnStage() );
2097
2098   // Recursively disconnect children
2099   if( mChildren )
2100   {
2101     ActorConstIter endIter = mChildren->end();
2102     for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2103     {
2104       (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2105     }
2106   }
2107
2108   // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2109   disconnectionList.push_back( ActorPtr( this ) );
2110
2111   // Notification for internal derived classes
2112   OnStageDisconnectionInternal();
2113
2114   DisconnectFromSceneGraph();
2115
2116   mIsOnStage = false;
2117 }
2118
2119 /**
2120  * This method is called by an actor or its parent, before a node removal message is sent.
2121  * This is recursive; the child calls DisconnectFromStage() for its children.
2122  */
2123 void Actor::DisconnectFromSceneGraph()
2124 {
2125   // Notification for Object::Observers
2126   OnSceneObjectRemove();
2127
2128   unsigned int rendererCount( GetRendererCount() );
2129   for( unsigned int i(0); i<rendererCount; ++i )
2130   {
2131     GetRendererAt(i)->Disconnect();
2132   }
2133 }
2134
2135 void Actor::NotifyStageDisconnection()
2136 {
2137   // Actors can be added (in a callback), before the off-stage state is reported.
2138   // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2139   // only do this step if there is a stage, i.e. Core is not being shut down
2140   if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2141   {
2142     // Notification for external (CustomeActor) derived classes
2143     OnStageDisconnectionExternal();
2144
2145     if( !mOffStageSignal.Empty() )
2146     {
2147       Dali::Actor handle( this );
2148       mOffStageSignal.Emit( handle );
2149     }
2150
2151     // Guard against Add during callbacks
2152     if( !OnStage() )
2153     {
2154       mOnStageSignalled = false; // signal required next time Actor is added
2155     }
2156   }
2157 }
2158
2159 bool Actor::IsNodeConnected() const
2160 {
2161   bool connected( false );
2162
2163   if( OnStage() && ( NULL != mNode ) )
2164   {
2165     if( IsRoot() || mNode->GetParent() )
2166     {
2167       connected = true;
2168     }
2169   }
2170
2171   return connected;
2172 }
2173
2174 unsigned int Actor::GetDefaultPropertyCount() const
2175 {
2176   return DEFAULT_PROPERTY_COUNT;
2177 }
2178
2179 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2180 {
2181   indices.Reserve( DEFAULT_PROPERTY_COUNT );
2182
2183   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2184   {
2185     indices.PushBack( i );
2186   }
2187 }
2188
2189 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2190 {
2191   if( index < DEFAULT_PROPERTY_COUNT )
2192   {
2193     return DEFAULT_PROPERTY_DETAILS[ index ].name;
2194   }
2195
2196   return NULL;
2197 }
2198
2199 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2200 {
2201   Property::Index index = Property::INVALID_INDEX;
2202
2203   // Look for name in default properties
2204   for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2205   {
2206     const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2207     if( 0 == name.compare( property->name ) )
2208     {
2209       index = i;
2210       break;
2211     }
2212   }
2213
2214   return index;
2215 }
2216
2217 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2218 {
2219   if( index < DEFAULT_PROPERTY_COUNT )
2220   {
2221     return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2222   }
2223
2224   return false;
2225 }
2226
2227 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2228 {
2229   if( index < DEFAULT_PROPERTY_COUNT )
2230   {
2231     return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2232   }
2233
2234   return false;
2235 }
2236
2237 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2238 {
2239   if( index < DEFAULT_PROPERTY_COUNT )
2240   {
2241     return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2242   }
2243
2244   return false;
2245 }
2246
2247 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2248 {
2249   if( index < DEFAULT_PROPERTY_COUNT )
2250   {
2251     return DEFAULT_PROPERTY_DETAILS[ index ].type;
2252   }
2253
2254   // index out of range...return Property::NONE
2255   return Property::NONE;
2256 }
2257
2258 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2259 {
2260   switch( index )
2261   {
2262     case Dali::Actor::Property::PARENT_ORIGIN:
2263     {
2264       SetParentOrigin( property.Get< Vector3 >() );
2265       break;
2266     }
2267
2268     case Dali::Actor::Property::PARENT_ORIGIN_X:
2269     {
2270       SetParentOriginX( property.Get< float >() );
2271       break;
2272     }
2273
2274     case Dali::Actor::Property::PARENT_ORIGIN_Y:
2275     {
2276       SetParentOriginY( property.Get< float >() );
2277       break;
2278     }
2279
2280     case Dali::Actor::Property::PARENT_ORIGIN_Z:
2281     {
2282       SetParentOriginZ( property.Get< float >() );
2283       break;
2284     }
2285
2286     case Dali::Actor::Property::ANCHOR_POINT:
2287     {
2288       SetAnchorPoint( property.Get< Vector3 >() );
2289       break;
2290     }
2291
2292     case Dali::Actor::Property::ANCHOR_POINT_X:
2293     {
2294       SetAnchorPointX( property.Get< float >() );
2295       break;
2296     }
2297
2298     case Dali::Actor::Property::ANCHOR_POINT_Y:
2299     {
2300       SetAnchorPointY( property.Get< float >() );
2301       break;
2302     }
2303
2304     case Dali::Actor::Property::ANCHOR_POINT_Z:
2305     {
2306       SetAnchorPointZ( property.Get< float >() );
2307       break;
2308     }
2309
2310     case Dali::Actor::Property::SIZE:
2311     {
2312       SetSize( property.Get< Vector3 >() );
2313       break;
2314     }
2315
2316     case Dali::Actor::Property::SIZE_WIDTH:
2317     {
2318       SetWidth( property.Get< float >() );
2319       break;
2320     }
2321
2322     case Dali::Actor::Property::SIZE_HEIGHT:
2323     {
2324       SetHeight( property.Get< float >() );
2325       break;
2326     }
2327
2328     case Dali::Actor::Property::SIZE_DEPTH:
2329     {
2330       SetDepth( property.Get< float >() );
2331       break;
2332     }
2333
2334     case Dali::Actor::Property::POSITION:
2335     {
2336       SetPosition( property.Get< Vector3 >() );
2337       break;
2338     }
2339
2340     case Dali::Actor::Property::POSITION_X:
2341     {
2342       SetX( property.Get< float >() );
2343       break;
2344     }
2345
2346     case Dali::Actor::Property::POSITION_Y:
2347     {
2348       SetY( property.Get< float >() );
2349       break;
2350     }
2351
2352     case Dali::Actor::Property::POSITION_Z:
2353     {
2354       SetZ( property.Get< float >() );
2355       break;
2356     }
2357
2358     case Dali::Actor::Property::ORIENTATION:
2359     {
2360       SetOrientation( property.Get< Quaternion >() );
2361       break;
2362     }
2363
2364     case Dali::Actor::Property::SCALE:
2365     {
2366       SetScale( property.Get< Vector3 >() );
2367       break;
2368     }
2369
2370     case Dali::Actor::Property::SCALE_X:
2371     {
2372       SetScaleX( property.Get< float >() );
2373       break;
2374     }
2375
2376     case Dali::Actor::Property::SCALE_Y:
2377     {
2378       SetScaleY( property.Get< float >() );
2379       break;
2380     }
2381
2382     case Dali::Actor::Property::SCALE_Z:
2383     {
2384       SetScaleZ( property.Get< float >() );
2385       break;
2386     }
2387
2388     case Dali::Actor::Property::VISIBLE:
2389     {
2390       SetVisible( property.Get< bool >() );
2391       break;
2392     }
2393
2394     case Dali::Actor::Property::COLOR:
2395     {
2396       SetColor( property.Get< Vector4 >() );
2397       break;
2398     }
2399
2400     case Dali::Actor::Property::COLOR_RED:
2401     {
2402       SetColorRed( property.Get< float >() );
2403       break;
2404     }
2405
2406     case Dali::Actor::Property::COLOR_GREEN:
2407     {
2408       SetColorGreen( property.Get< float >() );
2409       break;
2410     }
2411
2412     case Dali::Actor::Property::COLOR_BLUE:
2413     {
2414       SetColorBlue( property.Get< float >() );
2415       break;
2416     }
2417
2418     case Dali::Actor::Property::COLOR_ALPHA:
2419     {
2420       SetOpacity( property.Get< float >() );
2421       break;
2422     }
2423
2424     case Dali::Actor::Property::NAME:
2425     {
2426       SetName( property.Get< std::string >() );
2427       break;
2428     }
2429
2430     case Dali::Actor::Property::SENSITIVE:
2431     {
2432       SetSensitive( property.Get< bool >() );
2433       break;
2434     }
2435
2436     case Dali::Actor::Property::LEAVE_REQUIRED:
2437     {
2438       SetLeaveRequired( property.Get< bool >() );
2439       break;
2440     }
2441
2442     case Dali::Actor::Property::INHERIT_POSITION:
2443     {
2444       SetInheritPosition( property.Get< bool >() );
2445       break;
2446     }
2447
2448     case Dali::Actor::Property::INHERIT_ORIENTATION:
2449     {
2450       SetInheritOrientation( property.Get< bool >() );
2451       break;
2452     }
2453
2454     case Dali::Actor::Property::INHERIT_SCALE:
2455     {
2456       SetInheritScale( property.Get< bool >() );
2457       break;
2458     }
2459
2460     case Dali::Actor::Property::COLOR_MODE:
2461     {
2462       SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2463       break;
2464     }
2465
2466     case Dali::Actor::Property::POSITION_INHERITANCE:
2467     {
2468       SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2469       break;
2470     }
2471
2472     case Dali::Actor::Property::DRAW_MODE:
2473     {
2474       SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2475       break;
2476     }
2477
2478     case Dali::Actor::Property::SIZE_MODE_FACTOR:
2479     {
2480       SetSizeModeFactor( property.Get< Vector3 >() );
2481       break;
2482     }
2483
2484     case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2485     {
2486       ResizePolicy::Type type;
2487       if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2488       {
2489         SetResizePolicy( type, Dimension::WIDTH );
2490       }
2491       break;
2492     }
2493
2494     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2495     {
2496       ResizePolicy::Type type;
2497       if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2498       {
2499         SetResizePolicy( type, Dimension::HEIGHT );
2500       }
2501       break;
2502     }
2503
2504     case Dali::Actor::Property::SIZE_SCALE_POLICY:
2505     {
2506       SizeScalePolicy::Type type;
2507       if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2508       {
2509         SetSizeScalePolicy( type );
2510       }
2511       break;
2512     }
2513
2514     case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2515     {
2516       if( property.Get< bool >() )
2517       {
2518         SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2519       }
2520       break;
2521     }
2522
2523     case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2524     {
2525       if( property.Get< bool >() )
2526       {
2527         SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2528       }
2529       break;
2530     }
2531
2532     case Dali::Actor::Property::PADDING:
2533     {
2534       Vector4 padding = property.Get< Vector4 >();
2535       SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2536       SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2537       break;
2538     }
2539
2540     case Dali::Actor::Property::MINIMUM_SIZE:
2541     {
2542       Vector2 size = property.Get< Vector2 >();
2543       SetMinimumSize( size.x, Dimension::WIDTH );
2544       SetMinimumSize( size.y, Dimension::HEIGHT );
2545       break;
2546     }
2547
2548     case Dali::Actor::Property::MAXIMUM_SIZE:
2549     {
2550       Vector2 size = property.Get< Vector2 >();
2551       SetMaximumSize( size.x, Dimension::WIDTH );
2552       SetMaximumSize( size.y, Dimension::HEIGHT );
2553       break;
2554     }
2555
2556     default:
2557     {
2558       // this can happen in the case of a non-animatable default property so just do nothing
2559       break;
2560     }
2561   }
2562 }
2563
2564 // TODO: This method needs to be removed
2565 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2566 {
2567   switch( entry.GetType() )
2568   {
2569     case Property::BOOLEAN:
2570     {
2571       const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2572       DALI_ASSERT_DEBUG( NULL != property );
2573
2574       // property is being used in a separate thread; queue a message to set the property
2575       SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2576
2577       break;
2578     }
2579
2580     case Property::INTEGER:
2581     {
2582       const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2583       DALI_ASSERT_DEBUG( NULL != property );
2584
2585       // property is being used in a separate thread; queue a message to set the property
2586       SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2587
2588       break;
2589     }
2590
2591     case Property::FLOAT:
2592     {
2593       const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2594       DALI_ASSERT_DEBUG( NULL != property );
2595
2596       // property is being used in a separate thread; queue a message to set the property
2597       SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2598
2599       break;
2600     }
2601
2602     case Property::VECTOR2:
2603     {
2604       const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2605       DALI_ASSERT_DEBUG( NULL != property );
2606
2607       // property is being used in a separate thread; queue a message to set the property
2608       if(entry.componentIndex == 0)
2609       {
2610         SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2611       }
2612       else if(entry.componentIndex == 1)
2613       {
2614         SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2615       }
2616       else
2617       {
2618         SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2619       }
2620
2621       break;
2622     }
2623
2624     case Property::VECTOR3:
2625     {
2626       const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2627       DALI_ASSERT_DEBUG( NULL != property );
2628
2629       // property is being used in a separate thread; queue a message to set the property
2630       if(entry.componentIndex == 0)
2631       {
2632         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2633       }
2634       else if(entry.componentIndex == 1)
2635       {
2636         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2637       }
2638       else if(entry.componentIndex == 2)
2639       {
2640         SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2641       }
2642       else
2643       {
2644         SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2645       }
2646
2647       break;
2648     }
2649
2650     case Property::VECTOR4:
2651     {
2652       const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2653       DALI_ASSERT_DEBUG( NULL != property );
2654
2655       // property is being used in a separate thread; queue a message to set the property
2656       if(entry.componentIndex == 0)
2657       {
2658         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2659       }
2660       else if(entry.componentIndex == 1)
2661       {
2662         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2663       }
2664       else if(entry.componentIndex == 2)
2665       {
2666         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2667       }
2668       else if(entry.componentIndex == 3)
2669       {
2670         SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2671       }
2672       else
2673       {
2674         SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2675       }
2676
2677       break;
2678     }
2679
2680     case Property::ROTATION:
2681     {
2682       const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2683       DALI_ASSERT_DEBUG( NULL != property );
2684
2685       // property is being used in a separate thread; queue a message to set the property
2686       SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake,  value.Get<Quaternion>() );
2687
2688       break;
2689     }
2690
2691     case Property::MATRIX:
2692     {
2693       const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2694       DALI_ASSERT_DEBUG( NULL != property );
2695
2696       // property is being used in a separate thread; queue a message to set the property
2697       SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake,  value.Get<Matrix>() );
2698
2699       break;
2700     }
2701
2702     case Property::MATRIX3:
2703     {
2704       const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2705       DALI_ASSERT_DEBUG( NULL != property );
2706
2707       // property is being used in a separate thread; queue a message to set the property
2708       SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake,  value.Get<Matrix3>() );
2709
2710       break;
2711     }
2712
2713     default:
2714     {
2715       DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2716       break;
2717     }
2718   } // entry.GetType
2719 }
2720
2721 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2722 {
2723   Property::Value value;
2724
2725   switch( index )
2726   {
2727     case Dali::Actor::Property::PARENT_ORIGIN:
2728     {
2729       value = GetCurrentParentOrigin();
2730       break;
2731     }
2732
2733     case Dali::Actor::Property::PARENT_ORIGIN_X:
2734     {
2735       value = GetCurrentParentOrigin().x;
2736       break;
2737     }
2738
2739     case Dali::Actor::Property::PARENT_ORIGIN_Y:
2740     {
2741       value = GetCurrentParentOrigin().y;
2742       break;
2743     }
2744
2745     case Dali::Actor::Property::PARENT_ORIGIN_Z:
2746     {
2747       value = GetCurrentParentOrigin().z;
2748       break;
2749     }
2750
2751     case Dali::Actor::Property::ANCHOR_POINT:
2752     {
2753       value = GetCurrentAnchorPoint();
2754       break;
2755     }
2756
2757     case Dali::Actor::Property::ANCHOR_POINT_X:
2758     {
2759       value = GetCurrentAnchorPoint().x;
2760       break;
2761     }
2762
2763     case Dali::Actor::Property::ANCHOR_POINT_Y:
2764     {
2765       value = GetCurrentAnchorPoint().y;
2766       break;
2767     }
2768
2769     case Dali::Actor::Property::ANCHOR_POINT_Z:
2770     {
2771       value = GetCurrentAnchorPoint().z;
2772       break;
2773     }
2774
2775     case Dali::Actor::Property::SIZE:
2776     {
2777       value = GetTargetSize();
2778       break;
2779     }
2780
2781     case Dali::Actor::Property::SIZE_WIDTH:
2782     {
2783       value = GetTargetSize().width;
2784       break;
2785     }
2786
2787     case Dali::Actor::Property::SIZE_HEIGHT:
2788     {
2789       value = GetTargetSize().height;
2790       break;
2791     }
2792
2793     case Dali::Actor::Property::SIZE_DEPTH:
2794     {
2795       value = GetTargetSize().depth;
2796       break;
2797     }
2798
2799     case Dali::Actor::Property::POSITION:
2800     {
2801       value = GetTargetPosition();
2802       break;
2803     }
2804
2805     case Dali::Actor::Property::POSITION_X:
2806     {
2807       value = GetTargetPosition().x;
2808       break;
2809     }
2810
2811     case Dali::Actor::Property::POSITION_Y:
2812     {
2813       value = GetTargetPosition().y;
2814       break;
2815     }
2816
2817     case Dali::Actor::Property::POSITION_Z:
2818     {
2819       value = GetTargetPosition().z;
2820       break;
2821     }
2822
2823     case Dali::Actor::Property::WORLD_POSITION:
2824     {
2825       value = GetCurrentWorldPosition();
2826       break;
2827     }
2828
2829     case Dali::Actor::Property::WORLD_POSITION_X:
2830     {
2831       value = GetCurrentWorldPosition().x;
2832       break;
2833     }
2834
2835     case Dali::Actor::Property::WORLD_POSITION_Y:
2836     {
2837       value = GetCurrentWorldPosition().y;
2838       break;
2839     }
2840
2841     case Dali::Actor::Property::WORLD_POSITION_Z:
2842     {
2843       value = GetCurrentWorldPosition().z;
2844       break;
2845     }
2846
2847     case Dali::Actor::Property::ORIENTATION:
2848     {
2849       value = GetCurrentOrientation();
2850       break;
2851     }
2852
2853     case Dali::Actor::Property::WORLD_ORIENTATION:
2854     {
2855       value = GetCurrentWorldOrientation();
2856       break;
2857     }
2858
2859     case Dali::Actor::Property::SCALE:
2860     {
2861       value = GetCurrentScale();
2862       break;
2863     }
2864
2865     case Dali::Actor::Property::SCALE_X:
2866     {
2867       value = GetCurrentScale().x;
2868       break;
2869     }
2870
2871     case Dali::Actor::Property::SCALE_Y:
2872     {
2873       value = GetCurrentScale().y;
2874       break;
2875     }
2876
2877     case Dali::Actor::Property::SCALE_Z:
2878     {
2879       value = GetCurrentScale().z;
2880       break;
2881     }
2882
2883     case Dali::Actor::Property::WORLD_SCALE:
2884     {
2885       value = GetCurrentWorldScale();
2886       break;
2887     }
2888
2889     case Dali::Actor::Property::VISIBLE:
2890     {
2891       value = IsVisible();
2892       break;
2893     }
2894
2895     case Dali::Actor::Property::COLOR:
2896     {
2897       value = GetCurrentColor();
2898       break;
2899     }
2900
2901     case Dali::Actor::Property::COLOR_RED:
2902     {
2903       value = GetCurrentColor().r;
2904       break;
2905     }
2906
2907     case Dali::Actor::Property::COLOR_GREEN:
2908     {
2909       value = GetCurrentColor().g;
2910       break;
2911     }
2912
2913     case Dali::Actor::Property::COLOR_BLUE:
2914     {
2915       value = GetCurrentColor().b;
2916       break;
2917     }
2918
2919     case Dali::Actor::Property::COLOR_ALPHA:
2920     {
2921       value = GetCurrentColor().a;
2922       break;
2923     }
2924
2925     case Dali::Actor::Property::WORLD_COLOR:
2926     {
2927       value = GetCurrentWorldColor();
2928       break;
2929     }
2930
2931     case Dali::Actor::Property::WORLD_MATRIX:
2932     {
2933       value = GetCurrentWorldMatrix();
2934       break;
2935     }
2936
2937     case Dali::Actor::Property::NAME:
2938     {
2939       value = GetName();
2940       break;
2941     }
2942
2943     case Dali::Actor::Property::SENSITIVE:
2944     {
2945       value = IsSensitive();
2946       break;
2947     }
2948
2949     case Dali::Actor::Property::LEAVE_REQUIRED:
2950     {
2951       value = GetLeaveRequired();
2952       break;
2953     }
2954
2955     case Dali::Actor::Property::INHERIT_POSITION:
2956     {
2957       value = IsPositionInherited();
2958       break;
2959     }
2960
2961     case Dali::Actor::Property::INHERIT_ORIENTATION:
2962     {
2963       value = IsOrientationInherited();
2964       break;
2965     }
2966
2967     case Dali::Actor::Property::INHERIT_SCALE:
2968     {
2969       value = IsScaleInherited();
2970       break;
2971     }
2972
2973     case Dali::Actor::Property::COLOR_MODE:
2974     {
2975       value = Scripting::GetColorMode( GetColorMode() );
2976       break;
2977     }
2978
2979     case Dali::Actor::Property::POSITION_INHERITANCE:
2980     {
2981       value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
2982       break;
2983     }
2984
2985     case Dali::Actor::Property::DRAW_MODE:
2986     {
2987       value = Scripting::GetDrawMode( GetDrawMode() );
2988       break;
2989     }
2990
2991     case Dali::Actor::Property::SIZE_MODE_FACTOR:
2992     {
2993       value = GetSizeModeFactor();
2994       break;
2995     }
2996
2997     case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2998     {
2999       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3000       break;
3001     }
3002
3003     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3004     {
3005       value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3006       break;
3007     }
3008
3009     case Dali::Actor::Property::SIZE_SCALE_POLICY:
3010     {
3011       value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3012       break;
3013     }
3014
3015     case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3016     {
3017       value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3018       break;
3019     }
3020
3021     case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3022     {
3023       value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3024       break;
3025     }
3026
3027     case Dali::Actor::Property::PADDING:
3028     {
3029       Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3030       Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3031       value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3032       break;
3033     }
3034
3035     case Dali::Actor::Property::MINIMUM_SIZE:
3036     {
3037       value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3038       break;
3039     }
3040
3041     case Dali::Actor::Property::MAXIMUM_SIZE:
3042     {
3043       value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3044       break;
3045     }
3046
3047     default:
3048     {
3049       DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3050       break;
3051     }
3052   }
3053
3054   return value;
3055 }
3056
3057 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3058 {
3059   return mNode;
3060 }
3061
3062 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3063 {
3064   // This method should only return an object connected to the scene-graph
3065   return OnStage() ? mNode : NULL;
3066 }
3067
3068 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3069 {
3070   DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3071
3072   const PropertyBase* property( NULL );
3073
3074   // This method should only return a property of an object connected to the scene-graph
3075   if( !OnStage() )
3076   {
3077     return property;
3078   }
3079
3080   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3081   {
3082     AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3083     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3084
3085     property = animatable->GetSceneGraphProperty();
3086   }
3087   else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3088   {
3089     CustomPropertyMetadata* custom = FindCustomProperty( index );
3090     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3091
3092     property = custom->GetSceneGraphProperty();
3093   }
3094   else if( NULL != mNode )
3095   {
3096     switch( index )
3097     {
3098       case Dali::Actor::Property::SIZE:
3099         property = &mNode->mSize;
3100         break;
3101
3102       case Dali::Actor::Property::SIZE_WIDTH:
3103         property = &mNode->mSize;
3104         break;
3105
3106       case Dali::Actor::Property::SIZE_HEIGHT:
3107         property = &mNode->mSize;
3108         break;
3109
3110       case Dali::Actor::Property::SIZE_DEPTH:
3111         property = &mNode->mSize;
3112         break;
3113
3114       case Dali::Actor::Property::POSITION:
3115         property = &mNode->mPosition;
3116         break;
3117
3118       case Dali::Actor::Property::POSITION_X:
3119         property = &mNode->mPosition;
3120         break;
3121
3122       case Dali::Actor::Property::POSITION_Y:
3123         property = &mNode->mPosition;
3124         break;
3125
3126       case Dali::Actor::Property::POSITION_Z:
3127         property = &mNode->mPosition;
3128         break;
3129
3130       case Dali::Actor::Property::ORIENTATION:
3131         property = &mNode->mOrientation;
3132         break;
3133
3134       case Dali::Actor::Property::SCALE:
3135         property = &mNode->mScale;
3136         break;
3137
3138       case Dali::Actor::Property::SCALE_X:
3139         property = &mNode->mScale;
3140         break;
3141
3142       case Dali::Actor::Property::SCALE_Y:
3143         property = &mNode->mScale;
3144         break;
3145
3146       case Dali::Actor::Property::SCALE_Z:
3147         property = &mNode->mScale;
3148         break;
3149
3150       case Dali::Actor::Property::VISIBLE:
3151         property = &mNode->mVisible;
3152         break;
3153
3154       case Dali::Actor::Property::COLOR:
3155         property = &mNode->mColor;
3156         break;
3157
3158       case Dali::Actor::Property::COLOR_RED:
3159         property = &mNode->mColor;
3160         break;
3161
3162       case Dali::Actor::Property::COLOR_GREEN:
3163         property = &mNode->mColor;
3164         break;
3165
3166       case Dali::Actor::Property::COLOR_BLUE:
3167         property = &mNode->mColor;
3168         break;
3169
3170       case Dali::Actor::Property::COLOR_ALPHA:
3171         property = &mNode->mColor;
3172         break;
3173
3174       default:
3175         break;
3176     }
3177   }
3178
3179   return property;
3180 }
3181
3182 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3183 {
3184   const PropertyInputImpl* property( NULL );
3185
3186   // This method should only return a property of an object connected to the scene-graph
3187   if( !OnStage() )
3188   {
3189     return property;
3190   }
3191
3192   if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3193   {
3194     AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3195     DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3196
3197     property = animatable->GetSceneGraphProperty();
3198   }
3199   else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3200   {
3201     CustomPropertyMetadata* custom = FindCustomProperty( index );
3202     DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3203     property = custom->GetSceneGraphProperty();
3204   }
3205   else if( NULL != mNode )
3206   {
3207     switch( index )
3208     {
3209       case Dali::Actor::Property::PARENT_ORIGIN:
3210         property = &mNode->mParentOrigin;
3211         break;
3212
3213       case Dali::Actor::Property::PARENT_ORIGIN_X:
3214         property = &mNode->mParentOrigin;
3215         break;
3216
3217       case Dali::Actor::Property::PARENT_ORIGIN_Y:
3218         property = &mNode->mParentOrigin;
3219         break;
3220
3221       case Dali::Actor::Property::PARENT_ORIGIN_Z:
3222         property = &mNode->mParentOrigin;
3223         break;
3224
3225       case Dali::Actor::Property::ANCHOR_POINT:
3226         property = &mNode->mAnchorPoint;
3227         break;
3228
3229       case Dali::Actor::Property::ANCHOR_POINT_X:
3230         property = &mNode->mAnchorPoint;
3231         break;
3232
3233       case Dali::Actor::Property::ANCHOR_POINT_Y:
3234         property = &mNode->mAnchorPoint;
3235         break;
3236
3237       case Dali::Actor::Property::ANCHOR_POINT_Z:
3238         property = &mNode->mAnchorPoint;
3239         break;
3240
3241       case Dali::Actor::Property::SIZE:
3242         property = &mNode->mSize;
3243         break;
3244
3245       case Dali::Actor::Property::SIZE_WIDTH:
3246         property = &mNode->mSize;
3247         break;
3248
3249       case Dali::Actor::Property::SIZE_HEIGHT:
3250         property = &mNode->mSize;
3251         break;
3252
3253       case Dali::Actor::Property::SIZE_DEPTH:
3254         property = &mNode->mSize;
3255         break;
3256
3257       case Dali::Actor::Property::POSITION:
3258         property = &mNode->mPosition;
3259         break;
3260
3261       case Dali::Actor::Property::POSITION_X:
3262         property = &mNode->mPosition;
3263         break;
3264
3265       case Dali::Actor::Property::POSITION_Y:
3266         property = &mNode->mPosition;
3267         break;
3268
3269       case Dali::Actor::Property::POSITION_Z:
3270         property = &mNode->mPosition;
3271         break;
3272
3273       case Dali::Actor::Property::WORLD_POSITION:
3274         property = &mNode->mWorldPosition;
3275         break;
3276
3277       case Dali::Actor::Property::WORLD_POSITION_X:
3278         property = &mNode->mWorldPosition;
3279         break;
3280
3281       case Dali::Actor::Property::WORLD_POSITION_Y:
3282         property = &mNode->mWorldPosition;
3283         break;
3284
3285       case Dali::Actor::Property::WORLD_POSITION_Z:
3286         property = &mNode->mWorldPosition;
3287         break;
3288
3289       case Dali::Actor::Property::ORIENTATION:
3290         property = &mNode->mOrientation;
3291         break;
3292
3293       case Dali::Actor::Property::WORLD_ORIENTATION:
3294         property = &mNode->mWorldOrientation;
3295         break;
3296
3297       case Dali::Actor::Property::SCALE:
3298         property = &mNode->mScale;
3299         break;
3300
3301       case Dali::Actor::Property::SCALE_X:
3302         property = &mNode->mScale;
3303         break;
3304
3305       case Dali::Actor::Property::SCALE_Y:
3306         property = &mNode->mScale;
3307         break;
3308
3309       case Dali::Actor::Property::SCALE_Z:
3310         property = &mNode->mScale;
3311         break;
3312
3313       case Dali::Actor::Property::WORLD_SCALE:
3314         property = &mNode->mWorldScale;
3315         break;
3316
3317       case Dali::Actor::Property::VISIBLE:
3318         property = &mNode->mVisible;
3319         break;
3320
3321       case Dali::Actor::Property::COLOR:
3322         property = &mNode->mColor;
3323         break;
3324
3325       case Dali::Actor::Property::COLOR_RED:
3326         property = &mNode->mColor;
3327         break;
3328
3329       case Dali::Actor::Property::COLOR_GREEN:
3330         property = &mNode->mColor;
3331         break;
3332
3333       case Dali::Actor::Property::COLOR_BLUE:
3334         property = &mNode->mColor;
3335         break;
3336
3337       case Dali::Actor::Property::COLOR_ALPHA:
3338         property = &mNode->mColor;
3339         break;
3340
3341       case Dali::Actor::Property::WORLD_COLOR:
3342         property = &mNode->mWorldColor;
3343         break;
3344
3345       case Dali::Actor::Property::WORLD_MATRIX:
3346         property = &mNode->mWorldMatrix;
3347         break;
3348
3349       default:
3350         break;
3351     }
3352   }
3353
3354   return property;
3355 }
3356
3357 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3358 {
3359   int componentIndex( Property::INVALID_COMPONENT_INDEX );
3360
3361   if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3362   {
3363     // check whether the animatable property is registered already, if not then register one.
3364     AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3365     if( animatableProperty )
3366     {
3367       componentIndex = animatableProperty->componentIndex;
3368     }
3369   }
3370   else
3371   {
3372     switch( index )
3373     {
3374       case Dali::Actor::Property::PARENT_ORIGIN_X:
3375       case Dali::Actor::Property::ANCHOR_POINT_X:
3376       case Dali::Actor::Property::SIZE_WIDTH:
3377       case Dali::Actor::Property::POSITION_X:
3378       case Dali::Actor::Property::WORLD_POSITION_X:
3379       case Dali::Actor::Property::SCALE_X:
3380       case Dali::Actor::Property::COLOR_RED:
3381       {
3382         componentIndex = 0;
3383         break;
3384       }
3385
3386       case Dali::Actor::Property::PARENT_ORIGIN_Y:
3387       case Dali::Actor::Property::ANCHOR_POINT_Y:
3388       case Dali::Actor::Property::SIZE_HEIGHT:
3389       case Dali::Actor::Property::POSITION_Y:
3390       case Dali::Actor::Property::WORLD_POSITION_Y:
3391       case Dali::Actor::Property::SCALE_Y:
3392       case Dali::Actor::Property::COLOR_GREEN:
3393       {
3394         componentIndex = 1;
3395         break;
3396       }
3397
3398       case Dali::Actor::Property::PARENT_ORIGIN_Z:
3399       case Dali::Actor::Property::ANCHOR_POINT_Z:
3400       case Dali::Actor::Property::SIZE_DEPTH:
3401       case Dali::Actor::Property::POSITION_Z:
3402       case Dali::Actor::Property::WORLD_POSITION_Z:
3403       case Dali::Actor::Property::SCALE_Z:
3404       case Dali::Actor::Property::COLOR_BLUE:
3405       {
3406         componentIndex = 2;
3407         break;
3408       }
3409
3410       case Dali::Actor::Property::COLOR_ALPHA:
3411       {
3412         componentIndex = 3;
3413         break;
3414       }
3415
3416       default:
3417       {
3418         // Do nothing
3419         break;
3420       }
3421     }
3422   }
3423
3424   return componentIndex;
3425 }
3426
3427 void Actor::SetParent( Actor* parent )
3428 {
3429   if( parent )
3430   {
3431     DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3432
3433     mParent = parent;
3434
3435     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3436          parent->OnStage() )
3437     {
3438       // Instruct each actor to create a corresponding node in the scene graph
3439       ConnectToStage( parent->GetHierarchyDepth() );
3440     }
3441   }
3442   else // parent being set to NULL
3443   {
3444     DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3445
3446     mParent = NULL;
3447
3448     if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3449          OnStage() )
3450     {
3451       DALI_ASSERT_ALWAYS( mNode != NULL );
3452
3453       if( NULL != mNode )
3454       {
3455         // Disconnect the Node & its children from the scene-graph.
3456         DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3457       }
3458
3459       // Instruct each actor to discard pointers to the scene-graph
3460       DisconnectFromStage();
3461     }
3462   }
3463 }
3464
3465 SceneGraph::Node* Actor::CreateNode() const
3466 {
3467   return Node::New();
3468 }
3469
3470 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3471 {
3472   bool done = false;
3473   Actor* actor = dynamic_cast< Actor* >( object );
3474
3475   if( actor )
3476   {
3477     if( 0 == actionName.compare( ACTION_SHOW ) )
3478     {
3479       actor->SetVisible( true );
3480       done = true;
3481     }
3482     else if( 0 == actionName.compare( ACTION_HIDE ) )
3483     {
3484       actor->SetVisible( false );
3485       done = true;
3486     }
3487   }
3488
3489   return done;
3490 }
3491
3492 void Actor::EnsureRelayoutData()
3493 {
3494   // Assign relayout data.
3495   if( !mRelayoutData )
3496   {
3497     mRelayoutData = new RelayoutData();
3498   }
3499 }
3500
3501 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3502 {
3503   // Check if actor is dependent on parent
3504   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3505   {
3506     if( ( dimension & ( 1 << i ) ) )
3507     {
3508       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3509       if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3510       {
3511         return true;
3512       }
3513     }
3514   }
3515
3516   return false;
3517 }
3518
3519 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3520 {
3521   // Check if actor is dependent on children
3522   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3523   {
3524     if( ( dimension & ( 1 << i ) ) )
3525     {
3526       const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3527       switch( resizePolicy )
3528       {
3529         case ResizePolicy::FIT_TO_CHILDREN:
3530         case ResizePolicy::USE_NATURAL_SIZE:      // i.e. For things that calculate their size based on children
3531         {
3532           return true;
3533         }
3534
3535         default:
3536         {
3537           break;
3538         }
3539       }
3540     }
3541   }
3542
3543   return false;
3544 }
3545
3546 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3547 {
3548   return Actor::RelayoutDependentOnChildren( dimension );
3549 }
3550
3551 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3552 {
3553   // Check each possible dimension and see if it is dependent on the input one
3554   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3555   {
3556     if( dimension & ( 1 << i ) )
3557     {
3558       return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3559     }
3560   }
3561
3562   return false;
3563 }
3564
3565 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3566 {
3567   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3568   {
3569     if( dimension & ( 1 << i ) )
3570     {
3571       mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3572     }
3573   }
3574 }
3575
3576 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3577 {
3578   // If more than one dimension is requested, just return the first one found
3579   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3580   {
3581     if( ( dimension & ( 1 << i ) ) )
3582     {
3583       return mRelayoutData->negotiatedDimensions[ i ];
3584     }
3585   }
3586
3587   return 0.0f;   // Default
3588 }
3589
3590 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3591 {
3592   EnsureRelayoutData();
3593
3594   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3595   {
3596     if( dimension & ( 1 << i ) )
3597     {
3598       mRelayoutData->dimensionPadding[ i ] = padding;
3599     }
3600   }
3601 }
3602
3603 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3604 {
3605   if ( mRelayoutData )
3606   {
3607     // If more than one dimension is requested, just return the first one found
3608     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3609     {
3610       if( ( dimension & ( 1 << i ) ) )
3611       {
3612         return mRelayoutData->dimensionPadding[ i ];
3613       }
3614     }
3615   }
3616
3617   return GetDefaultDimensionPadding();
3618 }
3619
3620 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3621 {
3622   EnsureRelayoutData();
3623
3624   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3625   {
3626     if( dimension & ( 1 << i ) )
3627     {
3628       mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3629     }
3630   }
3631 }
3632
3633 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3634 {
3635   if ( mRelayoutData )
3636   {
3637     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3638     {
3639       if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3640       {
3641         return true;
3642       }
3643     }
3644   }
3645
3646   return false;
3647 }
3648
3649 float Actor::GetHeightForWidthBase( float width )
3650 {
3651   float height = 0.0f;
3652
3653   const Vector3 naturalSize = GetNaturalSize();
3654   if( naturalSize.width > 0.0f )
3655   {
3656     height = naturalSize.height * width / naturalSize.width;
3657   }
3658   else // we treat 0 as 1:1 aspect ratio
3659   {
3660     height = width;
3661   }
3662
3663   return height;
3664 }
3665
3666 float Actor::GetWidthForHeightBase( float height )
3667 {
3668   float width = 0.0f;
3669
3670   const Vector3 naturalSize = GetNaturalSize();
3671   if( naturalSize.height > 0.0f )
3672   {
3673     width = naturalSize.width * height / naturalSize.height;
3674   }
3675   else // we treat 0 as 1:1 aspect ratio
3676   {
3677     width = height;
3678   }
3679
3680   return width;
3681 }
3682
3683 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3684 {
3685   // Fill to parent, taking size mode factor into account
3686   switch( child.GetResizePolicy( dimension ) )
3687   {
3688     case ResizePolicy::FILL_TO_PARENT:
3689     {
3690       return GetLatestSize( dimension );
3691     }
3692
3693     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3694     {
3695       return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3696     }
3697
3698     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3699     {
3700       return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3701     }
3702
3703     default:
3704     {
3705       return GetLatestSize( dimension );
3706     }
3707   }
3708 }
3709
3710 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3711 {
3712   // Can be overridden in derived class
3713   return CalculateChildSizeBase( child, dimension );
3714 }
3715
3716 float Actor::GetHeightForWidth( float width )
3717 {
3718   // Can be overridden in derived class
3719   return GetHeightForWidthBase( width );
3720 }
3721
3722 float Actor::GetWidthForHeight( float height )
3723 {
3724   // Can be overridden in derived class
3725   return GetWidthForHeightBase( height );
3726 }
3727
3728 float Actor::GetLatestSize( Dimension::Type dimension ) const
3729 {
3730   return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3731 }
3732
3733 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3734 {
3735   Vector2 padding = GetPadding( dimension );
3736
3737   return GetLatestSize( dimension ) + padding.x + padding.y;
3738 }
3739
3740 float Actor::NegotiateFromParent( Dimension::Type dimension )
3741 {
3742   Actor* parent = GetParent();
3743   if( parent )
3744   {
3745     Vector2 padding( GetPadding( dimension ) );
3746     Vector2 parentPadding( parent->GetPadding( dimension ) );
3747     return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3748   }
3749
3750   return 0.0f;
3751 }
3752
3753 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3754 {
3755   float maxDimensionPoint = 0.0f;
3756
3757   for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3758   {
3759     ActorPtr child = GetChildAt( i );
3760
3761     if( !child->RelayoutDependentOnParent( dimension ) )
3762     {
3763       // Calculate the min and max points that the children range across
3764       float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3765       float dimensionSize = child->GetRelayoutSize( dimension );
3766       maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3767     }
3768   }
3769
3770   return maxDimensionPoint;
3771 }
3772
3773 float Actor::GetSize( Dimension::Type dimension ) const
3774 {
3775   return GetDimensionValue( GetTargetSize(), dimension );
3776 }
3777
3778 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3779 {
3780   return GetDimensionValue( GetNaturalSize(), dimension );
3781 }
3782
3783 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3784 {
3785   switch( GetResizePolicy( dimension ) )
3786   {
3787     case ResizePolicy::USE_NATURAL_SIZE:
3788     {
3789       return GetNaturalSize( dimension );
3790     }
3791
3792     case ResizePolicy::FIXED:
3793     {
3794       return GetDimensionValue( GetPreferredSize(), dimension );
3795     }
3796
3797     case ResizePolicy::USE_ASSIGNED_SIZE:
3798     {
3799       return GetDimensionValue( maximumSize, dimension );
3800     }
3801
3802     case ResizePolicy::FILL_TO_PARENT:
3803     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3804     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3805     {
3806       return NegotiateFromParent( dimension );
3807     }
3808
3809     case ResizePolicy::FIT_TO_CHILDREN:
3810     {
3811       return NegotiateFromChildren( dimension );
3812     }
3813
3814     case ResizePolicy::DIMENSION_DEPENDENCY:
3815     {
3816       const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3817
3818       // Custom rules
3819       if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3820       {
3821         return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
3822       }
3823
3824       if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3825       {
3826         return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
3827       }
3828
3829       break;
3830     }
3831
3832     default:
3833     {
3834       break;
3835     }
3836   }
3837
3838   return 0.0f;  // Default
3839 }
3840
3841 float Actor::ClampDimension( float size, Dimension::Type dimension )
3842 {
3843   const float minSize = GetMinimumSize( dimension );
3844   const float maxSize = GetMaximumSize( dimension );
3845
3846   return std::max( minSize, std::min( size, maxSize ) );
3847 }
3848
3849 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
3850 {
3851   // Check if it needs to be negotiated
3852   if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
3853   {
3854     // Check that we havn't gotten into an infinite loop
3855     ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
3856     bool recursionFound = false;
3857     for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
3858     {
3859       if( *it == searchActor )
3860       {
3861         recursionFound = true;
3862         break;
3863       }
3864     }
3865
3866     if( !recursionFound )
3867     {
3868       // Record the path that we have taken
3869       recursionStack.push_back( ActorDimensionPair( this, dimension ) );
3870
3871       // Dimension dependency check
3872       for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3873       {
3874         Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
3875
3876         if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
3877         {
3878           NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
3879         }
3880       }
3881
3882       // Parent dependency check
3883       Actor* parent = GetParent();
3884       if( parent && RelayoutDependentOnParent( dimension ) )
3885       {
3886         parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
3887       }
3888
3889       // Children dependency check
3890       if( RelayoutDependentOnChildren( dimension ) )
3891       {
3892         for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3893         {
3894           ActorPtr child = GetChildAt( i );
3895
3896           // Only relayout child first if it is not dependent on this actor
3897           if( !child->RelayoutDependentOnParent( dimension ) )
3898           {
3899             child->NegotiateDimension( dimension, allocatedSize, recursionStack );
3900           }
3901         }
3902       }
3903
3904       // For deriving classes
3905       OnCalculateRelayoutSize( dimension );
3906
3907       // All dependencies checked, calculate the size and set negotiated flag
3908       const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
3909
3910       SetNegotiatedDimension( newSize, dimension );
3911       SetLayoutNegotiated( true, dimension );
3912
3913       // For deriving classes
3914       OnLayoutNegotiated( newSize, dimension );
3915
3916       // This actor has been successfully processed, pop it off the recursion stack
3917       recursionStack.pop_back();
3918     }
3919     else
3920     {
3921       // TODO: Break infinite loop
3922       SetLayoutNegotiated( true, dimension );
3923     }
3924   }
3925 }
3926
3927 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
3928 {
3929   // Negotiate all dimensions that require it
3930   ActorDimensionStack recursionStack;
3931
3932   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3933   {
3934     const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
3935
3936     // Negotiate
3937     NegotiateDimension( dimension, allocatedSize, recursionStack );
3938   }
3939 }
3940
3941 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
3942 {
3943   switch( mRelayoutData->sizeSetPolicy )
3944   {
3945     case SizeScalePolicy::USE_SIZE_SET:
3946     {
3947       return size;
3948     }
3949
3950     case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
3951     {
3952       // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
3953       const Vector3 naturalSize = GetNaturalSize();
3954       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3955       {
3956         const float sizeRatio = size.width / size.height;
3957         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3958
3959         if( naturalSizeRatio < sizeRatio )
3960         {
3961           return Vector2( naturalSizeRatio * size.height, size.height );
3962         }
3963         else if( naturalSizeRatio > sizeRatio )
3964         {
3965           return Vector2( size.width, size.width / naturalSizeRatio );
3966         }
3967         else
3968         {
3969           return size;
3970         }
3971       }
3972
3973       break;
3974     }
3975
3976     case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
3977     {
3978       // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
3979       const Vector3 naturalSize = GetNaturalSize();
3980       if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3981       {
3982         const float sizeRatio = size.width / size.height;
3983         const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3984
3985         if( naturalSizeRatio < sizeRatio )
3986         {
3987           return Vector2( size.width, size.width / naturalSizeRatio );
3988         }
3989         else if( naturalSizeRatio > sizeRatio )
3990         {
3991           return Vector2( naturalSizeRatio * size.height, size.height );
3992         }
3993         else
3994         {
3995           return size;
3996         }
3997       }
3998       break;
3999     }
4000
4001     default:
4002     {
4003       break;
4004     }
4005   }
4006
4007   return size;
4008 }
4009
4010 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4011 {
4012   // Do the set actor size
4013   Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4014
4015   // Adjust for size set policy
4016   negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4017
4018   // Lock the flag to stop recursive relayouts on set size
4019   mRelayoutData->insideRelayout = true;
4020   SetSize( negotiatedSize );
4021   mRelayoutData->insideRelayout = false;
4022
4023   // Clear flags for all dimensions
4024   SetLayoutDirty( false );
4025
4026   // Give deriving classes a chance to respond
4027   OnRelayout( negotiatedSize, container );
4028
4029   if( !mOnRelayoutSignal.Empty() )
4030   {
4031     Dali::Actor handle( this );
4032     mOnRelayoutSignal.Emit( handle );
4033   }
4034 }
4035
4036 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4037 {
4038   // Force a size negotiation for actors that has assigned size during relayout
4039   // This is required as otherwise the flags that force a relayout will not
4040   // necessarilly be set. This will occur if the actor has already been laid out.
4041   // The dirty flags are then cleared. Then if the actor is added back into the
4042   // relayout container afterwards, the dirty flags would still be clear...
4043   // causing a relayout to be skipped. Here we force any actors added to the
4044   // container to be relayed out.
4045   if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4046   {
4047     SetLayoutNegotiated(false, Dimension::WIDTH);
4048   }
4049   if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4050   {
4051     SetLayoutNegotiated(false, Dimension::HEIGHT);
4052   }
4053
4054   // Do the negotiation
4055   NegotiateDimensions( allocatedSize );
4056
4057   // Set the actor size
4058   SetNegotiatedSize( container );
4059
4060   // Negotiate down to children
4061   const Vector2 newBounds = GetTargetSize().GetVectorXY();
4062
4063   for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4064   {
4065     ActorPtr child = GetChildAt( i );
4066
4067     // Forces children that have already been laid out to be relayed out
4068     // if they have assigned size during relayout.
4069     if(child->GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4070     {
4071       child->SetLayoutNegotiated(false, Dimension::WIDTH);
4072       child->SetLayoutDirty(true, Dimension::WIDTH);
4073     }
4074     if(child->GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4075     {
4076       child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4077       child->SetLayoutDirty(true, Dimension::HEIGHT);
4078     }
4079
4080     // Only relayout if required
4081     if( child->RelayoutRequired() )
4082     {
4083       container.Add( Dali::Actor( child.Get() ), newBounds );
4084     }
4085   }
4086 }
4087
4088 void Actor::RelayoutRequest( Dimension::Type dimension )
4089 {
4090   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4091   if( relayoutController )
4092   {
4093     Dali::Actor self( this );
4094     relayoutController->RequestRelayout( self, dimension );
4095   }
4096 }
4097
4098 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4099 {
4100 }
4101
4102 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4103 {
4104 }
4105
4106 void Actor::SetPreferredSize( const Vector2& size )
4107 {
4108   EnsureRelayoutData();
4109
4110   if( size.width > 0.0f )
4111   {
4112     SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4113   }
4114
4115   if( size.height > 0.0f )
4116   {
4117     SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4118   }
4119
4120   mRelayoutData->preferredSize = size;
4121
4122   RelayoutRequest();
4123 }
4124
4125 Vector2 Actor::GetPreferredSize() const
4126 {
4127   if ( mRelayoutData )
4128   {
4129     return Vector2( mRelayoutData->preferredSize );
4130   }
4131
4132   return GetDefaultPreferredSize();
4133 }
4134
4135 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4136 {
4137   EnsureRelayoutData();
4138
4139   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4140   {
4141     if( dimension & ( 1 << i ) )
4142     {
4143       mRelayoutData->minimumSize[ i ] = size;
4144     }
4145   }
4146
4147   RelayoutRequest();
4148 }
4149
4150 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4151 {
4152   if ( mRelayoutData )
4153   {
4154     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4155     {
4156       if( dimension & ( 1 << i ) )
4157       {
4158         return mRelayoutData->minimumSize[ i ];
4159       }
4160     }
4161   }
4162
4163   return 0.0f;  // Default
4164 }
4165
4166 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4167 {
4168   EnsureRelayoutData();
4169
4170   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4171   {
4172     if( dimension & ( 1 << i ) )
4173     {
4174       mRelayoutData->maximumSize[ i ] = size;
4175     }
4176   }
4177
4178   RelayoutRequest();
4179 }
4180
4181 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4182 {
4183   if ( mRelayoutData )
4184   {
4185     for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4186     {
4187       if( dimension & ( 1 << i ) )
4188       {
4189         return mRelayoutData->maximumSize[ i ];
4190       }
4191     }
4192   }
4193
4194   return FLT_MAX;  // Default
4195 }
4196
4197 } // namespace Internal
4198
4199 } // namespace Dali