vtm-app: revive / update with latest VTM, closes #90

This commit is contained in:
Emux
2016-07-21 20:22:22 +03:00
parent c67b35a277
commit 436b66be82
133 changed files with 10436 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
package org.osmdroid.overlays;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import org.oscim.android.MapView;
import org.oscim.app.App;
import org.osmdroid.utils.BonusPackHelper;
/**
* Default implementation of InfoWindow. It handles a text and a description. It
* also handles optionally a sub-description and an image. Clicking on the
* bubble will close it.
*
* @author M.Kergall
*/
public class DefaultInfoWindow extends InfoWindow {
// resource ids
private static int mTitleId = 0, mDescriptionId = 0, mSubDescriptionId = 0, mImageId = 0;
private static void setResIds(Context context) {
// get application package name
String packageName = context.getPackageName();
Resources res = context.getResources();
mTitleId = res.getIdentifier("id/bubble_title", null, packageName);
mDescriptionId = res.getIdentifier("id/bubble_description", null, packageName);
mSubDescriptionId = res.getIdentifier("id/bubble_subdescription", null, packageName);
mImageId = res.getIdentifier("id/bubble_image", null, packageName);
if (mTitleId == 0 || mDescriptionId == 0) {
Log.e(BonusPackHelper.LOG_TAG, "DefaultInfoWindow: unable to get res ids in "
+ packageName);
}
}
public DefaultInfoWindow(int layoutResId, MapView mapView) {
super(layoutResId, mapView);
if (mTitleId == 0)
setResIds(App.activity);
// default behaviour: close it when clicking on the bubble:
mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
close();
}
});
}
@Override
public void onOpen(ExtendedMarkerItem item) {
String title = item.getTitle();
if (title == null)
title = "";
((TextView) mView.findViewById(mTitleId)).setText(title);
String snippet = item.getDescription();
if (snippet == null)
snippet = "";
((TextView) mView.findViewById(mDescriptionId)).setText(snippet);
// handle sub-description, hidding or showing the text view:
TextView subDescText = (TextView) mView.findViewById(mSubDescriptionId);
String subDesc = item.getSubDescription();
if (subDesc != null && !("".equals(subDesc))) {
subDescText.setText(subDesc);
subDescText.setVisibility(View.VISIBLE);
} else {
subDescText.setVisibility(View.GONE);
}
// handle image
ImageView imageView = (ImageView) mView.findViewById(mImageId);
Drawable image = item.getImage();
if (image != null) {
// or setBackgroundDrawable(image)?
imageView.setImageDrawable(image);
imageView.setVisibility(View.VISIBLE);
} else
imageView.setVisibility(View.GONE);
}
@Override
public void onClose() {
// by default, do nothing
}
}

View File

