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