Changed all property & signal names to lowerCamelCase
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / builder / builder-signals.cpp
index f832721..ed22ef3 100644 (file)
  */
 
 // EXTERNAL INCLUDES
-#include <boost/function.hpp>
 #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>
@@ -52,7 +54,7 @@ struct ChildActorAction
   std::string actorName;
   std::string actionName;
   std::string childName;
-  PropertyValueContainer parameters;
+  Property::Map parameters;
 
   void operator()(void)
   {
@@ -113,7 +115,7 @@ struct GenericAction
 {
   std::string actorName;
   std::string actionName;
-  PropertyValueContainer parameters;
+  Property::Map parameters;
 
   void operator()(void)
   {
@@ -126,6 +128,16 @@ 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
 {
@@ -142,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
  */
@@ -198,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, PropertyValueContainer& 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, boost::function<void (void)> quitAction, Dali::Toolkit::Internal::Builder* const builder)
+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") );
@@ -236,8 +467,6 @@ 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;
@@ -245,7 +474,7 @@ boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &chi
     action.childName       = *childActorName;
     action.actionName      = *actionName;
     GetParameters(child, action.parameters);
-    callback = action;
+    connector.Connect( action );
   }
   else if(actorName)
   {
@@ -259,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
     {
@@ -267,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 = quitAction;
+    QuitAction action;
+    action.builder = builder;
+    connector.Connect( action );
   }
   else if("play" == *actionName)
   {
@@ -286,7 +517,7 @@ boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &chi
         action.animNode = animNode;
         action.builder = builder;
         // @todo; put constants into the map
-        callback = action;
+        connector.Connect( action );
       }
       else
       {
@@ -298,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
@@ -305,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;
 }
 
 
@@ -367,7 +702,7 @@ Actor SetupPropertyNotification(const TreeNode &child, Actor actor, Dali::Toolki
 /**
  * Setup signals and actions on an actor
  */
-Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function<void (void)> quitAction, Dali::Toolkit::Internal::Builder* const builder )
+Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder )
 {
   DALI_ASSERT_ALWAYS(actor);
 
@@ -384,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, quitAction, builder );
-
-      actor.ConnectSignal(tracker, *name, callback);
+      SignalConnector<Actor> connector(tracker, actor, *name);
+      SetActionOnSignal(root, key_child.second, actor, builder, connector);
     }
   }
 
@@ -396,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, boost::function<void (void)> quitAction, Dali::Toolkit::Internal::Builder* const builder )
+Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder )
 {
   DALI_ASSERT_ALWAYS(actor);
 
@@ -408,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, quitAction, builder );
-
       OptionalString prop(IsString( IsChild(key_child.second, "property")) );
       DALI_ASSERT_ALWAYS(prop && "Notification signal must specify a property");
 
@@ -425,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
       {