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