(V8 Plugin) Use new Touch API
[platform/core/uifw/dali-toolkit.git] / plugins / dali-script-v8 / src / signals / signal-manager.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 "signal-manager.h"
20
21 // EXTERNAL INCLUDES
22 #include <cstring> // for strcmp
23 #include <dali/public-api/images/resource-image.h>
24 #include <dali/public-api/object/any.h>
25 #include <dali/public-api/events/pan-gesture-detector.h>
26 #include <dali/public-api/object/any.h>
27 #include <dali/public-api/images/image.h>
28 #include <dali/public-api/events/touch-data.h>
29 #include <dali/public-api/events/hover-event.h>
30 #include <dali/public-api/events/wheel-event.h>
31 #include <dali/public-api/events/key-event.h>
32 #include <dali/public-api/events/pan-gesture.h>
33 #include <dali/devel-api/object/weak-handle.h>
34
35 // INTERNAL INCLUDES
36 #include <v8-utils.h>
37 #include <object/handle-wrapper.h>
38 #include <object/property-value-wrapper.h>
39 #include <actors/actor-wrapper.h>
40 #include <image/image-wrapper.h>
41 #include <animation/animation-wrapper.h>
42 #include <stage/stage-wrapper.h>
43 #include <events/pan-gesture-detector-wrapper.h>
44 #include <toolkit/focus-manager/keyboard-focus-manager-wrapper.h>
45 #include <signals/dali-any-javascript-converter.h>
46
47
48
49 namespace Dali
50 {
51
52 namespace V8Plugin
53 {
54
55 namespace // un-named namespace
56 {
57 const char* const SIGNAL_TOUCH = "touch";
58 const char* const SIGNAL_HOVERED = "hovered";
59 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
60 const char* const SIGNAL_ON_STAGE = "onStage";
61 const char* const SIGNAL_OFF_STAGE = "offStage";
62 const char* const ANIMATION_SIGNAL_FINISHED = "finished";
63 const char* const SIGNAL_PAN_DETECTED = "panDetected";
64
65 const char* const STAGE_SIGNAL_KEY_EVENT = "keyEvent";
66 const char* const STAGE_SIGNAL_EVENT_PROCESSING_FINISHED = "eventProcessingFinished";
67 const char* const STAGE_SIGNAL_TOUCH = "touch";
68 const char* const SIGNAL_IMAGE_LOADING_FINISHED = "imageLoadingFinished";
69 const char* const SIGNAL_IMAGE_UPLOADED = "uploaded";
70
71 const char* const KEYBOARD_FOCUS_MANAGER_SIGNAL_PRE_FOCUS_CHANGE = "keyboardPreFocusChange";
72 const char* const KEYBOARD_FOCUS_MANAGER_SIGNAL_FOCUS_CHANGED = "keyboardFocusChanged";
73 const char* const KEYBOARD_FOCUS_MANAGER_SIGNAL_FOCUS_GROUP_CHANGED = "keyboardFocusGroupChanged";
74 const char* const KEYBOARD_FOCUS_MANAGER_SIGNAL_FOCUSED_ACTOR_ENTER_KEY = "keyboardFocusedActorEnterKey";
75 const unsigned int MAX_SIGNAL_NAME_LENGTH = 64;
76
77 } // un-named name space
78
79 class BaseJavaScriptCallback
80 {
81 public:
82
83   BaseJavaScriptCallback(  v8::Isolate* isolate,  const v8::Local<v8::Function>& callback )
84   :mIsolate( isolate ),mEmitInterface( NULL )
85   {
86     mCallback.Reset( isolate, callback);
87   }
88   ~BaseJavaScriptCallback()
89   {
90     mCallback.Reset();
91   };
92
93   bool IsFunction( const v8::Local<v8::Function>& function)
94   {
95     v8::HandleScope handleScope( mIsolate );
96     v8::Local<v8::Function> localCallback =  v8::Local<v8::Function>::New( mIsolate, mCallback );
97     return ( localCallback == function );
98   }
99
100   void Call( Dali::Any& returnValue, std::vector< Dali::Any >& data )
101   {
102     mEmitInterface->CallbackEnter();
103
104     v8::HandleScope handleScope( mIsolate );
105     v8::TryCatch tryCatch;
106
107     // create a vector of JavaScript arguments to pass to the JavaScript function
108     std::vector< v8::Local<v8::Value> > arguments;
109
110     for( unsigned int i = 0; i < data.size(); ++i )
111     {
112       // convert each Dali::Any object into a JavaScript object based on it's type
113       arguments.push_back( DaliAnyConverter::ConvertToJavaScriptObject( mIsolate, data[i]));
114     }
115
116     // call the javascript function
117     v8::Local<v8::Function> localCallback =  v8::Local<v8::Function>::New( mIsolate, mCallback );
118     v8::Local<v8::Value>  javaScriptReturnVal = v8::Local<v8::Value>::Cast( localCallback->Call( localCallback, arguments.size(), &arguments[0] ));
119
120     // Print errors that happened during execution.
121     if( tryCatch.HasCaught() )
122     {
123       V8Utils::ReportException( mIsolate, &tryCatch);
124       DALI_ASSERT_ALWAYS( 0 && "Script error \n");
125     }
126
127     // convert will log an error, if the return type we want isn't found
128     returnValue = DaliAnyConverter::ConvertToDaliAny( mIsolate,  javaScriptReturnVal, returnValue );
129
130     mEmitInterface->CallbackExit();
131
132   }
133
134   void SetEmitInterface( EmitNotificationInterface* interface)
135   {
136     mEmitInterface = interface;
137   }
138 protected:
139   v8::Isolate*                 mIsolate;
140   v8::Persistent<v8::Function> mCallback;
141   EmitNotificationInterface*   mEmitInterface;
142
143 };
144 /**
145  * base class for callback
146  */
147 class BaseCallBack : public ConnectionTracker
148 {
149 public:
150     BaseCallBack( v8::Isolate* isolate,  const v8::Local<v8::Function>& callback, const std::string& signalName )
151     :mSignalName( signalName ),
152      mJavaFunctor( isolate, callback)
153     {
154
155     }
156     void CallJavaScript(  Dali::Any& returnValue, std::vector< Dali::Any >& data )
157     {
158       mJavaFunctor.Call( returnValue, data);
159     }
160
161     bool IsFunction( const v8::Local<v8::Function>& function)
162     {
163       return mJavaFunctor.IsFunction(function);
164     }
165
166     void SetEmitInterface( EmitNotificationInterface* interface)
167     {
168       mJavaFunctor.SetEmitInterface( interface );
169     }
170     virtual ~BaseCallBack() {}
171
172     std::string mSignalName;
173     BaseJavaScriptCallback mJavaFunctor;
174 };
175
176 namespace
177 {
178
179 class ActorCallback :  public BaseCallBack
180 {
181 public:
182
183   ActorCallback(v8::Isolate* isolate,  const v8::Local<v8::Function>& callback ,const std::string& signalName, Actor actor )
184   : BaseCallBack( isolate, callback, signalName ),
185     mActor(actor)
186   {
187   }
188   bool OnTouch( Actor actor, const TouchData& touch )
189   {
190     std::vector< Dali::Any > arguments;  // Dali::Vector considers Dali::Any to be a non trivial type so won't compile
191     Dali::Any returnValue(false);
192     arguments.push_back( actor );
193     arguments.push_back( touch );
194     CallJavaScript( returnValue, arguments );
195     bool ret;
196     returnValue.Get(ret);
197     return ret;
198   }
199   bool OnHover( Actor actor, const HoverEvent& event)
200   {
201     std::vector< Dali::Any > arguments;  // Dali::Vector considers Dali::Any to be a non trivial type so won't compile
202     Dali::Any returnValue(false);
203     arguments.push_back( actor );
204     arguments.push_back( event );
205     CallJavaScript( returnValue, arguments );
206     bool ret;
207     returnValue.Get(ret);
208     return ret;
209   }
210   bool OnWheel( Actor actor, const WheelEvent& event)
211   {
212     std::vector< Dali::Any > arguments;
213     Dali::Any returnValue(false);
214     arguments.push_back( actor );
215     arguments.push_back( event );
216     CallJavaScript( returnValue, arguments );
217     bool ret;
218     returnValue.Get(ret);
219     return ret;
220   }
221   void OnStage( Actor actor)
222   {
223     std::vector< Dali::Any > arguments;
224     Dali::Any returnValue;          //no return
225     arguments.push_back( actor );
226     CallJavaScript( returnValue, arguments );
227   }
228   void OffStage( Actor actor)
229   {
230     std::vector< Dali::Any > arguments;
231     Dali::Any returnValue;          //no return
232     arguments.push_back( actor );
233     CallJavaScript( returnValue, arguments );
234   }
235
236   WeakHandle< Actor > mActor;
237
238 };
239
240 struct ActorGenericCallbackFunctor
241 {
242   ActorGenericCallbackFunctor(ActorCallback& callback) : callback(callback) { }
243   void operator()()
244   {
245     std::vector< Dali::Any > arguments;
246     Dali::Any returnValue;          //no return
247     arguments.push_back(callback.mActor.GetHandle()); //pass the actor handle as the parameter
248     callback.CallJavaScript( returnValue, arguments );
249   }
250
251   ActorCallback& callback;
252 };
253
254
255 class AnimationCallback :  public BaseCallBack
256 {
257 public:
258
259   AnimationCallback(v8::Isolate* isolate,  const v8::Local<v8::Function>& callback ,const std::string& signalName )
260   : BaseCallBack( isolate, callback, signalName )
261   {
262   }
263   void Finished( Animation& animation)
264   {
265     std::vector< Dali::Any > arguments;  // Dali::Vector considers Dali::Any to be a non trivial type so won't compile
266     Dali::Any returnValue;    //no return
267     arguments.push_back( animation );
268     CallJavaScript( returnValue, arguments );
269   }
270 };
271
272
273 class ImageCallback :  public BaseCallBack
274 {
275 public:
276
277   ImageCallback(v8::Isolate* isolate,  const v8::Local<v8::Function>& callback ,const std::string& signalName )
278   : BaseCallBack( isolate, callback, signalName )
279   {
280   }
281   void LoadingFinished( ResourceImage image)
282   {
283     std::vector< Dali::Any > arguments;  // Dali::Vector considers Dali::Any to be a non trivial type so won't compile
284     Dali::Any returnValue;  //no return
285     arguments.push_back( image );
286     CallJavaScript( returnValue, arguments );
287   }
288 };
289 class StageCallback :  public BaseCallBack
290 {
291 public:
292
293   StageCallback(v8::Isolate* isolate,  const v8::Local<v8::Function>& callback ,const std::string& signalName )
294   : BaseCallBack( isolate, callback, signalName )
295   {
296   }
297
298   void KeyEventSignal( const KeyEvent& keyEvent )
299   {
300     std::vector< Dali::Any > arguments;
301     Dali::Any returnValue;  //no return
302     arguments.push_back( keyEvent );
303     CallJavaScript( returnValue, arguments );
304   }
305   void EventProcessingFinishedSignal()
306   {
307     std::vector< Dali::Any > arguments;
308     Dali::Any returnValue;  //no return
309     CallJavaScript( returnValue, arguments );
310   }
311   void TouchSignal( const TouchData& touch )
312   {
313     std::vector< Dali::Any > arguments;
314     Dali::Any returnValue;   //no return
315     arguments.push_back( touch );
316     CallJavaScript( returnValue, arguments );
317   }
318 };
319
320 class KeyboardFocusCallback :  public BaseCallBack
321 {
322 public:
323
324   KeyboardFocusCallback(v8::Isolate* isolate,  const v8::Local<v8::Function>& callback ,const std::string& signalName )
325   : BaseCallBack( isolate, callback, signalName )
326   {
327   }
328
329   Actor PreFocusChangeSignal(Actor currentFocusedActor,
330                              Actor proposedActorToFocus,
331                              Toolkit::Control::KeyboardFocus::Direction direction  )
332   {
333     std::vector< Dali::Any > arguments;
334     Dali::Any returnValue = Actor();  // we want an actor as a return value
335
336     arguments.push_back( currentFocusedActor );
337     arguments.push_back( proposedActorToFocus );
338
339     std::string name = KeyboardFocusManagerWrapper::GetDirectionName( direction );
340     arguments.push_back( name );
341
342     CallJavaScript( returnValue, arguments );
343
344     Actor ret;
345     returnValue.Get(ret);
346     return ret;
347   }
348   void FocusChangedSignal(Actor originalFocusedActor, Actor currentFocusedActor)
349   {
350     std::vector< Dali::Any > arguments;
351     Dali::Any returnValue;  //no return
352     arguments.push_back( originalFocusedActor );
353     arguments.push_back( currentFocusedActor );
354     CallJavaScript( returnValue, arguments );
355   }
356   void FocusGroupSignal( Actor currentFocusedActor, bool forward )
357   {
358     std::vector< Dali::Any > arguments;
359     Dali::Any returnValue;   //no return
360     arguments.push_back( currentFocusedActor );
361     arguments.push_back( forward );
362     CallJavaScript( returnValue, arguments );
363   }
364   void EnterKeyPressedActorSignal( Actor enterKeyPressedActor )
365   {
366     std::vector< Dali::Any > arguments;
367     Dali::Any returnValue;   //no return
368     arguments.push_back( enterKeyPressedActor );
369     CallJavaScript( returnValue, arguments );
370   }
371 };
372
373 class PanGestureDetectorCallback :  public BaseCallBack
374 {
375 public:
376
377   PanGestureDetectorCallback(v8::Isolate* isolate,  const v8::Local<v8::Function>& callback ,const std::string& signalName )
378   : BaseCallBack( isolate, callback, signalName )
379   {
380   }
381   void OnPan( Actor actor, const PanGesture& panGesture)
382   {
383     std::vector< Dali::Any > arguments;
384     Dali::Any returnValue;    //no return
385     arguments.push_back( actor );
386     arguments.push_back( panGesture );
387     CallJavaScript( returnValue, arguments );
388   }
389 };
390
391 void ActorConnection( v8::Isolate* isolate,
392                                      v8::Local<v8::Function> javaScriptCallback,
393                                      ActorWrapper* actorWrapper,
394                                      const std::string& signalName,
395                                      Actor actor )
396 {
397   bool connected(true);
398
399   ActorCallback* callback =new ActorCallback( isolate, javaScriptCallback, signalName, actor );
400
401   if( strcmp( signalName.c_str(), SIGNAL_TOUCH ) == 0 )
402   {
403     actor.TouchSignal().Connect( callback, &ActorCallback::OnTouch );
404   }
405   else if( strcmp( signalName.c_str(), SIGNAL_HOVERED ) == 0 )
406   {
407     actor.HoveredSignal().Connect( callback, &ActorCallback::OnHover );
408   }
409   else if ( strcmp( signalName.c_str(), SIGNAL_WHEEL_EVENT ) == 0 )
410   {
411     actor.WheelEventSignal().Connect( callback, &ActorCallback::OnWheel );
412   }
413   else if ( strcmp( signalName.c_str(), SIGNAL_ON_STAGE ) == 0 )
414   {
415     actor.OnStageSignal().Connect( callback, &ActorCallback::OnStage);
416   }
417   else if ( strcmp( signalName.c_str(), SIGNAL_OFF_STAGE ) == 0 )
418   {
419     actor.OffStageSignal().Connect( callback, &ActorCallback::OffStage);
420   }
421   else
422   {
423     connected = actor.ConnectSignal( callback, signalName, ActorGenericCallbackFunctor(*callback) );
424   }
425
426   if( connected )
427   {
428     actorWrapper->GetSignalManager()->AddCallback( static_cast<BaseCallBack*>(callback) );
429   }
430   else
431   {
432     delete callback;
433     DALI_SCRIPT_EXCEPTION( isolate, "the signal is not available in this object.");
434   }
435 }
436
437 void AnimationConnection( v8::Isolate* isolate,
438                                      v8::Local<v8::Function> javaScriptCallback,
439                                      AnimationWrapper* animWrapper,
440                                      const std::string& signalName,
441                                      Animation anim )
442 {
443   if( signalName ==  ANIMATION_SIGNAL_FINISHED)
444   {
445     AnimationCallback* callback =new AnimationCallback( isolate, javaScriptCallback, signalName );
446     anim.FinishedSignal().Connect( callback, &AnimationCallback::Finished );
447     animWrapper->GetSignalManager()->AddCallback( static_cast<BaseCallBack*>(callback) );
448   }
449 }
450
451 void ImageConnection( v8::Isolate* isolate,
452                                      v8::Local<v8::Function> javaScriptCallback,
453                                      ImageWrapper* imageWrapper,
454                                      const std::string& signalName,
455                                      Image image)
456 {
457   // Nine patch will downcast to ResourceImage
458   ResourceImage resourceImage( ResourceImage::DownCast( image ) );
459   if( !resourceImage )
460   {
461     DALI_SCRIPT_EXCEPTION( isolate, "can only connect to Resource / NinePatch Images");
462     return;
463   }
464
465   if( strcmp( signalName.c_str(), SIGNAL_IMAGE_LOADING_FINISHED ) == 0 )
466   {
467     ImageCallback* callback =new ImageCallback( isolate, javaScriptCallback, signalName );
468
469     resourceImage.LoadingFinishedSignal().Connect( callback, &ImageCallback::LoadingFinished );
470     imageWrapper->GetSignalManager()->AddCallback( static_cast<BaseCallBack*>(callback) );
471   }
472   else if ( strcmp( signalName.c_str() , SIGNAL_IMAGE_UPLOADED ) == 0 )
473   {
474     ImageCallback* callback =new ImageCallback( isolate, javaScriptCallback, signalName );
475     resourceImage.LoadingFinishedSignal().Connect( callback, &ImageCallback::LoadingFinished );
476     imageWrapper->GetSignalManager()->AddCallback( static_cast<BaseCallBack*>(callback) );
477   }
478 }
479
480 void StageConnection( v8::Isolate* isolate,
481                                      v8::Local<v8::Function> javaScriptCallback,
482                                      StageWrapper* stageWrapper,
483                                      const std::string& signalName,
484                                      Stage stage)
485 {
486   bool connected( true );
487   StageCallback* callback =new StageCallback( isolate, javaScriptCallback, signalName );
488
489   if( strcmp( signalName.c_str() ,STAGE_SIGNAL_KEY_EVENT) == 0 )
490   {
491     stage.KeyEventSignal().Connect( callback, &StageCallback::KeyEventSignal );
492    }
493   else if ( strcmp( signalName.c_str(),  STAGE_SIGNAL_EVENT_PROCESSING_FINISHED ) == 0)
494   {
495     stage.EventProcessingFinishedSignal().Connect( callback, &StageCallback::EventProcessingFinishedSignal );
496   }
497   else if (strcmp( signalName.c_str(), STAGE_SIGNAL_TOUCH ) == 0 )
498   {
499     stage.TouchSignal().Connect( callback, &StageCallback::TouchSignal );
500   }
501   else
502   {
503     connected = false;
504   }
505
506   if( connected )
507   {
508     stageWrapper->GetSignalManager()->AddCallback( static_cast<BaseCallBack*>(callback) );
509   }
510   else
511   {
512     delete  callback;
513   }
514 }
515
516 void KeyboardFocusManagerConnection( v8::Isolate* isolate,
517       v8::Local<v8::Function> javaScriptCallback,
518       KeyboardFocusManagerWrapper* keyboardFocusWrapper,
519       const std::string& signalName,
520       Toolkit::KeyboardFocusManager keyboardFocusManager)
521 {
522   bool connected( true );
523   KeyboardFocusCallback* callback =new KeyboardFocusCallback( isolate, javaScriptCallback, signalName );
524
525   if( strcmp( signalName.c_str(), KEYBOARD_FOCUS_MANAGER_SIGNAL_PRE_FOCUS_CHANGE ) == 0 )
526   {
527     keyboardFocusManager.PreFocusChangeSignal().Connect( callback, &KeyboardFocusCallback::PreFocusChangeSignal );
528   }
529   else if ( strcmp( signalName.c_str(),  KEYBOARD_FOCUS_MANAGER_SIGNAL_FOCUS_CHANGED ) == 0 )
530   {
531     keyboardFocusManager.FocusChangedSignal().Connect( callback, &KeyboardFocusCallback::FocusChangedSignal );
532   }
533   else if ( strcmp( signalName.c_str(), KEYBOARD_FOCUS_MANAGER_SIGNAL_FOCUS_GROUP_CHANGED ) == 0 )
534   {
535     keyboardFocusManager.FocusGroupChangedSignal().Connect( callback, &KeyboardFocusCallback::FocusGroupSignal );
536   }
537   else if ( strcmp( signalName.c_str(), KEYBOARD_FOCUS_MANAGER_SIGNAL_FOCUSED_ACTOR_ENTER_KEY ) == 0 )
538   {
539     keyboardFocusManager.FocusedActorEnterKeySignal().Connect( callback, &KeyboardFocusCallback::EnterKeyPressedActorSignal );
540   }
541   else
542   {
543     connected = false;
544   }
545
546   if( connected )
547   {
548     keyboardFocusWrapper->GetSignalManager()->AddCallback( static_cast<BaseCallBack*>(callback) );
549   }
550   else
551   {
552     delete  callback;
553   }
554 }
555
556 void PanGestureDetectorConnection( v8::Isolate* isolate,
557                                      v8::Local<v8::Function> javaScriptCallback,
558                                      PanGestureDetectorWrapper* panGestureDetectorWrapper,
559                                      const std::string& signalName,
560                                      PanGestureDetector panGestureDetector )
561 {
562   if( strcmp( signalName.c_str() , SIGNAL_PAN_DETECTED ) == 0 )
563   {
564     PanGestureDetectorCallback* callback =new PanGestureDetectorCallback( isolate, javaScriptCallback, signalName );
565     panGestureDetector.DetectedSignal().Connect( callback, &PanGestureDetectorCallback::OnPan );
566     panGestureDetectorWrapper->GetSignalManager()->AddCallback( static_cast<BaseCallBack*>(callback) );
567   }
568 }
569
570 } // un-named namespace
571
572
573 SignalManager::SignalManager()
574 :mInsideCallback(false)
575 {
576
577 }
578 SignalManager::~SignalManager()
579 {
580   // the object owning the signal manager ( e.g. an actor wrapper ) has been deleted
581   // delete the callbacks objects
582   for( CallBackContainer::Iterator iter = mCallbacks.Begin(); iter != mCallbacks.End(); ++iter )
583   {
584       BaseCallBack* callback = (*iter);
585       delete callback;
586   }
587   for( CallBackContainer::Iterator iter = mDisconnectedCallbacks.Begin(); iter != mDisconnectedCallbacks.End(); ++iter )
588   {
589     BaseCallBack* callback = (*iter);
590     delete callback;
591   }
592 }
593
594
595 void SignalManager::SignalConnect( const v8::FunctionCallbackInfo< v8::Value >& args)
596 {
597   // format is
598   // first paramter =  signal to connect to
599   // Second parameter = function ( to run )
600   // args.This() = myActor
601   // e.g. myActor.Connect("touch", myJavaScriptActorTouched );
602
603   // Inside Callback on myJavaScriptActorTouched
604   // myActor.Disconnect("touch", myJavaScriptActorTouched );
605
606   v8::Isolate* isolate = args.GetIsolate();
607   v8::HandleScope handleScope( isolate );
608
609   if( !args[1]->IsFunction() )
610   {
611     DALI_SCRIPT_EXCEPTION(isolate, "function parameter not found ");
612     return;
613   }
614
615   // get the function
616   v8::Local<v8::Function> func =v8::Handle<v8::Function>::Cast(args[1]);
617
618   // get the handle wrapper
619   BaseWrappedObject* baseObject = BaseWrappedObject::UnWrap( isolate, args.This() );
620
621   // First paramter = signal name as a string
622   bool found( false );
623   std::string signal = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args );
624   if( !found )
625   {
626     DALI_SCRIPT_EXCEPTION(isolate, "signal name parameter not found ");
627     return;
628   }
629
630   if( signal.empty() || ( signal.length() > MAX_SIGNAL_NAME_LENGTH ) )
631   {
632     DALI_SCRIPT_EXCEPTION(isolate, "signal name length out of range");
633     return;
634   }
635   // We need to determine what type of function needs to be hooked
636   // see if we're connecting to an Actor
637   switch( baseObject->GetType() )
638   {
639     case BaseWrappedObject::ACTOR:
640     {
641       ActorWrapper* actorWrapper = static_cast< ActorWrapper*>( baseObject );
642       ActorConnection( isolate, func, actorWrapper, signal,  actorWrapper->GetActor() );
643       break;
644     }
645     case BaseWrappedObject::ANIMATION:
646     {
647       AnimationWrapper* animWrapper = static_cast< AnimationWrapper*>( baseObject );
648       AnimationConnection( isolate, func, animWrapper, signal, animWrapper->GetAnimation() );
649       break;
650     }
651     case BaseWrappedObject::IMAGE:
652     {
653       ImageWrapper* imageWrapper = static_cast< ImageWrapper*>( baseObject );
654       ImageConnection( isolate, func, imageWrapper, signal, imageWrapper->GetImage() );
655       break;
656     }
657     case BaseWrappedObject::STAGE:
658     {
659       StageWrapper* stageWrapper = static_cast< StageWrapper*>( baseObject );
660       StageConnection( isolate, func, stageWrapper, signal, stageWrapper->GetStage() );
661       break;
662     }
663     case BaseWrappedObject::KEYBOARD_FOCUS_MANAGER:
664     {
665       KeyboardFocusManagerWrapper* keyboardFocusWrapper = static_cast< KeyboardFocusManagerWrapper*>( baseObject );
666       KeyboardFocusManagerConnection( isolate, func, keyboardFocusWrapper, signal, keyboardFocusWrapper->GetKeyboardFocusManager() );
667       break;
668     }
669     case BaseWrappedObject::PAN_GESTURE_DETECTOR:
670     {
671       PanGestureDetectorWrapper* panGestureDetectorWrapper = static_cast< PanGestureDetectorWrapper*>( baseObject );
672       PanGestureDetectorConnection( isolate, func, panGestureDetectorWrapper, signal, panGestureDetectorWrapper->GetPanGestureDetector() );
673       break;
674     }
675     default:
676     {
677       DALI_SCRIPT_EXCEPTION( isolate, "object does not support connections");
678       break;
679     }
680   }
681
682 }
683
684 void SignalManager::SignalDisconnect( const v8::FunctionCallbackInfo< v8::Value >& args)
685 {
686   // we can get the function name.... use that to disconnect from the object
687   v8::Isolate* isolate = args.GetIsolate();
688   v8::HandleScope handleScope( isolate );
689
690   if( !args[1]->IsFunction() )
691   {
692     DALI_SCRIPT_EXCEPTION(isolate, "function parameter not found ");
693     return;
694   }
695
696   // get the function
697   v8::Local<v8::Function> func =v8::Handle<v8::Function>::Cast(args[1]);
698
699   // get the handle wrapper
700   BaseWrappedObject* baseObject = BaseWrappedObject::UnWrap( isolate, args.This() );
701
702   // First parameter = signal name as a string
703   bool found( false );
704   std::string signal = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args );
705   if( !found )
706   {
707     DALI_SCRIPT_EXCEPTION(isolate, "signal name parameter not found ");
708     return;
709   }
710
711   SignalManager* signalManager = baseObject->GetSignalManager();
712   if(signalManager )
713   {
714     signalManager->RemoveCallback( isolate, signal, func);
715   }
716
717
718 }
719 void SignalManager::AddCallback( BaseCallBack* callback )
720 {
721   // used by the callback to inform signal manager when it is being triggered.
722    callback->SetEmitInterface( this );
723
724    mCallbacks.PushBack( callback );
725 }
726 void SignalManager::RemoveCallback( v8::Isolate* isolate, const std::string& signalName, const v8::Local<v8::Function>& function )
727 {
728   // lets disconnect
729   for( CallBackContainer::Iterator iter = mCallbacks.Begin(); iter != mCallbacks.End(); ++iter )
730   {
731     BaseCallBack* callback = (*iter);
732     if( ( callback->mSignalName == signalName ) &&
733         ( callback->IsFunction(  function  )  )  )
734     {
735       mCallbacks.Erase( iter );
736
737       // if we're inside a callback::Call function, then deleting it will cause a seg fault
738       if( mInsideCallback )
739       {
740         callback->DisconnectAll();
741         mDisconnectedCallbacks.PushBack( callback );
742       }
743       else
744       {
745         delete callback;
746       }
747       return;
748     }
749   }
750 }
751
752 void SignalManager::CallbackEnter()
753 {
754   mInsideCallback = true;
755 }
756
757 void SignalManager::CallbackExit()
758 {
759   // this gets called when we've finished calling into JavaScript, e.g. as a result of animation finishing
760   // which is being listened to by a javascript function.
761
762   // it possible that inside the JavaScript call, it tries to disconnect.
763   // If this happens the callback is added to the mDisconnectedCallbacks list.
764   // We then delay deleting of the callback object until the JavaScript call has finished in this function.
765
766   mInsideCallback = false;
767
768   // lets delete any call backs that were disconnect during the JavaScript call
769   for( CallBackContainer::Iterator iter = mDisconnectedCallbacks.Begin(); iter != mDisconnectedCallbacks.End(); ++iter )
770   {
771     BaseCallBack* callback = (*iter);
772     delete callback;
773   }
774   mDisconnectedCallbacks.Clear();
775
776 }
777
778 } // namespace V8Plugin
779
780 } // namespace Dali