X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Flayouting%2Flayout-controller-impl.cpp;h=746e8e5509ea85c10c6035efda078e8e07efaa77;hp=f912810a317f322fd99a2be5cf347f8f5648d9c5;hb=118f87dfe57967bfed8ccdf9143a078eaef1b119;hpb=a9783f4a9684d20c8b20e34a34e15cae5a773787 diff --git a/dali-toolkit/internal/layouting/layout-controller-impl.cpp b/dali-toolkit/internal/layouting/layout-controller-impl.cpp index f912810..746e8e5 100644 --- a/dali-toolkit/internal/layouting/layout-controller-impl.cpp +++ b/dali-toolkit/internal/layouting/layout-controller-impl.cpp @@ -17,11 +17,13 @@ #include #include #include +#include #include #include #include #include #include +#include using namespace Dali; @@ -42,7 +44,9 @@ namespace Internal { LayoutController::LayoutController() -: mLayoutRequested(false) +: mLayoutRequested( false ), + mFocusChangedFunctor( *this ), + mSlotDelegate( this ) { } @@ -52,15 +56,52 @@ LayoutController::~LayoutController() void LayoutController::Initialize() { + mAnimation = Animation::New( 0.0f ); + + Dali::Toolkit::KeyInputFocusManager manager = Dali::Toolkit::KeyInputFocusManager::Get(); + manager.KeyInputFocusChangedSignal().Connect( mSlotDelegate.GetConnectionTracker(), mFocusChangedFunctor ); +} + +void LayoutController::FocusChangedFunctor::operator() ( Dali::Toolkit::Control gainingControl, Dali::Toolkit::Control lostControl ) +{ + Toolkit::LayoutItem layoutItem = Toolkit::DevelControl::GetLayout( gainingControl ); + if( layoutItem ) + { + Toolkit::Internal::LayoutItem& layoutItemImpl = GetImplementation( layoutItem ); + LayoutParent* layoutParent = layoutItemImpl.GetParent(); + if( layoutParent ) + { + LayoutGroup* layoutGroup = static_cast< LayoutGroup* >( layoutParent ); + layoutController.RequestLayout( dynamic_cast< Toolkit::Internal::LayoutItem& >( *layoutGroup ), Dali::Toolkit::LayoutTransitionData::ON_CHILD_FOCUS, gainingControl, lostControl ); + } + } } -void LayoutController::RequestLayout( LayoutItem& LayoutItem ) +void LayoutController::RequestLayout( LayoutItem& layoutItem, int layoutTransitionType, Actor gainedChild, Actor lostChild ) { - DALI_LOG_INFO( gLogFilter, Debug::Concise, "LayoutController::RequestLayout\n" ); + auto actor = Actor::DownCast( layoutItem.GetOwner() ); + if ( actor ) + { + DALI_LOG_INFO( gLogFilter, Debug::Concise, "LayoutController::RequestLayout owner[%s] layoutItem[%p] layoutTransitionType(%d)\n", actor.GetName().c_str(), &layoutItem, layoutTransitionType ); + } + else + { + DALI_LOG_INFO( gLogFilter, Debug::Concise, "LayoutController::RequestLayout layoutItem[%p] layoutAnimationType(%d)\n", &layoutItem, layoutTransitionType ); + } + mLayoutRequested = true; + if( layoutTransitionType != -1 ) + { + LayoutTransition layoutTransition = LayoutTransition( layoutItem, layoutTransitionType, gainedChild, lostChild ); + if( std::find( mLayoutTransitions.begin(), mLayoutTransitions.end(), layoutTransition ) == mLayoutTransitions.end() && layoutItem.GetTransitionData( layoutTransitionType ).Get() ) + { + DALI_LOG_INFO( gLogFilter, Debug::Concise, "LayoutController::RequestLayout Add transition layoutTransitionType(%d)\n", layoutTransitionType ); + mLayoutTransitions.push_back( layoutTransition ); + } + } // Go up the tree and mark all parents to relayout - LayoutParent* layoutParent = LayoutItem.GetParent(); + LayoutParent* layoutParent = layoutItem.GetParent(); if( layoutParent ) { LayoutGroup& layoutGroup = static_cast< LayoutGroup& >( *layoutParent ); @@ -74,11 +115,10 @@ void LayoutController::RequestLayout( LayoutItem& LayoutItem ) void LayoutController::Process() { // Perform the full process. + DALI_LOG_INFO( gLogFilter, Debug::Concise, "LayoutController::Process\n" ); if( mLayoutRequested ) { - mLayoutRequested = false; - // If window size has changed, expect stage to have already been updated Stage stage = Stage::GetCurrent(); auto stageWidth = stage.GetSize().width; @@ -87,12 +127,52 @@ void LayoutController::Process() MeasureSpec widthSpec( stageWidth, MeasureSpec::Mode::EXACTLY ); MeasureSpec heightSpec( stageHeight, MeasureSpec::Mode::EXACTLY ); + LayoutTransition layoutTransition; + LayoutPositionDataArray layoutPositionDataArray; + LayoutAnimatorArray layoutAnimatorArray; + LayoutDataArray layoutDataArray; + LayoutDataArray childrenLayoutDataArray; + + if ( mLayoutTransitions.size() ) + { + layoutTransition = mLayoutTransitions.front(); + mLayoutTransitions.pop_front(); + mLayoutRequested = ( mLayoutTransitions.size() != 0 ); + } + else + { + mLayoutRequested = false; + } + + LayoutData layoutData( layoutTransition, layoutPositionDataArray, layoutAnimatorArray, layoutDataArray, childrenLayoutDataArray ); + LayoutItem::Impl::sLayoutData = &layoutData; + + if( layoutTransition.layoutTransitionType != -1 ) + { + UpdateMeasureHierarchyForAnimation( layoutData ); + } + // Test how to perform a measure on each control. MeasureHierarchy( stage.GetRootLayer(), widthSpec, heightSpec ); LAYOUT_DEBUG_MEASURE_STATES( stage.GetRootLayer() ); + + if( layoutTransition.layoutTransitionType != -1 ) + { + RestoreActorsSpecs(); + } + + layoutAnimatorArray.clear(); + layoutDataArray.clear(); + childrenLayoutDataArray.clear(); + PerformLayout( stage.GetRootLayer(), 0, 0, stageWidth, stageHeight ); + PerformLayoutPositioning( layoutPositionDataArray, false ); + + PerformLayoutAnimation( layoutTransition, layoutPositionDataArray, layoutDataArray, layoutAnimatorArray ); + LayoutItem::Impl::sLayoutData = nullptr; + LAYOUT_DEBUG_AFTER_LAYOUT( stage.GetRootLayer() ); } } @@ -133,6 +213,93 @@ void LayoutController::MeasureHierarchy( Actor root, MeasureSpec widthSpec, Meas } } +void LayoutController::UpdateMeasureHierarchyForAnimation( LayoutData& layoutData ) +{ + LayoutTransition& layoutTransition = layoutData.layoutTransition; + Actor transitionOwner = Actor::DownCast( layoutTransition.layoutItem.Get()->GetOwner() ); + LayoutTransitionDataPtr layoutTransitionDataPtr = layoutTransition.layoutItem->GetTransitionData( layoutTransition.layoutTransitionType ); + + if( !layoutTransitionDataPtr->HasUpdateMeasuredSize() ) + { + return; + } + + layoutData.updateMeasuredSize = true; + layoutTransitionDataPtr->CollectLayoutDataElements( transitionOwner, layoutData ); + + UpdateMeasureHierarchyForAnimation( transitionOwner, layoutData ); + + for( auto layoutDataElement : layoutData.layoutDataArray ) + { + if( !layoutDataElement.updateMeasuredSize ) + { + continue; + } + + Actor actor = Actor::DownCast( layoutDataElement.handle ); + LayoutDataAnimator animator = layoutData.layoutAnimatorArray[ layoutDataElement.animatorIndex ]; + float width = actor.GetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION ); + float height = actor.GetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION ); + + if( layoutDataElement.AdjustMeasuredSize( width, height, animator.animatorType ) ) + { + mActorSizeSpecs.push_back( ActorSizeSpec( actor ) ); + actor.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, static_cast( width ) ); + actor.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, static_cast( height ) ); + } + } + + layoutData.updateMeasuredSize = false; +} + +void LayoutController::UpdateMeasureHierarchyForAnimation( Actor root, LayoutData& layoutData ) +{ + Toolkit::Control control = Toolkit::Control::DownCast( root ); + if( control ) + { + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutController::UpdateMeasureHierarchyForAnimation control:%s\n", control.GetName().c_str() ); + Internal::Control& controlImpl = GetImplementation( control ); + Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get( controlImpl ); + LayoutItemPtr layout = controlDataImpl.GetLayout(); + + if( layout ) + { + auto layoutGroup = Toolkit::LayoutGroup::DownCast( layout.Get() ); + if( layoutGroup ) + { + unsigned int childCount = layoutGroup.GetChildCount(); + for( unsigned int i=0; iLayout( left, top, right, bottom ); } } @@ -161,6 +327,164 @@ void LayoutController::PerformLayout( Actor root, int left, int top, int right, } } +void LayoutController::PerformLayoutPositioning( LayoutPositionDataArray& layoutPositionDataArray, bool all ) const +{ + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutController::PerformLayoutPositioning %d\n", (int)all ); + + for( auto layoutPositionData : layoutPositionDataArray ) + { + Actor actor = Actor::DownCast( layoutPositionData.handle ); + if( actor && ( !layoutPositionData.animated || all ) ) + { + if ( !layoutPositionData.animated ) + { + actor.SetPosition( layoutPositionData.left, layoutPositionData.top ); + actor.SetSize( layoutPositionData.right - layoutPositionData.left, layoutPositionData.bottom - layoutPositionData.top ); + } + else + { + actor.SetPosition( actor.GetCurrentPosition() ); + actor.SetSize( actor.GetCurrentSize() ); + } + } + } +} + +void LayoutController::PerformLayoutAnimation( LayoutTransition& layoutTransition, LayoutPositionDataArray& layoutPositionDataArray, LayoutDataArray& layoutDataArray, LayoutAnimatorArray& layoutAnimatorArray ) +{ + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutController::PerformLayoutAnimation\n" ); + Animation animation = Animation::New( 0 ); + bool isAnimatorAdded = false; + + if( layoutAnimatorArray.size() == 0 ) + { + layoutAnimatorArray.push_back( LayoutDataAnimator() ); + } + + for( auto layoutDataElement : layoutDataArray ) + { + if( layoutDataElement.animatorIndex >= 0 ) + { + Actor actor = Actor::DownCast( layoutDataElement.handle ); + if ( actor ) + { + LayoutDataAnimator animator = layoutAnimatorArray[ layoutDataElement.animatorIndex ]; + TimePeriod timePeriod = TimePeriod( 0, animation.GetDuration() ); + if( animator.timePeriod.durationSeconds >= 0 ) + { + timePeriod = animator.timePeriod; + } + + Property::Value value = layoutDataElement.targetValue; + // Capture calculated position and size values after layout if target values are not set. + // Other values are set to current actor ones. + if( value.GetType() == Property::NONE ) + { + if( layoutDataElement.positionDataIndex < 0) + { + auto result = std::find_if( layoutPositionDataArray.begin(), layoutPositionDataArray.end(), [&actor](const LayoutPositionData& iter) + { return iter.handle == actor; } ); + if( result == layoutPositionDataArray.end() ) + { + continue; + } + layoutDataElement.positionDataIndex = std::distance( layoutPositionDataArray.begin(), result ); + } + + LayoutPositionData& positionData = layoutPositionDataArray[ layoutDataElement.positionDataIndex ]; + // with updated measured size scale animation the measured size includes scale, so we need to fit in the centre of the measured rectangle + // the real size child so that the all scale related animations placed correctly + if( positionData.updateWithCurrentSize ) + { + Vector3 size = actor.GetCurrentSize(); + float dX = ( ( positionData.right - positionData.left ) - size.width ) / 2; + float dY = ( ( positionData.bottom - positionData.top ) - size.height ) / 2; + positionData.left += dX; + positionData.top += dY; + positionData.right -= dX; + positionData.bottom -= dY; + positionData.updateWithCurrentSize = false; + } + + switch ( layoutDataElement.propertyIndex ) + { + case Actor::Property::POSITION: + value = Vector3( positionData.left, positionData.top, 0.0f ); + break; + case Actor::Property::POSITION_X: + value = positionData.left; + break; + case Actor::Property::POSITION_Y: + value = positionData.top; + break; + case Actor::Property::SIZE: + value = Vector3( positionData.right - positionData.left, positionData.bottom - positionData.top, 0.0f ); + break; + case Actor::Property::SIZE_WIDTH: + value = positionData.right - positionData.left; + break; + case Actor::Property::SIZE_HEIGHT: + value = positionData.bottom - positionData.top; + break; + default: + value = actor.GetProperty( layoutDataElement.propertyIndex ); + } + } + + // Failed to get target value, just move to the next one + if( value.GetType() == Property::NONE ) + { + continue; + } + + // Set initial value + Property::Value initialValue = layoutDataElement.initialValue; + if( initialValue.GetType() != Property::NONE ) + { + actor.SetProperty( layoutDataElement.propertyIndex, initialValue ); + } + + // Create an animator for the property + switch( animator.animatorType ) + { + case Toolkit::LayoutTransitionData::Animator::ANIMATE_TO: + { + animation.AnimateTo( Property( actor, layoutDataElement.propertyIndex ), value, animator.alphaFunction, timePeriod ); + break; + } + case Toolkit::LayoutTransitionData::Animator::ANIMATE_BY: + { + animation.AnimateBy( Property( actor, layoutDataElement.propertyIndex ), value, animator.alphaFunction, timePeriod ); + break; + } + case Toolkit::LayoutTransitionData::Animator::ANIMATE_BETWEEN: + { + animation.AnimateBetween( Property( actor, layoutDataElement.propertyIndex ), animator.keyFrames, animator.alphaFunction, animator.interpolation ); + break; + } + case Toolkit::LayoutTransitionData::Animator::ANIMATE_PATH: + { + animation.Animate( actor, animator.path, animator.forward, animator.alphaFunction, timePeriod ); + break; + } + } + isAnimatorAdded = true; + } + } + } + + if( isAnimatorAdded ) + { + if( mAnimation.GetState() == Animation::PLAYING ) + { + mAnimation.SetCurrentProgress( 1.0f ); + } + mAnimation = animation; + mAnimationFinishedFunctors.push_back( AnimationFinishedFunctor( *this, layoutTransition, layoutPositionDataArray ) ); + mAnimation.FinishedSignal().Connect( mSlotDelegate.GetConnectionTracker(), mAnimationFinishedFunctors.back() ); + mAnimation.Play(); + } +} } // namespace Internal } // namespace Toolkit