1
2
3
4
5
6
7
8
9
10
11
12
13
14 package com.googlecode.mgwt.dom.client.recognizer.pinch;
15
16 import com.google.gwt.core.client.GWT;
17 import com.google.gwt.event.shared.HasHandlers;
18 import com.googlecode.mgwt.dom.client.event.touch.Touch;
19 import com.googlecode.mgwt.dom.client.event.touch.TouchCancelEvent;
20 import com.googlecode.mgwt.dom.client.event.touch.TouchEndEvent;
21 import com.googlecode.mgwt.dom.client.event.touch.TouchHandler;
22 import com.googlecode.mgwt.dom.client.event.touch.TouchMoveEvent;
23 import com.googlecode.mgwt.dom.client.event.touch.TouchStartEvent;
24 import com.googlecode.mgwt.dom.client.event.touch.TouchUtil;
25 import com.googlecode.mgwt.dom.client.recognizer.EventPropagator;
26
27
28
29
30
31
32
33 public class PinchRecognizer implements TouchHandler {
34
35 private static EventPropagator DEFAULT_EVENT_PROPAGATOR;
36
37 private final HasHandlers source;
38
39 private EventPropagator eventPropagator;
40
41 private enum State {
42 READY, INVALID, ONE_FINGER, TWO_FINGER;
43 }
44
45 private State state;
46
47 private Touch touchStart1;
48 private Touch touchStart2;
49
50 private int touchCount;
51 private double distance;
52
53 private final OffsetProvider offsetProvider;
54
55
56
57
58
59
60
61 public PinchRecognizer(HasHandlers source, OffsetProvider offsetProvider) {
62
63 if (source == null) {
64 throw new IllegalArgumentException("source can not be null");
65 }
66 if (offsetProvider == null) {
67 throw new IllegalArgumentException("offsetProvider can not be null");
68 }
69
70 this.source = source;
71 this.offsetProvider = offsetProvider;
72 state = State.READY;
73
74 }
75
76
77
78
79
80
81
82
83 @Override
84 public void onTouchStart(TouchStartEvent event) {
85 touchCount++;
86 switch (state) {
87 case READY:
88 touchStart1 = TouchUtil.cloneTouch(event.getTouches().get(0));
89 state = State.ONE_FINGER;
90 break;
91 case ONE_FINGER:
92 touchStart2 = TouchUtil.cloneTouch(event.getTouches().get(1));
93 distance = (int) Math.sqrt(Math.pow(touchStart1.getPageX() - touchStart2.getPageX(), 2) + Math.pow(touchStart1.getPageY() - touchStart1.getPageY(), 2));
94 state = State.TWO_FINGER;
95 break;
96
97 default:
98 state = State.INVALID;
99 break;
100 }
101
102 }
103
104
105
106
107
108
109
110
111 @Override
112 public void onTouchMove(TouchMoveEvent event) {
113 switch (state) {
114 case TWO_FINGER:
115
116 Touch touch1 = event.getTouches().get(0);
117 Touch touch2 = event.getTouches().get(1);
118
119 int left = offsetProvider.getLeft();
120 int top = offsetProvider.getTop();
121
122 int x1 = touch1.getPageX() - left;
123 int y1 = touch1.getPageY() - top;
124 int x2 = touch2.getPageX() - left;
125 int y2 = touch2.getPageY() - top;
126
127 double newDistance = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
128 int x = (x1 + x2) / 2;
129 int y = (y1 + y2) / 2;
130
131 getEventPropagator().fireEvent(source, new PinchEvent(x, y, distance / newDistance));
132 distance = newDistance;
133
134 break;
135
136 default:
137 state = State.INVALID;
138 break;
139 }
140
141 }
142
143
144
145
146
147
148
149
150 @Override
151 public void onTouchEnd(TouchEndEvent event) {
152 touchCount--;
153 if (touchCount <= 0) {
154 reset();
155 } else {
156 if (state == State.TWO_FINGER) {
157 state = State.ONE_FINGER;
158 } else {
159 if (touchCount == 2) {
160 state = State.TWO_FINGER;
161 }
162 }
163 }
164
165 }
166
167
168
169
170
171
172
173
174 @Override
175 public void onTouchCanceled(TouchCancelEvent event) {
176 touchCount--;
177 if (touchCount <= 0) {
178 reset();
179 } else {
180 if (state == State.TWO_FINGER) {
181 state = State.ONE_FINGER;
182 } else {
183 if (touchCount == 2) {
184 state = State.TWO_FINGER;
185 }
186 }
187 }
188 }
189
190 protected EventPropagator getEventPropagator() {
191 if (eventPropagator == null) {
192 if (DEFAULT_EVENT_PROPAGATOR == null) {
193 DEFAULT_EVENT_PROPAGATOR = GWT.create(EventPropagator.class);
194 }
195 eventPropagator = DEFAULT_EVENT_PROPAGATOR;
196 }
197 return eventPropagator;
198 }
199
200 protected void setEventPropagator(EventPropagator eventPropagator) {
201 this.eventPropagator = eventPropagator;
202
203 }
204
205 private void reset() {
206 touchCount = 0;
207 state = State.READY;
208
209 }
210
211 }