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