/*
* 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 .
*/
package org.oscim.overlay;
import java.util.List;
import org.oscim.app.R;
import org.oscim.core.BoundingBox;
import org.oscim.core.PointF;
import org.oscim.view.MapView;
import org.oscim.view.MapViewPosition;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.MotionEvent;
public class ItemizedIconOverlay- extends ItemizedOverlay
- {
//private static final String TAG = ItemizedIconOverlay.class.getName();
protected final List
- mItemList;
protected OnItemGestureListener
- mOnItemGestureListener;
private int mDrawnItemsLimit = Integer.MAX_VALUE;
private final PointF mItemPoint = new PointF();
public ItemizedIconOverlay(
final MapView mapView,
final List
- pList,
final Drawable pDefaultMarker,
final ItemizedIconOverlay.OnItemGestureListener
- pOnItemGestureListener) {
super(mapView, pDefaultMarker);
this.mItemList = pList;
this.mOnItemGestureListener = pOnItemGestureListener;
populate();
}
public ItemizedIconOverlay(
final MapView mapView,
final Context pContext,
final List
- pList,
final ItemizedIconOverlay.OnItemGestureListener
- pOnItemGestureListener) {
this(mapView, pList, pContext.getResources().getDrawable(R.drawable.marker_default),
pOnItemGestureListener);
}
@Override
public boolean onSnapToItem(final int pX, final int pY, final PointF pSnapPoint) {
// TODO Implement this!
return false;
}
@Override
protected Item createItem(final int index) {
return mItemList.get(index);
}
@Override
public int size() {
return Math.min(mItemList.size(), mDrawnItemsLimit);
}
public boolean addItem(final Item item) {
final boolean result = mItemList.add(item);
populate();
return result;
}
public void addItem(final int location, final Item item) {
mItemList.add(location, item);
}
public boolean addItems(final List
- items) {
final boolean result = mItemList.addAll(items);
populate();
return result;
}
public void removeAllItems() {
removeAllItems(true);
}
public void removeAllItems(final boolean withPopulate) {
mItemList.clear();
if (withPopulate) {
populate();
}
}
public boolean removeItem(final Item item) {
final boolean result = mItemList.remove(item);
populate();
return result;
}
public Item removeItem(final int position) {
final Item result = mItemList.remove(position);
populate();
return result;
}
/**
* Each of these methods performs a item sensitive check. If the item is
* located its corresponding method is called. The result of the call is
* returned. Helper methods are provided so that child classes may more
* easily override behavior without resorting to overriding the
* ItemGestureListener methods.
*/
@Override
public boolean onSingleTapUp(final MotionEvent event) {
return activateSelectedItems(event, mActiveItemSingleTap) || super.onSingleTapUp(event);
}
protected boolean onSingleTapUpHelper(final int index, final Item item) {
return this.mOnItemGestureListener.onItemSingleTapUp(index, item);
}
private final ActiveItem mActiveItemSingleTap = new ActiveItem() {
@Override
public boolean run(final int index) {
final ItemizedIconOverlay
- that = ItemizedIconOverlay.this;
if (that.mOnItemGestureListener == null) {
return false;
}
return onSingleTapUpHelper(index, that.mItemList.get(index));
}
};
@Override
public boolean onLongPress(final MotionEvent event) {
return activateSelectedItems(event, mActiveItemLongPress) || super.onLongPress(event);
}
protected boolean onLongPressHelper(final int index, final Item item) {
return this.mOnItemGestureListener.onItemLongPress(index, item);
}
private final ActiveItem mActiveItemLongPress = new ActiveItem() {
@Override
public boolean run(final int index) {
final ItemizedIconOverlay
- that = ItemizedIconOverlay.this;
if (that.mOnItemGestureListener == null) {
return false;
}
return onLongPressHelper(index, getItem(index));
}
};
/**
* When a content sensitive action is performed the content item needs to be
* identified. This method does that and then performs the assigned task on
* that item.
*
* @param event
* ...
* @param task
* ..
* @return true if event is handled false otherwise
*/
private boolean activateSelectedItems(MotionEvent event, ActiveItem task) {
int size = mItemList.size();
if (size == 0)
return false;
int eventX = (int) event.getX() - mMapView.getWidth() / 2;
int eventY = (int) event.getY() - mMapView.getHeight() / 2;
MapViewPosition mapViewPosition = mMapView.getMapViewPosition();
BoundingBox bbox = mapViewPosition.getViewBox();
int nearest = -1;
double dist = Double.MAX_VALUE;
for (int i = 0; i < size; i++) {
Item item = getItem(i);
if (!bbox.contains(item.mGeoPoint)){
//Log.d(TAG, "skip: " + item.getTitle());
continue;
}
// final Drawable marker = (item.getMarker(0) == null) ? this.mDefaultMarker : item
// .getMarker(0);
// TODO use intermediate projection
mapViewPosition.project(item.getPoint(), mItemPoint);
float dx = mItemPoint.x - eventX;
float dy = mItemPoint.y - eventY;
//Log.d(TAG, item.getTitle() + " " + mItemPoint + " " + dx + "/" + dy);
double d = dx * dx + dy * dy;
// squared dist: 50*50 pixel
if (d < 2500) {
if (d < dist) {
dist = d;
nearest = i;
}
}
}
if (nearest >= 0 && task.run(nearest)) {
return true;
}
return false;
}
// ===========================================================
// Getter & Setter
// ===========================================================
public int getDrawnItemsLimit() {
return this.mDrawnItemsLimit;
}
public void setDrawnItemsLimit(final int aLimit) {
this.mDrawnItemsLimit = aLimit;
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
/**
* When the item is touched one of these methods may be invoked depending on
* the type of touch. Each of them returns true if the event was completely
* handled.
*
* @param
* ....
*/
public static interface OnItemGestureListener {
public boolean onItemSingleTapUp(final int index, final T item);
public boolean onItemLongPress(final int index, final T item);
}
public static interface ActiveItem {
public boolean run(final int aIndex);
}
}