(Gestures) Extract out GestureData from Actor
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 6 Jun 2014 14:23:38 +0000 (15:23 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Tue, 10 Jun 2014 15:11:22 +0000 (16:11 +0100)
[problem]      Actor is too closely coupled with gesture-detectors.
[cause]        GestureData is private within Actor which stores info about gesture detection.
[solution]     Move GestureData out of actor-impl.cpp and Actor provides a method to retrieve this.

Change-Id: I534723f5cfb772c88f13d2d90ab97d8c64571f8f
Signed-off-by: Adeel Kazmi <adeel.kazmi@samsung.com>
dali/internal/event/actors/actor-impl.cpp
dali/internal/event/actors/actor-impl.h
dali/internal/event/events/actor-gesture-data.cpp [new file with mode: 0644]
dali/internal/event/events/actor-gesture-data.h [new file with mode: 0644]
dali/internal/event/events/gesture-detector-impl.cpp
dali/internal/file.list

index 80ec97f..1f926f0 100644 (file)
@@ -47,6 +47,7 @@
 #include <dali/internal/update/nodes/node-declarations.h>
 #include <dali/internal/update/animation/scene-graph-constraint.h>
 #include <dali/internal/event/effects/shader-effect-impl.h>
+#include <dali/internal/event/events/actor-gesture-data.h>
 #include <dali/internal/common/message.h>
 #include <dali/integration-api/debug.h>
 
 #include <dali/internal/event/dynamics/dynamics-world-impl.h>
 #endif
 
-#include <dali/internal/event/events/pan-gesture-detector-impl.h>
-#include <dali/internal/event/events/pinch-gesture-detector-impl.h>
-#include <dali/internal/event/events/long-press-gesture-detector-impl.h>
-#include <dali/internal/event/events/tap-gesture-detector-impl.h>
-
 using Dali::Internal::SceneGraph::Node;
 using Dali::Internal::SceneGraph::AnimatableProperty;
 using Dali::Internal::SceneGraph::PropertyBase;
@@ -182,90 +178,6 @@ namespace Internal
 unsigned int Actor::mActorCounter = 0;
 ActorContainer Actor::mNullChildren;
 
-// Encapsulate actor related gesture information
-struct GestureData
-{
-  /**
-   * Constructor
-   */
-  GestureData()
-  : gesturesRequired( Gesture::Type( 0 ) ),
-    panDetectors( NULL ),
-    pinchDetectors( NULL ),
-    longPressDetectors( NULL ),
-    tapDetectors( NULL )
-  {
-  }
-
-  /**
-   * Destructor
-   */
-  ~GestureData()
-  {
-    delete panDetectors;
-    delete pinchDetectors;
-    delete longPressDetectors;
-    delete tapDetectors;
-  }
-
-  /**
-   * Checks if the containers in GestureData are empty
-   */
-  bool Empty() const
-  {
-    return !panDetectors       &&
-           !pinchDetectors     &&
-           !longPressDetectors &&
-           !tapDetectors;
-  }
-
-  /**
-   * Template to add a detector to the appropriate container. Dynamically allocates the container
-   * only if it is used.
-   */
-  template< typename DetectorType, typename ContainerType >
-  void AddDetector( ContainerType*& containerPtr, GestureDetector* detector )
-  {
-    if ( NULL == containerPtr )
-    {
-      containerPtr = new ContainerType;
-    }
-
-    containerPtr->push_back( static_cast< DetectorType* >( detector ) );
-    gesturesRequired = Gesture::Type( gesturesRequired | detector->GetType() );
-  }
-
-  /**
-   * Template to remove a detector from the appropriate container. Deletes the container if it is
-   * no longer required.
-   */
-  template< typename ContainerType >
-  void RemoveDetector( ContainerType*& containerPtr, GestureDetector* detector )
-  {
-    if ( NULL != containerPtr )
-    {
-      ContainerType& container( *containerPtr );
-      typename ContainerType::iterator match( std::remove( container.begin(), container.end(), detector ) );
-      DALI_ASSERT_DEBUG( match != container.end() && "Actor does not have the detector" );
-      container.erase( match, container.end() );
-
-      if ( container.empty() )
-      {
-        gesturesRequired = Gesture::Type( gesturesRequired & ~detector->GetType() );
-        delete containerPtr;
-        containerPtr = NULL;
-      }
-    }
-  }
-
-  Gesture::Type gesturesRequired;
-
-  PanGestureDetectorContainer*       panDetectors;
-  PinchGestureDetectorContainer*     pinchDetectors;
-  LongPressGestureDetectorContainer* longPressDetectors;
-  TapGestureDetectorContainer*       tapDetectors;
-};
-
 #ifdef DYNAMICS_SUPPORT
 
 // Encapsulate actor related dynamics data
@@ -1976,89 +1888,20 @@ bool Actor::IsHittable() const
          IsNodeConnected();
 }
 