@@ -0,0 +1,123 @@
package org.osmdroid.overlays;
import android.graphics.drawable.Drawable;
import org.oscim.core.GeoPoint;
import org.oscim.layers.marker.MarkerItem;
import org.oscim.map.Map;
/**
* An OverlayItem to use in ItemizedOverlayWithBubble<br>
* - more complete: can contain an image and a sub-description that will be
* displayed in the bubble, <br>
* - and flexible: attributes are modifiable<br>
* Known Issues:<br>
* - Bubble offset is not perfect on h&xhdpi resolutions, due to an osmdroid
* issue on marker drawing<br>
* - Bubble offset is at 0 when using the default marker => set the marker on
* each item!<br>
*
* @author M.Kergall
* @see ItemizedOverlayWithBubble
*/
public class ExtendedMarkerItem extends MarkerItem {
// now, they are modifiable
private String mTitle, mDescription;
// now, they are modifiable
// a third field that can be displayed in
// the infowindow, on a third line
// that will be shown in the infowindow.
//unfortunately, this is not so simple...
private String mSubDescription;
private Drawable mImage;
private Object mRelatedObject; // reference to an object (of any kind)
// linked to this item.
public ExtendedMarkerItem(String aTitle, String aDescription, GeoPoint aGeoPoint) {
super(aTitle, aDescription, aGeoPoint);
mTitle = aTitle;
mDescription = aDescription;
mSubDescription = null;
mImage = null;
mRelatedObject = null;
}
public void setTitle(String aTitle) {
mTitle = aTitle;
}
public void setDescription(String aDescription) {
mDescription = aDescription;
}
public void setSubDescription(String aSubDescription) {
mSubDescription = aSubDescription;
}
public void setImage(Drawable anImage) {
mImage = anImage;
}
public void setRelatedObject(Object o) {
mRelatedObject = o;
}
@Override
public String getTitle() {
return mTitle;
}
public String getDescription() {
return mDescription;
}
public String getSubDescription() {
return mSubDescription;
}
public Drawable getImage() {
return mImage;
}
public Object getRelatedObject() {
return mRelatedObject;
}
/**
* Populates this bubble with all item info:
* <ul>
* title and description in any case,
* </ul>
* <ul>
* image and sub-description if any.
* </ul>
* and centers the map on the item. <br>
*
* @param bubble ...
* @param map ...
*/
public void showBubble(InfoWindow bubble, Map map) {
// offset the bubble to be top-centered on the marker:
// Drawable marker = getMarker(0 /* OverlayItem.ITEM_STATE_FOCUSED_MASK */);
// int markerWidth = 0, markerHeight = 0;
// if (marker != null) {
// markerWidth = marker.getIntrinsicWidth();
// markerHeight = marker.getIntrinsicHeight();
// } // else... we don't have the default marker size => don't user default
// // markers!!!
// Point markerH = getHotspot(getMarkerHotspot(), markerWidth, markerHeight);
// Point bubbleH = getHotspot(HotspotPlace.TOP_CENTER, markerWidth, markerHeight);
// bubbleH.offset(-markerH.x, -markerH.y);
//
// bubble.open(this, bubbleH.x, bubbleH.y);
// OverlayMarker marker = getMarker();
// PointF hotspot = marker.getHotspot();
// Bitmap b = marker.getBitmap();
//bubble.open(this, (int)(-b.getWidth() * hotspot.x), (int)(-b.getHeight()));
//bubble.open(this, 0, (int)(b.getHeight()));
bubble.open(this, 0, 0);
}
}

View File

