[dali_1.3.40] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-impl.cpp
index ea7fe9f..bbf91e8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 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.
@@ -33,7 +33,6 @@
 #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/object/weak-handle.h>
 #include <dali/devel-api/scripting/scripting.h>
 #include <dali/internal/common/internal-constants.h>
 #include <dali/internal/event/common/event-thread-services.h>
@@ -208,6 +207,8 @@ DALI_PROPERTY( "minimumSize",               VECTOR2,  true,  false, false, Dali:
 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( "layoutDirection",           STRING,   true,  false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
+DALI_PROPERTY( "inheritLayoutDirection",    BOOLEAN,  true,  false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
 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 )
@@ -223,6 +224,10 @@ const char* const SIGNAL_ON_STAGE = "onStage";
 const char* const SIGNAL_OFF_STAGE = "offStage";
 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
 const char* const SIGNAL_TOUCH = "touch";
+const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
+const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
+const char* const SIGNAL_CHILD_ADDED = "childAdded";
+const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
 
 // Actions
 
@@ -243,6 +248,10 @@ SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectS
 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
+SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
+SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
+SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
+SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
 
 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
@@ -307,6 +316,10 @@ DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
 
+DALI_ENUM_TO_STRING_TABLE_BEGIN( LAYOUT_DIRECTION )
+DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, LEFT_TO_RIGHT )
+DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, RIGHT_TO_LEFT )
+DALI_ENUM_TO_STRING_TABLE_END( LAYOUT_DIRECTION )
 
 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
 {
@@ -468,7 +481,7 @@ void Actor::Add( Actor& child )
     // if we already have parent, unparent us first
     if( oldParent )
     {
-      oldParent->Remove( child ); // This causes OnChildRemove callback
+      oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
 
       // Old parent may need to readjust to missing child
       if( oldParent->RelayoutDependentOnChildren() )
@@ -488,6 +501,9 @@ void Actor::Add( Actor& child )
 
       // Notification for derived classes
       OnChildAdd( child );
+      EmitChildAddedSignal( child );
+
+      InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
 
       // Only put in a relayout request if there is a suitable dependency
       if( RelayoutDependentOnChildren() )
@@ -540,6 +556,7 @@ void Actor::Remove( Actor& child )
 
   // Notification for derived classes
   OnChildRemove( child );
+  EmitChildRemovedSignal( child );
 }
 
 void Actor::Unparent()
@@ -807,11 +824,14 @@ const Vector3& Actor::GetCurrentWorldPosition() const
 
 const Vector2 Actor::GetCurrentScreenPosition() const
 {
-  if( OnStage() && NULL != mNode )
+  StagePtr stage = Stage::GetCurrent();
+  if( stage && OnStage() && NULL != mNode )
   {
-    StagePtr stage = Stage::GetCurrent();
     Vector3 worldPosition =  mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
-    Vector3 actorSize = GetCurrentSize() * GetCurrentScale();
+    Vector3 cameraPosition = stage->GetDefaultCameraActor().mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
+    worldPosition -= cameraPosition;
+
+    Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
     Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage
     Vector3 halfActorSize( actorSize * 0.5f );
     Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
@@ -1986,6 +2006,33 @@ void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityCha
   }
 }
 
+void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
+{
+  if( ! mLayoutDirectionChangedSignal.Empty() )
+  {
+    Dali::Actor handle( this );
+    mLayoutDirectionChangedSignal.Emit( handle, type );
+  }
+}
+
+void Actor::EmitChildAddedSignal( Actor& child )
+{
+  if( ! mChildAddedSignal.Empty() )
+  {
+    Dali::Actor handle( &child );
+    mChildAddedSignal.Emit( handle );
+  }
+}
+
+void Actor::EmitChildRemovedSignal( Actor& child )
+{
+  if( ! mChildRemovedSignal.Empty() )
+  {
+    Dali::Actor handle( &child );
+    mChildRemovedSignal.Emit( handle );
+  }
+}
+
 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
 {
   return mTouchedSignal;
@@ -2026,6 +2073,26 @@ DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
   return mVisibilityChangedSignal;
 }
 
+Dali::Actor::LayoutDirectionChangedSignalType& Actor::LayoutDirectionChangedSignal()
+{
+  return mLayoutDirectionChangedSignal;
+}
+
+DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
+{
+  return mChildAddedSignal;
+}
+
+DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
+{
+  return mChildRemovedSignal;
+}
+
+DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
+{
+  return mChildOrderChangedSignal;
+}
+
 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
 {
   bool connected( true );
@@ -2059,6 +2126,22 @@ bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tra
   {
     actor->TouchSignal().Connect( tracker, functor );
   }
+  else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
+  {
+    actor->VisibilityChangedSignal().Connect( tracker, functor );
+  }
+  else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
+  {
+    actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
+  }
+  else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
+  {
+    actor->ChildAddedSignal().Connect( tracker, functor );
+  }
+  else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
+  {
+    actor->ChildRemovedSignal().Connect( tracker, functor );
+  }
   else
   {
     // signalName does not match any signal
@@ -2077,6 +2160,18 @@ Actor::Actor( DerivedType derivedType )
   mAnchorPoint( NULL ),
   mRelayoutData( NULL ),
   mGestureData( NULL ),
+  mTouchedSignal(),
+  mTouchSignal(),
+  mHoveredSignal(),
+  mWheelEventSignal(),
+  mOnStageSignal(),
+  mOffStageSignal(),
+  mOnRelayoutSignal(),
+  mVisibilityChangedSignal(),
+  mLayoutDirectionChangedSignal(),
+  mChildAddedSignal(),
+  mChildRemovedSignal(),
+  mChildOrderChangedSignal(),
   mTargetOrientation( Quaternion::IDENTITY ),
   mTargetColor( Color::WHITE ),
   mTargetSize( Vector3::ZERO ),
@@ -2102,6 +2197,8 @@ Actor::Actor( DerivedType derivedType )
   mInheritScale( true ),
   mPositionUsesAnchorPoint( true ),
   mVisible( true ),
+  mInheritLayoutDirection( true ),
+  mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
   mDrawMode( DrawMode::NORMAL ),
   mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
   mColorMode( Node::DEFAULT_COLOR_MODE ),
@@ -2860,6 +2957,28 @@ void Actor::SetDefaultProperty( Property::Index index, const Property::Value& pr
       break;
     }
 
+    case Dali::Actor::Property::LAYOUT_DIRECTION:
+    {
+      Dali::LayoutDirection::Type direction = mLayoutDirection;
+      mInheritLayoutDirection = false;
+
+      if( Scripting::GetEnumerationProperty< LayoutDirection::Type >( property, LAYOUT_DIRECTION_TABLE, LAYOUT_DIRECTION_TABLE_COUNT, direction ) )
+      {
+        InheritLayoutDirectionRecursively( this, direction, true );
+      }
+      break;
+    }
+
+    case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
+    {
+      bool value = false;
+      if( property.Get( value ) )
+      {
+        SetInheritLayoutDirection( value );
+      }
+      break;
+    }
+
     default:
     {
       // this can happen in the case of a non-animatable default property so just do nothing
@@ -3774,7 +3893,7 @@ void Actor::SetParent( Actor* parent )
 
 SceneGraph::Node* Actor::CreateNode() const
 {
-  return Node::New();
+  return Node::New( mId );
 }
 
 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
@@ -4102,6 +4221,18 @@ bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& valu
       break;
     }
 
+    case Dali::Actor::Property::LAYOUT_DIRECTION:
+    {
+      value = mLayoutDirection;
+      break;
+    }
+
+    case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
+    {
+      value = IsLayoutDirectionInherited();
+      break;
+    }
+
     default:
     {
       // Must be a scene-graph only property
@@ -5136,6 +5267,10 @@ void Actor::Raise()
         }
       }
     }
+
+    Dali::Actor handle( this );
+    mParent->mChildOrderChangedSignal.Emit( handle );
+
     RequestRebuildDepthTree();
   }
   else
