Merge branch 'double-tap-to-zoom'
This commit is contained in:
commit
04ea503184
143
vtm-tests/test/org/oscim/layers/MapEventLayerTest.java
Normal file
143
vtm-tests/test/org/oscim/layers/MapEventLayerTest.java
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
package org.oscim.layers;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.oscim.event.Gesture;
|
||||||
|
import org.oscim.event.MotionEvent;
|
||||||
|
import org.oscim.map.Animator;
|
||||||
|
import org.oscim.map.Map;
|
||||||
|
import org.oscim.map.ViewController;
|
||||||
|
|
||||||
|
import static org.fest.assertions.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
public class MapEventLayerTest {
|
||||||
|
private MapEventLayer layer;
|
||||||
|
private Map mockMap;
|
||||||
|
private ViewController mockViewport;
|
||||||
|
private Animator mockAnimator;
|
||||||
|
private ArgumentCaptor<Float> argumentCaptor;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
mockMap = Mockito.mock(Map.class);
|
||||||
|
mockViewport = Mockito.mock(ViewController.class);
|
||||||
|
mockAnimator = Mockito.mock(Animator.class);
|
||||||
|
layer = new MapEventLayer(mockMap);
|
||||||
|
when(mockMap.viewport()).thenReturn(mockViewport);
|
||||||
|
when(mockMap.animator()).thenReturn(mockAnimator);
|
||||||
|
when(mockMap.getHeight()).thenReturn(6);
|
||||||
|
argumentCaptor = ArgumentCaptor.forClass(float.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotBeNull() throws Exception {
|
||||||
|
assertThat(layer).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void doubleTap_shouldAnimateZoom() throws Exception {
|
||||||
|
simulateDoubleTap();
|
||||||
|
verify(mockAnimator).animateZoom(300, 2, 1.0f, -2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void doubleTap_shouldAnimateZoomAfterDoubleTouchDrag() throws Exception {
|
||||||
|
simulateDoubleTouchDragUp();
|
||||||
|
simulateDoubleTap();
|
||||||
|
verify(mockAnimator).animateZoom(300, 2, 1.0f, -2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void doubleTouchDrag_shouldNotAnimateZoom() throws Exception {
|
||||||
|
simulateDoubleTouchDragUp();
|
||||||
|
verify(mockAnimator, never()).animateZoom(any(long.class), any(double.class),
|
||||||
|
any(float.class), any(float.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void doubleTouchDragUp_shouldDecreaseContentScale() throws Exception {
|
||||||
|
simulateDoubleTouchDragUp();
|
||||||
|
verify(mockViewport).scaleMap(argumentCaptor.capture(), any(float.class), any(float.class));
|
||||||
|
assertThat(argumentCaptor.getValue()).isLessThan(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void doubleTouchDragDown_shouldIncreaseContentScale() throws Exception {
|
||||||
|
simulateDoubleTouchDragDown();
|
||||||
|
verify(mockViewport).scaleMap(argumentCaptor.capture(), any(float.class), any(float.class));
|
||||||
|
assertThat(argumentCaptor.getValue()).isGreaterThan(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void simulateDoubleTap() {
|
||||||
|
layer.onTouchEvent(new TestMotionEvent(MotionEvent.ACTION_DOWN, 1, 1));
|
||||||
|
layer.onGesture(Gesture.DOUBLE_TAP, new TestMotionEvent(MotionEvent.ACTION_UP, 1, 1));
|
||||||
|
layer.onTouchEvent(new TestMotionEvent(MotionEvent.ACTION_UP, 1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void simulateDoubleTouchDragUp() {
|
||||||
|
layer.onTouchEvent(new TestMotionEvent(MotionEvent.ACTION_DOWN, 1, 1));
|
||||||
|
layer.onGesture(Gesture.DOUBLE_TAP, new TestMotionEvent(MotionEvent.ACTION_MOVE, 1, 0));
|
||||||
|
layer.onTouchEvent(new TestMotionEvent(MotionEvent.ACTION_MOVE, 1, 0));
|
||||||
|
layer.onTouchEvent(new TestMotionEvent(MotionEvent.ACTION_UP, 1, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void simulateDoubleTouchDragDown() {
|
||||||
|
layer.onTouchEvent(new TestMotionEvent(MotionEvent.ACTION_DOWN, 1, 1));
|
||||||
|
layer.onGesture(Gesture.DOUBLE_TAP, new TestMotionEvent(MotionEvent.ACTION_MOVE, 1, 2));
|
||||||
|
layer.onTouchEvent(new TestMotionEvent(MotionEvent.ACTION_MOVE, 1, 2));
|
||||||
|
layer.onTouchEvent(new TestMotionEvent(MotionEvent.ACTION_UP, 1, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestMotionEvent extends MotionEvent {
|
||||||
|
final int action;
|
||||||
|
final float x;
|
||||||
|
final float y;
|
||||||
|
|
||||||
|
public TestMotionEvent(int action, float x, float y) {
|
||||||
|
this.action = action;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTime() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getX(int idx) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getY(int idx) {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPointerCount() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -54,6 +54,7 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
|
|
||||||
private boolean mDown;
|
private boolean mDown;
|
||||||
private boolean mDoubleTap;
|
private boolean mDoubleTap;
|
||||||
|
private boolean mDrag;
|
||||||
|
|
||||||
private float mPrevX1;
|
private float mPrevX1;
|
||||||
private float mPrevY1;
|
private float mPrevY1;
|
||||||
@ -74,14 +75,12 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
protected static final float MIN_SLOP = 25.4f / 2;
|
protected static final float MIN_SLOP = 25.4f / 2;
|
||||||
|
|
||||||
/** 100 ms since start of move to reduce fling scroll */
|
/** 100 ms since start of move to reduce fling scroll */
|
||||||
protected static final float FLING_THREHSHOLD = 100;
|
protected static final float FLING_MIN_THREHSHOLD = 100;
|
||||||
|
|
||||||
//private final Viewport mViewport;
|
|
||||||
private final VelocityTracker mTracker;
|
private final VelocityTracker mTracker;
|
||||||
|
|
||||||
public MapEventLayer(Map map) {
|
public MapEventLayer(Map map) {
|
||||||
super(map);
|
super(map);
|
||||||
//mViewport = map.viewport();
|
|
||||||
mTracker = new VelocityTracker();
|
mTracker = new VelocityTracker();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,6 +119,7 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
mDoubleTap = false;
|
mDoubleTap = false;
|
||||||
mStartMove = -1;
|
mStartMove = -1;
|
||||||
mDown = true;
|
mDown = true;
|
||||||
|
mDrag = false;
|
||||||
|
|
||||||
mPrevX1 = e.getX(0);
|
mPrevX1 = e.getX(0);
|
||||||
mPrevY1 = e.getY(0);
|
mPrevY1 = e.getY(0);
|
||||||
@ -136,29 +136,33 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
}
|
}
|
||||||
if (action == MotionEvent.ACTION_UP) {
|
if (action == MotionEvent.ACTION_UP) {
|
||||||
mDown = false;
|
mDown = false;
|
||||||
if (mStartMove < 0)
|
if (mDoubleTap && !mDrag) {
|
||||||
return true;
|
/* handle double tap zoom */
|
||||||
|
mMap.animator().animateZoom(300, 2,
|
||||||
|
mPrevX1 - mMap.getWidth() / 2,
|
||||||
|
mPrevY1 - mMap.getHeight() / 2);
|
||||||
|
|
||||||
|
} else if (mStartMove > 0) {
|
||||||
|
/* handle fling gesture */
|
||||||
mTracker.update(e.getX(), e.getY(), e.getTime());
|
mTracker.update(e.getX(), e.getY(), e.getTime());
|
||||||
|
|
||||||
float vx = mTracker.getVelocityX();
|
float vx = mTracker.getVelocityX();
|
||||||
float vy = mTracker.getVelocityY();
|
float vy = mTracker.getVelocityY();
|
||||||
|
|
||||||
/* reduce velocity for short moves */
|
/* reduce velocity for short moves */
|
||||||
float t = e.getTime() - mStartMove;
|
float t = e.getTime() - mStartMove;
|
||||||
if (t < FLING_THREHSHOLD) {
|
if (t < FLING_MIN_THREHSHOLD) {
|
||||||
t = t / FLING_THREHSHOLD;
|
t = t / FLING_MIN_THREHSHOLD;
|
||||||
vy *= t * t;
|
vy *= t * t;
|
||||||
vx *= t * t;
|
vx *= t * t;
|
||||||
}
|
}
|
||||||
doFling(vx, vy);
|
doFling(vx, vy);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (action == MotionEvent.ACTION_CANCEL) {
|
if (action == MotionEvent.ACTION_CANCEL) {
|
||||||
//mStartMove = -1;
|
return false;
|
||||||
mDown = false;
|
|
||||||
mDoubleTap = false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
if (action == MotionEvent.ACTION_POINTER_DOWN) {
|
if (action == MotionEvent.ACTION_POINTER_DOWN) {
|
||||||
mStartMove = -1;
|
mStartMove = -1;
|
||||||
@ -200,7 +204,8 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// FIXME limit scale properly
|
// FIXME limit scale properly
|
||||||
mViewport.scaleMap(1 - my / (height / 6), 0, 0);
|
mDrag = true;
|
||||||
|
mViewport.scaleMap(1 + my / (height / 6), 0, 0);
|
||||||
mMap.updateMap(true);
|
mMap.updateMap(true);
|
||||||
mStartMove = -1;
|
mStartMove = -1;
|
||||||
return true;
|
return true;
|
||||||
@ -302,7 +307,6 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mCanScale || mDoRotate) {
|
if (mCanScale || mDoRotate) {
|
||||||
|
|
||||||
if (!(mDoScale || mDoRotate)) {
|
if (!(mDoScale || mDoRotate)) {
|
||||||
/* enter exclusive scale mode */
|
/* enter exclusive scale mode */
|
||||||
if (Math.abs(deltaPinch) > (CanvasAdapter.dpi
|
if (Math.abs(deltaPinch) > (CanvasAdapter.dpi
|
||||||
@ -330,9 +334,7 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
float fy = (y2 + y1) / 2 - height / 2;
|
float fy = (y2 + y1) / 2 - height / 2;
|
||||||
|
|
||||||
synchronized (mViewport) {
|
synchronized (mViewport) {
|
||||||
|
|
||||||
if (!mDoTilt) {
|
if (!mDoTilt) {
|
||||||
|
|
||||||
if (rotateBy != 0)
|
if (rotateBy != 0)
|
||||||
mViewport.rotateMap(rotateBy, fx, fy);
|
mViewport.rotateMap(rotateBy, fx, fy);
|
||||||
if (scaleBy != 1)
|
if (scaleBy != 1)
|
||||||
@ -340,10 +342,8 @@ public class MapEventLayer extends Layer implements InputListener, GestureListen
|
|||||||
|
|
||||||
mViewport.moveMap(mx, my);
|
mViewport.moveMap(mx, my);
|
||||||
} else {
|
} else {
|
||||||
if (tiltBy != 0) {
|
if (tiltBy != 0 && mViewport.tiltMap(-tiltBy))
|
||||||
mViewport.moveMap(0, my / 2);
|
mViewport.moveMap(0, my / 2);
|
||||||
mViewport.tiltMap(tiltBy);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user