package com.nutiteq.ui; /** * Thread driven panning implementation, that will pan map at 35 ms intervals. * Based on panning time, the panning speed will increase. At the beginning map * will be moved by one pixel, the by two pixels and at the end by four pixels. * * This implementation has additional checks using keyRepeated events to check, * if panning is still active. If no keyRepeat events have been received for two * seconds, then panning is considered abandoned and is stopped. Current panning * action will be stopped, not the thread. * * Abandoned panning actions can be created, when key is pressed for moving and * then some system interruption (incoming call, etc.) happens. Then the key * released event is never received by {@link com.nutiteq.MapComponent} and * panning is never stopped. * * NOTE - for this implementation to work correctly, * {@link com.nutiteq.MapComponent} needs to receive keyRepeated events. */ public class ThreadDrivenPanning extends Thread implements PanningStrategy { private static final int ABANDONED_PANNING_TIME = 2000; private static final int PAN_TIMEOUT = 35; // ms private Pannable pannable; private int moveX; private int moveY; private boolean running; private int count; private long lastKeyRepeat; private boolean panningWithKeys; public void run() { running = true; while (running) { try { while (moveX == 0 && moveY == 0 && running) { count = 0; synchronized (this) { wait(); } } if (!running) { break; } if (panningWithKeys && (System.currentTimeMillis() - lastKeyRepeat) > ABANDONED_PANNING_TIME) { stopPanning(); } count++; int dx = moveX; int dy = moveY; if (count >= 10 && count < 15) { dx = dx * 2; dy = dy * 2; } else if (count >= 15) { dx = dx * 4; dy = dy * 4; } pannable.panMap(dx, dy); synchronized (this) { wait(PAN_TIMEOUT); } } catch (final InterruptedException ignore) { } } } public synchronized void startPanning(final int directionX, final int directionY, final boolean panningWithKeys) { this.panningWithKeys = panningWithKeys; lastKeyRepeat = System.currentTimeMillis(); moveX = directionX; moveY = directionY; notify(); } public synchronized boolean isPanning() { return moveX != 0 || moveY != 0; } public synchronized void stopPanning() { moveX = 0; moveY = 0; } public synchronized void quit() { running = false; notify(); } public void keyRepeated(final int keyCode) { lastKeyRepeat = System.currentTimeMillis(); } public void setMapComponent(final Pannable mapComponent) { pannable = mapComponent; } }