Using SingletonService instead of Adaptor
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / public-api / controls / control-impl.cpp
index 1e420b1..e45436f 100644 (file)
@@ -62,6 +62,7 @@ Integration::Log::Filter* gLogFilter  = Integration::Log::Filter::New(Debug::NoL
 #endif
 
 const float MAX_FLOAT_VALUE( std::numeric_limits<float>::max() );
+const Vector3 MAX_SIZE( MAX_FLOAT_VALUE, MAX_FLOAT_VALUE, MAX_FLOAT_VALUE );
 const float BACKGROUND_ACTOR_Z_POSITION( -0.1f );
 
 BaseHandle Create()
@@ -73,28 +74,13 @@ TypeRegistration CONTROL_TYPE( typeid(Control), typeid(CustomActor), Create );
 
 // Property Registration after Internal::Control::Impl definition below
 
-TypeAction ACTION_TYPE_1(CONTROL_TYPE, Toolkit::Control::ACTION_CONTROL_ACTIVATED, &Internal::Control::DoAction);
+TypeAction ACTION_TYPE_1( CONTROL_TYPE, Toolkit::Control::ACTION_CONTROL_ACTIVATED, &Internal::Control::DoAction );
 
-/**
- * Helper class used to set the Control's size through the Actor's API or through children added.
- */
-class SetSizeLock
-{
-public:
-  SetSizeLock( bool& lock )
-  : mLock( lock )
-  {
-    mLock = true;
-  }
-
-  ~SetSizeLock()
-  {
-    mLock = false;
-  }
-
-private:
-  bool& mLock;
-};
+SignalConnectorType SIGNAL_CONNECTOR_1( CONTROL_TYPE, Toolkit::Control::SIGNAL_KEY_EVENT,     &Internal::Control::DoConnectSignal );
+SignalConnectorType SIGNAL_CONNECTOR_2( CONTROL_TYPE, Toolkit::Control::SIGNAL_TAPPED,        &Internal::Control::DoConnectSignal );
+SignalConnectorType SIGNAL_CONNECTOR_3( CONTROL_TYPE, Toolkit::Control::SIGNAL_PANNED,        &Internal::Control::DoConnectSignal );
+SignalConnectorType SIGNAL_CONNECTOR_4( CONTROL_TYPE, Toolkit::Control::SIGNAL_PINCHED,       &Internal::Control::DoConnectSignal );
+SignalConnectorType SIGNAL_CONNECTOR_5( CONTROL_TYPE, Toolkit::Control::SIGNAL_LONG_PRESSED,  &Internal::Control::DoConnectSignal );
 
 /**
  * Structure which holds information about the background of a control
@@ -233,40 +219,47 @@ void SetupBackgroundActor( Actor actor, Property::Index constrainingIndex, const
 namespace Internal
 {
 
-class Control::Impl : public ConnectionTrackerInterface
+class Control::Impl : public ConnectionTracker
 {
 public:
+
+  /**
+   * Size indices for mMinMaxSize array
+   */
+  enum
+  {
+    MIN_SIZE_INDEX = 0,
+    MAX_SIZE_INDEX = 1
+  };
+
+public:
   // Construction & Destruction
   Impl(Control& controlImpl)
-  : mControlImpl(controlImpl),
-    mInitialized( false ),
+  : mControlImpl( controlImpl ),
+    mBackground( NULL ),
+    mStartingPinchScale( NULL ),
+    mKeyEventSignalV2(),
     mPinchGestureDetector(),
     mPanGestureDetector(),
     mTapGestureDetector(),
     mLongPressGestureDetector(),
-    mStartingPinchScale(),
-    mLockSetSize( false ),
+    mCurrentSize(),
+    mNaturalSize(),
     mWidthPolicy( Toolkit::Control::Fixed ),
     mHeightPolicy( Toolkit::Control::Fixed ),
-    mSize(),
-    mSetSize(),
-    mMinimumSize(),
-    mMaximumSize( MAX_FLOAT_VALUE, MAX_FLOAT_VALUE, MAX_FLOAT_VALUE ),
-    mIsKeyboardNavigationSupported(false),
-    mIsKeyboardFocusGroup(false),
-    mKeyEventSignalV2(),
-    mBackground( NULL ),
-    mFlags( Control::CONTROL_BEHAVIOUR_NONE )
+    mFlags( Control::CONTROL_BEHAVIOUR_NONE ),
+    mInsideRelayout( false ),
+    mIsKeyboardNavigationSupported( false ),
+    mIsKeyboardFocusGroup( false ),
+    mInitialized( false )
   {
   }
 
   ~Impl()
   {
     // All gesture detectors will be destroyed so no need to disconnect.
-    if ( mBackground )
-    {
-      delete mBackground;
-    }
+    delete mBackground;
+    delete mStartingPinchScale;
   }
 
   // Gesture Detection Methods
@@ -291,30 +284,6 @@ public:
     mControlImpl.OnLongPress(longPress);
   }
 
