Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ios / chrome / browser / ui / side_swipe_gesture_recognizer.mm
blobbc145f3acc296d1c5e31a63ba1cc2101a2c42834
1 // Copyright 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.
5 #import "ios/chrome/browser/ui/side_swipe_gesture_recognizer.h"
7 #include <cmath>
9 #include "base/logging.h"
11 namespace {
13 // The absolute maximum swipe angle from |x = y| for a swipe to begin.
14 const CGFloat kMaxSwipeYAngle = 65;
15 // The distance between touches for a swipe to begin.
16 const CGFloat kMinSwipeXThreshold = 4;
18 }  // namespace
20 @implementation SideSwipeGestureRecognizer {
21   // Expected direction of the swipe, based on starting point.
22   UISwipeGestureRecognizerDirection _direction;
25 @synthesize swipeEdge = _swipeEdge;
26 @synthesize direction = _direction;
27 @synthesize swipeOffset = _swipeOffset;
28 @synthesize startPoint = _startPoint;
30 // To quickly avoid interference with other gesture recognizers, fail
31 // immediately if the touches aren't at the edge of the touched view.
32 - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
33   [super touchesBegan:touches withEvent:event];
35   // Don't interrupt gestures in progress.
36   if (self.state != UIGestureRecognizerStatePossible)
37     return;
39   UITouch* touch = [[event allTouches] anyObject];
40   CGPoint location = [touch locationInView:self.view];
41   if (_swipeEdge > 0) {
42     if (location.x > _swipeEdge &&
43         location.x < CGRectGetMaxX([self.view bounds]) - _swipeEdge) {
44       self.state = UIGestureRecognizerStateFailed;
45     } else {
46       if (location.x < _swipeEdge) {
47         _direction = UISwipeGestureRecognizerDirectionRight;
48       } else {
49         _direction = UISwipeGestureRecognizerDirectionLeft;
50       }
51       _startPoint = location;
52     }
53   } else {
54     _startPoint = location;
55     _direction = 0;
56   }
59 - (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
60   // Revert to normal pan gesture recognizer characteristics after state began.
61   if (self.state != UIGestureRecognizerStatePossible) {
62     [super touchesMoved:touches withEvent:event];
63     return;
64   }
66   // Only one touch.
67   if ([[event allTouches] count] > 1) {
68     self.state = UIGestureRecognizerStateFailed;
69     return;
70   }
72   // Don't swipe at an angle greater than |kMaxSwipeYAngle|.
73   UITouch* touch = [[event allTouches] anyObject];
74   CGPoint currentPoint = [touch locationInView:self.view];
75   CGFloat dy = currentPoint.y - _startPoint.y;
76   CGFloat dx = std::abs(currentPoint.x - _startPoint.x);
77   CGFloat degrees = std::fabs(std::atan2(dy, dx) * 180 / CGFloat(M_PI));
78   if (degrees > kMaxSwipeYAngle) {
79     self.state = UIGestureRecognizerStateFailed;
80     return;
81   }
83   // Don't recognize swipe in the wrong direction.
84   if ((_direction == UISwipeGestureRecognizerDirectionRight &&
85        currentPoint.x - _startPoint.x < 0) ||
86       (_direction == UISwipeGestureRecognizerDirectionLeft &&
87        currentPoint.x - _startPoint.x > 0)) {
88     self.state = UIGestureRecognizerStateFailed;
89     return;
90   }
92   if (_swipeEdge == 0 && _direction == 0) {
93     if (currentPoint.x > _startPoint.x) {
94       _direction = UISwipeGestureRecognizerDirectionRight;
95     } else {
96       _direction = UISwipeGestureRecognizerDirectionLeft;
97     }
98   }
100   // Begin recognizer after |kMinSwipeXThreshold| distance swiped.
101   if (std::abs(currentPoint.x - _startPoint.x) > kMinSwipeXThreshold) {
102     if (_direction == UISwipeGestureRecognizerDirectionRight) {
103       _swipeOffset = currentPoint.x;
104     } else {
105       _swipeOffset = -(CGRectGetMaxX([self.view bounds]) - currentPoint.x);
106     }
108     self.state = UIGestureRecognizerStateBegan;
109     return;
110   }
113 - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
114   _startPoint = CGPointZero;
115   [super touchesEnded:touches withEvent:event];
118 - (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event {
119   _startPoint = CGPointZero;
120   [super touchesCancelled:touches withEvent:event];
123 @end