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