Home | History | Annotate | Download | only in app_list
      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 {
     31     Transition(int target_page, double progress)
     32         : target_page(target_page),
     33           progress(progress) {
     34     }
     35 
     36     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 
     88   int total_pages() const { return total_pages_; }
     89   int selected_page() const { return selected_page_; }
     90   const Transition& transition() const { return transition_; }
     91 
     92   bool is_valid_page(int page) const {
     93     return page >= 0 && page < total_pages_;
     94   }
     95 
     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 
    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