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