-void Actor::AddGestureDetector( GestureDetector& detector )
+ActorGestureData& Actor::GetGestureData()
 {
+  // Likely scenario is that once gesture-data is created for this actor, the actor will require
+  // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
   if ( NULL == mGestureData )
   {
-    mGestureData = new GestureData;
-  }
-
-  const Gesture::Type type( detector.GetType() );
-  switch ( type )
-  {
-    case Gesture::Pan:
-    {
-      mGestureData->AddDetector< PanGestureDetector, PanGestureDetectorContainer >( mGestureData->panDetectors, &detector );
-      break;
-    }
-
-    case Gesture::Pinch:
-    {
-      mGestureData->AddDetector< PinchGestureDetector, PinchGestureDetectorContainer >( mGestureData->pinchDetectors, &detector );
-      break;
-    }
-
-    case Gesture::LongPress:
-    {
-      mGestureData->AddDetector< LongPressGestureDetector, LongPressGestureDetectorContainer >( mGestureData->longPressDetectors, &detector );
-      break;
-    }
-
-    case Gesture::Tap:
-    {
-      mGestureData->AddDetector< TapGestureDetector, TapGestureDetectorContainer >( mGestureData->tapDetectors, &detector );
-      break;
-    }
-  }
-}
-
-void Actor::RemoveGestureDetector( GestureDetector& detector )
-{
-  if ( NULL != mGestureData )
-  {
-    switch ( detector.GetType() )
-    {
-      case Gesture::Pan:
-      {
-        mGestureData->RemoveDetector< PanGestureDetectorContainer >( mGestureData->panDetectors, &detector );
-        break;
-      }
-
-      case Gesture::Pinch:
-      {
-        mGestureData->RemoveDetector< PinchGestureDetectorContainer >( mGestureData->pinchDetectors, &detector );
-        break;
-      }
-
-      case Gesture::LongPress:
-      {
-        mGestureData->RemoveDetector< LongPressGestureDetectorContainer >( mGestureData->longPressDetectors, &detector );
-        break;
-      }
-
-      case Gesture::Tap:
-      {
-        mGestureData->RemoveDetector< TapGestureDetectorContainer >( mGestureData->tapDetectors, &detector );
-        break;
-      }
-    }
-
-    if ( mGestureData->Empty() )
-    {
-      delete mGestureData;
-      mGestureData = NULL;
-    }
+    mGestureData = new ActorGestureData;
   }
+  return *mGestureData;
 }
 
 bool Actor::IsGestureRequred( Gesture::Type type ) const
 {
-  bool required( false );
-  if ( NULL != mGestureData )
-  {
-    required = type & mGestureData->gesturesRequired;
-  }
-  return required;
+  return mGestureData && mGestureData->IsGestureRequred( type );
 }
 
 bool Actor::EmitTouchEventSignal(const TouchEvent& event)
