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