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/base/animation/animation_delegate.h"
     15 
     16 namespace ui {
     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 ui::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   void SetTransition(const Transition& transition);
     63   void SetTransitionDurations(int duration_ms, int overscroll_duration_ms);
     64 
     65   // Starts a scroll transition. If there is a running transition animation,
     66   // cancels it but keeps the transition info.
     67   void StartScroll();
     68 
     69   // Updates transition progress from |delta|. |delta| > 0 means transit to
     70   // previous page (moving pages to the right). |delta| < 0 means transit
     71   // to next page (moving pages to the left).
     72   void UpdateScroll(double delta);
     73 
     74   // Finishes the current scroll transition if |cancel| is false. Otherwise,
     75   // reverses it.
     76   void EndScroll(bool cancel);
     77 
     78   // Returns true if current transition is being reverted.
     79   bool IsRevertingCurrentTransition() const;
     80 
     81   void AddObserver(PaginationModelObserver* observer);
     82   void RemoveObserver(PaginationModelObserver* observer);
     83 
     84   int total_pages() const { return total_pages_; }
     85   int selected_page() const { return selected_page_; }
     86   const Transition& transition() const { return transition_; }
     87 
     88   bool is_valid_page(int page) const {
     89     return page >= 0 && page < total_pages_;
     90   }
     91 
     92   bool has_transition() const {
     93     return transition_.target_page != -1 || transition_.progress != 0;
     94   }
     95 
     96  private:
     97   void NotifySelectedPageChanged(int old_selected, int new_selected);
     98   void NotifyTransitionStarted();
     99   void NotifyTransitionChanged();
    100 
    101   void clear_transition() {
    102     SetTransition(Transition(-1, 0));
    103   }
    104 
    105   // Calculates a target page number by combining current page and |delta|.
    106   // When there is no transition, current page is the currently selected page.
    107   // If there is a transition, current page is the transition target page or the
    108   // pending transition target page. When current page + |delta| goes beyond
    109   // valid range and |selected_page_| is at the range ends, invalid page number
    110   // -1 or |total_pages_| is returned to indicate the situation.
    111   int CalculateTargetPage(int delta) const;
    112 
    113   void StartTransitionAnimation(const Transition& transition);
    114   void ResetTransitionAnimation();
    115 
    116   // ui::AnimationDelegate overrides:
    117   virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE;
    118   virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE;
    119 
    120   int total_pages_;
    121   int selected_page_;
    122 
    123   Transition transition_;
    124 
    125   // Pending selected page when SelectedPage is called during a transition. If
    126   // multiple SelectPage is called while a transition is in progress, only the
    127   // last target page is remembered here.
    128   int pending_selected_page_;
    129 
    130   scoped_ptr<ui::SlideAnimation> transition_animation_;
    131   int transition_duration_ms_;  // Transition duration in millisecond.
    132   int overscroll_transition_duration_ms_;
    133 
    134   int last_overscroll_target_page_;
    135   base::TimeTicks last_overscroll_animation_start_time_;
    136 
    137   ObserverList<PaginationModelObserver> observers_;
    138 
    139   DISALLOW_COPY_AND_ASSIGN(PaginationModel);
    140 };
    141 
    142 }  // namespace app_list
    143 
    144 #endif  // UI_APP_LIST_PAGINATION_MODEL_H_
    145