Added checks to Sibling Order Raise/Lower API
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-impl.cpp
index ce9d371..d1bfa59 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 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.
@@ -87,6 +87,32 @@ inline const Vector2& GetDefaultDimensionPadding()
 
 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
 
+int GetSiblingOrder( ActorPtr actor )
+{
+  Property::Value value  = actor->GetProperty(Dali::DevelActor::Property::SIBLING_ORDER );
+  int order;
+  value.Get( order );
+  return order;
+}
+
+bool ValidateActors( const Internal::Actor& actor, const Internal::Actor& target )
+{
+  bool validTarget = true;
+
+  if( &actor == &target )
+  {
+    DALI_LOG_WARNING( "Source actor and target actor can not be the same, Sibling order not changed.\n" );
+    validTarget = false;
+  }
+  else if( actor.GetParent() != target.GetParent() )
+  {
+    DALI_LOG_WARNING( "Source actor and target actor need to have common parent, Sibling order not changed.\n" );
+    validTarget = false;
+  }
+
+  return validTarget;
+}
+
 } // unnamed namespace
 
 /**
@@ -200,7 +226,8 @@ DALI_PROPERTY( "minimumSize",         VECTOR2,  true,  false, false, Dali::Actor
 DALI_PROPERTY( "maximumSize",         VECTOR2,  true,  false, false, Dali::Actor::Property::MAXIMUM_SIZE )
 DALI_PROPERTY( "inheritPosition",     BOOLEAN,  true,  false, false, Dali::Actor::Property::INHERIT_POSITION )
 DALI_PROPERTY( "clippingMode",        STRING,   true,  false, false, Dali::Actor::Property::CLIPPING_MODE )
-DALI_PROPERTY( "batchParent",         BOOLEAN,  true,  false, false, Dali::DevelActor::Property::BATCH_PARENT )
+DALI_PROPERTY( "siblingOrder",        INTEGER,  true,  false, false, Dali::DevelActor::Property::SIBLING_ORDER )
+DALI_PROPERTY( "opacity",             FLOAT,    true,  true,  true,  Dali::DevelActor::Property::OPACITY )
 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
 
 // Signals
@@ -358,7 +385,7 @@ float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
 
 unsigned int GetDepthIndex( uint16_t depth, uint16_t siblingOrder )
 {
-  return depth * Dali::DevelLayer::TREE_DEPTH_MULTIPLIER + siblingOrder * Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
+  return depth * Dali::DevelLayer::ACTOR_DEPTH_MULTIPLIER + siblingOrder * Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
 }
 
 } // unnamed namespace
@@ -1016,6 +1043,11 @@ ClippingMode::Type Actor::GetClippingMode() const
   return mClippingMode;
 }
 
+unsigned int Actor::GetSortingDepth()
+{
+  return GetDepthIndex( mDepth, mSiblingOrder );
+}
+
 const Vector4& Actor::GetCurrentWorldColor() const
 {
   if( NULL != mNode )
@@ -1290,6 +1322,9 @@ void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimensio
 {
   EnsureRelayoutData();
 
+  ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
+  ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
+
   for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
   {
     if( dimension & ( 1 << i ) )
@@ -1314,6 +1349,34 @@ void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimensio
   // If calling SetResizePolicy, assume we want relayout enabled
   SetRelayoutEnabled( true );
 
+  // If the resize policy is set to be FIXED, the preferred size
+  // should be overrided by the target size. Otherwise the target
+  // size should be overrided by the preferred size.
+
+  if( dimension & Dimension::WIDTH )
+  {
+    if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
+    {
+      mRelayoutData->preferredSize.width = mTargetSize.width;
+    }
+    else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
+    {
+      mTargetSize.width = mRelayoutData->preferredSize.width;
+    }
+  }
+
+  if( dimension & Dimension::HEIGHT )
+  {
+    if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
+    {
+      mRelayoutData->preferredSize.height = mTargetSize.height;
+    }
+    else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
+    {
+      mTargetSize.height = mRelayoutData->preferredSize.height;
+    }
+  }
+
   OnSetResizePolicy( policy, dimension );
 
   // Trigger relayout on this control
@@ -1455,12 +1518,6 @@ unsigned int Actor::AddRenderer( Renderer& renderer )
   RendererPtr rendererPtr = RendererPtr( &renderer );
   mRenderers->push_back( rendererPtr );
   AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
-
-  if( mIsOnStage)
-  {
-    rendererPtr->Connect();
-  }
-
   return index;
 }
 
@@ -1886,7 +1943,6 @@ bool Actor::EmitWheelEventSignal( const WheelEvent& event )
 
 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
 {
-  DALI_LOG_WARNING( "Deprecated: Use TouchSignal() instead\n" );
   return mTouchedSignal;
 }
 
@@ -1993,8 +2049,7 @@ Actor::Actor( DerivedType derivedType )
   mDrawMode( DrawMode::NORMAL ),
   mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
   mColorMode( Node::DEFAULT_COLOR_MODE ),
-  mClippingMode( ClippingMode::DISABLED ),
-  mIsBatchParent( false )
+  mClippingMode( ClippingMode::DISABLED )
 {
 }
 
@@ -2114,12 +2169,6 @@ void Actor::ConnectToSceneGraph()
     ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
   }
 
-  unsigned int rendererCount( GetRendererCount() );
-  for( unsigned int i(0); i<rendererCount; ++i )
-  {
-    GetRendererAt(i)->Connect();
-  }
-
   // Request relayout on all actors that are added to the scenegraph
   RelayoutRequest();
 
@@ -2200,12 +2249,6 @@ void Actor::DisconnectFromSceneGraph()
 {
   // Notification for Object::Observers
   OnSceneObjectRemove();
-
-  unsigned int rendererCount( GetRendererCount() );
-  for( unsigned int i(0); i<rendererCount; ++i )
-  {
-    GetRendererAt(i)->Disconnect();
-  }
 }
 
 void Actor::NotifyStageDisconnection()
@@ -2520,8 +2563,13 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr
     }
 
     case Dali::Actor::Property::COLOR_ALPHA:
+    case Dali::DevelActor::Property::OPACITY:
     {
-      SetOpacity( property.Get< float >() );
+      float value;
+      if( property.Get( value ) )
+      {
+        SetOpacity( value );
+      }
       break;
     }
 
@@ -2563,8 +2611,8 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr
 
     case Dali::Actor::Property::COLOR_MODE:
     {
-      ColorMode mode;
-      if ( Scripting::GetEnumeration< ColorMode >( property.Get< std::string >().c_str(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
+      ColorMode mode = mColorMode;
+      if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
       {
         SetColorMode( mode );
       }
@@ -2573,8 +2621,8 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr
 
     case Dali::Actor::Property::POSITION_INHERITANCE:
     {
-      PositionInheritanceMode mode;
-      if( Scripting::GetEnumeration< PositionInheritanceMode >( property.Get< std::string >().c_str(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
+      PositionInheritanceMode mode = mPositionInheritanceMode;
+      if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
       {
         SetPositionInheritanceMode( mode );
       }
@@ -2583,8 +2631,8 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr
 
     case Dali::Actor::Property::DRAW_MODE:
     {
-      DrawMode::Type mode;
-      if( Scripting::GetEnumeration< DrawMode::Type >( property.Get< std::string >().c_str(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
+      DrawMode::Type mode = mDrawMode;
+      if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
       {
         SetDrawMode( mode );
       }
@@ -2599,8 +2647,8 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr
 
     case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
     {
-      ResizePolicy::Type type;
-      if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
+      ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
+      if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
       {
         SetResizePolicy( type, Dimension::WIDTH );
       }
@@ -2609,8 +2657,8 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr
 
     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
     {
-      ResizePolicy::Type type;
-      if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
+      ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
+      if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
       {
         SetResizePolicy( type, Dimension::HEIGHT );
       }
@@ -2669,39 +2717,20 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr
       break;
     }
 
-    case Dali::DevelActor::Property::BATCH_PARENT:
+    case Dali::DevelActor::Property::SIBLING_ORDER:
     {
-      bool value;
+      int value;
 
       if( property.Get( value ) )
       {
-        if( value != mIsBatchParent )
+        if( static_cast<unsigned int>(value) != mSiblingOrder )
         {
-          mIsBatchParent = value;
-          SetIsBatchParentMessage( GetEventThreadServices(), *mNode, mIsBatchParent );
+          SetSiblingOrder( value );
         }
       }
       break;
     }
 
-    case Dali::DevelActor::Property::SIBLING_ORDER:
-       {
-         int value;
-
-         if( property.Get( value ) )
-         {
-           if( static_cast<unsigned int>(value) != mSiblingOrder )
-           {
-             mSiblingOrder = value;
-             if( mIsOnStage )
-             {
-               SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
-             }
-           }
-         }
-         break;
-       }
-
     case Dali::Actor::Property::CLIPPING_MODE:
     {
       ClippingMode::Type convertedValue = mClippingMode;
@@ -2884,6 +2913,11 @@ Property::Value Actor::GetDefaultProperty( Property::Index index ) const
 {
   Property::Value value;
 
+  if( index >= DEFAULT_PROPERTY_COUNT )
+  {
+    return value;
+  }
+
   switch( index )
   {
     case Dali::Actor::Property::PARENT_ORIGIN:
@@ -2936,19 +2970,48 @@ Property::Value Actor::GetDefaultProperty( Property::Index index ) const
 
     case Dali::Actor::Property::SIZE:
     {
-      value = GetTargetSize();
+      Vector3 size = GetTargetSize();
+
+      // Should return preferred size if size is fixed as set by SetSize
+      if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
+      {
+        size.width = GetPreferredSize().width;
+      }
+      if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
+      {
+        size.height = GetPreferredSize().height;
+      }
+
+      value = size;
+
       break;
     }
 
     case Dali::Actor::Property::SIZE_WIDTH:
     {
-      value = GetTargetSize().width;
+      if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
+      {
+        // Should return preferred size if size is fixed as set by SetSize
+        value = GetPreferredSize().width;
+      }
+      else
+      {
+        value = GetTargetSize().width;
+      }
       break;
     }
 
     case Dali::Actor::Property::SIZE_HEIGHT:
     {
-      value = GetTargetSize().height;
+      if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
+      {
+        // Should return preferred size if size is fixed as set by SetSize
+        value = GetPreferredSize().height;
+      }
+      else
+      {
+        value = GetTargetSize().height;
+      }
       break;
     }
 
@@ -3079,6 +3142,7 @@ Property::Value Actor::GetDefaultProperty( Property::Index index ) const
     }
 
     case Dali::Actor::Property::COLOR_ALPHA:
+    case Dali::DevelActor::Property::OPACITY:
     {
       value = GetCurrentColor().a;
       break;
@@ -3206,12 +3270,6 @@ Property::Value Actor::GetDefaultProperty( Property::Index index ) const
       break;
     }
 
-    case Dali::DevelActor::Property::BATCH_PARENT:
-    {
-      value = mIsBatchParent;
-      break;
-    }
-
     case Dali::DevelActor::Property::SIBLING_ORDER:
     {
       value = static_cast<int>(mSiblingOrder);
@@ -3343,6 +3401,7 @@ const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index ind
         break;
 
       case Dali::Actor::Property::COLOR_ALPHA:
+      case Dali::DevelActor::Property::OPACITY:
         property = &mNode->mColor;
         break;
 
@@ -3511,8 +3570,11 @@ const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index ind
         break;
 
       case Dali::Actor::Property::COLOR_ALPHA:
+      case Dali::DevelActor::Property::OPACITY:
+      {
         property = &mNode->mColor;
         break;
+      }
 
       case Dali::Actor::Property::WORLD_COLOR:
         property = &mNode->mWorldColor;
@@ -3584,6 +3646,7 @@ int Actor::GetPropertyComponentIndex( Property::Index index ) const
       }
 
       case Dali::Actor::Property::COLOR_ALPHA:
+      case Dali::DevelActor::Property::OPACITY:
       {
         componentIndex = 3;
         break;
@@ -4378,6 +4441,483 @@ Object* Actor::GetParentObject() const
   return mParent;
 }
 
+void Actor::SetSiblingOrder( unsigned int order )
+{
+  mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
+  if( mIsOnStage )
+  {
+    SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
+  }
+}
+
+void Actor::DefragmentSiblingIndexes( ActorContainer& siblings )
+{
+  // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER )
+  // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range.
+
+  // Start at index 0, while index <= highest order
+  // Find next index higher than 0
+  //   if nextHigher > index+1
+  //      set all nextHigher orders to index+1
+
+  // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling.
+
+  ActorIter end = siblings.end();
+  int highestOrder = 0;
+  for( ActorIter iter = siblings.begin(); iter != end; ++iter )
+  {
+    ActorPtr sibling = (*iter);
+    int siblingOrder = sibling->mSiblingOrder;
+    highestOrder = std::max( highestOrder, siblingOrder );
+  }
+
+  for ( int index = 0; index <= highestOrder; index++ )
+  {
+    int nextHighest = -1;
+
+    // Find Next highest
+    for( ActorIter iter = siblings.begin(); iter != end; ++iter )
+    {
+      ActorPtr sibling = (*iter);
+      int siblingOrder = sibling->mSiblingOrder;
+
+      if ( siblingOrder > index )
+      {
+        if ( nextHighest == -1 )
+        {
+          nextHighest = siblingOrder;
+        }
+        nextHighest = std::min( nextHighest, siblingOrder );
+      }
+    }
+
+    // Check if a gap exists between indexes, if so set next index to consecutive number
+    if ( ( nextHighest - index ) > 1 )
+    {
+      for( ActorIter iter = siblings.begin(); iter != end; ++iter )
+      {
+        ActorPtr sibling = (*iter);
+        int siblingOrder = sibling->mSiblingOrder;
+        if ( siblingOrder == nextHighest )
+        {
+          sibling->mSiblingOrder =  index + 1;
+          if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER )
+          {
+            DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" );
+            sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
+          }
+          sibling->SetSiblingOrder( sibling->mSiblingOrder );
+        }
+      }
+    }
+  }
+}
+
+bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom )
+{
+  // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1
+  bool defragmentationRequired( false );
+  ActorIter end = siblings.end();
+  for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter )
+  {
+    // Move actors at nearest order and above up by 1
+    ActorPtr sibling = (*iter);
+    if ( sibling != this )
+    {
+      // Iterate through container of actors, any actor with a sibling order of the target or greater should
+      // be incremented by 1.
+      if ( sibling->mSiblingOrder >= targetLevelToShiftFrom )
+      {
+        sibling->mSiblingOrder++;
+        if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
+        {
+          // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so
+          // can re-order all sibling orders.
+          defragmentationRequired = true;
+        }
+        sibling->SetSiblingOrder( sibling->mSiblingOrder );
+      }
+    }
+  }
+  return defragmentationRequired;
+}
+
+void Actor::Raise()
+{
+  /*
+     1) Check if already at top and nothing to be done.
+        This Actor can have highest sibling order but if not exclusive then another actor at same sibling
+        order can be positioned above it due to insertion order of actors.
+     2) Find nearest sibling level above, these are the siblings this actor needs to be above
+     3) a) There may be other levels above this target level
+        b) Increment all sibling levels at the level above nearest(target)
+        c) Now have a vacant sibling level
+     4) Set this actor's sibling level to nearest +1 as now vacated.
+
+     Note May not just be sibling level + 1 as could be empty levels in-between
+
+     Example:
+
+     1 ) Initial order
+        ActorC ( sibling level 4 )
+        ActorB ( sibling level 3 )
+        ActorA ( sibling level 1 )
+
+     2 )  ACTION: Raise A above B
+        a) Find nearest level above A = Level 3
+        b) Increment levels above Level 3
+
+           ActorC ( sibling level 5 )
+           ActorB ( sibling level 3 )  NEAREST
+           ActorA ( sibling level 1 )
+
+     3 ) Set Actor A sibling level to nearest +1 as vacant
+
+         ActorC ( sibling level 5 )
+         ActorA ( sibling level 4 )
+         ActorB ( sibling level 3 )
+
+     4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
+         If shifting causes this ceiling to be reached. then a defragmentation can be performed to
+         remove any empty sibling order gaps and start from sibling level 0 again.
+         If the number of actors reaches this maximum and all using exclusive sibling order values then
+         defragmention will stop and new sibling orders will be set to same max value.
+  */
+  if ( mParent )
+  {
+    int nearestLevel = mSiblingOrder;
+    int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
+    bool defragmentationRequired( false );
+
+    ActorContainer* siblings = mParent->mChildren;
+
+    // Find Nearest sibling level above this actor
+    ActorIter end = siblings->end();
+    for( ActorIter iter = siblings->begin(); iter != end; ++iter )
+    {
+      ActorPtr sibling = (*iter);
+      if ( sibling != this )
+      {
+        int order = GetSiblingOrder( sibling );
+
+        if ( ( order >= mSiblingOrder ) )
+        {
+          int distanceToNextLevel =  order - mSiblingOrder;
+          if ( distanceToNextLevel < shortestDistanceToNextLevel )
+          {
+            nearestLevel = order;
+            shortestDistanceToNextLevel = distanceToNextLevel;
+          }
+        }
+      }
+    }
+
+    if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top
+    {
+      mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level
+      defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
+      // Move current actor to newly vacated order level
+      SetSiblingOrder( mSiblingOrder );
+      if ( defragmentationRequired )
+      {
+        DefragmentSiblingIndexes( *siblings );
+      }
+    }
+    SetSiblingOrder( mSiblingOrder );
+  }
+  else
+  {
+    DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
+  }
+}
+
+void Actor::Lower()
+{
+  /**
+    1) Check if actor already at bottom and if nothing needs to be done
+       This Actor can have lowest sibling order but if not exclusive then another actor at same sibling
+       order can be positioned above it due to insertion order of actors so need to move this actor below it.
+    2) Find nearest sibling level below, this Actor needs to be below it
+    3) a) Need to vacate a sibling level below nearest for this actor to occupy
+       b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level.
+       c) Set this actor's sibling level to this newly vacated level.
+    4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
+       If shifting causes this ceiling to be reached. then a defragmentation can be performed to
+       remove any empty sibling order gaps and start from sibling level 0 again.
+       If the number of actors reaches this maximum and all using exclusive sibling order values then
+       defragmention will stop and new sibling orders will be set to same max value.
+  */
+
+  if ( mParent )
+  {
+    // 1) Find nearest level below
+    int nearestLevel = mSiblingOrder;
+    int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
+
+    ActorContainer* siblings = mParent->mChildren;
+
+    ActorIter end = siblings->end();
+    for( ActorIter iter = siblings->begin(); iter != end; ++iter )
+    {
+      ActorPtr sibling = (*iter);
+      if ( sibling != this )
+      {
+        int order = GetSiblingOrder( sibling );
+
+        if ( order <= mSiblingOrder )
+        {
+          int distanceToNextLevel =  mSiblingOrder - order;
+          if ( distanceToNextLevel < shortestDistanceToNextLevel )
+          {
+            nearestLevel = order;
+            shortestDistanceToNextLevel = distanceToNextLevel;
+          }
+        }
+      }
+    }
+
+    bool defragmentationRequired ( false );
+
+    // 2) If actor already not at bottom, raise all actors at required level and above
+    if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom
+    {
+      mSiblingOrder = nearestLevel;
+      defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
+      // Move current actor to newly vacated order
+      SetSiblingOrder( mSiblingOrder );
+      if ( defragmentationRequired )
+      {
+        DefragmentSiblingIndexes( *siblings );
+      }
+    }
+  }
+  else
+  {
+    DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
+  }
+}
+
+void Actor::RaiseToTop()
+{
+  /**
+    1 ) Find highest sibling order actor
+    2 ) If highest sibling level not itself then set sibling order to that + 1
+    3 ) highest sibling order can be same as itself so need to increment over that
+    4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
+        If shifting causes this ceiling to be reached. then a defragmentation can be performed to
+        remove any empty sibling order gaps and start from sibling level 0 again.
+        If the number of actors reaches this maximum and all using exclusive sibling order values then
+        defragmention will stop and new sibling orders will be set to same max value.
+   */
+
+  if ( mParent )
+  {
+    int maxOrder = 0;
+
+    ActorContainer* siblings = mParent->mChildren;
+
+    ActorIter end = siblings->end();
+    for( ActorIter iter = siblings->begin(); iter != end; ++iter )
+    {
+      ActorPtr sibling = (*iter);
+      if ( sibling != this )
+      {
+        maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder );
+      }
+    }
+
+    bool defragmentationRequired( false );
+
+    if ( maxOrder >= mSiblingOrder )
+    {
+      mSiblingOrder = maxOrder + 1;
+      if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
+      {
+        defragmentationRequired = true;
+      }
+    }
+
+    SetSiblingOrder( mSiblingOrder );
+
+    if ( defragmentationRequired )
+    {
+      DefragmentSiblingIndexes( *siblings );
+    }
+  }
+  else
+  {
+    DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
+  }
+}
+
+void Actor::LowerToBottom()
+{
+  /**
+    See Actor::LowerToBottom()
+
+    1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done.
+    2 ) a ) Check if the bottom position 0 is vacant.
+        b ) If 0 position is not vacant then shift up all sibling order values from 0 and above
+        c ) 0 sibling position is vacant.
+    3 ) Set this actor to vacant sibling order 0;
+    4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
+        If shifting causes this ceiling to be reached. then a defragmentation can be performed to
+        remove any empty sibling order gaps and start from sibling level 0 again.
+        If the number of actors reaches this maximum and all using exclusive sibling order values then
+        defragmention will stop and new sibling orders will be set to same max value.
+   */
+
+  if ( mParent )
+  {
+    bool defragmentationRequired( false );
+    bool orderZeroFree ( true );
+
+    ActorContainer* siblings = mParent->mChildren;
+
+    bool actorAtLowestOrder = true;
+    ActorIter end = siblings->end();
+    for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
+    {
+      ActorPtr sibling = (*iter);
+      if ( sibling != this )
+      {
+        int siblingOrder = GetSiblingOrder( sibling );
+        if ( siblingOrder <= mSiblingOrder )
+        {
+          actorAtLowestOrder = false;
+        }
+
+        if ( siblingOrder == 0 )
+        {
+          orderZeroFree = false;
+        }
+      }
+    }
+
+    if ( ! actorAtLowestOrder  )
+    {
+      if ( ! orderZeroFree )
+      {
+        defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 );
+      }
+      mSiblingOrder = 0;
+      SetSiblingOrder( mSiblingOrder );
+
+      if ( defragmentationRequired )
+      {
+        DefragmentSiblingIndexes( *siblings );
+      }
+    }
+  }
+  else
+  {
+    DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
+  }
+}
+
+void Actor::RaiseAbove( Internal::Actor& target )
+{
+  /**
+    1 ) a) Find target actor's sibling order
+        b) If sibling order of target is the same as this actor then need to this Actor's sibling order
+           needs to be above it or the insertion order will determine which is drawn on top.
+    2 ) Shift up by 1 all sibling order greater than target sibling order
+    3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above
+    4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
+        If shifting causes this ceiling to be reached. then a defragmentation can be performed to
+        remove any empty sibling order gaps and start from sibling level 0 again.
+        If the number of actors reaches this maximum and all using exclusive sibling order values then
+        defragmention will stop and new sibling orders will be set to same max value.
+   */
+
+  if ( mParent )
+  {
+    if ( ValidateActors( *this, target ) )
+    {
+       // Find target's sibling order
+       // Set actor sibling order to this number +1
+      int targetSiblingOrder = GetSiblingOrder( &target );
+      ActorContainer* siblings = mParent->mChildren;
+      mSiblingOrder = targetSiblingOrder + 1;
+      bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
+
+      SetSiblingOrder( mSiblingOrder );
+
+      if ( defragmentationRequired )
+      {
+        DefragmentSiblingIndexes( *(mParent->mChildren) );
+      }
+    }
+  }
+  else
+  {
+    DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
+  }
+}
+
+void Actor::LowerBelow( Internal::Actor& target )
+{
+  /**
+     1 ) a) Find target actor's sibling order
+         b) If sibling order of target is the same as this actor then need to this Actor's sibling order
+            needs to be below it or the insertion order will determine which is drawn on top.
+     2 ) Shift the target sibling order and all sibling orders at that level or above by 1
+     3 ) Set this actor to the sibling order of the target before it changed.
+     4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
+         If shifting causes this ceiling to be reached. then a defragmentation can be performed to
+         remove any empty sibling order gaps and start from sibling level 0 again.
+         If the number of actors reaches this maximum and all using exclusive sibling order values then
+         defragmention will stop and new sibling orders will be set to same max value.
+   */
+
+  if ( mParent )
+  {
+    if ( ValidateActors( *this, target )  )
+    {
+      bool defragmentationRequired ( false );
+      // Find target's sibling order
+      // Set actor sibling order to target sibling order - 1
+      int targetSiblingOrder = GetSiblingOrder( &target);
+      ActorContainer* siblings = mParent->mChildren;
+      if ( targetSiblingOrder == 0 )
+      {
+        //lower to botton
+        ActorIter end = siblings->end();
+        for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
+        {
+          ActorPtr sibling = (*iter);
+          if ( sibling != this )
+          {
+            sibling->mSiblingOrder++;
+            if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
+            {
+              defragmentationRequired = true;
+            }
+            sibling->SetSiblingOrder( sibling->mSiblingOrder );
+          }
+        }
+        mSiblingOrder = 0;
+      }
+      else
+      {
+        defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder );
+
+        mSiblingOrder = targetSiblingOrder;
+      }
+      SetSiblingOrder( mSiblingOrder );
+
+      if ( defragmentationRequired )
+      {
+        DefragmentSiblingIndexes( *(mParent->mChildren) );
+      }
+    }
+  }
+  else
+  {
+    DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
+  }
+}
+
 } // namespace Internal
 
 } // namespace Dali