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