Merge "Added style name for styling TextEditor ScrollBar" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / builder / builder-signals.cpp
index 804deb3..55809bd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2016 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.
  */
 
 // 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>
 
@@ -35,7 +35,7 @@ namespace Toolkit
 namespace Internal
 {
 extern Animation CreateAnimation( const TreeNode& child, Dali::Toolkit::Internal::Builder* const builder  );
-extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value );
+extern bool DeterminePropertyFromNode( const TreeNode& node, Property::Value& value );
 }
 }
 }
@@ -54,7 +54,7 @@ struct ChildActorAction
   std::string actorName;
   std::string actionName;
   std::string childName;
-  PropertyValueContainer parameters;
+  Property::Map parameters;
 
   void operator()(void)
   {
@@ -115,7 +115,7 @@ struct GenericAction
 {
   std::string actorName;
   std::string actionName;
-  PropertyValueContainer parameters;
+  Property::Map parameters;
 
   void operator()(void)
   {
@@ -128,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
 {
@@ -332,7 +342,7 @@ Property::Value GetPropertyValue(const TreeNode &child)
   if(0 == nChildren)
   {
     // cast away unused return for static analyzers
-    static_cast<void>( Dali::Toolkit::Internal::SetPropertyFromNode( child, ret ) );
+    static_cast<void>( Dali::Toolkit::Internal::DeterminePropertyFromNode( child, ret ) );
   }
   else if(1 == nChildren)
   {
@@ -376,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") );
@@ -414,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;
@@ -423,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)
   {
@@ -433,11 +484,8 @@ boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &chi
       action.actorName       = *actorName;
       action.propertyName    = *propertyName;
       // actor may not exist yet so we can't check the property type
-      if( !Dali::Toolkit::Internal::SetPropertyFromNode( *valueChild, action.value ) )
-      {
-        DALI_SCRIPT_WARNING("Cannot set property for set property action\n");
-      }
-      callback = action;
+      Dali::Toolkit::Internal::DeterminePropertyFromNode( *valueChild, action.value );
+      connector.Connect( action );
     }
     else
     {
@@ -445,12 +493,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)
   {
@@ -464,7 +514,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
       {
@@ -543,12 +593,9 @@ boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &chi
           action.ranges.push_back(*range);
           action.wrapRanges.push_back(wrap);
         }
-
-        callback = action;
+        connector.Connect(action);
       }
     }
-
-
   }
   else if("removeConstraints" == *actionName )
   {
@@ -582,7 +629,7 @@ boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &chi
           }
         }
       }
-      callback = action;
+      connector.Connect(action);
     }
   }
   else
@@ -592,10 +639,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;
 }
 
 
@@ -654,7 +699,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);
 
@@ -671,9 +716,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);
     }
   }
 
@@ -683,7 +727,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);
 
@@ -695,10 +739,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");
 
@@ -712,33 +752,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
       {