2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 // http://floralicense.org/license/
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.
18 #include <dali-toolkit/internal/builder/builder-impl.h>
19 #include <dali-toolkit/internal/builder/builder-get-is.inl.h>
31 * Set a property value from a tree node.
32 * This function guesses the type of the property from the format of the string in the node.
33 * This is not always possible and could be surprising.
34 * @param node The node string to convert from
35 * @param value The property value to set
36 * @return true if the string could be converted.
38 bool SetPropertyFromNode( const TreeNode& node, Property::Value& value );
41 * Set a property value as the given type from a tree node.
42 * @param node The node string to convert from
43 * @param type The property type to convert to.
44 * @param value The property value to set
45 * @return true if the string could be converted to the correct type.
47 bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value );
50 * A property value type can be forced when its unknown by a disambiguation convention in the json
51 * ie "myarray": [1,2,3,4] ; would be a vector but
52 * "myarray": {'type-cast':'array', 'value':[1,2,3,4]} would be an array
53 * @param child The node whos string to search for a disambiguated type
54 * @param value The value to set
55 * @return True if child contained a disambiguated string that could be converted.
57 bool Disambiguated(const TreeNode& child, // ConstantLut& constantLut,
58 Dali::Property::Value& value)
60 OptionalString childType = IsString( IsChild(child, "type-cast") );
61 OptionalChild childValue = IsChild(child, "value");
63 if( childType && childValue && (2 == child.Size()) )
65 // this case allows disambiguation but normally the type is guessed
66 // 2 == child.count() is an extra check as the user could have a user dictionary/map with
67 // type-cast and value keys. If they do then a work around is to add a bogus key to not run this case.
68 if(*childType == "boolean")
70 return SetPropertyFromNode( *childValue, Dali::Property::BOOLEAN, value);
72 else if(*childType == "float")
74 return SetPropertyFromNode( *childValue, Dali::Property::FLOAT, value);
76 else if(*childType == "vector2")
78 return SetPropertyFromNode( *childValue, Dali::Property::VECTOR2, value);
80 else if(*childType == "vector3")
82 return SetPropertyFromNode( *childValue, Dali::Property::VECTOR3, value);
84 else if(*childType == "vector4")
86 return SetPropertyFromNode( *childValue, Dali::Property::VECTOR4, value);
88 else if(*childType == "rotation")
90 return SetPropertyFromNode( *childValue, Dali::Property::ROTATION, value);
92 else if(*childType == "rect")
94 return SetPropertyFromNode( *childValue, Dali::Property::RECTANGLE, value);
96 else if(*childType == "string")
98 return SetPropertyFromNode( *childValue, Dali::Property::STRING, value);
100 else if(*childType == "map")
102 return SetPropertyFromNode( *childValue, Dali::Property::MAP, value);
104 else if(*childType == "array")
106 return SetPropertyFromNode( *childValue, Dali::Property::ARRAY, value);
110 // else we failed to disambiguate
114 bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value )
120 case Property::BOOLEAN:
122 if( OptionalBoolean v = IsBoolean(node) )
129 case Property::FLOAT:
131 if( OptionalFloat v = IsFloat(node) )
138 case Property::INTEGER:
140 if( OptionalInteger v = IsInteger(node) )
147 case Property::UNSIGNED_INTEGER:
149 if( OptionalInteger v = IsInteger(node) )
151 if( *v >= 0 ) // with a loss of resolution....
159 case Property::VECTOR2:
161 if( OptionalVector2 v = IsVector2(node) )
168 case Property::VECTOR3:
170 if( OptionalVector3 v = IsVector3(node) )
177 case Property::VECTOR4:
179 if( OptionalVector4 v = IsVector4(node) )
186 case Property::MATRIX3:
188 if( OptionalMatrix3 v = IsMatrix3(node) )
195 case Property::MATRIX:
197 if( OptionalMatrix v = IsMatrix(node) )
204 case Property::RECTANGLE:
206 if( OptionalRect v = IsRect(node) )
213 case Property::ROTATION:
217 if( OptionalVector4 ov = IsVector4(node) )
219 const Vector4& v = *ov;
220 // angle, axis as per spec
221 value = Quaternion(Radian(Degree(v[3])),
222 Vector3(v[0],v[1],v[2]));
228 // degrees Euler as per spec
229 if( OptionalVector3 v = IsVector3(node) )
231 value = Quaternion(Radian(Degree((*v).x)),
232 Radian(Degree((*v).y)),
233 Radian(Degree((*v).z)));
239 case Property::STRING:
241 if( OptionalString v = IsString(node) )
248 case Property::ARRAY:
252 value = Property::Value(Property::ARRAY);
254 TreeNode::ConstIterator iter(node.CBegin());
255 for( ; i < node.Size(); ++i, ++iter)
258 if( SetPropertyFromNode( (*iter).second, v) )
264 if( value.GetSize() == static_cast<int>(node.Size()) )
279 value = Property::Value(Property::MAP);
281 TreeNode::ConstIterator iter(node.CBegin());
282 for( ; i < node.Size(); ++i, ++iter)
285 if( SetPropertyFromNode( (*iter).second, v) )
287 value.SetValue( (*iter).first, v );
291 if( value.GetSize() == static_cast<int>(node.Size()) )
302 case Property::TYPE_COUNT:
313 bool SetPropertyFromNode( const TreeNode& node, Property::Value& value )
317 // some values are ambiguous as we have no Property::Type but can be disambiguated in the json
319 // Currently Rotations and Rectangle must always be disambiguated when a type isnt available
320 if( Disambiguated( node, value ) )
328 // our current heuristic for deciding an array is actually a vector and not say a map
329 // is to check if the values are all floats
330 bool allNumbers = true;
331 for(TreeConstIter iter = node.CBegin(); iter != node.CEnd(); ++iter)
333 OptionalFloat f = IsFloat((*iter).second);
343 // prefer finding vectors over presuming composite Property::Array...
344 if( OptionalMatrix v = IsMatrix(node) )
349 else if( OptionalMatrix3 v = IsMatrix3(node) )
354 if( OptionalVector4 v = IsVector4(node) )
359 else if( OptionalVector3 v = IsVector3(node) )
364 else if( OptionalVector2 v = IsVector2(node) )
369 else if( 4 == node.Size() )
371 if( OptionalVector4 v = IsVector4(node) )
379 value = Property::Value(Property::ARRAY);
382 for(TreeConstIter iter = node.CBegin(); iter != node.CEnd(); ++iter)
384 if( SetPropertyFromNode( (*iter).second, v) )
395 // presume an array or map
396 // container of size 1
397 TreeNode::ConstIterator iter = node.CBegin();
399 // its seems legal with current json parser for a map to have an empty key
400 // but here we take that to mean the structure is a list
401 if( ((*iter).first) == 0 )
403 value = Property::Value(Property::ARRAY);
405 for(unsigned int i = 0; i < node.Size(); ++i, ++iter)
407 if( SetPropertyFromNode( (*iter).second, v) )
416 value = Property::Value(Property::MAP);
418 for(unsigned int i = 0; i < node.Size(); ++i, ++iter)
420 if( SetPropertyFromNode( (*iter).second, v) )
422 value.SetValue((*iter).first, v);
429 else // if( 0 == node.size() )
431 // no children so either one of bool, float, integer, string
432 OptionalBoolean aBool = IsBoolean(node);
433 OptionalInteger anInt = IsInteger(node);
434 OptionalFloat aFloat = IsFloat(node);
435 OptionalString aString = IsString(node);
439 // a bool is also an int but here we presume int
453 // Note: These are both floats and strings
456 // This means we can't have a string with purely numeric content without disambiguation.
469 // string always succeeds with the current json parser so its last
476 } // if( node.size() )
478 } // if Disambiguated()
481 } // bool SetPropertyFromNode( const TreeNode& node, Property::Value& value )
484 } // namespace Internal
486 } // namespace Toolkit