//
#include <dali-toolkit/internal/controls/scroll-bar/scroll-bar-impl.h>
+#include <dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h>
using namespace Dali;
const float DEFAULT_SLIDER_DEPTH(1.0f);
const float INDICATOR_SHOW_TIME(0.5f);
const float INDICATOR_HIDE_TIME(0.5f);
+const float DEFAULT_PAN_GESTURE_PROCESS_TIME(16.7f); // 16.7 milliseconds, i.e. one frame
/**
* Indicator size constraint
}
ScrollBar::ScrollBar()
-: mScrollStart(0.0f)
+: mScrollStart(0.0f),
+ mIsPanning(false),
+ mCurrentScrollPosition(0.0f)
{
}
mAnimation.Play();
}
+bool ScrollBar::OnPanGestureProcessTick()
+{
+ // Update the scroll position property.
+ mScrollPositionObject.SetProperty( Toolkit::ScrollConnector::SCROLL_POSITION, mCurrentScrollPosition );
+
+ Dali::Toolkit::ItemView itemView = Dali::Toolkit::ItemView::DownCast(Self().GetParent());
+ if(itemView)
+ {
+ // Refresh ItemView immediately when the scroll position is changed.
+ GetImpl(itemView).DoRefresh(mCurrentScrollPosition, false); // No need to cache extra items.
+ }
+
+ return true;
+}
+
void ScrollBar::OnPan( PanGesture gesture )
{
if(mScrollPositionObject)
{
case Gesture::Started:
{
+ if( !mTimer )
+ {
+ // Make sure the pan gesture is only being processed once per frame.
+ mTimer = Timer::New( DEFAULT_PAN_GESTURE_PROCESS_TIME );
+ mTimer.TickSignal().Connect( this, &ScrollBar::OnPanGestureProcessTick );
+ mTimer.Start();
+ }
+
Show();
mScrollStart = mScrollPositionObject.GetProperty<float>( Toolkit::ScrollConnector::SCROLL_POSITION );
mGestureDisplacement = Vector3::ZERO;
+ mIsPanning = true;
+
break;
}
case Gesture::Continuing:
Vector3 span = Self().GetCurrentSize() - mIndicator.GetCurrentSize();
const float domainSize = fabs(mScrollConnector.GetMaxLimit() - mScrollConnector.GetMinLimit());
- float position = mScrollStart - mGestureDisplacement.y * domainSize / span.y;
- position = std::min(mScrollConnector.GetMaxLimit(), std::max(position, mScrollConnector.GetMinLimit()));
- mScrollPositionObject.SetProperty( Toolkit::ScrollConnector::SCROLL_POSITION, position );
+ mCurrentScrollPosition = mScrollStart - mGestureDisplacement.y * domainSize / span.y;
+ mCurrentScrollPosition = std::min(mScrollConnector.GetMaxLimit(), std::max(mCurrentScrollPosition, mScrollConnector.GetMinLimit()));
+
break;
}
default:
{
+ mIsPanning = false;
+
+ if( mTimer )
+ {
+ // Destroy the timer when pan gesture is finished.
+ mTimer.Stop();
+ mTimer.TickSignal().Disconnect( this, &ScrollBar::OnPanGestureProcessTick );
+ mTimer.Reset();
+ }
+
break;
}
}
+
+ Dali::Toolkit::ItemView itemView = Dali::Toolkit::ItemView::DownCast(Self().GetParent());
+ if(itemView)
+ {
+ // Disable automatic refresh in ItemView during fast scrolling
+ GetImpl(itemView).SetRefreshEnabled(!mIsPanning);
+ }
}
}
*/
void OnScrollPositionNotified(PropertyNotification& source);
+ /**
+ * Process the pan gesture per predefined timeout until the gesture is finished.
+ * @return True if the timer should be kept running.
+ */
+ bool OnPanGestureProcessTick();
+
private:
Constrainable mScrollPositionObject; ///< From mScrollConnector
ImageActor mIndicator; ///< Image of scroll indicator.
Animation mAnimation; ///< Scroll indicator Show/Hide Animation.
- float mScrollStart; ///< Scroll Start position (start of drag)
+ float mScrollStart; ///< Scroll Start position (start of drag)
Vector3 mGestureDisplacement; ///< Gesture Displacement.
+ bool mIsPanning; ///< Whether the scroll bar is being panned.
+ float mCurrentScrollPosition; ///< The current scroll position updated by the pan gesture
+
+ Timer mTimer; ///< The timer to process the pan gesture after the gesture is started.
+
Property::Index mPropertyIndicatorPosition; ///< Indicatore Position ("indicator-position")
PropertyNotification mPositionNotification; ///< Stores the property notification used for scroll position changes
mScrollOvershoot(0.0f),
mIsFlicking(false),
mGestureState(Gesture::Clear),
- mAddingItems(false)
+ mAddingItems(false),
+ mRefreshEnabled(true)
{
SetRequiresMouseWheelEvents(true);
SetKeyboardNavigationSupport(true);
}
// Refresh the new layout
- ItemRange range = GetItemRange(*mActiveLayout, targetSize, true/*reserve extra*/);
+ ItemRange range = GetItemRange(*mActiveLayout, targetSize, GetCurrentLayoutPosition(0), true/*reserve extra*/);
AddActorsWithinRange( range, durationSeconds );
// Scroll to an appropriate layout position
void ItemView::OnRefreshNotification(PropertyNotification& source)
{
+ if(mRefreshEnabled)
+ {
+ // Only refresh the cache during normal scrolling
+ DoRefresh(GetCurrentLayoutPosition(0), true);
+ }
+}
+
+void ItemView::DoRefresh(float currentLayoutPosition, bool cacheExtra)
+{
if (mActiveLayout)
{
- ItemRange range = GetItemRange(*mActiveLayout, mActiveLayoutTargetSize, true/*reserve extra*/);
+ ItemRange range = GetItemRange(*mActiveLayout, mActiveLayoutTargetSize, currentLayoutPosition, cacheExtra/*reserve extra*/);
RemoveActorsOutsideRange( range );
AddActorsWithinRange( range, 0.0f/*immediate*/ );
- Vector3 currentScrollPosition = GetCurrentScrollPosition();
- mScrollUpdatedSignalV2.Emit( currentScrollPosition );
+ mScrollUpdatedSignalV2.Emit( Vector3(0.0f, currentLayoutPosition, 0.0f) );
}
}
return mRefreshIntervalLayoutPositions;
}
+void ItemView::SetRefreshEnabled(bool enabled)
+{
+ mRefreshEnabled = enabled;
+}
+
Actor ItemView::GetItem(unsigned int itemId) const
{
Actor actor;
}
}
-ItemRange ItemView::GetItemRange(ItemLayout& layout, const Vector3& layoutSize, bool reserveExtra)
+ItemRange ItemView::GetItemRange(ItemLayout& layout, const Vector3& layoutSize, float layoutPosition, bool reserveExtra)
{
unsigned int itemCount = mItemFactory.GetNumberOfItems();
ItemRange available(0u, itemCount);
- ItemRange range = layout.GetItemsWithinArea( GetCurrentLayoutPosition(0), layoutSize );
+ ItemRange range = layout.GetItemsWithinArea( layoutPosition, layoutSize );
if (reserveExtra)
{
*/
void ScrollTo(const Vector3& position, float duration);
+ /**
+ * @brief Set whether to enable automatic refresh or not. When refresh is disabled,
+ * ItemView will not automatically refresh the cache in the given interval when the
+ * layout position is changed. This is useful in some cases, for example, automatic
+ * refresh is not needed during fast scrolling, otherwise it will cache unneeded
+ * items when the layout position changes quickly.
+ *
+ * @param[in] enabled True to enable automatic refresh or false to disable it.
+ */
+ void SetRefreshEnabled(bool enabled);
+
+ /**
+ * @brief Helper to perform the refresh.
+ *
+ * @param[in] currentLayoutPosition The current layout position.
+ * @param[in] cacheExtra Whether to cache extra items during refresh.
+ */
+ void DoRefresh(float currentLayoutPosition, bool cacheExtra);
+
private:
/**
* @param[in] range The range of items.
* @param[in] reserveExtra True if reserve items should be included.
*/
- ItemRange GetItemRange(ItemLayout& layout, const Vector3& layoutSize, bool reserveExtra);
+ ItemRange GetItemRange(ItemLayout& layout, const Vector3& layoutSize, float layoutPosition, bool reserveExtra);
// Input Handling
Property::Index mPropertyPosition; ///< The physical position of the first item within the layout
Property::Index mPropertyMinimumLayoutPosition; ///< The minimum valid layout position in the layout.
Property::Index mPropertyScrollSpeed; ///< The current scroll speed of item view
+
+ bool mRefreshEnabled; ///< Whether to refresh the cache automatically
};
} // namespace Internal
int firstVisibleItem = -(static_cast<int>(firstItemPosition / mImpl->mNumberOfColumns)) * mImpl->mNumberOfColumns;
int firstItemIndex = std::max(0, firstVisibleItem - static_cast<int>(mImpl->mNumberOfColumns));
- int lastItemIndex = std::max(0, firstVisibleItem + (itemsPerPage - 1));
+ int lastItemIndex = std::max(0, firstVisibleItem + itemsPerPage);
return ItemRange(firstItemIndex, lastItemIndex);
}