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=19d737379364997aac996414629dd94f89de9f7b;hp=c8bb12fc205ea4ab16fa327717a1f1b46320ed15;hb=f546dd5d83a968e573f8f053a01ce43df32c71a0;hpb=c0c5757663eb6ebbed43e0a3de8933f6b90a0c6a 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 c8bb12f..19d7373 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 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. @@ -21,22 +21,28 @@ // EXTERNAL INCLUDES #include // for strcmp #include +#include + #include #include -#include -#include +#include #include -#include +#include #include #include +#include // INTERNAL INCLUDES -#include +#include #include +#include +#include +#include +#include +#include #include using std::string; -using std::set; using namespace Dali; namespace // Unnamed namespace @@ -60,6 +66,8 @@ 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; +const unsigned int OVERSHOOT_SIZE_CONSTRAINT_TAG(42); + /** * Local helper to convert pan distance (in actor coordinates) to the layout-specific scrolling direction */ @@ -250,6 +258,8 @@ DALI_PROPERTY_REGISTRATION( Toolkit, ItemView, "minimumSwipeDistance", FLO DALI_PROPERTY_REGISTRATION( Toolkit, ItemView, "wheelScrollDistanceStep", FLOAT, WHEEL_SCROLL_DISTANCE_STEP ) DALI_PROPERTY_REGISTRATION( Toolkit, ItemView, "snapToItemEnabled", BOOLEAN, SNAP_TO_ITEM_ENABLED ) DALI_PROPERTY_REGISTRATION( Toolkit, ItemView, "refreshInterval", FLOAT, REFRESH_INTERVAL ) +DALI_PROPERTY_REGISTRATION( Toolkit, ItemView, "layout", ARRAY, LAYOUT ) + DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "layoutPosition", FLOAT, LAYOUT_POSITION) DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "scrollSpeed", FLOAT, SCROLL_SPEED) @@ -267,17 +277,42 @@ DALI_ACTION_REGISTRATION( Toolkit, ItemView, "disableRefresh", DALI_TYPE_REGISTRATION_END() -bool FindById( const ItemContainer& items, ItemId id ) +const ItemIter FindItemById( ItemContainer& items, ItemId id ) { - for( ConstItemIter iter = items.begin(); items.end() != iter; ++iter ) + for( ItemIter iter = items.begin(); items.end() != iter; ++iter ) { if( iter->first == id ) { - return true; + return iter; } } - return false; + return items.end(); +} + +void InsertToItemContainer( ItemContainer& items, Item item ) +{ + if( items.end() == FindItemById( items, item.first ) ) + { + ItemIter iterToInsert = std::lower_bound( items.begin(), items.end(), item ); + items.insert( iterToInsert, item ); + } +} + + +/** + * Helper to apply size constraint to mOvershootOverlay + * @param[in] overshootOverlay The overshootOverlay actor + * @param[in] The required height + */ +void ApplyOvershootSizeConstraint( Actor overshootOverlay, float height ) +{ + Constraint constraint = Constraint::New( overshootOverlay, Actor::Property::SIZE, OvershootOverlaySizeConstraint( height ) ); + constraint.AddSource( ParentSource( Dali::Toolkit::ItemView::Property::SCROLL_DIRECTION ) ); + constraint.AddSource( ParentSource( Dali::Toolkit::ItemView::Property::LAYOUT_ORIENTATION ) ); + constraint.AddSource( ParentSource( Dali::Actor::Property::SIZE ) ); + constraint.SetTag( OVERSHOOT_SIZE_CONSTRAINT_TAG ); + constraint.Apply(); } } // unnamed namespace @@ -298,7 +333,7 @@ Dali::Toolkit::ItemView ItemView::New(ItemFactory& factory) } ItemView::ItemView(ItemFactory& factory) -: Scrollable( ControlBehaviour( DISABLE_SIZE_NEGOTIATION | REQUIRES_WHEEL_EVENTS | REQUIRES_KEYBOARD_NAVIGATION_SUPPORT ) ), +: Scrollable( ControlBehaviour( DISABLE_SIZE_NEGOTIATION | DISABLE_STYLE_CHANGE_SIGNALS | REQUIRES_KEYBOARD_NAVIGATION_SUPPORT ) ), mItemFactory(factory), mItemsParentOrigin(ParentOrigin::CENTER), mItemsAnchorPoint(AnchorPoint::CENTER), @@ -312,7 +347,7 @@ ItemView::ItemView(ItemFactory& factory) mScrollDistance(0.0f), mScrollSpeed(0.0f), mScrollOvershoot(0.0f), - mGestureState(Gesture::Clear), + mGestureState(GestureState::CLEAR), mAnimatingOvershootOn(false), mAnimateOvershootOff(false), mAnchoringEnabled(false), @@ -327,18 +362,23 @@ ItemView::ItemView(ItemFactory& factory) void ItemView::OnInitialize() { + Scrollable::OnInitialize(); + Actor self = Self(); Vector2 stageSize = Stage::GetCurrent().GetSize(); mWheelScrollDistanceStep = stageSize.y * DEFAULT_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION; - self.TouchSignal().Connect( this, &ItemView::OnTouch ); - EnableGestureDetection(Gesture::Type(Gesture::Pan)); + self.TouchedSignal().Connect( this, &ItemView::OnTouch ); + EnableGestureDetection(GestureType::Value(GestureType::PAN)); mWheelEventFinishedTimer = Timer::New( WHEEL_EVENT_FINISHED_TIME_OUT ); mWheelEventFinishedTimer.TickSignal().Connect( this, &ItemView::OnWheelEventFinished ); SetRefreshInterval(DEFAULT_REFRESH_INTERVAL_LAYOUT_POSITIONS); + + // Connect wheel event + self.WheelEventSignal().Connect( this, &ItemView::OnWheelEvent ); } ItemView::~ItemView() @@ -379,7 +419,7 @@ ItemLayoutPtr ItemView::GetActiveLayout() const float ItemView::GetCurrentLayoutPosition(unsigned int itemId) const { - return Self().GetProperty( Toolkit::ItemView::Property::LAYOUT_POSITION ) + static_cast( itemId ); + return Self().GetCurrentProperty< float >( Toolkit::ItemView::Property::LAYOUT_POSITION ) + static_cast( itemId ); } void ItemView::ActivateLayout(unsigned int layoutIndex, const Vector3& targetSize, float durationSeconds) @@ -391,7 +431,7 @@ void ItemView::ActivateLayout(unsigned int layoutIndex, const Vector3& targetSiz Actor self = Self(); // The ItemView size should match the active layout size - self.SetSize(targetSize); + self.SetProperty( Actor::Property::SIZE, targetSize); mActiveLayoutTargetSize = targetSize; // Switch to the new layout @@ -399,7 +439,7 @@ void ItemView::ActivateLayout(unsigned int layoutIndex, const Vector3& targetSiz // Move the items to the new layout positions... - for (ConstItemPoolIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter) + for (ConstItemIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter) { unsigned int itemId = iter->first; Actor actor = iter->second; @@ -407,11 +447,11 @@ void ItemView::ActivateLayout(unsigned int layoutIndex, const Vector3& targetSiz // Remove constraints from previous layout actor.RemoveConstraints(); + mActiveLayout->ApplyConstraints(actor, itemId, targetSize, Self() ); + Vector3 size; mActiveLayout->GetItemSize( itemId, targetSize, size ); - actor.SetSize( size.GetVectorXY() ); - - mActiveLayout->ApplyConstraints(actor, itemId, targetSize, Self() ); + actor.SetProperty( Actor::Property::SIZE, size.GetVectorXY() ); } // Refresh the new layout @@ -466,7 +506,7 @@ void ItemView::DeactivateCurrentLayout() { if (mActiveLayout) { - for (ConstItemPoolIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter) + for (ConstItemIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter) { Actor actor = iter->second; actor.RemoveConstraints(); @@ -493,7 +533,7 @@ void ItemView::OnRefreshNotification(PropertyNotification& source) void ItemView::Refresh() { - for (ItemPoolIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter ) + for (ConstItemIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter ) { ReleaseActor( iter->first, iter->second ); } @@ -508,7 +548,7 @@ void ItemView::DoRefresh(float currentLayoutPosition, bool cacheExtra) { ItemRange range = GetItemRange(*mActiveLayout, mActiveLayoutTargetSize, currentLayoutPosition, cacheExtra/*reserve extra*/); RemoveActorsOutsideRange( range ); - AddActorsWithinRange( range, Self().GetCurrentSize() ); + AddActorsWithinRange( range, Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE ) ); mScrollUpdatedSignal.Emit( Vector2(0.0f, currentLayoutPosition) ); } @@ -594,10 +634,13 @@ Actor ItemView::GetItem(unsigned int itemId) const { Actor actor; - ConstItemPoolIter iter = mItemPool.find( itemId ); - if( iter != mItemPool.end() ) + for ( ConstItemIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter ) { - actor = iter->second; + if( iter->first == itemId ) + { + actor = iter->second; + break; + } } return actor; @@ -607,7 +650,7 @@ unsigned int ItemView::GetItemId( Actor actor ) const { unsigned int itemId( 0 ); - for ( ConstItemPoolIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter ) + for ( ConstItemIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter ) { if( iter->second == actor ) { @@ -622,12 +665,12 @@ unsigned int ItemView::GetItemId( Actor actor ) const void ItemView::InsertItem( Item newItem, float durationSeconds ) { mAddingItems = true; - Vector3 layoutSize = Self().GetCurrentSize(); + Vector3 layoutSize = Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE ); Actor displacedActor; - ItemPoolIter afterDisplacedIter = mItemPool.end(); + ItemIter afterDisplacedIter = mItemPool.end(); - ItemPoolIter foundIter = mItemPool.find( newItem.first ); + ItemIter foundIter = FindItemById( mItemPool, newItem.first ); if( mItemPool.end() != foundIter ) { SetupActor( newItem, layoutSize ); @@ -641,12 +684,12 @@ void ItemView::InsertItem( Item newItem, float durationSeconds ) else { // Inserting before the existing item range? - ItemPoolIter iter = mItemPool.begin(); + ItemIter iter = mItemPool.begin(); if( iter != mItemPool.end() && iter->first > newItem.first ) { displacedActor = iter->second; - mItemPool.erase( iter++ ); // iter is still valid after the erase + iter = mItemPool.erase( iter ); // iter is still valid after the erase afterDisplacedIter = iter; } @@ -655,7 +698,7 @@ void ItemView::InsertItem( Item newItem, float durationSeconds ) if( displacedActor ) { // Move the existing actors to make room - for( ItemPoolIter iter = afterDisplacedIter; mItemPool.end() != iter; ++iter ) + for( ItemIter iter = afterDisplacedIter; mItemPool.end() != iter; ++iter ) { Actor temp = iter->second; iter->second = displacedActor; @@ -666,12 +709,12 @@ void ItemView::InsertItem( Item newItem, float durationSeconds ) } // Create last item - ItemPool::reverse_iterator lastIter = mItemPool.rbegin(); + ItemContainer::reverse_iterator lastIter = mItemPool.rbegin(); if ( lastIter != mItemPool.rend() ) { ItemId lastId = lastIter->first; Item lastItem( lastId + 1, displacedActor ); - mItemPool.insert( lastItem ); + InsertToItemContainer( mItemPool, lastItem ); lastItem.second.RemoveConstraints(); mActiveLayout->ApplyConstraints( lastItem.second, lastItem.first, layoutSize, Self() ); @@ -686,27 +729,24 @@ void ItemView::InsertItem( Item newItem, float durationSeconds ) void ItemView::InsertItems( const ItemContainer& newItems, float durationSeconds ) { mAddingItems = true; - Vector3 layoutSize = Self().GetCurrentSize(); + Vector3 layoutSize = Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE ); // Insert from lowest id to highest - std::set sortedItems; - for( ConstItemIter iter = newItems.begin(); newItems.end() != iter; ++iter ) - { - sortedItems.insert( *iter ); - } + ItemContainer sortedItems(newItems); + std::sort( sortedItems.begin(), sortedItems.end() ); - for( std::set::iterator iter = sortedItems.begin(); sortedItems.end() != iter; ++iter ) + for( ItemIter iter = sortedItems.begin(); sortedItems.end() != iter; ++iter ) { Self().Add( iter->second ); - ItemPoolIter foundIter = mItemPool.find( iter->first ); + ItemIter foundIter = FindItemById( mItemPool, iter->first ); if( mItemPool.end() != foundIter ) { Actor moveMe = foundIter->second; foundIter->second = iter->second; // Move the existing actors to make room - for( ItemPoolIter iter = ++foundIter; mItemPool.end() != iter; ++iter ) + for( ItemIter iter = ++foundIter; mItemPool.end() != iter; ++iter ) { Actor temp = iter->second; iter->second = moveMe; @@ -716,19 +756,19 @@ void ItemView::InsertItems( const ItemContainer& newItems, float durationSeconds // Create last item ItemId lastId = mItemPool.rbegin()->first; Item lastItem( lastId + 1, moveMe ); - mItemPool.insert( lastItem ); + InsertToItemContainer( mItemPool, lastItem ); } else { - mItemPool.insert( *iter ); + InsertToItemContainer( mItemPool, *iter ); } } // Relayout everything - for (ItemPoolIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter) + for (ItemIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter) { // If newly inserted - if( FindById( newItems, iter->first ) ) + if( std::binary_search( sortedItems.begin(), sortedItems.end(), *iter ) ) { SetupActor( *iter, layoutSize ); } @@ -760,13 +800,10 @@ void ItemView::RemoveItems( const ItemIdContainer& itemIds, float durationSecond bool actorsReordered( false ); // Remove from highest id to lowest - set sortedItems; - for( ConstItemIdIter iter = itemIds.begin(); itemIds.end() != iter; ++iter ) - { - sortedItems.insert( *iter ); - } + ItemIdContainer sortedItems(itemIds); + std::sort( sortedItems.begin(), sortedItems.end() ); - for( set::reverse_iterator iter = sortedItems.rbegin(); sortedItems.rend() != iter; ++iter ) + for( ItemIdContainer::reverse_iterator iter = sortedItems.rbegin(); sortedItems.rend() != iter; ++iter ) { if( RemoveActor( *iter ) ) { @@ -786,7 +823,7 @@ bool ItemView::RemoveActor(unsigned int itemId) { bool reordered( false ); - ItemPoolIter removeIter = mItemPool.find( itemId ); + ItemIter removeIter = FindItemById( mItemPool, itemId ); if( removeIter != mItemPool.end() ) { ReleaseActor(itemId, removeIter->second); @@ -794,12 +831,12 @@ bool ItemView::RemoveActor(unsigned int itemId) else { // Removing before the existing item range? - ItemPoolIter iter = mItemPool.begin(); + ItemIter iter = mItemPool.begin(); if( iter != mItemPool.end() && iter->first > itemId ) { // In order to decrement the first visible item ID - mItemPool.insert( Item(iter->first - 1, Actor()) ); + InsertToItemContainer( mItemPool, Item(iter->first - 1, Actor()) ); removeIter = mItemPool.begin(); } @@ -815,11 +852,11 @@ bool ItemView::RemoveActor(unsigned int itemId) // ID 2 - ActorB ID 2 - ActorC (previously ID 3) // ID 3 - ActorC ID 3 - ActorB (previously ID 4) // ID 4 - ActorD - for (ItemPoolIter iter = removeIter; iter != mItemPool.end(); ++iter) + for (ItemIter iter = removeIter; iter != mItemPool.end(); ++iter) { if( iter->first < mItemPool.rbegin()->first ) { - iter->second = mItemPool[ iter->first + 1 ]; + iter->second = ( iter + 1 )->second; } else { @@ -835,12 +872,12 @@ bool ItemView::RemoveActor(unsigned int itemId) void ItemView::ReplaceItem( Item replacementItem, float durationSeconds ) { mAddingItems = true; - Vector3 layoutSize = Self().GetCurrentSize(); + Vector3 layoutSize = Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE ); SetupActor( replacementItem, layoutSize ); Self().Add( replacementItem.second ); - const ItemPoolIter iter = mItemPool.find( replacementItem.first ); + const ItemIter iter = FindItemById( mItemPool, replacementItem.first ); if( mItemPool.end() != iter ) { ReleaseActor(iter->first, iter->second); @@ -848,7 +885,7 @@ void ItemView::ReplaceItem( Item replacementItem, float durationSeconds ) } else { - mItemPool.insert( replacementItem ); + InsertToItemContainer( mItemPool, replacementItem ); } CalculateDomainSize( layoutSize ); @@ -867,7 +904,7 @@ void ItemView::ReplaceItems( const ItemContainer& replacementItems, float durati void ItemView::RemoveActorsOutsideRange( ItemRange range ) { // Remove unwanted actors from the ItemView & ItemPool - for (ItemPoolIter iter = mItemPool.begin(); iter != mItemPool.end(); ) + for (ItemIter iter = mItemPool.begin(); iter != mItemPool.end(); ) { unsigned int current = iter->first; @@ -875,7 +912,7 @@ void ItemView::RemoveActorsOutsideRange( ItemRange range ) { ReleaseActor(iter->first, iter->second); - mItemPool.erase( iter++ ); // erase invalidates the return value of post-increment; iter remains valid + iter = mItemPool.erase( iter ); // iter is still valid after the erase } else { @@ -906,14 +943,14 @@ void ItemView::AddActorsWithinRange( ItemRange range, const Vector3& layoutSize // Total number of items may change dynamically. // Always recalculate the domain size to reflect that. - CalculateDomainSize(Self().GetCurrentSize()); + CalculateDomainSize(Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE )); } void ItemView::AddNewActor( unsigned int itemId, const Vector3& layoutSize ) { mAddingItems = true; - if( mItemPool.end() == mItemPool.find( itemId ) ) + if( mItemPool.end() == FindItemById( mItemPool, itemId ) ) { Actor actor = mItemFactory.NewItem( itemId ); @@ -921,7 +958,7 @@ void ItemView::AddNewActor( unsigned int itemId, const Vector3& layoutSize ) { Item newItem( itemId, actor ); - mItemPool.insert( newItem ); + InsertToItemContainer( mItemPool, newItem ); SetupActor( newItem, layoutSize ); Self().Add( actor ); @@ -933,14 +970,14 @@ void ItemView::AddNewActor( unsigned int itemId, const Vector3& layoutSize ) void ItemView::SetupActor( Item item, const Vector3& layoutSize ) { - item.second.SetParentOrigin( mItemsParentOrigin ); - item.second.SetAnchorPoint( mItemsAnchorPoint ); + item.second.SetProperty( Actor::Property::PARENT_ORIGIN, mItemsParentOrigin ); + item.second.SetProperty( Actor::Property::ANCHOR_POINT, mItemsAnchorPoint ); if( mActiveLayout ) { Vector3 size; mActiveLayout->GetItemSize( item.first, mActiveLayoutTargetSize, size ); - item.second.SetSize( size.GetVectorXY() ); + item.second.SetProperty( Actor::Property::SIZE, size.GetVectorXY() ); mActiveLayout->ApplyConstraints( item.second, item.first, layoutSize, Self() ); } @@ -986,16 +1023,18 @@ void ItemView::OnChildAdd(Actor& child) Toolkit::ItemView::Property::SCROLL_CONTENT_SIZE); } } + + Scrollable::OnChildAdd( child ); } -bool ItemView::OnWheelEvent(const WheelEvent& event) +bool ItemView::OnWheelEvent(Actor actor, const WheelEvent& event) { // Respond the wheel event to scroll if (mActiveLayout) { Actor self = Self(); - const Vector3 layoutSize = Self().GetCurrentSize(); - float layoutPositionDelta = GetCurrentLayoutPosition(0) - (event.z * mWheelScrollDistanceStep * mActiveLayout->GetScrollSpeedFactor()); + const Vector3 layoutSize = Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE ); + float layoutPositionDelta = GetCurrentLayoutPosition(0) - (event.GetDelta() * mWheelScrollDistanceStep * mActiveLayout->GetScrollSpeedFactor()); float firstItemScrollPosition = ClampFirstItemPosition(layoutPositionDelta, layoutSize, *mActiveLayout); self.SetProperty(Toolkit::ItemView::Property::LAYOUT_POSITION, firstItemScrollPosition ); @@ -1041,9 +1080,9 @@ bool ItemView::OnWheelEventFinished() void ItemView::ReapplyAllConstraints() { - Vector3 layoutSize = Self().GetCurrentSize(); + Vector3 layoutSize = Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE ); - for (ConstItemPoolIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter) + for (ConstItemIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter) { unsigned int id = iter->first; Actor actor = iter->second; @@ -1055,12 +1094,12 @@ void ItemView::ReapplyAllConstraints() void ItemView::OnItemsRemoved() { - CalculateDomainSize(Self().GetCurrentSize()); + CalculateDomainSize(Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE )); // Adjust scroll-position after an item is removed if( mActiveLayout ) { - float firstItemScrollPosition = ClampFirstItemPosition(GetCurrentLayoutPosition(0), Self().GetCurrentSize(), *mActiveLayout); + float firstItemScrollPosition = ClampFirstItemPosition(GetCurrentLayoutPosition(0), Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE ), *mActiveLayout); Self().SetProperty( Toolkit::ItemView::Property::LAYOUT_POSITION, firstItemScrollPosition ); } } @@ -1080,7 +1119,7 @@ float ItemView::ClampFirstItemPosition( float targetPosition, const Vector3& tar return clamppedPosition; } -bool ItemView::OnTouch( Actor actor, const TouchData& touch ) +bool ItemView::OnTouch( Actor actor, const TouchEvent& touch ) { // Ignore events with multiple-touch points if (touch.GetPointCount() != 1) @@ -1091,7 +1130,7 @@ bool ItemView::OnTouch( Actor actor, const TouchData& touch ) if ( touch.GetState( 0 ) == PointState::DOWN ) { // Cancel ongoing scrolling etc. - mGestureState = Gesture::Clear; + mGestureState = GestureState::CLEAR; mScrollDistance = 0.0f; mScrollSpeed = 0.0f; @@ -1108,28 +1147,28 @@ bool ItemView::OnTouch( Actor actor, const TouchData& touch ) RemoveAnimation(mScrollAnimation); } - return true; // consume since we're potentially scrolling + return false; // Do not consume as we're potentially scrolling (detecting pan gestures) } void ItemView::OnPan( const PanGesture& gesture ) { Actor self = Self(); - const Vector3 layoutSize = Self().GetCurrentSize(); + const Vector3 layoutSize = Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE ); RemoveAnimation(mScrollAnimation); // Short-circuit if there is no active layout if (!mActiveLayout) { - mGestureState = Gesture::Clear; + mGestureState = GestureState::CLEAR; return; } - mGestureState = gesture.state; + mGestureState = gesture.GetState(); switch (mGestureState) { - case Gesture::Finished: + case GestureState::FINISHED: { // Swipe Detection if (fabsf(mScrollDistance) > mMinimumSwipeDistance && @@ -1159,10 +1198,12 @@ void ItemView::OnPan( const PanGesture& gesture ) mScrollAnimation.AnimateTo( Property(self, Toolkit::ItemView::Property::SCROLL_SPEED), 0.0f, AlphaFunction::EASE_OUT ); mIsFlicking = true; + // Check whether it has already scrolled to the end - if(fabs(currentLayoutPosition - firstItemScrollPosition) > Math::MACHINE_EPSILON_0) + if( fabs(currentLayoutPosition - firstItemScrollPosition) < Math::MACHINE_EPSILON_0 ) { - AnimateScrollOvershoot(0.0f); + AnimateScrollOvershoot( 0.0f ); + RemoveAnimation( mScrollAnimation ); } } @@ -1182,16 +1223,17 @@ void ItemView::OnPan( const PanGesture& gesture ) } break; - case Gesture::Started: // Fall through + case GestureState::STARTED: // Fall through { mTotalPanDisplacement = Vector2::ZERO; mScrollStartedSignal.Emit(GetCurrentScrollPosition()); mRefreshEnabled = true; } - case Gesture::Continuing: + case GestureState::CONTINUING: { - mScrollDistance = CalculateScrollDistance(gesture.displacement, *mActiveLayout); + const Vector2& displacement = gesture.GetDisplacement(); + mScrollDistance = CalculateScrollDistance(displacement, *mActiveLayout); mScrollSpeed = Clamp((gesture.GetSpeed() * gesture.GetSpeed() * mActiveLayout->GetFlickSpeedFactor() * MILLISECONDS_PER_SECONDS), 0.0f, mActiveLayout->GetMaximumSwipeSpeed()); // Refresh order depends on the direction of the scroll; negative is towards the last item. @@ -1201,7 +1243,7 @@ void ItemView::OnPan( const PanGesture& gesture ) float firstItemScrollPosition = ClampFirstItemPosition(layoutPositionDelta, layoutSize, *mActiveLayout); - float currentOvershoot = self.GetProperty(Toolkit::ItemView::Property::OVERSHOOT); + float currentOvershoot = self.GetCurrentProperty< float >( Toolkit::ItemView::Property::OVERSHOOT ); self.SetProperty(Toolkit::ItemView::Property::LAYOUT_POSITION, firstItemScrollPosition ); @@ -1210,7 +1252,7 @@ void ItemView::OnPan( const PanGesture& gesture ) ( firstItemScrollPosition <= mActiveLayout->GetMinimumLayoutPosition(mItemFactory.GetNumberOfItems(), layoutSize) && currentOvershoot > -1.0f ) ) { - mTotalPanDisplacement += gesture.displacement; + mTotalPanDisplacement += displacement; } mScrollOvershoot = CalculateScrollOvershoot(); @@ -1241,7 +1283,7 @@ void ItemView::OnPan( const PanGesture& gesture ) } break; - case Gesture::Cancelled: + case GestureState::CANCELLED: { mScrollAnimation = DoAnchoring(); } @@ -1287,7 +1329,7 @@ Actor ItemView::GetNextKeyboardFocusableActor(Actor actor, Toolkit::Control::Key } } float layoutPosition = mActiveLayout->GetClosestAnchorPosition( GetCurrentLayoutPosition(0) ); - Vector3 layoutSize = Self().GetCurrentSize(); + Vector3 layoutSize = Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE ); if(!nextFocusActor) { // likely the current item is not buffered, so not in our item pool, probably best to get first viewable item @@ -1306,7 +1348,7 @@ void ItemView::OnKeyboardFocusChangeCommitted(Actor commitedFocusableActor) { int nextItemID = GetItemId(commitedFocusableActor); float layoutPosition = GetCurrentLayoutPosition(0); - Vector3 layoutSize = Self().GetCurrentSize(); + Vector3 layoutSize = Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE ); float scrollTo = mActiveLayout->GetClosestOnScreenLayoutPosition(nextItemID, layoutPosition, layoutSize); ScrollTo(Vector2(0.0f, scrollTo), DEFAULT_KEYBOARD_FOCUS_SCROLL_DURATION); @@ -1381,7 +1423,7 @@ void ItemView::OnOvershootOnFinished(Animation& animation) void ItemView::ScrollToItem(unsigned int itemId, float durationSeconds) { Actor self = Self(); - const Vector3 layoutSize = Self().GetCurrentSize(); + const Vector3 layoutSize = Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE ); float firstItemScrollPosition = ClampFirstItemPosition(mActiveLayout->GetItemScrollToPosition(itemId), layoutSize, *mActiveLayout); if(durationSeconds > 0.0f) @@ -1467,12 +1509,12 @@ float ItemView::GetScrollPosition(float layoutPosition, const Vector3& layoutSiz Vector2 ItemView::GetCurrentScrollPosition() const { - return Vector2(0.0f, GetScrollPosition(GetCurrentLayoutPosition(0), Self().GetCurrentSize())); + return Vector2(0.0f, GetScrollPosition(GetCurrentLayoutPosition(0), Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE ))); } void ItemView::AddOverlay(Actor actor) { - actor.SetDrawMode( DrawMode::OVERLAY_2D ); + actor.SetProperty( Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D ); Self().Add(actor); } @@ -1484,7 +1526,7 @@ void ItemView::RemoveOverlay(Actor actor) void ItemView::ScrollTo(const Vector2& position, float duration) { Actor self = Self(); - const Vector3 layoutSize = Self().GetCurrentSize(); + const Vector3 layoutSize = Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE ); float firstItemScrollPosition = ClampFirstItemPosition(position.y, layoutSize, *mActiveLayout); @@ -1506,12 +1548,24 @@ void ItemView::ScrollTo(const Vector2& position, float duration) mRefreshEnabled = true; } +void ItemView::SetOvershootSize( const Vector2& size ) +{ + mOvershootSize = size; + + if( mOvershootOverlay ) + { + // Remove old & add new size constraint + mOvershootOverlay.RemoveConstraints( OVERSHOOT_SIZE_CONSTRAINT_TAG ); + ApplyOvershootSizeConstraint( mOvershootOverlay, mOvershootSize.height ); + } +} + void ItemView::SetOvershootEffectColor( const Vector4& color ) { mOvershootEffectColor = color; if( mOvershootOverlay ) { - mOvershootOverlay.SetColor( color ); + mOvershootOverlay.SetProperty( Actor::Property::COLOR, color ); } } @@ -1524,21 +1578,15 @@ void ItemView::EnableScrollOvershoot( bool enable ) { Property::Index effectOvershootPropertyIndex = Property::INVALID_INDEX; mOvershootOverlay = CreateBouncingEffectActor( effectOvershootPropertyIndex ); - mOvershootOverlay.SetColor(mOvershootEffectColor); - mOvershootOverlay.SetParentOrigin(ParentOrigin::TOP_LEFT); - mOvershootOverlay.SetAnchorPoint(AnchorPoint::TOP_LEFT); - mOvershootOverlay.SetDrawMode( DrawMode::OVERLAY_2D ); + mOvershootOverlay.SetProperty( Actor::Property::COLOR,mOvershootEffectColor); + mOvershootOverlay.SetProperty( Actor::Property::PARENT_ORIGIN,ParentOrigin::TOP_LEFT ); + mOvershootOverlay.SetProperty( Actor::Property::ANCHOR_POINT,AnchorPoint::TOP_LEFT); + mOvershootOverlay.SetProperty( Actor::Property::DRAW_MODE, DrawMode::OVERLAY_2D ); self.Add(mOvershootOverlay); - 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(mOvershootSize.width, mOvershootSize.height); + ApplyOvershootSizeConstraint( mOvershootOverlay, mOvershootSize.height ); - constraint = Constraint::New( mOvershootOverlay, Actor::Property::ORIENTATION, OvershootOverlayRotationConstraint ); + Constraint constraint = Constraint::New( mOvershootOverlay, Actor::Property::ORIENTATION, OvershootOverlayRotationConstraint ); constraint.AddSource( ParentSource( Toolkit::ItemView::Property::SCROLL_DIRECTION ) ); constraint.AddSource( ParentSource( Toolkit::ItemView::Property::LAYOUT_ORIENTATION ) ); constraint.AddSource( ParentSource( Toolkit::ItemView::Property::OVERSHOOT ) ); @@ -1581,7 +1629,7 @@ float ItemView::CalculateScrollOvershoot() Actor self = Self(); float scrollDistance = CalculateScrollDistance(mTotalPanDisplacement, *mActiveLayout) * mActiveLayout->GetScrollSpeedFactor(); float positionDelta = GetCurrentLayoutPosition(0) + scrollDistance; - float minLayoutPosition = mActiveLayout->GetMinimumLayoutPosition(mItemFactory.GetNumberOfItems(), Self().GetCurrentSize()); + float minLayoutPosition = mActiveLayout->GetMinimumLayoutPosition(mItemFactory.GetNumberOfItems(), Self().GetCurrentProperty< Vector3 >( Actor::Property::SIZE )); self.SetProperty(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX, Vector2(0.0f, -minLayoutPosition)); float clamppedPosition = std::min(0.0f, std::max(minLayoutPosition, positionDelta)); overshoot = positionDelta - clamppedPosition; @@ -1607,12 +1655,12 @@ void ItemView::AnimateScrollOvershoot(float overshootAmount, bool animateBack) if(mOvershootAnimationSpeed > Math::MACHINE_EPSILON_0) { - float currentOvershoot = self.GetProperty(Toolkit::ItemView::Property::OVERSHOOT); + float currentOvershoot = self.GetCurrentProperty< float >( Toolkit::ItemView::Property::OVERSHOOT ); float duration = 0.0f; if (mOvershootOverlay) { - duration = mOvershootOverlay.GetCurrentSize().height * (animatingOn ? (1.0f - fabsf(currentOvershoot)) : fabsf(currentOvershoot)) / mOvershootAnimationSpeed; + duration = mOvershootOverlay.GetCurrentProperty< Vector3 >( Actor::Property::SIZE ).height * (animatingOn ? (1.0f - fabsf(currentOvershoot)) : fabsf(currentOvershoot)) / mOvershootAnimationSpeed; } // Mark the animation as in progress to prevent manual property sets overwriting it. @@ -1635,9 +1683,9 @@ void ItemView::SetItemsParentOrigin( const Vector3& parentOrigin ) if( parentOrigin != mItemsParentOrigin ) { mItemsParentOrigin = parentOrigin; - for (ItemPoolIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter) + for (ItemIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter) { - iter->second.SetParentOrigin(parentOrigin); + iter->second.SetProperty( Actor::Property::PARENT_ORIGIN,parentOrigin ); } } } @@ -1652,9 +1700,9 @@ void ItemView::SetItemsAnchorPoint( const Vector3& anchorPoint ) if( anchorPoint != mItemsAnchorPoint ) { mItemsAnchorPoint = anchorPoint; - for (ItemPoolIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter) + for (ItemIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter) { - iter->second.SetAnchorPoint(anchorPoint); + iter->second.SetProperty( Actor::Property::ANCHOR_POINT,anchorPoint); } } } @@ -1712,26 +1760,119 @@ void ItemView::SetProperty( BaseObject* object, Property::Index index, const Pro itemViewImpl.SetMinimumSwipeSpeed( value.Get() ); break; } + case Toolkit::ItemView::Property::MINIMUM_SWIPE_DISTANCE: { itemViewImpl.SetMinimumSwipeDistance( value.Get() ); break; } + case Toolkit::ItemView::Property::WHEEL_SCROLL_DISTANCE_STEP: { itemViewImpl.SetWheelScrollDistanceStep( value.Get() ); break; } + case Toolkit::ItemView::Property::SNAP_TO_ITEM_ENABLED: { itemViewImpl.SetAnchoring( value.Get() ); break; } + case Toolkit::ItemView::Property::REFRESH_INTERVAL: { itemViewImpl.SetRefreshInterval( value.Get() ); break; } + + case Toolkit::ItemView::Property::LAYOUT: + { + // Get a Property::Array from the property if possible. + Property::Array layoutArray; + if( value.Get( layoutArray ) ) + { + itemViewImpl.SetLayoutArray( layoutArray ); + } + break; + } + } + } +} + +Property::Array ItemView::GetLayoutArray() +{ + return mlayoutArray; +} + +void ItemView::SetLayoutArray( const Property::Array& layouts ) +{ + mlayoutArray = layouts; + const int layoutCount = GetLayoutCount(); + if( layoutCount > 0 ) + { + for(int index = layoutCount - 1; index >= 0; --index) + { + RemoveLayout(index); + if(index == 0) break; + } + } + + for( unsigned int arrayIdx = 0, arrayCount = layouts.Count(); arrayIdx < arrayCount; ++arrayIdx ) + { + const Property::Value& element = layouts.GetElementAt( arrayIdx ); + + const Property::Map* layout = element.GetMap(); + if( layout != NULL ) + { + for( unsigned int mapIdx = 0, mapCount = (*layout).Count(); mapIdx < mapCount; ++mapIdx ) + { + KeyValuePair propertyPair( (*layout).GetKeyValue( mapIdx ) ); + + if(propertyPair.first == DefaultItemLayoutProperty::TYPE) + { + int layoutType = propertyPair.second.Get(); + if(layoutType <= DefaultItemLayout::SPIRAL && layoutType >= DefaultItemLayout::DEPTH) + { + //DEPTH, GRID, LIST, SPIRAL + switch(DefaultItemLayout::Type(layoutType)) + { + case DefaultItemLayout::DEPTH: + { + Internal::DepthLayoutPtr depthLayout = Internal::DepthLayout::New(); + (*depthLayout).SetLayoutProperties(*layout); + (*depthLayout).SetDepthLayoutProperties(*layout); + AddLayout(*depthLayout); + break; + } + case DefaultItemLayout::GRID: + { + Internal::GridLayoutPtr gridLayout = Internal::GridLayout::New(); + (*gridLayout).SetLayoutProperties(*layout); + (*gridLayout).SetGridLayoutProperties(*layout); + AddLayout(*gridLayout); + break; + } + case DefaultItemLayout::LIST: + { + Internal::GridLayoutPtr listLayout = Internal::GridLayout::New(); + listLayout->SetNumberOfColumns( 1 ); + (*listLayout).SetLayoutProperties(*layout); + (*listLayout).SetGridLayoutProperties(*layout); + AddLayout(*listLayout); + break; + } + case DefaultItemLayout::SPIRAL: + { + Internal::SpiralLayoutPtr spiralLayout = Internal::SpiralLayout::New(); + (*spiralLayout).SetLayoutProperties(*layout); + (*spiralLayout).SetSpiralLayoutProperties(*layout); + AddLayout(*spiralLayout); + break; + } + } + } + } + } } } } @@ -1752,26 +1893,37 @@ Property::Value ItemView::GetProperty( BaseObject* object, Property::Index index value = itemViewImpl.GetMinimumSwipeSpeed(); break; } + case Toolkit::ItemView::Property::MINIMUM_SWIPE_DISTANCE: { value = itemViewImpl.GetMinimumSwipeDistance(); break; } + case Toolkit::ItemView::Property::WHEEL_SCROLL_DISTANCE_STEP: { value = itemViewImpl.GetWheelScrollDistanceStep(); break; } + case Toolkit::ItemView::Property::SNAP_TO_ITEM_ENABLED: { value = itemViewImpl.GetAnchoring(); break; } + case Toolkit::ItemView::Property::REFRESH_INTERVAL: { value = itemViewImpl.GetRefreshInterval(); break; } + + case Toolkit::ItemView::Property::LAYOUT: + { + Property::Array layouts= itemViewImpl.GetLayoutArray(); + value = layouts; + break; + } } }