-  /**
-   * @copydoc ConnectionTrackerInterface::SignalConnected
-   */
-  virtual void SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
-  {
-    mConnectionTracker.SignalConnected( slotObserver, callback );
-  }
-
-  /**
-   * @copydoc ConnectionTrackerInterface::SignalDisconnected
-   */
-  virtual void SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
-  {
-    mConnectionTracker.SignalDisconnected( slotObserver, callback );
-  }
-
-  /**
-   * @copydoc ConnectionTrackerInterface::GetConnectionCount
-   */
-  virtual std::size_t GetConnectionCount() const
-  {
-    return mConnectionTracker.GetConnectionCount();
-  }
-
   // Background Methods
 
   /**
@@ -473,13 +442,13 @@ public:
 
         case Toolkit::Control::PROPERTY_MINIMUM_SIZE:
         {
-          value = controlImpl.mImpl->mMinimumSize;
+          value = controlImpl.mImpl->GetMinimumSize();
           break;
         }
 
         case Toolkit::Control::PROPERTY_MAXIMUM_SIZE:
         {
-          value = controlImpl.mImpl->mMaximumSize;
+          value = controlImpl.mImpl->GetMaximumSize();
           break;
         }
 
@@ -494,44 +463,103 @@ public:
     return value;
   }
 
-  // Data
-
-  Control& mControlImpl;
-
-  bool mInitialized:1;
-
-  ConnectionTracker mConnectionTracker; // signal connection tracker
-
-  // Gesture Detection
-
-  PinchGestureDetector     mPinchGestureDetector;
-  PanGestureDetector       mPanGestureDetector;
-  TapGestureDetector       mTapGestureDetector;
-  LongPressGestureDetector mLongPressGestureDetector;
-
-  Vector3 mStartingPinchScale;       ///< The scale when a pinch gesture starts
-
-  // Relayout and size negotiation
-
-  bool mLockSetSize;                 ///< Used to avoid. Can't be a bitfield as a reference to this member is used in SetSizeLock helper class.
-
-  Toolkit::Control::SizePolicy mWidthPolicy;  ///< Stores the width policy.
-  Toolkit::Control::SizePolicy mHeightPolicy; ///< Stores the height policy.
+  /**
+   * Helper to get minimum size
+   * @return minimum size
+   */
+  inline const Vector3& GetMinimumSize()
+  {
+    if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
+    {
+      return mMinMaxSize[ MIN_SIZE_INDEX ];
+    }
+    else
+    {
+      // its not been allocated so its ZERO
+      return Vector3::ZERO;
+    }
+  }
+  /**
+   * Helper to Set minimum size
+   * @param size to set
+   */
+  inline void SetMinimumSize( const Vector3& size )
+  {
+    if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
+    {
+      mMinMaxSize[ MIN_SIZE_INDEX ] = size;
+    }
+    else
+    {
+      // its not been allocated so push the new value there
+      mMinMaxSize.PushBack( size );
+    }
+  }
 
