X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fcontrols%2Fscrollable%2Fitem-view%2Fitem-view-impl.cpp;h=17299bcf0df6bcf8799835d88058e19c2a186631;hp=ffe368a19bc2733084f02d46a8699e073fe8d611;hb=f3da11c2818c6d17706fbb2417f21b602b3190f5;hpb=df5c192e17a7f8be8df32489111f5e6d09974680 diff --git a/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp b/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp index ffe368a..17299bc 100644 --- a/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp @@ -25,10 +25,10 @@ #include #include #include -#include +#include #include #include -#include +#include // INTERNAL INCLUDES #include @@ -46,30 +46,31 @@ namespace // Unnamed namespace DALI_TYPE_REGISTRATION_BEGIN( Toolkit::ItemView, Toolkit::Scrollable, NULL) -DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "layout-position", FLOAT, LAYOUT_POSITION) -DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "scroll-speed", FLOAT, SCROLL_SPEED) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "layoutPosition", FLOAT, LAYOUT_POSITION) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "scrollSpeed", FLOAT, SCROLL_SPEED) DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "overshoot", FLOAT, OVERSHOOT) -DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "scroll-direction", VECTOR2, SCROLL_DIRECTION) -DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "layout-orientation", INTEGER, LAYOUT_ORIENTATION) -DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "scroll-content-size", FLOAT, SCROLL_CONTENT_SIZE) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "scrollDirection", VECTOR2, SCROLL_DIRECTION) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "layoutOrientation", INTEGER, LAYOUT_ORIENTATION) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "scrollContentSize", FLOAT, SCROLL_CONTENT_SIZE) + +DALI_SIGNAL_REGISTRATION( Toolkit, ItemView, "layoutActivated", LAYOUT_ACTIVATED_SIGNAL ) DALI_TYPE_REGISTRATION_END() const float DEFAULT_MINIMUM_SWIPE_SPEED = 1.0f; const float DEFAULT_MINIMUM_SWIPE_DISTANCE = 3.0f; -const float DEFAULT_MOUSE_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION = 0.1f; +const float DEFAULT_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION = 0.1f; const float DEFAULT_MINIMUM_SWIPE_DURATION = 0.45f; const float DEFAULT_MAXIMUM_SWIPE_DURATION = 2.6f; const float DEFAULT_REFRESH_INTERVAL_LAYOUT_POSITIONS = 20.0f; // 1 updates per 20 items -const int MOUSE_WHEEL_EVENT_FINISHED_TIME_OUT = 500; // 0.5 second +const int WHEEL_EVENT_FINISHED_TIME_OUT = 500; // 0.5 second const float DEFAULT_ANCHORING_DURATION = 1.0f; // 1 second const float MILLISECONDS_PER_SECONDS = 1000.0f; -const Vector2 OVERSHOOT_BOUNCE_ACTOR_DEFAULT_SIZE( 720.0f, 42.0f ); const float OVERSHOOT_BOUNCE_ACTOR_RESIZE_THRESHOLD = 180.0f; const Vector4 OVERSHOOT_OVERLAY_NINE_PATCH_BORDER(0.0f, 0.0f, 1.0f, 12.0f); const float DEFAULT_KEYBOARD_FOCUS_SCROLL_DURATION = 0.2f; @@ -88,23 +89,33 @@ float CalculateScrollDistance(Vector2 panDistance, Toolkit::ItemLayout& layout) } // Overshoot overlay constraints -void OvershootOverlaySizeConstraint( Vector3& current, const PropertyInputContainer& inputs ) +struct OvershootOverlaySizeConstraint { - const Vector2& parentScrollDirection = inputs[0]->GetVector2(); - const Toolkit::ControlOrientation::Type& layoutOrientation = static_cast(inputs[1]->GetInteger()); - const Vector3& parentSize = inputs[2]->GetVector3(); - - if(Toolkit::IsVertical(layoutOrientation)) + OvershootOverlaySizeConstraint( float height ) + : mOvershootHeight( height ) { - current.width = fabsf(parentScrollDirection.y) > Math::MACHINE_EPSILON_1 ? parentSize.x : parentSize.y; } - else + + void operator()( Vector3& current, const PropertyInputContainer& inputs ) { - current.width = fabsf(parentScrollDirection.x) > Math::MACHINE_EPSILON_1 ? parentSize.y : parentSize.x; + const Vector2& parentScrollDirection = inputs[0]->GetVector2(); + const Toolkit::ControlOrientation::Type& layoutOrientation = static_cast(inputs[1]->GetInteger()); + const Vector3& parentSize = inputs[2]->GetVector3(); + + if(Toolkit::IsVertical(layoutOrientation)) + { + current.width = fabsf(parentScrollDirection.y) > Math::MACHINE_EPSILON_1 ? parentSize.x : parentSize.y; + } + else + { + current.width = fabsf(parentScrollDirection.x) > Math::MACHINE_EPSILON_1 ? parentSize.y : parentSize.x; + } + + current.height = ( current.width > OVERSHOOT_BOUNCE_ACTOR_RESIZE_THRESHOLD ) ? mOvershootHeight : mOvershootHeight*0.5f; } - current.height = ( current.width > OVERSHOOT_BOUNCE_ACTOR_RESIZE_THRESHOLD ) ? OVERSHOOT_BOUNCE_ACTOR_DEFAULT_SIZE.height : OVERSHOOT_BOUNCE_ACTOR_DEFAULT_SIZE.height*0.5f; -} + float mOvershootHeight; +}; void OvershootOverlayRotationConstraint( Quaternion& current, const PropertyInputContainer& inputs ) { @@ -276,28 +287,29 @@ Dali::Toolkit::ItemView ItemView::New(ItemFactory& factory) } ItemView::ItemView(ItemFactory& factory) -: Scrollable( ControlBehaviour( DISABLE_SIZE_NEGOTIATION | REQUIRES_MOUSE_WHEEL_EVENTS | REQUIRES_KEYBOARD_NAVIGATION_SUPPORT ) ), +: Scrollable( ControlBehaviour( DISABLE_SIZE_NEGOTIATION | REQUIRES_WHEEL_EVENTS | REQUIRES_KEYBOARD_NAVIGATION_SUPPORT ) ), mItemFactory(factory), + mItemsParentOrigin(ParentOrigin::CENTER), + mItemsAnchorPoint(AnchorPoint::CENTER), + mTotalPanDisplacement(Vector2::ZERO), mActiveLayout(NULL), - mAnimatingOvershootOn(false), - mAnimateOvershootOff(false), - mAnchoringEnabled(false), mAnchoringDuration(DEFAULT_ANCHORING_DURATION), mRefreshIntervalLayoutPositions(0.0f), - mRefreshOrderHint(true/*Refresh item 0 first*/), mMinimumSwipeSpeed(DEFAULT_MINIMUM_SWIPE_SPEED), mMinimumSwipeDistance(DEFAULT_MINIMUM_SWIPE_DISTANCE), - mMouseWheelScrollDistanceStep(0.0f), + mWheelScrollDistanceStep(0.0f), mScrollDistance(0.0f), mScrollSpeed(0.0f), - mTotalPanDisplacement(Vector2::ZERO), mScrollOvershoot(0.0f), - mIsFlicking(false), mGestureState(Gesture::Clear), + mAnimatingOvershootOn(false), + mAnimateOvershootOff(false), + mAnchoringEnabled(false), + mRefreshOrderHint(true/*Refresh item 0 first*/), + mIsFlicking(false), mAddingItems(false), mRefreshEnabled(true), - mItemsParentOrigin( ParentOrigin::CENTER), - mItemsAnchorPoint( AnchorPoint::CENTER) + mInAnimation(false) { } @@ -305,15 +317,13 @@ void ItemView::OnInitialize() { Actor self = Self(); - SetOvershootEnabled(true); - Vector2 stageSize = Stage::GetCurrent().GetSize(); - mMouseWheelScrollDistanceStep = stageSize.y * DEFAULT_MOUSE_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION; + mWheelScrollDistanceStep = stageSize.y * DEFAULT_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION; EnableGestureDetection(Gesture::Type(Gesture::Pan)); - mMouseWheelEventFinishedTimer = Timer::New( MOUSE_WHEEL_EVENT_FINISHED_TIME_OUT ); - mMouseWheelEventFinishedTimer.TickSignal().Connect( this, &ItemView::OnMouseWheelEventFinished ); + mWheelEventFinishedTimer = Timer::New( WHEEL_EVENT_FINISHED_TIME_OUT ); + mWheelEventFinishedTimer.TickSignal().Connect( this, &ItemView::OnWheelEventFinished ); SetRefreshInterval(DEFAULT_REFRESH_INTERVAL_LAYOUT_POSITIONS); } @@ -422,6 +432,11 @@ void ItemView::ActivateLayout(unsigned int layoutIndex, const Vector3& targetSiz mScrollAnimation.FinishedSignal().Connect(this, &ItemView::OnLayoutActivationScrollFinished); mScrollAnimation.Play(); } + else + { + // Emit the layout activated signal + mLayoutActivatedSignal.Emit(); + } AnimateScrollOvershoot(0.0f); mScrollOvershoot = 0.0f; @@ -450,11 +465,14 @@ void ItemView::DeactivateCurrentLayout() void ItemView::OnRefreshNotification(PropertyNotification& source) { - if(mRefreshEnabled || mScrollAnimation) + // Cancel scroll animation to prevent any fighting of setting the scroll position property by scroll bar during fast scroll. + if(!mRefreshEnabled && mScrollAnimation) { - // Only refresh the cache during normal scrolling - DoRefresh(GetCurrentLayoutPosition(0), true); + RemoveAnimation(mScrollAnimation); } + + // Only cache extra items when it is not a fast scroll + DoRefresh(GetCurrentLayoutPosition(0), mRefreshEnabled || mScrollAnimation); } void ItemView::Refresh() @@ -500,14 +518,14 @@ float ItemView::GetMinimumSwipeDistance() const return mMinimumSwipeDistance; } -void ItemView::SetMouseWheelScrollDistanceStep(float step) +void ItemView::SetWheelScrollDistanceStep(float step) { - mMouseWheelScrollDistanceStep = step; + mWheelScrollDistanceStep = step; } -float ItemView::GetMouseWheelScrollDistanceStep() const +float ItemView::GetWheelScrollDistanceStep() const { - return mMouseWheelScrollDistanceStep; + return mWheelScrollDistanceStep; } void ItemView::SetAnchoring(bool enabled) @@ -950,7 +968,6 @@ void ItemView::OnChildAdd(Actor& child) Toolkit::Scrollable::Property::SCROLL_POSITION_MIN_Y, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX_Y, Toolkit::ItemView::Property::SCROLL_CONTENT_SIZE); - scrollBar.ScrollPositionIntervalReachedSignal().Connect( this, &ItemView::OnScrollPositionChanged ); } } } @@ -986,14 +1003,14 @@ bool ItemView::OnTouchEvent(const TouchEvent& event) return true; // consume since we're potentially scrolling } -bool ItemView::OnMouseWheelEvent(const MouseWheelEvent& event) +bool ItemView::OnWheelEvent(const WheelEvent& event) { - // Respond the mouse wheel event to scroll + // Respond the wheel event to scroll if (mActiveLayout) { Actor self = Self(); const Vector3 layoutSize = Self().GetCurrentSize(); - float layoutPositionDelta = GetCurrentLayoutPosition(0) - (event.z * mMouseWheelScrollDistanceStep * mActiveLayout->GetScrollSpeedFactor()); + float layoutPositionDelta = GetCurrentLayoutPosition(0) - (event.z * mWheelScrollDistanceStep * mActiveLayout->GetScrollSpeedFactor()); float firstItemScrollPosition = ClampFirstItemPosition(layoutPositionDelta, layoutSize, *mActiveLayout); self.SetProperty(Toolkit::ItemView::Property::LAYOUT_POSITION, firstItemScrollPosition ); @@ -1002,23 +1019,23 @@ bool ItemView::OnMouseWheelEvent(const MouseWheelEvent& event) mRefreshEnabled = true; } - if (mMouseWheelEventFinishedTimer.IsRunning()) + if (mWheelEventFinishedTimer.IsRunning()) { - mMouseWheelEventFinishedTimer.Stop(); + mWheelEventFinishedTimer.Stop(); } - mMouseWheelEventFinishedTimer.Start(); + mWheelEventFinishedTimer.Start(); return true; } -bool ItemView::OnMouseWheelEventFinished() +bool ItemView::OnWheelEventFinished() { if (mActiveLayout) { RemoveAnimation(mScrollAnimation); - // No more mouse wheel events coming. Do the anchoring if enabled. + // No more wheel events coming. Do the anchoring if enabled. mScrollAnimation = DoAnchoring(); if (mScrollAnimation) { @@ -1168,13 +1185,39 @@ void ItemView::OnPan( const PanGesture& gesture ) self.SetProperty(Toolkit::ItemView::Property::LAYOUT_POSITION, firstItemScrollPosition ); - if( (firstItemScrollPosition >= 0.0f && currentOvershoot < 1.0f) || (firstItemScrollPosition >= mActiveLayout->GetMinimumLayoutPosition(mItemFactory.GetNumberOfItems(), layoutSize) && currentOvershoot > -1.0f) ) + if( ( firstItemScrollPosition >= 0.0f && + currentOvershoot < 1.0f ) || + ( firstItemScrollPosition <= mActiveLayout->GetMinimumLayoutPosition(mItemFactory.GetNumberOfItems(), layoutSize) && + currentOvershoot > -1.0f ) ) { mTotalPanDisplacement += gesture.displacement; } mScrollOvershoot = CalculateScrollOvershoot(); - self.SetProperty( Toolkit::ItemView::Property::OVERSHOOT, mScrollOvershoot ); + + // If the view is moved in a direction against the overshoot indicator, then the indicator should be animated off. + // First make sure we are not in an animation, otherwise a previously started + // off-animation will be overwritten as the user continues scrolling. + if( !mInAnimation ) + { + // Check if the movement is against the current overshoot amount (if we are currently displaying the indicator). + if( ( ( mScrollOvershoot > Math::MACHINE_EPSILON_0 ) && ( mScrollDistance < -Math::MACHINE_EPSILON_0 ) ) || + ( ( mScrollOvershoot < Math::MACHINE_EPSILON_0 ) && ( mScrollDistance > Math::MACHINE_EPSILON_0 ) ) ) + { + // The user has moved against the indicator direction. + // First, we reset the total displacement. This means the overshoot amount will become zero the next frame, + // and if the user starts dragging in the overshoot direction again, the indicator will appear once more. + mTotalPanDisplacement = Vector2::ZERO; + // Animate the overshoot indicator off. + AnimateScrollOvershoot( 0.0f, false ); + } + else + { + // Only set the property directly if we are not animating the overshoot away, + // as otherwise this will overwrite the animation generated value. + self.SetProperty( Toolkit::ItemView::Property::OVERSHOOT, mScrollOvershoot ); + } + } } break; @@ -1201,7 +1244,7 @@ bool ItemView::OnAccessibilityPan(PanGesture gesture) return true; } -Actor ItemView::GetNextKeyboardFocusableActor(Actor actor, Toolkit::Control::KeyboardFocusNavigationDirection direction, bool loopEnabled) +Actor ItemView::GetNextKeyboardFocusableActor(Actor actor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled) { Actor nextFocusActor; if(mActiveLayout) @@ -1298,6 +1341,9 @@ void ItemView::OnLayoutActivationScrollFinished(Animation& source) RemoveAnimation(mScrollAnimation); mRefreshEnabled = true; DoRefresh(GetCurrentLayoutPosition(0), true); + + // Emit the layout activated signal + mLayoutActivatedSignal.Emit(); } void ItemView::OnOvershootOnFinished(Animation& animation) @@ -1309,6 +1355,7 @@ void ItemView::OnOvershootOnFinished(Animation& animation) { AnimateScrollOvershoot(0.0f); } + mInAnimation = false; } void ItemView::ScrollToItem(unsigned int itemId, float durationSeconds) @@ -1415,6 +1462,7 @@ Vector2 ItemView::GetCurrentScrollPosition() const void ItemView::AddOverlay(Actor actor) { + actor.SetDrawMode( DrawMode::OVERLAY_2D ); Self().Add(actor); } @@ -1467,16 +1515,16 @@ void ItemView::EnableScrollOvershoot( bool enable ) mOvershootOverlay.SetColor(mOvershootEffectColor); mOvershootOverlay.SetParentOrigin(ParentOrigin::TOP_LEFT); mOvershootOverlay.SetAnchorPoint(AnchorPoint::TOP_LEFT); - mOvershootOverlay.SetDrawMode(DrawMode::OVERLAY); + mOvershootOverlay.SetDrawMode( DrawMode::OVERLAY_2D ); self.Add(mOvershootOverlay); - Constraint constraint = Constraint::New( mOvershootOverlay, Actor::Property::SIZE, OvershootOverlaySizeConstraint ); + Constraint constraint = Constraint::New( mOvershootOverlay, Actor::Property::SIZE, OvershootOverlaySizeConstraint(mOvershootSize.height) ); constraint.AddSource( ParentSource( Toolkit::ItemView::Property::SCROLL_DIRECTION ) ); constraint.AddSource( ParentSource( Toolkit::ItemView::Property::LAYOUT_ORIENTATION ) ); constraint.AddSource( ParentSource( Actor::Property::SIZE ) ); constraint.Apply(); - mOvershootOverlay.SetSize(OVERSHOOT_BOUNCE_ACTOR_DEFAULT_SIZE.width, OVERSHOOT_BOUNCE_ACTOR_DEFAULT_SIZE.height); + mOvershootOverlay.SetSize(mOvershootSize.width, mOvershootSize.height); constraint = Constraint::New( mOvershootOverlay, Actor::Property::ORIENTATION, OvershootOverlayRotationConstraint ); constraint.AddSource( ParentSource( Toolkit::ItemView::Property::SCROLL_DIRECTION ) ); @@ -1554,13 +1602,14 @@ void ItemView::AnimateScrollOvershoot(float overshootAmount, bool animateBack) duration = mOvershootOverlay.GetCurrentSize().height * (animatingOn ? (1.0f - fabsf(currentOvershoot)) : fabsf(currentOvershoot)) / mOvershootAnimationSpeed; } + // Mark the animation as in progress to prevent manual property sets overwriting it. + mInAnimation = true; + mAnimatingOvershootOn = animatingOn; RemoveAnimation(mScrollOvershootAnimation); mScrollOvershootAnimation = Animation::New(duration); mScrollOvershootAnimation.FinishedSignal().Connect(this, &ItemView::OnOvershootOnFinished); mScrollOvershootAnimation.AnimateTo( Property(self, Toolkit::ItemView::Property::OVERSHOOT), overshootAmount, TimePeriod(0.0f, duration) ); mScrollOvershootAnimation.Play(); - - mAnimatingOvershootOn = animatingOn; } else { @@ -1616,13 +1665,24 @@ void ItemView::GetItemsRange(ItemRange& range) } } -void ItemView::OnScrollPositionChanged( float position ) +bool ItemView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) { - // Cancel scroll animation to prevent any fighting of setting the scroll position property. - RemoveAnimation(mScrollAnimation); + Dali::BaseHandle handle( object ); + + bool connected( true ); + Toolkit::ItemView itemView = Toolkit::ItemView::DownCast( handle ); + + if( 0 == strcmp( signalName.c_str(), LAYOUT_ACTIVATED_SIGNAL ) ) + { + itemView.LayoutActivatedSignal().Connect( tracker, functor ); + } + else + { + // signalName does not match any signal + connected = false; + } - // Refresh the cache immediately when the scroll position is changed. - DoRefresh(position, false); // No need to cache extra items. + return connected; } } // namespace Internal