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