@@ -0,0 +1,135 @@
package org.osmdroid.overlays;
// TODO composite view as texture overlay and only allow one bubble at a time.
import android.content.Context;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import org.oscim.android.MapView;
/**
* View that can be displayed on an OSMDroid map, associated to a GeoPoint.
* Typical usage: cartoon-like bubbles displayed when clicking an overlay item.
* It mimics the InfoWindow class of Google Maps JavaScript API V3. Main
* differences are:
* <ul>
* <li>Structure and content of the view is let to the responsibility of the
* caller.</li>
* <li>The same InfoWindow can be associated to many items.</li>
* </ul>
* Known issues:
* <ul>
* <li>It disappears when zooming in/out (osmdroid issue #259 on osmdroid 3.0.8,
* should be fixed in next version).</li>
* <li>The window is displayed "above" the marker, so the queue of the bubble
* can hide the marker.</li>
* </ul>
* This is an abstract class.
*
* @author M.Kergall
* @see DefaultInfoWindow
*/
public abstract class InfoWindow {
protected View mView;
protected boolean mIsVisible = false;
protected RelativeLayout mLayout;
private android.widget.RelativeLayout.LayoutParams mLayoutPos;
private MapView mMap;
/**
* @param layoutResId the id of the view resource.
* @param mapView the mapview on which is hooked the view
*/
public InfoWindow(int layoutResId, MapView mapView) {
ViewGroup parent = (ViewGroup) mapView.getParent();
Context context = mapView.getContext();
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mView = inflater.inflate(layoutResId, parent, false);
RelativeLayout.LayoutParams rlp =
new RelativeLayout.LayoutParams(
android.view.ViewGroup.LayoutParams.MATCH_PARENT,
android.view.ViewGroup.LayoutParams.MATCH_PARENT);
mLayout = new RelativeLayout(context);
mLayout.setWillNotDraw(true);
mLayout.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
mLayout.setLayoutParams(rlp);
mLayoutPos = rlp;
mView.setDrawingCacheEnabled(true);
mLayout.addView(mView);
mIsVisible = false;
mLayout.setVisibility(View.GONE);
mMap = mapView;
parent.addView(mLayout);
}
/**
* Returns the Android view. This allows to set its content.
*
* @return the Android view
*/
public View getView() {
return (mView);
}
private int mHeight;
/**
* open the window at the specified position.
*
* @param item the item on which is hooked the view
* @param offsetX (&offsetY) the offset of the view to the position, in pixels.
* This allows to offset the view from the marker position.
* @param offsetY ...
*/
public void open(ExtendedMarkerItem item, int offsetX, int offsetY) {
onOpen(item);
close();
mView.buildDrawingCache();
mHeight = mMap.getHeight();
mLayout.setVisibility(View.VISIBLE);
mIsVisible = true;
}
public void position(int x, int y) {
RelativeLayout.LayoutParams rlp = mLayoutPos;
rlp.leftMargin = x;
rlp.rightMargin = -x;
rlp.topMargin = y;
rlp.bottomMargin = mHeight / 2 - y;
mLayout.setLayoutParams(rlp);
mLayout.requestLayout();
}
public void close() {
if (mIsVisible) {
mIsVisible = false;
mLayout.setVisibility(View.GONE);
onClose();
}
}
public boolean isOpen() {
return mIsVisible;
}
// Abstract methods to implement:
public abstract void onOpen(ExtendedMarkerItem item);
public abstract void onClose();
}

View File

