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