{
GestureProcessor::GestureProcessor()
-: mCurrentGesturedActor( NULL )
+: mCurrentGesturedActor( NULL ),
+ mGesturedActorDisconnected(false)
{
}
mCurrentGesturedActor = &GetImplementation( actor );
mCurrentGesturedActor->AddObserver( *this );
}
+ mGesturedActorDisconnected = false;
}
void GestureProcessor::ResetActor()
{
mCurrentGesturedActor->RemoveObserver( *this );
mCurrentGesturedActor = NULL;
+ mGesturedActorDisconnected = false;
}
}
+Actor* GestureProcessor::GetCurrentGesturedActor()
+{
+ return mGesturedActorDisconnected ? NULL : mCurrentGesturedActor;
+}
+
void GestureProcessor::SceneObjectRemoved(ProxyObject& proxy)
{
- if ( mCurrentGesturedActor == &proxy )
+ if ( mCurrentGesturedActor == &proxy &&
+ !mGesturedActorDisconnected )
{
// Inform deriving classes.
OnGesturedActorStageDisconnection();
- proxy.RemoveObserver( *this );
- mCurrentGesturedActor = NULL;
+ // do not call proxy.RemoveObserver here, proxy is currently iterating through observers... you wouldnt want to upset proxy now would you?
+ mGesturedActorDisconnected = true;
}
}
*/
void ResetActor();
+ /**
+ * Returns the current gestured actor if it is on stage
+ *
+ * @return The current gestured actor
+ */
+ Actor* GetCurrentGesturedActor();
+
// For derived classes to override
/**
*/
void OnStageDisconnection( Dali::Actor actor );
-protected: // Data
+private: // Data
- Actor* mCurrentGesturedActor; ///< The current actor that has been gestured.
+ Actor* mCurrentGesturedActor; ///< The current actor that has been gestured.
+ bool mGesturedActorDisconnected; ///< Indicates whether the gestured actor has been disconnected from the scene
};
} // namespace Internal
case Gesture::Started:
{
- if ( mCurrentGesturedActor )
+ Actor* currentGesturedActor = GetCurrentGesturedActor();
+ if ( currentGesturedActor )
{
HitTestAlgorithm::Results hitTestResults;
HitTestAlgorithm::HitTest( mStage, longPressEvent.point, hitTestResults );
- if ( hitTestResults.actor && ( mCurrentGesturedActor == &GetImplementation( hitTestResults.actor ) ) )
+ if ( hitTestResults.actor && ( currentGesturedActor == &GetImplementation( hitTestResults.actor ) ) )
{
// Record the current render-task for Screen->Actor coordinate conversions
mCurrentRenderTask = hitTestResults.renderTask;
// Only send subsequent long press gesture signals if we processed the gesture when it started.
// Check if actor is still touchable.
- if ( mCurrentGesturedActor )
+ Actor* currentGesturedActor = GetCurrentGesturedActor();
+ if ( currentGesturedActor )
{
- if ( mCurrentGesturedActor->IsHittable() && !mCurrentEmitters.empty() && mCurrentRenderTask )
+ if ( currentGesturedActor->IsHittable() && !mCurrentEmitters.empty() && mCurrentRenderTask )
{
// Ensure actor is still attached to the emitters, if it is not then remove the emitter.
- LongPressGestureDetectorContainer::iterator endIter = std::remove_if( mCurrentEmitters.begin(), mCurrentEmitters.end(), IsNotAttachedFunctor(mCurrentGesturedActor) );
+ LongPressGestureDetectorContainer::iterator endIter = std::remove_if( mCurrentEmitters.begin(), mCurrentEmitters.end(), IsNotAttachedFunctor(currentGesturedActor) );
mCurrentEmitters.erase( endIter, mCurrentEmitters.end() );
if ( !mCurrentEmitters.empty() )
{
Vector2 actorCoords;
RenderTask& renderTaskImpl( GetImplementation( mCurrentRenderTask ) );
- mCurrentGesturedActor->ScreenToLocal( renderTaskImpl, actorCoords.x, actorCoords.y, longPressEvent.point.x, longPressEvent.point.y );
+ currentGesturedActor->ScreenToLocal( renderTaskImpl, actorCoords.x, actorCoords.y, longPressEvent.point.x, longPressEvent.point.y );
- EmitLongPressSignal( Dali::Actor( mCurrentGesturedActor ), mCurrentEmitters, longPressEvent, actorCoords );
+ EmitLongPressSignal( Dali::Actor( currentGesturedActor ), mCurrentEmitters, longPressEvent, actorCoords );
}
}
case Gesture::Started:
{
- if ( mCurrentGesturedActor )
+ if ( GetCurrentGesturedActor() )
{
// The pan gesture should only be sent to the gesture detector which first received it so that
// it can be told when the gesture ends as well.
HitTestAlgorithm::Results hitTestResults;
HitTestAlgorithm::HitTest( mStage, mPossiblePanPosition, hitTestResults ); // Hit test original possible position...
- if ( hitTestResults.actor && ( mCurrentGesturedActor == &GetImplementation( hitTestResults.actor ) ) )
+ if ( hitTestResults.actor && ( GetCurrentGesturedActor() == &GetImplementation( hitTestResults.actor ) ) )
{
// Record the current render-task for Screen->Actor coordinate conversions
mCurrentRenderTask = hitTestResults.renderTask;
// Only send subsequent pan gesture signals if we processed the pan gesture when it started.
// Check if actor is still touchable.
- if ( mCurrentGesturedActor )
+ Actor* currentGesturedActor = GetCurrentGesturedActor();
+ if ( currentGesturedActor )
{
- if ( mCurrentGesturedActor->IsHittable() && !mCurrentPanEmitters.empty() && mCurrentRenderTask )
+ if ( currentGesturedActor->IsHittable() && !mCurrentPanEmitters.empty() && mCurrentRenderTask )
{
PanGestureDetectorContainer outsideTouchesRangeEmitters;
// Removes emitters that no longer have the actor attached
// Also remove emitters whose touches are outside the range of the current pan event and add them to outsideTouchesRangeEmitters
PanGestureDetectorContainer::iterator endIter = std::remove_if( mCurrentPanEmitters.begin(), mCurrentPanEmitters.end(),
- IsNotAttachedAndOutsideTouchesRangeFunctor(mCurrentGesturedActor, panEvent.numberOfTouches, outsideTouchesRangeEmitters) );
+ IsNotAttachedAndOutsideTouchesRangeFunctor(currentGesturedActor, panEvent.numberOfTouches, outsideTouchesRangeEmitters) );
mCurrentPanEmitters.erase( endIter, mCurrentPanEmitters.end() );
Vector2 actorCoords;
if ( !outsideTouchesRangeEmitters.empty() || !mCurrentPanEmitters.empty() )
{
- mCurrentGesturedActor->ScreenToLocal( GetImplementation( mCurrentRenderTask ), actorCoords.x, actorCoords.y, panEvent.currentPosition.x, panEvent.currentPosition.y );
+ currentGesturedActor->ScreenToLocal( GetImplementation( mCurrentRenderTask ), actorCoords.x, actorCoords.y, panEvent.currentPosition.x, panEvent.currentPosition.y );
// EmitPanSignal checks whether we have a valid actor and whether the container we are passing in has emitters before it emits the pan.
- EmitPanSignal(Dali::Actor(mCurrentGesturedActor), outsideTouchesRangeEmitters, panEvent, actorCoords, Gesture::Finished, mCurrentRenderTask);
- EmitPanSignal(Dali::Actor(mCurrentGesturedActor), mCurrentPanEmitters, panEvent, actorCoords, panEvent.state, mCurrentRenderTask);
+ EmitPanSignal(Dali::Actor(currentGesturedActor), outsideTouchesRangeEmitters, panEvent, actorCoords, Gesture::Finished, mCurrentRenderTask);
+ EmitPanSignal(Dali::Actor(currentGesturedActor), mCurrentPanEmitters, panEvent, actorCoords, panEvent.state, mCurrentRenderTask);
}
if ( mCurrentPanEmitters.empty() )
// Only send subsequent pinch gesture signals if we processed the pinch gesture when it started.
// Check if actor is still touchable.
- if ( mCurrentGesturedActor )
+ Actor* currentGesturedActor = GetCurrentGesturedActor();
+ if ( currentGesturedActor )
{
- if ( mCurrentGesturedActor->IsHittable() && !mCurrentPinchEmitters.empty() && mCurrentRenderTask )
+ if ( currentGesturedActor->IsHittable() && !mCurrentPinchEmitters.empty() && mCurrentRenderTask )
{
// Ensure actor is still attached to the emitters, if it is not then remove the emitter.
- PinchGestureDetectorContainer::iterator endIter = std::remove_if( mCurrentPinchEmitters.begin(), mCurrentPinchEmitters.end(), IsNotAttachedFunctor(mCurrentGesturedActor) );
+ PinchGestureDetectorContainer::iterator endIter = std::remove_if( mCurrentPinchEmitters.begin(), mCurrentPinchEmitters.end(), IsNotAttachedFunctor(currentGesturedActor) );
mCurrentPinchEmitters.erase( endIter, mCurrentPinchEmitters.end() );
if ( !mCurrentPinchEmitters.empty() )
{
Vector2 actorCoords;
RenderTask& renderTaskImpl( GetImplementation(mCurrentRenderTask) );
- mCurrentGesturedActor->ScreenToLocal( renderTaskImpl, actorCoords.x, actorCoords.y, pinchEvent.centerPoint.x, pinchEvent.centerPoint.y );
+ currentGesturedActor->ScreenToLocal( renderTaskImpl, actorCoords.x, actorCoords.y, pinchEvent.centerPoint.x, pinchEvent.centerPoint.y );
- EmitPinchSignal( Dali::Actor(mCurrentGesturedActor), mCurrentPinchEmitters, pinchEvent, actorCoords );
+ EmitPinchSignal( Dali::Actor(currentGesturedActor), mCurrentPinchEmitters, pinchEvent, actorCoords );
}
else
{
case Gesture::Started:
{
- if ( mCurrentGesturedActor )
+ if ( GetCurrentGesturedActor() )
{
HitTestAlgorithm::Results hitTestResults;
HitTestAlgorithm::HitTest( mStage, tapEvent.point, hitTestResults );
- if ( hitTestResults.actor && ( mCurrentGesturedActor == &GetImplementation( hitTestResults.actor ) ) )
+ if ( hitTestResults.actor && ( GetCurrentGesturedActor() == &GetImplementation( hitTestResults.actor ) ) )
{
TapEventFunctor functor( tapEvent );
GestureDetectorContainer gestureDetectors;
}
TouchEventProcessor::ActorObserver::ActorObserver()
-: mActor ( NULL )
+: mActor ( NULL ),
+ mActorDisconnected(false)
{
DALI_LOG_TRACE_METHOD( gLogFilter );
}
Actor* TouchEventProcessor::ActorObserver::GetActor()
{
- return mActor;
+ return mActorDisconnected ? NULL : mActor;
}
void TouchEventProcessor::ActorObserver::SetActor( Actor* actor )
if ( mActor != actor )
{
- if ( mActor )
- {
- SceneObjectRemoved( *mActor );
- }
+ ResetActor();
mActor = actor;
}
}
+void TouchEventProcessor::ActorObserver::ResetActor()
+{
+ if ( mActor )
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Stop Observing: %p\n", mActor);
+ mActor->RemoveObserver( *this );
+ mActor = NULL;
+ mActorDisconnected = false;
+ }
+}
+
void TouchEventProcessor::ActorObserver::SceneObjectRemoved( ProxyObject& proxy )
{
DALI_LOG_TRACE_METHOD( gLogFilter );
if ( mActor == &proxy )
{
- proxy.RemoveObserver( *this );
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Stop Observing: %p\n", mActor);
- mActor = NULL;
+ // do not call proxy.RemoveObserver here, proxy is currently iterating through observers... you wouldnt want to upset proxy now would you?
+ mActorDisconnected = true;
}
}
*/
void SetActor( Actor* actor );
+ /**
+ * Resets the set actor and disconnects any connected signals.
+ */
+ void ResetActor();
+
private:
// Undefined
virtual void ProxyDestroyed(ProxyObject& proxy);
private:
- Actor* mActor; ///< Raw pointer to an Actor.
+ Actor* mActor; ///< Raw pointer to an Actor.
+ bool mActorDisconnected; ///< Indicates whether the actor has been disconnected from the scene
};
Stage& mStage; ///< Used to deliver touch events