@@ -5151,7 +5286,7 @@ void Actor::Lower()
     ActorContainer& siblings = *(mParent->mChildren);
     if( siblings.front() != this ) // If not already at beginning
     {
-      for( size_t i=0; i<siblings.size(); ++i )
+      for( size_t i=1; i<siblings.size(); ++i )
       {
         if( siblings[i] == this )
         {
@@ -5163,6 +5298,10 @@ void Actor::Lower()
         }
       }
     }
+
+    Dali::Actor handle( this );
+    mParent->mChildOrderChangedSignal.Emit( handle );
+
     RequestRebuildDepthTree();
   }
   else
@@ -5185,6 +5324,10 @@ void Actor::RaiseToTop()
         siblings.push_back(ActorPtr(this));
       }
     }
+
+    Dali::Actor handle( this );
+    mParent->mChildOrderChangedSignal.Emit( handle );
+
     RequestRebuildDepthTree();
   }
   else
@@ -5209,6 +5352,10 @@ void Actor::LowerToBottom()
         siblings.insert(siblings.begin(), thisPtr);
       }
     }
+
+    Dali::Actor handle( this );
+    mParent->mChildOrderChangedSignal.Emit( handle );
+
     RequestRebuildDepthTree();
   }
   else
@@ -5237,6 +5384,10 @@ void Actor::RaiseAbove( Internal::Actor& target )
         ++targetIter;
         siblings.insert(targetIter, thisPtr);
       }
+
+      Dali::Actor handle( this );
+      mParent->mChildOrderChangedSignal.Emit( handle );
+
       RequestRebuildDepthTree();
     }
   }
@@ -5263,6 +5414,10 @@ void Actor::LowerBelow( Internal::Actor& target )
         siblings.erase(thisIter); // this only invalidates iterators at or after this point.
         siblings.insert(targetIter, thisPtr);
       }
+
+      Dali::Actor handle( this );
+      mParent->mChildOrderChangedSignal.Emit( handle );
+
       RequestRebuildDepthTree();
     }
   }
@@ -5272,6 +5427,46 @@ void Actor::LowerBelow( Internal::Actor& target )
   }
 }
 
+void Actor::SetInheritLayoutDirection( bool inherit )
+{
+  if( mInheritLayoutDirection != inherit )
+  {
+    mInheritLayoutDirection = inherit;
+
+    if( inherit && mParent )
+    {
+      InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
+    }
+  }
+}
+
+bool Actor::IsLayoutDirectionInherited() const
+{
+  return mInheritLayoutDirection;
+}
+
+void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
+{
+  if( actor && ( actor->mInheritLayoutDirection || set ) )
+  {
+    if( actor->mLayoutDirection != direction)
+    {
+      actor->mLayoutDirection = direction;
+      actor->EmitLayoutDirectionChangedSignal( direction );
+      actor->RelayoutRequest();
+    }
+
+    if( actor->GetChildCount() > 0 )
+    {
+      ActorContainer& children = actor->GetChildrenInternal();
+      for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
+      {
+        InheritLayoutDirectionRecursively( *iter, direction );
+      }
+    }
+  }
+}
+
 } // namespace Internal
 
 } // namespace Dali