[dali_1.0.21] Merge branch 'tizen'
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / public-api / controls / control-impl.cpp
index b2fb483..d678af6 100644 (file)
@@ -1,32 +1,40 @@
-//
-// Copyright (c) 2014 Samsung Electronics Co., Ltd.
-//
-// Licensed under the Flora License, Version 1.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://floralicense.org/license/
-//
-// 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.
-//
+/*
+ * 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-toolkit/public-api/controls/control-impl.h>
 
-#include <boost/thread/tss.hpp>
+// EXTERNAL INCLUDES
 #include <stack>
-
+#include <dali/public-api/actors/image-actor.h>
+#include <dali/public-api/actors/mesh-actor.h>
+#include <dali/public-api/animation/constraints.h>
+#include <dali/public-api/geometry/mesh.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/scripting/scripting.h>
 #include <dali/integration-api/debug.h>
 
-#include "dali-toolkit/internal/controls/style-change-processor.h"
-#include "dali-toolkit/internal/controls/relayout-controller.h"
-#include "dali-toolkit/internal/controls/relayout-helper.h"
-#include "dali-toolkit/public-api/focus-manager/keyinput-focus-manager.h"
-#include "dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h"
+#include <dali-toolkit/internal/controls/relayout-controller.h>
+#include <dali-toolkit/internal/controls/relayout-helper.h>
+#include <dali-toolkit/public-api/focus-manager/keyinput-focus-manager.h>
+#include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
 #include <dali-toolkit/public-api/controls/control.h>
+#include <dali-toolkit/public-api/styling/style-manager.h>
+#include <dali-toolkit/internal/styling/style-manager-impl.h>
 
 namespace Dali
 {
@@ -34,50 +42,51 @@ namespace Dali
 namespace Toolkit
 {
 
-const Property::Index Control::PROPERTY_BACKGROUND_COLOR      = ControlImpl::CONTROL_PROPERTY_START_INDEX;
-const Property::Index Control::PROPERTY_BACKGROUND            = ControlImpl::CONTROL_PROPERTY_START_INDEX + 1;
+const Property::Index Control::PROPERTY_BACKGROUND_COLOR      = Internal::Control::CONTROL_PROPERTY_START_INDEX;
+const Property::Index Control::PROPERTY_BACKGROUND            = Internal::Control::CONTROL_PROPERTY_START_INDEX + 1;
+const Property::Index Control::PROPERTY_WIDTH_POLICY          = Internal::Control::CONTROL_PROPERTY_START_INDEX + 2;
+const Property::Index Control::PROPERTY_HEIGHT_POLICY         = Internal::Control::CONTROL_PROPERTY_START_INDEX + 3;
+const Property::Index Control::PROPERTY_MINIMUM_SIZE          = Internal::Control::CONTROL_PROPERTY_START_INDEX + 4;
+const Property::Index Control::PROPERTY_MAXIMUM_SIZE          = Internal::Control::CONTROL_PROPERTY_START_INDEX + 5;
+const Property::Index Control::PROPERTY_KEY_INPUT_FOCUS       = Internal::Control::CONTROL_PROPERTY_START_INDEX + 6;
 
 namespace
 {
 
+const Scripting::StringEnum< Control::SizePolicy > SIZE_POLICY_STRING_TABLE[] =
+{
+  { "FIXED",      Control::Fixed      },
+  { "MINIMUM",    Control::Minimum    },
+  { "MAXIMUM",    Control::Maximum    },
+  { "RANGE",      Control::Range      },
+  { "FLEXIBLE",   Control::Flexible   },
+};
+const unsigned int SIZE_POLICY_STRING_TABLE_COUNT = sizeof( SIZE_POLICY_STRING_TABLE ) / sizeof( SIZE_POLICY_STRING_TABLE[0] );
+
 #if defined(DEBUG_ENABLED)
 Integration::Log::Filter* gLogFilter  = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_CONTROL");
 #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()
 {
-  return ControlImpl::New();
+  return Internal::Control::New();
 }
 
 TypeRegistration CONTROL_TYPE( typeid(Control), typeid(CustomActor), Create );
 
-// Property Registration after ControlImpl::Impl definition below
-
-TypeAction ACTION_TYPE_1(CONTROL_TYPE, Toolkit::Control::ACTION_CONTROL_ACTIVATED, &ControlImpl::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;
-  }
+// Property Registration after Internal::Control::Impl definition below
 
-  ~SetSizeLock()
-  {
-    mLock = false;
-  }
+TypeAction ACTION_TYPE_1( CONTROL_TYPE, Toolkit::Control::ACTION_CONTROL_ACTIVATED, &Internal::Control::DoAction );
 
-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
@@ -203,6 +212,7 @@ void SetupBackgroundActor( Actor actor, Property::Index constrainingIndex, const
 {
   actor.SetColor( color );
   actor.SetPositionInheritanceMode( USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
+  actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
   actor.SetZ( BACKGROUND_ACTOR_Z_POSITION );
 
   Constraint constraint = Constraint::New<Vector3>( constrainingIndex,
@@ -213,87 +223,74 @@ void SetupBackgroundActor( Actor actor, Property::Index constrainingIndex, const
 
 } // unnamed namespace
 
-class ControlImpl::Impl : public ConnectionTrackerInterface
+namespace Internal
 {
+
+class Control::Impl : public ConnectionTracker
+{
+public:
+
+  /**
+   * Size indices for mMinMaxSize array
+   */
+  enum
+  {
+    MIN_SIZE_INDEX = 0,
+    MAX_SIZE_INDEX = 1
+  };
+
 public:
   // Construction & Destruction
-  Impl(ControlImpl& controlImpl)
-  : mControlImpl(controlImpl),
-    mInitialized( false ),
+  Impl(Control& controlImpl)
+  : mControlImpl( controlImpl ),
+    mBackground( NULL ),
+    mStartingPinchScale( NULL ),
+    mKeyEventSignalV2(),
     mPinchGestureDetector(),
     mPanGestureDetector(),
     mTapGestureDetector(),
     mLongPressGestureDetector(),
-    mStartingPinchScale(),
-    mLockSetSize( false ),
-    mWidthPolicy( Control::Fixed ),
-    mHeightPolicy( Control::Fixed ),
-    mSize(),
-    mSetSize(),
-    mMinimumSize(),
-    mMaximumSize( MAX_FLOAT_VALUE, MAX_FLOAT_VALUE, MAX_FLOAT_VALUE ),
-    mIsKeyboardNavigationSupported(false),
-    mIsKeyboardFocusGroup(false),
-    mKeyEventSignalV2(),
-    mBackground( NULL )
+    mCurrentSize(),
+    mNaturalSize(),
+    mWidthPolicy( Toolkit::Control::Fixed ),
+    mHeightPolicy( Toolkit::Control::Fixed ),
+    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
 
