Merge "JavaScript support for DALi" into tizen
[platform/core/uifw/dali-toolkit.git] / plugins / dali-script-v8 / src / toolkit / builder / builder-api.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 // CLASS HEADER
19 #include "builder-api.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <string>
24 #include <fstream>
25 #include <streambuf>
26
27 // INTERNAL INCLUDES
28 #include <v8-utils.h>
29 #include <object/property-value-wrapper.h>
30 #include <object/handle-wrapper.h>
31 #include <toolkit/builder/builder-wrapper.h>
32 #include <actors/actor-wrapper.h>
33 #include <image/image-wrapper.h>
34 #include <animation/animation-wrapper.h>
35 #include <text/font-wrapper.h>
36 #include <shader-effects/shader-effect-wrapper.h>
37
38
39 namespace Dali
40 {
41
42 namespace V8Plugin
43 {
44
45 namespace // un named namespace
46 {
47
48
49 Dali::Toolkit::Builder GetBuilder( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
50 {
51   v8::HandleScope handleScope( isolate );
52
53   v8::Local<v8::Object> object = args.This();
54   v8::Local<v8::External> field = v8::Local<v8::External>::Cast( object->GetInternalField( 0 ) );
55   void* ptr = field->Value();
56
57   BuilderWrapper* wrapper = static_cast<BuilderWrapper *>( ptr );
58   return wrapper->GetBuilder();
59 }
60
61
62 void GetMapAndString( v8::Isolate* isolate,
63                       std::string stringKey,
64                       std::string& stringValue,
65                       std::string mapKey,
66                       Dali::Property::Map& map,
67                       v8::Local<v8::Object> object)
68 {
69     v8::Local<v8::Value> stringNameValue = object->Get( v8::String::NewFromUtf8( isolate, stringKey.c_str() ) );
70     if( !stringNameValue->IsString() )
71     {
72       std::string message = "missing field :"+stringKey;
73       DALI_SCRIPT_EXCEPTION( isolate,  message);
74       return;
75     }
76     stringValue = V8Utils::v8StringToStdString( stringNameValue );
77
78     // constants is optional
79
80     v8::Local<v8::Value> constants = object->Get( v8::String::NewFromUtf8( isolate, mapKey.c_str() ) );
81     if( constants->IsObject() )
82     {
83       map = V8Utils::GetPropertyMapFromObject( isolate, constants->ToObject() );
84     }
85 }
86
87
88 } // un-named namespace
89
90
91 Dali::Toolkit::Builder BuilderApi::New( const v8::FunctionCallbackInfo< v8::Value >& args )
92 {
93   v8::Isolate* isolate = args.GetIsolate();
94   v8::HandleScope handleScope( isolate );
95
96   return Dali::Toolkit::Builder::New();
97 }
98
99 void BuilderApi::LoadFromString( const v8::FunctionCallbackInfo< v8::Value >& args )
100 {
101   v8::Isolate* isolate = args.GetIsolate();
102   v8::HandleScope handleScope( isolate );
103
104   Dali::Toolkit::Builder builder = GetBuilder( isolate, args );
105
106   bool found(false);
107   std::string str = V8Utils::GetStringParameter( 0, found, isolate, args );
108   if( found )
109   {
110     builder.LoadFromString( str );
111   }
112   else
113   {
114     DALI_SCRIPT_EXCEPTION( isolate,  "missing string parameter");
115   }
116 }
117
118 void BuilderApi::LoadFromFile( const v8::FunctionCallbackInfo< v8::Value >& args )
119 {
120   v8::Isolate* isolate = args.GetIsolate();
121   v8::HandleScope handleScope( isolate );
122
123   Dali::Toolkit::Builder builder = GetBuilder( isolate, args );
124
125   bool found(false);
126   std::string fileName= V8Utils::GetStringParameter( 0, found, isolate, args );
127   if( !found )
128   {
129     DALI_SCRIPT_EXCEPTION( isolate,  "missing string parameter");
130     return;
131   }
132
133   std::ifstream fileStream( fileName.c_str() );
134   if( !fileStream.is_open() )
135   {
136     std::string message = "failed to open JSON file" + fileName;
137     DALI_SCRIPT_EXCEPTION( isolate,  message );
138     return;
139   }
140
141   //single-pass input iterator that reads successive characters from the input stream
142   std::string json = std::string( (std::istreambuf_iterator< char >( fileStream )), std::istreambuf_iterator< char >() );
143
144   builder.LoadFromString( json );
145
146 }
147
148 void BuilderApi::AddConstants( const v8::FunctionCallbackInfo< v8::Value >& args )
149 {
150   v8::Isolate* isolate = args.GetIsolate();
151   v8::HandleScope handleScope( isolate );
152
153   Dali::Toolkit::Builder builder = GetBuilder( isolate, args );
154
155   bool found(false);
156   Dali::Property::Map map = V8Utils::GetPropertyMapParameter( 0,found, isolate, args );
157
158   if( found )
159   {
160     builder.AddConstants( map );
161   }
162   else
163   {
164     DALI_SCRIPT_EXCEPTION( isolate,  "no constants found" );
165   }
166
167 }
168
169 void BuilderApi::GetConstants( const v8::FunctionCallbackInfo< v8::Value >& args )
170 {
171   v8::Isolate* isolate = args.GetIsolate();
172   v8::HandleScope handleScope( isolate );
173
174   Dali::Toolkit::Builder builder = GetBuilder( isolate, args );
175
176   const Dali::Property::Map& map  = builder.GetConstants();
177
178   v8::Local<v8::Object> object = v8::Object::New( isolate );
179
180   V8Utils::CreatePropertyMap( isolate, map, object );
181
182   args.GetReturnValue().Set( object );
183
184 }
185 void BuilderApi::CreateAnimation( const v8::FunctionCallbackInfo< v8::Value >& args )
186 {
187   v8::Isolate* isolate = args.GetIsolate();
188   v8::HandleScope handleScope( isolate );
189
190   // options =
191   // {
192   //    animation: ..
193   //    constants:
194   //    actor:
195   // }
196   //
197
198   Dali::Toolkit::Builder builder = GetBuilder( isolate, args );
199
200   if( !args[0]->IsObject() )
201   {
202     DALI_SCRIPT_EXCEPTION( isolate,  "invalid property map, expecting { animation: x, constants: y, actor: z}" );
203     return;
204   }
205   v8::Local<v8::Object> object = args[0]->ToObject();
206
207   std::string animationName;
208   Dali::Property::Map map;
209
210   //  get the animation name and constant map
211
212   GetMapAndString( isolate,
213                    "animation",
214                    animationName,
215                    "constants",
216                    map,
217                    object );
218
219   // actor is optional
220   Actor actor;
221   v8::Local<v8::Value> actorValue = object->Get( v8::String::NewFromUtf8( isolate, "actor" ) );
222   if( actorValue->IsObject() )
223   {
224     HandleWrapper* handleWrapper = HandleWrapper::Unwrap( isolate, actorValue->ToObject() );
225     if( handleWrapper )
226     {
227       actor = Actor::DownCast( handleWrapper->mHandle );
228     }
229   }
230   Animation anim;
231   if( actor )
232   {
233     //  Animation CreateAnimation( const std::string& animationName, const Dali::Property::Map& map, Dali::Actor sourceActor );
234     anim = builder.CreateAnimation( animationName, map, actor );
235   }
236   else
237   {
238     anim = builder.CreateAnimation( animationName, map);
239   }
240   v8::Local<v8::Object> localObject = AnimationWrapper::WrapAnimation( isolate, anim );
241   args.GetReturnValue().Set( localObject );
242 }
243
244 void BuilderApi::Create( const v8::FunctionCallbackInfo< v8::Value >& args )
245 {
246   v8::Isolate* isolate = args.GetIsolate();
247   v8::HandleScope handleScope( isolate );
248
249   Dali::Toolkit::Builder builder = GetBuilder( isolate, args );
250
251   if( !args[0]->IsObject() )
252   {
253     DALI_SCRIPT_EXCEPTION( isolate,  "invalid param");
254     return;
255   }
256   v8::Local<v8::Object> object = args[0]->ToObject();
257
258   // options =
259   // {
260   //    template: "my-temppalte",
261   //    constants: {  IMAGE_DIR: "/usr/apps" ,  SHADER_DIR: "/usr/apps/.."}
262   // }
263   //
264   std::string templateName;
265   Dali::Property::Map map;
266
267   GetMapAndString( isolate,
268                    "template",
269                    templateName,
270                    "constants",
271                    map,
272                    object );
273
274   BaseHandle handle = builder.Create( templateName, map );
275   std::string typeName = handle.GetTypeName();
276   ActorWrapper::ActorType actorType = ActorWrapper::GetActorType( typeName );
277
278   if( actorType != ActorWrapper::UNKNOWN_ACTOR )
279   {
280     v8::Local<v8::Object> actorObject =  ActorWrapper::WrapActor(isolate, Actor::DownCast(handle),actorType);
281     args.GetReturnValue().Set( actorObject );
282     return;
283   }
284
285   if( typeName == "Animation")
286   {
287     v8::Local<v8::Object> animation = AnimationWrapper::WrapAnimation(isolate, Animation::DownCast(handle) );
288     args.GetReturnValue().Set( animation );
289   }
290
291   if( typeName == "Image")
292   {
293     v8::Local<v8::Object> image = ImageWrapper::WrapImage(isolate, Image::DownCast(handle) );
294     args.GetReturnValue().Set( image );
295   }
296   if( typeName == "Font ")
297   {
298     v8::Local<v8::Object> font = FontWrapper::WrapFont(isolate, Font::DownCast(handle) );
299     args.GetReturnValue().Set( font );
300   }
301   if( typeName == "Shader")
302   {
303     v8::Local<v8::Object> shader = ShaderEffectWrapper::WrapShaderEffect(isolate, ShaderEffect::DownCast( handle ));
304     args.GetReturnValue().Set( shader );
305   }
306
307 }
308 void BuilderApi::ApplyStyle( const v8::FunctionCallbackInfo< v8::Value >& args )
309 {
310   v8::Isolate* isolate = args.GetIsolate();
311   v8::HandleScope handleScope( isolate );
312   Dali::Toolkit::Builder builder = GetBuilder( isolate, args );
313
314   // bool ApplyStyle( const std::string& styleName, Handle& handle );
315
316   bool found(false);
317   std::string styleName = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args);
318   if( !found )
319   {
320     DALI_SCRIPT_EXCEPTION( isolate,  "missing style name" );
321     return;
322   }
323
324   Dali::Handle handle = V8Utils::GetHandleParameter( PARAMETER_1, found, isolate, args  );
325   if( !found )
326   {
327     DALI_SCRIPT_EXCEPTION( isolate,  "missing handle parameter" );
328     return;
329   }
330
331   builder.ApplyStyle( styleName, handle );
332
333 }
334
335 void BuilderApi::ApplyFromJson( const v8::FunctionCallbackInfo< v8::Value >& args )
336 {
337   v8::Isolate* isolate = args.GetIsolate();
338   v8::HandleScope handleScope( isolate );
339   Dali::Toolkit::Builder builder = GetBuilder( isolate, args );
340
341   bool found;
342
343   Dali::Handle handle = V8Utils::GetHandleParameter( PARAMETER_0, found, isolate, args  );
344   if( !found )
345   {
346     DALI_SCRIPT_EXCEPTION( isolate,  "missing handle parameter" );
347     return;
348   }
349   std::string jsonString = V8Utils::GetStringParameter( PARAMETER_1, found, isolate, args);
350   if( !found )
351   {
352     DALI_SCRIPT_EXCEPTION( isolate,  "missing JSON string" );
353     return;
354   }
355   builder.ApplyFromJson( handle, jsonString );
356 }
357
358 void BuilderApi::AddActors( const v8::FunctionCallbackInfo< v8::Value >& args )
359 {
360   v8::Isolate* isolate = args.GetIsolate();
361   v8::HandleScope handleScope( isolate );
362   Dali::Toolkit::Builder builder = GetBuilder( isolate, args );
363
364   //{
365   //  actor:actor
366   //  section: name
367   //}
368
369   Actor actor;
370
371   if( !args[0]->IsObject() )
372   {
373     DALI_SCRIPT_EXCEPTION( isolate,  "invalid param");
374     return;
375   }
376   v8::Local<v8::Object> object = args[0]->ToObject();
377
378   v8::Local<v8::Value> actorValue = object->Get( v8::String::NewFromUtf8( isolate, "actor" ) );
379   if( actorValue->IsObject() )
380   {
381     HandleWrapper* handleWrapper = HandleWrapper::Unwrap( isolate, actorValue->ToObject() );
382     if( handleWrapper )
383     {
384       actor = Actor::DownCast( handleWrapper->mHandle );
385     }
386   }
387   else
388   {
389     DALI_SCRIPT_EXCEPTION( isolate,  "actor field not found in param");
390     return;
391   }
392
393   v8::Local<v8::Value> stringNameValue = object->Get( v8::String::NewFromUtf8( isolate, "section" ) );
394   if( !stringNameValue->IsString() )
395   {
396     std::string message = "missing field: section";
397     DALI_SCRIPT_EXCEPTION( isolate,  message);
398     return;
399   }
400   std::string sectionName = V8Utils::v8StringToStdString( stringNameValue );
401   if( !sectionName.empty() )
402   {
403     builder.AddActors( sectionName, actor );
404   }
405   else
406   {
407     builder.AddActors(  actor );
408   }
409
410 }
411
412 void BuilderApi::CreateRenderTask( const v8::FunctionCallbackInfo< v8::Value >& args )
413 {
414   v8::Isolate* isolate = args.GetIsolate();
415   v8::HandleScope handleScope( isolate );
416   Dali::Toolkit::Builder builder = GetBuilder( isolate, args );
417   bool found(false);
418   std::string str = V8Utils::GetStringParameter( 0, found, isolate, args );
419
420   if( found )
421   {
422     builder.CreateRenderTask( str );
423   }
424   else
425   {
426      DALI_SCRIPT_EXCEPTION( isolate, "render task name");
427   }
428 }
429
430 void BuilderApi::GetShaderEffect( const v8::FunctionCallbackInfo< v8::Value >& args )
431 {
432   v8::Isolate* isolate = args.GetIsolate();
433   v8::HandleScope handleScope( isolate );
434   Dali::Toolkit::Builder builder = GetBuilder( isolate, args );
435
436   bool found(false);
437   std::string str = V8Utils::GetStringParameter( 0, found, isolate, args );
438   if( found )
439   {
440     ShaderEffect handle = builder.GetShaderEffect( str );
441     v8::Local<v8::Object> shader = ShaderEffectWrapper::WrapShaderEffect(isolate, handle);
442     args.GetReturnValue().Set( shader );
443   }
444   else
445   {
446     DALI_SCRIPT_EXCEPTION( isolate, "missing shader name");
447   }
448 }
449
450 void BuilderApi::GetFrameBufferImage( const v8::FunctionCallbackInfo< v8::Value >& args )
451 {
452   v8::Isolate* isolate = args.GetIsolate();
453    v8::HandleScope handleScope( isolate );
454    Dali::Toolkit::Builder builder = GetBuilder( isolate, args );
455
456    bool found(false);
457    std::string str = V8Utils::GetStringParameter( 0, found, isolate, args );
458    if( found )
459    {
460      // wrap the image
461      // @TODO Test this, may need to implement a Framebuffer image wrapper.?
462      v8::Local<v8::Object> localObject = ImageWrapper::WrapImage( isolate, builder.GetFrameBufferImage(str)  );
463      args.GetReturnValue().Set( localObject );
464    }
465    else
466    {
467      DALI_SCRIPT_EXCEPTION( isolate,  "frame buffer name");
468    }
469
470 }
471
472 } // namespace V8Plugin
473
474 } // namespace Dali