Removed boost from builder
[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 <dali/public-api/actors/layer.h>
20 #include <dali/public-api/common/vector-wrapper.h>
21 #include <dali/public-api/object/type-info.h>
22 #include <dali/public-api/object/property-notification.h>
23
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 struct QuitAction
132 {
133   Dali::IntrusivePtr<Dali::Toolkit::Internal::Builder> builder;
134
135   void operator()(void)
136   {
137     builder->EmitQuitSignal();
138   }
139 };
140
141 // Delay an animation play; ie wait as its not on stage yet
142 struct DelayedAnimationPlay
143 {
144   OptionalChild                                         animNode;
145   Dali::IntrusivePtr<Dali::Toolkit::Internal::Builder>  builder;
146
147   void operator()(void)
148   {
149     Animation anim = Toolkit::Internal::CreateAnimation(*animNode, builder.Get() );
150     if(anim)
151     {
152       anim.Play();
153     }
154   };
155 };
156
157 // Delay a pathConstrainer apply
158 struct DelayedConstrainerApply
159 {
160   std::string     constrainerName;
161
162   std::vector<std::string> targetActorNames;
163   std::vector<std::string> sourceActorNames;
164   std::vector<std::string> targetPropertyNames;
165   std::vector<std::string> sourcePropertyNames;
166   std::vector<Vector2>  ranges;
167   std::vector<Vector2>  wrapRanges;
168
169   Dali::IntrusivePtr<Dali::Toolkit::Internal::Builder>  builder;
170
171   /*
172    * Helper function to get the parameters to apply each constraint
173    * @param[in] i i-essim element
174    * @param[out] tagetActor Target actor for the constraint
175    * @param[out] tagetPropertyIndex Target property index for the constraint
176    * @param[out] sourceActor Source actor for the constraint
177    * @param[out] sourcePropertyIndex Source property index for the constraint
178    */
179   bool GetApplyParameters( size_t i,
180                            Actor& targetActor, Property::Index& targetPropertyIndex,
181                            Actor& sourceActor, Property::Index& sourcePropertyIndex)
182   {
183
184     targetActor = Stage::GetCurrent().GetRootLayer().FindChildByName(targetActorNames[i]);
185     targetPropertyIndex = Property::INVALID_INDEX;
186     if(targetActor)
187     {
188       targetPropertyIndex = targetActor.GetPropertyIndex(targetPropertyNames[i]);
189       if( targetPropertyIndex ==  Property::INVALID_INDEX )
190       {
191         DALI_SCRIPT_WARNING("Property '%s' not founded in actor '%s'\n", targetPropertyNames[i].c_str(), targetActorNames[i].c_str() );
192         return false;
193       }
194     }
195     else
196     {
197       DALI_SCRIPT_WARNING("Actor '%s' not founded\n", targetActorNames[i].c_str() );
198       return false;
199     }
200
201
202     sourceActor = Stage::GetCurrent().GetRootLayer().FindChildByName(sourceActorNames[i]);
203     sourcePropertyIndex = Property::INVALID_INDEX;
204     if(sourceActor)
205     {
206       sourcePropertyIndex = sourceActor.GetPropertyIndex(sourcePropertyNames[i]);
207       if( sourcePropertyIndex ==  Property::INVALID_INDEX )
208       {
209         DALI_SCRIPT_WARNING("Property '%s' not founded in actor '%s'\n", sourcePropertyNames[i].c_str(), sourceActorNames[i].c_str() );
210         return false;
211       }
212     }
213     else
214     {
215       DALI_SCRIPT_WARNING("Actor '%s' not founded\n", targetActorNames[i].c_str() );
216       return false;
217     }
218     return true;
219   }
220
221   void operator()(void)
222   {
223     Actor sourceActor, targetActor;
224     Property::Index targetPropertyIndex(Property::INVALID_INDEX);
225     Property::Index sourcePropertyIndex(Property::INVALID_INDEX);
226     size_t actorCount( targetActorNames.size() );
227     if( builder.Get()->IsPathConstrainer( constrainerName ))
228     {
229       PathConstrainer constrainer = builder.Get()->GetPathConstrainer(constrainerName);
230       if( constrainer )
231       {
232         for(size_t i(0); i<actorCount; ++i )
233         {
234
235           if( GetApplyParameters( i, targetActor, targetPropertyIndex, sourceActor, sourcePropertyIndex ) )
236           {
237             constrainer.Apply( Property(targetActor,targetPropertyIndex),
238                                Property(sourceActor,sourcePropertyIndex),
239                                ranges[i],
240                                wrapRanges[i]);
241           }
242         }
243       }
244       else
245       {
246         DALI_SCRIPT_WARNING("Constrainer %s not found\n", constrainerName.c_str());
247       }
248     }
249     else if( builder.Get()->IsLinearConstrainer( constrainerName ) )
250     {
251       Dali::LinearConstrainer constrainer( builder.Get()->GetLinearConstrainer(constrainerName));
252       if( constrainer )
253       {
254         for(size_t i(0); i<actorCount; ++i )
255         {
256
257           if( GetApplyParameters( i, targetActor, targetPropertyIndex, sourceActor, sourcePropertyIndex ) )
258           {
259             constrainer.Apply( Property(targetActor,targetPropertyIndex),
260                                Property(sourceActor,sourcePropertyIndex),
261                                ranges[i],
262                                wrapRanges[i]);
263           }
264         }
265       }
266       else
267       {
268         DALI_SCRIPT_WARNING("Constrainer %s not found\n", constrainerName.c_str());
269       }
270     }
271     else
272     {
273       DALI_SCRIPT_WARNING("Constrainer %s is not of a valid type\n", constrainerName.c_str());
274     }
275   }
276 };
277
278 // Delay a pathConstrainer remove
279 struct DelayedConstrainerRemove
280 {
281   std::string     constrainerName;
282   std::vector<std::string> targetActorNames;
283   Dali::IntrusivePtr<Dali::Toolkit::Internal::Builder>  builder;
284
285   void operator()(void)
286   {
287     size_t actorCount( targetActorNames.size() );
288     if( builder.Get()->IsPathConstrainer( constrainerName ))
289     {
290       PathConstrainer constrainer = builder.Get()->GetPathConstrainer(constrainerName);
291       if( constrainer )
292       {
293         for(size_t i(0); i<actorCount; ++i )
294         {
295           Actor targetActor = Stage::GetCurrent().GetRootLayer().FindChildByName(targetActorNames[i]);
296           if(targetActor)
297           {
298             constrainer.Remove( targetActor );
299           }
300         }
301       }
302       else
303       {
304         DALI_SCRIPT_WARNING("Constrainer %s not found\n", constrainerName.c_str());
305       }
306     }
307     else if(builder.Get()->IsLinearConstrainer( constrainerName ))
308     {
309       LinearConstrainer constrainer = builder.Get()->GetLinearConstrainer(constrainerName);
310       if( constrainer )
311       {
312         for(size_t i(0); i<actorCount; ++i )
313         {
314           Actor targetActor = Stage::GetCurrent().GetRootLayer().FindChildByName(targetActorNames[i]);
315           if(targetActor)
316           {
317             constrainer.Remove( targetActor );
318           }
319         }
320       }
321       else
322       {
323         DALI_SCRIPT_WARNING("Constrainer %s not found\n", constrainerName.c_str());
324       }
325     }
326     else
327     {
328       DALI_SCRIPT_WARNING("Constrainer %s is not of a valid type\n", constrainerName.c_str());
329     }
330   }
331 };
332
333 /*
334  * Gets Property::Value from child
335  */
336 Property::Value GetPropertyValue(const TreeNode &child)
337 {
338   size_t nChildren = child.Size();
339
340   Property::Value ret;
341
342   if(0 == nChildren)
343   {
344     // cast away unused return for static analyzers
345     static_cast<void>( Dali::Toolkit::Internal::SetPropertyFromNode( child, ret ) );
346   }
347   else if(1 == nChildren)
348   {
349     // {"property": {"quaternion":[1,2,3,4]} }
350     // {"property": {"angle":22, "axis": [1,2,3]} }
351
352     OptionalChild quaternion  = IsChild(&child, "quaternion");
353     OptionalChild axis        = IsChild(&child, "axis");
354     OptionalChild angle       = IsChild(&child, "angle");
355
356     if(quaternion)
357     {
358       ret = Property::Value(Quaternion(GetVector4(*quaternion)));
359     }
360     else if(axis && angle)
361     {
362       ret = Property::Value(AngleAxis(Degree(GetFloat(*angle)), GetVector3(*axis)));
363     }
364   }
365   else if(2 == nChildren)
366   {
367     // {"property": [1,2]}
368     ret = Property::Value(GetVector2(child));
369   }
370   else if(3 == nChildren)
371   {
372     // {"property": [1,2,3]}
373     ret = Property::Value(GetVector3(child));
374   }
375   else if(4 == nChildren)
376   {
377     // {"property": [1,2,3,4]}
378     ret = Property::Value(GetVector4(child));
379   }
380
381   return ret;
382 }
383
384
385 /*
386  * Gets Parmeter list from child
387  * params is be cleared before insertion
388  */
389 void GetParameters(const TreeNode& child, Property::Map& params)
390 {
391   if( OptionalChild c = IsChild(child, "parameters") )
392   {
393     const TreeNode& node = *c;
394
395     params.Clear();
396
397     for(TreeNode::ConstIterator iter(node.CBegin()); iter != node.CEnd(); ++iter)
398     {
399       params[ (*iter).first ] = GetPropertyValue( (*iter).second );
400     }
401   }
402 }
403
404 // Shim for the property notifcation signal
405 template <typename T>
406 struct PropertyNotifcationSignalShim
407 {
408   T mFunctor;
409
410   PropertyNotifcationSignalShim(T& functor) : mFunctor(functor) {}
411
412   void operator()(PropertyNotification& /* source */)
413   {
414     mFunctor();
415   }
416 };
417
418 // Specializations for the different signal connection calls between actor & PropertyNotification
419 template <typename T>
420 struct SignalConnector {};
421
422 // Actor specialization
423 template <>
424 struct SignalConnector<Actor> {
425   Actor& mActor;
426   ConnectionTracker* mTracker;
427   const std::string& mName;
428
429   SignalConnector<Actor>(ConnectionTracker* tracker, Actor& actor, const std::string& name)
430   : mActor(actor), mTracker(tracker), mName(name) {}
431
432   template <typename T>
433   void Connect(T& functor)
434   {
435     mActor.ConnectSignal( mTracker, mName, functor);
436   }
437 };
438
439 // PropertyNotification specialization
440 template <>
441 struct SignalConnector<PropertyNotification>
442 {
443   PropertyNotification& mNotification;
444   ConnectionTracker* mTracker;
445
446   SignalConnector<PropertyNotification>(ConnectionTracker* tracker, PropertyNotification &notification)
447   : mNotification(notification), mTracker(tracker) {}
448
449   template <typename T>
450   void Connect(T& functor)
451   {
452     mNotification.NotifySignal().Connect( mTracker, PropertyNotifcationSignalShim<T>(functor) );
453   }
454 };
455
456 /**
457  * Set an action functor on a signal
458  */
459 template <typename T>
460 void SetActionOnSignal(const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder, SignalConnector<T>& connector)
461 {
462   OptionalString childActorName(IsString( IsChild(&child, "child-actor")) );
463   OptionalString actorName(IsString( IsChild(&child, "actor")) );
464   OptionalString propertyName(IsString( IsChild(&child, "property")) );
465   OptionalChild  valueChild( IsChild(&child, "value") );
466
467   OptionalString actionName = IsString( IsChild(&child, "action") );
468   DALI_ASSERT_ALWAYS(actionName && "Signal must have an action");
469
470   if(childActorName)
471   {
472     ChildActorAction action;
473     action.actorName       = *actorName;
474     action.childName       = *childActorName;
475     action.actionName      = *actionName;
476     GetParameters(child, action.parameters);
477     connector.Connect( action );
478   }
479   else if(actorName)
480   {
481     if(propertyName && valueChild && ("set" == *actionName) )
482     {
483       PropertySetAction action;
484       action.actorName       = *actorName;
485       action.propertyName    = *propertyName;
486       // actor may not exist yet so we can't check the property type
487       if( !Dali::Toolkit::Internal::SetPropertyFromNode( *valueChild, action.value ) )
488       {
489         DALI_SCRIPT_WARNING("Cannot set property for set property action\n");
490       }
491       connector.Connect( action );
492     }
493     else
494     {
495       GenericAction action;
496       action.actorName       = *actorName;
497       action.actionName      = *actionName;
498       GetParameters(child, action.parameters);
499       connector.Connect( action );
500     }
501   }
502   else if("quit" == *actionName)
503   {
504     QuitAction action;
505     action.builder = builder;
506     connector.Connect( action );
507   }
508   else if("play" == *actionName)
509   {
510     OptionalChild animations     = IsChild( root, "animations" );
511     OptionalString animationName = IsString( IsChild(child, "animation") );
512     if( animations && animationName )
513     {
514       if( OptionalChild animNode = IsChild(*animations, *animationName) )
515       {
516         DelayedAnimationPlay action;
517         action.animNode = animNode;
518         action.builder = builder;
519         // @todo; put constants into the map
520         connector.Connect( action );
521       }
522       else
523       {
524         DALI_SCRIPT_WARNING("Cannot find animation '%s'\n", (*animationName).c_str());
525       }
526     }
527     else
528     {
529       DALI_SCRIPT_WARNING("Cannot find animations section\n");
530     }
531   }
532   else if("applyConstraint" == *actionName )
533   {
534     OptionalString constrainerName = IsString( IsChild(child, "constrainer") );
535     if( !constrainerName )
536     {
537       DALI_SCRIPT_WARNING("Need to specify a constrainer\n");
538     }
539     else
540     {
541       DelayedConstrainerApply action;
542       action.constrainerName = *constrainerName;
543       action.builder = builder;
544       OptionalChild propertiesNode = IsChild(child, "properties");
545       if(propertiesNode)
546       {
547         const TreeNode::ConstIterator endIter = (*propertiesNode).CEnd();
548         for( TreeNode::ConstIterator iter = (*propertiesNode).CBegin(); endIter != iter; ++iter )
549         {
550           const TreeNode::KeyNodePair& pKeyChild = *iter;
551           OptionalString sourceActorName(IsString(IsChild(pKeyChild.second, "source")));
552           if(!sourceActorName)
553           {
554             DALI_SCRIPT_WARNING("Need to specify source actor to apply the constraint\n");
555             continue;
556           }
557           OptionalString sourcePropertyName( IsString( IsChild(pKeyChild.second, "sourceProperty" ) ) );
558           if(!sourcePropertyName)
559           {
560             DALI_SCRIPT_WARNING("Need to specify source property to apply the constraint\n");
561             continue;
562           }
563
564           OptionalString targetActorName(IsString(IsChild(pKeyChild.second, "target")));
565           if(!targetActorName)
566           {
567             DALI_SCRIPT_WARNING("Need to specify target actor to apply the constraint\n");
568             continue;
569           }
570
571           OptionalString targetPropertyName( IsString( IsChild(pKeyChild.second, "targetProperty" ) ) );
572           if(!targetPropertyName)
573           {
574             DALI_SCRIPT_WARNING("Need to specify target property name to apply the constraint\n");
575             continue;
576           }
577
578           OptionalVector2 range(IsVector2(IsChild(pKeyChild.second, "range")));
579           if(!range)
580           {
581             DALI_SCRIPT_WARNING("Constrainer range not specified\n");
582             continue;
583           }
584
585           Vector2 wrap(-std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
586           OptionalVector2 wrapRange(IsVector2(IsChild(pKeyChild.second, "wrap")));
587           if(wrapRange)
588           {
589             wrap = *wrapRange;
590           }
591
592           action.sourceActorNames.push_back(*sourceActorName);
593           action.sourcePropertyNames.push_back(*sourcePropertyName);
594           action.targetActorNames.push_back(*targetActorName);
595           action.targetPropertyNames.push_back(*targetPropertyName);
596           action.ranges.push_back(*range);
597           action.wrapRanges.push_back(wrap);
598         }
599         connector.Connect(action);
600       }
601     }
602   }
603   else if("removeConstraints" == *actionName )
604   {
605     OptionalString constrainerName = IsString( IsChild(child, "constrainer") );
606     if( !constrainerName )
607     {
608       DALI_SCRIPT_WARNING("Need to specify a constrainer\n");
609     }
610     else
611     {
612
613       DelayedConstrainerRemove action;
614       action.constrainerName = *constrainerName;
615       action.builder = builder;
616       OptionalChild propertiesNode = IsChild(child, "properties");
617       if(propertiesNode)
618       {
619         const TreeNode::ConstIterator endIter = (*propertiesNode).CEnd();
620         for( TreeNode::ConstIterator iter = (*propertiesNode).CBegin(); endIter != iter; ++iter )
621         {
622           const TreeNode::KeyNodePair& pKeyChild = *iter;
623           OptionalString targetActorName(IsString(IsChild(pKeyChild.second, "target")));
624           if(targetActorName)
625           {
626             action.targetActorNames.push_back(*targetActorName);
627           }
628           else
629           {
630             DALI_SCRIPT_WARNING("Need to specify target actor to remove the constraint\n");
631             continue;
632           }
633         }
634       }
635       connector.Connect(action);
636     }
637   }
638   else
639   {
640     // no named actor; presume self
641     GenericAction action;
642     action.actorName       = actor.GetName();
643     action.actionName      = *actionName;
644     GetParameters(child, action.parameters);
645     connector.Connect( action );
646   }
647 }
648
649
650 /**
651  * Get a notification condition argument0 as 'arg0' 'value' or 'min'
652  */
653 float GetConditionArg0(const TreeNode &child)
654 {
655   OptionalFloat f = IsFloat( IsChild(child, "arg0") );
656   // allowing some human preferable alternatives
657   if(!f)
658   {
659     f = IsFloat( IsChild(child, "value") );
660   }
661   if(!f)
662   {
663     f = IsFloat( IsChild(child, "min") );
664   }
665
666   DALI_ASSERT_ALWAYS(f && "Notification condition for arg0 not specified");
667
668   return *f;
669 }
670
671 /**
672  * Get a notification condition argument1 as 'arg1' or 'max'
673  */
674 float GetConditionArg1(const TreeNode &child)
675 {
676   OptionalFloat f = IsFloat( IsChild(child, "arg1") );
677   // allowing some human preferable alternatives
678   if(!f)
679   {
680     f = IsFloat( IsChild(child, "max") );
681   }
682
683   DALI_ASSERT_ALWAYS(f && "Notification condition for arg1 not specified");
684
685   return *f;
686 }
687
688
689
690 }; // anon namespace
691
692 namespace Dali
693 {
694 namespace Toolkit
695 {
696 namespace Internal
697 {
698
699 Actor SetupSignalAction(const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder );
700 Actor SetupPropertyNotification(const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder );
701
702 /**
703  * Setup signals and actions on an actor
704  */
705 Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder )
706 {
707   DALI_ASSERT_ALWAYS(actor);
708
709   if(OptionalChild signalsChild = IsChild(child, "signals"))
710   {
711     const TreeNode& signalsNode = *signalsChild;
712     const TreeConstIter endIter = signalsNode.CEnd();
713     for( TreeConstIter iter = signalsNode.CBegin(); endIter != iter; ++iter )
714     {
715       const TreeNode::KeyNodePair& key_child = *iter;
716
717       DALI_SCRIPT_INFO("  Creating Signal for: %s\n", actor.GetName().c_str());
718
719       OptionalString name( IsString( IsChild( key_child.second, "name")) );
720       DALI_ASSERT_ALWAYS(name && "Signal must have a name");
721
722       SignalConnector<Actor> connector(tracker, actor, *name);
723       SetActionOnSignal(root, key_child.second, actor, builder, connector);
724     }
725   }
726
727   return actor;
728 }
729
730 /**
731  * Setup Property notifications for an actor
732  */
733 Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder )
734 {
735   DALI_ASSERT_ALWAYS(actor);
736
737   if(OptionalChild notificationsChild = IsChild(child,"notifications"))
738   {
739     const TreeNode& notificationsNode = *notificationsChild;
740     const TreeNode::ConstIterator endIter = notificationsNode.CEnd();
741     for( TreeNode::ConstIterator iter = notificationsNode.CBegin(); endIter != iter; ++iter )
742     {
743       const TreeNode::KeyNodePair& key_child = *iter;
744
745       OptionalString prop(IsString( IsChild(key_child.second, "property")) );
746       DALI_ASSERT_ALWAYS(prop && "Notification signal must specify a property");
747
748       Property::Index prop_index = actor.GetPropertyIndex(*prop);
749       DALI_ASSERT_ALWAYS(prop_index != Property::INVALID_INDEX && "Notification signal specifies an unknown property");
750
751       OptionalString cond(IsString( IsChild(key_child.second, "condition")));
752       DALI_ASSERT_ALWAYS(cond && "Notification signal must specify a condition");
753
754       if("False" == *cond)
755       {
756         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
757                                                                            LessThanCondition(1.f) );
758         SignalConnector<PropertyNotification> connector(tracker, notification);
759         SetActionOnSignal(root, key_child.second, actor, builder, connector);
760       }
761       else if("LessThan" == *cond)
762       {
763         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
764                                                                            LessThanCondition(GetConditionArg0(key_child.second)) );
765         SignalConnector<PropertyNotification> connector(tracker, notification);
766         SetActionOnSignal(root, key_child.second, actor, builder, connector);
767       }
768       else if("GreaterThan" == *cond)
769       {
770         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
771                                                                            GreaterThanCondition(GetConditionArg0(key_child.second)) );
772         SignalConnector<PropertyNotification> connector(tracker, notification);
773         SetActionOnSignal(root, key_child.second, actor, builder, connector);
774       }
775       else if("Inside" == *cond)
776       {
777         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
778                                                                            InsideCondition(GetConditionArg0(key_child.second),
779                                                                            GetConditionArg1(key_child.second)) );
780         SignalConnector<PropertyNotification> connector(tracker, notification);
781         SetActionOnSignal(root, key_child.second, actor, builder, connector);
782       }
783       else if("Outside" == *cond)
784       {
785         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
786                                                                            OutsideCondition(GetConditionArg0(key_child.second),
787                                                                            GetConditionArg1(key_child.second)) );
788         SignalConnector<PropertyNotification> connector(tracker, notification);
789         SetActionOnSignal(root, key_child.second, actor, builder, connector);
790       }
791       else
792       {
793         DALI_ASSERT_ALWAYS(!"Unknown condition");
794       }
795     }
796   } // if notifications
797
798   return actor;
799
800 } // AddPropertyNotification
801
802
803 } // namespace Internal
804 } // namespace Toolkit
805 } // namespace Dali