JavaScript binding for new mesh APIs
[platform/core/uifw/dali-toolkit.git] / plugins / dali-script-v8 / src / object / handle-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 // CLASS HEADER
19 #include "handle-wrapper.h"
20
21 // EXTERNAL INCLUDES
22 #include <sstream>
23
24 // INTERNAL INCLUDES
25 #include <v8-utils.h>
26 #include <shared/base-wrapped-object.h>
27 #include <shared/object-template-helper.h>
28 #include <object/property-value-wrapper.h>
29
30 namespace Dali
31 {
32
33 namespace V8Plugin
34 {
35
36 namespace // un-named name space
37 {
38
39 /**
40  * Contains a list of all functions that can be called
41  */
42 const ApiFunction HandleFunctionTable[]=
43 {
44   { "RegisterAnimatableProperty",            HandleWrapper::RegisterAnimatableProperty },
45 };
46
47 const unsigned int HandleFunctionTableCount = sizeof(HandleFunctionTable)/sizeof(HandleFunctionTable[0]);
48 } //un-named space
49
50 /**
51  * @class Handle
52  */
53
54 HandleWrapper::HandleWrapper( BaseWrappedObject::Type type,
55     Handle handle,
56     GarbageCollectorInterface& gc ) :
57  BaseWrappedObject( type, gc ),
58  mHandle( handle )
59 {
60 }
61
62 HandleWrapper::~HandleWrapper()
63 {
64
65 }
66 HandleWrapper*  HandleWrapper::Unwrap( v8::Isolate* isolate, v8::Handle< v8::Object> obj)
67 {
68   v8::HandleScope handleScope( isolate );
69
70   v8::Local<v8::External> field = v8::Local<v8::External>::Cast( obj->GetInternalField(0) );
71   void* ptr = field->Value();
72   return static_cast< HandleWrapper *>(ptr);
73 }
74
75 // may have to do this IsUpper to intercept function calls or as function?
76 void HandleWrapper::PropertyGet( v8::Local<v8::String> propertyName,
77                                         const v8::PropertyCallbackInfo<v8::Value>& info)
78 {
79   v8::Isolate* isolate = info.GetIsolate();
80   v8::HandleScope handleScope( isolate );
81
82   // get the property name
83   std::string name = V8Utils::v8StringToStdString( propertyName );
84
85   if( std::isupper( name[0] ))
86   {
87     return;
88   }
89
90   // unwrap the object
91   HandleWrapper* handleWrapper = Unwrap( isolate, info.This() );
92   Handle handle =  handleWrapper->mHandle;
93
94   // get the property index
95   // convert from camel case to dali property style with hyphens
96   std::string daliPropertyName = V8Utils::JavaScriptNameToPropertyName(name);
97   Dali::Property::Index index = handle.GetPropertyIndex( daliPropertyName );
98
99   if(index != Dali::Property::INVALID_INDEX)
100   {
101     Dali::Property::Value value = handle.GetProperty(index);
102
103     // Simple Dali properties (ints, strings, bools etc) are stored as JavaScript primitives (v8::Boolean ...)
104     // more complex properties (Vectors, Rectangles...) are wrapped by a JavaScript object
105     v8::Local<v8::Object> ret = PropertyValueWrapper::WrapDaliProperty( isolate, value );
106
107     info.GetReturnValue().Set( ret );
108   }
109   else
110   {
111     //  std::string error="Invalid property Get for "+name + "\n";
112     // DALI_SCRIPT_EXCEPTION( isolate, error );
113   }
114
115 }
116 void HandleWrapper::PropertySet( v8::Local<v8::String> propertyName,
117                   v8::Local<v8::Value> javaScriptValue,
118                   const v8::PropertyCallbackInfo<v8::Value>& info)
119 {
120
121   v8::Isolate* isolate = info.GetIsolate();
122   v8::HandleScope handleScope( isolate );
123
124   // get the property name
125   std::string name = V8Utils::v8StringToStdString( propertyName );
126
127   // try to filter out function calls before going to the property system
128   // @todo use installed functions to generate a map
129   if( ( name.compare(0,2,"is") == 0 )  ||
130       ( name.compare(0,3,"get") == 0 ) ||
131       ( name.compare(0,3,"add") == 0 ) ||
132       ( name.compare(0,3,"set") == 0 ) ||
133       ( name.compare(0,3,"get") == 0 ) ||
134       ( name.compare(0,4,"find") == 0 ) ||
135       ( name.compare(0,6,"remove") == 0 )
136      )
137   {
138     //
139     return;
140   }
141   // unwrap the object
142   HandleWrapper* handleWrapper = Unwrap( isolate, info.This() );
143   if( !handleWrapper )
144   {
145     // printf("setting property name %s \n", name.c_str());
146     return;
147   }
148
149  // DALI_ASSERT_DEBUG( handleWrapper && "not a dali object");
150   Handle handle =  handleWrapper->mHandle;
151
152   // convert from camel case to dali property style with hyphens
153   std::string daliPropertyName = V8Utils::JavaScriptNameToPropertyName(name);
154   Dali::Property::Index index = handle.GetPropertyIndex( daliPropertyName );
155
156   if(index != Dali::Property::INVALID_INDEX)
157   {
158     Dali::Property::Type type = handle.GetPropertyType(index);
159
160     // we know the type we want to set ( int, vector, etc..)
161     // try and convert the javascript value in to the type we want.
162     Dali::Property::Value value = PropertyValueWrapper::ExtractPropertyValue( isolate, javaScriptValue, type);
163
164     if( Dali::Property::NONE == value.GetType() )
165       {
166         std::stringstream msg;
167         msg << "Invalid property Set: '";
168         msg << name;
169         msg << "(Index = ";
170         msg << index;
171         msg << ")";
172         msg << "' Cannot convert value to correct type: (";
173         msg << type;
174         msg << ")";
175         msg << Dali::PropertyTypes::GetName(type);
176         DALI_SCRIPT_EXCEPTION( isolate, msg.str().c_str());
177       }
178       else
179       {
180         handle.SetProperty( index, value );
181       }
182   }
183   else
184   {
185     std::string error="Invalid property Set for "+name + "\n";
186     DALI_SCRIPT_EXCEPTION( isolate, error );
187   }
188 }
189
190 void HandleWrapper::AddInterceptsToTemplate( v8::Isolate* isolate, v8::Local<v8::ObjectTemplate>& objTemplate )
191 {
192   v8::HandleScope handleScope( isolate );
193
194   objTemplate->SetNamedPropertyHandler( HandleWrapper::PropertyGet, HandleWrapper::PropertySet);
195
196   // add function properties
197   ObjectTemplateHelper::InstallFunctions( isolate, objTemplate, HandleFunctionTable, HandleFunctionTableCount );
198
199   ObjectTemplateHelper::AddSignalConnectAndDisconnect( isolate, objTemplate );
200
201 }
202
203 /**
204  * Register a new animatable property.
205  *
206  * The object should support dynamic properties.
207  * Property names are expected to be unique, but this is not enforced.
208  * Property indices are unique to each registered custom property in a given object.
209  * returns dali.PROPERTY_INVALID_INDEX if registration failed. This can happen if you try
210  * to register animatable property on an object that does not have scene graph object.
211  *
212  * @method registerAnimatableProperty
213  * @for Handle
214  * @param {string} name The name of the property.
215  * @param {Object} propertyValue The new value of the property.
216  * @return {integer} The index of the property or dali.PROPERTY_INVALID_INDEX if registration failed
217  * @example
218  *
219  *     var morphPropertyIdex = actor.registerAnimatableProperty("uMorphAmount", 0.0f);
220  *     var fadeColorPropertyIdex = handle.registerAnimatableProperty("uFadeColor", [1.0, 0.0, 0.0, 1.0]);
221  *
222  */
223 void HandleWrapper::RegisterAnimatableProperty( const v8::FunctionCallbackInfo< v8::Value >& args )
224 {
225   v8::Isolate* isolate = args.GetIsolate();
226   v8::HandleScope handleScope( isolate );
227
228   // unwrap the object
229   HandleWrapper* handleWrapper = Unwrap( isolate, args.This() );
230   if( !handleWrapper )
231   {
232     return;
233   }
234
235   Handle handle =  handleWrapper->mHandle;
236
237   bool found( false );
238   std::string propertyName = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args );
239   if( !found )
240   {
241     DALI_SCRIPT_EXCEPTION( isolate, "bad property name parameter" );
242     return;
243   }
244
245   found = false;
246   Dali::Property::Value daliPropertyValue = V8Utils::GetPropertyValueParameter(PARAMETER_1, found, isolate, args );
247   if( !found || Dali::Property::NONE == daliPropertyValue.GetType() )
248   {
249     DALI_SCRIPT_EXCEPTION( isolate, "bad property value parameter" );
250     return;
251   }
252   else
253   {
254     args.GetReturnValue().Set( v8::Integer::New( isolate, handle.RegisterProperty(propertyName, daliPropertyValue) ) );
255   }
256 }
257
258 } // namespace V8Plugin
259
260 } // namespace Dali