1// Copyright 2014 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#include "ui/app_list/pagination_controller.h"
6
7#include "ui/app_list/pagination_model.h"
8#include "ui/events/event.h"
9#include "ui/gfx/geometry/rect.h"
10#include "ui/gfx/geometry/vector2d.h"
11
12namespace app_list {
13
14namespace {
15
16// Constants for dealing with scroll events.
17const int kMinScrollToSwitchPage = 20;
18const int kMinHorizVelocityToSwitchPage = 800;
19
20const double kFinishTransitionThreshold = 0.33;
21
22}  // namespace
23
24PaginationController::PaginationController(PaginationModel* model,
25                                           ScrollAxis scroll_axis)
26    : pagination_model_(model), scroll_axis_(scroll_axis) {
27}
28
29bool PaginationController::OnScroll(const gfx::Vector2d& offset) {
30  int offset_magnitude;
31  if (scroll_axis_ == SCROLL_AXIS_HORIZONTAL) {
32    // If the view scrolls horizontally, both horizontal and vertical scroll
33    // events are valid (since most mouse wheels only have vertical scrolling).
34    offset_magnitude =
35        abs(offset.x()) > abs(offset.y()) ? offset.x() : offset.y();
36  } else {
37    // If the view scrolls vertically, only vertical scroll events are valid.
38    offset_magnitude = offset.y();
39  }
40
41  if (abs(offset_magnitude) > kMinScrollToSwitchPage) {
42    if (!pagination_model_->has_transition()) {
43      pagination_model_->SelectPageRelative(offset_magnitude > 0 ? -1 : 1,
44                                            true);
45    }
46    return true;
47  }
48
49  return false;
50}
51
52bool PaginationController::OnGestureEvent(const ui::GestureEvent& event,
53                                          const gfx::Rect& bounds) {
54  const ui::GestureEventDetails& details = event.details();
55  switch (event.type()) {
56    case ui::ET_GESTURE_SCROLL_BEGIN:
57      pagination_model_->StartScroll();
58      return true;
59    case ui::ET_GESTURE_SCROLL_UPDATE: {
60      float scroll = scroll_axis_ == SCROLL_AXIS_HORIZONTAL
61                         ? details.scroll_x()
62                         : details.scroll_y();
63      int width = scroll_axis_ == SCROLL_AXIS_HORIZONTAL ? bounds.width()
64                                                         : bounds.height();
65      // scroll > 0 means moving contents right or down. That is, transitioning
66      // to the previous page.
67      pagination_model_->UpdateScroll(scroll / width);
68      return true;
69    }
70    case ui::ET_GESTURE_SCROLL_END:
71      pagination_model_->EndScroll(pagination_model_->transition().progress <
72                                   kFinishTransitionThreshold);
73      return true;
74    case ui::ET_SCROLL_FLING_START: {
75      float velocity = scroll_axis_ == SCROLL_AXIS_HORIZONTAL
76                           ? details.velocity_x()
77                           : details.velocity_y();
78      pagination_model_->EndScroll(true);
79      if (fabs(velocity) > kMinHorizVelocityToSwitchPage)
80        pagination_model_->SelectPageRelative(velocity < 0 ? 1 : -1, true);
81      return true;
82    }
83    default:
84      return false;
85  }
86}
87
88}  // namespace app_list
89