Changed all property & signal names to lowerCamelCase
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / builder / builder-signals.cpp
index edf961f..ed22ef3 100644 (file)
@@ -1,21 +1,28 @@
-//
-// Copyright (c) 2014 Samsung Electronics Co., Ltd.
-//
-// Licensed under the Flora License, Version 1.0 (the License);
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://floralicense.org/license/
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an AS IS BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
 
 // EXTERNAL INCLUDES
+#include <dali/public-api/actors/layer.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/object/type-info.h>
+#include <dali/public-api/object/property-notification.h>
+
 #include <dali/integration-api/debug.h>
+#include <limits>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/builder/builder-impl.h>
@@ -27,7 +34,7 @@ namespace Toolkit
 {
 namespace Internal
 {
-extern Animation CreateAnimation( const TreeNode& child );
+extern Animation CreateAnimation( const TreeNode& child, Dali::Toolkit::Internal::Builder* const builder  );
 extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value );
 }
 }
@@ -41,24 +48,13 @@ using namespace Dali;
 // Signal Actions
 //
 
-// Action quit; connected to signals
-// TODO: MOVE TO BUILDER TEMPLATE
-struct ActionQuit
-{
-  ActionQuit(void) {};
-
-  void operator()(void) {
-    // Dali::Application::Get().Quit();
-  };
-};
-
-// Action on child actor. The child is found by alias so can be 'previous' etc.
+// Action on child actor. The child is found by name
 struct ChildActorAction
 {
   std::string actorName;
   std::string actionName;
-  std::string childAlias;
-  std::vector<Property::Value> parameters;
+  std::string childName;
+  Property::Map parameters;
 
   void operator()(void)
   {
@@ -66,7 +62,7 @@ struct ChildActorAction
 
     if(actor)
     {
-      Actor child_actor = actor.FindChildByAlias(childAlias);
+      Actor child_actor = actor.FindChildByName(childName);
 
       if(child_actor)
       {
@@ -74,7 +70,7 @@ struct ChildActorAction
       }
       else
       {
-        DALI_SCRIPT_WARNING("Could not find child by alias '%s'\n", childAlias.c_str());
+        DALI_SCRIPT_WARNING("Could not find child by name '%s'\n", childName.c_str());
       }
     }
   };
@@ -119,7 +115,7 @@ struct GenericAction
 {
   std::string actorName;
   std::string actionName;
-  std::vector<Property::Value> parameters;
+  Property::Map parameters;
 
   void operator()(void)
   {
@@ -132,14 +128,25 @@ struct GenericAction
   };
 };
 
+struct QuitAction
+{
+  Dali::IntrusivePtr<Dali::Toolkit::Internal::Builder> builder;
+
+  void operator()(void)
+  {
+    builder->EmitQuitSignal();
+  }
+};
+
 // Delay an animation play; ie wait as its not on stage yet
 struct DelayedAnimationPlay
 {
-  Toolkit::JsonParser memento;
+  OptionalChild                                         animNode;
+  Dali::IntrusivePtr<Dali::Toolkit::Internal::Builder>  builder;
 
   void operator()(void)
   {
-    Animation anim = Toolkit::Internal::CreateAnimation(*memento.GetRoot());
+    Animation anim = Toolkit::Internal::CreateAnimation(*animNode, builder.Get() );
     if(anim)
     {
       anim.Play();
@@ -147,6 +154,182 @@ struct DelayedAnimationPlay
   };
 };
 
+// Delay a pathConstrainer apply
+struct DelayedConstrainerApply
+{
+  std::string     constrainerName;
+
+  std::vector<std::string> targetActorNames;
+  std::vector<std::string> sourceActorNames;
+  std::vector<std::string> targetPropertyNames;
+  std::vector<std::string> sourcePropertyNames;
+  std::vector<Vector2>  ranges;
+  std::vector<Vector2>  wrapRanges;
+
+  Dali::IntrusivePtr<Dali::Toolkit::Internal::Builder>  builder;
+
+  /*
+   * Helper function to get the parameters to apply each constraint
+   * @param[in] i i-essim element
+   * @param[out] tagetActor Target actor for the constraint
+   * @param[out] tagetPropertyIndex Target property index for the constraint
+   * @param[out] sourceActor Source actor for the constraint
+   * @param[out] sourcePropertyIndex Source property index for the constraint
+   */
+  bool GetApplyParameters( size_t i,
+                           Actor& targetActor, Property::Index& targetPropertyIndex,
+                           Actor& sourceActor, Property::Index& sourcePropertyIndex)
+  {
+
+    targetActor = Stage::GetCurrent().GetRootLayer().FindChildByName(targetActorNames[i]);
+    targetPropertyIndex = Property::INVALID_INDEX;
+    if(targetActor)
+    {
+      targetPropertyIndex = targetActor.GetPropertyIndex(targetPropertyNames[i]);
+      if( targetPropertyIndex ==  Property::INVALID_INDEX )
+      {
+        DALI_SCRIPT_WARNING("Property '%s' not founded in actor '%s'\n", targetPropertyNames[i].c_str(), targetActorNames[i].c_str() );
+        return false;
+      }
+    }
+    else
+    {
+      DALI_SCRIPT_WARNING("Actor '%s' not founded\n", targetActorNames[i].c_str() );
+      return false;
+    }
+
+
+    sourceActor = Stage::GetCurrent().GetRootLayer().FindChildByName(sourceActorNames[i]);
+    sourcePropertyIndex = Property::INVALID_INDEX;
+    if(sourceActor)
+    {
+      sourcePropertyIndex = sourceActor.GetPropertyIndex(sourcePropertyNames[i]);
+      if( sourcePropertyIndex ==  Property::INVALID_INDEX )
+      {
+        DALI_SCRIPT_WARNING("Property '%s' not founded in actor '%s'\n", sourcePropertyNames[i].c_str(), sourceActorNames[i].c_str() );
+        return false;
+      }
+    }
+    else
+    {
+      DALI_SCRIPT_WARNING("Actor '%s' not founded\n", targetActorNames[i].c_str() );
+      return false;
+    }
+    return true;
+  }
+
+  void operator()(void)
+  {
+    Actor sourceActor, targetActor;
+    Property::Index targetPropertyIndex(Property::INVALID_INDEX);
+    Property::Index sourcePropertyIndex(Property::INVALID_INDEX);
+    size_t actorCount( targetActorNames.size() );
+    if( builder.Get()->IsPathConstrainer( constrainerName ))
+    {
+      PathConstrainer constrainer = builder.Get()->GetPathConstrainer(constrainerName);
+      if( constrainer )
+      {
+        for(size_t i(0); i<actorCount; ++i )
+        {
+
+          if( GetApplyParameters( i, targetActor, targetPropertyIndex, sourceActor, sourcePropertyIndex ) )
+          {
+            constrainer.Apply( Property(targetActor,targetPropertyIndex),
+                               Property(sourceActor,sourcePropertyIndex),
+                               ranges[i],
+                               wrapRanges[i]);
+          }
+        }
+      }
+      else
+      {
+        DALI_SCRIPT_WARNING("Constrainer %s not found\n", constrainerName.c_str());
+      }
+    }
+    else if( builder.Get()->IsLinearConstrainer( constrainerName ) )
+    {
+      Dali::LinearConstrainer constrainer( builder.Get()->GetLinearConstrainer(constrainerName));
+      if( constrainer )
+      {
+        for(size_t i(0); i<actorCount; ++i )
+        {
+
+          if( GetApplyParameters( i, targetActor, targetPropertyIndex, sourceActor, sourcePropertyIndex ) )
+          {
+            constrainer.Apply( Property(targetActor,targetPropertyIndex),
+                               Property(sourceActor,sourcePropertyIndex),
+                               ranges[i],
+                               wrapRanges[i]);
+          }
+        }
+      }
+      else
+      {
+        DALI_SCRIPT_WARNING("Constrainer %s not found\n", constrainerName.c_str());
+      }
+    }
+    else
+    {
+      DALI_SCRIPT_WARNING("Constrainer %s is not of a valid type\n", constrainerName.c_str());
+    }
+  }
+};
+
+// Delay a pathConstrainer remove
+struct DelayedConstrainerRemove
+{
+  std::string     constrainerName;
+  std::vector<std::string> targetActorNames;
+  Dali::IntrusivePtr<Dali::Toolkit::Internal::Builder>  builder;
+
+  void operator()(void)
+  {
+    size_t actorCount( targetActorNames.size() );
+    if( builder.Get()->IsPathConstrainer( constrainerName ))
+    {
+      PathConstrainer constrainer = builder.Get()->GetPathConstrainer(constrainerName);
+      if( constrainer )
+      {
+        for(size_t i(0); i<actorCount; ++i )
+        {
+          Actor targetActor = Stage::GetCurrent().GetRootLayer().FindChildByName(targetActorNames[i]);
+          if(targetActor)
+          {
+            constrainer.Remove( targetActor );
+          }
+        }
+      }
+      else
+      {
+        DALI_SCRIPT_WARNING("Constrainer %s not found\n", constrainerName.c_str());
+      }
+    }
+    else if(builder.Get()->IsLinearConstrainer( constrainerName ))
+    {
+      LinearConstrainer constrainer = builder.Get()->GetLinearConstrainer(constrainerName);
+      if( constrainer )
+      {
+        for(size_t i(0); i<actorCount; ++i )
+        {
+          Actor targetActor = Stage::GetCurrent().GetRootLayer().FindChildByName(targetActorNames[i]);
+          if(targetActor)
+          {
+            constrainer.Remove( targetActor );
+          }
+        }
+      }
+      else
+      {
+        DALI_SCRIPT_WARNING("Constrainer %s not found\n", constrainerName.c_str());
+      }
+    }
+    else
+    {
+      DALI_SCRIPT_WARNING("Constrainer %s is not of a valid type\n", constrainerName.c_str());
+    }
+  }
+};
+
 /*
  * Gets Property::Value from child
  */
@@ -203,37 +386,80 @@ Property::Value GetPropertyValue(const TreeNode &child)
  * Gets Parmeter list from child
  * params is be cleared before insertion
  */
-void GetParameters(const TreeNode &child, std::vector<Property::Value> &params)
+void GetParameters(const TreeNode& child, Property::Map& params)
 {
   if( OptionalChild c = IsChild(child, "parameters") )
   {
     const TreeNode& node = *c;
 
-    if(0 == node.Size())
-    {
-      GetPropertyValue(node);
-    }
-    else
-    {
-      params.clear();
-      params.reserve(node.Size());
+    params.Clear();
 
-      for(TreeNode::ConstIterator iter(node.CBegin()); iter != node.CEnd(); ++iter)
-      {
-        params.push_back( GetPropertyValue( (*iter).second ) );
-      }
+    for(TreeNode::ConstIterator iter(node.CBegin()); iter != node.CEnd(); ++iter)
+    {
+      params[ (*iter).first ] = GetPropertyValue( (*iter).second );
     }
   }
 }
 
-void DoNothing(void) {};
+// Shim for the property notifcation signal
+template <typename T>
+struct PropertyNotifcationSignalShim
+{
+  T mFunctor;
+
+  PropertyNotifcationSignalShim(T& functor) : mFunctor(functor) {}
+
+  void operator()(PropertyNotification& /* source */)
+  {
+    mFunctor();
+  }
+};
+
+// Specializations for the different signal connection calls between actor & PropertyNotification
+template <typename T>
+struct SignalConnector {};
+
+// Actor specialization
+template <>
+struct SignalConnector<Actor> {
+  Actor& mActor;
+  ConnectionTracker* mTracker;
+  const std::string& mName;
+
+  SignalConnector<Actor>(ConnectionTracker* tracker, Actor& actor, const std::string& name)
+  : mActor(actor), mTracker(tracker), mName(name) {}
+
+  template <typename T>
+  void Connect(T& functor)
+  {
+    mActor.ConnectSignal( mTracker, mName, functor);
+  }
+};
+
+// PropertyNotification specialization
+template <>
+struct SignalConnector<PropertyNotification>
+{
+  PropertyNotification& mNotification;
+  ConnectionTracker* mTracker;
+
+  SignalConnector<PropertyNotification>(ConnectionTracker* tracker, PropertyNotification &notification)
+  : mNotification(notification), mTracker(tracker) {}
+
+  template <typename T>
+  void Connect(T& functor)
+  {
+    mNotification.NotifySignal().Connect( mTracker, PropertyNotifcationSignalShim<T>(functor) );
+  }
+};
 
 /**
- * Get an action as boost function callback
+ * Set an action functor on a signal
  */
-boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &child, Actor actor)
+template <typename T>
+void SetActionOnSignal(const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder, SignalConnector<T>& connector)
 {
-  OptionalString childActorName(IsString( IsChild(&child, "child-actor")) );
+  OptionalString childActorName(IsString( IsChild(&child, "childActor")) );
   OptionalString actorName(IsString( IsChild(&child, "actor")) );
   OptionalString propertyName(IsString( IsChild(&child, "property")) );
   OptionalChild  valueChild( IsChild(&child, "value") );
@@ -241,16 +467,14 @@ boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &chi
   OptionalString actionName = IsString( IsChild(&child, "action") );
   DALI_ASSERT_ALWAYS(actionName && "Signal must have an action");
 
-  boost::function<void(void)> callback = DoNothing;
-
   if(childActorName)
   {
     ChildActorAction action;
     action.actorName       = *actorName;
-    action.childAlias      = *childActorName;
+    action.childName       = *childActorName;
     action.actionName      = *actionName;
     GetParameters(child, action.parameters);
-    callback = action;
+    connector.Connect( action );
   }
   else if(actorName)
   {
@@ -264,7 +488,7 @@ boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &chi
       {
         DALI_SCRIPT_WARNING("Cannot set property for set property action\n");
       }
-      callback = action;
+      connector.Connect( action );
     }
     else
     {
@@ -272,12 +496,14 @@ boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &chi
       action.actorName       = *actorName;
       action.actionName      = *actionName;
       GetParameters(child, action.parameters);
-      callback = action;
+      connector.Connect( action );
     }
   }
   else if("quit" == *actionName)
   {
-    callback = ActionQuit();
+    QuitAction action;
+    action.builder = builder;
+    connector.Connect( action );
   }
   else if("play" == *actionName)
   {
@@ -288,8 +514,10 @@ boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &chi
       if( OptionalChild animNode = IsChild(*animations, *animationName) )
       {
         DelayedAnimationPlay action;
-        action.memento = Toolkit::JsonParser::New(*animNode);
-        callback = action;
+        action.animNode = animNode;
+        action.builder = builder;
+        // @todo; put constants into the map
+        connector.Connect( action );
       }
       else
       {
@@ -301,6 +529,112 @@ boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &chi
       DALI_SCRIPT_WARNING("Cannot find animations section\n");
     }
   }
+  else if("applyConstraint" == *actionName )
+  {
+    OptionalString constrainerName = IsString( IsChild(child, "constrainer") );
+    if( !constrainerName )
+    {
+      DALI_SCRIPT_WARNING("Need to specify a constrainer\n");
+    }
+    else
+    {
+      DelayedConstrainerApply action;
+      action.constrainerName = *constrainerName;
+      action.builder = builder;
+      OptionalChild propertiesNode = IsChild(child, "properties");
+      if(propertiesNode)
+      {
+        const TreeNode::ConstIterator endIter = (*propertiesNode).CEnd();
+        for( TreeNode::ConstIterator iter = (*propertiesNode).CBegin(); endIter != iter; ++iter )
+        {
+          const TreeNode::KeyNodePair& pKeyChild = *iter;
+          OptionalString sourceActorName(IsString(IsChild(pKeyChild.second, "source")));
+          if(!sourceActorName)
+          {
+            DALI_SCRIPT_WARNING("Need to specify source actor to apply the constraint\n");
+            continue;
+          }
+          OptionalString sourcePropertyName( IsString( IsChild(pKeyChild.second, "sourceProperty" ) ) );
+          if(!sourcePropertyName)
+          {
+            DALI_SCRIPT_WARNING("Need to specify source property to apply the constraint\n");
+            continue;
+          }
+
+          OptionalString targetActorName(IsString(IsChild(pKeyChild.second, "target")));
+          if(!targetActorName)
+          {
+            DALI_SCRIPT_WARNING("Need to specify target actor to apply the constraint\n");
+            continue;
+          }
+
+          OptionalString targetPropertyName( IsString( IsChild(pKeyChild.second, "targetProperty" ) ) );
+          if(!targetPropertyName)
+          {
+            DALI_SCRIPT_WARNING("Need to specify target property name to apply the constraint\n");
+            continue;
+          }
+
+          OptionalVector2 range(IsVector2(IsChild(pKeyChild.second, "range")));
+          if(!range)
+          {
+            DALI_SCRIPT_WARNING("Constrainer range not specified\n");
+            continue;
+          }
+
+          Vector2 wrap(-std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
+          OptionalVector2 wrapRange(IsVector2(IsChild(pKeyChild.second, "wrap")));
+          if(wrapRange)
+          {
+            wrap = *wrapRange;
+          }
+
+          action.sourceActorNames.push_back(*sourceActorName);
+          action.sourcePropertyNames.push_back(*sourcePropertyName);
+          action.targetActorNames.push_back(*targetActorName);
+          action.targetPropertyNames.push_back(*targetPropertyName);
+          action.ranges.push_back(*range);
+          action.wrapRanges.push_back(wrap);
+        }
+        connector.Connect(action);
+      }
+    }
+  }
+  else if("removeConstraints" == *actionName )
+  {
+    OptionalString constrainerName = IsString( IsChild(child, "constrainer") );
+    if( !constrainerName )
+    {
+      DALI_SCRIPT_WARNING("Need to specify a constrainer\n");
+    }
+    else
+    {
+
+      DelayedConstrainerRemove action;
+      action.constrainerName = *constrainerName;
+      action.builder = builder;
+      OptionalChild propertiesNode = IsChild(child, "properties");
+      if(propertiesNode)
+      {
+        const TreeNode::ConstIterator endIter = (*propertiesNode).CEnd();
+        for( TreeNode::ConstIterator iter = (*propertiesNode).CBegin(); endIter != iter; ++iter )
+        {
+          const TreeNode::KeyNodePair& pKeyChild = *iter;
+          OptionalString targetActorName(IsString(IsChild(pKeyChild.second, "target")));
+          if(targetActorName)
+          {
+            action.targetActorNames.push_back(*targetActorName);
+          }
+          else
+          {
+            DALI_SCRIPT_WARNING("Need to specify target actor to remove the constraint\n");
+            continue;
+          }
+        }
+      }
+      connector.Connect(action);
+    }
+  }
   else
   {
     // no named actor; presume self
@@ -308,10 +642,8 @@ boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &chi
     action.actorName       = actor.GetName();
     action.actionName      = *actionName;
     GetParameters(child, action.parameters);
-    callback = action;
+    connector.Connect( action );
   }
-
-  return callback;
 }
 
 
@@ -330,15 +662,10 @@ float GetConditionArg0(const TreeNode &child)
   {
     f = IsFloat( IsChild(child, "min") );
   }
+
   DALI_ASSERT_ALWAYS(f && "Notification condition for arg0 not specified");
-  if(f)
-  {
-    return *f;
-  }
-  else
-  {
-    return 0.f;
-  }
+
+  return *f;
 }
 
 /**
@@ -352,15 +679,10 @@ float GetConditionArg1(const TreeNode &child)
   {
     f = IsFloat( IsChild(child, "max") );
   }
+
   DALI_ASSERT_ALWAYS(f && "Notification condition for arg1 not specified");
-  if(f)
-  {
-    return *f;
-  }
-  else
-  {
-    return 0.f;
-  }
+
+  return *f;
 }
 
 
@@ -374,13 +696,13 @@ namespace Toolkit
 namespace Internal
 {
 
-Actor SetupSignalAction(const TreeNode &child, Actor actor);
-Actor SetupPropertyNotification(const TreeNode &child, Actor actor);
+Actor SetupSignalAction(const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder );
+Actor SetupPropertyNotification(const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder );
 
 /**
  * Setup signals and actions on an actor
  */
-Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor)
+Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder )
 {
   DALI_ASSERT_ALWAYS(actor);
 
@@ -397,9 +719,8 @@ Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const
       OptionalString name( IsString( IsChild( key_child.second, "name")) );
       DALI_ASSERT_ALWAYS(name && "Signal must have a name");
 
-      boost::function<void (void)> callback = GetAction(root, key_child.second, actor);
-
-      actor.ConnectSignal(tracker, *name, callback);
+      SignalConnector<Actor> connector(tracker, actor, *name);
+      SetActionOnSignal(root, key_child.second, actor, builder, connector);
     }
   }
 