-  Vector3 mSize;                     ///< Stores the current control's size.
-  Vector3 mSetSize;                  ///< Always stores the size set through the Actor's API. Useful when reset to the initial size is needed.
-  Vector3 mMinimumSize;              ///< Stores the control's minimum size.
-  Vector3 mMaximumSize;              ///< Stores the control's maximum size.
+  /**
+   * Helper to get maximum size
+   * @return maximum size
+   */
+  inline const Vector3& GetMaximumSize()
+  {
+    if( mMinMaxSize.Count() > MAX_SIZE_INDEX )
+    {
+      return mMinMaxSize[ MAX_SIZE_INDEX ];
+    }
+    else
+    {
+      // its not been allocated so its MAX_SIZE
+      return MAX_SIZE;
+    }
+  }
 
-  bool mIsKeyboardNavigationSupported;  ///< Stores whether keyboard navigation is supported by the control.
-  bool mIsKeyboardFocusGroup;        ///< Stores whether the control is a focus group.
+  /**
+   * Helper to Set minimum size
+   * @param size to set
+   */
+  inline void SetMaximumSize( const Vector3& size )
+  {
+    if( mMinMaxSize.Count() > MAX_SIZE_INDEX )
+    {
+      mMinMaxSize[ MAX_SIZE_INDEX ] = size;
+    }
+    else if( mMinMaxSize.Count() > MIN_SIZE_INDEX )
+    {
+      // max has not been allocated, but min has
+      mMinMaxSize.PushBack( size );
+    }
+    else
+    {
+      // min and max both unallocated so allocate both
+      mMinMaxSize.Resize( 2u ); // this will reserve and default construct two Vector3s
+      mMinMaxSize[ MAX_SIZE_INDEX ] = size;
+    }
+  }
 
-  Toolkit::Control::KeyEventSignalV2 mKeyEventSignalV2;
+  // Data
 
-  // Background
+  Control& mControlImpl;
   Background* mBackground;           ///< Only create the background if we use it
+  Vector3* mStartingPinchScale;      ///< The scale when a pinch gesture starts, TODO: consider removing this
+  Toolkit::Control::KeyEventSignalV2 mKeyEventSignalV2;
 
-  ControlBehaviour mFlags;           ///< Flags passed in from constructor
+  // Gesture Detection
+  PinchGestureDetector mPinchGestureDetector;
+  PanGestureDetector mPanGestureDetector;
+  TapGestureDetector mTapGestureDetector;
+  LongPressGestureDetector mLongPressGestureDetector;
+  // @todo change all these to Vector2 when we have a chance to sanitize the public API as well
+  Vector3 mCurrentSize; ///< Stores the current control's size, this is the negotiated size
+  Vector3 mNaturalSize; ///< Stores the size set through the Actor's API. This is size the actor wants to be. Useful when reset to the initial size is needed.
+  Dali::Vector< Vector3 > mMinMaxSize; ///< Stores the minimum and maximum size if they are set
+
+  Toolkit::Control::SizePolicy mWidthPolicy :3;  ///< Stores the width policy. 3 bits covers 8 values
+  Toolkit::Control::SizePolicy mHeightPolicy :3; ///< Stores the height policy. 3 bits covers 8 values
+  ControlBehaviour mFlags :4;             ///< Flags passed in from constructor. Need to increase this size when new enums are added
+  bool mInsideRelayout:1;                 ///< Detect when were in Relayout
+  bool mIsKeyboardNavigationSupported:1;  ///< Stores whether keyboard navigation is supported by the control.
+  bool mIsKeyboardFocusGroup:1;           ///< Stores whether the control is a focus group.
+  bool mInitialized:1;
 
   // Properties - these need to be members of Internal::Control::Impl as they need to functions within this class.
   static PropertyRegistration PROPERTY_1;
@@ -582,7 +610,10 @@ void Control::Initialize()
     Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
 
     // Register for style changes
-    styleManager.StyleChangeSignal().Connect( this, &ControlImpl::DoStyleChange );
+    styleManager.StyleChangeSignal().Connect( this, &Control::DoStyleChange );
+
+    // SetTheme
+    GetImpl( styleManager ).ApplyThemeStyle( GetOwner() );
   }
 
   mImpl->mInitialized = true;
