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