/*
- * 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.
#include <cfloat>
// INTERNAL INCLUDES
+#include <dali/devel-api/actors/layer-devel.h>
#include <dali/public-api/common/dali-common.h>
#include <dali/public-api/common/constants.h>
#include <dali/public-api/events/touch-data.h>
#include <dali/public-api/math/vector3.h>
#include <dali/public-api/math/radian.h>
#include <dali/public-api/object/type-registry.h>
+#include <dali/devel-api/actors/actor-devel.h>
#include <dali/devel-api/scripting/scripting.h>
#include <dali/internal/common/internal-constants.h>
#include <dali/internal/event/common/event-thread-services.h>
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
/**
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::Actor::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( "screenPosition", VECTOR2, false, false, false, Dali::DevelActor::Property::SCREEN_POSITION )
DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
// Signals
return GetDimensionValue( values.GetVectorXY(), dimension );
}
+unsigned int GetDepthIndex( uint16_t depth, uint16_t siblingOrder )
+{
+ return depth * Dali::DevelLayer::ACTOR_DEPTH_MULTIPLIER + siblingOrder * Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
+}
} // unnamed namespace
return Vector3::ZERO;
}
+const Vector2 Actor::GetCurrentScreenPosition() const
+{
+ if( OnStage() && NULL != mNode )
+ {
+ StagePtr stage = Stage::GetCurrent();
+ Vector3 worldPosition = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
+ Vector3 actorSize = GetCurrentSize() * GetCurrentScale();
+ Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage
+ Vector3 halfActorSize( actorSize * 0.5f );
+ // Anchor point offset first set to TOP_LEFT (0,0.5) then moved to required anchor point.
+ Vector3 anchorPointOffSet = halfActorSize - actorSize * GetCurrentAnchorPoint();
+
+ return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x,
+ halfStageSize.height + worldPosition.y - anchorPointOffSet.y );
+ }
+
+ return Vector2::ZERO;
+}
+
void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
{
// this flag is not animatable so keep the value
return mClippingMode;
}
+unsigned int Actor::GetSortingDepth()
+{
+ return GetDepthIndex( mDepth, mSiblingOrder );
+}
+
const Vector4& Actor::GetCurrentWorldColor() const
{
if( NULL != mNode )
{
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 ) )
// 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
RendererPtr rendererPtr = RendererPtr( &renderer );
mRenderers->push_back( rendererPtr );
AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
-
- if( mIsOnStage)
- {
- rendererPtr->Connect();
- }
-
return index;
}
Dali::Actor::TouchSignalType& Actor::TouchedSignal()
{
- DALI_LOG_WARNING( "Deprecated: Use TouchSignal() instead\n" );
return mTouchedSignal;
}
mName(),
mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
mDepth( 0u ),
+ mSiblingOrder(0u),
mIsRoot( ROOT_LAYER == derivedType ),
mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
mIsOnStage( false ),
mDrawMode( DrawMode::NORMAL ),
mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
mColorMode( Node::DEFAULT_COLOR_MODE ),
- mClippingMode( ClippingMode::DISABLED ),
- mIsBatchParent( false )
+ mClippingMode( ClippingMode::DISABLED )
{
}
mIsOnStage = true;
mDepth = depth;
+ SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
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();
{
// Notification for Object::Observers
OnSceneObjectRemove();
-
- unsigned int rendererCount( GetRendererCount() );
- for( unsigned int i(0); i<rendererCount; ++i )
- {
- GetRendererAt(i)->Disconnect();
- }
}
void Actor::NotifyStageDisconnection()
}
case Dali::Actor::Property::COLOR_ALPHA:
+ case Dali::DevelActor::Property::OPACITY:
{
- SetOpacity( property.Get< float >() );
+ float value;
+ if( property.Get( value ) )
+ {
+ SetOpacity( value );
+ }
break;
}
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 );
}
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 );
}
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 );
}
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 );
}
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 );
}
break;
}
- case Dali::Actor::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;
default:
{
- DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
- break;
+ // nothing to do for other types
}
} // entry.GetType
}
{
Property::Value value;
+ if( index >= DEFAULT_PROPERTY_COUNT )
+ {
+ return value;
+ }
+
switch( index )
{
case Dali::Actor::Property::PARENT_ORIGIN:
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;
}
}
case Dali::Actor::Property::COLOR_ALPHA:
+ case Dali::DevelActor::Property::OPACITY:
{
value = GetCurrentColor().a;
break;
break;
}
- case Dali::Actor::Property::BATCH_PARENT:
+ case Dali::DevelActor::Property::SIBLING_ORDER:
{
- value = mIsBatchParent;
+ value = static_cast<int>(mSiblingOrder);
break;
}
break;
}
- default:
+ case Dali::DevelActor::Property::SCREEN_POSITION:
{
- DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
+ value = GetCurrentScreenPosition();
break;
}
}
break;
case Dali::Actor::Property::COLOR_ALPHA:
+ case Dali::DevelActor::Property::OPACITY:
property = &mNode->mColor;
break;
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;
}
case Dali::Actor::Property::COLOR_ALPHA:
+ case Dali::DevelActor::Property::OPACITY:
{
componentIndex = 3;
break;
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