@@ -409,7 +730,7 @@ Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const
 /**
  * Setup Property notifications for an actor
  */
-Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor)
+Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder )
 {
   DALI_ASSERT_ALWAYS(actor);
 
@@ -421,10 +742,6 @@ Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root
     {
       const TreeNode::KeyNodePair& key_child = *iter;
 
-      // Actor actions reference by pointer because of circular reference actor->signal
-      // So this callback should only go onto the actor maintained list.
-      boost::function<void (void)> callback = GetAction(root, key_child.second, actor);
-
       OptionalString prop(IsString( IsChild(key_child.second, "property")) );
       DALI_ASSERT_ALWAYS(prop && "Notification signal must specify a property");
 
@@ -438,33 +755,38 @@ Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root
       {
         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
                                                                            LessThanCondition(1.f) );
-        notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
+        SignalConnector<PropertyNotification> connector(tracker, notification);
+        SetActionOnSignal(root, key_child.second, actor, builder, connector);
       }
       else if("LessThan" == *cond)
       {
         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
                                                                            LessThanCondition(GetConditionArg0(key_child.second)) );
-        notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
+        SignalConnector<PropertyNotification> connector(tracker, notification);
+        SetActionOnSignal(root, key_child.second, actor, builder, connector);
       }
       else if("GreaterThan" == *cond)
       {
         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
                                                                            GreaterThanCondition(GetConditionArg0(key_child.second)) );
-        notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
+        SignalConnector<PropertyNotification> connector(tracker, notification);
+        SetActionOnSignal(root, key_child.second, actor, builder, connector);
       }
       else if("Inside" == *cond)
       {
         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
                                                                            InsideCondition(GetConditionArg0(key_child.second),
                                                                            GetConditionArg1(key_child.second)) );
-        notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
+        SignalConnector<PropertyNotification> connector(tracker, notification);
+        SetActionOnSignal(root, key_child.second, actor, builder, connector);
       }
       else if("Outside" == *cond)
       {
         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
                                                                            OutsideCondition(GetConditionArg0(key_child.second),
                                                                            GetConditionArg1(key_child.second)) );
-        notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
+        SignalConnector<PropertyNotification> connector(tracker, notification);
+        SetActionOnSignal(root, key_child.second, actor, builder, connector);
       }
       else
       {