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