[AT-SPI] Synchronize with AT-SPI cleanup in dali-adaptor
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / alignment / alignment-impl.cpp
index e887cb4..d9b3b4d 100644 (file)
  */
 
 // CLASS HEADER
-
 #include "alignment-impl.h"
 
 // EXTERNAL INCLUDES
+#include <dali/public-api/object/property-input.h>
+#include <dali/public-api/object/type-registry-helper.h>
 #include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/size-negotiation/relayout-container.h>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-devel.h>
 
 namespace Dali
 {
-
 namespace Toolkit
 {
-
 namespace Internal
 {
-
 namespace
 {
-
 //Type Registration
 BaseHandle Create()
 {
   return Toolkit::Alignment::New();
 }
 
-TypeRegistration mType( typeid(Toolkit::Alignment), typeid(Toolkit::Control), Create );
-
-struct ScaleToFillConstraint
-{
-  /**
-   * @param padding to be added.
-   */
-  ScaleToFillConstraint( const Toolkit::Alignment::Padding& padding )
-  : mPadding( padding )
-  {}
-
-  /**
-   * Called by render thread
-   */
-  Vector3 operator()( const Vector3& currentSize,
-                      const PropertyInput& parentSizeProperty )
-  {
-    const Vector3& parentSize( parentSizeProperty.GetVector3() );
-    return GetSize( currentSize, parentSize );
-  }
-
-  inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
-  {
-    const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
-    const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
-
-    // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
-    if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 ) )
-    {
-      // no point trying to squeeze actors into this small size
-      return Vector3::ZERO;
-    }
-    return  Vector3( parentSizeWidth, parentSizeHeight, parentSize.depth );
-  }
-
-  const Toolkit::Alignment::Padding mPadding;
-};
+DALI_TYPE_REGISTRATION_BEGIN(Toolkit::Alignment, Toolkit::Control, Create)
+DALI_TYPE_REGISTRATION_END()
 
-struct ScaleToFitKeepAspectConstraint
-{
-  /**
-   * @param padding to be added.
-   */
-  ScaleToFitKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
-  : mPadding( padding ),
-    mSizeStored( false ),
-    mOriginalSize()
-  {}
-
-  /**
-   * Called by render thread
-   */
-  Vector3 operator()( const Vector3& currentSize,
-                      const PropertyInput& parentSizeProperty )
-  {
-    const Vector3& parentSize( parentSizeProperty.GetVector3() );
-    return GetSize( currentSize, parentSize );
-  }
-
-  inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
-  {
-    if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
-    {
-      mOriginalSize = currentSize;
-      mSizeStored = true;
-    }
-
-    const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
-    const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
-
-    // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
-    if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
-        ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
-    {
-      // no point trying to squeeze actors into this small size
-      return Vector3::ZERO;
-    }
-
-    return mOriginalSize * std::min( ( parentSizeWidth / mOriginalSize.width ), ( parentSizeHeight / mOriginalSize.height ) );
-  }
-
-  const Toolkit::Alignment::Padding mPadding;
-        bool                        mSizeStored;
-        Vector3                     mOriginalSize;
-};
-
-struct ScaleToFillKeepAspectConstraint
+/**
+ * @param padding The padding value
+ * @param horizontalAlignment The horizontal alignment.
+ * @param verticalAlignment The vertical alignment.
+ * @param currentSize of the object
+ * @param parentSize
+ */
+inline Vector3 GetPosition(const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontalAlignment, Toolkit::Alignment::Type verticalAlignment, const Vector2& currentSize, const Vector2& parentSize)
 {
-  /**
-   * @param padding to be added.
-   */
-  ScaleToFillKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
-  : mPadding( padding ),
-    mSizeStored( false ),
-    mOriginalSize()
-  { }
-
-  /**
-   * Called by render thread
-   */
-  Vector3 operator()( const Vector3& currentSize,
-                      const PropertyInput& parentSizeProperty )
-  {
-    const Vector3& parentSize( parentSizeProperty.GetVector3() );
-    return GetSize( currentSize, parentSize );
-  }
+  Vector3 position(0.f, 0.f, 0.f);
 
-  Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
+  switch(horizontalAlignment)
   {
-    if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
+    case Dali::Toolkit::Alignment::HORIZONTAL_LEFT:
     {
-      mOriginalSize = currentSize;
-      mSizeStored = true;
+      position.x += padding.left;
+      break;
     }
-
-    const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
-    const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
-
-    // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
-    if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
-        ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
-    {
-      // no point trying to squeeze actors into this small size
-      return Vector3::ZERO;
-    }
-
-    return mOriginalSize * std::max( ( parentSizeWidth / mOriginalSize.width ), ( parentSizeHeight / mOriginalSize.height ) );
-  }
-
-  const Toolkit::Alignment::Padding mPadding;
-        bool                        mSizeStored;
-        Vector3                     mOriginalSize;
-};
-
-struct ShrinkToFitConstraint
-{
-  /**
-   * @param padding to be added.
-   */
-  ShrinkToFitConstraint( const Toolkit::Alignment::Padding& padding )
-  : mPadding( padding ),
-    mSizeStored( false ),
-    mOriginalSize()
-  {}
-
-  /**
-   * Called by render thread
-   */
-  Vector3 operator()( const Vector3& currentSize,
-                      const PropertyInput& parentSizeProperty )
-  {
-    const Vector3& parentSize( parentSizeProperty.GetVector3() );
-    return GetSize( currentSize, parentSize );
-  }
-
-  Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
-  {
-    if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
+    case Dali::Toolkit::Alignment::HORIZONTAL_RIGHT:
     {
-      mOriginalSize = currentSize;
-      mSizeStored = true;
+      position.x -= padding.right;
+      break;
     }
-
-    const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
-    const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
-
-    // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
-    if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
-        ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
+    case Dali::Toolkit::Alignment::HORIZONTAL_CENTER: // FALLTHROUGH
+    default:                                          // use center as default
     {
-      // no point trying to squeeze actors into this small size
-      return Vector3::ZERO;
+      if(currentSize.width + padding.left + padding.right >= parentSize.width)
+      {
+        position.x += 0.5f * (padding.left - padding.right);
+      }
+      break;
     }
-
-    return Vector3( std::min( parentSizeWidth, mOriginalSize.width ), std::min( parentSizeHeight, mOriginalSize.height ), std::min( parentSize.depth, mOriginalSize.depth ) );
   }
 
-  const Toolkit::Alignment::Padding mPadding;
-        bool                        mSizeStored;
-        Vector3                     mOriginalSize;
-};
-
-/**
- * Constraint that uses naturalSize if it fits inside parent and parent size if not. It also adds some padding pixels
- */
-struct ShrinkToFitKeepAspectConstraint
-{
-  /**
-   * @param padding to be added.
-   */
-  ShrinkToFitKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
-  : mPadding( padding ),
-    mSizeStored( false ),
-    mOriginalSize()
-  {}
-
-  /**
-   * Called by render thread
-   */
-  Vector3 operator()( const Vector3& currentSize,
-                      const PropertyInput& parentSizeProperty )
-  {
-    const Vector3& parentSize( parentSizeProperty.GetVector3() );
-    return GetSize( currentSize, parentSize );
-  }
-
-  inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
+  switch(verticalAlignment)
   {
-    if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
-    {
-      mOriginalSize = currentSize;
-      mSizeStored = true;
-    }
-
-    const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
-    const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
-
-    // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
-    if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
-        ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
+    case Dali::Toolkit::Alignment::VERTICAL_TOP:
     {
-      // no point trying to squeeze actors into this small size
-      return Vector3::ZERO;
+      position.y += padding.top;
+      break;
     }
-
-    return Vector3( ShrinkInside( Vector2( parentSizeWidth, parentSizeHeight ), Vector2( mOriginalSize ) ) );
-  }
-
-  const Toolkit::Alignment::Padding mPadding;
-        bool                        mSizeStored;
-        Vector3                     mOriginalSize;
-};
-
-/**
- * Constraint that modifies the contained actor taking into account the padding value.
- */
-struct PositionConstraint
-{
-  /**
-   * @param padding The padding value
-   * @param horizontalAlignment The horizontal alignment.
-   * @param verticalAlignment The vertical alignment.
-   */
-  PositionConstraint( const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontalAlignment, Toolkit::Alignment::Type verticalAlignment )
-  : mPadding( padding ),
-    mHorizontalAlignment( horizontalAlignment ),
-    mVerticalAlignment( verticalAlignment )
-  {}
-
-  /**
-   * Called by render thread.
-   */
-  Vector3 operator()( const Vector3& currentPosition,
-                      const PropertyInput& currentSizeProperty,
-                      const PropertyInput& parentSizeProperty )
-  {
-    const Vector3& currentSize( currentSizeProperty.GetVector3() );
-    const Vector3& parentSize( parentSizeProperty.GetVector3() );
-
-    Vector3 position( 0.f, 0.f, 0.f );
-
-    switch( mHorizontalAlignment )
+    case Dali::Toolkit::Alignment::VERTICAL_BOTTOM:
     {
-      case Dali::Toolkit::Alignment::HorizontalLeft:
-      {
-        position.x += mPadding.left;
-        break;
-      }
-      case Dali::Toolkit::Alignment::HorizontalCenter:
-      {
-        if( currentSize.width + mPadding.left + mPadding.right >= parentSize.width )
-        {
-          position.x += 0.5f * ( mPadding.left - mPadding.right );
-        }
-        break;
-      }
-      case Dali::Toolkit::Alignment::HorizontalRight:
-      {
-        position.x -= mPadding.right;
-        break;
-      }
-      default:
-      {
-        DALI_ASSERT_ALWAYS( !"Wrong horizontal alignment value" );
-        break;
-      }
+      position.y -= padding.bottom;
+      break;
     }
-
-    switch( mVerticalAlignment )
+    case Dali::Toolkit::Alignment::VERTICAL_CENTER: // FALLTHROUGH
+    default:                                        // use center as default
     {
-      case Dali::Toolkit::Alignment::VerticalTop:
+      if(currentSize.height + padding.top + padding.bottom >= parentSize.height)
       {
-        position.y += mPadding.top;
-        break;
-      }
-      case Dali::Toolkit::Alignment::VerticalCenter:
-      {
-        if( currentSize.height + mPadding.top + mPadding.bottom >= parentSize.height )
-        {
-          position.y += 0.5f * ( mPadding.top - mPadding.bottom );
-        }
-        break;
-      }
-      case Dali::Toolkit::Alignment::VerticalBottom:
-      {
-        position.y -= mPadding.bottom;
-        break;
-      }
-      default:
-      {
-        DALI_ASSERT_ALWAYS( !"Wrong vertical alignment value" );
-        break;
+        position.y += 0.5f * (padding.top - padding.bottom);
       }
+      break;
     }
-
-    return position;
   }
 
-  const Toolkit::Alignment::Padding mPadding;
-  const Toolkit::Alignment::Type mHorizontalAlignment;
-  const Toolkit::Alignment::Type mVerticalAlignment;
-};
-
-void SetPositionConstraint( Actor actor, const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
-{
-  Constraint constraint = Constraint::New<Vector3>( Actor::POSITION,
-                                                    LocalSource( Actor::SIZE ),
-                                                    ParentSource( Actor::SIZE ),
-                                                    PositionConstraint( padding, horizontal, vertical ) );
-  actor.ApplyConstraint( constraint );
+  return position;
 }
+
 } // namespace
 
-Toolkit::Alignment Alignment::New( Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
+Toolkit::Alignment Alignment::New(Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical)
 {
   // Create the implementation, temporarily owned on stack
-  IntrusivePtr< Alignment > internalAlignment = new Alignment( horizontal, vertical );
+  IntrusivePtr<Alignment> internalAlignment = new Alignment(horizontal, vertical);
 
-  // Pass ownership to Toolkit::View
-  Toolkit::Alignment alignment( *internalAlignment );
+  // Pass ownership to Toolkit::Alignment
+  Toolkit::Alignment alignment(*internalAlignment);
 
   // Second-phase init of the implementation
   // This can only be done after the CustomActor connection has been made...
@@ -390,34 +121,34 @@ Toolkit::Alignment Alignment::New( Toolkit::Alignment::Type horizontal, Toolkit:
   return alignment;
 }
 
-void Alignment::SetAlignmentType( Toolkit::Alignment::Type type )
+void Alignment::SetAlignmentType(Toolkit::Alignment::Type type)
 {
   // Horizontal Alignment
-  if( type & Toolkit::Alignment::HorizontalRight )
+  if(type & Toolkit::Alignment::HORIZONTAL_RIGHT)
   {
-    mHorizontal = Toolkit::Alignment::HorizontalRight;
+    mHorizontal = Toolkit::Alignment::HORIZONTAL_RIGHT;
   }
-  if( type & Toolkit::Alignment::HorizontalLeft )
+  if(type & Toolkit::Alignment::HORIZONTAL_LEFT)
   {
-    mHorizontal = Toolkit::Alignment::HorizontalLeft;
+    mHorizontal = Toolkit::Alignment::HORIZONTAL_LEFT;
   }
-  if( type & Toolkit::Alignment::HorizontalCenter )
+  if(type & Toolkit::Alignment::HORIZONTAL_CENTER)
   {
-    mHorizontal = Toolkit::Alignment::HorizontalCenter;
+    mHorizontal = Toolkit::Alignment::HORIZONTAL_CENTER;
   }
 
   // Vertical Alignment
-  if( type & Toolkit::Alignment::VerticalBottom )
+  if(type & Toolkit::Alignment::VERTICAL_BOTTOM)
   {
-    mVertical = Toolkit::Alignment::VerticalBottom;
+    mVertical = Toolkit::Alignment::VERTICAL_BOTTOM;
   }
-  if( type & Toolkit::Alignment::VerticalTop )
+  if(type & Toolkit::Alignment::VERTICAL_TOP)
   {
-    mVertical = Toolkit::Alignment::VerticalTop;
+    mVertical = Toolkit::Alignment::VERTICAL_TOP;
   }
-  if( type & Toolkit::Alignment::VerticalCenter )
+  if(type & Toolkit::Alignment::VERTICAL_CENTER)
   {
-    mVertical = Toolkit::Alignment::VerticalCenter;
+    mVertical = Toolkit::Alignment::VERTICAL_CENTER;
   }
 
   RelayoutRequest();
@@ -425,10 +156,10 @@ void Alignment::SetAlignmentType( Toolkit::Alignment::Type type )
 
 Toolkit::Alignment::Type Alignment::GetAlignmentType() const
 {
-  return Toolkit::Alignment::Type( mHorizontal | mVertical );
+  return Toolkit::Alignment::Type(mHorizontal | mVertical);
 }
 
-void Alignment::SetScaling( Toolkit::Alignment::Scaling scaling )
+void Alignment::SetScaling(Toolkit::Alignment::Scaling scaling)
 {
   mScaling = scaling;
 
@@ -440,9 +171,9 @@ Toolkit::Alignment::Scaling Alignment::GetScaling() const
   return mScaling;
 }
 
-void Alignment::SetPadding( const Toolkit::Alignment::Padding& padding )
+void Alignment::SetPadding(const Toolkit::Alignment::Padding& padding)
 {
-  DALI_ASSERT_ALWAYS( ( padding.left >= 0.f ) && ( padding.top >= 0.f ) && ( padding.right >= 0.f ) && ( padding.bottom >= 0.f ) );
+  DALI_ASSERT_ALWAYS((padding.left >= 0.f) && (padding.top >= 0.f) && (padding.right >= 0.f) && (padding.bottom >= 0.f));
 
   mPadding = padding;
 
@@ -454,112 +185,122 @@ const Toolkit::Alignment::Padding& Alignment::GetPadding() const
   return mPadding;
 }
 
-void Alignment::OnRelayout( const Vector2& size, ActorSizeContainer& container )
+void Alignment::OnInitialize()
+{
+  DevelControl::SetAccessibilityConstructor(Self(), [](Dali::Actor actor) {
+    return std::unique_ptr<Dali::Accessibility::Accessible>(
+      new DevelControl::ControlAccessible(actor, Dali::Accessibility::Role::FILLER));
+  });
+}
+
+void Alignment::OnRelayout(const Vector2& size, RelayoutContainer& container)
 {
   // lay out the actors
-  Vector3 anchorPointAndParentOrigin  = Vector3::ZERO;
-  anchorPointAndParentOrigin.z = 0.5f;
-  // anchorPoint.x is initialized to 0.0, which is HorizontalLeft
-  if( Toolkit::Alignment::HorizontalCenter == mHorizontal )
+  Vector3 anchorPointAndParentOrigin = Vector3::ZERO;
+  anchorPointAndParentOrigin.z       = 0.5f;
+  // anchorPoint.x is initialized to 0.0, which is HORIZONTAL_LEFT
+  if(Toolkit::Alignment::HORIZONTAL_CENTER == mHorizontal)
   {
     anchorPointAndParentOrigin.x = 0.5f;
   }
-  else if( Toolkit::Alignment::HorizontalRight == mHorizontal )
+  else if(Toolkit::Alignment::HORIZONTAL_RIGHT == mHorizontal)
   {
     anchorPointAndParentOrigin.x = 1.0f;
   }
-  // anchorPoint.y is initialized to 0.0, which is VerticalTop
-  if( Toolkit::Alignment::VerticalCenter == mVertical )
+  // anchorPoint.y is initialized to 0.0, which is VERTICAL_TOP
+  if(Toolkit::Alignment::VERTICAL_CENTER == mVertical)
   {
     anchorPointAndParentOrigin.y = 0.5f;
   }
-  else if( Toolkit::Alignment::VerticalBottom == mVertical )
+  else if(Toolkit::Alignment::VERTICAL_BOTTOM == mVertical)
   {
     anchorPointAndParentOrigin.y = 1.0f;
   }
 
-  unsigned int childCount = Self().GetChildCount();
-  for( unsigned int i=0; i<childCount; ++i )
+  for(unsigned int i = 0, childCount = Self().GetChildCount(); i < childCount; ++i)
   {
-    Actor actor = Self().GetChildAt(i);
+    Actor child = Self().GetChildAt(i);
 
-    actor.SetAnchorPoint( anchorPointAndParentOrigin );
-    actor.SetParentOrigin( anchorPointAndParentOrigin );
+    child.SetProperty(Actor::Property::ANCHOR_POINT, anchorPointAndParentOrigin);
+    child.SetProperty(Actor::Property::PARENT_ORIGIN, anchorPointAndParentOrigin);
 
-    if( Toolkit::Alignment::ScaleNone != mScaling )
+    Vector2 currentChildSize(child.GetTargetSize().GetVectorXY());
+    if(currentChildSize == Vector2::ZERO)
     {
-      actor.RemoveConstraints();
+      currentChildSize = child.GetNaturalSize();
     }
 
-    Vector3 actorSize ( actor.GetCurrentSize() );
-    Toolkit::Control control( Toolkit::Control::DownCast( actor ) );
-    if ( actorSize == Vector3::ZERO && control )
-    {
-      actorSize = control.GetNaturalSize();
-    }
+    bool    renegotiate = true;
+    Vector2 newChildSize;
+    newChildSize.width  = size.width - (mPadding.left + mPadding.right);
+    newChildSize.height = size.height - (mPadding.top + mPadding.bottom);
 
-    Vector2 childSize;
-
-    switch( mScaling )
+    // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
+    if((newChildSize.width > Math::MACHINE_EPSILON_1000) && (newChildSize.height > Math::MACHINE_EPSILON_1000) &&
+       (currentChildSize.width > Math::MACHINE_EPSILON_1000) && (currentChildSize.height > Math::MACHINE_EPSILON_1000))
     {
-      case Toolkit::Alignment::ScaleNone:
-      {
-        // Nothing to do but needed just to not to jump to the default.
-        childSize = size;
-        break;
-      }
-      case Toolkit::Alignment::ScaleToFill:
-      {
-        ScaleToFillConstraint constraint( mPadding );
-        childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
-        SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
-        break;
-      }
-      case Toolkit::Alignment::ScaleToFitKeepAspect:
-      {
-        ScaleToFitKeepAspectConstraint constraint( mPadding );
-        childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
-        SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
-        break;
-      }
-      case Toolkit::Alignment::ScaleToFillKeepAspect:
-      {
-        ScaleToFillKeepAspectConstraint constraint( mPadding );
-        childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
-        SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
-        break;
-      }
-      case Toolkit::Alignment::ShrinkToFit:
-      {
-        ShrinkToFitConstraint constraint( mPadding );
-        childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
-        SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
-        break;
-      }
-      case Toolkit::Alignment::ShrinkToFitKeepAspect:
+      // no point trying to squeeze actors into too small size
+      switch(mScaling)
       {
-        ShrinkToFitKeepAspectConstraint constraint( mPadding );
-        childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
-        SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
-        break;
-      }
-      default:
-      {
-        DALI_ASSERT_ALWAYS( !"Invalid Alignment::mGeometryScaling value" );
-        break;
+        case Toolkit::Alignment::SCALE_NONE:
+        {
+          // Nothing to do
+          renegotiate = false;
+          break;
+        }
+        case Toolkit::Alignment::SCALE_TO_FILL:
+        {
+          // Nothing to do, newChildSize is already full size minus padding
+          break;
+        }
+        case Toolkit::Alignment::SCALE_TO_FIT_KEEP_ASPECT:
+        {
+          newChildSize = currentChildSize * std::min((newChildSize.width / currentChildSize.width), (newChildSize.height / currentChildSize.height));
+          break;
+        }
+        case Toolkit::Alignment::SCALE_TO_FILL_KEEP_ASPECT:
+        {
+          newChildSize = currentChildSize * std::max((newChildSize.width / currentChildSize.width), (newChildSize.height / currentChildSize.height));
+          break;
+        }
+        case Toolkit::Alignment::SHRINK_TO_FIT:
+        {
+          newChildSize = Vector2(std::min(newChildSize.width, currentChildSize.width), std::min(newChildSize.height, currentChildSize.height));
+          break;
+        }
+        case Toolkit::Alignment::SHRINK_TO_FIT_KEEP_ASPECT:
+        {
+          // check source size vs target size to see if we need to shrink
+          float widthScale  = (newChildSize.width < currentChildSize.width) ? (newChildSize.width / currentChildSize.width) : 1.f;
+          float heightScale = (newChildSize.height < currentChildSize.height) ? (newChildSize.height / currentChildSize.height) : 1.0f;
+          // use smaller of the scales
+          float scale = std::min(widthScale, heightScale);
+          // check if we need to scale
+          if(scale < 1.0f)
+          {
+            // scale natural size to fit inside
+            newChildSize *= scale;
+          }
+          break;
+        }
       }
     }
 
-    Relayout( actor, childSize, container );
+    child.SetProperty(Actor::Property::POSITION, GetPosition(mPadding, mHorizontal, mVertical, newChildSize, currentChildSize));
+
+    if(renegotiate)
+    {
+      container.Add(child, newChildSize);
+    }
   }
 }
 
-Alignment::Alignment( Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
-: Control( CONTROL_BEHAVIOUR_NONE ),
-  mHorizontal( horizontal ),
-  mVertical( vertical ),
-  mScaling( Toolkit::Alignment::ScaleNone ),
-  mPadding( 0.f, 0.f, 0.f, 0.f )
+Alignment::Alignment(Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical)
+: Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
+  mHorizontal(horizontal),
+  mVertical(vertical),
+  mScaling(Toolkit::Alignment::SCALE_NONE),
+  mPadding(0.f, 0.f, 0.f, 0.f)
 {
 }