diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2015-12-11 12:39:43 -0800 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2015-12-16 14:52:29 -0800 |
commit | 13d5b18ebaeb330f05c4abfc04e0247222e038ba (patch) | |
tree | 90e24f1fb745581767b6979d1c562e60859cbcf6 /platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations | |
parent | 0db9f229f2bb14e2c6ccd3a8c0d0a30eb25ea5c5 (diff) | |
download | qtlocation-mapboxgl-13d5b18ebaeb330f05c4abfc04e0247222e038ba.tar.gz |
[android] Move into platform subdirectory
Diffstat (limited to 'platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations')
14 files changed, 1336 insertions, 0 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java new file mode 100644 index 0000000000..bf89998788 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java @@ -0,0 +1,92 @@ +package com.mapbox.mapboxsdk.annotations; + +import android.support.annotation.NonNull; + +import com.mapbox.mapboxsdk.views.MapView; + +/** + * Annotation is the most general kind of overlay on top of a map, + * from which {@link InfoWindow} and {@link Marker} are derived: it manages + * attachment to a map and identification, but does not require + * content to be placed at a geographical point. + */ +public abstract class Annotation implements Comparable<Annotation> { + + /** + * <p> + * The annotation id + * </p> + * Internal C++ id is stored as unsigned int. + */ + private long id = -1; // -1 unless added to a MapView + private MapView mapView; + + protected Annotation() { + } + + /** + * <p> + * Gets the annotation's unique ID. + * </p> + * This ID is unique for a MapView instance and is suitable for associating your own extra + * data with. + */ + public long getId() { + return id; + } + + public void remove() { + if (mapView == null) { + return; + } + mapView.removeAnnotation(this); + } + + /** + * Do not use this method. Used internally by the SDK. + */ + public void setId(long id) { + this.id = id; + } + + /** + * Do not use this method. Used internally by the SDK. + */ + public void setMapView(MapView mapView) { + this.mapView = mapView; + } + + protected MapView getMapView() { + if (mapView == null) { + return null; + } + return mapView; + } + + @Override + public int compareTo(@NonNull Annotation annotation) { + if (id < annotation.getId()) { + return 1; + } else if (id > annotation.getId()) { + return -1; + } + + // Equal + return 0; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Annotation that = (Annotation) o; + + return getId() == that.getId(); + } + + @Override + public int hashCode() { + return (int) (getId() ^ (getId() >>> 32)); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java new file mode 100644 index 0000000000..e0433f00d1 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java @@ -0,0 +1,251 @@ +package com.mapbox.mapboxsdk.annotations; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.PointF; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.mapbox.mapboxsdk.R; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.views.MapView; + +import java.lang.ref.WeakReference; + +/** + * <p> + * A tooltip view. This is a UI element placed over a map at a specific geographic + * location. + * </p> + */ +public class InfoWindow { + + private WeakReference<Marker> mBoundMarker; + private WeakReference<MapView> mMapView; + private float mMarkerHeightOffset; + private float mViewWidthOffset; + private PointF mCoordinates; + private boolean mIsVisible; + protected View mView; + + static int mTitleId = 0; + static int mDescriptionId = 0; + static int mSubDescriptionId = 0; + static int mImageId = 0; + + InfoWindow(int layoutResId, MapView mapView) { + View view = LayoutInflater.from(mapView.getContext()).inflate(layoutResId, mapView, false); + + if (mTitleId == 0) { + setResIds(mapView.getContext()); + } + + initialize(view, mapView); + } + + InfoWindow(View view, MapView mapView) { + initialize(view, mapView); + } + + private void initialize(View view, MapView mapView) { + mMapView = new WeakReference<>(mapView); + mIsVisible = false; + mView = view; + + // default behavior: close it when clicking on the tooltip: + mView.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent e) { + if (e.getAction() == MotionEvent.ACTION_UP) { + boolean handledDefaultClick = false; + MapView.OnInfoWindowClickListener onInfoWindowClickListener = + mMapView.get().getOnInfoWindowClickListener(); + if (onInfoWindowClickListener != null) { + handledDefaultClick = onInfoWindowClickListener.onMarkerClick(getBoundMarker()); + } + + if (!handledDefaultClick) { + close(); + } + } + return true; + } + }); + } + + + /** + * open the window at the specified position. + * + * @param boundMarker the marker on which is hooked the view + * @param position to place the window on the map + * @param offsetX (&offsetY) the offset of the view to the position, in pixels. + * This allows to offset the view from the object position. + * @return this infowindow + */ + InfoWindow open(Marker boundMarker, LatLng position, int offsetX, int offsetY) { + setBoundMarker(boundMarker); + + MapView.LayoutParams lp = new MapView.LayoutParams(MapView.LayoutParams.WRAP_CONTENT, MapView.LayoutParams.WRAP_CONTENT); + mView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); + + // Calculate y-offset for update method + mMarkerHeightOffset = -mView.getMeasuredHeight() + offsetY; + + // Calculate default Android x,y coordinate + mCoordinates = mMapView.get().toScreenLocation(position); + float x = mCoordinates.x - (mView.getMeasuredWidth() / 2) + offsetX; + float y = mCoordinates.y - mView.getMeasuredHeight() + offsetY; + + if (mView instanceof InfoWindowView) { + // only apply repositioning/margin for InfoWindowView + Resources resources = mMapView.get().getContext().getResources(); + + // get right/left popup window + float rightSideInfowWindow = x + mView.getMeasuredWidth(); + float leftSideInfoWindow = x; + + // get right/left map view + final float mapRight = mMapView.get().getRight(); + final float mapLeft = mMapView.get().getLeft(); + + float marginHorizontal = resources.getDimension(R.dimen.infowindow_margin); + float tipViewOffset = resources.getDimension(R.dimen.infowindow_tipview_width) / 2; + float tipViewMarginLeft = mView.getMeasuredWidth() / 2 - tipViewOffset; + + boolean outOfBoundsLeft = false; + boolean outOfBoundsRight = false; + + // if out of bounds right + if (rightSideInfowWindow > mapRight) { + outOfBoundsRight = true; + x -= rightSideInfowWindow - mapRight; + tipViewMarginLeft += rightSideInfowWindow - mapRight + tipViewOffset; + rightSideInfowWindow = x + mView.getMeasuredWidth(); + } + + // fit screen left + if (leftSideInfoWindow < mapLeft) { + outOfBoundsLeft = true; + x += mapLeft - leftSideInfoWindow; + tipViewMarginLeft -= mapLeft - leftSideInfoWindow + tipViewOffset; + leftSideInfoWindow = x; + } + + // Add margin right + if (outOfBoundsRight && mapRight - rightSideInfowWindow < marginHorizontal) { + x -= marginHorizontal - (mapRight - rightSideInfowWindow); + tipViewMarginLeft += marginHorizontal - (mapRight - rightSideInfowWindow) - tipViewOffset; + leftSideInfoWindow = x; + } + + // Add margin left + if (outOfBoundsLeft && leftSideInfoWindow - mapLeft < marginHorizontal) { + x += marginHorizontal - (leftSideInfoWindow - mapLeft); + tipViewMarginLeft -= (marginHorizontal - (leftSideInfoWindow - mapLeft)) - tipViewOffset; + } + + // Adjust tipView + InfoWindowView infoWindowView = (InfoWindowView) mView; + infoWindowView.setTipViewMarginLeft((int) tipViewMarginLeft); + } + + // set anchor popupwindowview + mView.setX(x); + mView.setY(y); + + // Calculate x-offset for update method + mViewWidthOffset = x - mCoordinates.x - offsetX; + + close(); //if it was already opened + mMapView.get().addView(mView, lp); + mIsVisible = true; + return this; + } + + /** + * Close this InfoWindow if it is visible, otherwise don't do anything. + * + * @return this info window + */ + InfoWindow close() { + if (mIsVisible) { + mIsVisible = false; + ((ViewGroup) mView.getParent()).removeView(mView); + setBoundMarker(null); + onClose(); + } + return this; + } + + /** + * Constructs the view that is displayed when the InfoWindow opens. + * This retrieves data from overlayItem and shows it in the tooltip. + * + * @param overlayItem the tapped overlay item + */ + void adaptDefaultMarker(Marker overlayItem) { + String title = overlayItem.getTitle(); + ((TextView) mView.findViewById(mTitleId /*R.id.title*/)).setText(title); + String snippet = overlayItem.getSnippet(); + ((TextView) mView.findViewById(mDescriptionId /*R.id.description*/)).setText(snippet); + +/* + //handle sub-description, hiding or showing the text view: + TextView subDescText = (TextView) mView.findViewById(mSubDescriptionId); + String subDesc = overlayItem.getSubDescription(); + if ("".equals(subDesc)) { + subDescText.setVisibility(View.GONE); + } else { + subDescText.setText(subDesc); + subDescText.setVisibility(View.VISIBLE); + } +*/ + } + + private void onClose() { + mMapView.get().deselectMarker(getBoundMarker()); + } + + InfoWindow setBoundMarker(Marker boundMarker) { + mBoundMarker = new WeakReference<>(boundMarker); + return this; + } + + Marker getBoundMarker() { + if (mBoundMarker == null) { + return null; + } + return mBoundMarker.get(); + } + + /** + * Given a context, set the resource ids for the layout + * of the InfoWindow. + * + * @param context the apps Context + */ + private static void setResIds(Context context) { + String packageName = context.getPackageName(); //get application package name + mTitleId = context.getResources().getIdentifier("id/infowindow_title", null, packageName); + mDescriptionId = + context.getResources().getIdentifier("id/infowindow_description", null, packageName); + mSubDescriptionId = context.getResources() + .getIdentifier("id/infowindow_subdescription", null, packageName); + mImageId = context.getResources().getIdentifier("id/infowindow_image", null, packageName); + } + + public void update() { + MapView mapView = mMapView.get(); + Marker marker = mBoundMarker.get(); + if (mapView != null && marker != null) { + mCoordinates = mapView.toScreenLocation(marker.getPosition()); + mView.setX(mCoordinates.x + mViewWidthOffset); + mView.setY(mCoordinates.y + mMarkerHeightOffset); + } + } + +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowTipView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowTipView.java new file mode 100644 index 0000000000..d2afafc59d --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowTipView.java @@ -0,0 +1,62 @@ +package com.mapbox.mapboxsdk.annotations; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.util.AttributeSet; +import android.view.View; + +import com.mapbox.mapboxsdk.R; + +final class InfoWindowTipView extends View { + + private Paint mPaint; + private Path mPath; + private int mLineWidth; + + public InfoWindowTipView(Context context, AttributeSet attrs) { + super(context, attrs); + + mPath = new Path(); + mLineWidth = (int) context.getResources().getDimension(R.dimen.infowindow_line_width); + mPaint = new Paint(); + mPaint.setColor(Color.WHITE); + mPaint.setAntiAlias(true); + mPaint.setStrokeWidth(0.0f); + mPaint.setStyle(Paint.Style.FILL); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + int height = getMeasuredHeight(); + int width = getMeasuredWidth(); + + mPath.rewind(); + + this.mPaint.setColor(Color.WHITE); + this.mPaint.setAntiAlias(true); + this.mPaint.setStrokeWidth(0.0f); + this.mPaint.setStyle(Paint.Style.FILL); + + mPath.moveTo(0, 0); + mPath.lineTo(width, 0); + mPath.lineTo((width / 2), height); + mPath.lineTo(0, 0); + canvas.drawPath(mPath, this.mPaint); + + mPath.rewind(); + + this.mPaint.setColor(Color.parseColor("#C2C2C2")); + this.mPaint.setAntiAlias(true); + this.mPaint.setStrokeWidth(mLineWidth); + this.mPaint.setStyle(Paint.Style.STROKE); + + mPath.moveTo(0, 0); + mPath.lineTo(width / 2, height); + mPath.lineTo(width, 0); + canvas.drawPath(mPath, this.mPaint); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowView.java new file mode 100644 index 0000000000..80dc5931a7 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowView.java @@ -0,0 +1,38 @@ +package com.mapbox.mapboxsdk.annotations; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.widget.RelativeLayout; + +import com.mapbox.mapboxsdk.R; + +class InfoWindowView extends RelativeLayout { + + private InfoWindowTipView mTipView; + + public InfoWindowView(Context context) { + this(context, null); + } + + public InfoWindowView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public InfoWindowView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(context); + } + + private void initialize(Context context) { + LayoutInflater.from(context).inflate(R.layout.infowindow_content, this); + mTipView = (InfoWindowTipView) findViewById(R.id.infowindow_tipview); + } + + void setTipViewMarginLeft(int marginLeft) { + RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) mTipView.getLayoutParams(); + layoutParams.leftMargin = marginLeft; + // This is a bit of a hack but prevents an occasional gap between the InfoWindow + layoutParams.topMargin = (int) getResources().getDimension(R.dimen.infowindow_offset); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java new file mode 100644 index 0000000000..0f626a2618 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java @@ -0,0 +1,158 @@ +package com.mapbox.mapboxsdk.annotations; + +import android.support.annotation.Nullable; +import android.view.View; + +import com.mapbox.mapboxsdk.R; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.views.MapView; + +/** + * A marker is a map overlay that shows an icon image at a specific + * geographical location and can be associated with a {@link InfoWindow} + * that is shown when the marker is tapped. + */ +public final class Marker extends Annotation { + + private LatLng position; + private String snippet; + private Sprite icon; + private String title; + private InfoWindow infoWindow = null; + private boolean infoWindowShown = false; + private int topOffsetPixels; + + /** + * Constructor + */ + Marker() { + super(); + } + + public LatLng getPosition() { + return position; + } + + public String getSnippet() { + return snippet; + } + + public String getTitle() { + return title; + } + + /** + * Do not use this method. Used internally by the SDK. + */ + public void hideInfoWindow() { + if (infoWindow != null) { + infoWindow.close(); + } + infoWindowShown = false; + } + + /** + * Do not use this method. Used internally by the SDK. + */ + public boolean isInfoWindowShown() { + return infoWindowShown; + } + + void setPosition(LatLng position) { + this.position = position; + } + + void setSnippet(String snippet) { + this.snippet = snippet; + } + + /** + * Do not use this method. Used internally by the SDK. + */ + public void setIcon(@Nullable Sprite icon) { + this.icon = icon; + } + + public Sprite getIcon() { + return icon; + } + + void setTitle(String title) { + this.title = title; + } + + /** + * Do not use this method. Used internally by the SDK. + */ + public InfoWindow showInfoWindow() { + if (getMapView() == null) { + return null; + } + + MapView.InfoWindowAdapter infoWindowAdapter = getMapView().getInfoWindowAdapter(); + if (infoWindowAdapter != null) { + // end developer is using a custom InfoWindowAdapter + View content = infoWindowAdapter.getInfoWindow(this); + if (content != null) { + infoWindow = new InfoWindow(content, getMapView()); + showInfoWindow(infoWindow); + return infoWindow; + } + } + + getInfoWindow().adaptDefaultMarker(this); + return showInfoWindow(getInfoWindow()); + } + + private InfoWindow showInfoWindow(InfoWindow iw) { + iw.open(this, getPosition(), 0, topOffsetPixels); + infoWindowShown = true; + return iw; + } + + private InfoWindow getInfoWindow() { + if (infoWindow == null) { + infoWindow = new InfoWindow(R.layout.infowindow_view, getMapView()); + } + return infoWindow; + } + + /* + @Override + void setVisible(boolean visible) { + super.setVisible(visible); + if (!visible && infoWindowShown) { + hideInfoWindow(); + } + } + */ + + /** + * Do not use this method. Used internally by the SDK. + */ + public void setTopOffsetPixels(int topOffsetPixels) { + this.topOffsetPixels = topOffsetPixels; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + + Marker marker = (Marker) o; + return !(getPosition() != null ? !getPosition().equals(marker.getPosition()) : marker.getPosition() != null); + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (getPosition() != null ? getPosition().hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "Marker [position[" + getPosition() + "]]"; + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerOptions.java new file mode 100644 index 0000000000..b5bb24a49d --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerOptions.java @@ -0,0 +1,140 @@ +package com.mapbox.mapboxsdk.annotations; + +import android.graphics.Bitmap; +import android.os.Parcel; +import android.os.Parcelable; +import android.support.annotation.Nullable; + +import com.mapbox.mapboxsdk.geometry.LatLng; + + +/** + * <p> + * A builder object for the options configuration {@link com.mapbox.mapboxsdk.annotations.Marker} and + * {@link com.mapbox.mapboxsdk.annotations.InfoWindow} + * instances on maps. + * </p> + * + * <h3>Example</h3> + * + * <pre> + * mMapView.addMarker(new MarkerOptions() + * .title("Intersection") + * .snippet("H St NW with 15th St NW") + * .position(new LatLng(38.9002073, -77.03364419))); + * </pre> + */ +public final class MarkerOptions implements Parcelable { + + public static final Parcelable.Creator<MarkerOptions> CREATOR + = new Parcelable.Creator<MarkerOptions>() { + public MarkerOptions createFromParcel(Parcel in) { + return new MarkerOptions(in); + } + + public MarkerOptions[] newArray(int size) { + return new MarkerOptions[size]; + } + }; + + private MarkerOptions(Parcel in) { + marker = new Marker(); + position((LatLng) in.readParcelable(LatLng.class.getClassLoader())); + snippet(in.readString()); + String spriteId = in.readString(); + Bitmap spriteBitmap = in.readParcelable(Bitmap.class.getClassLoader()); + Sprite icon = new Sprite(spriteId, spriteBitmap); + icon(icon); + title(in.readString()); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeParcelable(getPosition(), flags); + out.writeString(getSnippet()); + out.writeString(getIcon().getId()); + out.writeParcelable(getIcon().getBitmap(), flags); + out.writeString(getTitle()); + } + + private Marker marker; + + public MarkerOptions() { + marker = new Marker(); + } + + /** + * Do not use this method. Used internally by the SDK. + */ + public Marker getMarker() { + return marker; + } + + public LatLng getPosition() { + return marker.getPosition(); + } + + public String getSnippet() { + return marker.getSnippet(); + } + + public String getTitle() { + return marker.getTitle(); + } + + public Sprite getIcon() { + return marker.getIcon(); + } + + public MarkerOptions position(LatLng position) { + marker.setPosition(position); + return this; + } + + public MarkerOptions snippet(String snippet) { + marker.setSnippet(snippet); + return this; + } + + public MarkerOptions icon(@Nullable Sprite icon) { + marker.setIcon(icon); + return this; + } + + public MarkerOptions title(String title) { + marker.setTitle(title); + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + MarkerOptions marker = (MarkerOptions) o; + + if (getPosition() != null ? !getPosition().equals(marker.getPosition()) : marker.getPosition() != null) + return false; + if (getSnippet() != null ? !getSnippet().equals(marker.getSnippet()) : marker.getSnippet() != null) + return false; + if (getIcon() != null ? !getIcon().equals(marker.getIcon()) : marker.getIcon() != null) + return false; + return !(getTitle() != null ? !getTitle().equals(marker.getTitle()) : marker.getTitle() != null); + + } + + @Override + public int hashCode() { + int result = 1; + result = 31 * result + (getPosition() != null ? getPosition().hashCode() : 0); + result = 31 * result + (getSnippet() != null ? getSnippet().hashCode() : 0); + result = 31 * result + (getIcon() != null ? getIcon().hashCode() : 0); + result = 31 * result + (getTitle() != null ? getTitle().hashCode() : 0); + return result; + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MultiPoint.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MultiPoint.java new file mode 100644 index 0000000000..5c1dfb119f --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MultiPoint.java @@ -0,0 +1,49 @@ +package com.mapbox.mapboxsdk.annotations; + +import com.mapbox.mapboxsdk.geometry.LatLng; + +import java.util.ArrayList; +import java.util.List; + +public abstract class MultiPoint extends Annotation { + + private List<LatLng> points; + private float alpha = 1.0f; + + protected MultiPoint() { + super(); + points = new ArrayList<>(); + } + + /** + * Returns a copy of the points. + * + * @return points - as a copy + */ + public List<LatLng> getPoints() { + return new ArrayList<>(points); + } + + /** + * Sets the points of this polyline. This method will take a copy + * of the points, so further mutations to points will have no effect + * on this polyline. + * + * @param points the points of the polyline + */ + void setPoints(List<LatLng> points) { + this.points = new ArrayList<>(points); + } + + void addPoint(LatLng point) { + points.add(point); + } + + public float getAlpha() { + return alpha; + } + + void setAlpha(float alpha) { + this.alpha = alpha; + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polygon.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polygon.java new file mode 100644 index 0000000000..4a07b16827 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polygon.java @@ -0,0 +1,37 @@ +package com.mapbox.mapboxsdk.annotations; + +import android.graphics.Color; + +import com.mapbox.mapboxsdk.geometry.LatLng; + +import java.util.ArrayList; +import java.util.List; + +/** + * Polygon is a geometry annotation that's a closed loop of coordinates. + */ +public final class Polygon extends MultiPoint { + + private int fillColor = Color.BLACK; // default fillColor is black + private int strokeColor = Color.BLACK; // default strokeColor is black + + Polygon() { + super(); + } + + public int getFillColor() { + return fillColor; + } + + public int getStrokeColor() { + return strokeColor; + } + + void setFillColor(int color) { + fillColor = color; + } + + void setStrokeColor(int color) { + strokeColor = color; + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolygonOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolygonOptions.java new file mode 100644 index 0000000000..c716d10edf --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolygonOptions.java @@ -0,0 +1,146 @@ +package com.mapbox.mapboxsdk.annotations; + + +import android.os.Parcel; +import android.os.Parcelable; + +import com.mapbox.mapboxsdk.geometry.LatLng; + +import java.util.ArrayList; +import java.util.List; + +public final class PolygonOptions implements Parcelable { + + public static final Parcelable.Creator<PolygonOptions> CREATOR + = new Parcelable.Creator<PolygonOptions>() { + public PolygonOptions createFromParcel(Parcel in) { + return new PolygonOptions(in); + } + + public PolygonOptions[] newArray(int size) { + return new PolygonOptions[size]; + } + }; + + private PolygonOptions(Parcel in) { + polygon = new Polygon(); + ArrayList<LatLng> pointsList = new ArrayList<>(); + in.readList(pointsList, LatLng.class.getClassLoader()); + addAll(pointsList); + alpha(in.readFloat()); + fillColor(in.readInt()); + strokeColor(in.readInt()); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeList(getPoints()); + out.writeFloat(getAlpha()); + out.writeInt(getFillColor()); + out.writeInt(getStrokeColor()); + } + + private Polygon polygon; + + public PolygonOptions() { + polygon = new Polygon(); + } + + public PolygonOptions add(LatLng point) { + polygon.addPoint(point); + return this; + } + + public PolygonOptions add(LatLng... points) { + for (LatLng point : points) { + add(point); + } + return this; + } + + public PolygonOptions addAll(Iterable<LatLng> points) { + for (LatLng point : points) { + add(point); + } + return this; + } + + public PolygonOptions alpha(float alpha) { + polygon.setAlpha(alpha); + return this; + } + + public float getAlpha() { + return polygon.getAlpha(); + } + + /** + * Sets the color of the polygon. + * + * @param color - the color in ARGB format + * @return PolygonOptions - the options object + */ + public PolygonOptions fillColor(int color) { + polygon.setFillColor(color); + return this; + } + + public int getFillColor() { + return polygon.getFillColor(); + } + + /** + * Do not use this method. Used internally by the SDK. + */ + public Polygon getPolygon() { + return polygon; + } + + /** + * Sets the color of the stroke of the polygon. + * + * @param color - the color in ARGB format + * @return PolygonOptions - the options object + */ + public PolygonOptions strokeColor(int color) { + polygon.setStrokeColor(color); + return this; + } + + public int getStrokeColor() { + return polygon.getStrokeColor(); + } + + public List<LatLng> getPoints() { + // the getter gives us a copy, which is the safe thing to do... + return polygon.getPoints(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + PolygonOptions polygon = (PolygonOptions) o; + + if (Float.compare(polygon.getAlpha(), getAlpha()) != 0) return false; + if (getFillColor() != polygon.getFillColor()) return false; + if (getStrokeColor() != polygon.getStrokeColor()) return false; + return !(getPoints() != null ? !getPoints().equals(polygon.getPoints()) : polygon.getPoints() != null); + } + + @Override + public int hashCode() { + int result = 1; + result = 31 * result + (getAlpha() != +0.0f ? Float.floatToIntBits(getAlpha()) : 0); + result = 31 * result + getFillColor(); + result = 31 * result + getStrokeColor(); + result = 31 * result + (getPoints() != null ? getPoints().hashCode() : 0); + return result; + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polyline.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polyline.java new file mode 100644 index 0000000000..cfaf0d21d9 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polyline.java @@ -0,0 +1,42 @@ +package com.mapbox.mapboxsdk.annotations; + +import android.graphics.Color; + +/** + * Polyline is a geometry feature with an unclosed list of coordinates drawn as a line + */ +public final class Polyline extends MultiPoint { + + private int color = Color.BLACK; // default color is black + private float width = 10; // As specified by Google API Docs (in pixels) + + Polyline() { + super(); + } + + public int getColor() { + return color; + } + + public float getWidth() { + return width; + } + + /** + * Sets the color of the polyline. + * + * @param color - the color in ARGB format + */ + void setColor(int color) { + this.color = color; + } + + /** + * Sets the width of the polyline. + * + * @param width in pixels + */ + void setWidth(float width) { + this.width = width; + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolylineOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolylineOptions.java new file mode 100644 index 0000000000..d48858c7d9 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolylineOptions.java @@ -0,0 +1,145 @@ +package com.mapbox.mapboxsdk.annotations; + +import android.os.Parcel; +import android.os.Parcelable; + +import com.mapbox.mapboxsdk.geometry.LatLng; + +import java.util.ArrayList; +import java.util.List; + +public final class PolylineOptions implements Parcelable { + + + public static final Parcelable.Creator<PolylineOptions> CREATOR + = new Parcelable.Creator<PolylineOptions>() { + public PolylineOptions createFromParcel(Parcel in) { + return new PolylineOptions(in); + } + + public PolylineOptions[] newArray(int size) { + return new PolylineOptions[size]; + } + }; + + private PolylineOptions(Parcel in) { + polyline = new Polyline(); + ArrayList<LatLng> pointsList = new ArrayList<>(); + in.readList(pointsList, LatLng.class.getClassLoader()); + addAll(pointsList); + alpha(in.readFloat()); + color(in.readInt()); + width(in.readFloat()); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeList(getPoints()); + out.writeFloat(getAlpha()); + out.writeInt(getColor()); + out.writeFloat(getWidth()); + } + + private Polyline polyline; + + public PolylineOptions() { + polyline = new Polyline(); + } + + public PolylineOptions add(LatLng point) { + polyline.addPoint(point); + return this; + } + + public PolylineOptions add(LatLng... points) { + for (LatLng point : points) { + add(point); + } + return this; + } + + public PolylineOptions addAll(Iterable<LatLng> points) { + for (LatLng point : points) { + add(point); + } + return this; + } + + public PolylineOptions alpha(float alpha) { + polyline.setAlpha(alpha); + return this; + } + + public float getAlpha() { + return polyline.getAlpha(); + } + + /** + * Sets the color of the polyline. + * + * @param color - the color in ARGB format + */ + public PolylineOptions color(int color) { + polyline.setColor(color); + return this; + } + + public int getColor() { + return polyline.getColor(); + } + + /** + * Do not use this method. Used internally by the SDK. + */ + public Polyline getPolyline() { + return polyline; + } + + public float getWidth() { + return polyline.getWidth(); + } + + /** + * Sets the width of the polyline. + * + * @param width in pixels + * @return a new PolylineOptions + */ + public PolylineOptions width(float width) { + polyline.setWidth(width); + return this; + } + + public List<LatLng> getPoints() { + // the getter gives us a copy, which is the safe thing to do... + return polyline.getPoints(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + PolylineOptions polyline = (PolylineOptions) o; + + if (Float.compare(polyline.getAlpha(), getAlpha()) != 0) return false; + if (getColor() != polyline.getColor()) return false; + if (Float.compare(polyline.getWidth(), getWidth()) != 0) return false; + return !(getPoints() != null ? !getPoints().equals(polyline.getPoints()) : polyline.getPoints() != null); + } + + @Override + public int hashCode() { + int result = 1; + result = 31 * result + (getAlpha() != +0.0f ? Float.floatToIntBits(getAlpha()) : 0); + result = 31 * result + getColor(); + result = 31 * result + (getWidth() != +0.0f ? Float.floatToIntBits(getWidth()) : 0); + result = 31 * result + (getPoints() != null ? getPoints().hashCode() : 0); + return result; + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Sprite.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Sprite.java new file mode 100644 index 0000000000..597c196d2a --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Sprite.java @@ -0,0 +1,40 @@ +package com.mapbox.mapboxsdk.annotations; + +import android.graphics.Bitmap; + +public final class Sprite { + private Bitmap mBitmap; + private String mId; + + Sprite(String id, Bitmap bitmap) { + mId = id; + mBitmap = bitmap; + } + + public String getId() { + return mId; + } + + public Bitmap getBitmap() { + return mBitmap; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Sprite sprite = (Sprite) o; + + if (!mBitmap.equals(sprite.mBitmap)) return false; + return mId.equals(sprite.mId); + + } + + @Override + public int hashCode() { + int result = mBitmap.hashCode(); + result = 31 * result + mId.hashCode(); + return result; + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/SpriteFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/SpriteFactory.java new file mode 100644 index 0000000000..3395c5039d --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/SpriteFactory.java @@ -0,0 +1,132 @@ +package com.mapbox.mapboxsdk.annotations; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.util.DisplayMetrics; +import android.view.WindowManager; + +import com.mapbox.mapboxsdk.R; +import com.mapbox.mapboxsdk.exceptions.TooManySpritesException; +import com.mapbox.mapboxsdk.views.MapView; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +public final class SpriteFactory { + + private static final String SPRITE_ID_PREFIX = "com.mapbox.sprites.sprite_"; + + private MapView mMapView; + private Sprite mDefaultMarker; + private BitmapFactory.Options mOptions; + + private int mNextId = 0; + + public SpriteFactory(MapView mapView) { + mMapView = mapView; + DisplayMetrics realMetrics = null; + DisplayMetrics metrics = new DisplayMetrics(); + WindowManager wm = (WindowManager) mMapView.getContext().getSystemService(Context.WINDOW_SERVICE); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + realMetrics = new DisplayMetrics(); + wm.getDefaultDisplay().getRealMetrics(realMetrics); + } + wm.getDefaultDisplay().getMetrics(metrics); + + mOptions = new BitmapFactory.Options(); + mOptions.inScaled = true; + mOptions.inDensity = DisplayMetrics.DENSITY_DEFAULT; + mOptions.inTargetDensity = metrics.densityDpi; + if (realMetrics != null) { + mOptions.inScreenDensity = realMetrics.densityDpi; + } + + } + + public Sprite fromBitmap(Bitmap bitmap) { + if (bitmap == null) { + return null; + } + + if (mNextId < 0) { + throw new TooManySpritesException(); + } + String id = SPRITE_ID_PREFIX + ++mNextId; + + return new Sprite(id, bitmap); + } + + public Sprite fromDrawable(Drawable drawable) { + int width = drawable.getIntrinsicWidth(); + int height = drawable.getIntrinsicHeight(); + + return fromDrawable(drawable, width, height); + } + + + public Sprite fromDrawable(Drawable drawable, int width, int height) { + if ((width < 0) || (height < 0)) { + return null; + } + + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + Rect temp = drawable.getBounds(); + Rect bounds = new Rect(0, 0, width, height); + drawable.setBounds(bounds); + drawable.draw(canvas); + drawable.setBounds(temp); + + return fromBitmap(bitmap); + } + + public Sprite fromResource(int resourceId) { + Bitmap bitmap = BitmapFactory.decodeResource(mMapView.getResources(), resourceId); + return fromBitmap(bitmap); + } + + public Sprite defaultMarker() { + if (mDefaultMarker == null) { + mDefaultMarker = fromResource(R.drawable.default_marker); + } + return mDefaultMarker; + } + + private Sprite fromInputStream(InputStream is) { + Bitmap bitmap = BitmapFactory.decodeStream(is, null, mOptions); + return fromBitmap(bitmap); + } + + public Sprite fromAsset(String assetName) { + InputStream is; + try { + is = mMapView.getContext().getAssets().open(assetName); + } catch (IOException e) { + return null; + } + return fromInputStream(is); + } + + public Sprite fromPath(String absolutePath) { + Bitmap bitmap = BitmapFactory.decodeFile(absolutePath, mOptions); + return fromBitmap(bitmap); + } + + public Sprite fromFile(String fileName) { + FileInputStream is; + try { + is = mMapView.getContext().openFileInput(fileName); + } catch (FileNotFoundException e) { + return null; + } + return fromInputStream(is); + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/package-info.java new file mode 100644 index 0000000000..575d10c564 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/package-info.java @@ -0,0 +1,4 @@ +/** + * This package contains classes to add and manage annotations and markers in your map. + */ +package com.mapbox.mapboxsdk.annotations; |