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