(StyleManager) Remove StyleManager header include form CAPI
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / builder / builder-signals.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 // EXTERNAL INCLUDES
18 #include <dali/integration-api/debug.h>
19
20 // INTERNAL INCLUDES
21 #include <dali-toolkit/internal/builder/builder-impl.h>
22 #include <dali-toolkit/internal/builder/builder-get-is.inl.h>
23
24 namespace Dali
25 {
26 namespace Toolkit
27 {
28 namespace Internal
29 {
30 extern Animation CreateAnimation( const TreeNode& child );
31 extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value );
32 }
33 }
34 }
35
36 namespace
37 {
38 using namespace Dali;
39
40 //
41 // Signal Actions
42 //
43
44 // Action quit; connected to signals
45 // TODO: MOVE TO BUILDER TEMPLATE
46 struct ActionQuit
47 {
48   ActionQuit(void) {};
49
50   void operator()(void) {
51     // Dali::Application::Get().Quit();
52   };
53 };
54
55 // Action on child actor. The child is found by alias so can be 'previous' etc.
56 struct ChildActorAction
57 {
58   std::string actorName;
59   std::string actionName;
60   std::string childAlias;
61   std::vector<Property::Value> parameters;
62
63   void operator()(void)
64   {
65     Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName(actorName);
66
67     if(actor)
68     {
69       Actor child_actor = actor.FindChildByAlias(childAlias);
70
71       if(child_actor)
72       {
73         child_actor.DoAction(actionName, parameters);
74       }
75       else
76       {
77         DALI_SCRIPT_WARNING("Could not find child by alias '%s'\n", childAlias.c_str());
78       }
79     }
80   };
81 };
82
83 // Action to set a property
84 struct PropertySetAction
85 {
86   std::string actorName;
87   std::string propertyName;
88   Property::Value value;
89
90   void operator()(void)
91   {
92     Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName(actorName);
93
94     if(actor)
95     {
96       Property::Index idx = actor.GetPropertyIndex(propertyName);
97
98       if( idx != Property::INVALID_INDEX )
99       {
100         if( actor.GetPropertyType(idx) != value.GetType() )
101         {
102           DALI_SCRIPT_WARNING("Set property action has different type for property '%s'\n", propertyName.c_str());
103         }
104         else
105         {
106           actor.SetProperty( idx, value );
107         }
108       }
109       else
110       {
111         DALI_SCRIPT_WARNING("Set property action cannot find property '%s'\n", propertyName.c_str());
112       }
113     }
114   };
115 };
116
117 // Generic action on a handle (Animation & Actor)
118 struct GenericAction
119 {
120   std::string actorName;
121   std::string actionName;
122   std::vector<Property::Value> parameters;
123
124   void operator()(void)
125   {
126     Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName(actorName);
127     if(actor)
128     {
129       actor.DoAction(actionName, parameters);
130     }
131
132   };
133 };
134
135 // Delay an animation play; ie wait as its not on stage yet
136 struct DelayedAnimationPlay
137 {
138   Toolkit::JsonParser memento;
139
140   void operator()(void)
141   {
142     Animation anim = Toolkit::Internal::CreateAnimation(*memento.GetRoot());
143     if(anim)
144     {
145       anim.Play();
146     }
147   };
148 };
149
150 /*
151  * Gets Property::Value from child
152  */
153 Property::Value GetPropertyValue(const TreeNode &child)
154 {
155   size_t nChildren = child.Size();
156
157   Property::Value ret;
158
159   if(0 == nChildren)
160   {
161     // cast away unused return for static analyzers
162     static_cast<void>( Dali::Toolkit::Internal::SetPropertyFromNode( child, ret ) );
163   }
164   else if(1 == nChildren)
165   {
166     // {"property": {"quaternion":[1,2,3,4]} }
167     // {"property": {"angle":22, "axis": [1,2,3]} }
168
169     OptionalChild quaternion  = IsChild(&child, "quaternion");
170     OptionalChild axis        = IsChild(&child, "axis");
171     OptionalChild angle       = IsChild(&child, "angle");
172
173     if(quaternion)
174     {
175       ret = Property::Value(Quaternion(GetVector4(*quaternion)));
176     }
177     else if(axis && angle)
178     {
179       ret = Property::Value(AngleAxis(Degree(GetFloat(*angle)), GetVector3(*axis)));
180     }
181   }
182   else if(2 == nChildren)
183   {
184     // {"property": [1,2]}
185     ret = Property::Value(GetVector2(child));
186   }
187   else if(3 == nChildren)
188   {
189     // {"property": [1,2,3]}
190     ret = Property::Value(GetVector3(child));
191   }
192   else if(4 == nChildren)
193   {
194     // {"property": [1,2,3,4]}
195     ret = Property::Value(GetVector4(child));
196   }
197
198   return ret;
199 }
200
201
202 /*
203  * Gets Parmeter list from child
204  * params is be cleared before insertion
205  */
206 void GetParameters(const TreeNode &child, std::vector<Property::Value> &params)
207 {
208   if( OptionalChild c = IsChild(child, "parameters") )
209   {
210     const TreeNode& node = *c;
211
212     if(0 == node.Size())
213     {
214       GetPropertyValue(node);
215     }
216     else
217     {
218       params.clear();
219       params.reserve(node.Size());
220
221       for(TreeNode::ConstIterator iter(node.CBegin()); iter != node.CEnd(); ++iter)
222       {
223         params.push_back( GetPropertyValue( (*iter).second ) );
224       }
225     }
226   }
227 }
228
229 void DoNothing(void) {};
230
231 /**
232  * Get an action as boost function callback
233  */
234 boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &child, Actor actor)
235 {
236   OptionalString childActorName(IsString( IsChild(&child, "child-actor")) );
237   OptionalString actorName(IsString( IsChild(&child, "actor")) );
238   OptionalString propertyName(IsString( IsChild(&child, "property")) );
239   OptionalChild  valueChild( IsChild(&child, "value") );
240
241   OptionalString actionName = IsString( IsChild(&child, "action") );
242   DALI_ASSERT_ALWAYS(actionName && "Signal must have an action");
243
244   boost::function<void(void)> callback = DoNothing;
245
246   if(childActorName)
247   {
248     ChildActorAction action;
249     action.actorName       = *actorName;
250     action.childAlias      = *childActorName;
251     action.actionName      = *actionName;
252     GetParameters(child, action.parameters);
253     callback = action;
254   }
255   else if(actorName)
256   {
257     if(propertyName && valueChild && ("set" == *actionName) )
258     {
259       PropertySetAction action;
260       action.actorName       = *actorName;
261       action.propertyName    = *propertyName;
262       // actor may not exist yet so we can't check the property type
263       if( !Dali::Toolkit::Internal::SetPropertyFromNode( *valueChild, action.value ) )
264       {
265         DALI_SCRIPT_WARNING("Cannot set property for set property action\n");
266       }
267       callback = action;
268     }
269     else
270     {
271       GenericAction action;
272       action.actorName       = *actorName;
273       action.actionName      = *actionName;
274       GetParameters(child, action.parameters);
275       callback = action;
276     }
277   }
278   else if("quit" == *actionName)
279   {
280     callback = ActionQuit();
281   }
282   else if("play" == *actionName)
283   {
284     OptionalChild animations     = IsChild( root, "animations" );
285     OptionalString animationName = IsString( IsChild(child, "animation") );
286     if( animations && animationName )
287     {
288       if( OptionalChild animNode = IsChild(*animations, *animationName) )
289       {
290         DelayedAnimationPlay action;
291         action.memento = Toolkit::JsonParser::New(*animNode);
292         // @todo; put constants into the map
293         callback = action;
294       }
295       else
296       {
297         DALI_SCRIPT_WARNING("Cannot find animation '%s'\n", (*animationName).c_str());
298       }
299     }
300     else
301     {
302       DALI_SCRIPT_WARNING("Cannot find animations section\n");
303     }
304   }
305   else
306   {
307     // no named actor; presume self
308     GenericAction action;
309     action.actorName       = actor.GetName();
310     action.actionName      = *actionName;
311     GetParameters(child, action.parameters);
312     callback = action;
313   }
314
315   return callback;
316 }
317
318
319 /**
320  * Get a notification condition argument0 as 'arg0' 'value' or 'min'
321  */
322 float GetConditionArg0(const TreeNode &child)
323 {
324   OptionalFloat f = IsFloat( IsChild(child, "arg0") );
325   // allowing some human preferable alternatives
326   if(!f)
327   {
328     f = IsFloat( IsChild(child, "value") );
329   }
330   if(!f)
331   {
332     f = IsFloat( IsChild(child, "min") );
333   }
334   DALI_ASSERT_ALWAYS(f && "Notification condition for arg0 not specified");
335   if(f)
336   {
337     return *f;
338   }
339   else
340   {
341     return 0.f;
342   }
343 }
344
345 /**
346  * Get a notification condition argument1 as 'arg1' or 'max'
347  */
348 float GetConditionArg1(const TreeNode &child)
349 {
350   OptionalFloat f = IsFloat( IsChild(child, "arg1") );
351   // allowing some human preferable alternatives
352   if(!f)
353   {
354     f = IsFloat( IsChild(child, "max") );
355   }
356   DALI_ASSERT_ALWAYS(f && "Notification condition for arg1 not specified");
357   if(f)
358   {
359     return *f;
360   }
361   else
362   {
363     return 0.f;
364   }
365 }
366
367
368
369 }; // anon namespace
370
371 namespace Dali
372 {
373 namespace Toolkit
374 {
375 namespace Internal
376 {
377
378 Actor SetupSignalAction(const TreeNode &child, Actor actor);
379 Actor SetupPropertyNotification(const TreeNode &child, Actor actor);
380
381 /**
382  * Setup signals and actions on an actor
383  */
384 Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor)
385 {
386   DALI_ASSERT_ALWAYS(actor);
387
388   if(OptionalChild signalsChild = IsChild(child, "signals"))
389   {
390     const TreeNode& signalsNode = *signalsChild;
391     const TreeConstIter endIter = signalsNode.CEnd();
392     for( TreeConstIter iter = signalsNode.CBegin(); endIter != iter; ++iter )
393     {
394       const TreeNode::KeyNodePair& key_child = *iter;
395
396       DALI_SCRIPT_INFO("  Creating Signal for: %s\n", actor.GetName().c_str());
397
398       OptionalString name( IsString( IsChild( key_child.second, "name")) );
399       DALI_ASSERT_ALWAYS(name && "Signal must have a name");
400
401       boost::function<void (void)> callback = GetAction(root, key_child.second, actor);
402
403       actor.ConnectSignal(tracker, *name, callback);
404     }
405   }
406
407   return actor;
408 }
409
410 /**
411  * Setup Property notifications for an actor
412  */
413 Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor)
414 {
415   DALI_ASSERT_ALWAYS(actor);
416
417   if(OptionalChild notificationsChild = IsChild(child,"notifications"))
418   {
419     const TreeNode& notificationsNode = *notificationsChild;
420     const TreeNode::ConstIterator endIter = notificationsNode.CEnd();
421     for( TreeNode::ConstIterator iter = notificationsNode.CBegin(); endIter != iter; ++iter )
422     {
423       const TreeNode::KeyNodePair& key_child = *iter;
424
425       // Actor actions reference by pointer because of circular reference actor->signal
426       // So this callback should only go onto the actor maintained list.
427       boost::function<void (void)> callback = GetAction(root, key_child.second, actor);
428
429       OptionalString prop(IsString( IsChild(key_child.second, "property")) );
430       DALI_ASSERT_ALWAYS(prop && "Notification signal must specify a property");
431
432       Property::Index prop_index = actor.GetPropertyIndex(*prop);
433       DALI_ASSERT_ALWAYS(prop_index != Property::INVALID_INDEX && "Notification signal specifies an unknown property");
434
435       OptionalString cond(IsString( IsChild(key_child.second, "condition")));
436       DALI_ASSERT_ALWAYS(cond && "Notification signal must specify a condition");
437
438       if("False" == *cond)
439       {
440         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
441                                                                            LessThanCondition(1.f) );
442         notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
443       }
444       else if("LessThan" == *cond)
445       {
446         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
447                                                                            LessThanCondition(GetConditionArg0(key_child.second)) );
448         notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
449       }
450       else if("GreaterThan" == *cond)
451       {
452         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
453                                                                            GreaterThanCondition(GetConditionArg0(key_child.second)) );
454         notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
455       }
456       else if("Inside" == *cond)
457       {
458         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
459                                                                            InsideCondition(GetConditionArg0(key_child.second),
460                                                                            GetConditionArg1(key_child.second)) );
461         notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
462       }
463       else if("Outside" == *cond)
464       {
465         PropertyNotification notification = actor.AddPropertyNotification( actor.GetPropertyIndex(*prop),
466                                                                            OutsideCondition(GetConditionArg0(key_child.second),
467                                                                            GetConditionArg1(key_child.second)) );
468         notification.NotifySignal().Connect( tracker, FunctorDelegate::New(callback) );
469       }
470       else
471       {
472         DALI_ASSERT_ALWAYS(!"Unknown condition");
473       }
474     }
475   } // if notifications
476
477   return actor;
478
479 } // AddPropertyNotification
480
481
482 } // namespace Internal
483 } // namespace Toolkit
484 } // namespace Dali