@@ -0,0 +1,195 @@
package org.osmdroid.overlays;
import android.content.Context;
import android.util.Log;
import org.oscim.app.App;
import org.oscim.core.GeoPoint;
import org.oscim.core.MapPosition;
import org.oscim.core.Point;
import org.oscim.event.Event;
import org.oscim.event.MotionEvent;
import org.oscim.layers.marker.ItemizedLayer;
import org.oscim.layers.marker.MarkerItem;
import org.oscim.layers.marker.MarkerSymbol;
import org.oscim.map.Map;
import org.osmdroid.utils.BonusPackHelper;
import java.util.List;
/**
* An itemized overlay with an InfoWindow or "bubble" which opens when the user
* taps on an overlay item, and displays item attributes. <br>
* Items must be ExtendedMarkerItem. <br>
*
* @param <Item> ...
* @author M.Kergall
* @see ExtendedMarkerItem
* @see InfoWindow
*/
public class ItemizedOverlayWithBubble<Item extends MarkerItem> extends
ItemizedLayer<Item> implements
ItemizedLayer.OnItemGestureListener<Item>, Map.UpdateListener {
/* only one for all items of this overlay => one at a time */
protected InfoWindow mBubble;
/* the item currently showing the bubble. Null if none. */
protected MarkerItem mItemWithBubble;
static int layoutResId = 0;
public ItemizedOverlayWithBubble(Map map, Context context,
MarkerSymbol marker, List<Item> list, InfoWindow bubble) {
super(map, list, marker, null);
if (bubble != null) {
mBubble = bubble;
} else {
// build default bubble:
String packageName = context.getPackageName();
if (layoutResId == 0) {
layoutResId = context.getResources().getIdentifier(
"layout/bonuspack_bubble",
null,
packageName);
if (layoutResId == 0)
Log.e(BonusPackHelper.LOG_TAG,
"ItemizedOverlayWithBubble: layout/bonuspack_bubble not found in "
+ packageName);
}
mBubble = new DefaultInfoWindow(layoutResId, App.view);
}
mItemWithBubble = null;
mOnItemGestureListener = this;
}
public ItemizedOverlayWithBubble(Map map, Context context,
MarkerSymbol marker, List<Item> aList) {
this(map, context, marker, aList, null);
}
@Override
public boolean onItemLongPress(int index, MarkerItem item) {
if (mBubble.isOpen())
hideBubble();
else
showBubble(index);
return false;
}
@Override
public boolean onItemSingleTapUp(int index, MarkerItem item) {
showBubble(index);
return true;
}
private final Point mTmpPoint = new Point();
@Override
protected boolean activateSelectedItems(MotionEvent event, ActiveItem task) {
boolean hit = super.activateSelectedItems(event, task);
if (!hit)
hideBubble();
return hit;
}
@Override
public void onMapEvent(Event e, MapPosition mapPosition) {
if (mBubble.isOpen()) {
GeoPoint gp = mItemWithBubble.getPoint();
Point p = mTmpPoint;
mMap.viewport().toScreenPoint(gp, p);
mBubble.position((int) p.x, (int) p.y);
}
}
void showBubble(int index) {
showBubbleOnItem(index);
}
/**
* Opens the bubble on the item. For each ItemizedOverlay, only one bubble
* is opened at a time. If you want more bubbles opened simultaneously, use
* many ItemizedOverlays.
*
* @param index of the overlay item to show
*/
@SuppressWarnings("unchecked")
public void showBubbleOnItem(int index) {
ExtendedMarkerItem item = (ExtendedMarkerItem) (mItemList.get(index));
mItemWithBubble = item;
if (item != null) {
item.showBubble(mBubble, (Map) mMap);
mMap.animator().animateTo(item.geoPoint);
mMap.updateMap(true);
setFocus((Item) item);
}
}
/**
* Close the bubble (if it's opened).
*/
public void hideBubble() {
mBubble.close();
mItemWithBubble = null;
}
// @Override
// public boolean onSingleTapUp(final MotionEvent event) {
// boolean handled = super.onSingleTapUp(event);
// if (!handled)
// hideBubble();
// return handled;
// }
//
// @Override
// protected boolean onSingleTapUpHelper(final int index, final Item item) {
// showBubbleOnItem(index);
// return true;
// }
/**
* @return the item currenty showing the bubble, or null if none.
*/
public MarkerItem getBubbledItem() {
if (mBubble.isOpen())
return mItemWithBubble;
return null;
}
/**
* @return the index of the item currenty showing the bubble, or -1 if none.
*/
public int getBubbledItemId() {
MarkerItem item = getBubbledItem();
if (item == null)
return -1;
return mItemList.indexOf(item);
}
@Override
public boolean removeItem(final Item item) {
boolean result = super.removeItem(item);
if (mItemWithBubble == item) {
hideBubble();
}
return result;
}
@Override
public void removeAllItems() {
super.removeAllItems();
hideBubble();
}
}

View File

@@ -0,0 +1,34 @@
package org.osmdroid.overlays;
import org.oscim.core.GeoPoint;
/**
* Interface for objects that need to handle map events thrown by a
* MapEventsOverlay.
*
* @author M.Kergall
*/
public interface MapEventsReceiver {
/**
* @param p the position where the event occurred.
* @return true if the event has been "consumed" and should not be handled
* by other objects.
*/
boolean singleTapUpHelper(GeoPoint p);
/**
* @param p the position where the event occurred.
* @return true if the event has been "consumed" and should not be handled
* by other objects.
*/
boolean longPressHelper(GeoPoint p);
/**
* @param p1 p2
* the position where the event occurred for 2 finger.
* @return true if the event has been "consumed" and should not be handled
* by other objects.
*/
boolean longPressHelper(GeoPoint p1, GeoPoint p2);
}