DALi Version 1.4.26
[platform/core/uifw/dali-toolkit.git] / plugins / dali-script-v8 / src / controls / scroll-view-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 "scroll-view-api.h"
20
21 // EXTERNAL INCLUDES
22
23 // INTERNAL INCLUDES
24 #include <v8-utils.h>
25 #include <actors/actor-wrapper.h>
26 #include <controls/control-wrapper.h>
27
28 namespace Dali
29 {
30
31 namespace V8Plugin
32 {
33
34 namespace  // unanmed namespace
35 {
36
37 Toolkit::ScrollView GetScrollView( v8::Isolate* isolate, const v8::FunctionCallbackInfo<v8::Value>& args )
38 {
39   HandleWrapper* handleWrapper = HandleWrapper::Unwrap( isolate, args.This() );
40   return Toolkit::ScrollView::DownCast( handleWrapper->mHandle );
41 }
42
43 } //unanmed namespace
44
45 /***************************************
46  * SCROLLVIEW API FUNCTIONS
47  ***************************************/
48
49 /**
50  * Constructor
51  *
52  * @for ScrollView
53  * @constructor
54  * @method ScrollView
55  * @return {Object} scrollView
56  */
57 Toolkit::Control ScrollViewApi::New( const v8::FunctionCallbackInfo< v8::Value >& args )
58 {
59   v8::Isolate* isolate = args.GetIsolate();
60   v8::HandleScope handleScope( isolate );
61
62   Toolkit::ScrollView scrollView = Toolkit::ScrollView::New();
63   return scrollView;
64 }
65
66 /**
67  * Set the scroll mode of ScrollView.
68  *
69  * This defines whether scrolling is enabled horizontally or vertically, how
70  * scrolling is snapped, and the boundary in which the scroll view can pan.
71  *
72  * When no specific scroll mode is set, scroll view can scroll to any position
73  * both horizontally and vertically and no snapping is enabled.
74  *
75  * Example of setting the scroll boundary of scroll view in the X axis to
76  * three pages (page size equals to the width of scroll view) and allowing
77  * snapping between pages, and disabling scrolling in the Y axis.
78  *
79  * ```
80  *  var scrollMode = {
81  *                     xAxisScrollEnabled  : true,
82  *                     xAxisSnapToInterval : scrollView.sizeWidth,
83  *                     xAxisScrollBoundary : scrollView.sizeWidth * 3,
84  *                     yAxisScrollEnabled  : false
85  *                   }
86  *
87  *  scrollView.setScrollMode(scrollMode);
88  * ```
89  *
90  * @for ScrollView
91  * @method setScrollMode
92  * @param {Object} scrollMode
93  * @param {Boolean} scrollMode.xAxisScrollEnabled True if the content can be scrolled in X axis or false if not.
94  * @param {Float} [scrollMode.xAxisSnapToInterval] When set, causes scroll view to snap to multiples of the value of the interval in the X axis while flicking. (by default no snapping)
95  * @param {Float} [scrollMode.xAxisScrollBoundary] When set, causes scroll view unable to scroll beyond the value of the boundary in the X axis (by default no boundary)
96  * @param {Boolean} scrollMode.yAxisScrollEnabled True if the content can be scrolled in Y axis or false if not.
97  * @param {Float} [scrollMode.yAxisSnapToInterval] When set, causes scroll view to snap to multiples of the value of the interval in the Y axis while flicking. (by default no snapping)
98  * @param {Float} [scrollMode.yAxisScrollBoundary] When set, causes scroll view unable to scroll beyond the value of the boundary in the Y axis (by default no boundary)
99  */
100 void ScrollViewApi::SetScrollMode( const v8::FunctionCallbackInfo< v8::Value >& args)
101 {
102   v8::Isolate* isolate = args.GetIsolate();
103   v8::HandleScope handleScope( isolate );
104
105   Toolkit::ScrollView scrollView = GetScrollView( isolate, args );
106
107   v8::Local<v8::Value> scrollMode( args[0] );
108   if( !scrollMode->IsObject() )
109   {
110     DALI_SCRIPT_EXCEPTION( isolate, "invalid scroll mode parameter" );
111     return;
112   }
113
114   v8::Local<v8::Object> scrollModeObj = scrollMode->ToObject();
115
116   Toolkit::RulerPtr rulerX, rulerY;
117
118   // Check the scroll mode in the X axis
119   bool xAxisScrollEnabled = true;
120   v8::Local<v8::Value> xAxisScrollEnabledValue= scrollModeObj->Get( v8::String::NewFromUtf8( isolate, "xAxisScrollEnabled" ) );
121   if( xAxisScrollEnabledValue->IsBoolean() )
122   {
123     xAxisScrollEnabled = xAxisScrollEnabledValue->ToBoolean()->Value();
124   }
125   else
126   {
127     DALI_SCRIPT_EXCEPTION( isolate, "Missing xAxisScrollEnabled");
128     return;
129   }
130
131   if(!xAxisScrollEnabled)
132   {
133     // Default ruler and disabled
134     rulerX = new Toolkit::DefaultRuler();
135     rulerX->Disable();
136   }
137   else
138   {
139     v8::Local<v8::Value> xAxisSnapToIntervalValue= scrollModeObj->Get( v8::String::NewFromUtf8( isolate, "xAxisSnapToInterval" ) );
140     if( xAxisSnapToIntervalValue->IsNumber() )
141     {
142       // Fixed ruler and enabled
143       float xAxisSnapToInterval = xAxisSnapToIntervalValue->ToNumber()->Value();
144       rulerX = new Toolkit::FixedRuler(xAxisSnapToInterval);
145     }
146     else
147     {
148       // Default ruler and enabled
149       rulerX = new Toolkit::DefaultRuler();
150     }
151
152     v8::Local<v8::Value> xAxisScrollBoundaryValue= scrollModeObj->Get( v8::String::NewFromUtf8( isolate, "xAxisScrollBoundary" ) );
153     if( xAxisScrollBoundaryValue->IsNumber() )
154     {
155       // By default ruler domain is disabled unless set
156       float xAxisScrollBoundary = xAxisScrollBoundaryValue->ToNumber()->Value();
157       rulerX->SetDomain( Toolkit::RulerDomain( 0, xAxisScrollBoundary, true ) );
158     }
159   }
160
161   // Check the scroll mode in the Y axis
162   bool yAxisScrollEnabled = true;
163   v8::Local<v8::Value> yAxisScrollEnabledValue= scrollModeObj->Get( v8::String::NewFromUtf8( isolate, "yAxisScrollEnabled" ) );
164   if( yAxisScrollEnabledValue->IsBoolean() )
165   {
166     yAxisScrollEnabled = yAxisScrollEnabledValue->ToBoolean()->Value();
167   }
168   else
169   {
170     DALI_SCRIPT_EXCEPTION( isolate, "Missing yAxisScrollEnabled");
171     return;
172   }
173
174   if(!yAxisScrollEnabled)
175   {
176     // Default ruler and disabled
177     rulerY = new Toolkit::DefaultRuler();
178     rulerY->Disable();
179   }
180   else
181   {
182     v8::Local<v8::Value> yAxisSnapToIntervalValue= scrollModeObj->Get( v8::String::NewFromUtf8( isolate, "yAxisSnapToInterval" ) );
183     if( yAxisSnapToIntervalValue->IsNumber() )
184     {
185       // Fixed ruler and enabled
186       float yAxisSnapToInterval = yAxisSnapToIntervalValue->ToNumber()->Value();
187       rulerY = new Toolkit::FixedRuler(yAxisSnapToInterval);
188     }
189     else
190     {
191       // Default ruler and enabled
192       rulerY = new Toolkit::DefaultRuler();
193     }
194
195     v8::Local<v8::Value> yAxisScrollBoundaryValue= scrollModeObj->Get( v8::String::NewFromUtf8( isolate, "yAxisScrollBoundary" ) );
196     if( yAxisScrollBoundaryValue->IsNumber() )
197     {
198       // By default ruler domain is disabled unless set
199       float yAxisScrollBoundary = yAxisScrollBoundaryValue->ToNumber()->Value();
200       rulerY->SetDomain( Toolkit::RulerDomain( 0, yAxisScrollBoundary, true ) );
201     }
202   }
203
204   scrollView.SetRulerX(rulerX);
205   scrollView.SetRulerY(rulerY);
206 }
207
208 /**
209  * Retrieves current scroll page based on the defined snap interval being the
210  * size of one page, and all pages laid out in a grid fashion, increasing from
211  * left to right until the end of the scroll boundary. Pages start from 0 as the
212  * first page.
213  *
214  * If no snap interval is defined, this API will return undefined value.
215  *
216  * @for ScrollView
217  * @method getCurrentPage
218  * @return {Integer} The index of current page in scroll view
219  */
220 void ScrollViewApi::GetCurrentPage( const v8::FunctionCallbackInfo< v8::Value >& args)
221 {
222   v8::Isolate* isolate = args.GetIsolate();
223   v8::HandleScope handleScope( isolate );
224
225   Toolkit::ScrollView scrollView = GetScrollView( isolate, args );
226   args.GetReturnValue().Set( v8::Integer::New( isolate, scrollView.GetCurrentPage() ) );
227 }
228
229 /**
230  * Scrolls the contents to the given position.
231  *
232  * Position 0,0 is the origin. Increasing X scrolls contents left, while
233  * increasing Y scrolls contents up. If Rulers have been applied to the axes,
234  * then the contents will scroll until reaching the scroll boundary.
235  * Contents will not snap.
236  *
237  * The biasing parameters are provided such that in scenarios with 2 or 2x2 pages
238  * in wrap mode, the application developer can decide whether to scroll left or
239  * right to get to the target page.
240  *
241  * @for ScrollView
242  * @method scrollToPosition
243  * @param {Array} position The position to scroll to.
244  * @param {Float} [durationSeconds] The duration of the scroll animation in seconds (default value is scrollView.scrollSnapDuration)
245  * @param {Integer} [alphaFunction] The alpha function to use.
246  * @param {Integer} [horizontalBias] Whether to bias scrolling to left or right (by default no bias).
247  * @param {Integer} [verticalBias] Whether to bias scrolling to top or bottom (by default no bias).
248  * @example
249  *      // scroll direction bias is one of the following
250  *      dali.DIRECTION_BIAS_NONE           // Don't bias scroll snap
251  *      dali.DIRECTION_BIAS_LEFT           // Bias scroll snap to Left
252  *      dali.DIRECTION_BIAS_RIGHT          // Bias scroll snap to Right
253  *
254  *      scrollView.scrollToPosition( [150.0, 100.0], 0.5, dali.ALPHA_FUNCTION_EASE_IN_OUT, dali.DIRECTION_BIAS_LEFT, dali.DIRECTION_BIAS_NONE );
255  */
256 void ScrollViewApi::ScrollToPosition( const v8::FunctionCallbackInfo< v8::Value >& args)
257 {
258   v8::Isolate* isolate = args.GetIsolate();
259   v8::HandleScope handleScope( isolate );
260
261   Toolkit::ScrollView scrollView = GetScrollView( isolate, args );
262
263   bool found( false );
264   Vector2 position = V8Utils::GetVector2Parameter( PARAMETER_0, found, isolate, args );
265   if( !found )
266   {
267     DALI_SCRIPT_EXCEPTION( isolate, "bad position parameter" );
268     return;
269   }
270
271   float durationSeconds = V8Utils::GetFloatParameter( PARAMETER_1, found, isolate, args, scrollView.GetScrollSnapDuration() );
272
273   AlphaFunction alphaFunction = scrollView.GetScrollSnapAlphaFunction();
274
275   found = false;
276   int alpha = V8Utils::GetIntegerParameter( PARAMETER_2, found, isolate,  args, 0 );
277   if(found)
278   {
279     alphaFunction = static_cast<AlphaFunction::BuiltinFunction>(alpha);
280   }
281
282   Toolkit::DirectionBias horizontalBias = static_cast<Toolkit::DirectionBias>( V8Utils::GetIntegerParameter( PARAMETER_3, found, isolate, args, Toolkit::DirectionBiasNone ) );
283   Toolkit::DirectionBias verticalBias = static_cast<Toolkit::DirectionBias>( V8Utils::GetIntegerParameter( PARAMETER_4, found, isolate, args, Toolkit::DirectionBiasNone ) );
284
285   scrollView.ScrollTo( position, durationSeconds, alphaFunction, horizontalBias, verticalBias );
286 }
287
288 /**
289  * Scrolls the contents to the page with the given index.
290  *
291  * This is based on assumption that the page index starts from 0 and the
292  * position of each page is: [pageIndex * snapToInterval, 0].
293  *
294  * If no snap interval is defined, calling this API will cause unexpected
295  * behaviour.
296  *
297  * The biasing parameter is provided such that in scenarios with 2 pages
298  * in wrap mode, the application developer can decide whether to scroll
299  * left or right to get to the target page.
300  *
301  * @for ScrollView
302  * @method scrollToPage
303  * @param {Integer} pageIndex The index of the page to scroll to.
304  * @param {Float} [durationSeconds] The duration of the scroll animation in seconds (default value is scrollView.scrollSnapDuration)
305  * @param {Integer} [bias] Whether to bias scrolling to left or right (by default no bias).
306  * @example
307  *      // scroll direction bias is one of the following
308  *      dali.DIRECTION_BIAS_NONE           // Don't bias scroll snap
309  *      dali.DIRECTION_BIAS_LEFT           // Bias scroll snap to Left
310  *      dali.DIRECTION_BIAS_RIGHT          // Bias scroll snap to Right
311  *
312  *      scrollView.scrollToPage( 1, 0.5, dali.DIRECTION_BIAS_RIGHT );
313  */
314 void ScrollViewApi::ScrollToPage( const v8::FunctionCallbackInfo< v8::Value >& args)
315 {
316   v8::Isolate* isolate = args.GetIsolate();
317   v8::HandleScope handleScope( isolate );
318
319   Toolkit::ScrollView scrollView = GetScrollView( isolate, args );
320
321   bool found( false );
322   int pageIndex = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 );
323   if( !found )
324   {
325     DALI_SCRIPT_EXCEPTION( isolate, "bad page index parameter" );
326     return;
327   }
328
329   float durationSeconds = V8Utils::GetFloatParameter( PARAMETER_1, found, isolate, args, scrollView.GetScrollSnapDuration() );
330   Toolkit::DirectionBias bias = static_cast<Toolkit::DirectionBias>( V8Utils::GetIntegerParameter( PARAMETER_2, found, isolate, args, Toolkit::DirectionBiasNone ) );
331
332   scrollView.ScrollTo( pageIndex, durationSeconds, bias );
333 }
334
335 /**
336  * Scrolls the contents such that the given actor appears in the center of
337  * the scroll view.
338  *
339  * The actor must be a direct child of scroll view.
340  *
341  * @for ScrollView
342  * @method scrollToActor
343  * @param {Object} actor The actor to scroll to.
344  * @param {Float} [durationSeconds] The duration of the scroll animation in seconds (default value is scrollView.scrollSnapDuration)
345  * @example
346  *      scrollView.scrollToActor( childActor, 0.5 );
347  */
348 void ScrollViewApi::ScrollToActor( const v8::FunctionCallbackInfo< v8::Value >& args)
349 {
350   v8::Isolate* isolate = args.GetIsolate();
351   v8::HandleScope handleScope( isolate );
352
353   Toolkit::ScrollView scrollView = GetScrollView( isolate, args );
354
355   bool found( false );
356   Actor actor = V8Utils::GetActorParameter( 0, found, isolate, args );
357   if( !found )
358   {
359     DALI_SCRIPT_EXCEPTION( isolate, "invalid actor parameter" );
360     return;
361   }
362
363   float durationSeconds = V8Utils::GetFloatParameter( PARAMETER_1, found, isolate, args, scrollView.GetScrollSnapDuration() );
364
365   scrollView.ScrollTo( actor, durationSeconds );
366 }
367
368 /**
369  * Scrolls the content to the nearest snap point as specified by the snap interval.
370  * If already at snap points, it will not scroll.
371  *
372  * @for ScrollView
373  * @method scrollToSnapInterval
374  * @return {Boolean} True if snapping is needed or false if already at snap points
375  * @example
376  *      var success = scrollView.scrollToSnapInterval();
377  */
378 void ScrollViewApi::ScrollToSnapInterval( const v8::FunctionCallbackInfo< v8::Value >& args)
379 {
380   v8::Isolate* isolate = args.GetIsolate();
381   v8::HandleScope handleScope( isolate );
382
383   Toolkit::ScrollView scrollView = GetScrollView( isolate, args );
384
385   args.GetReturnValue().Set( v8::Boolean::New( isolate, scrollView.ScrollToSnapPoint() ) );
386 }
387
388 /**
389  * Set the alpha function of flick animation.
390  *
391  * @for ScrollView
392  * @method setScrollFlickAlphaFunction
393  * @param {Integer} alphaFunction The alpha function to use.
394  * @example
395  *      scrollView.setScrollFlickAlphaFunction( dali.ALPHA_FUNCTION_EASE_IN_OUT );
396  */
397 void ScrollViewApi::SetScrollFlickAlphaFunction( const v8::FunctionCallbackInfo< v8::Value >& args)
398 {
399   v8::Isolate* isolate = args.GetIsolate();
400   v8::HandleScope handleScope( isolate );
401
402   Toolkit::ScrollView scrollView = GetScrollView( isolate, args );
403
404   bool found( false );
405   int alphaFunction = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate,  args, 0 );
406   if( !found )
407   {
408     DALI_SCRIPT_EXCEPTION( isolate, "invalid alpha function parameter" );
409     return;
410   }
411   else
412   {
413     scrollView.SetScrollFlickAlphaFunction( static_cast<AlphaFunction::BuiltinFunction>(alphaFunction) );
414   }
415 }
416
417 /**
418  * Set the alpha function of snap animation.
419  *
420  * @for ScrollView
421  * @method setScrollSnapAlphaFunction
422  * @param {String} alphaFunction The alpha function to use.
423  * @example
424  *      scrollView.setScrollSnapAlphaFunction( dali.ALPHA_FUNCTION_EASE_IN_OUT );
425  */
426 void ScrollViewApi::SetScrollSnapAlphaFunction( const v8::FunctionCallbackInfo< v8::Value >& args)
427 {
428   v8::Isolate* isolate = args.GetIsolate();
429   v8::HandleScope handleScope( isolate );
430
431   Toolkit::ScrollView scrollView = GetScrollView( isolate, args );
432
433   bool found( false );
434   int alphaFunction = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate,  args, 0 );
435   if( !found )
436   {
437     DALI_SCRIPT_EXCEPTION( isolate, "invalid alpha function parameter" );
438     return;
439   }
440   else
441   {
442     scrollView.SetScrollSnapAlphaFunction( static_cast<AlphaFunction::BuiltinFunction>(alphaFunction) );
443   }
444 }
445
446 /**
447  * Set the alpha function of overshoot snap animation.
448  *
449  * @for ScrollView
450  * @method setSnapOvershootAlphaFunction
451  * @param {String} alphaFunction The alpha function to use.
452  * @example
453  *      scrollView.setSnapOvershootAlphaFunction( dali.ALPHA_FUNCTION_EASE_IN_OUT );
454  */
455 void ScrollViewApi::SetSnapOvershootAlphaFunction( const v8::FunctionCallbackInfo< v8::Value >& args)
456 {
457   v8::Isolate* isolate = args.GetIsolate();
458   v8::HandleScope handleScope( isolate );
459
460   Toolkit::ScrollView scrollView = GetScrollView( isolate, args );
461
462   bool found( false );
463   int alphaFunction = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate,  args, 0 );
464   if( !found )
465   {
466     DALI_SCRIPT_EXCEPTION( isolate, "invalid alpha function parameter" );
467     return;
468   }
469   else
470   {
471     scrollView.SetSnapOvershootAlphaFunction( static_cast<AlphaFunction::BuiltinFunction>(alphaFunction) );
472   }
473 }
474
475 } // namespace V8Plugin
476
477 } // namespace Dali