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