Include required header files directly rather than through dali.h
[platform/core/uifw/dali-toolkit.git] / base / 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 );
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);
53 extern Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function<void (void)> quitAction);
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 );
359       SetupPropertyNotification( mSlotDelegate.GetConnectionTracker(), root, node, actor, quitAction );
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 Toolkit::Builder::Signal& Builder::QuitSignal()
749 {
750   return mQuitSignal;
751 }
752
753 void Builder::EmitQuitSignal()
754 {
755   mQuitSignal.Emit();
756 }
757
758 void Builder::AddActors( Actor toActor )
759 {
760   // 'stage' is the default/by convention section to add from
761   AddActors( "stage", toActor );
762 }
763
764 void Builder::AddActors( const std::string &sectionName, Actor toActor )
765 {
766   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
767
768   Property::Map overrideMap;
769   Replacement replacements(overrideMap, mReplacementMap);
770
771   OptionalChild add = IsChild(*mParser.GetRoot(), sectionName);
772
773   if( add )
774   {
775     for( TreeNode::ConstIterator iter = (*add).CBegin(); iter != (*add).CEnd(); ++iter )
776     {
777       // empty actor adds directly to the stage
778       BaseHandle baseHandle = DoCreate( *mParser.GetRoot(), (*iter).second, Actor(), replacements );
779       Actor actor = Actor::DownCast(baseHandle);
780       if(actor)
781       {
782         toActor.Add( actor );
783       }
784     }
785
786     // if were adding the 'stage' section then also check for a render task called stage
787     // to add automatically
788     if( "stage" == sectionName )
789     {
790       if( OptionalChild renderTasks = IsChild(*mParser.GetRoot(), "render-tasks") )
791       {
792         if( OptionalChild tasks = IsChild(*renderTasks, "stage") )
793         {
794           CreateRenderTask( "stage" );
795         }
796       }
797     }
798   }
799 }
800
801 Animation Builder::CreateAnimation( const std::string& animationName, const Replacement& replacement, Dali::Actor sourceActor )
802 {
803   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
804
805   Animation anim;
806
807   if( OptionalChild animations = IsChild(*mParser.GetRoot(), "animations") )
808   {
809     if( OptionalChild animation = IsChild(*animations, animationName) )
810     {
811       anim = Dali::Toolkit::Internal::CreateAnimation( *animation, replacement, sourceActor );
812     }
813     else
814     {
815       DALI_SCRIPT_WARNING( "Request for Animation called '%s' failed\n", animationName.c_str() );
816     }
817   }
818   else
819   {
820     DALI_SCRIPT_WARNING( "Request for Animation called '%s' failed (no animation section)\n", animationName.c_str() );
821   }
822
823   return anim;
824 }
825
826 Animation Builder::CreateAnimation( const std::string& animationName, const Property::Map& map, Dali::Actor sourceActor )
827 {
828   Replacement replacement(map, mReplacementMap);
829   return CreateAnimation( animationName, replacement, sourceActor);
830 }
831
832 Animation Builder::CreateAnimation( const std::string& animationName, const Property::Map& map )
833 {
834   Replacement replacement(map, mReplacementMap);
835   return CreateAnimation( animationName, replacement, Stage::GetCurrent().GetRootLayer() );
836 }
837
838 Animation Builder::CreateAnimation( const std::string& animationName, Dali::Actor sourceActor )
839 {
840   Replacement replacement( mReplacementMap );
841
842   return CreateAnimation( animationName, replacement, sourceActor );
843 }
844
845 Animation Builder::CreateAnimation( const std::string& animationName )
846 {
847   Replacement replacement( mReplacementMap );
848
849   return CreateAnimation( animationName, replacement, Dali::Stage::GetCurrent().GetRootLayer() );
850 }
851
852 void Builder::LoadFromString( std::string const& data, Dali::Toolkit::Builder::UIFormat format )
853 {
854   DALI_ASSERT_ALWAYS( format == Dali::Toolkit::Builder::JSON && "Currently only JSON is supported" );
855
856   // parser to get constants and includes only
857   Dali::Toolkit::JsonParser parser = Dali::Toolkit::JsonParser::New();
858
859   if( !parser.Parse( data ) )
860   {
861     DALI_LOG_WARNING( "JSON Parse Error:%d:%d:'%s'\n",
862                       parser.GetErrorLineNumber(),
863                       parser.GetErrorColumn(),
864                       parser.GetErrorDescription().c_str() );
865
866     DALI_ASSERT_ALWAYS(!"Cannot parse JSON");
867
868   }
869   else
870   {
871     // load constant map (allows the user to override the constants in the json after loading)
872     LoadConstants( *parser.GetRoot(), mReplacementMap );
873
874     // merge includes
875     if( OptionalChild includes = IsChild(*parser.GetRoot(), KEYNAME_INCLUDES) )
876     {
877       Replacement replacer( mReplacementMap );
878
879       for(TreeNode::ConstIterator iter = (*includes).CBegin(); iter != (*includes).CEnd(); ++iter)
880       {
881         OptionalString filename = replacer.IsString( (*iter).second );
882
883         if( filename )
884         {
885 #if defined(DEBUG_ENABLED)
886           DALI_SCRIPT_VERBOSE("Loading Include '%s'\n", (*filename).c_str());
887 #endif
888           LoadFromString( GetFileContents(*filename) );
889         }
890       }
891     }
892
893     if( !mParser.Parse( data ) )
894     {
895       DALI_LOG_WARNING( "JSON Parse Error:%d:%d:'%s'\n",
896                         mParser.GetErrorLineNumber(),
897                         mParser.GetErrorColumn(),
898                         mParser.GetErrorDescription().c_str() );
899
900       DALI_ASSERT_ALWAYS(!"Cannot parse JSON");
901     }
902   }
903
904   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Cannot parse JSON");
905
906 }
907
908 void Builder::AddConstants( const Property::Map& map )
909 {
910   mReplacementMap.Merge( map );
911 }
912
913 void Builder::AddConstant( const std::string& key, const Property::Value& value )
914 {
915   mReplacementMap[key] = value;
916 }
917
918 const Property::Map& Builder::GetConstants() const
919 {
920   return mReplacementMap;
921 }
922
923 const Property::Value& Builder::GetConstant( const std::string& key ) const
924 {
925   Property::Value* match = mReplacementMap.Find( key );
926   if( match )
927   {
928     return (*match);
929   }
930   else
931   {
932     static Property::Value invalid;
933     return invalid;
934   }
935 }
936
937 void Builder::LoadConstants( const TreeNode& root, Property::Map& intoMap )
938 {
939   Replacement replacer(intoMap);
940
941   if( OptionalChild constants = IsChild(root, "constants") )
942   {
943     for(TreeNode::ConstIterator iter = (*constants).CBegin();
944         iter != (*constants).CEnd(); ++iter)
945     {
946       Dali::Property::Value property;
947       if( (*iter).second.GetName() )
948       {
949 #if defined(DEBUG_ENABLED)
950         DALI_SCRIPT_VERBOSE("Constant set from json '%s'\n", (*iter).second.GetName());
951 #endif
952         if( SetPropertyFromNode( (*iter).second, property, replacer ) )
953         {
954           intoMap[ (*iter).second.GetName() ] = property;
955         }
956         else
957         {
958           DALI_SCRIPT_WARNING("Cannot convert property for constant %s\n",
959                               (*iter).second.GetName() == NULL ? "no name?" : (*iter).second.GetName());
960         }
961       }
962     }
963   }
964
965 #if defined(DEBUG_ENABLED)
966   Property::Value* iter = intoMap.Find( "CONFIG_SCRIPT_LOG_LEVEL" );
967   if( iter && iter->GetType() == Property::STRING )
968   {
969     std::string logLevel( iter->Get< std::string >() );
970     if( logLevel == "NoLogging" )
971     {
972       gFilterScript->SetLogLevel( Integration::Log::NoLogging );
973     }
974     else if( logLevel == "Concise" )
975     {
976       gFilterScript->SetLogLevel( Integration::Log::Concise );
977     }
978     else if( logLevel == "General" )
979     {
980       gFilterScript->SetLogLevel( Integration::Log::General );
981     }
982     else if( logLevel == "Verbose" )
983     {
984       gFilterScript->SetLogLevel( Integration::Log::Verbose );
985     }
986   }
987 #endif
988
989 }
990
991 bool Builder::ApplyStyle( const std::string& styleName, Handle& handle )
992 {
993   Replacement replacer( mReplacementMap );
994   return ApplyStyle( styleName, handle, replacer );
995 }
996
997 bool Builder::ApplyStyle( const std::string& styleName, Handle& handle, const Replacement& replacement )
998 {
999   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
1000
1001   OptionalChild styles = IsChild( *mParser.GetRoot(), KEYNAME_STYLES );
1002   OptionalChild style  = IsChild( *styles, styleName );
1003
1004   if( styles && style )
1005   {
1006     ApplyAllStyleProperties( *mParser.GetRoot(), *style, handle, replacement );
1007     return true;
1008   }
1009   else
1010   {
1011     return false;
1012   }
1013 }
1014
1015 BaseHandle Builder::Create( const std::string& templateName, const Property::Map& map )
1016 {
1017   Replacement replacement( map, mReplacementMap );
1018   return Create( templateName, replacement );
1019 }
1020
1021 BaseHandle Builder::Create( const std::string& templateName, const Replacement& constant )
1022 {
1023   DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
1024
1025   BaseHandle baseHandle;
1026
1027   OptionalChild templates = IsChild(*mParser.GetRoot(), KEYNAME_TEMPLATES);
1028
1029   if( !templates )
1030   {
1031     DALI_SCRIPT_WARNING("No template section found to CreateFromTemplate\n");
1032   }
1033   else
1034   {
1035     OptionalChild childTemplate = IsChild(*templates, templateName);
1036     if(!childTemplate)
1037     {
1038       DALI_SCRIPT_WARNING("Template '%s' does not exist in template section\n", templateName.c_str());
1039     }
1040     else
1041     {
1042       OptionalString type = constant.IsString( IsChild(*childTemplate, KEYNAME_TYPE) );
1043
1044       if(!type)
1045       {
1046         DALI_SCRIPT_WARNING("Cannot create template '%s' as template section is missing 'type'\n", templateName.c_str());
1047       }
1048       else
1049       {
1050         baseHandle = DoCreate( *mParser.GetRoot(), *childTemplate, Actor(), constant );
1051       }
1052     }
1053   }
1054
1055   return baseHandle;
1056 }
1057
1058 BaseHandle Builder::CreateFromJson( const std::string& json )
1059 {
1060   BaseHandle ret;
1061
1062   // merge in new template, hoping no one else has one named '@temp@'
1063   std::string newTemplate =
1064     std::string("{\"templates\":{\"@temp@\":") +                      \
1065     json +                                                            \
1066     std::string("}}");
1067
1068   if( mParser.Parse(newTemplate) )
1069   {
1070     Replacement replacement( mReplacementMap );
1071     ret = Create( "@temp@", replacement );
1072   }
1073
1074   return ret;
1075 }
1076
1077 bool Builder::ApplyFromJson(  Handle& handle, const std::string& json )
1078 {
1079   bool ret = false;
1080
1081   // merge new style, hoping no one else has one named '@temp@'
1082   std::string newStyle =
1083     std::string("{\"styles\":{\"@temp@\":") +                           \
1084     json +                                                              \
1085     std::string("}}");
1086
1087   if( mParser.Parse(newStyle) )
1088   {
1089     Replacement replacement( mReplacementMap );
1090     ret = ApplyStyle( "@temp@", handle, replacement );
1091   }
1092
1093   return ret;
1094 }
1095
1096
1097 BaseHandle Builder::Create( const std::string& templateName )
1098 {
1099   Replacement replacement( mReplacementMap );
1100   return Create( templateName, replacement );
1101 }
1102
1103 Builder::Builder()
1104 : mSlotDelegate( this )
1105 {
1106   mParser = Dali::Toolkit::JsonParser::New();
1107 }
1108
1109 Builder::~Builder()
1110 {
1111 }
1112
1113 } // namespace Internal
1114
1115 } // namespace Toolkit
1116
1117 } // namespace Dali