/* * Copyright 2012 osmdroid * Copyright 2013 Hannes Janetzek * * This program is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. */ // Created by plusminus on 20:32:01 - 27.09.2008 package org.oscim.overlay; import java.util.concurrent.atomic.AtomicInteger; import org.oscim.core.MapPosition; import org.oscim.renderer.overlays.RenderOverlay; import org.oscim.view.MapView; import android.graphics.Point; import android.view.KeyEvent; import android.view.MotionEvent; /** * Base class representing an overlay which may be displayed on top of a * {@link MapView}. To add an overlay, subclass this class, create an instance, * and add it to the list obtained from getOverlays() of {@link MapView}. This * class implements a form of Gesture Handling similar to * {@link android.view.GestureDetector.SimpleOnGestureListener} and * GestureDetector.OnGestureListener. The difference is there is an additional * argument for the item. * * @author Nicolas Gramlich */ public abstract class Overlay { // =========================================================== // Constants // =========================================================== private static AtomicInteger sOrdinal = new AtomicInteger(); // From Google Maps API protected static final float SHADOW_X_SKEW = -0.8999999761581421f; protected static final float SHADOW_Y_SCALE = 0.5f; // =========================================================== // Fields // =========================================================== //protected final ResourceProxy mResourceProxy; //protected final float mScale; // private static final Rect mRect = new Rect(); private boolean mEnabled = true; protected final MapView mMapView; protected RenderOverlay mLayer; public RenderOverlay getLayer() { return mLayer; } // =========================================================== // Constructors // =========================================================== public Overlay(MapView mapView) { mMapView = mapView; } // =========================================================== // Getter & Setter // =========================================================== /** * Sets whether the Overlay is marked to be enabled. This setting does * nothing by default, but should be checked before calling draw(). * * @param pEnabled * ... */ public void setEnabled(final boolean pEnabled) { this.mEnabled = pEnabled; } /** * Specifies if the Overlay is marked to be enabled. This should be checked * before calling draw(). * * @return true if the Overlay is marked enabled, false otherwise */ public boolean isEnabled() { return this.mEnabled; } /** * Since the menu-chain will pass through several independent Overlays, menu * IDs cannot be fixed at compile time. Overlays should use this method to * obtain and store a menu id for each menu item at construction time. This * will ensure that two overlays don't use the same id. * * @return an integer suitable to be used as a menu identifier */ protected final static int getSafeMenuId() { return sOrdinal.getAndIncrement(); } /** * Similar to <see cref="getSafeMenuId" />, except this reserves a sequence * of IDs of length <param name="count" />. The returned number is the * starting index of that sequential list. * * @param count * .... * @return an integer suitable to be used as a menu identifier */ protected final static int getSafeMenuIdSequence(final int count) { return sOrdinal.getAndAdd(count); } // =========================================================== // Methods for SuperClass/Interfaces // =========================================================== // /** // * Draw the overlay over the map. This will be called on all active overlays // * with shadow=true, to lay down the shadow layer, and then again on all // * overlays with shadow=false. Callers should check isEnabled() before // * calling draw(). By default, draws nothing. // * // * @param c // * ... // * @param osmv // * ... // * @param shadow // * ... // */ // protected abstract void draw(final Canvas c, final MapView osmv, final boolean shadow); // =========================================================== // Methods // =========================================================== /** * Override to perform clean up of resources before shutdown. By default * does nothing. */ public void onDetach() { } /** * By default does nothing (<code>return false</code>). If you handled the * Event, return <code>true</code>, otherwise return <code>false</code>. If * you returned <code>true</code> none of the following Overlays or the * underlying {@link MapView} has the chance to handle this event. * * @param keyCode * ... * @param event * ... * @return ... */ public boolean onKeyDown(final int keyCode, final KeyEvent event) { return false; } /** * By default does nothing (<code>return false</code>). If you handled the * Event, return <code>true</code>, otherwise return <code>false</code>. If * you returned <code>true</code> none of the following Overlays or the * underlying {@link MapView} has the chance to handle this event. * * @param keyCode * ... * @param event * ... * @return ... */ public boolean onKeyUp(final int keyCode, final KeyEvent event) { return false; } /** * <b>You can prevent all(!) other Touch-related events from happening!</b><br /> * By default does nothing (<code>return false</code>). If you handled the * Event, return <code>true</code>, otherwise return <code>false</code>. If * you returned <code>true</code> none of the following Overlays or the * underlying {@link MapView} has the chance to handle this event. * * @param e * ... * @return ... */ public boolean onTouchEvent(final MotionEvent e) { return false; } /** * By default does nothing (<code>return false</code>). If you handled the * Event, return <code>true</code>, otherwise return <code>false</code>. If * you returned <code>true</code> none of the following Overlays or the * underlying {@link MapView} has the chance to handle this event. * * @param e * ... * @return ... */ public boolean onTrackballEvent(final MotionEvent e) { return false; } /** GestureDetector.OnDoubleTapListener **/ /** * By default does nothing (<code>return false</code>). If you handled the * Event, return <code>true</code>, otherwise return <code>false</code>. If * you returned <code>true</code> none of the following Overlays or the * underlying {@link MapView} has the chance to handle this event. * * @param e * ... * @return ... */ public boolean onDoubleTap(final MotionEvent e) { return false; } /** * By default does nothing (<code>return false</code>). If you handled the * Event, return <code>true</code>, otherwise return <code>false</code>. If * you returned <code>true</code> none of the following Overlays or the * underlying {@link MapView} has the chance to handle this event. * * @param e * ... * @return ... */ public boolean onDoubleTapEvent(final MotionEvent e) { return false; } /** * By default does nothing (<code>return false</code>). If you handled the * Event, return <code>true</code>, otherwise return <code>false</code>. If * you returned <code>true</code> none of the following Overlays or the * underlying {@link MapView} has the chance to handle this event. * * @param e * ... * @return ... */ public boolean onSingleTapConfirmed(final MotionEvent e) { return false; } /** OnGestureListener **/ /** * By default does nothing (<code>return false</code>). If you handled the * Event, return <code>true</code>, otherwise return <code>false</code>. If * you returned <code>true</code> none of the following Overlays or the * underlying {@link MapView} has the chance to handle this event. * * @param e * ... * @return ... */ public boolean onDown(final MotionEvent e) { return false; } /** * By default does nothing (<code>return false</code>). If you handled the * Event, return <code>true</code>, otherwise return <code>false</code>. If * you returned <code>true</code> none of the following Overlays or the * underlying {@link MapView} has the chance to handle this event. * * @param pEvent1 * ... * @param pEvent2 * ... * @param pVelocityX * ... * @param pVelocityY * ... * @return ... */ public boolean onFling(final MotionEvent pEvent1, final MotionEvent pEvent2, final float pVelocityX, final float pVelocityY) { return false; } /** * By default does nothing (<code>return false</code>). If you handled the * Event, return <code>true</code>, otherwise return <code>false</code>. If * you returned <code>true</code> none of the following Overlays or the * underlying {@link MapView} has the chance to handle this event. * * @param e * ... * @return ... */ public boolean onLongPress(final MotionEvent e) { return false; } /** * By default does nothing (<code>return false</code>). If you handled the * Event, return <code>true</code>, otherwise return <code>false</code>. If * you returned <code>true</code> none of the following Overlays or the * underlying {@link MapView} has the chance to handle this event. * * @param pEvent1 * ... * @param pEvent2 * ... * @param pDistanceX * ... * @param pDistanceY * ... * @return ... */ public boolean onScroll(final MotionEvent pEvent1, final MotionEvent pEvent2, final float pDistanceX, final float pDistanceY) { return false; } /** * @param pEvent * ... */ public void onShowPress(final MotionEvent pEvent) { return; } /** * By default does nothing (<code>return false</code>). If you handled the * Event, return <code>true</code>, otherwise return <code>false</code>. If * you returned <code>true</code> none of the following Overlays or the * underlying {@link MapView} has the chance to handle this event. * * @param e * ... * @return ... */ public boolean onSingleTapUp(final MotionEvent e) { return false; } /** * @param mapPosition * current MapPosition * @param changed ... */ public void onUpdate(MapPosition mapPosition, boolean changed) { } // =========================================================== // Inner and Anonymous Classes // =========================================================== /** * Interface definition for overlays that contain items that can be snapped * to (for example, when the user invokes a zoom, this could be called * allowing the user to snap the zoom to an interesting point.) */ public interface Snappable { /** * Checks to see if the given x and y are close enough to an item * resulting in snapping the current action (e.g. zoom) to the item. * * @param x * The x in screen coordinates. * @param y * The y in screen coordinates. * @param snapPoint * To be filled with the the interesting point (in screen * coordinates) that is closest to the given x and y. Can be * untouched if not snapping. * @return Whether or not to snap to the interesting point. */ boolean onSnapToItem(int x, int y, Point snapPoint); } }