Merge remote-tracking branch 'origin/tizen' into new_text
[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         RenderableActor actor = RenderableActor::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         RenderableActor actor = RenderableActor::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         // TEMP: Assume all script created actors are not using size negotiation for now
538         actor.SetRelayoutEnabled( false );
539
540         // add children of all the styles
541         if( OptionalChild actors = IsChild( node, KEYNAME_ACTORS ) )
542         {
543           for( TreeConstIter iter = (*actors).CBegin(); iter != (*actors).CEnd(); ++iter )
544           {
545             DoCreate( root, (*iter).second, actor, replacements );
546           }
547         }
548
549         // apply style on top as they need the children to exist
550         ApplyAllStyleProperties( root, node, actor, replacements );
551
552         // then add to parent
553         if( parent )
554         {
555           parent.Add( actor );
556         }
557       }
558       else
559       {
560         ApplyProperties( root, node, handle, replacements );
561       }
562     }
563     else
564     {
565       DALI_SCRIPT_WARNING("Cannot create handle from type '%s'\n", typeInfo.GetName().c_str());
566     }
567   }
568
569   return baseHandle;
570 }
571
572 void Builder::SetupTask( RenderTask& task, const TreeNode& node, const Replacement& constant )
573 {
574   const Stage& stage = Stage::GetCurrent();
575   Layer root  = stage.GetRootLayer();
576
577   if( OptionalString s = constant.IsString( IsChild(node, "source-actor") ) )
578   {
579     Actor actor = root.FindChildByName(*s);
580     if(actor)
581     {
582       task.SetSourceActor( actor );
583     }
584     else
585     {
586       DALI_SCRIPT_WARNING("Cannot find source actor on stage for render task called '%s'\n", (*s).c_str() );
587     }
588   }
589
590   if( OptionalString s = constant.IsString( IsChild(node, "camera-actor") ) )
591   {
592     CameraActor actor = CameraActor::DownCast( root.FindChildByName(*s) );
593     if(actor)
594     {
595       task.SetCameraActor( actor );
596     }
597     else
598     {
599       DALI_SCRIPT_WARNING("Cannot find camera actor on stage for render task called '%s'\n", (*s).c_str() );
600     }
601   }
602
603   if( OptionalString s = constant.IsString( IsChild(node, "target-frame-buffer") ) )
604   {
605     FrameBufferImage fb = GetFrameBufferImage( *s, constant );
606     if(fb)
607     {
608       task.SetTargetFrameBuffer( fb );
609     }
610     else
611     {
612       DALI_SCRIPT_WARNING("Cannot find target frame buffer '%s'\n", (*s).c_str() );
613     }
614   }
615
616   if( OptionalString s = constant.IsString( IsChild(node, "screen-to-frame-buffer-function") ) )
617   {
618     if("DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION" == *s)
619     {
620       task.SetScreenToFrameBufferFunction( RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION );
621     }
622     else if("FULLSCREEN_FRAMEBUFFER_FUNCTION" == *s)
623     {
624       task.SetScreenToFrameBufferFunction( RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION );
625     }
626     else
627     {
628       DALI_SCRIPT_WARNING("todo");
629     }
630   }
631
632   // other setup is via the property system
633   SetProperties( node, task, constant ); // @ todo, remove 'source-actor', 'camera-actor'?
634
635 }
636
637 void Builder::CreateRenderTask( const std::string &name )
638 {
639   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
640
641   Replacement constant(mReplacementMap);
642
643   const Stage& stage = Stage::GetCurrent();
644
645   OptionalChild tasks = IsChild(*mParser.GetRoot(), "render-tasks");
646
647   if(tasks)
648   {
649     //
650     // Create the tasks from the current task as generally we want
651     // to setup task zero and onwards. Although this does overwrite
652     // the properties of the current task.
653     //
654     if( OptionalChild renderTask = IsChild(*tasks, name ) )
655     {
656       RenderTaskList list = stage.GetRenderTaskList();
657       unsigned int start = list.GetTaskCount();
658
659       RenderTask task;
660       if(0 == start)
661       {
662         // zero should have already been created by the stage so really
663         // this case should never happen
664         task = list.CreateTask();
665         start++;
666       }
667
668       TreeNode::ConstIterator iter = (*renderTask).CBegin();
669       task = list.GetTask( start - 1 );
670
671       SetupTask( task, (*iter).second, constant  );
672
673       ++iter;
674
675       for(; iter != (*renderTask).CEnd(); ++iter )
676       {
677         task = list.CreateTask();
678         SetupTask( task, (*iter).second, constant );
679       }
680     }
681   }
682 }
683
684 ShaderEffect Builder::GetShaderEffect( const std::string &name)
685 {
686   Replacement constant( mReplacementMap );
687   return GetShaderEffect( name, constant );
688 }
689
690 ShaderEffect Builder::GetShaderEffect( const std::string &name, const Replacement& constant )
691 {
692   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
693
694   ShaderEffect ret;
695
696   ShaderEffectLut::const_iterator iter( mShaderEffectLut.find( name ) );
697   if( iter != mShaderEffectLut.end() )
698   {
699     ret = iter->second;
700   }
701   else
702   {
703     if( OptionalChild effects = IsChild( *mParser.GetRoot(), "shader-effects") )
704     {
705       if( OptionalChild effect = IsChild( *effects, name ) )
706       {
707         Dali::Property::Value propertyMap(Property::MAP);
708         if( SetPropertyFromNode( *effect, Property::MAP, propertyMap, constant ) )
709         {
710           ret = Dali::Scripting::NewShaderEffect( propertyMap );
711           mShaderEffectLut[ name ] = ret;
712         }
713       }
714     }
715   }
716
717   return ret;
718 }
719
720 FrameBufferImage Builder::GetFrameBufferImage( const std::string &name )
721 {
722   Replacement constant( mReplacementMap );
723   return GetFrameBufferImage(name, constant);
724 }
725
726 FrameBufferImage Builder::GetFrameBufferImage( const std::string &name, const Replacement& constant )
727 {
728   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
729
730   FrameBufferImage ret;
731
732   ImageLut::const_iterator iter( mFrameBufferImageLut.find( name ) );
733   if( iter != mFrameBufferImageLut.end() )
734   {
735     ret = iter->second;
736   }
737   else
738   {
739     if( OptionalChild images = IsChild( *mParser.GetRoot(), "frame-buffer-images") )
740     {
741       if( OptionalChild image = IsChild( *images, name ) )
742       {
743         Dali::Property::Value propertyMap(Property::MAP);
744         if( SetPropertyFromNode( *image, Property::MAP, propertyMap, constant ) )
745         {
746           propertyMap.SetValue(KEYNAME_TYPE, Property::Value(std::string("FrameBufferImage")));
747           ret = FrameBufferImage::DownCast( Dali::Scripting::NewImage( propertyMap ) );
748           mFrameBufferImageLut[ name ] = ret;
749         }
750       }
751     }
752   }
753
754   return ret;
755 }
756
757 Path Builder::GetPath( const std::string& name )
758 {
759   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
760
761   Path ret;
762
763   PathLut::const_iterator iter( mPathLut.find( name ) );
764   if( iter != mPathLut.end() )
765   {
766     ret = iter->second;
767   }
768   else
769   {
770     if( OptionalChild paths = IsChild( *mParser.GetRoot(), "paths") )
771     {
772       if( OptionalChild path = IsChild( *paths, name ) )
773       {
774         //points property
775         if( OptionalChild pointsProperty = IsChild( *path, "points") )
776         {
777           Dali::Property::Value points(Property::ARRAY);
778           if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
779           {
780             ret = Path::New();
781             ret.SetProperty( Path::Property::POINTS, points);
782
783             //control-points property
784             if( OptionalChild pointsProperty = IsChild( *path, "control-points") )
785             {
786               Dali::Property::Value points(Property::ARRAY);
787               if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
788               {
789                 ret.SetProperty( Path::Property::CONTROL_POINTS, points);
790               }
791             }
792             else
793             {
794               //Curvature
795               float curvature(0.25f);
796               if( OptionalFloat pointsProperty = IsFloat( *path, "curvature") )
797               {
798                 curvature = *pointsProperty;
799               }
800               ret.GenerateControlPoints(curvature);
801             }
802
803             //Add the new path to the hash table for paths
804             mPathLut[ name ] = ret;
805           }
806         }
807         else
808         {
809           //Interpolation points not specified
810           DALI_SCRIPT_WARNING("Interpolation points not specified for path '%s'\n", name.c_str() );
811         }
812       }
813
814     }
815   }
816
817   return ret;
818 }
819
820 Toolkit::Builder::BuilderSignalType& Builder::QuitSignal()
821 {
822   return mQuitSignal;
823 }
824
825 void Builder::EmitQuitSignal()
826 {
827   mQuitSignal.Emit();
828 }
829
830 void Builder::AddActors( Actor toActor )
831 {
832   // 'stage' is the default/by convention section to add from
833   AddActors( "stage", toActor );
834 }
835
836 void Builder::AddActors( const std::string &sectionName, Actor toActor )
837 {
838   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
839
840   Property::Map overrideMap;
841   Replacement replacements(overrideMap, mReplacementMap);
842
843   OptionalChild add = IsChild(*mParser.GetRoot(), sectionName);
844
845   if( add )
846   {
847     for( TreeNode::ConstIterator iter = (*add).CBegin(); iter != (*add).CEnd(); ++iter )
848     {
849       // empty actor adds directly to the stage
850       BaseHandle baseHandle = DoCreate( *mParser.GetRoot(), (*iter).second, Actor(), replacements );
851       Actor actor = Actor::DownCast(baseHandle);
852       if(actor)
853       {
854         toActor.Add( actor );
855       }
856     }
857
858     // if were adding the 'stage' section then also check for a render task called stage
859     // to add automatically
860     if( "stage" == sectionName )
861     {
862       if( OptionalChild renderTasks = IsChild(*mParser.GetRoot(), "render-tasks") )
863       {
864         if( OptionalChild tasks = IsChild(*renderTasks, "stage") )
865         {
866           CreateRenderTask( "stage" );
867         }
868       }
869     }
870   }
871 }
872
873 Animation Builder::CreateAnimation( const std::string& animationName, const Replacement& replacement, Dali::Actor sourceActor )
874 {
875   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
876
877   Animation anim;
878
879   if( OptionalChild animations = IsChild(*mParser.GetRoot(), "animations") )
880   {
881     if( OptionalChild animation = IsChild(*animations, animationName) )
882     {
883       anim = Dali::Toolkit::Internal::CreateAnimation( *animation, replacement, sourceActor, this );
884     }
885     else
886     {
887       DALI_SCRIPT_WARNING( "Request for Animation called '%s' failed\n", animationName.c_str() );
888     }
889   }
890   else
891   {
892     DALI_SCRIPT_WARNING( "Request for Animation called '%s' failed (no animation section)\n", animationName.c_str() );
893   }
894
895   return anim;
896 }
897
898 Animation Builder::CreateAnimation( const std::string& animationName, const Property::Map& map, Dali::Actor sourceActor )
899 {
900   Replacement replacement(map, mReplacementMap);
901   return CreateAnimation( animationName, replacement, sourceActor);
902 }
903
904 Animation Builder::CreateAnimation( const std::string& animationName, const Property::Map& map )
905 {
906   Replacement replacement(map, mReplacementMap);
907   return CreateAnimation( animationName, replacement, Stage::GetCurrent().GetRootLayer() );
908 }
909
910 Animation Builder::CreateAnimation( const std::string& animationName, Dali::Actor sourceActor )
911 {
912   Replacement replacement( mReplacementMap );
913
914   return CreateAnimation( animationName, replacement, sourceActor );
915 }
916
917 Animation Builder::CreateAnimation( const std::string& animationName )
918 {
919   Replacement replacement( mReplacementMap );
920
921   return CreateAnimation( animationName, replacement, Dali::Stage::GetCurrent().GetRootLayer() );
922 }
923
924 void Builder::LoadFromString( std::string const& data, Dali::Toolkit::Builder::UIFormat format )
925 {
926   // parser to get constants and includes only
927   Dali::Toolkit::JsonParser parser = Dali::Toolkit::JsonParser::New();
928
929   if( !parser.Parse( data ) )
930   {
931     DALI_LOG_WARNING( "JSON Parse Error:%d:%d:'%s'\n",
932                       parser.GetErrorLineNumber(),
933                       parser.GetErrorColumn(),
934                       parser.GetErrorDescription().c_str() );
935
936     DALI_ASSERT_ALWAYS(!"Cannot parse JSON");
937
938   }
939   else
940   {
941     // load constant map (allows the user to override the constants in the json after loading)
942     LoadConstants( *parser.GetRoot(), mReplacementMap );
943
944     // merge includes
945     if( OptionalChild includes = IsChild(*parser.GetRoot(), KEYNAME_INCLUDES) )
946     {
947       Replacement replacer( mReplacementMap );
948
949       for(TreeNode::ConstIterator iter = (*includes).CBegin(); iter != (*includes).CEnd(); ++iter)
950       {
951         OptionalString filename = replacer.IsString( (*iter).second );
952
953         if( filename )
954         {
955 #if defined(DEBUG_ENABLED)
956           DALI_SCRIPT_VERBOSE("Loading Include '%s'\n", (*filename).c_str());
957 #endif
958           LoadFromString( GetFileContents(*filename) );
959         }
960       }
961     }
962
963     if( !mParser.Parse( data ) )
964     {
965       DALI_LOG_WARNING( "JSON Parse Error:%d:%d:'%s'\n",
966                         mParser.GetErrorLineNumber(),
967                         mParser.GetErrorColumn(),
968                         mParser.GetErrorDescription().c_str() );
969
970       DALI_ASSERT_ALWAYS(!"Cannot parse JSON");
971     }
972   }
973
974   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Cannot parse JSON");
975
976 }
977
978 void Builder::AddConstants( const Property::Map& map )
979 {
980   mReplacementMap.Merge( map );
981 }
982
983 void Builder::AddConstant( const std::string& key, const Property::Value& value )
984 {
985   mReplacementMap[key] = value;
986 }
987
988 const Property::Map& Builder::GetConstants() const
989 {
990   return mReplacementMap;
991 }
992
993 const Property::Value& Builder::GetConstant( const std::string& key ) const
994 {
995   Property::Value* match = mReplacementMap.Find( key );
996   if( match )
997   {
998     return (*match);
999   }
1000   else
1001   {
1002     static Property::Value invalid;
1003     return invalid;
1004   }
1005 }
1006
1007 void Builder::LoadConstants( const TreeNode& root, Property::Map& intoMap )
1008 {
1009   Replacement replacer(intoMap);
1010
1011   if( OptionalChild constants = IsChild(root, "constants") )
1012   {
1013     for(TreeNode::ConstIterator iter = (*constants).CBegin();
1014         iter != (*constants).CEnd(); ++iter)
1015     {
1016       Dali::Property::Value property;
1017       if( (*iter).second.GetName() )
1018       {
1019 #if defined(DEBUG_ENABLED)
1020         DALI_SCRIPT_VERBOSE("Constant set from json '%s'\n", (*iter).second.GetName());
1021 #endif
1022         if( SetPropertyFromNode( (*iter).second, property, replacer ) )
1023         {
1024           intoMap[ (*iter).second.GetName() ] = property;
1025         }
1026         else
1027         {
1028           DALI_SCRIPT_WARNING("Cannot convert property for constant %s\n",
1029                               (*iter).second.GetName() == NULL ? "no name?" : (*iter).second.GetName());
1030         }
1031       }
1032     }
1033   }
1034
1035 #if defined(DEBUG_ENABLED)
1036   Property::Value* iter = intoMap.Find( "CONFIG_SCRIPT_LOG_LEVEL" );
1037   if( iter && iter->GetType() == Property::STRING )
1038   {
1039     std::string logLevel( iter->Get< std::string >() );
1040     if( logLevel == "NoLogging" )
1041     {
1042       gFilterScript->SetLogLevel( Integration::Log::NoLogging );
1043     }
1044     else if( logLevel == "Concise" )
1045     {
1046       gFilterScript->SetLogLevel( Integration::Log::Concise );
1047     }
1048     else if( logLevel == "General" )
1049     {
1050       gFilterScript->SetLogLevel( Integration::Log::General );
1051     }
1052     else if( logLevel == "Verbose" )
1053     {
1054       gFilterScript->SetLogLevel( Integration::Log::Verbose );
1055     }
1056   }
1057 #endif
1058
1059 }
1060
1061 bool Builder::ApplyStyle( const std::string& styleName, Handle& handle )
1062 {
1063   Replacement replacer( mReplacementMap );
1064   return ApplyStyle( styleName, handle, replacer );
1065 }
1066
1067 bool Builder::ApplyStyle( const std::string& styleName, Handle& handle, const Replacement& replacement )
1068 {
1069   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
1070
1071   OptionalChild styles = IsChild( *mParser.GetRoot(), KEYNAME_STYLES );
1072   OptionalChild style  = IsChild( *styles, styleName );
1073
1074   if( styles && style )
1075   {
1076     ApplyAllStyleProperties( *mParser.GetRoot(), *style, handle, replacement );
1077     return true;
1078   }
1079   else
1080   {
1081     return false;
1082   }
1083 }
1084
1085 BaseHandle Builder::Create( const std::string& templateName, const Property::Map& map )
1086 {
1087   Replacement replacement( map, mReplacementMap );
1088   return Create( templateName, replacement );
1089 }
1090
1091 BaseHandle Builder::Create( const std::string& templateName, const Replacement& constant )
1092 {
1093   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
1094
1095   BaseHandle baseHandle;
1096
1097   OptionalChild templates = IsChild(*mParser.GetRoot(), KEYNAME_TEMPLATES);
1098
1099   if( !templates )
1100   {
1101     DALI_SCRIPT_WARNING("No template section found to CreateFromTemplate\n");
1102   }
1103   else
1104   {
1105     OptionalChild childTemplate = IsChild(*templates, templateName);
1106     if(!childTemplate)
1107     {
1108       DALI_SCRIPT_WARNING("Template '%s' does not exist in template section\n", templateName.c_str());
1109     }
1110     else
1111     {
1112       OptionalString type = constant.IsString( IsChild(*childTemplate, KEYNAME_TYPE) );
1113
1114       if(!type)
1115       {
1116         DALI_SCRIPT_WARNING("Cannot create template '%s' as template section is missing 'type'\n", templateName.c_str());
1117       }
1118       else
1119       {
1120         baseHandle = DoCreate( *mParser.GetRoot(), *childTemplate, Actor(), constant );
1121       }
1122     }
1123   }
1124
1125   return baseHandle;
1126 }
1127
1128 BaseHandle Builder::CreateFromJson( const std::string& json )
1129 {
1130   BaseHandle ret;
1131
1132   // merge in new template, hoping no one else has one named '@temp@'
1133   std::string newTemplate =
1134     std::string("{\"templates\":{\"@temp@\":") +                      \
1135     json +                                                            \
1136     std::string("}}");
1137
1138   if( mParser.Parse(newTemplate) )
1139   {
1140     Replacement replacement( mReplacementMap );
1141     ret = Create( "@temp@", replacement );
1142   }
1143
1144   return ret;
1145 }
1146
1147 bool Builder::ApplyFromJson(  Handle& handle, const std::string& json )
1148 {
1149   bool ret = false;
1150
1151   // merge new style, hoping no one else has one named '@temp@'
1152   std::string newStyle =
1153     std::string("{\"styles\":{\"@temp@\":") +                           \
1154     json +                                                              \
1155     std::string("}}");
1156
1157   if( mParser.Parse(newStyle) )
1158   {
1159     Replacement replacement( mReplacementMap );
1160     ret = ApplyStyle( "@temp@", handle, replacement );
1161   }
1162
1163   return ret;
1164 }
1165
1166
1167 BaseHandle Builder::Create( const std::string& templateName )
1168 {
1169   Replacement replacement( mReplacementMap );
1170   return Create( templateName, replacement );
1171 }
1172
1173 Builder::Builder()
1174 : mSlotDelegate( this )
1175 {
1176   mParser = Dali::Toolkit::JsonParser::New();
1177 }
1178
1179 Builder::~Builder()
1180 {
1181 }
1182
1183 } // namespace Internal
1184
1185 } // namespace Toolkit
1186
1187 } // namespace Dali