summaryrefslogtreecommitdiff
path: root/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2015-12-11 12:39:43 -0800
committerJohn Firebaugh <john.firebaugh@gmail.com>2015-12-16 14:52:29 -0800
commit13d5b18ebaeb330f05c4abfc04e0247222e038ba (patch)
tree90e24f1fb745581767b6979d1c562e60859cbcf6 /platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations
parent0db9f229f2bb14e2c6ccd3a8c0d0a30eb25ea5c5 (diff)
downloadqtlocation-mapboxgl-13d5b18ebaeb330f05c4abfc04e0247222e038ba.tar.gz
[android] Move into platform subdirectory
Diffstat (limited to 'platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations')
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java92
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java251
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowTipView.java62
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindowView.java38
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java158
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerOptions.java140
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MultiPoint.java49
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polygon.java37
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolygonOptions.java146
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Polyline.java42
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/PolylineOptions.java145
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Sprite.java40
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/SpriteFactory.java132
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/package-info.java4
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;