summaryrefslogtreecommitdiffstats
path: root/ui/app_list/pagination_controller.cc
blob: 26494eb24a18901b59922f0ee9bb5efe91cf0dd5 (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
// Copyright 2014 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.

#include "ui/app_list/pagination_controller.h"

#include "ui/app_list/pagination_model.h"
#include "ui/events/event.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/vector2d.h"

namespace app_list {

namespace {

// Constants for dealing with scroll events.
const int kMinScrollToSwitchPage = 20;
const int kMinHorizVelocityToSwitchPage = 800;

const double kFinishTransitionThreshold = 0.33;

}  // namespace

PaginationController::PaginationController(PaginationModel* model,
                                           ScrollAxis scroll_axis)
    : pagination_model_(model), scroll_axis_(scroll_axis) {
}

bool PaginationController::OnScroll(const gfx::Vector2d& offset,
                                    ScrollEventType type) {
  int offset_magnitude;
  if (scroll_axis_ == SCROLL_AXIS_HORIZONTAL) {
    // If the view scrolls horizontally, both horizontal and vertical scroll
    // events are valid (since most mouse wheels only have vertical scrolling).
    offset_magnitude =
        abs(offset.x()) > abs(offset.y()) ? offset.x() : offset.y();
  } else {
    // If the view scrolls vertically, only vertical scroll events are valid.
    offset_magnitude = offset.y();
  }

  // Do not scroll on very small touchpad events. Mouse wheel events should
  // scroll, no matter how small the value change.
  if (type == SCROLL_MOUSE_WHEEL ||
      abs(offset_magnitude) > kMinScrollToSwitchPage) {
    if (!pagination_model_->has_transition()) {
      pagination_model_->SelectPageRelative(offset_magnitude > 0 ? -1 : 1,
                                            true);
    }
    return true;
  }

  return false;
}

bool PaginationController::OnGestureEvent(const ui::GestureEvent& event,
                                          const gfx::Rect& bounds) {
  const ui::GestureEventDetails& details = event.details();
  switch (event.type()) {
    case ui::ET_GESTURE_SCROLL_BEGIN:
      pagination_model_->StartScroll();
      return true;
    case ui::ET_GESTURE_SCROLL_UPDATE: {
      float scroll = scroll_axis_ == SCROLL_AXIS_HORIZONTAL
                         ? details.scroll_x()
                         : details.scroll_y();
      int width = scroll_axis_ == SCROLL_AXIS_HORIZONTAL ? bounds.width()
                                                         : bounds.height();
      // scroll > 0 means moving contents right or down. That is, transitioning
      // to the previous page.
      pagination_model_->UpdateScroll(scroll / width);
      return true;
    }
    case ui::ET_GESTURE_SCROLL_END:
      pagination_model_->EndScroll(pagination_model_->transition().progress <
                                   kFinishTransitionThreshold);
      return true;
    case ui::ET_SCROLL_FLING_START: {
      float velocity = scroll_axis_ == SCROLL_AXIS_HORIZONTAL
                           ? details.velocity_x()
                           : details.velocity_y();
      pagination_model_->EndScroll(true);
      if (fabs(velocity) > kMinHorizVelocityToSwitchPage)
        pagination_model_->SelectPageRelative(velocity < 0 ? 1 : -1, true);
      return true;
    }
    default:
      return false;
  }
}

}  // namespace app_list