Purge underscored header file barriers
[platform/core/uifw/dali-toolkit.git] / plugins / dali-script-v8 / src / controls / control-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 <actors/actor-wrapper.h>
20 #include "control-wrapper.h"
21
22 // EXTERNAL INCLUDES
23 #include <dali/public-api/object/type-registry.h>
24
25 // INTERNAL INCLUDES
26 #include <controls/item-view-api.h>
27 #include <controls/scroll-view-api.h>
28 #include <v8-utils.h>
29 #include <dali-wrapper.h>
30
31 namespace Dali
32 {
33
34 namespace V8Plugin
35 {
36
37 v8::Persistent<v8::ObjectTemplate> ControlWrapper::mControlTemplate;
38 v8::Persistent<v8::ObjectTemplate> ControlWrapper::mItemViewTemplate;
39 v8::Persistent<v8::ObjectTemplate> ControlWrapper::mScrollViewTemplate;
40
41 Vector< void* > ControlWrapper::mControlGarbageContainer;
42
43 namespace
44 {
45
46
47 /**
48  * pointer to a persistent template handle
49  */
50 struct ControlTemplate
51 {
52   v8::Persistent<v8::ObjectTemplate>* controlTemplate;
53 };
54
55 /**
56  * array of templates for each type of control
57  */
58 const ControlTemplate ControlTemplateLookup[]=
59 {
60     { &ControlWrapper::mControlTemplate },        // CONTROL
61     { &ControlWrapper::mItemViewTemplate },       // ITEMVIEW
62     { &ControlWrapper::mScrollViewTemplate }      // SCROLLVIEW
63 };
64
65 /**
66  * Bitmask of API's that an control can support
67  */
68 enum ControlApiBitMask
69 {
70   CONTROL_API             = 1 << 0,
71   ITEMVIEW_API            = 1 << 1,
72   SCROLLVIEW_API          = 1 << 2
73 };
74
75 /**
76  * structure used for the ControlApiLookup.
77  */
78 struct ControlApiStruct
79 {
80   const char* controlName;
81   ControlWrapper::ControlType controlType;
82   Toolkit::Control (*constructor)( const v8::FunctionCallbackInfo< v8::Value >& args);
83   int supportApis;
84 };
85
86 /**
87  * Lookup table to match a control type with a constructor and supported API's.
88  * ControlWrapper::ControlType is used to index this table
89  */
90 const ControlApiStruct ControlApiLookup[]=
91 {
92   {"Control",      ControlWrapper::CONTROL,      NULL,                 CONTROL_API },
93   {"ItemView",     ControlWrapper::ITEMVIEW,     ItemViewApi::New,     CONTROL_API | ITEMVIEW_API },
94   {"ScrollView",   ControlWrapper::SCROLLVIEW,   ScrollViewApi::New,   CONTROL_API | SCROLLVIEW_API }
95 };
96
97 const unsigned int ControlApiLookupCount = sizeof(ControlApiLookup)/sizeof(ControlApiLookup[0]);
98
99
100 /**
101  * Creates a control given a type name
102  * Uses the type registry to create an control of the correct type
103  */
104 Toolkit::Control CreateControl( const v8::FunctionCallbackInfo< v8::Value >& args,
105                         const std::string& typeName )
106 {
107   Toolkit::Control control;
108
109   ControlWrapper::ControlType controlType = ControlWrapper::GetControlType( typeName );
110
111   // if we don't currently have specific binding for the given control type,
112   // try to use type registry to create it
113   if( controlType == ControlWrapper::UNKNOWN_CONTROL )
114   {
115     Dali::TypeInfo typeInfo = Dali::TypeRegistry::Get().GetTypeInfo( typeName );
116     if( typeInfo )
117     {
118       Dali::BaseHandle handle = typeInfo.CreateInstance();
119       if( handle )
120       {
121         control = Toolkit::Control::DownCast( handle );
122         if( !control )
123         {
124           DALI_SCRIPT_EXCEPTION( args.GetIsolate(), "Unknown control type" );
125           return Toolkit::Control();
126         }
127       }
128     }
129   }
130   else
131   {
132     // run the constructor for this type of control so it can pull out custom parameters
133     control = (ControlApiLookup[controlType].constructor)( args );
134   }
135
136   return control;
137 }
138
139 /**
140  * given a control type return what api's it supports
141  */
142 int GetControlSupportedApis( ControlWrapper::ControlType type )
143 {
144   return ControlApiLookup[type].supportApis;
145 }
146
147 /**
148  * Used for the ControlFunctionTable to map function names to functions
149  * with for a specific API
150  */
151 struct ControlFunctions
152 {
153   const char* name;               ///< function name
154   void (*function)( const v8::FunctionCallbackInfo< v8::Value >& args);
155   ControlApiBitMask api;
156 };
157
158 /**
159  * Contains a list of all functions that can be called in
160  * ItemView
161  */
162 const ControlFunctions ControlFunctionTable[]=
163 {
164
165     /**************************************
166      * ItemView  API
167      **************************************/
168     { "GetLayoutCount",                  ItemViewApi::GetLayoutCount,                   ITEMVIEW_API  },
169     { "AddLayout",                       ItemViewApi::AddLayout,                        ITEMVIEW_API  },
170     { "RemoveLayout",                    ItemViewApi::RemoveLayout,                     ITEMVIEW_API  },
171     { "ActivateLayout",                  ItemViewApi::ActivateLayout,                   ITEMVIEW_API  },
172     { "GetItemSize",                     ItemViewApi::GetItemSize,                      ITEMVIEW_API  },
173     { "SetItemSize",                     ItemViewApi::SetItemSize,                      ITEMVIEW_API  },
174     { "ScrollToItem",                    ItemViewApi::ScrollToItem,                     ITEMVIEW_API  },
175     { "GetItem",                         ItemViewApi::GetItem,                          ITEMVIEW_API  },
176     { "GetItemId",                       ItemViewApi::GetItemId,                        ITEMVIEW_API  },
177     { "GetItemsRange",                   ItemViewApi::GetItemsRange,                    ITEMVIEW_API  },
178
179     /**************************************
180      * ScrollView  API
181      **************************************/
182     { "SetScrollMode",                   ScrollViewApi::SetScrollMode,                  SCROLLVIEW_API },
183     { "GetCurrentPage",                  ScrollViewApi::GetCurrentPage,                 SCROLLVIEW_API },
184     { "ScrollToPosition",                ScrollViewApi::ScrollToPosition,               SCROLLVIEW_API },
185     { "ScrollToPage",                    ScrollViewApi::ScrollToPage,                   SCROLLVIEW_API },
186     { "ScrollToActor",                   ScrollViewApi::ScrollToActor,                  SCROLLVIEW_API },
187     { "ScrollToSnapInterval",            ScrollViewApi::ScrollToSnapInterval,           SCROLLVIEW_API },
188     { "SetScrollFlickAlphaFunction",     ScrollViewApi::SetScrollFlickAlphaFunction,    SCROLLVIEW_API },
189     { "SetScrollSnapAlphaFunction",      ScrollViewApi::SetScrollSnapAlphaFunction,     SCROLLVIEW_API },
190     { "SetSnapOvershootAlphaFunction",   ScrollViewApi::SetSnapOvershootAlphaFunction,  SCROLLVIEW_API },
191
192 };
193
194 const unsigned int ControlFunctionTableCount = sizeof(ControlFunctionTable)/sizeof(ControlFunctionTable[0]);
195 } //un-named space
196
197
198 ControlWrapper::ControlWrapper( Toolkit::Control control,
199               GarbageCollectorInterface& gc )
200 : ActorWrapper( control, gc ),
201   mControl( control )
202
203 {
204 }
205
206 ControlWrapper::~ControlWrapper()
207 {
208   mControlGarbageContainer.Release();
209 }
210
211 v8::Handle<v8::Object> ControlWrapper::WrapControl(v8::Isolate* isolate, Toolkit::Control control )
212 {
213   v8::EscapableHandleScope handleScope( isolate );
214
215   // Check whether the control is a Control
216   ControlWrapper::ControlType controlType = GetControlType( control.GetTypeName() );
217
218   if( controlType == ControlWrapper::UNKNOWN_CONTROL && Toolkit::Control::DownCast(control) )
219   {
220     controlType = ControlWrapper::CONTROL;
221   }
222
223   v8::Local<v8::Object> object = WrapControl( isolate, control, controlType );
224
225   return handleScope.Escape( object );
226 }
227
228 Toolkit::Control ControlWrapper::GetControl()
229 {
230   return mControl;
231 }
232
233 v8::Handle<v8::Object> ControlWrapper::WrapControl( v8::Isolate* isolate, Toolkit::Control control, ControlType controlType )
234 {
235   v8::EscapableHandleScope handleScope( isolate );
236   v8::Local<v8::ObjectTemplate> objectTemplate;
237
238   objectTemplate = GetControlTemplate( isolate, controlType );
239
240   // create an instance of the template
241   v8::Local<v8::Object> localObject = objectTemplate->NewInstance();
242
243   // create the control object
244   ControlWrapper* pointer = new ControlWrapper( control, Dali::V8Plugin::DaliWrapper::Get().GetDaliGarbageCollector() );
245
246   // assign the JavaScript object to the wrapper.
247   // This also stores Dali object, in an internal field inside the JavaScript object.
248   pointer->SetJavascriptObject( isolate, localObject );
249
250   return handleScope.Escape( localObject );
251 }
252
253 v8::Local<v8::ObjectTemplate> ControlWrapper::GetControlTemplate( v8::Isolate* isolate, ControlWrapper::ControlType type )
254 {
255   v8::EscapableHandleScope handleScope( isolate );
256   v8::Local<v8::ObjectTemplate> objectTemplate;
257
258   if( ControlTemplateLookup[type].controlTemplate->IsEmpty() )
259   {
260     objectTemplate = MakeDaliControlTemplate( isolate, type );
261     ControlTemplateLookup[type].controlTemplate->Reset( isolate, objectTemplate );
262   }
263   else
264   {
265     // get the object template
266     objectTemplate = v8::Local<v8::ObjectTemplate>::New( isolate, *ControlTemplateLookup[type].controlTemplate );
267   }
268
269   return handleScope.Escape( objectTemplate );
270 }
271
272 v8::Handle<v8::ObjectTemplate> ControlWrapper::MakeDaliControlTemplate( v8::Isolate* isolate, ControlType controlType )
273 {
274   v8::EscapableHandleScope handleScope( isolate );
275
276   // all the controls support actor APIs
277   v8::Local<v8::ObjectTemplate> objTemplate = ActorWrapper::MakeDaliActorTemplate( isolate, ActorWrapper::ACTOR );
278
279   // find out what API's this control supports
280   int supportApis = GetControlSupportedApis( controlType );
281
282   // add our function properties
283   for( unsigned int i = 0; i < ControlFunctionTableCount; ++i )
284   {
285     const ControlFunctions property =  ControlFunctionTable[i];
286
287     // check to see if the control supports a certain type of API
288     // e.g. ItemView will support CONTROL_API and ITEMVIEW_API
289     if( supportApis &  property.api )
290     {
291       std::string funcName = V8Utils::GetJavaScriptFunctionName( property.name);
292
293       objTemplate->Set( v8::String::NewFromUtf8( isolate, funcName.c_str() ),
294                       v8::FunctionTemplate::New( isolate, property.function ) );
295     }
296   }
297
298   return handleScope.Escape( objTemplate );
299 }
300
301 void ControlWrapper::NewControl( const v8::FunctionCallbackInfo< v8::Value >& args)
302 {
303   v8::Isolate* isolate = args.GetIsolate();
304   v8::HandleScope handleScope( isolate );
305
306   if( !args.IsConstructCall() )
307   {
308     DALI_SCRIPT_EXCEPTION( isolate, "constructor called without 'new" );
309     return;
310   }
311
312   bool found( false );
313   std::string controlName = V8Utils::GetStringParameter( PARAMETER_0, found, isolate,  args );
314
315   Toolkit::Control control;
316   if( found && controlName != ControlApiLookup[0].controlName )
317   {
318     control = CreateControl( args, controlName ); // create the control with the given type
319   }
320   else
321   {
322     control = Toolkit::Control::New(); // no given type, so create the base type of control
323   }
324
325   if( control )
326   {
327     v8::Local<v8::Object> localObject = WrapControl( isolate, control );
328     args.GetReturnValue().Set( localObject );
329   }
330   else
331   {
332     DALI_SCRIPT_EXCEPTION( isolate, "unsupported control type" );
333   }
334 }
335
336 /**
337  * Given a control type name, e.g. ItemView returns the type, e.g. ControlWrapper::ITEMVIEW
338  */
339 ControlWrapper::ControlType ControlWrapper::GetControlType( const std::string& name )
340 {
341   for( unsigned int i = 0 ; i < ControlApiLookupCount ; i++ )
342   {
343     if( ControlApiLookup[i].controlName == name )
344     {
345       return ControlApiLookup[i].controlType;
346     }
347   }
348   return ControlWrapper::UNKNOWN_CONTROL;
349 }
350
351 void ControlWrapper::RegisterGarbage(void* garbage)
352 {
353   mControlGarbageContainer.PushBack(garbage);
354 }
355
356 } // namespace V8Plugin
357
358 } // namespace Dali