-  void PinchDetected(Actor actor, PinchGesture pinch)
+  void PinchDetected(Actor actor, const PinchGesture& pinch)
   {
     mControlImpl.OnPinch(pinch);
   }
 
-  void PanDetected(Actor actor, PanGesture pan)
+  void PanDetected(Actor actor, const PanGesture& pan)
   {
     mControlImpl.OnPan(pan);
   }
 
-  void TapDetected(Actor actor, TapGesture tap)
+  void TapDetected(Actor actor, const TapGesture& tap)
   {
     mControlImpl.OnTap(tap);
   }
 
-  void LongPressDetected(Actor actor, LongPressGesture longPress)
+  void LongPressDetected(Actor actor, const LongPressGesture& longPress)
   {
     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
 
   /**
@@ -319,21 +316,21 @@ public:
    */
   static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
   {
-    Control control = Control::DownCast( BaseHandle( object ) );
+    Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
 
     if ( control )
     {
-      ControlImpl& controlImpl( control.GetImplementation() );
+      Control& controlImpl( control.GetImplementation() );
 
       switch ( index )
       {
-        case Control::PROPERTY_BACKGROUND_COLOR:
+        case Toolkit::Control::PROPERTY_BACKGROUND_COLOR:
         {
           controlImpl.SetBackgroundColor( value.Get< Vector4 >() );
           break;
         }
 
-        case Control::PROPERTY_BACKGROUND:
+        case Toolkit::Control::PROPERTY_BACKGROUND:
         {
           if ( value.HasKey( "image" ) )
           {
@@ -345,13 +342,50 @@ public:
               controlImpl.SetBackground( image );
             }
           }
-          else if ( value.Get< Property::Map >().empty() )
+          else if ( value.Get< Property::Map >().Empty() )
           {
             // An empty map means the background is no longer required
             controlImpl.ClearBackground();
           }
           break;
         }
+
+        case Toolkit::Control::PROPERTY_WIDTH_POLICY:
+        {
+          controlImpl.mImpl->mWidthPolicy = Scripting::GetEnumeration< Toolkit::Control::SizePolicy >( value.Get< std::string >(), SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT );
+          break;
+        }
+
+        case Toolkit::Control::PROPERTY_HEIGHT_POLICY:
+        {
+          controlImpl.mImpl->mHeightPolicy = Scripting::GetEnumeration< Toolkit::Control::SizePolicy >( value.Get< std::string >(), SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT );
+          break;
+        }
+
+        case Toolkit::Control::PROPERTY_MINIMUM_SIZE:
+        {
+          controlImpl.SetMinimumSize( value.Get< Vector3 >() );
+          break;
+        }
+
+        case Toolkit::Control::PROPERTY_MAXIMUM_SIZE:
+        {
+          controlImpl.SetMaximumSize( value.Get< Vector3 >() );
+          break;
+        }
+
+        case Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS:
+        {
+          if ( value.Get< bool >() )
+          {
+            controlImpl.SetKeyInputFocus();
+          }
+          else
+          {
+            controlImpl.ClearKeyInputFocus();
+          }
+          break;
+        }
       }
     }
   }
@@ -366,21 +400,21 @@ public:
   {
     Property::Value value;
 
-    Control control = Control::DownCast( BaseHandle( object ) );
+    Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
 
     if ( control )
     {
-      ControlImpl& controlImpl( control.GetImplementation() );
+      Control& controlImpl( control.GetImplementation() );
 
       switch ( index )
       {
-        case Control::PROPERTY_BACKGROUND_COLOR:
+        case Toolkit::Control::PROPERTY_BACKGROUND_COLOR:
         {
           value = controlImpl.GetBackgroundColor();
           break;
         }
 
-        case Control::PROPERTY_BACKGROUND:
+        case Toolkit::Control::PROPERTY_BACKGROUND:
         {
           Property::Map map;
 
@@ -393,7 +427,7 @@ public:
               Image image = imageActor.GetImage();
               Property::Map imageMap;
               Scripting::CreatePropertyMap( image, imageMap );
-              map.push_back( Property::StringValuePair( "image", imageMap ) );
+              map[ "image" ] = imageMap;
             }
           }
 
@@ -401,64 +435,164 @@ public:
           break;
         }
 
-      }
-    }
-
-    return value;
-  }
-
-  // Data
-
-  ControlImpl& mControlImpl;
-
-  bool mInitialized:1;
+        case Toolkit::Control::PROPERTY_WIDTH_POLICY:
+        {
+          value = std::string( Scripting::GetEnumerationName< Toolkit::Control::SizePolicy >( controlImpl.mImpl->mWidthPolicy, SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT ) );
+          break;
+        }
 
-  ConnectionTracker mConnectionTracker; // signal connection tracker
+        case Toolkit::Control::PROPERTY_HEIGHT_POLICY:
+        {
+          value = std::string( Scripting::GetEnumerationName< Toolkit::Control::SizePolicy >( controlImpl.mImpl->mHeightPolicy, SIZE_POLICY_STRING_TABLE, SIZE_POLICY_STRING_TABLE_COUNT ) );
+          break;
+        }
 
-  // Gesture Detection
+        case Toolkit::Control::PROPERTY_MINIMUM_SIZE:
+        {
+          value = controlImpl.mImpl->GetMinimumSize();
+          break;
+        }
 
-  PinchGestureDetector     mPinchGestureDetector;
-  PanGestureDetector       mPanGestureDetector;
-  TapGestureDetector       mTapGestureDetector;
-  LongPressGestureDetector mLongPressGestureDetector;
+        case Toolkit::Control::PROPERTY_MAXIMUM_SIZE:
+        {
+          value = controlImpl.mImpl->GetMaximumSize();
+          break;
+        }
 
-  Vector3 mStartingPinchScale;       ///< The scale when a pinch gesture starts
+        case Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS:
+        {
+          value = controlImpl.HasKeyInputFocus();
+          break;
+        }
+      }
+    }
 
-  // Relayout and size negotiation
+    return value;
+  }
 
