Remove a dead virtual method from proxy object
[platform/core/uifw/dali-core.git] / dali / internal / event / animation / active-constraint-base.cpp
index bb67c2d..121ed80 100644 (file)
@@ -1,18 +1,19 @@
-//
-// Copyright (c) 2014 Samsung Electronics Co., Ltd.
-//
-// Licensed under the Flora License, Version 1.0 (the License);
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://floralicense.org/license/
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an AS IS BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
 
 // CLASS HEADER
 #include <dali/internal/event/animation/active-constraint-base.h>
@@ -60,7 +61,7 @@ namespace // unnamed namespace
  * We want to discourage the use of property strings (minimize string comparisons),
  * particularly for the default properties.
  */
-const std::string DEFAULT_PROPERTY_NAMES[] =
+const char* DEFAULT_PROPERTY_NAMES[] =
 {
   "weight"
 };
@@ -73,39 +74,76 @@ const Property::Type DEFAULT_PROPERTY_TYPES[DEFAULT_PROPERTY_COUNT] =
 
 } // unnamed namespace
 
-ActiveConstraintBase::ActiveConstraintBase( EventToUpdate& eventToUpdate, Property::Index targetPropertyIndex )
+ActiveConstraintBase::ActiveConstraintBase( EventToUpdate& eventToUpdate, Property::Index targetPropertyIndex, SourceContainer& sources, unsigned int sourceCount )
 : mEventToUpdate( eventToUpdate ),
   mTargetPropertyIndex( targetPropertyIndex ),
+  mSources( sources ),
+  mSourceCount( sourceCount ),
   mTargetProxy( NULL ),
+  mObservedProxies(),
   mSceneGraphConstraint( NULL ),
+  mCustomWeight( NULL ),
   mOffstageWeight( Dali::ActiveConstraint::DEFAULT_WEIGHT ),
-  mRemoveTime( 0.0f ),
   mAlphaFunction( Dali::Constraint::DEFAULT_ALPHA_FUNCTION ),
   mRemoveAction( Dali::Constraint::DEFAULT_REMOVE_ACTION ),
-  mApplyAnimation(),
-  mRemoveAnimation()
+  mTag(0),
+  mApplyAnimation()
 {
+  // Skip init when any of the proxy objects have been destroyed
+  if ( mSources.size() != mSourceCount )
+  {
+    // Discard all proxy pointers
+    mTargetProxy = NULL;
+    mSources.clear();
+  }
+
+  // Observe the objects providing properties
+  for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
+  {
+    if ( OBJECT_PROPERTY == iter->sourceType )
+    {
+      DALI_ASSERT_ALWAYS( NULL != iter->object && "ActiveConstraint source object not found" );
+
+      ObserveProxy( *(iter->object) );
+    }
+  }
 }
 
 ActiveConstraintBase::~ActiveConstraintBase()
 {
-  // Disconnect from internal animation signals
+  StopObservation();
 
+  // Disconnect from internal animation signals
   if ( mApplyAnimation )
   {
     GetImplementation(mApplyAnimation).SetFinishedCallback( NULL, NULL );
   }
+}
+
+void ActiveConstraintBase::SetCustomWeightObject( ProxyObject& weightObject, Property::Index weightIndex )
+{
+  const SceneGraph::PropertyBase* base = weightObject.GetSceneObjectAnimatableProperty( weightIndex );
+  const SceneGraph::AnimatableProperty<float>* sceneProperty = dynamic_cast< const SceneGraph::AnimatableProperty<float>* >( base );
 
-  if( mRemoveAnimation )
+  if( sceneProperty )
   {
-    GetImplementation(mRemoveAnimation).SetFinishedCallback( NULL, NULL );
+    mCustomWeight = sceneProperty;
+
+    ObserveProxy( weightObject );
   }
 }
 
