1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef UI_APP_LIST_PAGINATION_MODEL_H_ 6 #define UI_APP_LIST_PAGINATION_MODEL_H_ 7 8 #include "base/basictypes.h" 9 #include "base/compiler_specific.h" 10 #include "base/memory/scoped_ptr.h" 11 #include "base/observer_list.h" 12 #include "base/time/time.h" 13 #include "ui/app_list/app_list_export.h" 14 #include "ui/gfx/animation/animation_delegate.h" 15 16 namespace gfx { 17 class SlideAnimation; 18 } 19 20 namespace app_list { 21 22 class PaginationModelObserver; 23 24 // A simple pagination model that consists of two numbers: the total pages and 25 // the currently selected page. The model is a single selection model that at 26 // the most one page can become selected at any time. 27 class APP_LIST_EXPORT PaginationModel : public gfx::AnimationDelegate { 28 public: 29 // Holds info for transition animation and touch scroll. 30 struct Transition { TransitionTransition31 Transition(int target_page, double progress) 32 : target_page(target_page), 33 progress(progress) { 34 } 35 EqualsTransition36 bool Equals(const Transition& rhs) const { 37 return target_page == rhs.target_page && progress == rhs.progress; 38 } 39 40 // Target page for the transition or -1 if there is no target page. For 41 // page switcher, this is the target selected page. For touch scroll, 42 // this is usually the previous or next page (or -1 when there is no 43 // previous or next page). 44 int target_page; 45 46 // A [0, 1] progress indicates how much of the current page is being 47 // transitioned. 48 double progress; 49 }; 50 51 PaginationModel(); 52 virtual ~PaginationModel(); 53 54 void SetTotalPages(int total_pages); 55 56 // Selects a page. |animate| is true if the transition should be animated. 57 void SelectPage(int page, bool animate); 58 59 // Selects a page by relative |delta|. 60 void SelectPageRelative(int delta, bool animate); 61 62 // Immediately completes all queued animations, jumping directly to the final 63 // target page. 64 void FinishAnimation(); 65 66 void SetTransition(const Transition& transition); 67 void SetTransitionDurations(int duration_ms, int overscroll_duration_ms); 68 69 // Starts a scroll transition. If there is a running transition animation, 70 // cancels it but keeps the transition info. 71 void StartScroll(); 72 73 // Updates transition progress from |delta|. |delta| > 0 means transit to 74 // previous page (moving pages to the right). |delta| < 0 means transit 75 // to next page (moving pages to the left). 76 void UpdateScroll(double delta); 77 78 // Finishes the current scroll transition if |cancel| is false. Otherwise, 79 // reverses it. 80 void EndScroll(bool cancel); 81 82 // Returns true if current transition is being reverted. 83 bool IsRevertingCurrentTransition() const; 84 85 void AddObserver(PaginationModelObserver* observer); 86 void RemoveObserver(PaginationModelObserver* observer); 87 total_pages()88 int total_pages() const { return total_pages_; } selected_page()89 int selected_page() const { return selected_page_; } transition()90 const Transition& transition() const { return transition_; } 91 is_valid_page(int page)92 bool is_valid_page(int page) const { 93 return page >= 0 && page < total_pages_; 94 } 95 has_transition()96 bool has_transition() const { 97 return transition_.target_page != -1 || transition_.progress != 0; 98 } 99 100 // Gets the page that the animation will eventually land on. If there is no 101 // active animation, just returns selected_page(). 102 int SelectedTargetPage() const; 103 104 private: 105 void NotifySelectedPageChanged(int old_selected, int new_selected); 106 void NotifyTransitionStarted(); 107 void NotifyTransitionChanged(); 108 clear_transition()109 void clear_transition() { 110 SetTransition(Transition(-1, 0)); 111 } 112 113 // Calculates a target page number by combining current page and |delta|. 114 // When there is no transition, current page is the currently selected page. 115 // If there is a transition, current page is the transition target page or the 116 // pending transition target page. When current page + |delta| goes beyond 117 // valid range and |selected_page_| is at the range ends, invalid page number 118 // -1 or |total_pages_| is returned to indicate the situation. 119 int CalculateTargetPage(int delta) const; 120 121 void StartTransitionAnimation(const Transition& transition); 122 void ResetTransitionAnimation(); 123 124 // gfx::AnimationDelegate overrides: 125 virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; 126 virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE; 127 128 int total_pages_; 129 int selected_page_; 130 131 Transition transition_; 132 133 // Pending selected page when SelectedPage is called during a transition. If 134 // multiple SelectPage is called while a transition is in progress, only the 135 // last target page is remembered here. 136 int pending_selected_page_; 137 138 scoped_ptr<gfx::SlideAnimation> transition_animation_; 139 int transition_duration_ms_; // Transition duration in millisecond. 140 int overscroll_transition_duration_ms_; 141 142 int last_overscroll_target_page_; 143 base::TimeTicks last_overscroll_animation_start_time_; 144 145 ObserverList<PaginationModelObserver> observers_; 146 147 DISALLOW_COPY_AND_ASSIGN(PaginationModel); 148 }; 149 150 } // namespace app_list 151 152 #endif // UI_APP_LIST_PAGINATION_MODEL_H_ 153