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