summaryrefslogtreecommitdiff
path: root/chromium/ui/app_list/pagination_model.h
blob: 0546adc4bf894573f1d95ab5994e94d56eeed7d5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_APP_LIST_PAGINATION_MODEL_H_
#define UI_APP_LIST_PAGINATION_MODEL_H_

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
#include "ui/app_list/app_list_export.h"
#include "ui/gfx/animation/animation_delegate.h"

namespace gfx {
class SlideAnimation;
}

namespace app_list {

class PaginationModelObserver;

// A simple pagination model that consists of two numbers: the total pages and
// the currently selected page. The model is a single selection model that at
// the most one page can become selected at any time.
class APP_LIST_EXPORT PaginationModel : public gfx::AnimationDelegate {
 public:
  // Holds info for transition animation and touch scroll.
  struct Transition {
    Transition(int target_page, double progress)
        : target_page(target_page),
          progress(progress) {
    }

    bool Equals(const Transition& rhs) const {
      return target_page == rhs.target_page && progress == rhs.progress;
    }

    // Target page for the transition or -1 if there is no target page. For
    // page switcher, this is the target selected page. For touch scroll,
    // this is usually the previous or next page (or -1 when there is no
    // previous or next page).
    int target_page;

    // A [0, 1] progress indicates how much of the current page is being
    // transitioned.
    double progress;
  };

  PaginationModel();
  virtual ~PaginationModel();

  void SetTotalPages(int total_pages);

  // Selects a page. |animate| is true if the transition should be animated.
  void SelectPage(int page, bool animate);

  // Selects a page by relative |delta|.
  void SelectPageRelative(int delta, bool animate);

  void SetTransition(const Transition& transition);
  void SetTransitionDurations(int duration_ms, int overscroll_duration_ms);

  // Starts a scroll transition. If there is a running transition animation,
  // cancels it but keeps the transition info.
  void StartScroll();

  // Updates transition progress from |delta|. |delta| > 0 means transit to
  // previous page (moving pages to the right). |delta| < 0 means transit
  // to next page (moving pages to the left).
  void UpdateScroll(double delta);

  // Finishes the current scroll transition if |cancel| is false. Otherwise,
  // reverses it.
  void EndScroll(bool cancel);

  // Returns true if current transition is being reverted.
  bool IsRevertingCurrentTransition() const;

  void AddObserver(PaginationModelObserver* observer);
  void RemoveObserver(PaginationModelObserver* observer);

  int total_pages() const { return total_pages_; }
  int selected_page() const { return selected_page_; }
  const Transition& transition() const { return transition_; }

  bool is_valid_page(int page) const {
    return page >= 0 && page < total_pages_;
  }

  bool has_transition() const {
    return transition_.target_page != -1 || transition_.progress != 0;
  }

 private:
  void NotifySelectedPageChanged(int old_selected, int new_selected);
  void NotifyTransitionStarted();
  void NotifyTransitionChanged();

  void clear_transition() {
    SetTransition(Transition(-1, 0));
  }

  // Calculates a target page number by combining current page and |delta|.
  // When there is no transition, current page is the currently selected page.
  // If there is a transition, current page is the transition target page or the
  // pending transition target page. When current page + |delta| goes beyond
  // valid range and |selected_page_| is at the range ends, invalid page number
  // -1 or |total_pages_| is returned to indicate the situation.
  int CalculateTargetPage(int delta) const;

  void StartTransitionAnimation(const Transition& transition);
  void ResetTransitionAnimation();

  // gfx::AnimationDelegate overrides:
  virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
  virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;

  int total_pages_;
  int selected_page_;

  Transition transition_;

  // Pending selected page when SelectedPage is called during a transition. If
  // multiple SelectPage is called while a transition is in progress, only the
  // last target page is remembered here.
  int pending_selected_page_;

  scoped_ptr<gfx::SlideAnimation> transition_animation_;
  int transition_duration_ms_;  // Transition duration in millisecond.
  int overscroll_transition_duration_ms_;

  int last_overscroll_target_page_;
  base::TimeTicks last_overscroll_animation_start_time_;

  ObserverList<PaginationModelObserver> observers_;

  DISALLOW_COPY_AND_ASSIGN(PaginationModel);
};

}  // namespace app_list

#endif  // UI_APP_LIST_PAGINATION_MODEL_H_