Merge "Emscripten minimal adaptor build" into devel/master
[platform/core/uifw/dali-adaptor.git] / adaptors / emscripten / wrappers / property-value-wrapper.cpp
1 /*
2  * Copyright (c) 2015 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 #include "property-value-wrapper.h"
19
20 // EXTERNAL INCLUDES
21 #include <sstream>
22 #include <cassert>
23
24 // INTERNAL INCLUDES
25
26 namespace Dali
27 {
28 namespace Internal
29 {
30 namespace Emscripten
31 {
32
33 void RecursiveSetProperty(Dali::Property::Value& propertyValue, const emscripten::val& fromVal)
34 {
35   static const std::string number("number"); // we could maybe just check the first three chars? (avoiding null ...if that's returned)
36   const std::string fromType( fromVal.typeof().as<std::string>() );
37
38   if( fromType == "object" )
39   {
40     // hasOwnProperty is the only way I can find to tell if the object is an array
41     // (keys in HasKey returns the JS keys "0","1","2","3",...)
42     if( fromVal.hasOwnProperty("length") )
43     {
44       int length = fromVal["length"].as<int>();
45       // we can't tell if what the user of the property value wants with a JS Array
46       // by default 'standard' length arrays are always interpreted as Vector2/3/4 etc
47       // If the user specifically wants an array they must recast.
48       bool isArray = false; // nested ie [ [1,2,3], [4,5,6] ]
49       if( 4 == length )
50       {
51         if( number == fromVal["0"].typeof().as<std::string>() &&
52             number == fromVal["1"].typeof().as<std::string>() &&
53             number == fromVal["2"].typeof().as<std::string>() &&
54             number == fromVal["3"].typeof().as<std::string>() )
55         {
56           propertyValue = Dali::Vector4( fromVal["0"].as<float>(),
57                                          fromVal["1"].as<float>(),
58                                          fromVal["2"].as<float>(),
59                                          fromVal["3"].as<float>() );
60         }
61         else
62         {
63           isArray = true;
64         }
65       }
66       else if( 3 == length )
67       {
68         if( number == fromVal["0"].typeof().as<std::string>() &&
69             number == fromVal["1"].typeof().as<std::string>() &&
70             number == fromVal["2"].typeof().as<std::string>() )
71         {
72           propertyValue = Dali::Vector3( fromVal["0"].as<float>(),
73                                          fromVal["1"].as<float>(),
74                                          fromVal["2"].as<float>() );
75         }
76         else
77         {
78           isArray = true;
79         }
80       }
81       else if( 2 == length )
82       {
83         if( number == fromVal["0"].typeof().as<std::string>() &&
84             number == fromVal["1"].typeof().as<std::string>() )
85         {
86           propertyValue = Dali::Vector2( fromVal["0"].as<float>(),
87                                          fromVal["1"].as<float>() );
88         }
89         else
90         {
91           isArray = true;
92         }
93       }
94       else
95       {
96         isArray = true;
97       }
98
99       if( isArray )
100       {
101         propertyValue = Dali::Property::Value(Dali::Property::ARRAY);
102         Dali::Property::Array* array = propertyValue.GetArray();
103         for( int j = 0; j < length; ++j )
104         {
105           Dali::Property::Value add;
106           array->PushBack( add );
107
108           std::stringstream ss;
109           ss << j;
110
111           emscripten::val val = fromVal[ ss.str() ];
112           RecursiveSetProperty( array->GetElementAt(j), val );
113         }
114       }
115     }
116     else
117     {
118       propertyValue = Dali::Property::Value(Dali::Property::MAP);
119       Dali::Property::Map* map = propertyValue.GetMap();
120       emscripten::val keys = emscripten::val::global("Object").call<emscripten::val>("keys", fromVal);
121       int keyLength = keys["length"].as<int>();
122       for( int j = 0; j < keyLength; ++j )
123       {
124         Dali::Property::Value add;
125         std::string key = keys[j].as<std::string>();
126         (*map)[key] = add;
127         emscripten::val keyVal = fromVal[ key ];
128         RecursiveSetProperty( *(map->Find( key )), keyVal );
129       }
130     }
131   }
132   else if( fromType == "number" )
133   {
134     propertyValue = Dali::Property::Value( fromVal.as<float>() );
135   }
136   else if( fromType == "string" )
137   {
138     propertyValue = Dali::Property::Value( fromVal.as<std::string>() );
139   }
140   else
141   {
142     assert(0);
143   }
144
145 }
146
147 emscripten::val JavascriptValue( const Dali::Property::Value& v )
148 {
149   switch( v.GetType() )
150   {
151     case Dali::Property::BOOLEAN:
152     {
153       return emscripten::val(v.Get<bool>());
154       break;
155     }
156     case Dali::Property::FLOAT:
157     {
158       return emscripten::val(v.Get<float>());
159       break;
160     }
161     case Dali::Property::INTEGER:
162     {
163       return emscripten::val(v.Get<int>());
164       break;
165     }
166     case Dali::Property::VECTOR2:
167     {
168       Dali::Vector2 in = v.Get<Dali::Vector2>();
169       emscripten::val out = emscripten::val::array();
170       out.set("0", emscripten::val(in.x) );
171       out.set("1", emscripten::val(in.y) );
172       return out;
173       break;
174     }
175     case Dali::Property::VECTOR3:
176     {
177       Dali::Vector3 in = v.Get<Dali::Vector3>();
178       emscripten::val out = emscripten::val::array();
179       out.set("0", emscripten::val(in.x) );
180       out.set("1", emscripten::val(in.y) );
181       out.set("2", emscripten::val(in.z) );
182       return out;
183       break;
184     }
185     case Dali::Property::VECTOR4:
186     {
187       Dali::Vector4 in = v.Get<Dali::Vector4>();
188       emscripten::val out = emscripten::val::array();
189       out.set("0", emscripten::val(in.x) );
190       out.set("1", emscripten::val(in.y) );
191       out.set("2", emscripten::val(in.z) );
192       out.set("3", emscripten::val(in.w) );
193       return out;
194       break;
195     }
196     case Dali::Property::MATRIX3:
197     {
198       emscripten::val val = emscripten::val::array();
199       Dali::Matrix3 mat3 = v.Get<Dali::Matrix3>();
200
201       for( int i = 0; i < 9; ++i )
202       {
203         std::stringstream key;
204         key << i;
205         val.set( key.str(), emscripten::val(mat3.AsFloat()[i]) );
206       }
207       return val;
208       break;
209     }
210     case Dali::Property::MATRIX:
211     {
212       emscripten::val val = emscripten::val::array();
213       Dali::Matrix mat = v.Get<Dali::Matrix>();
214
215       for( int i = 0; i < 16; ++i )
216       {
217         std::stringstream key;
218         key << i;
219         val.set( key.str(), emscripten::val(mat.AsFloat()[i]) );
220       }
221       return val;
222       break;
223     }
224     case Dali::Property::RECTANGLE:
225     {
226       Dali::Rect<int> in = v.Get<Dali::Rect<int> >();
227       emscripten::val out = emscripten::val::array();
228       out.set("0", emscripten::val(in.x) );
229       out.set("1", emscripten::val(in.y) );
230       out.set("2", emscripten::val(in.width) );
231       out.set("3", emscripten::val(in.height) );
232       return out;
233       break;
234     }
235     case Dali::Property::ROTATION:
236     {
237       Dali::Quaternion in = v.Get<Dali::Quaternion>();
238       emscripten::val out = emscripten::val::array();
239       Dali::Vector3 axis;
240       Dali::Radian angle;
241       in.ToAxisAngle(axis, angle);
242
243       out.set("0", emscripten::val( axis.x ) );
244       out.set("1", emscripten::val( axis.y ) );
245       out.set("2", emscripten::val( axis.z ) );
246       out.set("3", emscripten::val( Dali::Degree(angle).degree ) );
247
248       return out;
249       break;
250     }
251     case Dali::Property::STRING:
252     {
253       return emscripten::val( v.Get<std::string>() );
254       break;
255     }
256     case Dali::Property::ARRAY:
257     {
258       emscripten::val val = emscripten::val::array();
259       Dali::Property::Array *array = v.GetArray();
260       DALI_ASSERT_ALWAYS(array);
261
262       for( int i = 0; i < array->Count(); ++i )
263       {
264         Dali::Property::Value& property = array->GetElementAt( i );
265         std::stringstream key;
266         key << i;
267         val.set( key.str(), JavascriptValue( property ) );
268       }
269
270       return val;
271       break;
272     }
273     case Dali::Property::MAP:
274     {
275       emscripten::val val = emscripten::val::object();
276       Dali::Property::Map *map = v.GetMap();
277       DALI_ASSERT_ALWAYS(map);
278
279       for( int i = 0; i < map->Count(); ++i )
280       {
281         std::string key;
282         StringValuePair pair = map->GetPair(i);
283         val.set( pair.first, JavascriptValue( pair.second ) );
284       }
285
286       return val;
287       break;
288     }
289     case Dali::Property::NONE:
290     {
291       break;
292     }
293   } // switch type
294
295   return emscripten::val::undefined();
296
297 }
298
299 Dali::Property::Value PropertyMapGet( Dali::Property::Map& self, const std::string& key)
300 {
301   Dali::Property::Value ret;
302
303   Dali::Property::Value* v = self.Find(key);
304
305   if(v)
306   {
307     ret = *v;
308   }
309
310   return ret;
311 }
312
313 }; // namespace Emscripten
314 }; // namespace Internal
315 }; // namespace Dali