vtm/src/org/oscim/view/MapZoomControls.java

359 lines
10 KiB
Java

/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* 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/>.
*/
package org.oscim.view;
import org.oscim.generator.TileGenerator;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup.LayoutParams;
import android.widget.ZoomControls;
/**
* A MapZoomControls instance displays buttons for zooming in and out in a map.
*/
public class MapZoomControls {
private static class ZoomControlsHideHandler extends Handler {
private final ZoomControls mZoomControls;
ZoomControlsHideHandler(ZoomControls zoomControls) {
super();
mZoomControls = zoomControls;
}
@Override
public void handleMessage(Message message) {
mZoomControls.hide();
}
}
private static class ZoomInClickListener implements View.OnClickListener {
private final MapZoomControls mMapZoomControls;
ZoomInClickListener(MapZoomControls mapZoomControls) {
mMapZoomControls = mapZoomControls;
}
@Override
public void onClick(View view) {
// if (MapView.testRegionZoom)
// mMapView.mRegionLookup.updateRegion(1, null);
// else
// MapZoomControls.this.zoom((byte) 1);
mMapZoomControls.zoom((byte) 1);
}
}
private static class ZoomOutClickListener implements View.OnClickListener {
private final MapZoomControls mMapZoomControls;
ZoomOutClickListener(MapZoomControls mapZoomControls) {
mMapZoomControls = mapZoomControls;
}
@Override
public void onClick(View view) {
// if (MapView.testRegionZoom)
// mMapView.mRegionLookup.updateRegion(-1, null);
// else
mMapZoomControls.zoom((byte) -1);
}
}
/**
* Default {@link Gravity} of the zoom controls.
*/
private static final int DEFAULT_ZOOM_CONTROLS_GRAVITY = Gravity.BOTTOM
| Gravity.RIGHT;
/**
* Default maximum zoom level.
*/
private static final byte DEFAULT_ZOOM_LEVEL_MAX = 18;
/**
* Default minimum zoom level.
*/
private static final byte DEFAULT_ZOOM_LEVEL_MIN = 1;
/**
* Message code for the handler to hide the zoom controls.
*/
private static final int MSG_ZOOM_CONTROLS_HIDE = 0;
/**
* Horizontal padding for the zoom controls.
*/
private static final int ZOOM_CONTROLS_HORIZONTAL_PADDING = 5;
/**
* Delay in milliseconds after which the zoom controls disappear.
*/
private static final long ZOOM_CONTROLS_TIMEOUT = ViewConfiguration
.getZoomControlsTimeout();
private boolean mGravityChanged;
private boolean mShowMapZoomControls;
private final ZoomControls mZoomControls;
private int mZoomControlsGravity;
private final Handler mZoomControlsHideHandler;
private byte mZoomLevelMax;
private byte mZoomLevelMin;
private final MapView mMapView;
MapZoomControls(Context context, final MapView mapView) {
mMapView = mapView;
mZoomControls = new ZoomControls(context);
mShowMapZoomControls = true;
mZoomLevelMax = DEFAULT_ZOOM_LEVEL_MAX;
mZoomLevelMin = DEFAULT_ZOOM_LEVEL_MIN;
// if (!MapView.testRegionZoom)
mZoomControls.setVisibility(View.GONE);
mZoomControlsGravity = DEFAULT_ZOOM_CONTROLS_GRAVITY;
mZoomControls.setOnZoomInClickListener(new ZoomInClickListener(this));
mZoomControls.setOnZoomOutClickListener(new ZoomOutClickListener(this));
mZoomControlsHideHandler = new ZoomControlsHideHandler(mZoomControls);
int wrapContent = android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
LayoutParams layoutParams = new LayoutParams(wrapContent, wrapContent);
mapView.addView(mZoomControls, layoutParams);
}
/**
* Zooms in or out by the given amount of zoom levels.
*
* @param zoomLevelDiff
* the difference to the current zoom level.
* @return true if the zoom level was changed, false otherwise.
*/
boolean zoom(byte zoomLevelDiff) {
MapViewPosition mapViewPosition = mMapView.getMapViewPosition();
int z = mapViewPosition.getZoomLevel() + zoomLevelDiff;
if (zoomLevelDiff > 0) {
// check if zoom in is possible
if (z > mZoomLevelMax) {
return false;
}
} else if (zoomLevelDiff < 0) {
// check if zoom out is possible
if (z < getZoomLevelMin()) {
return false;
}
}
mapViewPosition.setZoomLevel((byte) z);
mMapView.redrawMap();
return true;
}
/**
* @return the current gravity for the placing of the zoom controls.
* @see Gravity
*/
public int getZoomControlsGravity() {
return mZoomControlsGravity;
}
/**
* @return the maximum zoom level of the map.
*/
public byte getZoomLevelMax() {
return mZoomLevelMax;
}
/**
* @return the minimum zoom level of the map.
*/
public byte getZoomLevelMin() {
return mZoomLevelMin;
}
/**
* @return true if the zoom controls are visible, false otherwise.
*/
public boolean isShowMapZoomControls() {
return mShowMapZoomControls;
}
/**
* @param show
* true if the zoom controls should be visible, false otherwise.
*/
public void setShowMapZoomControls(boolean show) {
mShowMapZoomControls = show;
}
/**
* Sets the gravity for the placing of the zoom controls. Supported values
* are {@link Gravity#TOP}, {@link Gravity#CENTER_VERTICAL},
* {@link Gravity#BOTTOM}, {@link Gravity#LEFT},
* {@link Gravity#CENTER_HORIZONTAL} and {@link Gravity#RIGHT}.
*
* @param zoomControlsGravity
* a combination of {@link Gravity} constants describing the
* desired placement.
*/
public void setZoomControlsGravity(int zoomControlsGravity) {
if (mZoomControlsGravity != zoomControlsGravity) {
mZoomControlsGravity = zoomControlsGravity;
mGravityChanged = true;
}
}
/**
* Sets the maximum zoom level of the map.
* <p>
* The maximum possible zoom level of the MapView depends also on the
* current {@link TileGenerator}. For example, downloading map tiles may
* only be possible up to a certain zoom level. Setting a higher maximum
* zoom level has no effect in this case.
*
* @param zoomLevelMax
* the maximum zoom level.
* @throws IllegalArgumentException
* if the maximum zoom level is smaller than the current minimum
* zoom level.
*/
public void setZoomLevelMax(byte zoomLevelMax) {
if (zoomLevelMax < mZoomLevelMin) {
throw new IllegalArgumentException();
}
mZoomLevelMax = zoomLevelMax;
}
/**
* Sets the minimum zoom level of the map.
*
* @param zoomLevelMin
* the minimum zoom level.
* @throws IllegalArgumentException
* if the minimum zoom level is larger than the current maximum
* zoom level.
*/
public void setZoomLevelMin(byte zoomLevelMin) {
if (zoomLevelMin > mZoomLevelMax) {
throw new IllegalArgumentException();
}
mZoomLevelMin = zoomLevelMin;
}
private int calculatePositionLeft(int left, int right, int zoomControlsWidth) {
int gravity = mZoomControlsGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
switch (gravity) {
case Gravity.LEFT:
return ZOOM_CONTROLS_HORIZONTAL_PADDING;
case Gravity.CENTER_HORIZONTAL:
return (right - left - zoomControlsWidth) / 2;
case Gravity.RIGHT:
return right - left - zoomControlsWidth
- ZOOM_CONTROLS_HORIZONTAL_PADDING;
}
throw new IllegalArgumentException("unknown horizontal gravity: " + gravity);
}
private int calculatePositionTop(int top, int bottom, int zoomControlsHeight) {
int gravity = mZoomControlsGravity & Gravity.VERTICAL_GRAVITY_MASK;
switch (gravity) {
case Gravity.TOP:
return 0;
case Gravity.CENTER_VERTICAL:
return (bottom - top - zoomControlsHeight) / 2;
case Gravity.BOTTOM:
return bottom - top - zoomControlsHeight;
}
throw new IllegalArgumentException("unknown vertical gravity: " + gravity);
}
private void showZoomControls() {
mZoomControlsHideHandler.removeMessages(MSG_ZOOM_CONTROLS_HIDE);
if (mZoomControls.getVisibility() != View.VISIBLE) {
mZoomControls.show();
}
}
private void showZoomControlsWithTimeout() {
showZoomControls();
mZoomControlsHideHandler.sendEmptyMessageDelayed(MSG_ZOOM_CONTROLS_HIDE,
ZOOM_CONTROLS_TIMEOUT);
}
int getMeasuredHeight() {
return mZoomControls.getMeasuredHeight();
}
int getMeasuredWidth() {
return mZoomControls.getMeasuredWidth();
}
void measure(int widthMeasureSpec, int heightMeasureSpec) {
mZoomControls.measure(widthMeasureSpec, heightMeasureSpec);
}
void onLayout(boolean changed, int left, int top, int right, int bottom) {
if (!changed && !mGravityChanged) {
return;
}
int zoomControlsWidth = mZoomControls.getMeasuredWidth();
int zoomControlsHeight = mZoomControls.getMeasuredHeight();
int positionLeft = calculatePositionLeft(left, right, zoomControlsWidth);
int positionTop = calculatePositionTop(top, bottom, zoomControlsHeight);
int positionRight = positionLeft + zoomControlsWidth;
int positionBottom = positionTop + zoomControlsHeight;
mZoomControls.layout(positionLeft, positionTop, positionRight, positionBottom);
mGravityChanged = false;
}
void onMapViewTouchEvent(int action) {
if (mShowMapZoomControls) {
switch (action) {
case MotionEvent.ACTION_DOWN:
showZoomControls();
break;
case MotionEvent.ACTION_CANCEL:
showZoomControlsWithTimeout();
break;
case MotionEvent.ACTION_UP:
showZoomControlsWithTimeout();
break;
}
}
}
void onZoomLevelChange(int zoomLevel) {
boolean zoomInEnabled = zoomLevel < mZoomLevelMax;
boolean zoomOutEnabled = zoomLevel > mZoomLevelMin;
mZoomControls.setIsZoomInEnabled(zoomInEnabled);
mZoomControls.setIsZoomOutEnabled(zoomOutEnabled);
}
}