-void ActiveConstraintBase::FirstApply( ProxyObject& parent, TimePeriod applyTime, ActiveConstraintCallbackType* callback )
+void ActiveConstraintBase::FirstApply( ProxyObject& parent, TimePeriod applyTime )
 {
-  // Notify derived classes
-  OnFirstApply( parent );
+  DALI_ASSERT_ALWAYS( NULL == mTargetProxy && "Parent of ActiveConstraint already set" );
+
+  // No need to do anything, if the source objects are gone
+  if( mSources.size() == mSourceCount )
+  {
+    mTargetProxy = &parent;
+
+    ConnectConstraint();
+  }
 
   if ( applyTime.durationSeconds > 0.0f )
   {
@@ -125,45 +163,59 @@ void ActiveConstraintBase::FirstApply( ProxyObject& parent, TimePeriod applyTime
   }
 }
 
-void ActiveConstraintBase::BeginRemove()
+void ActiveConstraintBase::OnParentDestroyed()
 {
-  // Notify derived classes
-  OnBeginRemove();
-
-  // Remove gradually by animating weight down to zero
-  if ( mRemoveTime.durationSeconds > 0.0f )
-  {
-    // Stop baking behaviour from interfering with remove animation
-    if ( mSceneGraphConstraint )
-    {
-      // Immediately remove from scene-graph
-      SetRemoveActionMessage( mEventToUpdate, *mSceneGraphConstraint, Dali::Constraint::Discard );
-    }
-
-    // Interrupt ongoing apply-animations
-    if ( mApplyAnimation )
-    {
-      mApplyAnimation.Stop();
-    }
+  // Stop observing the remaining proxies
+  StopObservation();
 
-    // Reduce the weight to zero
-    mRemoveAnimation = Dali::Animation::New( mRemoveTime.delaySeconds + mRemoveTime.durationSeconds );
-    Dali::ActiveConstraint self( this );
-    mRemoveAnimation.AnimateTo( Property( self, Dali::ActiveConstraint::WEIGHT ), 0.0f, mAlphaFunction, mRemoveTime );
-    mRemoveAnimation.Play();
+  // Discard all proxy pointers
+  mTargetProxy = NULL;
+  mSources.clear();
+}
 
-    // Finish removal when animation ends
-    GetImplementation(mRemoveAnimation).SetFinishedCallback( &ActiveConstraintBase::OnRemoveFinished, this );
+void ActiveConstraintBase::OnParentSceneObjectAdded()
+{
+  if ( NULL == mSceneGraphConstraint &&
+       mTargetProxy )
+  {
+    ConnectConstraint();
   }
-  else
+}
+
+void ActiveConstraintBase::OnParentSceneObjectRemoved()
+{
+  if ( mSceneGraphConstraint )
   {
-    OnRemoveFinished( this );
+    // Notify base class that the scene-graph constraint is being removed
+    OnSceneObjectRemove();
+
+    // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
+    mSceneGraphConstraint = NULL;
   }
 }
 
-bool ActiveConstraintBase::IsRemoving()
+void ActiveConstraintBase::BeginRemove()
 {
-  return mRemoveAnimation;
+  // Stop observing the remaining proxies
+  StopObservation();
+
+  // Discard all proxy pointers
+  mSources.clear();
+
+  const SceneGraph::PropertyOwner* propertyOwner = mTargetProxy ? mTargetProxy->GetSceneObject() : NULL;
+
+  if ( propertyOwner &&
+       mSceneGraphConstraint )
+  {
+    // Notify base class that the scene-graph constraint is being removed
+    OnSceneObjectRemove();
+
+    // Remove from scene-graph
+    RemoveConstraintMessage( mEventToUpdate, *propertyOwner, *(mSceneGraphConstraint) );
+
+    // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
+    mSceneGraphConstraint = NULL;
+  }
 }
 
 ProxyObject* ActiveConstraintBase::GetParent()
@@ -233,16 +285,6 @@ bool ActiveConstraintBase::DoConnectSignal( BaseObject* object, ConnectionTracke
   return connected;
 }
 
-void ActiveConstraintBase::SetRemoveTime( TimePeriod removeTime )
-{
-  mRemoveTime = removeTime;
-}
-
-TimePeriod ActiveConstraintBase::GetRemoveTime() const
-{
-  return mRemoveTime;
-}
-
 void ActiveConstraintBase::SetAlphaFunction( AlphaFunction alphaFunc )
 {
   mAlphaFunction = alphaFunc;
@@ -263,9 +305,14 @@ ActiveConstraintBase::RemoveAction ActiveConstraintBase::GetRemoveAction() const
   return mRemoveAction;
 }
 
-bool ActiveConstraintBase::IsSceneObjectRemovable() const
+void ActiveConstraintBase::SetTag(const unsigned int tag)
+{
+  mTag = tag;
+}
+
+unsigned int ActiveConstraintBase::GetTag() const
 {
-  return true; // The constraint removed when target SceneGraph::PropertyOwner is destroyed
+  return mTag;
 }
 
 unsigned int ActiveConstraintBase::GetDefaultPropertyCount() const
@@ -283,7 +330,7 @@ void ActiveConstraintBase::GetDefaultPropertyIndices( Property::IndexContainer&
   }
 }
 
-const std::string& ActiveConstraintBase::GetDefaultPropertyName( Property::Index index ) const
+const char* ActiveConstraintBase::GetDefaultPropertyName( Property::Index index ) const
 {
   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
   {
@@ -291,9 +338,7 @@ const std::string& ActiveConstraintBase::GetDefaultPropertyName( Property::Index
   }
   else
   {
-    // index out of range..return empty string
-    static const std::string INVALID_PROPERTY_NAME;
-    return INVALID_PROPERTY_NAME;
+    return NULL;
   }
 }
 
@@ -302,7 +347,7 @@ Property::Index ActiveConstraintBase::GetDefaultPropertyIndex( const std::string
   Property::Index index = Property::INVALID_INDEX;
 
   // Only one name to compare with...
-  if ( name == DEFAULT_PROPERTY_NAMES[0] )
+  if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_NAMES[0] ) ) // dont want to convert rhs to string
   {
     index = 0;
   }
@@ -320,6 +365,11 @@ bool ActiveConstraintBase::IsDefaultPropertyAnimatable( Property::Index index )
   return true; // All default properties are currently animatable
 }
 
