From ae1982a116aae1d8e25837fa553ba2e37bc062a7 Mon Sep 17 00:00:00 2001 From: Paul Wisbey Date: Fri, 14 Mar 2014 15:19:40 +0000 Subject: [PATCH] More ItemView Insert/Remove/Replace APIs [Issue#] N/A [Problem] Not easy enough to write applications with ItemView [Cause] API limitations [Solution] Provided Insert/Remove/Replace APIs Change-Id: I81a89021a99664d95a08e2f5dd659905186f052e --- .../scrollable/item-view/item-view-declarations.h | 57 +++ .../controls/scrollable/item-view/item-view.h | 75 +++- capi/dali-toolkit/public-api/file.list | 3 +- .../scrollable/item-view/item-view-impl.cpp | 404 ++++++++++++++------- .../controls/scrollable/item-view/item-view-impl.h | 165 ++++----- .../controls/scrollable/item-view/item-view.cpp | 27 +- 6 files changed, 481 insertions(+), 250 deletions(-) create mode 100644 capi/dali-toolkit/public-api/controls/scrollable/item-view/item-view-declarations.h diff --git a/capi/dali-toolkit/public-api/controls/scrollable/item-view/item-view-declarations.h b/capi/dali-toolkit/public-api/controls/scrollable/item-view/item-view-declarations.h new file mode 100644 index 0000000..cd643b6 --- /dev/null +++ b/capi/dali-toolkit/public-api/controls/scrollable/item-view/item-view-declarations.h @@ -0,0 +1,57 @@ +#ifndef __DALI_TOOLKIT_ITEM_VIEW_DECLARATIONS_H__ +#define __DALI_TOOLKIT_ITEM_VIEW_DECLARATIONS_H__ + +// +// 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. +// + +/** + * @addtogroup CAPI_DALI_FRAMEWORK + * @{ + */ + +// EXTERNAL INCLUDES +#include // std::pair +#include + +namespace Dali DALI_IMPORT_API +{ + +namespace Toolkit +{ + +typedef unsigned int ItemId; + +typedef std::vector ItemIdContainer; +typedef ItemIdContainer::iterator ItemIdIter; +typedef ItemIdContainer::const_iterator ConstItemIdIter; + +typedef std::pair Item; + +typedef std::vector ItemContainer; +typedef ItemContainer::iterator ItemIter; +typedef ItemContainer::const_iterator ConstItemIter; + +class ItemView; +class ItemLayout; + +} // namespace Toolkit + +} // namespace Dali + +/** + * @} + */ +#endif // __DALI_TOOLKIT_ITEM_VIEW_DECLARATIONS_H__ diff --git a/capi/dali-toolkit/public-api/controls/scrollable/item-view/item-view.h b/capi/dali-toolkit/public-api/controls/scrollable/item-view/item-view.h index fc24681..cb5ed06 100644 --- a/capi/dali-toolkit/public-api/controls/scrollable/item-view/item-view.h +++ b/capi/dali-toolkit/public-api/controls/scrollable/item-view/item-view.h @@ -22,10 +22,12 @@ * @{ */ -// INTERNAL INCLUDES +// EXTERNAL INCLUDES #include +// INTERNAL INCLUDES #include +#include namespace Dali DALI_IMPORT_API { @@ -133,7 +135,7 @@ public: * @param[in] itemId The item identifier. * @return The current layout-position. */ - float GetCurrentLayoutPosition(unsigned int itemId) const; + float GetCurrentLayoutPosition(ItemId itemId) const; /** * Activate one of the layouts; this will resize the ItemView & relayout actors within the ItemView. @@ -224,7 +226,7 @@ public: * @param[in] itemId The ID of an item in the layout. * @param[in] durationSeconds How long the scrolling takes in seconds. */ - void ScrollToItem(unsigned int itemId, float durationSeconds); + void ScrollToItem(ItemId itemId, float durationSeconds); /** * Set the interval between refreshes, during which new items are requested from ItemFactory. @@ -243,7 +245,7 @@ public: * @param[in] itemId The Item ID of the actor required. * @return The Actor corresponding to the Item ID. */ - Actor GetItem(unsigned int itemId) const; + Actor GetItem(ItemId itemId) const; /** * Returns the Item ID of the specified actor. @@ -251,16 +253,71 @@ public: * @return The Item ID of the item. * @pre The actor should be an item of ItemView. */ - unsigned int GetItemId(Actor actor) const; + ItemId GetItemId(Actor actor) const; + + /** + * Insert an item. + * A relayout will occur for the existing actors; for example if InsertItem(Item(2, ActorZ), 0) is called, + * the items with ID 2 or greater will be moved: + * Initial actors: After insert: + * ID 1 - ActorA ID 1 - ActorA + * ID 2 - ActorB ID 2 - ActorZ ! + * ID 3 - ActorC ID 3 - ActorB + * ID 4 - ActorC + * @pre durationSeconds must be zero or greater; zero means the relayout occurs instantly. + * @param[in] newItem The item to insert. + * @param[in] durationSeconds How long the relayout takes in seconds. + */ + void InsertItem(Item newItem, float durationSeconds); + + /** + * Insert a set of items; this is more efficient than calling InsertItem() repeatedly. + * @pre durationSeconds must be zero or greater; zero means the relayout occurs instantly. + * @param[in] newItems The items to insert. + * @param[in] durationSeconds How long the relayout takes in seconds. + */ + void InsertItems(const ItemContainer& newItems, float durationSeconds); /** * Removes an item with the given ID. - * @pre durationSeconds must be zero or greater; zero means when the item is deleted the remaining items - * will finish the relayout instantly. + * A relayout will occur for the remaining actors; for example if RemoveItem(Item(2, ActorZ), 0) is called, + * the items with ID 3 or greater will be moved: + * Initial actors: After remove: + * ID 1 - ActorA ID 1 - ActorA + * ID 2 - ActorB ID 2 - ActorC (previously ID 3) + * ID 3 - ActorC ID 3 - ActorB (previously ID 4) + * ID 4 - ActorD + * @pre durationSeconds must be zero or greater; zero means the relayout occurs instantly. * @param[in] itemId The Item ID of the item to remove. - * @param[in] durationSeconds How long the realyout takes in seconds after the item is deleted. + * @param[in] durationSeconds How long the relayout takes in seconds. + */ + void RemoveItem(ItemId itemId, float durationSeconds); + + /** + * Remove a set of items; this is more efficient than calling RemoveItem() repeatedly. + * @pre durationSeconds must be zero or greater; zero means the relayout occurs instantly. + * @param[in] itemIds The IDs of the items to remove. + * @param[in] durationSeconds How long the relayout takes in seconds. + */ + void RemoveItems(const ItemIdContainer& itemIds, float durationSeconds); + + /** + * Replace an item. + * A relayout will occur for the replacement item only. + * @pre durationSeconds must be zero or greater; zero means the relayout occurs instantly. + * @param[in] replacementItem The replacement for an existing item. + * @param[in] durationSeconds How long the relayout takes in seconds. + */ + void ReplaceItem(Item replacementItem, float durationSeconds); + + /** + * Replace a set of items. + * A relayout will occur for the replacement items only. + * @pre durationSeconds must be zero or greater; zero means the relayout occurs instantly. + * @param[in] replacementItems The replacements for a set of existing items. + * @param[in] durationSeconds How long the relayout takes in seconds. */ - void RemoveItem(unsigned int itemId, float durationSeconds); + void ReplaceItems(const ItemContainer& replacementItems, float durationSeconds); public: // Not intended for application developers diff --git a/capi/dali-toolkit/public-api/file.list b/capi/dali-toolkit/public-api/file.list index d655ee2..0ba0f28 100644 --- a/capi/dali-toolkit/public-api/file.list +++ b/capi/dali-toolkit/public-api/file.list @@ -38,7 +38,8 @@ capi_devel_item_view_header_files = \ $(capi_devel_src_dir)/controls/scrollable/item-view/grid-layout.h \ $(capi_devel_src_dir)/controls/scrollable/item-view/item-factory.h \ $(capi_devel_src_dir)/controls/scrollable/item-view/item-layout.h \ - $(capi_devel_src_dir)/controls/scrollable/item-view/item-view.h + $(capi_devel_src_dir)/controls/scrollable/item-view/item-view.h \ + $(capi_devel_src_dir)/controls/scrollable/item-view/item-view-declarations.h capi_devel_scroll_view_header_files = \ $(capi_devel_src_dir)/controls/scrollable/scroll-view/scroll-view.h \ 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 acb74dc..dad90ef 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 @@ -19,6 +19,7 @@ // EXTERNAL INCLUDES #include +#include // INTERNAL INCLUDES #include @@ -358,107 +359,23 @@ namespace Toolkit namespace Internal { -/////////////////////////////////////////////////////////////////////////////////////////////////// -// ItemPool -/////////////////////////////////////////////////////////////////////////////////////////////////// - -void ItemPool::AddItems(bool scrollingTowardsLast, ItemRange range, const Vector3& targetSize) -{ - // Add new actors to the ItemPool. - // The order of addition depends on the scroll direction. - if (scrollingTowardsLast) - { - for (unsigned int itemId = range.begin; itemId < range.end; ++itemId) - { - AddItem(itemId, targetSize); - } - } - else - { - for (unsigned int itemId = range.end; itemId > range.begin; --itemId) - { - AddItem(itemId-1, targetSize); - } - } -} - -void ItemPool::RemoveItems(ItemRange range) -{ - // Remove unwanted actors from the ItemView & ItemPool - for (IDKeyIter iter = mIdKeyContainer.begin(); iter != mIdKeyContainer.end(); ) - { - unsigned int current = iter->first; - - if (!range.Within(current)) - { - mItemView.ActorRemovedFromItemPool(iter->second, iter->first); - - mActorKeyContainer.erase(iter->second); - mIdKeyContainer.erase(iter++); // erase invalidates the current iter; the post-increment is important here - } - else - { - ++iter; - } - } -} - -void ItemPool::AddItem(unsigned int itemId, const Vector3& targetSize) +namespace // unnamed namespace { - if (mIdKeyContainer.find(itemId) == mIdKeyContainer.end()) - { - Actor actor = mItemView.CreateActor(itemId); - - if (actor) - { - mIdKeyContainer.insert(IDKeyPair(itemId, actor)); - mActorKeyContainer.insert(ActorKeyPair(actor, itemId)); - mItemView.ActorAddedToItemPool(actor, itemId, targetSize); - } - } -} - -bool ItemPool::RemoveItem(unsigned int itemId) +bool FindById( const ItemContainer& items, ItemId id ) { - bool found = false; - - IDKeyIter iter = mIdKeyContainer.find(itemId); - if (iter != mIdKeyContainer.end()) + for( ConstItemIter iter = items.begin(); items.end() != iter; ++iter ) { - mItemView.ActorRemovedFromItemPool(iter->second, iter->first); - - mActorKeyContainer.erase(iter->second); - for (ActorKeyIter iterActorKey = mActorKeyContainer.begin(); iterActorKey != mActorKeyContainer.end(); ++iterActorKey) - { - if(iterActorKey->second > itemId) - { - iterActorKey->second--; - } - } - - for (IDKeyIter iterIDKey = iter; iterIDKey != mIdKeyContainer.end(); ++iterIDKey) + if( iter->first == id ) { - if(iterIDKey->first < mIdKeyContainer.rbegin()->first) - { - iterIDKey->second = mIdKeyContainer[iterIDKey->first + 1]; - } - else - { - mIdKeyContainer.erase(iterIDKey); - break; - } + return true; } - - found = true; } - return found; + return false; } -/////////////////////////////////////////////////////////////////////////////////////////////////// -// ItemView -/////////////////////////////////////////////////////////////////////////////////////////////////// +} // unnamed namespace Dali::Toolkit::ItemView ItemView::New(ItemFactory& factory) { @@ -478,7 +395,6 @@ Dali::Toolkit::ItemView ItemView::New(ItemFactory& factory) ItemView::ItemView(ItemFactory& factory) : Scrollable(), mItemFactory(factory), - mItemPool(*this), mActiveLayout(NULL), mAnimatingOvershootOn(false), mAnimateOvershootOff(false), @@ -598,6 +514,7 @@ void ItemView::ActivateLayout(unsigned int layoutIndex, const Vector3& targetSiz // The ItemView size should match the active layout size self.SetSize(targetSize); + mActiveLayoutTargetSize = targetSize; // Switch to the new layout ItemLayout* previousLayout = mActiveLayout; @@ -611,8 +528,7 @@ void ItemView::ActivateLayout(unsigned int layoutIndex, const Vector3& targetSiz bool resizeAnimationNeeded(false); - const ItemPool::IDKeyContainer& itemPool = mItemPool.GetIDKeyContainer(); - for (ItemPool::IDKeyConstIter iter = itemPool.begin(); iter != itemPool.end(); ++iter) + for (ConstItemPoolIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter) { unsigned int itemId = iter->first; Actor actor = iter->second; @@ -658,7 +574,7 @@ void ItemView::ActivateLayout(unsigned int layoutIndex, const Vector3& targetSiz // Refresh the new layout ItemRange range = GetItemRange(*mActiveLayout, targetSize, true/*reserve extra*/); - AddItems(*mActiveLayout, targetSize, range); + AddActorsWithinRange( range ); // Scroll to an appropriate layout position @@ -706,8 +622,7 @@ void ItemView::DeactivateCurrentLayout() { if (mActiveLayout) { - const ItemPool::IDKeyContainer& itemPool = mItemPool.GetIDKeyContainer(); - for (ItemPool::IDKeyConstIter iter = itemPool.begin(); iter != itemPool.end(); ++iter) + for (ConstItemPoolIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter) { Actor actor = iter->second; actor.RemoveConstraints(); @@ -727,12 +642,11 @@ bool ItemView::OnRefreshTick() return false; } - const Vector3 layoutSize = Self().GetCurrentSize(); + ItemRange range = GetItemRange(*mActiveLayout, mActiveLayoutTargetSize, true/*reserve extra*/); - ItemRange range = GetItemRange(*mActiveLayout, layoutSize, true/*reserve extra*/); + RemoveActorsOutsideRange( range ); - RemoveItems(range); - AddItems(*mActiveLayout, layoutSize, range); + AddActorsWithinRange( range ); // Keep refreshing whilst the layout is moving return mScrollAnimation || (mGestureState == Gesture::Started || mGestureState == Gesture::Continuing); @@ -802,88 +716,290 @@ Actor ItemView::GetItem(unsigned int itemId) const { Actor actor; - ItemPool::IDKeyConstIter found = mItemPool.GetIDKeyContainer().find(itemId); - if (found != mItemPool.GetIDKeyContainer().end()) + ConstItemPoolIter iter = mItemPool.find( itemId ); + if( iter != mItemPool.end() ) { - actor = found->second; + actor = iter->second; } return actor; } -unsigned int ItemView::GetItemId(Actor actor) const +unsigned int ItemView::GetItemId( Actor actor ) const { - unsigned int itemId(0); + unsigned int itemId( 0 ); - ItemPool::ActorKeyConstIter found = mItemPool.GetActorKeyContainer().find(actor); - if (found != mItemPool.GetActorKeyContainer().end()) + for ( ConstItemPoolIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter ) { - itemId = found->second; + if( iter->second == actor ) + { + itemId = iter->first; + break; + } } return itemId; } -void ItemView::RemoveItem(unsigned int itemId, float durationSeconds) +void ItemView::InsertItem( Item newItem, float durationSeconds ) { - if (mItemPool.RemoveItem(itemId)) + SetupActor( newItem, durationSeconds ); + Self().Add( newItem.second ); + + ItemPoolIter foundIter = mItemPool.find( newItem.first ); + if( mItemPool.end() != foundIter ) { - const ItemPool::IDKeyContainer& itemPool = mItemPool.GetIDKeyContainer(); - for (ItemPool::IDKeyConstIter iter = itemPool.begin(); iter != itemPool.end(); ++iter) + Actor moveMe = foundIter->second; + foundIter->second = newItem.second; + + // Move the existing actors to make room + for( ItemPoolIter iter = ++foundIter; mItemPool.end() != iter; ++iter ) { - unsigned int id = iter->first; - Actor actor = iter->second; + Actor temp = iter->second; + iter->second = moveMe; + moveMe = temp; - // Reposition the items if necessary - actor.RemoveConstraints(); - ApplyConstraints(actor, *mActiveLayout, id, durationSeconds); + iter->second.RemoveConstraints(); + ApplyConstraints( iter->second, *mActiveLayout, iter->first, durationSeconds ); } - CalculateDomainSize(Self().GetCurrentSize()); + // Create last item + ItemId lastId = mItemPool.rbegin()->first; + Item lastItem( lastId + 1, moveMe ); + mItemPool.insert( lastItem ); + + lastItem.second.RemoveConstraints(); + ApplyConstraints( lastItem.second, *mActiveLayout, lastItem.first, durationSeconds ); + } + else + { + mItemPool.insert( newItem ); } } -Actor ItemView::CreateActor(unsigned int itemId) +void ItemView::InsertItems( const ItemContainer& newItems, float durationSeconds ) { - return mItemFactory.NewItem(itemId); + // Insert from lowest id to highest + set sortedItems; + for( ConstItemIter iter = newItems.begin(); newItems.end() != iter; ++iter ) + { + sortedItems.insert( *iter ); + } + + for( set::iterator iter = sortedItems.begin(); sortedItems.end() != iter; ++iter ) + { + Self().Add( iter->second ); + + cout << "inserting item: " << iter->first << endl; + + ItemPoolIter foundIter = mItemPool.find( 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 ) + { + Actor temp = iter->second; + iter->second = moveMe; + moveMe = temp; + } + + // Create last item + ItemId lastId = mItemPool.rbegin()->first; + Item lastItem( lastId + 1, moveMe ); + mItemPool.insert( lastItem ); + } + else + { + mItemPool.insert( *iter ); + } + } + + // Relayout everything + for (ItemPoolIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter) + { + // If newly inserted + if( FindById( newItems, iter->first ) ) + { + SetupActor( *iter, durationSeconds ); + } + else + { + iter->second.RemoveConstraints(); + ApplyConstraints( iter->second, *mActiveLayout, iter->first, durationSeconds ); + } + } } -void ItemView::ActorAddedToItemPool(Actor actor, unsigned int itemId, const Vector3& targetSize) +void ItemView::RemoveItem( unsigned int itemId, float durationSeconds ) { - Actor self = Self(); + bool actorRemoved = RemoveActor( itemId ); + if( actorRemoved ) + { + ReapplyAllConstraints( durationSeconds ); + } +} - actor.SetParentOrigin(ParentOrigin::CENTER); - actor.SetAnchorPoint(AnchorPoint::CENTER); +void ItemView::RemoveItems( const ItemIdContainer& itemIds, float durationSeconds ) +{ + bool actorRemoved( false ); - if (mActiveLayout) + // Remove from highest id to lowest + set sortedItems; + for( ConstItemIdIter iter = itemIds.begin(); itemIds.end() != iter; ++iter ) { - Vector3 size; - if(mActiveLayout->GetItemSize(itemId, targetSize, size)) + sortedItems.insert( *iter ); + } + + for( set::reverse_iterator iter = sortedItems.rbegin(); sortedItems.rend() != iter; ++iter ) + { + if( RemoveActor( *iter ) ) { - actor.SetSize(size); + actorRemoved = true; } + } - ApplyConstraints(actor, *mActiveLayout, itemId, 0.0f/*immediate*/); + if( actorRemoved ) + { + ReapplyAllConstraints( durationSeconds ); + } +} + +bool ItemView::RemoveActor(unsigned int itemId) +{ + bool removed( false ); + + const ItemPoolIter removeIter = mItemPool.find( itemId ); + + if( removeIter != mItemPool.end() ) + { + Self().Remove( removeIter->second ); + removed = true; + + // Adjust the remaining item IDs, for example if item 2 is removed: + // Initial actors: After insert: + // ID 1 - ActorA ID 1 - ActorA + // 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) + { + if( iter->first < mItemPool.rbegin()->first ) + { + iter->second = mItemPool[ iter->first + 1 ]; + } + else + { + mItemPool.erase( iter ); + break; + } + } } - self.Add(actor); + return removed; } -void ItemView::ActorRemovedFromItemPool(Actor actor, unsigned int itemId) +void ItemView::ReplaceItem( Item replacementItem, float durationSeconds ) { - Self().Remove(actor); + SetupActor( replacementItem, durationSeconds ); + Self().Add( replacementItem.second ); + + const ItemPoolIter iter = mItemPool.find( replacementItem.first ); + if( mItemPool.end() != iter ) + { + Self().Remove( iter->second ); + iter->second = replacementItem.second; + } + else + { + mItemPool.insert( replacementItem ); + } } -void ItemView::RemoveItems(ItemRange range) +void ItemView::ReplaceItems( const ItemContainer& replacementItems, float durationSeconds ) { - mItemPool.RemoveItems(range); + for( ConstItemIter iter = replacementItems.begin(); replacementItems.end() != iter; ++iter ) + { + ReplaceItem( *iter, durationSeconds ); + } +} + +void ItemView::RemoveActorsOutsideRange( ItemRange range ) +{ + // Remove unwanted actors from the ItemView & ItemPool + for (ItemPoolIter iter = mItemPool.begin(); iter != mItemPool.end(); ) + { + unsigned int current = iter->first; + + if( ! range.Within( current ) ) + { + Self().Remove( iter->second ); + + mItemPool.erase( iter++ ); // erase invalidates the return value of post-increment; iter remains valid + } + else + { + ++iter; + } + } } -void ItemView::AddItems(ItemLayout& layout, const Vector3& layoutSize, ItemRange range) +void ItemView::AddActorsWithinRange( ItemRange range ) { range.end = min(mItemFactory.GetNumberOfItems(), range.end); - mItemPool.AddItems(mRefreshOrderHint, range, layoutSize); + // The order of addition depends on the scroll direction. + if (mRefreshOrderHint) + { + for (unsigned int itemId = range.begin; itemId < range.end; ++itemId) + { + AddNewActor( itemId ); + } + } + else + { + for (unsigned int itemId = range.end; itemId > range.begin; --itemId) + { + AddNewActor( itemId-1 ); + } + } +} + +void ItemView::AddNewActor( unsigned int itemId ) +{ + if( mItemPool.end() == mItemPool.find( itemId ) ) + { + Actor actor = mItemFactory.NewItem( itemId ); + + if( actor ) + { + Item newItem( itemId, actor ); + + mItemPool.insert( newItem ); + + SetupActor( newItem, 0.0f/*immediate*/ ); + Self().Add( actor ); + } + } +} + +void ItemView::SetupActor( Item item, float durationSeconds ) +{ + item.second.SetParentOrigin( ParentOrigin::CENTER ); + item.second.SetAnchorPoint( AnchorPoint::CENTER ); + + if( mActiveLayout ) + { + Vector3 size; + if( mActiveLayout->GetItemSize( item.first, mActiveLayoutTargetSize, size ) ) + { + item.second.SetSize( size ); + } + + ApplyConstraints( item.second, *mActiveLayout, item.first, durationSeconds ); + } } ItemRange ItemView::GetItemRange(ItemLayout& layout, const Vector3& layoutSize, bool reserveExtra) @@ -1072,6 +1188,20 @@ void ItemView::ApplyConstraints(Actor& actor, ItemLayout& layout, unsigned int i } } +void ItemView::ReapplyAllConstraints( float durationSeconds ) +{ + for (ConstItemPoolIter iter = mItemPool.begin(); iter != mItemPool.end(); ++iter) + { + unsigned int id = iter->first; + Actor actor = iter->second; + + actor.RemoveConstraints(); + ApplyConstraints(actor, *mActiveLayout, id, durationSeconds); + } + + CalculateDomainSize(Self().GetCurrentSize()); +} + float ItemView::ClampFirstItemPosition(float targetPosition, const Vector3& targetSize, ItemLayout& layout) { Actor self = Self(); diff --git a/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h b/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h index 2012081..f92894e 100644 --- a/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h +++ b/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h @@ -19,6 +19,7 @@ // EXTERNAL INCLUDES #include +#include // INTERNAL INCLUDES #include @@ -43,91 +44,6 @@ class ItemView; typedef IntrusivePtr ItemViewPtr; /** - * ItemPool is container of Actor/ID pairs stored by ItemView - */ -class ItemPool -{ -public: // types - - typedef std::pair IDKeyPair; - typedef std::map IDKeyContainer; - typedef IDKeyContainer::iterator IDKeyIter; - typedef IDKeyContainer::const_iterator IDKeyConstIter; - - typedef std::pair ActorKeyPair; - typedef std::map ActorKeyContainer; - typedef ActorKeyContainer::iterator ActorKeyIter; - typedef ActorKeyContainer::const_iterator ActorKeyConstIter; - -public: // Construction & Destruction - - /** - * Constructor - * @param[in] itemView A reference to the ItemView class that owns this. - */ - ItemPool(ItemView& itemView) - : mItemView(itemView) - { - } - -public: // Methods - - /** - * Returns a const reference to the IDKeyContainer whose key is based on the Item ID. - * @return Const reference to IDKeyContainer. - */ - const IDKeyContainer& GetIDKeyContainer() const - { - return mIdKeyContainer; - } - - /** - * Returns a const reference to the ActorKeyContainer whose key is based on the Actor. - * @return Const reference to IDKeyContainer. - */ - const ActorKeyContainer& GetActorKeyContainer() const - { - return mActorKeyContainer; - } - - /** - * Add a range of items to the ItemPool, if they are not already in the ItemPool. - * @param[in] scrollingTowardsLast Should be true if scrolling towards the last item in the range. - * @param[in] range The range of Item IDs to associate with the new actors. - * @param[in] targetSize The current size of the layout. - */ - void AddItems(bool scrollingTowardsLast, ItemRange range, const Vector3& targetSize); - - /** - * Remove items from the ItemPool that are outside the given range. - * @param[in] range The range of required items. - */ - void RemoveItems(ItemRange range); - - /** - * Remove an item from the ItemPool. - * @param[in] itemId The item to remove. - * @return Whether the item is found and removed or not. - */ - bool RemoveItem(unsigned int itemId); - -private: - - /** - * Adds an item, if not already in the ItemPool. - * @param[in] itemId The item to add. - * @param[in] targetSize The target size of the layout. - */ - void AddItem(unsigned int itemId, const Vector3& targetSize); - -private: - - IDKeyContainer mIdKeyContainer; - ActorKeyContainer mActorKeyContainer; - ItemView& mItemView; -}; - -/** * ItemView is a scrollable layout container. * Multiple ItemLayouts may be provided, to determine the logical position of each item a layout. * Actor-ID pairs are provided from a shared ItemFactory, to display the currently visible items. @@ -264,9 +180,34 @@ public: unsigned int GetItemId(Actor actor) const; /** + * @copydoc Toolkit::ItemView::InsertItem + */ + void InsertItem(Item newItem, float durationSeconds); + + /** + * @copydoc Toolkit::ItemView::InsertItem + */ + void InsertItems(const ItemContainer& newItems, float durationSeconds); + + /** * @copydoc Toolkit::ItemView::RemoveItem */ - void RemoveItem(unsigned int itemId, float durationSeconds); + void RemoveItem(ItemId itemId, float durationSeconds); + + /** + * @copydoc Toolkit::ItemView::InsertItem + */ + void RemoveItems(const ItemIdContainer& itemIds, float durationSeconds); + + /** + * @copydoc Toolkit::ItemView::InsertItem + */ + void ReplaceItem(Item replacementItem, float durationSeconds); + + /** + * @copydoc Toolkit::ItemView::InsertItem + */ + void ReplaceItems(const ItemContainer& replacementItems, float durationSeconds); /** * @copydoc Toolkit::Scrollable::GetDomainSize @@ -293,30 +234,40 @@ public: */ void ScrollTo(const Vector3& position, float duration); -public: // Used By ItemPool +private: /** - * Called by the ItemPool when it wishes to create an actor from the ItemFactory with the - * specified ItemId. - * @param[in] itemId The Item ID of the actor to create. + * Remove an Actor if found in the ItemPool. + * @param[in] itemId The item to remove. + * @return True if an actor was removed. */ - Actor CreateActor(unsigned int itemId); + bool RemoveActor( unsigned int itemId ); /** - * Called by the ItemPool when an actor is added to the ItemPool. - * @param[in] actor The actor that has been added. - * @param[in] itemId The associated Item ID. - * @param[in] targetSize The target size that was specified upon addition. + * Remove any Actors outside a given range. + * @param[in] @param[in] range The range of required items. */ - void ActorAddedToItemPool(Actor actor, unsigned int itemId, const Vector3& targetSize); + void RemoveActorsOutsideRange( ItemRange range ); /** - * Called by the ItemPool when an actor with the specified itemId is about to be removed from the - * ItemPool. - * @param[in] actor The actor about to be removed. - * @param[in] itemId The associated Item ID. + * Add a range of Actors, if they are not already in the ItemPool. + * @param[in] layout The active layout. + * @param[in] range The range of Item IDs to associate with the new actors. */ - void ActorRemovedFromItemPool(Actor actor, unsigned int itemId); + void AddActorsWithinRange( ItemRange range ); + + /** + * Add a new Actor, if not already in the ItemPool. + * @param[in] item The ID for the new item. + */ + void AddNewActor( ItemId item ); + + /** + * Apply the constraints etc. that are required for ItemView children. + * @param[in] item The item to setup. + * @param[in] durationSeconds The time taken to fully constrain the actor. + */ + void SetupActor( Item item, float durationSeconds ); private: // From CustomActorImpl @@ -387,6 +338,12 @@ private: void ApplyConstraints(Actor& actor, ItemLayout& layout, unsigned int itemId, float durationSeconds); /** + * Helper to re-apply all the constraints after items have been inserted, removed etc. + * @param[in] durationSeconds The time taken to fully constrain the actors. + */ + void ReapplyAllConstraints( float durationSeconds ); + + /** * Helper to remove items outside a given range. * @param[in] range The range of required items. */ @@ -514,7 +471,6 @@ private: */ void CalculateDomainSize(const Vector3& layoutSize); - /** * Calculates whether we want to allow current item view to scroll. * @param[in] layoutSize The current size of the layout. @@ -526,10 +482,15 @@ private: ItemFactory& mItemFactory; + typedef std::map ItemPool; + typedef ItemPool::iterator ItemPoolIter; + typedef ItemPool::const_iterator ConstItemPoolIter; + ItemPool mItemPool; ItemLayoutContainer mLayouts; ItemLayout* mActiveLayout; + Vector3 mActiveLayoutTargetSize; Animation mResizeAnimation; Animation mScrollAnimation; diff --git a/dali-toolkit/public-api/controls/scrollable/item-view/item-view.cpp b/dali-toolkit/public-api/controls/scrollable/item-view/item-view.cpp index c951b0c..3e7f757 100644 --- a/dali-toolkit/public-api/controls/scrollable/item-view/item-view.cpp +++ b/dali-toolkit/public-api/controls/scrollable/item-view/item-view.cpp @@ -187,9 +187,34 @@ unsigned int ItemView::GetItemId(Actor actor) const return GetImpl(*this).GetItemId(actor); } +void ItemView::InsertItem(Item newItem, float durationSeconds) +{ + GetImpl(*this).InsertItem( newItem, durationSeconds ); +} + +void ItemView::InsertItems(const ItemContainer& newItems, float durationSeconds) +{ + GetImpl(*this).InsertItems( newItems, durationSeconds ); +} + void ItemView::RemoveItem(unsigned int itemId, float durationSeconds) { - GetImpl(*this).RemoveItem(itemId, durationSeconds); + GetImpl(*this).RemoveItem( itemId, durationSeconds ); +} + +void ItemView::RemoveItems(const ItemIdContainer& itemIds, float durationSeconds) +{ + GetImpl(*this).RemoveItems( itemIds, durationSeconds ); +} + +void ItemView::ReplaceItem(Item replacementItem, float durationSeconds) +{ + GetImpl(*this).ReplaceItem( replacementItem, durationSeconds ); +} + +void ItemView::ReplaceItems(const ItemContainer& replacementItems, float durationSeconds) +{ + GetImpl(*this).ReplaceItems( replacementItems, durationSeconds ); } } // namespace Toolkit -- 2.7.4