Remove ImageActor from comments and variable names
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / builder / builder-impl.cpp
1 /*
2  * Copyright (c) 2016 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 // CLASS HEADER
19 #include <dali-toolkit/internal/builder/builder-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <sys/stat.h>
23 #include <sstream>
24
25 #include <dali/public-api/render-tasks/render-task-list.h>
26 #include <dali/public-api/object/type-info.h>
27 #include <dali/public-api/object/type-registry.h>
28 #include <dali/public-api/object/property-array.h>
29 #include <dali/public-api/actors/layer.h>
30 #include <dali/public-api/actors/camera-actor.h>
31 #include <dali/devel-api/scripting/scripting.h>
32 #include <dali/public-api/signals/functor-delegate.h>
33 #include <dali/integration-api/debug.h>
34
35 // INTERNAL INCLUDES
36 #include <dali-toolkit/public-api/controls/control.h>
37 #include <dali-toolkit/devel-api/builder/json-parser.h>
38
39 #include <dali-toolkit/internal/builder/builder-get-is.inl.h>
40 #include <dali-toolkit/internal/builder/builder-filesystem.h>
41 #include <dali-toolkit/internal/builder/builder-declarations.h>
42 #include <dali-toolkit/internal/builder/builder-set-property.h>
43 #include <dali-toolkit/internal/builder/replacement.h>
44 #include <dali-toolkit/internal/builder/tree-node-manipulator.h>
45
46 #include <dali-toolkit/internal/builder/builder-impl-debug.h>
47
48 namespace Dali
49 {
50
51 namespace Toolkit
52 {
53
54 namespace Internal
55 {
56 class Replacement;
57
58 extern Animation CreateAnimation(const TreeNode& child, const Replacement& replacements, const Dali::Actor searchRoot, Builder* const builder );
59 extern Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder);
60 extern Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder);
61 extern Actor SetupActor( const TreeNode& node, Actor& actor, const Replacement& constant );
62
63 #if defined(DEBUG_ENABLED)
64 Integration::Log::Filter* gFilterScript  = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_SCRIPT");
65 #endif
66
67 namespace
68 {
69
70 #define TOKEN_STRING(x) #x
71
72 const std::string KEYNAME_STYLES    = "styles";
73 const std::string KEYNAME_TYPE      = "type";
74 const std::string KEYNAME_ACTORS    = "actors";
75 const std::string KEYNAME_SIGNALS   = "signals";
76 const std::string KEYNAME_NAME      = "name";
77 const std::string KEYNAME_TEMPLATES = "templates";
78 const std::string KEYNAME_INCLUDES  = "includes";
79 const std::string KEYNAME_MAPPINGS  = "mappings";
80
81 const std::string PROPERTIES = "properties";
82 const std::string ANIMATABLE_PROPERTIES = "animatableProperties";
83
84 typedef std::vector<const TreeNode*> TreeNodeList;
85
86
87 bool GetMappingKey( const std::string& str, std::string& key )
88 {
89   bool result = false;
90   std::string test( str );
91   if( ! test.empty() )
92   {
93     if( test.at(0) == '<' )
94     {
95       if( test.at(test.length()-1) == '>' )
96       {
97         key = test.substr( 1, test.length()-2 );
98         result = true;
99       }
100     }
101   }
102   return result;
103 }
104
105 /*
106  * Recursively collects all stylesin a node (An array of style names).
107  *
108  * stylesCollection The set of styles from the json file (a json object of named styles)
109  * style The style array to begin the collection from
110  * styleList The style list to add nodes to apply
111  */
112 void CollectAllStyles( const TreeNode& stylesCollection, const TreeNode& style, TreeNodeList& styleList )
113 {
114   // style is an array of style names
115   if( TreeNode::ARRAY == style.GetType() )
116   {
117     for(TreeNode::ConstIterator iter = style.CBegin(); iter != style.CEnd(); ++iter)
118     {
119       if( OptionalString styleName = IsString( (*iter).second ) )
120       {
121         if( OptionalChild node = IsChild( stylesCollection, *styleName) )
122         {
123           styleList.push_back( &(*node) );
124
125           if( OptionalChild subStyle = IsChild( *node, KEYNAME_STYLES ) )
126           {
127             CollectAllStyles( stylesCollection, *subStyle, styleList );
128           }
129         }
130       }
131     }
132   }
133 }
134
135
136 } // namespace anon
137
138 /*
139  * Sets the handle properties found in the tree node
140  */
141 void Builder::SetProperties( const TreeNode& node, Handle& handle, const Replacement& constant )
142 {
143   if( handle )
144   {
145
146     for( TreeNode::ConstIterator iter = node.CBegin(); iter != node.CEnd(); ++iter )
147     {
148       const TreeNode::KeyNodePair& keyChild = *iter;
149
150       std::string key( keyChild.first );
151
152       // ignore special fields; type,actors,signals,styles
153       if(key == KEYNAME_TYPE || key == KEYNAME_ACTORS || key == KEYNAME_SIGNALS || key == KEYNAME_STYLES || key == KEYNAME_MAPPINGS )
154       {
155         continue;
156       }
157
158       Handle propertyObject( handle );
159
160       Dali::Property::Index index = propertyObject.GetPropertyIndex( key );
161
162       if( Property::INVALID_INDEX != index )
163       {
164         Property::Type type = propertyObject.GetPropertyType(index);
165         Property::Value value;
166         bool mapped = false;
167
168         // if node.value is a mapping, get the property value from the "mappings" table
169         if( keyChild.second.GetType() == TreeNode::STRING )
170         {
171           std::string mappingKey;
172           if( GetMappingKey(keyChild.second.GetString(), mappingKey) )
173           {
174             OptionalChild mappingRoot = IsChild( mParser.GetRoot(), KEYNAME_MAPPINGS );
175             mapped = GetPropertyMap( *mappingRoot, mappingKey.c_str(), type, value );
176           }
177         }
178         if( ! mapped )
179         {
180           mapped = DeterminePropertyFromNode( keyChild.second, type, value, constant );
181           if( ! mapped )
182           {
183             // verbose as this might not be a problem
184             // eg parentOrigin can be a string which is picked up later
185             DALI_SCRIPT_VERBOSE("Could not convert property:%s\n", key.c_str());
186           }
187         }
188         if( mapped )
189         {
190           DALI_SCRIPT_VERBOSE("SetProperty '%s' Index=:%d Value Type=%d Value '%s'\n", key.c_str(), index, value.GetType(), PropertyValueToString(value).c_str() );
191
192           propertyObject.SetProperty( index, value );
193         }
194       }
195       else
196       {
197         DALI_SCRIPT_VERBOSE("SetProperty INVALID '%s' Index=:%d\n", key.c_str(), index);
198       }
199
200       // Add custom properties
201       SetCustomProperties(node, handle, constant, PROPERTIES, Property::READ_WRITE);
202       SetCustomProperties(node, handle, constant, ANIMATABLE_PROPERTIES, Property::ANIMATABLE);
203
204     } // for property nodes
205   }
206   else
207   {
208     DALI_SCRIPT_WARNING("Style applied to empty handle\n");
209   }
210 }
211
212 void Builder::SetCustomProperties( const TreeNode& node, Handle& handle, const Replacement& constant,
213                           const std::string& childName, Property::AccessMode accessMode )
214 {
215   // Add custom properties
216   if( OptionalChild customPropertiesChild = IsChild(node, childName) )
217   {
218     const TreeNode& customPropertiesNode = *customPropertiesChild;
219     const TreeConstIter endIter = customPropertiesNode.CEnd();
220     for( TreeConstIter iter = customPropertiesNode.CBegin(); endIter != iter; ++iter )
221     {
222       const TreeNode::KeyNodePair& keyChild = *iter;
223       std::string key( keyChild.first );
224
225       Property::Value value;
226       DeterminePropertyFromNode( keyChild.second, value, constant );
227       // Register/Set property.
228       handle.RegisterProperty( key, value, accessMode );
229     }
230   }
231 }
232
233 // Set properties from node on handle.
234 void Builder::ApplyProperties( const TreeNode& root, const TreeNode& node,
235                                Dali::Handle& handle, const Replacement& constant )
236 {
237   if( Actor actor = Actor::DownCast(handle) )
238   {
239     SetProperties( node, actor, constant );
240
241     if( actor )
242     {
243       SetupActor( node, actor, constant );
244
245       // add signals
246       SetupSignalAction( mSlotDelegate.GetConnectionTracker(), root, node, actor, this );
247       SetupPropertyNotification( mSlotDelegate.GetConnectionTracker(), root, node, actor, this );
248    }
249   }
250   else
251   {
252     SetProperties( node, handle, constant );
253   }
254 }
255
256 // Appling by style helper
257 // use FindChildByName() to apply properties referenced in KEYNAME_ACTORS in the node
258 void Builder::ApplyStylesByActor(  const TreeNode& root, const TreeNode& node,
259                                    Dali::Handle& handle, const Replacement& constant )
260 {
261   if( Dali::Actor actor = Dali::Actor::DownCast( handle ) )
262   {
263     if( const TreeNode* actors = node.GetChild( KEYNAME_ACTORS ) )
264     {
265       // in a style the actor subtree properties referenced by actor name
266       for( TreeConstIter iter = actors->CBegin(); iter != actors->CEnd(); ++iter )
267       {
268         Dali::Actor foundActor;
269
270         if( (*iter).first )
271         {
272           foundActor = actor.FindChildByName( (*iter).first );
273         }
274
275         if( !foundActor )
276         {
277           // debug log cannot find searched for actor
278 #if defined(DEBUG_ENABLED)
279           DALI_SCRIPT_VERBOSE("Cannot find actor in style application '%s'\n", (*iter).first);
280 #endif
281         }
282         else
283         {
284 #if defined(DEBUG_ENABLED)
285           DALI_SCRIPT_VERBOSE("Styles applied to actor '%s'\n", (*iter).first);
286 #endif
287           ApplyProperties( root, (*iter).second, foundActor, constant );
288         }
289       }
290     }
291   }
292 }
293
294
295 void Builder::ApplyAllStyleProperties( const TreeNode& root, const TreeNode& node,
296                                        Dali::Handle& handle, const Replacement& constant )
297 {
298   OptionalChild styles = IsChild(root, KEYNAME_STYLES);
299   OptionalChild style  = IsChild(node, KEYNAME_STYLES);
300
301   if( styles && style )
302   {
303     TreeNodeList additionalStyles;
304
305     CollectAllStyles( *styles, *style, additionalStyles );
306
307 #if defined(DEBUG_ENABLED)
308     for(TreeNode::ConstIterator iter = (*style).CBegin(); iter != (*style).CEnd(); ++iter)
309     {
310       if( OptionalString styleName = IsString( (*iter).second ) )
311       {
312         DALI_SCRIPT_VERBOSE("Style Applied '%s'\n", (*styleName).c_str());
313       }
314     }
315 #endif
316
317     // a style may have other styles, which has other styles etc so we apply in reverse by convention.
318     for(TreeNodeList::reverse_iterator iter = additionalStyles.rbegin(); iter != additionalStyles.rend(); ++iter)
319     {
320       ApplyProperties( root, *(*iter), handle, constant );
321
322       ApplyStylesByActor( root, *(*iter), handle, constant );
323     }
324   }
325
326   // applying given node last
327   ApplyProperties( root, node, handle, constant );
328
329   ApplyStylesByActor( root, node, handle, constant );
330
331 }
332
333
334 /*
335  * Create a dali type from a node.
336  * If parent given and an actor type was created then add it to the parent and
337  * recursively add nodes children.
338  */
339 BaseHandle Builder::DoCreate( const TreeNode& root, const TreeNode& node,
340                               Actor parent, const Replacement& replacements )
341 {
342   BaseHandle baseHandle;
343   TypeInfo typeInfo;
344   const TreeNode* templateNode = NULL;
345
346   if( OptionalString typeName = IsString(node, KEYNAME_TYPE) )
347   {
348     typeInfo = TypeRegistry::Get().GetTypeInfo( *typeName );
349
350     if( !typeInfo )
351     {
352       // a template name is also allowed inplace of the type name
353       OptionalChild templates = IsChild( root, KEYNAME_TEMPLATES);
354
355       if( templates )
356       {
357         if( OptionalChild isTemplate = IsChild( *templates, *typeName ) )
358         {
359           templateNode = &(*isTemplate);
360
361           if( OptionalString templateTypeName = IsString(*templateNode, KEYNAME_TYPE) )
362           {
363             typeInfo = TypeRegistry::Get().GetTypeInfo( *templateTypeName );
364           }
365         }
366       }
367     }
368   }
369
370   if(!typeInfo)
371   {
372     DALI_SCRIPT_WARNING("Cannot create Dali type from node '%s'\n", node.GetName());
373   }
374   else
375   {
376     baseHandle       = typeInfo.CreateInstance();
377     Handle handle    = Handle::DownCast(baseHandle);
378     Actor actor      = Actor::DownCast(handle);
379
380     if(handle)
381     {
382
383       DALI_SCRIPT_VERBOSE("Create:%s\n", typeInfo.GetName().c_str());
384
385 #if defined(DEBUG_ENABLED)
386       if(handle)
387       {
388         DALI_SCRIPT_VERBOSE("  Is Handle Object=%d\n", (long*)handle.GetObjectPtr());
389         DALI_SCRIPT_VERBOSE("  Is Handle Property Count=%d\n", handle.GetPropertyCount());
390       }
391
392       if(actor)
393       {
394         DALI_SCRIPT_VERBOSE("  Is Actor id=%d\n", actor.GetId());
395       }
396
397       Toolkit::Control control  = Toolkit::Control::DownCast(handle);
398       if(control)
399       {
400         DALI_SCRIPT_VERBOSE("  Is Control id=%d\n", actor.GetId());
401       }
402 #endif // DEBUG_ENABLED
403
404       if( templateNode )
405       {
406         ApplyProperties( root, *templateNode, handle, replacements );
407
408         if( OptionalChild actors = IsChild( *templateNode, KEYNAME_ACTORS ) )
409         {
410           for( TreeConstIter iter = (*actors).CBegin(); iter != (*actors).CEnd(); ++iter )
411           {
412             DoCreate( root, (*iter).second, actor, replacements );
413           }
414         }
415       }
416
417       if( actor )
418       {
419         // add children of all the styles
420         if( OptionalChild actors = IsChild( node, KEYNAME_ACTORS ) )
421         {
422           for( TreeConstIter iter = (*actors).CBegin(); iter != (*actors).CEnd(); ++iter )
423           {
424             DoCreate( root, (*iter).second, actor, replacements );
425           }
426         }
427
428         // apply style on top as they need the children to exist
429         ApplyAllStyleProperties( root, node, actor, replacements );
430
431         // then add to parent
432         if( parent )
433         {
434           parent.Add( actor );
435         }
436       }
437       else
438       {
439         ApplyProperties( root, node, handle, replacements );
440       }
441     }
442     else
443     {
444       DALI_SCRIPT_WARNING("Cannot create handle from type '%s'\n", typeInfo.GetName().c_str());
445     }
446   }
447
448   return baseHandle;
449 }
450
451 void Builder::SetupTask( RenderTask& task, const TreeNode& node, const Replacement& constant )
452 {
453   const Stage& stage = Stage::GetCurrent();
454   Layer root  = stage.GetRootLayer();
455
456   if( OptionalString s = constant.IsString( IsChild(node, "sourceActor") ) )
457   {
458     Actor actor = root.FindChildByName(*s);
459     if(actor)
460     {
461       task.SetSourceActor( actor );
462     }
463     else
464     {
465       DALI_SCRIPT_WARNING("Cannot find source actor on stage for render task called '%s'\n", (*s).c_str() );
466     }
467   }
468
469   if( OptionalString s = constant.IsString( IsChild(node, "cameraActor") ) )
470   {
471     CameraActor actor = CameraActor::DownCast( root.FindChildByName(*s) );
472     if(actor)
473     {
474       task.SetCameraActor( actor );
475     }
476     else
477     {
478       DALI_SCRIPT_WARNING("Cannot find camera actor on stage for render task called '%s'\n", (*s).c_str() );
479     }
480   }
481
482   if( OptionalString s = constant.IsString( IsChild(node, "targetFrameBuffer") ) )
483   {
484     FrameBufferImage fb = GetFrameBufferImage( *s, constant );
485     if(fb)
486     {
487       task.SetTargetFrameBuffer( fb );
488     }
489     else
490     {
491       DALI_SCRIPT_WARNING("Cannot find target frame buffer '%s'\n", (*s).c_str() );
492     }
493   }
494
495   if( OptionalString s = constant.IsString( IsChild(node, "screenToFrameBufferFunction") ) )
496   {
497     if("DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION" == *s)
498     {
499       task.SetScreenToFrameBufferFunction( RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION );
500     }
501     else if("FULLSCREEN_FRAMEBUFFER_FUNCTION" == *s)
502     {
503       task.SetScreenToFrameBufferFunction( RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION );
504     }
505     else
506     {
507       DALI_SCRIPT_WARNING("todo");
508     }
509   }
510
511   // other setup is via the property system
512   SetProperties( node, task, constant );
513 }
514
515 void Builder::CreateRenderTask( const std::string &name )
516 {
517   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
518
519   Replacement constant(mReplacementMap);
520
521   const Stage& stage = Stage::GetCurrent();
522
523   OptionalChild tasks = IsChild(*mParser.GetRoot(), "renderTasks");
524
525   if(tasks)
526   {
527     //
528     // Create the tasks from the current task as generally we want
529     // to setup task zero and onwards. Although this does overwrite
530     // the properties of the current task.
531     //
532     if( OptionalChild renderTask = IsChild(*tasks, name ) )
533     {
534       RenderTaskList list = stage.GetRenderTaskList();
535       unsigned int start = list.GetTaskCount();
536
537       RenderTask task;
538       if(0 == start)
539       {
540         // zero should have already been created by the stage so really
541         // this case should never happen
542         task = list.CreateTask();
543         start++;
544       }
545
546       TreeNode::ConstIterator iter = (*renderTask).CBegin();
547       task = list.GetTask( start - 1 );
548
549       SetupTask( task, (*iter).second, constant  );
550
551       ++iter;
552
553       for(; iter != (*renderTask).CEnd(); ++iter )
554       {
555         task = list.CreateTask();
556         SetupTask( task, (*iter).second, constant );
557       }
558     }
559   }
560 }
561
562 FrameBufferImage Builder::GetFrameBufferImage( const std::string &name )
563 {
564   Replacement constant( mReplacementMap );
565   return GetFrameBufferImage(name, constant);
566 }
567
568 FrameBufferImage Builder::GetFrameBufferImage( const std::string &name, const Replacement& constant )
569 {
570   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
571
572   FrameBufferImage ret;
573
574   ImageLut::const_iterator iter( mFrameBufferImageLut.find( name ) );
575   if( iter != mFrameBufferImageLut.end() )
576   {
577     ret = iter->second;
578   }
579   else
580   {
581     if( OptionalChild images = IsChild( *mParser.GetRoot(), "frameBufferImages") )
582     {
583       if( OptionalChild image = IsChild( *images, name ) )
584       {
585         Dali::Property::Value property(Property::MAP);
586         if( DeterminePropertyFromNode( *image, Property::MAP, property, constant ) )
587         {
588           Property::Map* map = property.GetMap();
589
590           if( map )
591           {
592             (*map)[ KEYNAME_TYPE ] = Property::Value(std::string("FrameBufferImage") );
593             ret = FrameBufferImage::DownCast( Dali::Scripting::NewImage( property ) );
594             mFrameBufferImageLut[ name ] = ret;
595           }
596         }
597       }
598     }
599   }
600
601   return ret;
602 }
603
604 Path Builder::GetPath( const std::string& name )
605 {
606   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
607
608   Path ret;
609
610   PathLut::const_iterator iter( mPathLut.find( name ) );
611   if( iter != mPathLut.end() )
612   {
613     ret = iter->second;
614   }
615   else
616   {
617     if( OptionalChild paths = IsChild( *mParser.GetRoot(), "paths") )
618     {
619       if( OptionalChild path = IsChild( *paths, name ) )
620       {
621         //points property
622         if( OptionalChild pointsProperty = IsChild( *path, "points") )
623         {
624           Dali::Property::Value points(Property::ARRAY);
625           if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
626           {
627             ret = Path::New();
628             ret.SetProperty( Path::Property::POINTS, points);
629
630             //controlPoints property
631             if( OptionalChild pointsProperty = IsChild( *path, "controlPoints") )
632             {
633               Dali::Property::Value points(Property::ARRAY);
634               if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
635               {
636                 ret.SetProperty( Path::Property::CONTROL_POINTS, points);
637               }
638             }
639             else
640             {
641               //Curvature
642               float curvature(0.25f);
643               if( OptionalFloat pointsProperty = IsFloat( *path, "curvature") )
644               {
645                 curvature = *pointsProperty;
646               }
647               ret.GenerateControlPoints(curvature);
648             }
649
650             //Add the new path to the hash table for paths
651             mPathLut[ name ] = ret;
652           }
653         }
654         else
655         {
656           //Interpolation points not specified
657           DALI_SCRIPT_WARNING("Interpolation points not specified for path '%s'\n", name.c_str() );
658         }
659       }
660
661     }
662   }
663
664   return ret;
665 }
666
667 PathConstrainer Builder::GetPathConstrainer( const std::string& name )
668 {
669   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
670
671   //Search the pathConstrainer in the LUT
672   size_t count( mPathConstrainerLut.size() );
673   for( size_t i(0); i!=count; ++i )
674   {
675     if( mPathConstrainerLut[i].name == name )
676     {
677       //PathConstrainer has already been created
678       return mPathConstrainerLut[i].pathConstrainer;
679     }
680   }
681
682   //Create a new PathConstrainer
683   PathConstrainer ret;
684   if( OptionalChild constrainers = IsChild( *mParser.GetRoot(), "constrainers") )
685   {
686     if( OptionalChild pathConstrainer = IsChild( *constrainers, name ) )
687     {
688       OptionalString constrainerType(IsString(IsChild(*pathConstrainer, "type")));
689       if(!constrainerType)
690       {
691         DALI_SCRIPT_WARNING("Constrainer type not specified for constrainer '%s'\n", name.c_str() );
692       }
693       else if( *constrainerType == "PathConstrainer")
694       {
695         //points property
696         if( OptionalChild pointsProperty = IsChild( *pathConstrainer, "points") )
697         {
698           Dali::Property::Value points(Property::ARRAY);
699           if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
700           {
701             ret = PathConstrainer::New();
702             ret.SetProperty( PathConstrainer::Property::POINTS, points);
703
704             //controlPoints property
705             if( OptionalChild pointsProperty = IsChild( *pathConstrainer, "controlPoints") )
706             {
707               Dali::Property::Value points(Property::ARRAY);
708               if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
709               {
710                 ret.SetProperty( PathConstrainer::Property::CONTROL_POINTS, points);
711               }
712
713               //Forward vector
714               OptionalVector3 forward( IsVector3( IsChild(*pathConstrainer, "forward" ) ) );
715               if( forward )
716               {
717                 ret.SetProperty( PathConstrainer::Property::FORWARD, *forward);
718               }
719
720               //Add the new constrainer to the vector of PathConstrainer
721               PathConstrainerEntry entry = {name,ret};
722               mPathConstrainerLut.push_back( entry );
723             }
724             else
725             {
726               //Control points not specified
727               DALI_SCRIPT_WARNING("Control points not specified for pathConstrainer '%s'\n", name.c_str() );
728             }
729           }
730         }
731         else
732         {
733           //Interpolation points not specified
734           DALI_SCRIPT_WARNING("Interpolation points not specified for pathConstrainer '%s'\n", name.c_str() );
735         }
736       }
737       else
738       {
739         DALI_SCRIPT_WARNING("Constrainer '%s' is not a PathConstrainer\n", name.c_str() );
740       }
741     }
742   }
743
744   return ret;
745 }
746
747 bool Builder::IsPathConstrainer( const std::string& name )
748 {
749   size_t count( mPathConstrainerLut.size() );
750   for( size_t i(0); i!=count; ++i )
751   {
752     if( mPathConstrainerLut[i].name == name )
753     {
754       return true;
755     }
756   }
757
758   if( OptionalChild constrainers = IsChild( *mParser.GetRoot(), "constrainers") )
759   {
760     if( OptionalChild constrainer = IsChild( *constrainers, name ) )
761     {
762       OptionalString constrainerType(IsString(IsChild(*constrainer, "type")));
763       if(!constrainerType)
764       {
765         return false;
766       }
767       else
768       {
769          return *constrainerType == "PathConstrainer";
770       }
771     }
772   }
773   return false;
774 }
775
776 Dali::LinearConstrainer Builder::GetLinearConstrainer( const std::string& name )
777 {
778   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
779
780   //Search the LinearConstrainer in the LUT
781   size_t count( mLinearConstrainerLut.size() );
782   for( size_t i(0); i!=count; ++i )
783   {
784     if( mLinearConstrainerLut[i].name == name )
785     {
786       //LinearConstrainer has already been created
787       return mLinearConstrainerLut[i].linearConstrainer;
788     }
789   }
790
791   //Create a new LinearConstrainer
792   LinearConstrainer ret;
793   if( OptionalChild constrainers = IsChild( *mParser.GetRoot(), "constrainers") )
794   {
795     if( OptionalChild linearConstrainer = IsChild( *constrainers, name ) )
796     {
797       OptionalString constrainerType(IsString(IsChild(*linearConstrainer, "type")));
798       if(!constrainerType)
799       {
800         DALI_SCRIPT_WARNING("Constrainer type not specified for constrainer '%s'\n", name.c_str() );
801       }
802       else if( *constrainerType == "LinearConstrainer")
803       {
804         //points property
805         if( OptionalChild pointsProperty = IsChild( *linearConstrainer, "value") )
806         {
807           Dali::Property::Value points(Property::ARRAY);
808           if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
809           {
810             ret = Dali::LinearConstrainer::New();
811             ret.SetProperty( LinearConstrainer::Property::VALUE, points);
812
813             //controlPoints property
814             if( OptionalChild pointsProperty = IsChild( *linearConstrainer, "progress") )
815             {
816               Dali::Property::Value points(Property::ARRAY);
817               if( DeterminePropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
818               {
819                 ret.SetProperty( LinearConstrainer::Property::PROGRESS, points);
820               }
821             }
822             //Add the new constrainer to vector of LinearConstrainer
823             LinearConstrainerEntry entry = {name,ret};
824             mLinearConstrainerLut.push_back( entry );
825           }
826         }
827         else
828         {
829           //Interpolation points not specified
830           DALI_SCRIPT_WARNING("Values not specified for LinearConstrainer '%s'\n", name.c_str() );
831         }
832       }
833       else
834       {
835         DALI_SCRIPT_WARNING("Constrainer '%s' is not a LinearConstrainer\n", name.c_str() );
836       }
837     }
838   }
839
840   return ret;
841 }
842
843 bool Builder::IsLinearConstrainer( const std::string& name )
844 {
845   // Search the LinearConstrainer in the LUT
846   size_t count( mLinearConstrainerLut.size() );
847   for( size_t i(0); i!=count; ++i )
848   {
849     if( mLinearConstrainerLut[i].name == name )
850     {
851       return true;
852     }
853   }
854
855   if( OptionalChild constrainers = IsChild( *mParser.GetRoot(), "constrainers") )
856   {
857     if( OptionalChild constrainer = IsChild( *constrainers, name ) )
858     {
859       OptionalString constrainerType(IsString(IsChild(*constrainer, "type")));
860       if(!constrainerType)
861       {
862         return false;
863       }
864       else
865       {
866          return *constrainerType == "LinearConstrainer";
867       }
868     }
869   }
870   return false;
871 }
872
873 Toolkit::Builder::BuilderSignalType& Builder::QuitSignal()
874 {
875   return mQuitSignal;
876 }
877
878 void Builder::EmitQuitSignal()
879 {
880   mQuitSignal.Emit();
881 }
882
883 void Builder::AddActors( Actor toActor )
884 {
885   // 'stage' is the default/by convention section to add from
886   AddActors( "stage", toActor );
887 }
888
889 void Builder::AddActors( const std::string &sectionName, Actor toActor )
890 {
891   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
892
893   Property::Map overrideMap;
894   Replacement replacements(overrideMap, mReplacementMap);
895
896   OptionalChild add = IsChild(*mParser.GetRoot(), sectionName);
897
898   if( add )
899   {
900     for( TreeNode::ConstIterator iter = (*add).CBegin(); iter != (*add).CEnd(); ++iter )
901     {
902       // empty actor adds directly to the stage
903       BaseHandle baseHandle = DoCreate( *mParser.GetRoot(), (*iter).second, Actor(), replacements );
904       Actor actor = Actor::DownCast(baseHandle);
905       if(actor)
906       {
907         toActor.Add( actor );
908       }
909     }
910
911     // if were adding the 'stage' section then also check for a render task called stage
912     // to add automatically
913     if( "stage" == sectionName )
914     {
915       if( OptionalChild renderTasks = IsChild(*mParser.GetRoot(), "renderTasks") )
916       {
917         if( OptionalChild tasks = IsChild(*renderTasks, "stage") )
918         {
919           CreateRenderTask( "stage" );
920         }
921       }
922     }
923   }
924 }
925
926 Animation Builder::CreateAnimation( const std::string& animationName, const Replacement& replacement, Dali::Actor sourceActor )
927 {
928   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
929
930   Animation anim;
931
932   if( OptionalChild animations = IsChild(*mParser.GetRoot(), "animations") )
933   {
934     if( OptionalChild animation = IsChild(*animations, animationName) )
935     {
936       anim = Dali::Toolkit::Internal::CreateAnimation( *animation, replacement, sourceActor, this );
937     }
938     else
939     {
940       DALI_SCRIPT_WARNING( "Request for Animation called '%s' failed\n", animationName.c_str() );
941     }
942   }
943   else
944   {
945     DALI_SCRIPT_WARNING( "Request for Animation called '%s' failed (no animation section)\n", animationName.c_str() );
946   }
947
948   return anim;
949 }
950
951 Animation Builder::CreateAnimation( const std::string& animationName, const Property::Map& map, Dali::Actor sourceActor )
952 {
953   Replacement replacement(map, mReplacementMap);
954   return CreateAnimation( animationName, replacement, sourceActor);
955 }
956
957 Animation Builder::CreateAnimation( const std::string& animationName, const Property::Map& map )
958 {
959   Replacement replacement(map, mReplacementMap);
960   return CreateAnimation( animationName, replacement, Stage::GetCurrent().GetRootLayer() );
961 }
962
963 Animation Builder::CreateAnimation( const std::string& animationName, Dali::Actor sourceActor )
964 {
965   Replacement replacement( mReplacementMap );
966
967   return CreateAnimation( animationName, replacement, sourceActor );
968 }
969
970 Animation Builder::CreateAnimation( const std::string& animationName )
971 {
972   Replacement replacement( mReplacementMap );
973
974   return CreateAnimation( animationName, replacement, Dali::Stage::GetCurrent().GetRootLayer() );
975 }
976
977 bool Builder::ConvertChildValue( const TreeNode& mappingRoot, KeyStack& keyStack, Property::Value& child )
978 {
979   bool result = false;
980
981   switch( child.GetType() )
982   {
983     case Property::STRING:
984     {
985       std::string value;
986       if( child.Get( value ) )
987       {
988         std::string key;
989         if( GetMappingKey( value, key ) )
990         {
991           // Check key for cycles:
992           result=true;
993           for( KeyStack::iterator iter = keyStack.begin() ; iter != keyStack.end(); ++iter )
994           {
995             if( key.compare(*iter) == 0 )
996             {
997               // key is already in stack; stop.
998               DALI_LOG_WARNING("Detected cycle in stylesheet mapping table:%s\n", key.c_str());
999               child = Property::Value("");
1000               result=false;
1001               break;
1002             }
1003           }
1004
1005           if( result )
1006           {
1007             // The following call will overwrite the child with the value
1008             // from the mapping.
1009             RecursePropertyMap( mappingRoot, keyStack, key.c_str(), Property::NONE, child );
1010             result = true;
1011           }
1012         }
1013       }
1014       break;
1015     }
1016
1017     case Property::MAP:
1018     {
1019       Property::Map* map = child.GetMap();
1020       for( Property::Map::SizeType i=0; i < map->Count(); ++i )
1021       {
1022         Property::Value& child = map->GetValue(i);
1023         ConvertChildValue(mappingRoot, keyStack, child);
1024       }
1025       break;
1026     }
1027
1028     case Property::ARRAY:
1029     {
1030       Property::Array* array = child.GetArray();
1031       for( Property::Array::SizeType i=0; i < array->Count(); ++i )
1032       {
1033         Property::Value& child = array->GetElementAt(i);
1034         ConvertChildValue(mappingRoot, keyStack, child);
1035       }
1036       break;
1037     }
1038
1039     default:
1040       // Ignore other types.
1041       break;
1042   }
1043
1044   return result;
1045 }
1046
1047 bool Builder::RecursePropertyMap( const TreeNode& mappingRoot, KeyStack& keyStack, const char* theKey, Property::Type propertyType, Property::Value& value )
1048 {
1049   Replacement replacer( mReplacementMap );
1050   bool result = false;
1051
1052   keyStack.push_back( theKey );
1053
1054   for( TreeNode::ConstIterator iter = mappingRoot.CBegin(); iter != mappingRoot.CEnd(); ++iter )
1055   {
1056     std::string aKey( (*iter).first );
1057     if( aKey.compare( theKey ) == 0 )
1058     {
1059       if( propertyType == Property::NONE )
1060       {
1061         DeterminePropertyFromNode( (*iter).second, value, replacer );
1062         result = true;
1063       }
1064       else
1065       {
1066         result = DeterminePropertyFromNode( (*iter).second, propertyType, value, replacer );
1067       }
1068
1069       if( result )
1070       {
1071         ConvertChildValue(mappingRoot, keyStack, value);
1072       }
1073       break;
1074     }
1075   }
1076   keyStack.pop_back();
1077
1078   return result;
1079 }
1080
1081
1082 bool Builder::GetPropertyMap( const TreeNode& mappingRoot, const char* theKey, Property::Type propertyType, Property::Value& value )
1083 {
1084   KeyStack keyStack;
1085   return RecursePropertyMap( mappingRoot, keyStack, theKey, propertyType, value );
1086 }
1087
1088
1089 void Builder::LoadFromString( std::string const& data, Dali::Toolkit::Builder::UIFormat format )
1090 {
1091   // parser to get constants and includes only
1092   Dali::Toolkit::JsonParser parser = Dali::Toolkit::JsonParser::New();
1093
1094   if( !parser.Parse( data ) )
1095   {
1096     DALI_LOG_WARNING( "JSON Parse Error:%d:%d:'%s'\n",
1097                       parser.GetErrorLineNumber(),
1098                       parser.GetErrorColumn(),
1099                       parser.GetErrorDescription().c_str() );
1100
1101     DALI_ASSERT_ALWAYS(!"Cannot parse JSON");
1102   }
1103   else
1104   {
1105     // load constant map (allows the user to override the constants in the json after loading)
1106     LoadConstants( *parser.GetRoot(), mReplacementMap );
1107
1108     // merge includes
1109     if( OptionalChild includes = IsChild(*parser.GetRoot(), KEYNAME_INCLUDES) )
1110     {
1111       Replacement replacer( mReplacementMap );
1112
1113       for(TreeNode::ConstIterator iter = (*includes).CBegin(); iter != (*includes).CEnd(); ++iter)
1114       {
1115         OptionalString filename = replacer.IsString( (*iter).second );
1116
1117         if( filename )
1118         {
1119 #if defined(DEBUG_ENABLED)
1120           DALI_SCRIPT_VERBOSE("Loading Include '%s'\n", (*filename).c_str());
1121 #endif
1122           LoadFromString( GetFileContents(*filename) );
1123         }
1124       }
1125     }
1126
1127     if( !mParser.Parse( data ) )
1128     {
1129       DALI_LOG_WARNING( "JSON Parse Error:%d:%d:'%s'\n",
1130                         mParser.GetErrorLineNumber(),
1131                         mParser.GetErrorColumn(),
1132                         mParser.GetErrorDescription().c_str() );
1133
1134       DALI_ASSERT_ALWAYS(!"Cannot parse JSON");
1135     }
1136   }
1137
1138   DUMP_PARSE_TREE(parser); // This macro only writes out if DEBUG is enabled and the "DUMP_TREE" constant is defined in the stylesheet.
1139   DUMP_TEST_MAPPINGS(parser);
1140
1141   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Cannot parse JSON");
1142 }
1143
1144 void Builder::AddConstants( const Property::Map& map )
1145 {
1146   mReplacementMap.Merge( map );
1147 }
1148
1149 void Builder::AddConstant( const std::string& key, const Property::Value& value )
1150 {
1151   mReplacementMap[key] = value;
1152 }
1153
1154 const Property::Map& Builder::GetConstants() const
1155 {
1156   return mReplacementMap;
1157 }
1158
1159 const Property::Value& Builder::GetConstant( const std::string& key ) const
1160 {
1161   Property::Value* match = mReplacementMap.Find( key );
1162   if( match )
1163   {
1164     return (*match);
1165   }
1166   else
1167   {
1168     static Property::Value invalid;
1169     return invalid;
1170   }
1171 }
1172
1173 void Builder::LoadConstants( const TreeNode& root, Property::Map& intoMap )
1174 {
1175   Replacement replacer(intoMap);
1176
1177   if( OptionalChild constants = IsChild(root, "constants") )
1178   {
1179     for(TreeNode::ConstIterator iter = (*constants).CBegin();
1180         iter != (*constants).CEnd(); ++iter)
1181     {
1182       Dali::Property::Value property;
1183       if( (*iter).second.GetName() )
1184       {
1185 #if defined(DEBUG_ENABLED)
1186         DALI_SCRIPT_VERBOSE("Constant set from json '%s'\n", (*iter).second.GetName());
1187 #endif
1188         DeterminePropertyFromNode( (*iter).second, property, replacer );
1189         intoMap[ (*iter).second.GetName() ] = property;
1190       }
1191     }
1192   }
1193
1194 #if defined(DEBUG_ENABLED)
1195   Property::Value* iter = intoMap.Find( "CONFIG_SCRIPT_LOG_LEVEL" );
1196   if( iter && iter->GetType() == Property::STRING )
1197   {
1198     std::string logLevel( iter->Get< std::string >() );
1199     if( logLevel == "NoLogging" )
1200     {
1201       gFilterScript->SetLogLevel( Integration::Log::NoLogging );
1202     }
1203     else if( logLevel == "Concise" )
1204     {
1205       gFilterScript->SetLogLevel( Integration::Log::Concise );
1206     }
1207     else if( logLevel == "General" )
1208     {
1209       gFilterScript->SetLogLevel( Integration::Log::General );
1210     }
1211     else if( logLevel == "Verbose" )
1212     {
1213       gFilterScript->SetLogLevel( Integration::Log::Verbose );
1214     }
1215   }
1216 #endif
1217
1218 }
1219
1220 bool Builder::ApplyStyle( const std::string& styleName, Handle& handle )
1221 {
1222   Replacement replacer( mReplacementMap );
1223   return ApplyStyle( styleName, handle, replacer );
1224 }
1225
1226 bool Builder::ApplyStyle( const std::string& styleName, Handle& handle, const Replacement& replacement )
1227 {
1228   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
1229
1230   OptionalChild styles = IsChild( *mParser.GetRoot(), KEYNAME_STYLES );
1231   OptionalChild style  = IsChild( *styles, styleName );
1232
1233   if( styles && style )
1234   {
1235     ApplyAllStyleProperties( *mParser.GetRoot(), *style, handle, replacement );
1236     return true;
1237   }
1238   else
1239   {
1240     return false;
1241   }
1242 }
1243
1244 BaseHandle Builder::Create( const std::string& templateName, const Property::Map& map )
1245 {
1246   Replacement replacement( map, mReplacementMap );
1247   return Create( templateName, replacement );
1248 }
1249
1250 BaseHandle Builder::Create( const std::string& templateName, const Replacement& constant )
1251 {
1252   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
1253
1254   BaseHandle baseHandle;
1255
1256   OptionalChild templates = IsChild(*mParser.GetRoot(), KEYNAME_TEMPLATES);
1257
1258   if( !templates )
1259   {
1260     DALI_SCRIPT_WARNING("No template section found to CreateFromTemplate\n");
1261   }
1262   else
1263   {
1264     OptionalChild childTemplate = IsChild(*templates, templateName);
1265     if(!childTemplate)
1266     {
1267       DALI_SCRIPT_WARNING("Template '%s' does not exist in template section\n", templateName.c_str());
1268     }
1269     else
1270     {
1271       OptionalString type = constant.IsString( IsChild(*childTemplate, KEYNAME_TYPE) );
1272
1273       if(!type)
1274       {
1275         DALI_SCRIPT_WARNING("Cannot create template '%s' as template section is missing 'type'\n", templateName.c_str());
1276       }
1277       else
1278       {
1279         baseHandle = DoCreate( *mParser.GetRoot(), *childTemplate, Actor(), constant );
1280       }
1281     }
1282   }
1283
1284   return baseHandle;
1285 }
1286
1287 BaseHandle Builder::CreateFromJson( const std::string& json )
1288 {
1289   BaseHandle ret;
1290
1291   // merge in new template, hoping no one else has one named '@temp@'
1292   std::string newTemplate =
1293     std::string("{\"templates\":{\"@temp@\":") +                      \
1294     json +                                                            \
1295     std::string("}}");
1296
1297   if( mParser.Parse(newTemplate) )
1298   {
1299     Replacement replacement( mReplacementMap );
1300     ret = Create( "@temp@", replacement );
1301   }
1302
1303   return ret;
1304 }
1305
1306 bool Builder::ApplyFromJson(  Handle& handle, const std::string& json )
1307 {
1308   bool ret = false;
1309
1310   // merge new style, hoping no one else has one named '@temp@'
1311   std::string newStyle =
1312     std::string("{\"styles\":{\"@temp@\":") +                           \
1313     json +                                                              \
1314     std::string("}}");
1315
1316   if( mParser.Parse(newStyle) )
1317   {
1318     Replacement replacement( mReplacementMap );
1319     ret = ApplyStyle( "@temp@", handle, replacement );
1320   }
1321
1322   return ret;
1323 }
1324
1325
1326 BaseHandle Builder::Create( const std::string& templateName )
1327 {
1328   Replacement replacement( mReplacementMap );
1329   return Create( templateName, replacement );
1330 }
1331
1332 Builder::Builder()
1333 : mSlotDelegate( this )
1334 {
1335   mParser = Dali::Toolkit::JsonParser::New();
1336
1337   Property::Map defaultDirs;
1338   defaultDirs[ TOKEN_STRING(DALI_IMAGE_DIR) ]       = DALI_IMAGE_DIR;
1339   defaultDirs[ TOKEN_STRING(DALI_SOUND_DIR) ]       = DALI_SOUND_DIR;
1340   defaultDirs[ TOKEN_STRING(DALI_STYLE_DIR) ]       = DALI_STYLE_DIR;
1341   defaultDirs[ TOKEN_STRING(DALI_STYLE_IMAGE_DIR) ] = DALI_STYLE_IMAGE_DIR;
1342
1343   AddConstants( defaultDirs );
1344 }
1345
1346 Builder::~Builder()
1347 {
1348 }
1349
1350 } // namespace Internal
1351
1352 } // namespace Toolkit
1353
1354 } // namespace Dali