@@ -748,12 +779,18 @@ void Control::OnThemeChange( Toolkit::StyleManager styleManager )
 
 void Control::OnPinch(PinchGesture pinch)
 {
-  if (pinch.state == Gesture::Started)
+  if( !( mImpl->mStartingPinchScale ) )
+  {
+    // lazy allocate
+    mImpl->mStartingPinchScale = new Vector3;
+  }
+
+  if( pinch.state == Gesture::Started )
   {
-    mImpl->mStartingPinchScale = Self().GetCurrentScale();
+    *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale();
   }
 
-  Self().SetScale(mImpl->mStartingPinchScale * pinch.scale);
+  Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale );
 }
 
 void Control::OnStageConnection()
@@ -802,16 +839,16 @@ void Control::OnChildRemove(Actor& child)
 
 void Control::OnSizeSet(const Vector3& targetSize)
 {
-  if( ( !mImpl->mLockSetSize ) && ( targetSize != mImpl->mSetSize ) )
+  if( ( !mImpl->mInsideRelayout ) && ( targetSize != mImpl->mNaturalSize ) )
   {
     // Only updates size if set through Actor's API
-    mImpl->mSetSize = targetSize;
+    mImpl->mNaturalSize = targetSize;
   }
 
-  if( targetSize != mImpl->mSize )
+  if( targetSize != mImpl->mCurrentSize )
   {
     // Update control size.
-    mImpl->mSize = targetSize;
+    mImpl->mCurrentSize = targetSize;
 
     // Notify derived classes.
     OnControlSizeSet( targetSize );
@@ -820,7 +857,7 @@ void Control::OnSizeSet(const Vector3& targetSize)
 
 void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
 {
-  // Do Nothing
+  // @todo consider animating negotiated child sizes to target size
 }
 
 bool Control::OnTouchEvent(const TouchEvent& event)
@@ -914,6 +951,50 @@ bool Control::DoAction(BaseObject* object, const std::string& actionName, const
   return ret;
 }
 
+bool Control::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  Dali::BaseHandle handle( object );
+
+  bool connected( false );
+  Toolkit::Control control = Toolkit::Control::DownCast(handle);
+  if ( control )
+  {
+    Control& controlImpl( control.GetImplementation() );
+    connected = true;
+
+    if ( Toolkit::Control::SIGNAL_KEY_EVENT == signalName )
+    {
+      controlImpl.KeyEventSignal().Connect( tracker, functor );
+    }
+    else if( Toolkit::Control::SIGNAL_TAPPED == signalName )
+    {
+      controlImpl.EnableGestureDetection( Gesture::Tap );
+      controlImpl.GetTapGestureDetector().DetectedSignal().Connect( tracker, functor );
+    }
+    else if( Toolkit::Control::SIGNAL_PANNED == signalName )
+    {
+      controlImpl.EnableGestureDetection( Gesture::Pan );
+      controlImpl.GetPanGestureDetector().DetectedSignal().Connect( tracker, functor );
+    }
+    else if( Toolkit::Control::SIGNAL_PINCHED == signalName )
+    {
+      controlImpl.EnableGestureDetection( Gesture::Pinch );
+      controlImpl.GetPinchGestureDetector().DetectedSignal().Connect( tracker, functor );
+    }
+    else if( Toolkit::Control::SIGNAL_LONG_PRESSED == signalName )
+    {
+      controlImpl.EnableGestureDetection( Gesture::LongPress );
+      controlImpl.GetLongPressGestureDetector().DetectedSignal().Connect( tracker, functor );
+    }
+    else
+    {
+      // signalName does not match any signal
+      connected = false;
+    }
+  }
+  return connected;
+}
+
 void Control::DoStyleChange( Toolkit::StyleManager styleManager, StyleChange change )
 {
   if( change.themeChange )
@@ -922,9 +1003,6 @@ void Control::DoStyleChange( Toolkit::StyleManager styleManager, StyleChange cha
   }
   else if( change.defaultFontChange || change.defaultFontSizeChange )
   {
-    // This OnStyleChange(StyleChange change ) is deprecated, use OnFontChange instead
-    OnStyleChange( change );
-
     OnFontChange( change.defaultFontChange, change.defaultFontSizeChange );
   }
 }
@@ -961,9 +1039,11 @@ void Control::GetSizePolicy( Toolkit::Control::SizePolicy& widthPolicy, Toolkit:
 
 void Control::SetMinimumSize( const Vector3& size )
 {
-  if ( mImpl->mMinimumSize != size )
+  const Vector3& minSize = mImpl->GetMinimumSize();
+  if ( fabsf( minSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
+       fabsf( minSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
   {
-    mImpl->mMinimumSize = size;
+    mImpl->SetMinimumSize( size );
 
     // Only relayout if our control is using the minimum or range policy.
     if ( ( mImpl->mHeightPolicy == Toolkit::Control::Minimum ) || ( mImpl->mWidthPolicy  == Toolkit::Control::Minimum ) ||
@@ -976,14 +1056,16 @@ void Control::SetMinimumSize( const Vector3& size )
 
 const Vector3& Control::GetMinimumSize() const
 {
-  return mImpl->mMinimumSize;
+  return mImpl->GetMinimumSize();
 }
 
 void Control::SetMaximumSize( const Vector3& size )
 {
-  if ( mImpl->mMaximumSize != size )
+  const Vector3& maxSize = mImpl->GetMaximumSize();
+  if ( fabsf( maxSize.width - size.width ) > Math::MACHINE_EPSILON_1000 ||
+       fabsf( maxSize.height - size.height ) > Math::MACHINE_EPSILON_1000 )
   {
-    mImpl->mMaximumSize = size;
+    mImpl->SetMaximumSize( size );
 
     // Only relayout if our control is using the maximum or range policy.
     if ( ( mImpl->mHeightPolicy == Toolkit::Control::Maximum ) || ( mImpl->mWidthPolicy  == Toolkit::Control::Maximum ) ||
@@ -996,22 +1078,22 @@ void Control::SetMaximumSize( const Vector3& size )
 
 const Vector3& Control::GetMaximumSize() const
 {
-  return mImpl->mMaximumSize;
+  return mImpl->GetMaximumSize();
 }
 
 Vector3 Control::GetNaturalSize()
 {
   // could be overridden in derived classes.
-  return mImpl->mSetSize;
+  return mImpl->mNaturalSize;
 }
 
 float Control::GetHeightForWidth( float width )
 {
   // could be overridden in derived classes.
   float height( 0.0f );
-  if ( mImpl->mSetSize.width > 0.0f )
+  if ( mImpl->mNaturalSize.width > 0.0f )
   {
-    height = mImpl->mSetSize.height * width / mImpl->mSetSize.width;
+    height = mImpl->mNaturalSize.height * width / mImpl->mNaturalSize.width;
   }
   return height;
 }
@@ -1020,21 +1102,21 @@ float Control::GetWidthForHeight( float height )
 {
   // could be overridden in derived classes.
   float width( 0.0f );
-  if ( mImpl->mSetSize.height > 0.0f )
+  if ( mImpl->mNaturalSize.height > 0.0f )
   {
-    width = mImpl->mSetSize.width * height / mImpl->mSetSize.height;
+    width = mImpl->mNaturalSize.width * height / mImpl->mNaturalSize.height;
   }
   return width;
 }
 
 const Vector3& Control::GetControlSize() const
 {
-  return mImpl->mSize;
+  return mImpl->mCurrentSize;
 }
 
 const Vector3& Control::GetSizeSet() const
 {
-  return mImpl->mSetSize;
+  return mImpl->mNaturalSize;
 }
 
 void Control::SetKeyInputFocus()
@@ -1073,13 +1155,13 @@ void Control::RelayoutRequest()
   }
 }
 
-void Control::Relayout( Vector2 size, ActorSizeContainer& container )
+void Control::Relayout(Vector2 size, ActorSizeContainer& container)
 {
   // Avoids relayout again when OnSizeSet callback arrives.
-  {
-    SetSizeLock lock( mImpl->mLockSetSize );
-    Self().SetSize( size );
-  }
+  mImpl->mInsideRelayout = true;
+  Self().SetSize( size );
+  // @todo this really needs to be at the end of method but not sure why the scope used to be only the SetSize, needs to be cleaned up in size negotiation rework
+  mImpl->mInsideRelayout = false;
 
   // Only relayout controls which requested to be relaid out.
   OnRelaidOut( size, container );
@@ -1120,7 +1202,7 @@ void Control::NegotiateSize( Vector2 allocatedSize, ActorSizeContainer& containe
     if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
     {
       // If a control says it has a fixed size, then use the size set by the application / control.
-      Vector2 setSize( mImpl->mSetSize );
+      Vector2 setSize( mImpl->mNaturalSize );
       if ( setSize != Vector2::ZERO )
       {
         size = setSize;
@@ -1145,9 +1227,9 @@ void Control::NegotiateSize( Vector2 allocatedSize, ActorSizeContainer& containe
     else
     {
       // Width is fixed so if the application / control has set it, then use that.
-      if ( !EqualsZero( mImpl->mSetSize.width ) )
+      if ( !EqualsZero( mImpl->mNaturalSize.width ) )
       {
-        size.width = mImpl->mSetSize.width;
+        size.width = mImpl->mNaturalSize.width;
       }
       else
       {
@@ -1159,7 +1241,7 @@ void Control::NegotiateSize( Vector2 allocatedSize, ActorSizeContainer& containe
       size.height = GetHeightForWidth( size.width );
 
       // Ensure height is within our policy rules
-      size.height = Calculate( mImpl->mHeightPolicy, mImpl->mMinimumSize.height, mImpl->mMaximumSize.height, size.height );
+      size.height = Calculate( mImpl->mHeightPolicy, GetMinimumSize().height, GetMaximumSize().height, size.height );
     }
   }
   else
@@ -1167,9 +1249,9 @@ void Control::NegotiateSize( Vector2 allocatedSize, ActorSizeContainer& containe
     if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
     {
       // Height is fixed so if the application / control has set it, then use that.
-      if ( !EqualsZero( mImpl->mSetSize.height ) )
+      if ( !EqualsZero( mImpl->mNaturalSize.height ) )
       {
-        size.height = mImpl->mSetSize.height;
+        size.height = mImpl->mNaturalSize.height;
       }
       else
       {
@@ -1181,14 +1263,14 @@ void Control::NegotiateSize( Vector2 allocatedSize, ActorSizeContainer& containe
       size.width = GetWidthForHeight( size.height );
 
       // Ensure width is within our policy rules
-      size.width = Calculate( mImpl->mWidthPolicy, mImpl->mMinimumSize.width, mImpl->mMaximumSize.width, size.width );
+      size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, size.width );
     }
     else
     {
       // Width and height are BOTH flexible.
       // Calculate the width and height using the policy rules.
-      size.width = Calculate( mImpl->mWidthPolicy, mImpl->mMinimumSize.width, mImpl->mMaximumSize.width, allocatedSize.width );
-      size.height = Calculate( mImpl->mHeightPolicy, mImpl->mMinimumSize.height, mImpl->mMaximumSize.height, allocatedSize.height );
+      size.width = Calculate( mImpl->mWidthPolicy, mImpl->GetMinimumSize().width, mImpl->GetMaximumSize().width, allocatedSize.width );
+      size.height = Calculate( mImpl->mHeightPolicy, mImpl->GetMinimumSize().height, mImpl->GetMaximumSize().height, allocatedSize.height );
     }
   }
 
@@ -1248,17 +1330,6 @@ void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* call
   mImpl->SignalDisconnected( slotObserver, callback );
 }
 
-std::size_t Control::GetConnectionCount() const
-{
-  return mImpl->GetConnectionCount();
-}
-
-Control::Control( bool requiresTouchEvents )
-: CustomActorImpl( requiresTouchEvents ),
-  mImpl(new Impl(*this))
-{
-}
-
 Control::Control( ControlBehaviour behaviourFlags )
 : CustomActorImpl( behaviourFlags & REQUIRES_TOUCH_EVENTS ),
   mImpl(new Impl(*this))