+bool ActiveConstraintBase::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  return true; // All default properties can currently be used as a constraint input
+}
+
 Property::Type ActiveConstraintBase::GetDefaultPropertyType( Property::Index index ) const
 {
   if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
@@ -414,50 +464,99 @@ const PropertyInputImpl* ActiveConstraintBase::GetSceneObjectInputProperty( Prop
   return &mSceneGraphConstraint->mWeight;
 }
 
-void ActiveConstraintBase::FirstApplyFinished( Object* object )
+void ActiveConstraintBase::SceneObjectAdded( ProxyObject& proxy )
 {
-  ActiveConstraintBase& self = dynamic_cast<ActiveConstraintBase&>( *object );
+  // Should not be getting callbacks when mSources has been cleared
+   DALI_ASSERT_DEBUG( mSources.size() == mSourceCount );
 
-  // This is necessary when the constraint was not added to scene-graph during the animation
-  self.SetWeight( Dali::ActiveConstraint::FINAL_WEIGHT );
+  if ( NULL == mSceneGraphConstraint &&
+       mTargetProxy )
+  {
+    ConnectConstraint();
+  }
+}
 
-  // The animation is no longer needed
-  GetImplementation(self.mApplyAnimation).SetFinishedCallback( NULL, NULL );
-  self.mApplyAnimation.Reset();
+void ActiveConstraintBase::SceneObjectRemoved( ProxyObject& proxy )
+{
+  // Notify base class that the scene-graph constraint is being removed
+  OnSceneObjectRemove();
 
-  // Chain "Finish" to "Applied" signal
+  if ( mSceneGraphConstraint )
+  {
+    // Preserve the previous weight
+    mOffstageWeight = mSceneGraphConstraint->GetWeight( mEventToUpdate.GetEventBufferIndex() );
+
+    const SceneGraph::PropertyOwner* propertyOwner = mTargetProxy ? mTargetProxy->GetSceneObject() : NULL;
+
+    if( propertyOwner )
+    {
+      // Remove from scene-graph
+      RemoveConstraintMessage( mEventToUpdate, *propertyOwner, *(mSceneGraphConstraint) );
+    }
+
+    // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
+    mSceneGraphConstraint = NULL;
+  }
+}
 
-  if ( !self.mAppliedSignal.Empty() )
+void ActiveConstraintBase::ProxyDestroyed( ProxyObject& proxy )
+{
+  // Remove proxy pointer from observation set
+  ProxyObjectIter iter = std::find( mObservedProxies.Begin(), mObservedProxies.End(), &proxy );
+  DALI_ASSERT_DEBUG( mObservedProxies.End() != iter );
+  mObservedProxies.Erase( iter );
+
+  // Stop observing the remaining proxies
+  StopObservation();
+
+  // Discard all proxy & scene-graph pointers
+  mSceneGraphConstraint = NULL;
+  mTargetProxy = NULL;
+  mSources.clear();
+}
+
+void ActiveConstraintBase::ObserveProxy( ProxyObject& proxy )
+{
+  ProxyObjectIter iter = std::find( mObservedProxies.Begin(), mObservedProxies.End(), &proxy );
+  if ( mObservedProxies.End() == iter )
   {
-    Dali::ActiveConstraint handle( &self );
+    proxy.AddObserver( *this );
+    mObservedProxies.PushBack( &proxy );
+  }
+}
 
-    self.mAppliedSignal.Emit( handle );
+void ActiveConstraintBase::StopObservation()
+{
+  const ProxyObjectIter end = mObservedProxies.End();
+  for( ProxyObjectIter iter = mObservedProxies.Begin(); iter != end; ++iter )
+  {
+    (*iter)->RemoveObserver( *this );
   }
 
-  // WARNING - this constraint may now have been deleted; don't do anything else here
+  mObservedProxies.Clear();
 }
 
-void ActiveConstraintBase::OnRemoveFinished( Object* object )
+void ActiveConstraintBase::FirstApplyFinished( Object* object )
 {
-  ActiveConstraintBase& self = dynamic_cast<ActiveConstraintBase&>( *object );
+  // trust the object is correct as its set in FirstApply (in this same file)
+  ActiveConstraintBase* self = static_cast<ActiveConstraintBase*>( object );
 
-  const SceneGraph::PropertyOwner* propertyOwner = self.mTargetProxy ? self.mTargetProxy->GetSceneObject() : NULL;
+  // This is necessary when the constraint was not added to scene-graph during the animation
+  self->SetWeight( Dali::ActiveConstraint::FINAL_WEIGHT );
 
-  if ( propertyOwner &&
-       self.mSceneGraphConstraint )
-  {
-    // Notify base class that the scene-graph constraint is being removed
-    self.OnSceneObjectRemove();
+  // The animation is no longer needed
+  GetImplementation(self->mApplyAnimation).SetFinishedCallback( NULL, NULL );
+  self->mApplyAnimation.Reset();
 
-    // Remove from scene-graph
-    RemoveConstraintMessage( self.mEventToUpdate, *propertyOwner, *(self.mSceneGraphConstraint) );
+  // Chain "Finish" to "Applied" signal
 
-    // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
-    self.mSceneGraphConstraint = NULL;
+  if ( !self->mAppliedSignal.Empty() )
+  {
+    Dali::ActiveConstraint handle( self );
+    self->mAppliedSignal.Emit( handle );
   }
 
-  // The animation is no longer needed
-  self.mRemoveAnimation.Reset();
+  // WARNING - this constraint may now have been deleted; don't do anything else here
 }
 
 } // namespace Internal