index 5c78424..75f5eac 100644 (file)
@@ -50,11 +50,10 @@ namespace Internal
 {
 
 class Actor;
-class GestureDetector;
+class ActorGestureData;
 class RenderTask;
 class ShaderEffect;
 struct DynamicsData;
-struct GestureData;
 
 typedef IntrusivePtr<Actor>                   ActorPtr;
 typedef IntrusivePtr<ShaderEffect>            ShaderEffectPtr;
@@ -947,21 +946,14 @@ public:
   // Gestures
 
   /**
-   * Adds a gesture detector to the actor so that the actor is aware that it requires this type of
-   * gesture.
-   * @param[in] detector The detector being added.
-   * @note A raw pointer to the detector is stored, so the detector MUST remove itself when it is
-   * destroyed using RemoveGestureDetector()
+   * Retrieve the gesture data associated with this actor. The first call to this method will
+   * allocate space for the ActorGestureData so this should only be called if an actor really does
+   * require gestures.
+   * @return Reference to the ActorGestureData for this actor.
+   * @note Once the gesture-data is created for an actor it is likely that gestures are required
+   * throughout the actor's lifetime so it will only be deleted when the actor is destroyed.
    */
-  void AddGestureDetector( GestureDetector& detector );
-
-  /**
-   * Removes a previously added gesture detector from the actor. If no more gesture detectors of
-   * this type are registered with this actor then the actor will no longer be hit-tested for that
-   * gesture.
-   * @param[in] detector The detector to remove.
-   */
-  void RemoveGestureDetector( GestureDetector& detector );
+  ActorGestureData& GetGestureData();
 
   /**
    * Queries whether the actor requires the gesture type.
@@ -1332,7 +1324,7 @@ protected:
   DynamicsData*           mDynamicsData; ///< optional physics data
 #endif
 
-  GestureData*            mGestureData; /// Optional Gesture data. Only created when actor requires gestures
+  ActorGestureData*            mGestureData; /// Optional Gesture data. Only created when actor requires gestures
 
   ActorAttachmentPtr      mAttachment;   ///< Optional referenced attachment
   ShaderEffectPtr         mShaderEffect; ///< Optional referenced shader effect
diff --git a/dali/internal/event/events/actor-gesture-data.cpp b/dali/internal/event/events/actor-gesture-data.cpp
new file mode 100644 (file)
index 0000000..1b41d0a
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/actor-gesture-data.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+/**
+ * Template to add a detector to the appropriate container. Dynamically allocates the container only if it is used.
+ */
+template< typename DetectorType, typename ContainerType >
+inline void AddDetector( ContainerType*& containerPtr, GestureDetector* detector, Gesture::Type& gesturesRequired )
+{
+  if ( NULL == containerPtr )
+  {
+    containerPtr = new ContainerType;
+  }
+
+  containerPtr->push_back( static_cast< DetectorType* >( detector ) );
+  gesturesRequired = Gesture::Type( gesturesRequired | detector->GetType() );
+}
+
+/**
+ * Template to remove a detector from the appropriate container. Deletes the container if it is no longer required.
+ */
+template< typename ContainerType >
+inline void RemoveDetector( ContainerType*& containerPtr, GestureDetector* detector, Gesture::Type& gesturesRequired )
+{
+  if ( NULL != containerPtr )
+  {
+    ContainerType& container( *containerPtr );
+    typename ContainerType::iterator match( std::remove( container.begin(), container.end(), detector ) );
+    DALI_ASSERT_DEBUG( match != container.end() && "Actor does not have the detector" );
+    container.erase( match, container.end() );
+
+    if ( container.empty() )
+    {
+      gesturesRequired = Gesture::Type( gesturesRequired & ~detector->GetType() );
+      delete containerPtr;
+      containerPtr = NULL;
+    }
+  }
+}
+
+} // unnamed namespace
+
+ActorGestureData::ActorGestureData()
+: gesturesRequired( Gesture::Type( 0 ) ),
+  panDetectors( NULL ),
+  pinchDetectors( NULL ),
+  longPressDetectors( NULL ),
+  tapDetectors( NULL )
+{
+}
+
+ActorGestureData::~ActorGestureData()
+{
+  delete panDetectors;
+  delete pinchDetectors;
+  delete longPressDetectors;
+  delete tapDetectors;
+}
+
+void ActorGestureData::AddGestureDetector( GestureDetector& detector )
+{
+  const Gesture::Type type( detector.GetType() );
+  switch ( type )
+  {
+    case Gesture::Pan:
+    {
+      AddDetector< PanGestureDetector, PanGestureDetectorContainer >( panDetectors, &detector, gesturesRequired );
+      break;
+    }
+
+    case Gesture::Pinch:
+    {
+      AddDetector< PinchGestureDetector, PinchGestureDetectorContainer >( pinchDetectors, &detector, gesturesRequired );
+      break;
+    }
+
+    case Gesture::LongPress:
+    {
+      AddDetector< LongPressGestureDetector, LongPressGestureDetectorContainer >( longPressDetectors, &detector, gesturesRequired );
+      break;
+    }
+
+    case Gesture::Tap:
+    {
+      AddDetector< TapGestureDetector, TapGestureDetectorContainer >( tapDetectors, &detector, gesturesRequired );
+      break;
+    }
+  }
+}
+
+void ActorGestureData::RemoveGestureDetector( GestureDetector& detector )
+{
+  switch ( detector.GetType() )
+  {
+    case Gesture::Pan:
+    {
+      RemoveDetector< PanGestureDetectorContainer >( panDetectors, &detector, gesturesRequired );
+      break;
+    }
+
+    case Gesture::Pinch:
+    {
+      RemoveDetector< PinchGestureDetectorContainer >( pinchDetectors, &detector, gesturesRequired );
+      break;
+    }
+
+    case Gesture::LongPress:
+    {
+      RemoveDetector< LongPressGestureDetectorContainer >( longPressDetectors, &detector, gesturesRequired );
+      break;
+    }
+
+    case Gesture::Tap:
+    {
+      RemoveDetector< TapGestureDetectorContainer >( tapDetectors, &detector, gesturesRequired );
+      break;
+    }
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
diff --git a/dali/internal/event/events/actor-gesture-data.h b/dali/internal/event/events/actor-gesture-data.h
new file mode 100644 (file)
index 0000000..56cc947
--- /dev/null
@@ -0,0 +1,92 @@
+#ifndef __DALI_INTERNAL_ACTOR_GESTURE_DATA_H__
+#define __DALI_INTERNAL_ACTOR_GESTURE_DATA_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/events/pan-gesture-detector-impl.h>
+#include <dali/internal/event/events/pinch-gesture-detector-impl.h>
+#include <dali/internal/event/events/long-press-gesture-detector-impl.h>
+#include <dali/internal/event/events/tap-gesture-detector-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Holds gesture specific data for an Actor
+ */
+class ActorGestureData
+{
+public:
+
+  /**
+   * Constructor
+   */
+  ActorGestureData();
+
+  /**
+   * Non-virtual Destructor
+   */
+  ~ActorGestureData();
+
+  /**
+   * Adds a gesture detector to the data so that the owning actor is aware that it requires this
+   * type of gesture.
+   * @param[in] detector The detector being added.
+   * @note A raw pointer to the detector is stored, so the detector MUST remove itself when it is
+   * destroyed using RemoveGestureDetector()
+   */
+  void AddGestureDetector( GestureDetector& detector );
+
+  /**
+   * Removes a previously added gesture detector from the data. If no more gesture detectors of
+   * this type are registered then the actor owning this data will no longer be hit-tested for that
+   * gesture.
+   * @param[in] detector The detector to remove.
+   */
+  void RemoveGestureDetector( GestureDetector& detector );
+
+  /**
+   * Queries whether the actor requires the gesture type.
+   * @param[in] type The gesture type.
+   * @return true if the gesture is required, false otherwise.
+   */
+  inline bool IsGestureRequred( Gesture::Type type ) const
+  {
+    return type & gesturesRequired;
+  }
+
+private:
+
+  Gesture::Type gesturesRequired; ///< Stores which gestures are required
+
+  PanGestureDetectorContainer*       panDetectors;       ///< Pointer to a container of pan-detectors
+  PinchGestureDetectorContainer*     pinchDetectors;     ///< Pointer to a container of pinch-detectors
+  LongPressGestureDetectorContainer* longPressDetectors; ///< Pointer to a container of long-press-detectors
+  TapGestureDetectorContainer*       tapDetectors;       ///< Pointer to a container of tap-detectors
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ACTOR_GESTURE_DATA_H__
+
index 98c1481..3032227 100644 (file)
@@ -23,6 +23,7 @@
 
 // INTERNAL INCLUDES
 #include <dali/integration-api/debug.h>
+#include <dali/internal/event/events/actor-gesture-data.h>
 #include <dali/internal/event/events/gesture-event-processor.h>
 #include <dali/internal/event/common/thread-local-storage.h>
 #include <dali/internal/event/common/stage-impl.h>
@@ -33,11 +34,6 @@ namespace Dali
 namespace Internal
 {
 
-namespace
-{
-const std::string INVALID_PROPERTY; // Empty string for invalid calls
-}
-
 GestureDetector::GestureDetector(Gesture::Type type)
 : mType(type),
   mGestureEventProcessor(ThreadLocalStorage::Get().GetGestureEventProcessor())
@@ -52,7 +48,7 @@ GestureDetector::~GestureDetector()
     {
       Actor* actor( *iter );
       actor->RemoveObserver( *this );
-      actor->RemoveGestureDetector( *this );
+      actor->GetGestureData().RemoveGestureDetector( *this );
     }
 
     mAttachedActors.clear();
@@ -81,7 +77,7 @@ void GestureDetector::Attach(Actor& actor)
     actor.AddObserver(*this);
 
     // Add the detector to the actor (so the actor knows it requires this gesture when going through hit-test algorithm)
-    actor.AddGestureDetector( *this );
+    actor.GetGestureData().AddGestureDetector( *this );
 
     // Notification for derived classes
     OnActorAttach(actor);
@@ -99,8 +95,8 @@ void GestureDetector::Detach(Actor& actor)
       // We no longer need to observe the actor's destruction
       actor.RemoveObserver(*this);
 
-      // Remove detector from actor (so it is set to no longer requiring this gesture when going through the hit-test algorithm)
-      actor.RemoveGestureDetector( *this );
+      // Remove detector from actor-gesture-data
+      actor.GetGestureData().RemoveGestureDetector( *this );
 
       mAttachedActors.erase(match);
 
@@ -132,8 +128,8 @@ void GestureDetector::DetachAll()
       // We no longer need to observe the actor's destruction
       actor->RemoveObserver(*this);
 
-      // Remove detector from actor (so it is set to no longer requiring this gesture when going through the hit-test algorithm)
-      actor->RemoveGestureDetector( *this );
+      // Remove detector from actor-gesture-data
+      actor->GetGestureData().RemoveGestureDetector( *this );
 
       // Notification for derived classes
       OnActorDetach(*actor);
@@ -202,7 +198,7 @@ void GestureDetector::GetDefaultPropertyIndices( Property::IndexContainer& ) con
 
 const std::string& GestureDetector::GetDefaultPropertyName( Property::Index index ) const
 {
-  return INVALID_PROPERTY;
+  return String::EMPTY;
 }
 
 Property::Index GestureDetector::GetDefaultPropertyIndex(const std::string& name) const
index ecb527c..a87631a 100644 (file)
@@ -46,6 +46,7 @@ internal_src_files = \
   $(internal_src_dir)/event/common/type-registry-impl.cpp \
   $(internal_src_dir)/event/effects/shader-effect-impl.cpp \
   $(internal_src_dir)/event/effects/shader-factory.cpp \
+  $(internal_src_dir)/event/events/actor-gesture-data.cpp \
   $(internal_src_dir)/event/events/event-processor.cpp \
   $(internal_src_dir)/event/events/key-event-processor.cpp \
   $(internal_src_dir)/event/events/gesture-detector-impl.cpp \