More ItemView Insert/Remove/Replace APIs
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / scrollable / item-view / item-view-impl.h
1 #ifndef __DALI_TOOLKIT_INTERNAL_ITEM_VIEW_H__
2 #define __DALI_TOOLKIT_INTERNAL_ITEM_VIEW_H__
3
4 //
5 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
6 //
7 // Licensed under the Flora License, Version 1.0 (the License);
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //     http://floralicense.org/license/
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an AS IS BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19
20 // EXTERNAL INCLUDES
21 #include <dali/dali.h>
22 #include <map>
23
24 // INTERNAL INCLUDES
25 #include <dali-toolkit/public-api/controls/control-impl.h>
26 #include <dali-toolkit/public-api/controls/scrollable/item-view/item-view.h>
27 #include <dali-toolkit/public-api/controls/scrollable/item-view/item-layout.h>
28 #include <dali-toolkit/public-api/controls/scrollable/scroll-connector.h>
29 #include <dali-toolkit/internal/controls/scrollable/scrollable-impl.h>
30 #include <dali-toolkit/public-api/focus-manager/keyboard-focus-manager.h>
31 #include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-overshoot-indicator-impl.h>
32
33 namespace Dali
34 {
35
36 namespace Toolkit
37 {
38
39 namespace Internal
40 {
41
42 class ItemView;
43
44 typedef IntrusivePtr<ItemView> ItemViewPtr;
45
46 /**
47  * ItemView is a scrollable layout container.
48  * Multiple ItemLayouts may be provided, to determine the logical position of each item a layout.
49  * Actor-ID pairs are provided from a shared ItemFactory, to display the currently visible items.
50  */
51 class ItemView : public Scrollable
52 {
53 public:
54
55   /**
56    * Create a new ItemView.
57    * @param[in] factory The factory which provides ItemView with items.
58    * @return A public handle to the newly allocated ItemView.
59    */
60   static Dali::Toolkit::ItemView New(ItemFactory& factory);
61
62   /**
63    * @copydoc Toolkit::ItemView::GetScrollConnector
64    */
65   Dali::Toolkit::ScrollConnector GetScrollConnector() const;
66
67   /**
68    * @copydoc Toolkit::ItemView::GetLayoutCount
69    */
70   unsigned int GetLayoutCount() const;
71
72   /**
73    * @copydoc Toolkit::ItemView::AddLayout
74    */
75   void AddLayout(ItemLayout& layout);
76
77   /**
78    * @copydoc Toolkit::ItemView::RemoveLayout
79    */
80   void RemoveLayout(unsigned int layoutIndex);
81
82   /**
83    * @copydoc Toolkit::ItemView::GetLayout
84    */
85   ItemLayoutPtr GetLayout(unsigned int layoutIndex) const;
86
87   /**
88    * @copydoc Toolkit::ItemView::GetActiveLayout
89    */
90   ItemLayoutPtr GetActiveLayout() const;
91
92   /**
93    * @copydoc Toolkit::ItemView::GetCurrentLayoutPosition
94    */
95   float GetCurrentLayoutPosition(unsigned int itemId) const;
96
97   /**
98    * @copydoc Toolkit::ItemView::ActivateLayout
99    */
100   void ActivateLayout(unsigned int layoutIndex, const Vector3& targetSize, float durationSeconds);
101
102   /**
103    * @copydoc Toolkit::ItemView::DeactivateCurrentLayout
104    */
105   void DeactivateCurrentLayout();
106
107   /**
108    * @copydoc Toolkit::ItemView::SetMinimumSwipeSpeed
109    */
110   void SetMinimumSwipeSpeed(float speed);
111
112   /**
113    * @copydoc Toolkit::ItemView::GetMinimumSwipeSpeed
114    */
115   float GetMinimumSwipeSpeed() const;
116
117   /**
118    * @copydoc Toolkit::ItemView::SetMinimumSwipeDistance
119    */
120   void SetMinimumSwipeDistance(float distance);
121
122   /**
123    * @copydoc Toolkit::ItemView::GetMinimumSwipeDistance
124    */
125   float GetMinimumSwipeDistance() const;
126
127   /**
128    * @copydoc Toolkit::ItemView::SetMouseWheelScrollDistanceStep
129    */
130   void SetMouseWheelScrollDistanceStep(float step);
131
132   /**
133    * @copydoc Toolkit::ItemView::GetMouseWheelScrollDistanceStep
134    */
135   float GetMouseWheelScrollDistanceStep() const;
136
137   /**
138    * @copydoc Toolkit::ItemView::SetAnchoring
139    */
140   void SetAnchoring(bool enabled);
141
142   /**
143    * @copydoc Toolkit::ItemView::GetAnchoring
144    */
145   bool GetAnchoring() const;
146
147   /**
148    * @copydoc Toolkit::ItemView::SetAnchoringDuration
149    */
150   void SetAnchoringDuration(float durationSeconds);
151
152   /**
153    * @copydoc Toolkit::ItemView::GetAnchoringDuration
154    */
155   float GetAnchoringDuration() const;
156
157   /**
158    * @copydoc Toolkit::ItemView::ScrollToItem
159    */
160   void ScrollToItem(unsigned int itemId, float durationSeconds);
161
162   /**
163    * @copydoc Toolkit::ItemView::SetRefreshInterval
164    */
165   void SetRefreshInterval(unsigned int intervalMilliseconds);
166
167   /**
168    * @copydoc Toolkit::ItemView::GetRefreshInterval
169    */
170   unsigned int GetRefreshInterval() const;
171
172   /**
173    * @copydoc Toolkit::ItemView::GetItem
174    */
175   Actor GetItem(unsigned int itemId) const;
176
177   /**
178    * @copydoc Toolkit::ItemView::GetItemId
179    */
180   unsigned int GetItemId(Actor actor) const;
181
182   /**
183    * @copydoc Toolkit::ItemView::InsertItem
184    */
185   void InsertItem(Item newItem, float durationSeconds);
186
187   /**
188    * @copydoc Toolkit::ItemView::InsertItem
189    */
190   void InsertItems(const ItemContainer& newItems, float durationSeconds);
191
192   /**
193    * @copydoc Toolkit::ItemView::RemoveItem
194    */
195   void RemoveItem(ItemId itemId, float durationSeconds);
196
197   /**
198    * @copydoc Toolkit::ItemView::InsertItem
199    */
200   void RemoveItems(const ItemIdContainer& itemIds, float durationSeconds);
201
202   /**
203    * @copydoc Toolkit::ItemView::InsertItem
204    */
205   void ReplaceItem(Item replacementItem, float durationSeconds);
206
207   /**
208    * @copydoc Toolkit::ItemView::InsertItem
209    */
210   void ReplaceItems(const ItemContainer& replacementItems, float durationSeconds);
211
212   /**
213    * @copydoc Toolkit::Scrollable::GetDomainSize
214    */
215   Vector3 GetDomainSize() const;
216
217   /**
218    * @copydoc Toolkit::Scrollable::GetCurrentScrollPosition
219    */
220   Vector3 GetCurrentScrollPosition() const;
221
222   /**
223    * @copydoc Toolkit::Scrollable::AddOverlay()
224    */
225   void AddOverlay(Actor actor);
226
227   /**
228    * @copydoc Toolkit::Scrollable::RemoveOverlay()
229    */
230   void RemoveOverlay(Actor actor);
231
232   /**
233    * @copydoc Toolkit::Scrollable::ScrollTo(const Vector3& position, float duration)
234    */
235   void ScrollTo(const Vector3& position, float duration);
236
237 private:
238
239   /**
240    * Remove an Actor if found in the ItemPool.
241    * @param[in] itemId The item to remove.
242    * @return True if an actor was removed.
243    */
244   bool RemoveActor( unsigned int itemId );
245
246   /**
247    * Remove any Actors outside a given range.
248    * @param[in] @param[in] range The range of required items.
249    */
250   void RemoveActorsOutsideRange( ItemRange range );
251
252   /**
253    * Add a range of Actors, if they are not already in the ItemPool.
254    * @param[in] layout The active layout.
255    * @param[in] range The range of Item IDs to associate with the new actors.
256    */
257   void AddActorsWithinRange( ItemRange range );
258
259   /**
260    * Add a new Actor, if not already in the ItemPool.
261    * @param[in] item The ID for the new item.
262    */
263   void AddNewActor( ItemId item );
264
265   /**
266    * Apply the constraints etc. that are required for ItemView children.
267    * @param[in] item The item to setup.
268    * @param[in] durationSeconds The time taken to fully constrain the actor.
269    */
270   void SetupActor( Item item, float durationSeconds );
271
272 private: // From CustomActorImpl
273
274   /**
275    * From CustomActorImpl; called after a touch-signal is received by the owning actor.
276    * @param[in] event The touch event.
277    * @return True if the event should be consumed.
278    */
279   virtual bool OnTouchEvent(const TouchEvent& event);
280
281   /**
282    * From CustomActorImpl; called after a mouse-wheel-event is received by the owning actor.
283    * @param[in] event The mouse wheel event.
284    * @return True if the event should be consumed.
285    */
286   virtual bool OnMouseWheelEvent(const MouseWheelEvent& event);
287
288 private: // From ControlImpl
289
290   /**
291    * @copydoc Toolkit::Control::OnInitialize()
292    */
293   virtual void OnInitialize();
294
295   /**
296    * @copydoc Toolkit::Control::OnAccessibilityPan()
297    */
298   virtual bool OnAccessibilityPan(PanGesture gesture);
299
300   /**
301    * @copydoc Toolkit::Control::GetNextKeyboardFocusableActor()
302    */
303   virtual Actor GetNextKeyboardFocusableActor(Actor actor, Control::KeyboardFocusNavigationDirection direction, bool loopEnabled);
304
305   /**
306    * @copydoc Toolkit::Control::OnKeyboardFocusChangeCommitted()
307    */
308   virtual void OnKeyboardFocusChangeCommitted(Actor commitedFocusableActor);
309
310 protected:
311
312   /**
313    * Construct a new ItemView.
314    * @param[in] factory The factory which provides ItemView with items.
315    */
316   ItemView(ItemFactory& factory);
317
318   /**
319    * A reference counted object may only be deleted by calling Unreference()
320    */
321   virtual ~ItemView();
322
323 private:
324
325   // Undefined
326   ItemView(const ItemView&);
327
328   // Undefined
329   ItemView& operator=(const ItemView& rhs);
330
331   /**
332    * Helper to apply constraints to an actor.
333    * @param[in] actor The actor to constrain.
334    * @param[in] layout The active layout.
335    * @param[in] itemId The ID of the item represented by the actor.
336    * @param[in] durationSeconds The time taken to fully constrain the actors.
337    */
338   void ApplyConstraints(Actor& actor, ItemLayout& layout, unsigned int itemId, float durationSeconds);
339
340   /**
341    * Helper to re-apply all the constraints after items have been inserted, removed etc.
342    * @param[in] durationSeconds The time taken to fully constrain the actors.
343    */
344   void ReapplyAllConstraints( float durationSeconds );
345
346   /**
347    * Helper to remove items outside a given range.
348    * @param[in] range The range of required items.
349    */
350   void RemoveItems(ItemRange range);
351
352   /**
353    * Helper to add a range of items, if not already in the ItemPool.
354    * @param[in] layout The layout used to position the new items.
355    * @param[in] layoutSize The current size of the layout.
356    * @param[in] range The range of required items.
357    */
358   void AddItems(ItemLayout& layout, const Vector3& layoutSize, ItemRange range);
359
360   /**
361    * Helper to find the range of items to populate with.
362    * @param[in] layout The current layout.
363    * @param[in] range The range of items.
364    * @param[in] reserveExtra True if reserve items should be included.
365    */
366   ItemRange GetItemRange(ItemLayout& layout, const Vector3& layoutSize, bool reserveExtra);
367
368   // Input Handling
369
370   /**
371    * Helper to handle pressed (Down) events.
372    * @param[in] x The X coordinate of the touch event.
373    * @param[in] y The Y coordinate of the touch event.
374    * @param[in] timeMs The time-stamp of the touch event.
375    */
376   void OnPressed(float x, float y, unsigned long timeMs);
377
378   /**
379    * Helper to clamp the first-item position when dragging/swiping.
380    * @param[in] targetPosition The target position of the drag etc.
381    * @param[in] targetSize The target ItemView & layout size.
382    * @param[in] layout The current layout.
383    * @return The clamped first-item position.
384    */
385   float ClampFirstItemPosition(float targetPosition, const Vector3& targetSize, ItemLayout& layout);
386
387   /**
388    * Called upon pan gesture event.
389    *
390    * @param[in] gesture The gesture event.
391    */
392   void OnPan(PanGesture pan);
393
394   /**
395    * Helper to handle anchoring animations.
396    * @return The animation, or an uninitialized handle if not necessary.
397    */
398   Animation DoAnchoring();
399
400   /**
401    * Callback from scroll animations
402    * @param[in] animation The scroll-animation which has finished.
403    */
404   void OnScrollFinished(Animation& animation);
405
406   /**
407    * Called by animation system when overshoot has finished animating to maximum (either -1.0f or 1.0f)
408    *
409    * @param[in] animation the animation that has finished
410    */
411   void OnOvershootOnFinished(Animation& animation);
412
413   /**
414    * Helper to start the refresh timer.
415    */
416   void StartRefreshTimer();
417
418   /**
419    * Helper to cancel the refresh timer.
420    */
421   void CancelRefreshTimer();
422
423   /**
424    * Refresh the ItemView; this is called after a timeout when scrolling.
425    * During a refresh, ItemFactory::NewItem() will be called to create newly visible items.
426    * @return True if the refresh timer should be kept running.
427    */
428   bool OnRefreshTick();
429
430   /**
431    * This is called after a timeout when no new mouse wheel event is received for a certain period of time.
432    * @return will return false; one-shot timer.
433    */
434   bool OnMouseWheelEventFinished();
435
436   /**
437    * Stops and removes animation if exists.
438    * @param[in,out] animation The animation handle to be removed.
439    */
440   void RemoveAnimation(Animation& animation);
441
442   /**
443    * Helper to apply constraints to the overshoot overlay actor.
444    */
445   void ApplyOvershootOverlayConstraints();
446
447   /**
448    * Helper to calculate the scroll overshoot according to the pan gesture displacement.
449    * @return The scroll overshoot.
450    */
451   float CalculateScrollOvershoot();
452
453   /**
454    * Helper to calculate the scroll overshoot according to the pan gesture displacement.
455    *
456    * @param[in] overshootAmount amount to animate to
457    * @param[in] animateBack whether to animate back to zero immediately after
458    * @return The scroll overshoot.
459    */
460   void AnimateScrollOvershoot(float overshootAmount, bool animateBack = false);
461
462   /**
463    * Gets the scroll position in pixels according to the logical layout position.
464    * @param[in] layoutSize The current size of the layout.
465    */
466   float GetScrollPosition(float layoutPosition, const Vector3& layoutSize) const;
467
468   /**
469    * Calculates the minimum and maximum positions for each axis to scroll to.
470    * @param[in] layoutSize The current size of the layout.
471    */
472   void CalculateDomainSize(const Vector3& layoutSize);
473
474   /**
475    * Calculates whether we want to allow current item view to scroll.
476    * @param[in] layoutSize The current size of the layout.
477    * @return    true if itemview is scrollable
478    */
479   bool IsLayoutScrollable(const Vector3& layoutSize);
480
481 private:
482
483   ItemFactory& mItemFactory;
484
485   typedef std::map<unsigned int, Actor> ItemPool;
486   typedef ItemPool::iterator            ItemPoolIter;
487   typedef ItemPool::const_iterator      ConstItemPoolIter;
488
489   ItemPool mItemPool;
490
491   ItemLayoutContainer mLayouts;
492   ItemLayout* mActiveLayout;
493   Vector3 mActiveLayoutTargetSize;
494
495   Animation mResizeAnimation;
496   Animation mScrollAnimation;
497   Animation mScrollSpeedAnimation;
498   Animation mScrollOvershootAnimation;
499   bool      mAnimatingOvershootOn;          ///< whether we are currently animating overshoot to 1.0f/-1.0f (on) or to 0.0f (off)
500   bool      mAnimateOvershootOff;         ///< whether we are currently animating overshoot to 1.0f/-1.0f (on) or to 0.0f (off)
501
502   bool mAnchoringEnabled;
503   float mAnchoringDuration;
504
505   Timer mRefreshTimer;
506   int mRefreshIntervalMilliseconds;
507   bool mRefreshOrderHint; ///< True if scrolling towards the last item
508
509   // Input handling
510
511   float mMinimumSwipeSpeed;
512   float mMinimumSwipeDistance;
513   float mMouseWheelScrollDistanceStep; ///< The step of scroll distance in actor coordinates for each mouse wheel event received.
514
515   float mScrollDistance;
516   float mScrollSpeed;
517   Vector2 mTotalPanDisplacement;
518
519   float mScrollOvershoot;
520   bool mIsFlicking;
521
522   Timer mMouseWheelEventFinishedTimer; ///< The timer to determine whether there is no mouse wheel event received for a certain period of time.
523
524   Dali::Gesture::State mGestureState;
525
526   ImageActor mOvershootOverlay;           ///< The overlay actor for overshoot effect
527   OvershootRippleEffect mOvershootEffect; ///< The vertex/fragment shader used to display the overshoot ripple effect
528
529   Dali::Toolkit::ScrollConnector mScrollConnector; ///< Connects ItemView with scrollable components e.g. scroll bars
530   Constrainable   mScrollPositionObject;     ///< From mScrollConnector
531
532   Property::Index mPropertyPosition; ///< The physical position of the first item within the layout
533   Property::Index mPropertyMinimumLayoutPosition; ///< The minimum valid layout position in the layout.
534   Property::Index mPropertyScrollSpeed; ///< The current scroll speed of item view
535   Property::Index mPropertyOvershoot; ///< The scroll overshoot (difference of the layout position before and after clamping)
536 };
537
538 } // namespace Internal
539
540 // Helpers for public-api forwarding methods
541
542 inline Toolkit::Internal::ItemView& GetImpl(Toolkit::ItemView& itemView)
543 {
544   DALI_ASSERT_ALWAYS(itemView);
545
546   Dali::RefObject& handle = itemView.GetImplementation();
547
548   return static_cast<Toolkit::Internal::ItemView&>(handle);
549 }
550
551 inline const Toolkit::Internal::ItemView& GetImpl(const Toolkit::ItemView& itemView)
552 {
553   DALI_ASSERT_ALWAYS(itemView);
554
555   const Dali::RefObject& handle = itemView.GetImplementation();
556
557   return static_cast<const Toolkit::Internal::ItemView&>(handle);
558 }
559
560 } // namespace Toolkit
561
562 } // namespace Dali
563
564 #endif // __DALI_TOOLKIT_INTERNAL_ITEM_VIEW_H__