3f26d0b64522947560b1e9e280a31af87b195198
[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-event.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_TOUCHED = "touched";
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_TOUCHED = "touched";
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 TouchEvent& event)
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( event );
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 TouchedSignal( const TouchEvent& touchEvent)
312   {
313     std::vector< Dali::Any > arguments;
314     Dali::Any returnValue;   //no return
315     arguments.push_back( touchEvent );
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_TOUCHED ) == 0 )
402   {
403     actor.TouchedSignal().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   }
434 }
435
436 void AnimationConnection( v8::Isolate* isolate,
437                                      v8::Local<v8::Function> javaScriptCallback,
438                                      AnimationWrapper* animWrapper,
439                                      const std::string& signalName,
440                                      Animation anim )
441 {
442   if( signalName ==  ANIMATION_SIGNAL_FINISHED)
443   {
444     AnimationCallback* callback =new AnimationCallback( isolate, javaScriptCallback, signalName );
445     anim.FinishedSignal().Connect( callback, &AnimationCallback::Finished );
446     animWrapper->GetSignalManager()->AddCallback( static_cast<BaseCallBack*>(callback) );
447   }
448 }
449
450 void ImageConnection( v8::Isolate* isolate,
451                                      v8::Local<v8::Function> javaScriptCallback,
452                                      ImageWrapper* imageWrapper,
453                                      const std::string& signalName,
454                                      Image image)
455 {
456   // Nine patch will downcast to ResourceImage
457   ResourceImage resourceImage( ResourceImage::DownCast( image ) );
458   if( !resourceImage )
459   {
460     DALI_SCRIPT_EXCEPTION( isolate, "can only connect to Resource / NinePatch Images");
461     return;
462   }
463
464   if( strcmp( signalName.c_str(), SIGNAL_IMAGE_LOADING_FINISHED ) == 0 )
465   {
466     ImageCallback* callback =new ImageCallback( isolate, javaScriptCallback, signalName );
467
468     resourceImage.LoadingFinishedSignal().Connect( callback, &ImageCallback::LoadingFinished );
469     imageWrapper->GetSignalManager()->AddCallback( static_cast<BaseCallBack*>(callback) );
470   }
471   else if ( strcmp( signalName.c_str() , SIGNAL_IMAGE_UPLOADED ) == 0 )
472   {
473     ImageCallback* callback =new ImageCallback( isolate, javaScriptCallback, signalName );
474     resourceImage.LoadingFinishedSignal().Connect( callback, &ImageCallback::LoadingFinished );
475     imageWrapper->GetSignalManager()->AddCallback( static_cast<BaseCallBack*>(callback) );
476   }
477 }
478
479 void StageConnection( v8::Isolate* isolate,
480                                      v8::Local<v8::Function> javaScriptCallback,
481                                      StageWrapper* stageWrapper,
482                                      const std::string& signalName,
483                                      Stage stage)
484 {
485   bool connected( true );
486   StageCallback* callback =new StageCallback( isolate, javaScriptCallback, signalName );
487
488   if( strcmp( signalName.c_str() ,STAGE_SIGNAL_KEY_EVENT) == 0 )
489   {
490     stage.KeyEventSignal().Connect( callback, &StageCallback::KeyEventSignal );
491    }
492   else if ( strcmp( signalName.c_str(),  STAGE_SIGNAL_EVENT_PROCESSING_FINISHED ) == 0)
493   {
494     stage.EventProcessingFinishedSignal().Connect( callback, &StageCallback::EventProcessingFinishedSignal );
495   }
496   else if (strcmp( signalName.c_str(), STAGE_SIGNAL_TOUCHED ) == 0 )
497   {
498     stage.TouchedSignal().Connect( callback, &StageCallback::TouchedSignal );
499   }
500   else
501   {
502     connected = false;
503   }
504
505   if( connected )
506   {
507     stageWrapper->GetSignalManager()->AddCallback( static_cast<BaseCallBack*>(callback) );
508   }
509   else
510   {
511     delete  callback;
512   }
513 }
514
515 void KeyboardFocusManagerConnection( v8::Isolate* isolate,
516       v8::Local<v8::Function> javaScriptCallback,
517       KeyboardFocusManagerWrapper* keyboardFocusWrapper,
518       const std::string& signalName,
519       Toolkit::KeyboardFocusManager keyboardFocusManager)
520 {
521   bool connected( true );
522   KeyboardFocusCallback* callback =new KeyboardFocusCallback( isolate, javaScriptCallback, signalName );
523
524   if( strcmp( signalName.c_str(), KEYBOARD_FOCUS_MANAGER_SIGNAL_PRE_FOCUS_CHANGE ) == 0 )
525   {
526     keyboardFocusManager.PreFocusChangeSignal().Connect( callback, &KeyboardFocusCallback::PreFocusChangeSignal );
527   }
528   else if ( strcmp( signalName.c_str(),  KEYBOARD_FOCUS_MANAGER_SIGNAL_FOCUS_CHANGED ) == 0 )
529   {
530     keyboardFocusManager.FocusChangedSignal().Connect( callback, &KeyboardFocusCallback::FocusChangedSignal );
531   }
532   else if ( strcmp( signalName.c_str(), KEYBOARD_FOCUS_MANAGER_SIGNAL_FOCUS_GROUP_CHANGED ) == 0 )
533   {
534     keyboardFocusManager.FocusGroupChangedSignal().Connect( callback, &KeyboardFocusCallback::FocusGroupSignal );
535   }
536   else if ( strcmp( signalName.c_str(), KEYBOARD_FOCUS_MANAGER_SIGNAL_FOCUSED_ACTOR_ENTER_KEY ) == 0 )
537   {
538     keyboardFocusManager.FocusedActorEnterKeySignal().Connect( callback, &KeyboardFocusCallback::EnterKeyPressedActorSignal );
539   }
540   else
541   {
542     connected = false;
543   }
544
545   if( connected )
546   {
547     keyboardFocusWrapper->GetSignalManager()->AddCallback( static_cast<BaseCallBack*>(callback) );
548   }
549   else
550   {
551     delete  callback;
552   }
553 }
554
555 void PanGestureDetectorConnection( v8::Isolate* isolate,
556                                      v8::Local<v8::Function> javaScriptCallback,
557                                      PanGestureDetectorWrapper* panGestureDetectorWrapper,
558                                      const std::string& signalName,
559                                      PanGestureDetector panGestureDetector )
560 {
561   if( strcmp( signalName.c_str() , SIGNAL_PAN_DETECTED ) == 0 )
562   {
563     PanGestureDetectorCallback* callback =new PanGestureDetectorCallback( isolate, javaScriptCallback, signalName );
564     panGestureDetector.DetectedSignal().Connect( callback, &PanGestureDetectorCallback::OnPan );
565     panGestureDetectorWrapper->GetSignalManager()->AddCallback( static_cast<BaseCallBack*>(callback) );
566   }
567 }
568
569 } // un-named namespace
570
571
572 SignalManager::SignalManager()
573 :mInsideCallback(false)
574 {
575
576 }
577 SignalManager::~SignalManager()
578 {
579   // the object owning the signal manager ( e.g. an actor wrapper ) has been deleted
580   // delete the callbacks objects
581   for( CallBackContainer::Iterator iter = mCallbacks.Begin(); iter != mCallbacks.End(); ++iter )
582   {
583       BaseCallBack* callback = (*iter);
584       delete callback;
585   }
586   for( CallBackContainer::Iterator iter = mDisconnectedCallbacks.Begin(); iter != mDisconnectedCallbacks.End(); ++iter )
587   {
588     BaseCallBack* callback = (*iter);
589     delete callback;
590   }
591 }
592
593
594 void SignalManager::SignalConnect( const v8::FunctionCallbackInfo< v8::Value >& args)
595 {
596   // format is
597   // first paramter =  signal to connect to
598   // Second parameter = function ( to run )
599   // args.This() = myActor
600   // e.g. myActor.Connect("touched", myJavaScriptActorTouched );
601
602   // Inside Callback on myJavaScriptActorTouched
603   // myActor.Disconnect("touched", myJavaScriptActorTouched );
604
605   v8::Isolate* isolate = args.GetIsolate();
606   v8::HandleScope handleScope( isolate );
607
608   if( !args[1]->IsFunction() )
609   {
610     DALI_SCRIPT_EXCEPTION(isolate, "function parameter not found ");
611     return;
612   }
613
614   // get the function
615   v8::Local<v8::Function> func =v8::Handle<v8::Function>::Cast(args[1]);
616
617   // get the handle wrapper
618   BaseWrappedObject* baseObject = BaseWrappedObject::UnWrap( isolate, args.This() );
619
620   // First paramter = signal name as a string
621   bool found( false );
622   std::string signal = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args );
623   if( !found )
624   {
625     DALI_SCRIPT_EXCEPTION(isolate, "signal name parameter not found ");
626     return;
627   }
628
629   if( signal.empty() || ( signal.length() > MAX_SIGNAL_NAME_LENGTH ) )
630   {
631     DALI_SCRIPT_EXCEPTION(isolate, "signal name length out of range");
632     return;
633   }
634   // We need to determine what type of function needs to be hooked
635   // see if we're connecting to an Actor
636   switch( baseObject->GetType() )
637   {
638     case BaseWrappedObject::ACTOR:
639     {
640       ActorWrapper* actorWrapper = static_cast< ActorWrapper*>( baseObject );
641       ActorConnection( isolate, func, actorWrapper, signal,  actorWrapper->GetActor() );
642       break;
643     }
644     case BaseWrappedObject::ANIMATION:
645     {
646       AnimationWrapper* animWrapper = static_cast< AnimationWrapper*>( baseObject );
647       AnimationConnection( isolate, func, animWrapper, signal, animWrapper->GetAnimation() );
648       break;
649     }
650     case BaseWrappedObject::IMAGE:
651     {
652       ImageWrapper* imageWrapper = static_cast< ImageWrapper*>( baseObject );
653       ImageConnection( isolate, func, imageWrapper, signal, imageWrapper->GetImage() );
654       break;
655     }
656     case BaseWrappedObject::STAGE:
657     {
658       StageWrapper* stageWrapper = static_cast< StageWrapper*>( baseObject );
659       StageConnection( isolate, func, stageWrapper, signal, stageWrapper->GetStage() );
660       break;
661     }
662     case BaseWrappedObject::KEYBOARD_FOCUS_MANAGER:
663     {
664       KeyboardFocusManagerWrapper* keyboardFocusWrapper = static_cast< KeyboardFocusManagerWrapper*>( baseObject );
665       KeyboardFocusManagerConnection( isolate, func, keyboardFocusWrapper, signal, keyboardFocusWrapper->GetKeyboardFocusManager() );
666       break;
667     }
668     case BaseWrappedObject::PAN_GESTURE_DETECTOR:
669     {
670       PanGestureDetectorWrapper* panGestureDetectorWrapper = static_cast< PanGestureDetectorWrapper*>( baseObject );
671       PanGestureDetectorConnection( isolate, func, panGestureDetectorWrapper, signal, panGestureDetectorWrapper->GetPanGestureDetector() );
672       break;
673     }
674     default:
675     {
676       DALI_SCRIPT_EXCEPTION( isolate, "object does not support connections");
677       break;
678     }
679   }
680
681 }
682
683 void SignalManager::SignalDisconnect( const v8::FunctionCallbackInfo< v8::Value >& args)
684 {
685   // we can get the function name.... use that to disconnect from the object
686   v8::Isolate* isolate = args.GetIsolate();
687   v8::HandleScope handleScope( isolate );
688
689   if( !args[1]->IsFunction() )
690   {
691     DALI_SCRIPT_EXCEPTION(isolate, "function parameter not found ");
692     return;
693   }
694
695   // get the function
696   v8::Local<v8::Function> func =v8::Handle<v8::Function>::Cast(args[1]);
697
698   // get the handle wrapper
699   BaseWrappedObject* baseObject = BaseWrappedObject::UnWrap( isolate, args.This() );
700
701   // First parameter = signal name as a string
702   bool found( false );
703   std::string signal = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args );
704   if( !found )
705   {
706     DALI_SCRIPT_EXCEPTION(isolate, "signal name parameter not found ");
707     return;
708   }
709
710   SignalManager* signalManager = baseObject->GetSignalManager();
711   if(signalManager )
712   {
713     signalManager->RemoveCallback( isolate, signal, func);
714   }
715
716
717 }
718 void SignalManager::AddCallback( BaseCallBack* callback )
719 {
720   // used by the callback to inform signal manager when it is being triggered.
721    callback->SetEmitInterface( this );
722
723    mCallbacks.PushBack( callback );
724 }
725 void SignalManager::RemoveCallback( v8::Isolate* isolate, const std::string& signalName, const v8::Local<v8::Function>& function )
726 {
727   // lets disconnect
728   for( CallBackContainer::Iterator iter = mCallbacks.Begin(); iter != mCallbacks.End(); ++iter )
729   {
730     BaseCallBack* callback = (*iter);
731     if( ( callback->mSignalName == signalName ) &&
732         ( callback->IsFunction(  function  )  )  )
733     {
734       mCallbacks.Erase( iter );
735
736       // if we're inside a callback::Call function, then deleting it will cause a seg fault
737       if( mInsideCallback )
738       {
739         callback->DisconnectAll();
740         mDisconnectedCallbacks.PushBack( callback );
741       }
742       else
743       {
744         delete callback;
745       }
746       return;
747     }
748   }
749 }
750
751 void SignalManager::CallbackEnter()
752 {
753   mInsideCallback = true;
754 }
755
756 void SignalManager::CallbackExit()
757 {
758   // this gets called when we've finished calling into JavaScript, e.g. as a result of animation finishing
759   // which is being listened to by a javascript function.
760
761   // it possible that inside the JavaScript call, it tries to disconnect.
762   // If this happens the callback is added to the mDisconnectedCallbacks list.
763   // We then delay deleting of the callback object until the JavaScript call has finished in this function.
764
765   mInsideCallback = false;
766
767   // lets delete any call backs that were disconnect during the JavaScript call
768   for( CallBackContainer::Iterator iter = mDisconnectedCallbacks.Begin(); iter != mDisconnectedCallbacks.End(); ++iter )
769   {
770     BaseCallBack* callback = (*iter);
771     delete callback;
772   }
773   mDisconnectedCallbacks.Clear();
774
775 }
776
777 } // namespace V8Plugin
778
779 } // namespace Dali