Changes for std::vector removal from api
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / builder / builder-signals.cpp
1 /*
2  * Copyright (c) 2014 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 // EXTERNAL INCLUDES
19 #include <boost/function.hpp>
20 #include <dali/public-api/actors/layer.h>
21 #include <dali/public-api/common/vector-wrapper.h>
22 #include <dali/public-api/object/type-info.h>
23 #include <dali/public-api/object/property-notification.h>
24 #include <dali/integration-api/debug.h>
25 #include <limits>
26
27 // INTERNAL INCLUDES
28 #include <dali-toolkit/internal/builder/builder-impl.h>
29 #include <dali-toolkit/internal/builder/builder-get-is.inl.h>
30
31 namespace Dali
32 {
33 namespace Toolkit
34 {
35 namespace Internal
36 {
37 extern Animation CreateAnimation( const TreeNode& child, Dali::Toolkit::Internal::Builder* const builder  );
38 extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value );
39 }
40 }
41 }
42
43 namespace
44 {
45 using namespace Dali;
46
47 //
48 // Signal Actions
49 //
50
51 // Action on child actor. The child is found by name
52 struct ChildActorAction
53 {
54   std::string actorName;
55   std::string actionName;
56   std::string childName;
57   Property::Map parameters;
58
59   void operator()(void)
60   {
61     Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName(actorName);
62
63     if(actor)
64     {
65       Actor child_actor = actor.FindChildByName(childName);
66
67       if(child_actor)
68       {
69         child_actor.DoAction(actionName, parameters);
70       }
71       else
72       {
73         DALI_SCRIPT_WARNING("Could not find child by name '%s'\n", childName.c_str());
74       }
75     }
76   };
77 };
78
79 // Action to set a property
80 struct PropertySetAction
81 {
82   std::string actorName;
83   std::string propertyName;
84   Property::Value value;
85
86   void operator()(void)
87   {
88     Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName(actorName);
89
90     if(actor)
91     {
92       Property::Index idx = actor.GetPropertyIndex(propertyName);
93
94       if( idx != Property::INVALID_INDEX )
95       {
96         if( actor.GetPropertyType(idx) != value.GetType() )
97         {
98           DALI_SCRIPT_WARNING("Set property action has different type for property '%s'\n", propertyName.c_str());
99         }
100         else
101         {
102           actor.SetProperty( idx, value );
103         }
104       }
105       else
106       {
107         DALI_SCRIPT_WARNING("Set property action cannot find property '%s'\n", propertyName.c_str());
108       }
109     }
110   };
111 };
112
113 // Generic action on a handle (Animation & Actor)
114 struct GenericAction
115 {
116   std::string actorName;
117   std::string actionName;
118   Property::Map parameters;
119
120   void operator()(void)
121   {
122     Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName(actorName);
123     if(actor)
124     {
125       actor.DoAction(actionName, parameters);
126     }
127
128   };
129 };
130
131 // Delay an animation play; ie wait as its not on stage yet
132 struct DelayedAnimationPlay
133 {
134   OptionalChild                                         animNode;
135   Dali::IntrusivePtr<Dali::Toolkit::Internal::Builder>  builder;
136
137   void operator()(void)
138   {
139     Animation anim = Toolkit::Internal::CreateAnimation(*animNode, builder.Get() );
140     if(anim)
141     {
142       anim.Play();
143     }
144   };
145 };
146
147 // Delay a pathConstrainer apply
148 struct DelayedConstrainerApply
149 {
150   std::string     constrainerName;
151
152   std::vector<std::string> targetActorNames;
153   std::vector<std::string> sourceActorNames;
154   std::vector<std::string> targetPropertyNames;
155   std::vector<std::string> sourcePropertyNames;
156   std::vector<Vector2>  ranges;
157   std::vector<Vector2>  wrapRanges;
158
159   Dali::IntrusivePtr<Dali::Toolkit::Internal::Builder>  builder;
160
161   /*
162    * Helper function to get the parameters to apply each constraint
163    * @param[in] i i-essim element
164    * @param[out] tagetActor Target actor for the constraint
165    * @param[out] tagetPropertyIndex Target property index for the constraint
166    * @param[out] sourceActor Source actor for the constraint
167    * @param[out] sourcePropertyIndex Source property index for the constraint
168    */
169   bool GetApplyParameters( size_t i,
170                            Actor& targetActor, Property::Index& targetPropertyIndex,
171                            Actor& sourceActor, Property::Index& sourcePropertyIndex)
172   {
173
174     targetActor = Stage::GetCurrent().GetRootLayer().FindChildByName(targetActorNames[i]);
175     targetPropertyIndex = Property::INVALID_INDEX;
176     if(targetActor)
177     {
178       targetPropertyIndex = targetActor.GetPropertyIndex(targetPropertyNames[i]);
179       if( targetPropertyIndex ==  Property::INVALID_INDEX )
180       {
181         DALI_SCRIPT_WARNING("Property '%s' not founded in actor '%s'\n", targetPropertyNames[i].c_str(), targetActorNames[i].c_str() );
182         return false;
183       }
184     }
185     else
186     {
187       DALI_SCRIPT_WARNING("Actor '%s' not founded\n", targetActorNames[i].c_str() );
188       return false;
189     }
190
191
192     sourceActor = Stage::GetCurrent().GetRootLayer().FindChildByName(sourceActorNames[i]);
193     sourcePropertyIndex = Property::INVALID_INDEX;
194     if(sourceActor)
195     {
196       sourcePropertyIndex = sourceActor.GetPropertyIndex(sourcePropertyNames[i]);
197       if( sourcePropertyIndex ==  Property::INVALID_INDEX )
198       {
199         DALI_SCRIPT_WARNING("Property '%s' not founded in actor '%s'\n", sourcePropertyNames[i].c_str(), sourceActorNames[i].c_str() );
200         return false;
201       }
202     }
203     else
204     {
205       DALI_SCRIPT_WARNING("Actor '%s' not founded\n", targetActorNames[i].c_str() );
206       return false;
207     }
208     return true;
209   }
210
211   void operator()(void)
212   {
213     Actor sourceActor, targetActor;
214     Property::Index targetPropertyIndex(Property::INVALID_INDEX);
215     Property::Index sourcePropertyIndex(Property::INVALID_INDEX);
216     size_t actorCount( targetActorNames.size() );
217     if( builder.Get()->IsPathConstrainer( constrainerName ))
218     {
219       PathConstrainer constrainer = builder.Get()->GetPathConstrainer(constrainerName);
220       if( constrainer )
221       {
222         for(size_t i(0); i<actorCount; ++i )
223         {
224
225           if( GetApplyParameters( i, targetActor, targetPropertyIndex, sourceActor, sourcePropertyIndex ) )
226           {
227             constrainer.Apply( Property(targetActor,targetPropertyIndex),
228                                Property(sourceActor,sourcePropertyIndex),
229                                ranges[i],
230                                wrapRanges[i]);
231           }
232         }
233       }
234       else
235       {
236         DALI_SCRIPT_WARNING("Constrainer %s not found\n", constrainerName.c_str());
237       }
238     }
239     else if( builder.Get()->IsLinearConstrainer( constrainerName ) )
240     {
241       Dali::LinearConstrainer constrainer( builder.Get()->GetLinearConstrainer(constrainerName));
242       if( constrainer )
243       {
244         for(size_t i(0); i<actorCount; ++i )
245         {
246
247           if( GetApplyParameters( i, targetActor, targetPropertyIndex, sourceActor, sourcePropertyIndex ) )
248           {
249             constrainer.Apply( Property(targetActor,targetPropertyIndex),
250                                Property(sourceActor,sourcePropertyIndex),
251                                ranges[i],
252                                wrapRanges[i]);
253           }
254         }
255       }
256       else
257       {
258         DALI_SCRIPT_WARNING("Constrainer %s not found\n", constrainerName.c_str());
259       }
260     }
261     else
262     {
263       DALI_SCRIPT_WARNING("Constrainer %s is not of a valid type\n", constrainerName.c_str());
264     }
265   }
266 };
267
268 // Delay a pathConstrainer remove
269 struct DelayedConstrainerRemove
270 {
271   std::string     constrainerName;
272   std::vector<std::string> targetActorNames;
273   Dali::IntrusivePtr<Dali::Toolkit::Internal::Builder>  builder;
274
275   void operator()(void)
276   {
277     size_t actorCount( targetActorNames.size() );
278     if( builder.Get()->IsPathConstrainer( constrainerName ))
279     {
280       PathConstrainer constrainer = builder.Get()->GetPathConstrainer(constrainerName);
281       if( constrainer )
282       {
283         for(size_t i(0); i<actorCount; ++i )
284         {
285           Actor targetActor = Stage::GetCurrent().GetRootLayer().FindChildByName(targetActorNames[i]);
286           if(targetActor)
287           {
288             constrainer.Remove( targetActor );
289           }
290         }
291       }
292       else
293       {
294         DALI_SCRIPT_WARNING("Constrainer %s not found\n", constrainerName.c_str());
295       }
296     }
297     else if(builder.Get()->IsLinearConstrainer( constrainerName ))
298     {
299       LinearConstrainer constrainer = builder.Get()->GetLinearConstrainer(constrainerName);
300       if( constrainer )
301       {
302         for(size_t i(0); i<actorCount; ++i )
303         {
304           Actor targetActor = Stage::GetCurrent().GetRootLayer().FindChildByName(targetActorNames[i]);
305           if(targetActor)
306           {
307             constrainer.Remove( targetActor );
308           }
309         }
310       }
311       else
312       {
313         DALI_SCRIPT_WARNING("Constrainer %s not found\n", constrainerName.c_str());
314       }
315     }
316     else
317     {
318       DALI_SCRIPT_WARNING("Constrainer %s is not of a valid type\n", constrainerName.c_str());
319     }
320   }
321 };
322
323 /*
324  * Gets Property::Value from child
325  */
326 Property::Value GetPropertyValue(const TreeNode &child)
327 {
328   size_t nChildren = child.Size();
329
330   Property::Value ret;
331
332   if(0 == nChildren)
333   {
334     // cast away unused return for static analyzers
335     static_cast<void>( Dali::Toolkit::Internal::SetPropertyFromNode( child, ret ) );
336   }
337   else if(1 == nChildren)
338   {
339     // {"property": {"quaternion":[1,2,3,4]} }
340     // {"property": {"angle":22, "axis": [1,2,3]} }
341
342     OptionalChild quaternion  = IsChild(&child, "quaternion");
343     OptionalChild axis        = IsChild(&child, "axis");
344     OptionalChild angle       = IsChild(&child, "angle");
345
346     if(quaternion)
347     {
348       ret = Property::Value(Quaternion(GetVector4(*quaternion)));
349     }
350     else if(axis && angle)
351     {
352       ret = Property::Value(AngleAxis(Degree(GetFloat(*angle)), GetVector3(*axis)));
353     }
354   }
355   else if(2 == nChildren)
356   {
357     // {"property": [1,2]}
358     ret = Property::Value(GetVector2(child));
359   }
360   else if(3 == nChildren)
361   {
362     // {"property": [1,2,3]}
363     ret = Property::Value(GetVector3(child));
364   }
365   else if(4 == nChildren)
366   {
367     // {"property": [1,2,3,4]}
368     ret = Property::Value(GetVector4(child));
369   }
370
371   return ret;
372 }
373
374
375 /*
376  * Gets Parmeter list from child
377  * params is be cleared before insertion
378  */
379 void GetParameters(const TreeNode& child, Property::Map& params)
380 {
381   if( OptionalChild c = IsChild(child, "parameters") )
382   {
383     const TreeNode& node = *c;
384
385     params.Clear();
386
387     for(TreeNode::ConstIterator iter(node.CBegin()); iter != node.CEnd(); ++iter)
388     {
389       params[ (*iter).first ] = GetPropertyValue( (*iter).second );
390     }
391   }
392 }
393
394 void DoNothing(void) {};
395
396 /**
397  * Get an action as boost function callback
398  */
399 boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &child, Actor actor, boost::function<void (void)> quitAction, Dali::Toolkit::Internal::Builder* const builder)
400 {
401   OptionalString childActorName(IsString( IsChild(&child, "child-actor")) );
402   OptionalString actorName(IsString( IsChild(&child, "actor")) );
403   OptionalString propertyName(IsString( IsChild(&child, "property")) );
404   OptionalChild  valueChild( IsChild(&child, "value") );
405
406   OptionalString actionName = IsString( IsChild(&child, "action") );
407   DALI_ASSERT_ALWAYS(actionName && "Signal must have an action");
408
409   boost::function<void(void)> callback = DoNothing;
410
411   if(childActorName)
412   {
413     ChildActorAction action;
414     action.actorName       = *actorName;
415     action.childName       = *childActorName;
416     action.actionName      = *actionName;
417     GetParameters(child, action.parameters);
418     callback = action;
419   }
420   else if(actorName)
421   {
422     if(propertyName && valueChild && ("set" == *actionName) )
423     {
424       PropertySetAction action;
425       action.actorName       = *actorName;
426       action.propertyName    = *propertyName;
427       // actor may not exist yet so we can't check the property type
428       if( !Dali::Toolkit::Internal::SetPropertyFromNode( *valueChild, action.value ) )
429       {
430         DALI_SCRIPT_WARNING("Cannot set property for set property action\n");
431       }
432       callback = action;
433     }
434     else
435     {
436       GenericAction action;
437       action.actorName       = *actorName;
438       action.actionName      = *actionName;
439       GetParameters(child, action.parameters);
440       callback = action;
441     }
442   }
443   else if("quit" == *actionName)
444   {
445     callback = quitAction;
446   }
447   else if("play" == *actionName)
448   {
449     OptionalChild animations     = IsChild( root, "animations" );
450     OptionalString animationName = IsString( IsChild(child, "animation") );
451     if( animations && animationName )
452     {
453       if( OptionalChild animNode = IsChild(*animations, *animationName) )
454       {
455         DelayedAnimationPlay action;
456         action.animNode = animNode;
457         action.builder = builder;
458         // @todo; put constants into the map
459         callback = action;
460       }
461       else
462       {
463         DALI_SCRIPT_WARNING("Cannot find animation '%s'\n", (*animationName).c_str());
464       }
465     }
466     else
467     {
468       DALI_SCRIPT_WARNING("Cannot find animations section\n");
469     }
470   }
471   else if("applyConstraint" == *actionName )
472   {
473     OptionalString constrainerName = IsString( IsChild(child, "constrainer") );
474     if( !constrainerName )
475     {
476       DALI_SCRIPT_WARNING("Need to specify a constrainer\n");
477     }
478     else
479     {
480       DelayedConstrainerApply action;
481       action.constrainerName = *constrainerName;
482       action.builder = builder;
483       OptionalChild propertiesNode = IsChild(child, "properties");
484       if(propertiesNode)
485       {
486         const TreeNode::ConstIterator endIter = (*propertiesNode).CEnd();
487         for( TreeNode::ConstIterator iter = (*propertiesNode).CBegin(); endIter != iter; ++iter )
488         {
489           const TreeNode::KeyNodePair& pKeyChild = *iter;
490           OptionalString sourceActorName(IsString(IsChild(pKeyChild.second, "source")));
491           if(!sourceActorName)
492           {
493             DALI_SCRIPT_WARNING("Need to specify source actor to apply the constraint\n");
494             continue;
495           }
496           OptionalString sourcePropertyName( IsString( IsChild(pKeyChild.second, "sourceProperty" ) ) );
497           if(!sourcePropertyName)
498           {
499             DALI_SCRIPT_WARNING("Need to specify source property to apply the constraint\n");
500             continue;
501           }
502
503           OptionalString targetActorName(IsString(IsChild(pKeyChild.second, "target")));
504           if(!targetActorName)
505           {
506             DALI_SCRIPT_WARNING("Need to specify target actor to apply the constraint\n");
507             continue;
508           }
509
510           OptionalString targetPropertyName( IsString( IsChild(pKeyChild.second, "targetProperty" ) ) );
511           if(!targetPropertyName)
512           {
513             DALI_SCRIPT_WARNING("Need to specify target property name to apply the constraint\n");
514             continue;
515           }
516
517           OptionalVector2 range(IsVector2(IsChild(pKeyChild.second, "range")));
518           if(!range)
519           {
520             DALI_SCRIPT_WARNING("Constrainer range not specified\n");
521             continue;
522           }
523
524           Vector2 wrap(-std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
525           OptionalVector2 wrapRange(IsVector2(IsChild(pKeyChild.second, "wrap")));
526           if(wrapRange)
527           {
528             wrap = *wrapRange;
529           }
530
531           action.sourceActorNames.push_back(*sourceActorName);
532           action.sourcePropertyNames.push_back(*sourcePropertyName);
533           action.targetActorNames.push_back(*targetActorName);
534           action.targetPropertyNames.push_back(*targetPropertyName);
535           action.ranges.push_back(*range);
536           action.wrapRanges.push_back(wrap);
537         }
538
539         callback = action;
540       }
541     }
542
543
544   }
545   else if("removeConstraints" == *actionName )
546   {
547     OptionalString constrainerName = IsString( IsChild(child, "constrainer") );
548     if( !constrainerName )
549     {
550       DALI_SCRIPT_WARNING("Need to specify a constrainer\n");
551     }
552     else
553     {
554
555       DelayedConstrainerRemove action;
556       action.constrainerName = *constrainerName;
557       action.builder = builder;
558       OptionalChild propertiesNode = IsChild(child, "properties");
559       if(propertiesNode)
560       {
561         const TreeNode::ConstIterator endIter = (*propertiesNode).CEnd();
562         for( TreeNode::ConstIterator iter = (*propertiesNode).CBegin(); endIter != iter; ++iter )
563         {
564           const TreeNode::KeyNodePair& pKeyChild = *iter;
565           OptionalString targetActorName(IsString(IsChild(pKeyChild.second, "target")));
566           if(targetActorName)
567           {
568             action.targetActorNames.push_back(*targetActorName);
569           }
570           else
571           {
572             DALI_SCRIPT_WARNING("Need to specify target actor to remove the constraint\n");
573             continue;
574           }
575         }
576       }
577       callback = action;
578     }
579   }
580   else
581   {
582     // no named actor; presume self
583     GenericAction action;
584     action.actorName       = actor.GetName();
585     action.actionName      = *actionName;
586     GetParameters(child, action.parameters);
587     callback = action;
588   }
589
590   return callback;
591 }
592
593
594 /**
595  * Get a notification condition argument0 as 'arg0' 'value' or 'min'
596  */
597 float GetConditionArg0(const TreeNode &child)
598 {
599   OptionalFloat f = IsFloat( IsChild(child, "arg0") );
600   // allowing some human preferable alternatives
601   if(!f)
602   {
603     f = IsFloat( IsChild(child, "value") );
604   }
605   if(!f)
606   {
607     f = IsFloat( IsChild(child, "min") );
608   }
609
610   DALI_ASSERT_ALWAYS(f && "Notification condition for arg0 not specified");
611
612   return *f;
613 }
614
615 /**
616  * Get a notification condition argument1 as 'arg1' or 'max'
617  */
618 float GetConditionArg1(const TreeNode &child)
619 {
620   OptionalFloat f = IsFloat( IsChild(child, "arg1") );
621   // allowing some human preferable alternatives
622   if(!f)
623   {
624     f = IsFloat( IsChild(child, "max") );
625   }
626
627   DALI_ASSERT_ALWAYS(f && "Notification condition for arg1 not specified");
628
629   return *f;
630 }
631
632
633
634 }; // anon namespace
635
636 namespace Dali
637 {
638 namespace Toolkit
639 {
640 namespace Internal
641 {
642
643 Actor SetupSignalAction(const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder );
644 Actor SetupPropertyNotification(const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder );
645
646 /**
647  * Setup signals and actions on an actor
648  */
649 Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function<void (void)> quitAction, Dali::Toolkit::Internal::Builder* const builder )
650 {
651   DALI_ASSERT_ALWAYS(actor);
652
653   if(OptionalChild signalsChild = IsChild(child, "signals"))
654   {
655     const TreeNode& signalsNode = *signalsChild;
656     const TreeConstIter endIter = signalsNode.CEnd();
657     for( TreeConstIter iter = signalsNode.CBegin(); endIter != iter; ++iter )
658     {
659       const TreeNode::KeyNodePair& key_child = *iter;
660
661       DALI_SCRIPT_INFO("  Creating Signal for: %s\n", actor.GetName().c_str());
662
663       OptionalString name( IsString( IsChild( key_child.second, "name")) );
664       DALI_ASSERT_ALWAYS(name && "Signal must have a name");
665
666       boost::function<void (void)> callback = GetAction(root, key_child.second, actor, quitAction, builder );
667
668       actor.ConnectSignal(tracker, *name, callback);
669     }
670   }
671
672   return actor;
673 }
674
675 /**
676  * Setup Property notifications for an actor
677  */
678 Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function<void (void)> quitAction, Dali::Toolkit::Internal::Builder* const builder )
679 {
680   DALI_ASSERT_ALWAYS(actor);
681
682   if(OptionalChild notificationsChild = IsChild(child,"notifications"))
683   {
684     const TreeNode& notificationsNode = *notificationsChild;
685     const TreeNode::ConstIterator endIter = notificationsNode.CEnd();
686     for( TreeNode::ConstIterator iter = notificationsNode.CBegin(); endIter != iter; ++iter )
687     {
688       const TreeNode::KeyNodePair& key_child = *iter;
689
690       // Actor actions reference by pointer because of circular reference actor->signal
691       // So this callback should only go onto the actor maintained list.
692       boost::function<void (void)> callback = GetAction(root, key_child.second, actor, quitAction, builder );
693
694       OptionalString prop(IsString( IsChild(key_child.second, "property")) );
695       DALI_ASSERT_ALWAYS(prop && "Notification signal must specify a property");
696
697       Property::Index prop_index = actor.GetPropertyIndex(*prop);
698       DALI_ASSERT_ALWAYS(prop_index != Property::INVALID_INDEX && "Notification signal specifies an unknown property");
699
700       OptionalString cond(IsString( IsChild(key_child.second, "condition")));
701       DALI_ASSERT_ALWAYS(cond && "Notification signal must specify a condition");
702
703       if("False" == *cond)
704       {
705         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
706                                                                            LessThanCondition(1.f) );
707         notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
708       }
709       else if("LessThan" == *cond)
710       {
711         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
712                                                                            LessThanCondition(GetConditionArg0(key_child.second)) );
713         notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
714       }
715       else if("GreaterThan" == *cond)
716       {
717         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
718                                                                            GreaterThanCondition(GetConditionArg0(key_child.second)) );
719         notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
720       }
721       else if("Inside" == *cond)
722       {
723         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
724                                                                            InsideCondition(GetConditionArg0(key_child.second),
725                                                                            GetConditionArg1(key_child.second)) );
726         notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
727       }
728       else if("Outside" == *cond)
729       {
730         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
731                                                                            OutsideCondition(GetConditionArg0(key_child.second),
732                                                                            GetConditionArg1(key_child.second)) );
733         notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
734       }
735       else
736       {
737         DALI_ASSERT_ALWAYS(!"Unknown condition");
738       }
739     }
740   } // if notifications
741
742   return actor;
743
744 } // AddPropertyNotification
745
746
747 } // namespace Internal
748 } // namespace Toolkit
749 } // namespace Dali