-  bool mLockSetSize;                 ///< Used to avoid. Can't be a bitfield as a reference to this member is used in SetSizeLock helper class.
+  /**
+   * 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 );
+    }
+  }
 
-  Control::SizePolicy mWidthPolicy;  ///< Stores the width policy.
-  Control::SizePolicy mHeightPolicy; ///< Stores the height policy.
+  /**
+   * 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;
+    }
+  }
 
-  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 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;
+    }
+  }
 
-  bool mIsKeyboardNavigationSupported;  ///< Stores whether keyboard navigation is supported by the control.
-  bool mIsKeyboardFocusGroup;        ///< Stores whether the control is a focus group.
+  // Data
 
+  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;
 
-  // Background
-  Background* mBackground;           ///< Only create the background if we use it
+  // 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 :6;             ///< 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 - need to be part of this class as ControlImpl::Impl is private
+  // Properties - these need to be members of Internal::Control::Impl as they need to functions within this class.
   static PropertyRegistration PROPERTY_1;
   static PropertyRegistration PROPERTY_2;
+  static PropertyRegistration PROPERTY_3;
+  static PropertyRegistration PROPERTY_4;
+  static PropertyRegistration PROPERTY_5;
+  static PropertyRegistration PROPERTY_6;
+  static PropertyRegistration PROPERTY_7;
 };
 
-PropertyRegistration ControlImpl::Impl::PROPERTY_1( CONTROL_TYPE, "background-color", Control::PROPERTY_BACKGROUND_COLOR, Property::VECTOR4, &ControlImpl::Impl::SetProperty, &ControlImpl::Impl::GetProperty );
-PropertyRegistration ControlImpl::Impl::PROPERTY_2( CONTROL_TYPE, "background",       Control::PROPERTY_BACKGROUND,       Property::MAP,     &ControlImpl::Impl::SetProperty, &ControlImpl::Impl::GetProperty );
+PropertyRegistration Control::Impl::PROPERTY_1( CONTROL_TYPE, "background-color", Toolkit::Control::PROPERTY_BACKGROUND_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
+PropertyRegistration Control::Impl::PROPERTY_2( CONTROL_TYPE, "background",       Toolkit::Control::PROPERTY_BACKGROUND,       Property::MAP,     &Control::Impl::SetProperty, &Control::Impl::GetProperty );
+PropertyRegistration Control::Impl::PROPERTY_3( CONTROL_TYPE, "width-policy",     Toolkit::Control::PROPERTY_WIDTH_POLICY,     Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
+PropertyRegistration Control::Impl::PROPERTY_4( CONTROL_TYPE, "height-policy",    Toolkit::Control::PROPERTY_HEIGHT_POLICY,    Property::STRING,  &Control::Impl::SetProperty, &Control::Impl::GetProperty );
+PropertyRegistration Control::Impl::PROPERTY_5( CONTROL_TYPE, "minimum-size",     Toolkit::Control::PROPERTY_MINIMUM_SIZE,     Property::VECTOR3, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
+PropertyRegistration Control::Impl::PROPERTY_6( CONTROL_TYPE, "maximum-size",     Toolkit::Control::PROPERTY_MAXIMUM_SIZE,     Property::VECTOR3, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
+PropertyRegistration Control::Impl::PROPERTY_7( CONTROL_TYPE, "key-input-focus",  Toolkit::Control::PROPERTY_KEY_INPUT_FOCUS,  Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty );
 
-Control ControlImpl::New()
+Toolkit::Control Control::New()
 {
   // Create the implementation, temporarily owned on stack
-  IntrusivePtr<ControlImpl> controlImpl = new ControlImpl( false );
+  IntrusivePtr<Control> controlImpl = new Control( CONTROL_BEHAVIOUR_NONE );
 
   // Pass ownership to handle
-  Control handle( *controlImpl );
+  Toolkit::Control handle( *controlImpl );
 
   // Second-phase init of the implementation
   // This can only be done after the CustomActor connection has been made...
@@ -467,106 +601,165 @@ Control ControlImpl::New()
   return handle;
 }
 
-ControlImpl::~ControlImpl()
+Control::~Control()
 {
-  if( mImpl->mInitialized )
-  {
-    // Unregister only if control has been initialized.
-    Internal::StyleChangeProcessor::Unregister( this );
-  }
   delete mImpl;
 }
 
-void ControlImpl::Initialize()
+void Control::SetSizePolicy( Toolkit::Control::SizePolicy widthPolicy, Toolkit::Control::SizePolicy heightPolicy )
 {
-  // Register with the style change processor so we are informed when the default style changes
-  Internal::StyleChangeProcessor::Register( this );
+  bool relayoutRequest( false );
 
-  // Calling deriving classes
-  OnInitialize();
+  if ( ( mImpl->mWidthPolicy != widthPolicy ) || ( mImpl->mHeightPolicy != heightPolicy ) )
+  {
+    relayoutRequest = true;
+  }
 
-  mImpl->mInitialized = true;
-}
+  mImpl->mWidthPolicy = widthPolicy;
+  mImpl->mHeightPolicy = heightPolicy;
 
-void ControlImpl::EnableGestureDetection(Gesture::Type type)
-{
-  if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
+  // Ensure RelayoutRequest is called AFTER new policies have been set.
+  if ( relayoutRequest )
   {
-    mImpl->mPinchGestureDetector = PinchGestureDetector::New();
-    mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
-    mImpl->mPinchGestureDetector.Attach(Self());
+    RelayoutRequest();
   }
+}
 
-  if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
+void Control::GetSizePolicy( Toolkit::Control::SizePolicy& widthPolicy, Toolkit::Control::SizePolicy& heightPolicy ) const
+{
+  widthPolicy = mImpl->mWidthPolicy;
+  heightPolicy = mImpl->mHeightPolicy;
+}
+
+void Control::SetMinimumSize( const Vector3& 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->mPanGestureDetector = PanGestureDetector::New();
-    mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
-    mImpl->mPanGestureDetector.Attach(Self());
+    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 ) ||
+         ( mImpl->mHeightPolicy == Toolkit::Control::Range   ) || ( mImpl->mWidthPolicy  == Toolkit::Control::Range   ) )
+    {
+      RelayoutRequest();
+    }
   }
+}
 
-  if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
+const Vector3& Control::GetMinimumSize() const
+{
+  return mImpl->GetMinimumSize();
+}
+
+void Control::SetMaximumSize( const Vector3& 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->mTapGestureDetector = TapGestureDetector::New();
-    mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
-    mImpl->mTapGestureDetector.Attach(Self());
+    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 ) ||
+         ( mImpl->mHeightPolicy == Toolkit::Control::Range   ) || ( mImpl->mWidthPolicy  == Toolkit::Control::Range   ) )
+    {
+      RelayoutRequest();
+    }
   }
+}
 
-  if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
+const Vector3& Control::GetMaximumSize() const
+{
+  return mImpl->GetMaximumSize();
+}
+
+Vector3 Control::GetNaturalSize()
+{
+  // could be overridden in derived classes.
+  return mImpl->mNaturalSize;
+}
+
+float Control::GetHeightForWidth( float width )
+{
+  // could be overridden in derived classes.
+  float height( 0.0f );
+  if ( mImpl->mNaturalSize.width > 0.0f )
   {
-    mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
-    mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
-    mImpl->mLongPressGestureDetector.Attach(Self());
+    height = mImpl->mNaturalSize.height * width / mImpl->mNaturalSize.width;
   }
+  return height;
 }
 
-void ControlImpl::DisableGestureDetection(Gesture::Type type)
+float Control::GetWidthForHeight( float height )
 {
-  if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
+  // could be overridden in derived classes.
+  float width( 0.0f );
+  if ( mImpl->mNaturalSize.height > 0.0f )
   {
-    mImpl->mPinchGestureDetector.Detach(Self());
-    mImpl->mPinchGestureDetector.Reset();
+    width = mImpl->mNaturalSize.width * height / mImpl->mNaturalSize.height;
   }
+  return width;
+}
 
-  if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
+const Vector3& Control::GetControlSize() const
+{
+  return mImpl->mCurrentSize;
+}
+
+const Vector3& Control::GetSizeSet() const
+{
+  return mImpl->mNaturalSize;
+}
+
+void Control::SetKeyInputFocus()
+{
+  if( Self().OnStage() )
   {
-    mImpl->mPanGestureDetector.Detach(Self());
-    mImpl->mPanGestureDetector.Reset();
+    Toolkit::KeyInputFocusManager::Get().SetFocus(Toolkit::Control::DownCast(Self()));
   }
+}
 
-  if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
+bool Control::HasKeyInputFocus()
+{
+  bool result = false;
+  if( Self().OnStage() )
   {
-    mImpl->mTapGestureDetector.Detach(Self());
-    mImpl->mTapGestureDetector.Reset();
+    result = Toolkit::KeyInputFocusManager::Get().IsKeyboardListener(Toolkit::Control::DownCast(Self()));
   }
+  return result;
+}
 
-  if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
+void Control::ClearKeyInputFocus()
+{
+  if( Self().OnStage() )
   {
-    mImpl->mLongPressGestureDetector.Detach(Self());
-    mImpl->mLongPressGestureDetector.Reset();
+    Toolkit::KeyInputFocusManager::Get().RemoveFocus(Toolkit::Control::DownCast(Self()));
   }
 }
 
-PinchGestureDetector ControlImpl::GetPinchGestureDetector() const
+PinchGestureDetector Control::GetPinchGestureDetector() const
 {
   return mImpl->mPinchGestureDetector;
 }
 
-PanGestureDetector ControlImpl::GetPanGestureDetector() const
+PanGestureDetector Control::GetPanGestureDetector() const
 {
   return mImpl->mPanGestureDetector;
 }
 
-TapGestureDetector ControlImpl::GetTapGestureDetector() const
+TapGestureDetector Control::GetTapGestureDetector() const
 {
   return mImpl->mTapGestureDetector;
 }
 
-LongPressGestureDetector ControlImpl::GetLongPressGestureDetector() const
+LongPressGestureDetector Control::GetLongPressGestureDetector() const
 {
   return mImpl->mLongPressGestureDetector;
 }
 
-void ControlImpl::SetBackgroundColor( const Vector4& color )
+void Control::SetBackgroundColor( const Vector4& color )
 {
   Background& background( mImpl->GetBackground() );
 
@@ -591,7 +784,7 @@ void ControlImpl::SetBackgroundColor( const Vector4& color )
   background.color = color;
 }
 
-Vector4 ControlImpl::GetBackgroundColor() const
+Vector4 Control::GetBackgroundColor() const
 {
   if ( mImpl->mBackground )
   {
@@ -600,7 +793,7 @@ Vector4 ControlImpl::GetBackgroundColor() const
   return Color::TRANSPARENT;
 }
 
-void ControlImpl::SetBackground( Image image )
+void Control::SetBackground( Image image )
 {
   Background& background( mImpl->GetBackground() );
 
@@ -608,7 +801,7 @@ void ControlImpl::SetBackground( Image image )
   {
     // Remove Current actor, unset AFTER removal so that we do not inform deriving classes
     Self().Remove( background.actor );
-    background.actor = NULL;
+    background.actor.Reset();
   }
 
   ImageActor imageActor = ImageActor::New( image );
@@ -619,7 +812,7 @@ void ControlImpl::SetBackground( Image image )
   Self().Add( imageActor );
 }
 
-void ControlImpl::ClearBackground()
+void Control::ClearBackground()
 {
   if ( mImpl->mBackground )
   {
@@ -631,7 +824,7 @@ void ControlImpl::ClearBackground()
   }
 }
 
-Actor ControlImpl::GetBackgroundActor() const
+Actor Control::GetBackgroundActor() const
 {
   if ( mImpl->mBackground )
   {
@@ -641,332 +834,432 @@ Actor ControlImpl::GetBackgroundActor() const
   return Actor();
 }
 
-void ControlImpl::OnPinch(PinchGesture pinch)
+void Control::SetKeyboardNavigationSupport(bool isSupported)
 {
-  if (pinch.state == Gesture::Started)
-  {
-    mImpl->mStartingPinchScale = Self().GetCurrentScale();
-  }
-
-  Self().SetScale(mImpl->mStartingPinchScale * pinch.scale);
+  mImpl->mIsKeyboardNavigationSupported = isSupported;
 }
 
-void ControlImpl::OnStageConnection()
+bool Control::IsKeyboardNavigationSupported()
 {
-  RelayoutRequest();
+  return mImpl->mIsKeyboardNavigationSupported;
+}
 
-  // Notify derived classes.
-  OnControlStageConnection();
+void Control::Activate()
+{
+  // Inform deriving classes
+  OnActivated();
 }
 
-void ControlImpl::OnStageDisconnection()
+bool Control::OnAccessibilityPan(PanGesture gesture)
 {
-  // Notify derived classes
-  OnControlStageDisconnection();
+  return false; // Accessibility pan gesture is not handled by default
 }
 
-void ControlImpl::OnChildAdd(Actor& child)
+bool Control::OnAccessibilityTouch(const TouchEvent& touchEvent)
 {
-  // If this is the background actor, then we do not want to relayout or inform deriving classes
-  if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
-  {
-    return;
-  }
-
-  // Request for relayout.
-  RelayoutRequest();
+  return false; // Accessibility touch event is not handled by default
+}
 
-  // Notify derived classes.
-  OnControlChildAdd( child );
+bool Control::OnAccessibilityValueChange(bool isIncrease)
+{
+  return false; // Accessibility value change action is not handled by default
 }
 
-void ControlImpl::OnChildRemove(Actor& child)
+void Control::NegotiateSize( Vector2 allocatedSize, ActorSizeContainer& container )
 {
-  // If this is the background actor, then we do not want to relayout or inform deriving classes
-  if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
+  Vector2 size;
+
+  if ( mImpl->mWidthPolicy == Toolkit::Control::Fixed )
   {
-    return;
-  }
+    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->mNaturalSize );
+      if ( setSize != Vector2::ZERO )
+      {
+        size = setSize;
 
-  // Request for relayout.
-  RelayoutRequest();
+        // Policy is set to Fixed, so if the application / control has not set one of the dimensions,
+        // then we should use the natural size of the control rather than the full allocation.
+        if ( EqualsZero( size.width ) )
+        {
+          size.width = GetWidthForHeight( size.height );
+        }
+        else if ( EqualsZero( size.height ) )
+        {
+          size.height = GetHeightForWidth( size.width );
+        }
+      }
+      else
+      {
+        // If that is not set then set the size to the control's natural size
+        size = Vector2( GetNaturalSize() );
+      }
+    }
+    else
+    {
+      // Width is fixed so if the application / control has set it, then use that.
+      if ( !EqualsZero( mImpl->mNaturalSize.width ) )
+      {
+        size.width = mImpl->mNaturalSize.width;
+      }
+      else
+      {
+        // Otherwise, set the width to what has been allocated.
+        size.width = allocatedSize.width;
+      }
 
-  // Notify derived classes.
-  OnControlChildRemove( child );
-}
+      // Height is flexible so ask control what the height should be for our width.
+      size.height = GetHeightForWidth( size.width );
 
-void ControlImpl::OnSizeSet(const Vector3& targetSize)
-{
-  if( ( !mImpl->mLockSetSize ) && ( targetSize != mImpl->mSetSize ) )
+      // Ensure height is within our policy rules
+      size.height = Calculate( mImpl->mHeightPolicy, GetMinimumSize().height, GetMaximumSize().height, size.height );
+    }
+  }
+  else
   {
-    // Only updates size if set through Actor's API
-    mImpl->mSetSize = targetSize;
+    if ( mImpl->mHeightPolicy == Toolkit::Control::Fixed )
+    {
+      // Height is fixed so if the application / control has set it, then use that.
+      if ( !EqualsZero( mImpl->mNaturalSize.height ) )
+      {
+        size.height = mImpl->mNaturalSize.height;
+      }
+      else
+      {
+        // Otherwise, set the height to what has been allocated.
+        size.height = allocatedSize.height;
+      }
+
+      // Width is flexible so ask control what the width should be for our height.
+      size.width = GetWidthForHeight( size.height );
+
+      // Ensure width is within our policy rules
+      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->GetMinimumSize().width, mImpl->GetMaximumSize().width, allocatedSize.width );
+      size.height = Calculate( mImpl->mHeightPolicy, mImpl->GetMinimumSize().height, mImpl->GetMaximumSize().height, allocatedSize.height );
+    }
   }
 
-  if( targetSize != mImpl->mSize )
+  // If the width has not been set, then set to the allocated width.
+  // Also if the width set is greater than the allocated, then set to allocated (no exceed support).
+  if ( EqualsZero( size.width ) || ( size.width > allocatedSize.width ) )
   {
-    // Update control size.
-    mImpl->mSize = targetSize;
+    size.width = allocatedSize.width;
+  }
 
-    // Notify derived classes.
-    OnControlSizeSet( targetSize );
+  // If the height has not been set, then set to the allocated height.
+  // Also if the height set is greater than the allocated, then set to allocated (no exceed support).
+  if ( EqualsZero( size.height ) || ( size.height > allocatedSize.height ) )
+  {
+    size.height = allocatedSize.height;
   }
-}
 
-void ControlImpl::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
-{
-  // Do Nothing
-}
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose,
+                 "%p: Natural: [%.2f, %.2f] Allocated: [%.2f, %.2f] Set: [%.2f, %.2f]\n",
+                 Self().GetObjectPtr(),
+                 GetNaturalSize().x, GetNaturalSize().y,
+                 allocatedSize.x, allocatedSize.y,
+                 size.x, size.y );
 
-bool ControlImpl::OnTouchEvent(const TouchEvent& event)
-{
-  return false; // Do not consume
+  Relayout( size, container );
 }
 
-bool ControlImpl::OnKeyEvent(const KeyEvent& event)
+void Control::SetAsKeyboardFocusGroup(bool isFocusGroup)
 {
-  return false; // Do not consume
-}
+  mImpl->mIsKeyboardFocusGroup = isFocusGroup;
 
-bool ControlImpl::OnMouseWheelEvent(const MouseWheelEvent& event)
-{
-  return false; // Do not consume
+  // The following line will be removed when the deprecated API in KeyboardFocusManager is deleted
+  Toolkit::KeyboardFocusManager::Get().SetAsFocusGroup(Self(), isFocusGroup);
 }
 
-void ControlImpl::OnKeyInputFocusGained()
+bool Control::IsKeyboardFocusGroup()
 {
-  // Do Nothing
+  return Toolkit::KeyboardFocusManager::Get().IsFocusGroup(Self());
 }
 
-void ControlImpl::OnKeyInputFocusLost()
+Actor Control::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
 {
-  // Do Nothing
+  return Actor();
 }
 
-Actor ControlImpl::GetChildByAlias(const std::string& actorAlias)
+void Control::OnKeyboardFocusChangeCommitted(Actor commitedFocusableActor)
 {
-  return Actor();
 }
 
-bool ControlImpl::OnAccessibilityPan(PanGesture gesture)
+bool Control::DoAction(BaseObject* object, const std::string& actionName, const PropertyValueContainer& attributes)
 {
-  return false; // Accessibility pan gesture is not handled by default
+  bool ret = false;
+
+  if( object && (actionName == Toolkit::Control::ACTION_CONTROL_ACTIVATED) )
+  {
+    Toolkit::Control control = Toolkit::Control::DownCast( BaseHandle( object ) );
+    if( control )
+    {
+      // if cast succeeds there is an implementation so no need to check
+      control.GetImplementation().OnActivated();
+    }
+  }
+
+  return ret;
 }
 
-bool ControlImpl::OnAccessibilityValueChange(bool isIncrease)
+bool Control::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
 {
-  return false; // Accessibility value change action is not handled by default
-}
+  Dali::BaseHandle handle( object );
 
+  bool connected( false );
+  Toolkit::Control control = Toolkit::Control::DownCast(handle);
+  if ( control )
+  {
+    Control& controlImpl( control.GetImplementation() );
+    connected = true;
 
-void ControlImpl::SetKeyboardNavigationSupport(bool isSupported)
-{
-  mImpl->mIsKeyboardNavigationSupported = isSupported;
+    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;
 }
 
-bool ControlImpl::IsKeyboardNavigationSupported()
+Toolkit::Control::KeyEventSignalV2& Control::KeyEventSignal()
 {
-  return mImpl->mIsKeyboardNavigationSupported;
+  return mImpl->mKeyEventSignalV2;
 }
 
-void ControlImpl::SetAsKeyboardFocusGroup(bool isFocusGroup)
+bool Control::EmitKeyEventSignal( const KeyEvent& event )
 {
-  mImpl->mIsKeyboardFocusGroup = isFocusGroup;
+  // Guard against destruction during signal emission
+  Dali::Toolkit::Control handle( GetOwner() );
 
-  // The following line will be removed when the deprecated API in KeyboardFocusManager is deleted
-  KeyboardFocusManager::Get().SetAsFocusGroup(Self(), isFocusGroup);
-}
+  bool consumed = false;
 
-bool ControlImpl::IsKeyboardFocusGroup()
-{
-  return KeyboardFocusManager::Get().IsFocusGroup(Self());
+  // signals are allocated dynamically when someone connects
+  if ( !mImpl->mKeyEventSignalV2.Empty() )
+  {
+    consumed = mImpl->mKeyEventSignalV2.Emit( handle, event );
+  }
+
+  if (!consumed)
+  {
+    // Notification for derived classes
+    consumed = OnKeyEvent(event);
+  }
+
+  return consumed;
 }
 
-Actor ControlImpl::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
+Control::Control( ControlBehaviour behaviourFlags )
+: CustomActorImpl( behaviourFlags & REQUIRES_TOUCH_EVENTS ),
+  mImpl(new Impl(*this))
 {
-  return Actor();
+  mImpl->mFlags = behaviourFlags;
 }
 
-bool ControlImpl::DoAction(BaseObject* object, const std::string& actionName, const std::vector<Property::Value>& attributes)
+void Control::Initialize()
 {
-  bool ret = false;
 
-  return ret;
-}
+  // Calling deriving classes
+  OnInitialize();
 
-void ControlImpl::DoActivatedAction(const PropertyValueContainer& attributes)
-{
-  OnActivated();
+  if( mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS )
+  {
+    Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+
+    // Register for style changes
+    styleManager.StyleChangeSignal().Connect( this, &Control::DoStyleChange );
+
+    // SetTheme
+    GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
+  }
+
+  SetRequiresHoverEvents(mImpl->mFlags & REQUIRES_HOVER_EVENTS);
+  SetRequiresMouseWheelEvents(mImpl->mFlags & REQUIRES_MOUSE_WHEEL_EVENTS);
+
+  mImpl->mInitialized = true;
 }
 
-Toolkit::Control::KeyEventSignalV2& ControlImpl::KeyEventSignal()
+void Control::EnableGestureDetection(Gesture::Type type)
 {
-  return mImpl->mKeyEventSignalV2;
+  if ( (type & Gesture::Pinch) && !mImpl->mPinchGestureDetector )
+  {
+    mImpl->mPinchGestureDetector = PinchGestureDetector::New();
+    mImpl->mPinchGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PinchDetected);
+    mImpl->mPinchGestureDetector.Attach(Self());
+  }
+
+  if ( (type & Gesture::Pan) && !mImpl->mPanGestureDetector )
+  {
+    mImpl->mPanGestureDetector = PanGestureDetector::New();
+    mImpl->mPanGestureDetector.DetectedSignal().Connect(mImpl, &Impl::PanDetected);
+    mImpl->mPanGestureDetector.Attach(Self());
+  }
+
+  if ( (type & Gesture::Tap) && !mImpl->mTapGestureDetector )
+  {
+    mImpl->mTapGestureDetector = TapGestureDetector::New();
+    mImpl->mTapGestureDetector.DetectedSignal().Connect(mImpl, &Impl::TapDetected);
+    mImpl->mTapGestureDetector.Attach(Self());
+  }
+
+  if ( (type & Gesture::LongPress) && !mImpl->mLongPressGestureDetector )
+  {
+    mImpl->mLongPressGestureDetector = LongPressGestureDetector::New();
+    mImpl->mLongPressGestureDetector.DetectedSignal().Connect(mImpl, &Impl::LongPressDetected);
+    mImpl->mLongPressGestureDetector.Attach(Self());
+  }
 }
 
-void ControlImpl::SetSizePolicy( Control::SizePolicy widthPolicy, Control::SizePolicy heightPolicy )
+void Control::DisableGestureDetection(Gesture::Type type)
 {
-  bool relayoutRequest( false );
+  if ( (type & Gesture::Pinch) && mImpl->mPinchGestureDetector )
+  {
+    mImpl->mPinchGestureDetector.Detach(Self());
+    mImpl->mPinchGestureDetector.Reset();
+  }
 
-  if ( ( mImpl->mWidthPolicy != widthPolicy ) || ( mImpl->mHeightPolicy != heightPolicy ) )
+  if ( (type & Gesture::Pan) && mImpl->mPanGestureDetector )
   {
-    relayoutRequest = true;
+    mImpl->mPanGestureDetector.Detach(Self());
+    mImpl->mPanGestureDetector.Reset();
   }
 
-  mImpl->mWidthPolicy = widthPolicy;
-  mImpl->mHeightPolicy = heightPolicy;
+  if ( (type & Gesture::Tap) && mImpl->mTapGestureDetector )
+  {
+    mImpl->mTapGestureDetector.Detach(Self());
+    mImpl->mTapGestureDetector.Reset();
+  }
 
-  // Ensure RelayoutRequest is called AFTER new policies have been set.
-  if ( relayoutRequest )
+  if ( (type & Gesture::LongPress) && mImpl->mLongPressGestureDetector)
   {
-    RelayoutRequest();
+    mImpl->mLongPressGestureDetector.Detach(Self());
+    mImpl->mLongPressGestureDetector.Reset();
   }
 }
 
-void ControlImpl::GetSizePolicy( Control::SizePolicy& widthPolicy, Control::SizePolicy& heightPolicy ) const
+void Control::RelayoutRequest()
 {
-  widthPolicy = mImpl->mWidthPolicy;
-  heightPolicy = mImpl->mHeightPolicy;
+  // unfortunate double negative but thats to guarantee new controls get size negotiation
+  // by default and have to "opt-out" if they dont want it
+  if( !(mImpl->mFlags & NO_SIZE_NEGOTIATION) )
+  {
+    Internal::RelayoutController::Request();
+  }
 }
 
-void ControlImpl::SetMinimumSize( const Vector3& size )
+void Control::Relayout( Actor actor, Vector2 size, ActorSizeContainer& container )
 {
-  if ( mImpl->mMinimumSize != size )
+  if ( actor )
   {
-    mImpl->mMinimumSize = size;
-
-    // Only relayout if our control is using the minimum or range policy.
-    if ( ( mImpl->mHeightPolicy == Control::Minimum ) || ( mImpl->mWidthPolicy  == Control::Minimum ) ||
-         ( mImpl->mHeightPolicy == Control::Range   ) || ( mImpl->mWidthPolicy  == Control::Range   ) )
+    Toolkit::Control control( Toolkit::Control::DownCast( actor ) );
+    if( control )
     {
-      RelayoutRequest();
+      control.GetImplementation().NegotiateSize( size, container );
+    }
+    else
+    {
+      container.push_back( ActorSizePair( actor, size ) );
     }
   }
 }
 
-const Vector3& ControlImpl::GetMinimumSize() const
+void Control::OnInitialize()
 {
-  return mImpl->mMinimumSize;
 }
 
-void ControlImpl::SetMaximumSize( const Vector3& size )
+void Control::OnActivated()
 {
-  if ( mImpl->mMaximumSize != size )
-  {
-    mImpl->mMaximumSize = size;
-
-    // Only relayout if our control is using the maximum or range policy.
-    if ( ( mImpl->mHeightPolicy == Control::Maximum ) || ( mImpl->mWidthPolicy  == Control::Maximum ) ||
-         ( mImpl->mHeightPolicy == Control::Range   ) || ( mImpl->mWidthPolicy  == Control::Range   ) )
-    {
-      RelayoutRequest();
-    }
-  }
 }
 
-const Vector3& ControlImpl::GetMaximumSize() const
+void Control::OnThemeChange( Toolkit::StyleManager styleManager )
 {
-  return mImpl->mMaximumSize;
+  GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
 }
 
-Vector3 ControlImpl::GetNaturalSize()
+void Control::OnFontChange( bool defaultFontChange, bool defaultFontSizeChange )
 {
-  // could be overridden in derived classes.
-  return mImpl->mSetSize;
 }
 
-float ControlImpl::GetHeightForWidth( float width )
+void Control::OnPinch(const PinchGesture& pinch)
 {
-  // could be overridden in derived classes.
-  float height( 0.0f );
-  if ( mImpl->mSetSize.width > 0.0f )
+  if( !( mImpl->mStartingPinchScale ) )
   {
-    height = mImpl->mSetSize.height * width / mImpl->mSetSize.width;
+    // lazy allocate
+    mImpl->mStartingPinchScale = new Vector3;
   }
-  return height;
-}
 
-float ControlImpl::GetWidthForHeight( float height )
-{
-  // could be overridden in derived classes.
-  float width( 0.0f );
-  if ( mImpl->mSetSize.height > 0.0f )
+  if( pinch.state == Gesture::Started )
   {
-    width = mImpl->mSetSize.width * height / mImpl->mSetSize.height;
+    *( mImpl->mStartingPinchScale ) = Self().GetCurrentScale();
   }
-  return width;
+
+  Self().SetScale( *( mImpl->mStartingPinchScale ) * pinch.scale );
 }
 
-const Vector3& ControlImpl::GetControlSize() const
+void Control::OnPan( const PanGesture& pan )
 {
-  return mImpl->mSize;
 }
 
-const Vector3& ControlImpl::GetSizeSet() const
+void Control::OnTap(const TapGesture& tap)
 {
-  return mImpl->mSetSize;
 }
 
-void ControlImpl::SetKeyInputFocus()
+void Control::OnLongPress( const LongPressGesture& longPress )
 {
-  if( Self().OnStage() )
-  {
-    KeyInputFocusManager::Get().SetFocus(Control::DownCast(Self()));
-  }
 }
 
-bool ControlImpl::HasKeyInputFocus()
+void Control::OnControlStageConnection()
 {
-  bool result = false;
-  if( Self().OnStage() )
-  {
-    result = KeyInputFocusManager::Get().IsKeyboardListener(Control::DownCast(Self()));
-  }
-  return result;
 }
 
-void ControlImpl::ClearKeyInputFocus()
+void Control::OnControlStageDisconnection()
 {
-  if( Self().OnStage() )
-  {
-    KeyInputFocusManager::Get().RemoveFocus(Control::DownCast(Self()));
-  }
 }
 
-void ControlImpl::RelayoutRequest()
+void Control::OnControlChildAdd( Actor& child )
 {
-  Internal::RelayoutController::Get().Request();
 }
 
-void ControlImpl::Relayout( Vector2 size, ActorSizeContainer& container )
+void Control::OnControlChildRemove( Actor& child )
 {
-  // Avoids relayout again when OnSizeSet callback arrives.
-  {
-    SetSizeLock lock( mImpl->mLockSetSize );
-    Self().SetSize( size );
-  }
-
-  // Only relayout controls which requested to be relaid out.
-  OnRelaidOut( size, container );
 }
 
-void ControlImpl::Relayout( Actor actor, Vector2 size, ActorSizeContainer& container )
+void Control::OnControlSizeSet( const Vector3& size )
 {
-  if ( actor )
-  {
-    Control control( Control::DownCast( actor ) );
-    if( control )
-    {
-      control.GetImplementation().NegotiateSize( size, container );
-    }
-    else
-    {
-      container.push_back( ActorSizePair( actor, size ) );
-    }
-  }
 }
 
-void ControlImpl::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
+void Control::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
 {
   unsigned int numChildren = Self().GetChildCount();
 
@@ -976,154 +1269,144 @@ void ControlImpl::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
   }
 }
 
-void ControlImpl::NegotiateSize( Vector2 allocatedSize, ActorSizeContainer& container )
+void Control::OnKeyInputFocusGained()
 {
-  Vector2 size;
+  // Do Nothing
+}
 
-  if ( mImpl->mWidthPolicy == Control::Fixed )
-  {
-    if ( mImpl->mHeightPolicy == Control::Fixed )
-    {
-      // If a control says it has a fixed size, then use the size set by the application / control.
-      Vector2 setSize( mImpl->mSetSize );
-      if ( setSize != Vector2::ZERO )
-      {
-        size = setSize;
+void Control::OnKeyInputFocusLost()
+{
+  // Do Nothing
+}
 
-        // Policy is set to Fixed, so if the application / control has not set one of the dimensions,
-        // then we should use the natural size of the control rather than the full allocation.
-        if ( EqualsZero( size.width ) )
-        {
-          size.width = GetWidthForHeight( size.height );
-        }
-        else if ( EqualsZero( size.height ) )
-        {
-          size.height = GetHeightForWidth( size.width );
-        }
-      }
-      else
-      {
-        // If that is not set then set the size to the control's natural size
-        size = Vector2( GetNaturalSize() );
-      }
-    }
-    else
-    {
-      // Width is fixed so if the application / control has set it, then use that.
-      if ( !EqualsZero( mImpl->mSetSize.width ) )
-      {
-        size.width = mImpl->mSetSize.width;
-      }
-      else
-      {
-        // Otherwise, set the width to what has been allocated.
-        size.width = allocatedSize.width;
-      }
+void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
+{
+  // @todo consider animating negotiated child sizes to target size
+}
 
-      // Height is flexible so ask control what the height should be for our width.
-      size.height = GetHeightForWidth( size.width );
+bool Control::OnTouchEvent(const TouchEvent& event)
+{
+  return false; // Do not consume
+}
 
-      // Ensure height is within our policy rules
-      size.height = Calculate( mImpl->mHeightPolicy, mImpl->mMinimumSize.height, mImpl->mMaximumSize.height, size.height );
-    }
-  }
-  else
-  {
-    if ( mImpl->mHeightPolicy == Control::Fixed )
-    {
-      // Height is fixed so if the application / control has set it, then use that.
-      if ( !EqualsZero( mImpl->mSetSize.height ) )
-      {
-        size.height = mImpl->mSetSize.height;
-      }
-      else
-      {
-        // Otherwise, set the height to what has been allocated.
-        size.height = allocatedSize.height;
-      }
+bool Control::OnHoverEvent(const HoverEvent& event)
+{
+  return false; // Do not consume
+}
 
-      // Width is flexible so ask control what the width should be for our height.
-      size.width = GetWidthForHeight( size.height );
+bool Control::OnKeyEvent(const KeyEvent& event)
+{
+  return false; // Do not consume
+}
 
-      // Ensure width is within our policy rules
-      size.width = Calculate( mImpl->mWidthPolicy, mImpl->mMinimumSize.width, mImpl->mMaximumSize.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 );
-    }
-  }
+bool Control::OnMouseWheelEvent(const MouseWheelEvent& event)
+{
+  return false; // Do not consume
+}
 
-  // If the width has not been set, then set to the allocated width.
-  // Also if the width set is greater than the allocated, then set to allocated (no exceed support).
-  if ( EqualsZero( size.width ) || ( size.width > allocatedSize.width ) )
-  {
-    size.width = allocatedSize.width;
-  }
+Actor Control::GetChildByAlias(const std::string& actorAlias)
+{
+  return Actor();
+}
 
-  // If the height has not been set, then set to the allocated height.
-  // Also if the height set is greater than the allocated, then set to allocated (no exceed support).
-  if ( EqualsZero( size.height ) || ( size.height > allocatedSize.height ) )
+void Control::OnStageConnection()
+{
+  RelayoutRequest();
+
+  // Notify derived classes.
+  OnControlStageConnection();
+}
+
+void Control::OnStageDisconnection()
+{
+  // Notify derived classes
+  OnControlStageDisconnection();
+}
+
+void Control::OnChildAdd(Actor& child)
+{
+  // If this is the background actor, then we do not want to relayout or inform deriving classes
+  if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
   {
-    size.height = allocatedSize.height;
+    return;
   }
 
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose,
-                 "%p: Natural: [%.2f, %.2f] Allocated: [%.2f, %.2f] Set: [%.2f, %.2f]\n",
-                 Self().GetObjectPtr(),
-                 GetNaturalSize().x, GetNaturalSize().y,
-                 allocatedSize.x, allocatedSize.y,
-                 size.x, size.y );
+  // Request for relayout as we may need to position the new child and old ones
+  RelayoutRequest();
 
-  Relayout( size, container );
+  // Notify derived classes.
+  OnControlChildAdd( child );
 }
 
-bool ControlImpl::EmitKeyEventSignal( const KeyEvent& event )
+void Control::OnChildRemove(Actor& child)
 {
-  // Guard against destruction during signal emission
-  Dali::Toolkit::Control handle( GetOwner() );
+  // If this is the background actor, then we do not want to relayout or inform deriving classes
+  if ( mImpl->mBackground && ( child == mImpl->mBackground->actor ) )
+  {
+    return;
+  }
 
-  bool consumed = false;
+  // Request for relayout as we may need to re-position the old child
+  RelayoutRequest();
 
-  // signals are allocated dynamically when someone connects
-  if ( !mImpl->mKeyEventSignalV2.Empty() )
+  // Notify derived classes.
+  OnControlChildRemove( child );
+}
+
+void Control::OnSizeSet(const Vector3& targetSize)
+{
+  if( ( !mImpl->mInsideRelayout ) && ( targetSize != mImpl->mNaturalSize ) )
   {
-    consumed = mImpl->mKeyEventSignalV2.Emit( handle, event );
+    // Only updates size if set through Actor's API
+    mImpl->mNaturalSize = targetSize;
   }
 
-  if (!consumed)
+  if( targetSize != mImpl->mCurrentSize )
   {
-    // Notification for derived classes
-    consumed = OnKeyEvent(event);
-  }
+    // Update control size.
+    mImpl->mCurrentSize = targetSize;
 
-  return consumed;
+    // Notify derived classes.
+    OnControlSizeSet( targetSize );
+  }
 }
 
-void ControlImpl::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
+void Control::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
 {
   mImpl->SignalConnected( slotObserver, callback );
 }
 
-void ControlImpl::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
+void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
 {
   mImpl->SignalDisconnected( slotObserver, callback );
 }
 
-std::size_t ControlImpl::GetConnectionCount() const
+void Control::DoStyleChange( Toolkit::StyleManager styleManager, StyleChange change )
 {
-  return mImpl->GetConnectionCount();
+  if( change.themeChange )
+  {
+    OnThemeChange( styleManager );
+  }
+  else if( change.defaultFontChange || change.defaultFontSizeChange )
+  {
+    OnFontChange( change.defaultFontChange, change.defaultFontSizeChange );
+  }
 }
 
-ControlImpl::ControlImpl( bool requiresTouchEvents )
-: CustomActorImpl( requiresTouchEvents ),
-  mImpl(new Impl(*this))
+void Control::Relayout(Vector2 size, ActorSizeContainer& container)
 {
+  // Avoids relayout again when OnSizeSet callback arrives.
+  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 );
 }
 
+} // namespace Internal
+
 } // namespace Toolkit
 
 } // namespace Dali