diff options
author | Cameron Mace <cameron@mapbox.com> | 2016-12-16 16:19:15 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-16 16:19:15 -0500 |
commit | 20b958301eb208fe9ed0ae8edfb14b6f3741d8f2 (patch) | |
tree | 94ae0ce250cda159be13f9a21cc70c92d4908974 /platform/android/MapboxGLAndroidSDK/src/main/java | |
parent | f95b4838ea816b9da0c151a953a1f98f97c79a39 (diff) | |
download | qtlocation-mapboxgl-20b958301eb208fe9ed0ae8edfb14b6f3741d8f2.tar.gz |
Adds checkstyle to CI (#7442)
* adds checkstyle to CI
* fixed gradlew path
* resolved testapp checkstyle violations
* added back mapboxMap variable for test
* checkstyle annotations
* checkstyle SDK round 1
* maps package checkstyle
* rest of SDK checkstyle
* checkstyle gesture library
* checkstyle test
* finished rest of test checkstyle
* resolved all checkstyle errors
* fixed class name
* removed old test file
* fixed camera postion test
* fixed native crash
Diffstat (limited to 'platform/android/MapboxGLAndroidSDK/src/main/java')
112 files changed, 22059 insertions, 21594 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/BaseGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/BaseGestureDetector.java index 622e8f759c..b7bcb925a1 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/BaseGestureDetector.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/BaseGestureDetector.java @@ -6,19 +6,19 @@ import android.view.MotionEvent; /** * @author Almer Thie (code.almeros.com) Copyright (c) 2013, Almer Thie * (code.almeros.com) - * + * <p> * All rights reserved. - * + * <p> * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * <p> * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * <p> * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -33,129 +33,128 @@ import android.view.MotionEvent; * POSSIBILITY OF SUCH DAMAGE. */ public abstract class BaseGestureDetector { - protected final Context mContext; - protected boolean mGestureInProgress; - - protected MotionEvent mPrevEvent; - protected MotionEvent mCurrEvent; - - protected float mCurrPressure; - protected float mPrevPressure; - protected long mTimeDelta; - - /** - * This value is the threshold ratio between the previous combined pressure - * and the current combined pressure. When pressure decreases rapidly - * between events the position values can often be imprecise, as it usually - * indicates that the user is in the process of lifting a pointer off of the - * device. This value was tuned experimentally. - */ - protected static final float PRESSURE_THRESHOLD = 0.67f; - - public BaseGestureDetector(Context context) { - mContext = context; + protected final Context context; + protected boolean gestureInProgress; + + protected MotionEvent prevEvent; + protected MotionEvent currEvent; + + protected float currPressure; + protected float prevPressure; + protected long timeDelta; + + /** + * This value is the threshold ratio between the previous combined pressure + * and the current combined pressure. When pressure decreases rapidly + * between events the position values can often be imprecise, as it usually + * indicates that the user is in the process of lifting a pointer off of the + * device. This value was tuned experimentally. + */ + protected static final float PRESSURE_THRESHOLD = 0.67f; + + public BaseGestureDetector(Context context) { + this.context = context; + } + + /** + * All gesture detectors need to be called through this method to be able to + * detect gestures. This method delegates work to handler methods + * (handleStartProgressEvent, handleInProgressEvent) implemented in + * extending classes. + * + * @param event MotionEvent + * @return {@code true} as handled + */ + public boolean onTouchEvent(MotionEvent event) { + final int actionCode = event.getAction() & MotionEvent.ACTION_MASK; + if (!gestureInProgress) { + handleStartProgressEvent(actionCode, event); + } else { + handleInProgressEvent(actionCode, event); } - - /** - * All gesture detectors need to be called through this method to be able to - * detect gestures. This method delegates work to handler methods - * (handleStartProgressEvent, handleInProgressEvent) implemented in - * extending classes. - * - * @param event MotionEvent - * @return {@code true} as handled - */ - public boolean onTouchEvent(MotionEvent event) { - final int actionCode = event.getAction() & MotionEvent.ACTION_MASK; - if (!mGestureInProgress) { - handleStartProgressEvent(actionCode, event); - } else { - handleInProgressEvent(actionCode, event); - } - return true; - } - - /** - * Called when the current event occurred when NO gesture is in progress - * yet. The handling in this implementation may set the gesture in progress - * (via mGestureInProgress) or out of progress - * - * @param actionCode Action Code from MotionEvent - * @param event MotionEvent - */ - protected abstract void handleStartProgressEvent(int actionCode, - MotionEvent event); - - /** - * Called when the current event occurred when a gesture IS in progress. The - * handling in this implementation may set the gesture out of progress (via - * mGestureInProgress). - * - * - * @param actionCode Action Code from MotionEvent - * @param event MotionEvent - */ - protected abstract void handleInProgressEvent(int actionCode, - MotionEvent event); - - protected void updateStateByEvent(MotionEvent curr) { - final MotionEvent prev = mPrevEvent; - - // Reset mCurrEvent - if (mCurrEvent != null) { - mCurrEvent.recycle(); - mCurrEvent = null; - } - mCurrEvent = MotionEvent.obtain(curr); - - // Delta time - mTimeDelta = curr.getEventTime() - prev.getEventTime(); - - // Pressure - mCurrPressure = curr.getPressure(curr.getActionIndex()); - mPrevPressure = prev.getPressure(prev.getActionIndex()); + return true; + } + + /** + * Called when the current event occurred when NO gesture is in progress + * yet. The handling in this implementation may set the gesture in progress + * (via gestureInProgress) or out of progress + * + * @param actionCode Action Code from MotionEvent + * @param event MotionEvent + */ + protected abstract void handleStartProgressEvent(int actionCode, + MotionEvent event); + + /** + * Called when the current event occurred when a gesture IS in progress. The + * handling in this implementation may set the gesture out of progress (via + * gestureInProgress). + * + * @param actionCode Action Code from MotionEvent + * @param event MotionEvent + */ + protected abstract void handleInProgressEvent(int actionCode, + MotionEvent event); + + protected void updateStateByEvent(MotionEvent curr) { + final MotionEvent prev = prevEvent; + + // Reset currEvent + if (currEvent != null) { + currEvent.recycle(); + currEvent = null; } + currEvent = MotionEvent.obtain(curr); - protected void resetState() { - if (mPrevEvent != null) { - mPrevEvent.recycle(); - mPrevEvent = null; - } - if (mCurrEvent != null) { - mCurrEvent.recycle(); - mCurrEvent = null; - } - mGestureInProgress = false; - } + // Delta time + timeDelta = curr.getEventTime() - prev.getEventTime(); - /** - * Returns {@code true} if a gesture is currently in progress. - * - * @return {@code true} if a gesture is currently in progress, {@code false} - * otherwise. - */ - public boolean isInProgress() { - return mGestureInProgress; - } + // Pressure + currPressure = curr.getPressure(curr.getActionIndex()); + prevPressure = prev.getPressure(prev.getActionIndex()); + } - /** - * Return the time difference in milliseconds between the previous accepted - * GestureDetector event and the current GestureDetector event. - * - * @return Time difference since the last move event in milliseconds. - */ - public long getTimeDelta() { - return mTimeDelta; + protected void resetState() { + if (prevEvent != null) { + prevEvent.recycle(); + prevEvent = null; } - - /** - * Return the event time of the current GestureDetector event being - * processed. - * - * @return Current GestureDetector event time in milliseconds. - */ - public long getEventTime() { - return mCurrEvent.getEventTime(); + if (currEvent != null) { + currEvent.recycle(); + currEvent = null; } + gestureInProgress = false; + } + + /** + * Returns {@code true} if a gesture is currently in progress. + * + * @return {@code true} if a gesture is currently in progress, {@code false} + * otherwise. + */ + public boolean isInProgress() { + return gestureInProgress; + } + + /** + * Return the time difference in milliseconds between the previous accepted + * GestureDetector event and the current GestureDetector event. + * + * @return Time difference since the last move event in milliseconds. + */ + public long getTimeDelta() { + return timeDelta; + } + + /** + * Return the event time of the current GestureDetector event being + * processed. + * + * @return Current GestureDetector event time in milliseconds. + */ + public long getEventTime() { + return currEvent.getEventTime(); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/MoveGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/MoveGestureDetector.java index 2430f3f920..bc7dda6159 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/MoveGestureDetector.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/MoveGestureDetector.java @@ -7,19 +7,19 @@ import android.view.MotionEvent; /** * @author Almer Thie (code.almeros.com) Copyright (c) 2013, Almer Thie * (code.almeros.com) - * + * <p> * All rights reserved. - * + * <p> * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * <p> * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * <p> * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -35,151 +35,151 @@ import android.view.MotionEvent; */ public class MoveGestureDetector extends BaseGestureDetector { - /** - * Listener which must be implemented which is used by MoveGestureDetector - * to perform callbacks to any implementing class which is registered to a - * MoveGestureDetector via the constructor. - * - * @see MoveGestureDetector.SimpleOnMoveGestureListener - */ - public interface OnMoveGestureListener { - public boolean onMove(MoveGestureDetector detector); - - public boolean onMoveBegin(MoveGestureDetector detector); - - public void onMoveEnd(MoveGestureDetector detector); + /** + * Listener which must be implemented which is used by MoveGestureDetector + * to perform callbacks to any implementing class which is registered to a + * MoveGestureDetector via the constructor. + * + * @see MoveGestureDetector.SimpleOnMoveGestureListener + */ + public interface OnMoveGestureListener { + public boolean onMove(MoveGestureDetector detector); + + public boolean onMoveBegin(MoveGestureDetector detector); + + public void onMoveEnd(MoveGestureDetector detector); + } + + /** + * Helper class which may be extended and where the methods may be + * implemented. This way it is not necessary to implement all methods of + * OnMoveGestureListener. + */ + public static class SimpleOnMoveGestureListener implements + OnMoveGestureListener { + public boolean onMove(MoveGestureDetector detector) { + return false; } - /** - * Helper class which may be extended and where the methods may be - * implemented. This way it is not necessary to implement all methods of - * OnMoveGestureListener. - */ - public static class SimpleOnMoveGestureListener implements - OnMoveGestureListener { - public boolean onMove(MoveGestureDetector detector) { - return false; - } - - public boolean onMoveBegin(MoveGestureDetector detector) { - return true; - } + public boolean onMoveBegin(MoveGestureDetector detector) { + return true; + } - public void onMoveEnd(MoveGestureDetector detector) { - // Do nothing, overridden implementation may be used - } + public void onMoveEnd(MoveGestureDetector detector) { + // Do nothing, overridden implementation may be used } + } - private static final PointF FOCUS_DELTA_ZERO = new PointF(); + private static final PointF FOCUS_DELTA_ZERO = new PointF(); - private final OnMoveGestureListener mListener; + private final OnMoveGestureListener listener; - private PointF mFocusExternal = new PointF(); - private PointF mFocusDeltaExternal = new PointF(); + private PointF focusExternal = new PointF(); + private PointF focusDeltaExternal = new PointF(); - public MoveGestureDetector(Context context, OnMoveGestureListener listener) { - super(context); - mListener = listener; - } + public MoveGestureDetector(Context context, OnMoveGestureListener listener) { + super(context); + this.listener = listener; + } - @Override - protected void handleStartProgressEvent(int actionCode, MotionEvent event) { - switch (actionCode) { - case MotionEvent.ACTION_DOWN: - resetState(); // In case we missed an UP/CANCEL event + @Override + protected void handleStartProgressEvent(int actionCode, MotionEvent event) { + switch (actionCode) { + case MotionEvent.ACTION_DOWN: + resetState(); // In case we missed an UP/CANCEL event - mPrevEvent = MotionEvent.obtain(event); - mTimeDelta = 0; + prevEvent = MotionEvent.obtain(event); + timeDelta = 0; - updateStateByEvent(event); - break; + updateStateByEvent(event); + break; - case MotionEvent.ACTION_MOVE: - mGestureInProgress = mListener.onMoveBegin(this); - break; - } + case MotionEvent.ACTION_MOVE: + gestureInProgress = listener.onMoveBegin(this); + break; } - - @Override - protected void handleInProgressEvent(int actionCode, MotionEvent event) { - switch (actionCode) { - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - mListener.onMoveEnd(this); - resetState(); - break; - - case MotionEvent.ACTION_MOVE: - updateStateByEvent(event); - - // Only accept the event if our relative pressure is within - // a certain limit. This can help filter shaky data as a - // finger is lifted. - if (mCurrPressure / mPrevPressure > PRESSURE_THRESHOLD) { - final boolean updatePrevious = mListener.onMove(this); - if (updatePrevious) { - mPrevEvent.recycle(); - mPrevEvent = MotionEvent.obtain(event); - } - } - break; + } + + @Override + protected void handleInProgressEvent(int actionCode, MotionEvent event) { + switch (actionCode) { + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + listener.onMoveEnd(this); + resetState(); + break; + + case MotionEvent.ACTION_MOVE: + updateStateByEvent(event); + + // Only accept the event if our relative pressure is within + // a certain limit. This can help filter shaky data as a + // finger is lifted. + if (currPressure / prevPressure > PRESSURE_THRESHOLD) { + final boolean updatePrevious = listener.onMove(this); + if (updatePrevious) { + prevEvent.recycle(); + prevEvent = MotionEvent.obtain(event); + } } + break; } - - protected void updateStateByEvent(MotionEvent curr) { - super.updateStateByEvent(curr); - - final MotionEvent prev = mPrevEvent; - - // Focus intenal - PointF mCurrFocusInternal = determineFocalPoint(curr); - PointF mPrevFocusInternal = determineFocalPoint(prev); - - // Focus external - // - Prevent skipping of focus delta when a finger is added or removed - boolean mSkipNextMoveEvent = prev.getPointerCount() != curr - .getPointerCount(); - mFocusDeltaExternal = mSkipNextMoveEvent ? FOCUS_DELTA_ZERO - : new PointF(mCurrFocusInternal.x - mPrevFocusInternal.x, - mCurrFocusInternal.y - mPrevFocusInternal.y); - - // - Don't directly use mFocusInternal (or skipping will occur). Add - // unskipped delta values to mFocusExternal instead. - mFocusExternal.x += mFocusDeltaExternal.x; - mFocusExternal.y += mFocusDeltaExternal.y; + } + + protected void updateStateByEvent(MotionEvent curr) { + super.updateStateByEvent(curr); + + final MotionEvent prev = prevEvent; + + // Focus intenal + PointF currFocusInternal = determineFocalPoint(curr); + PointF prevFocusInternal = determineFocalPoint(prev); + + // Focus external + // - Prevent skipping of focus delta when a finger is added or removed + boolean skipNextMoveEvent = prev.getPointerCount() != curr + .getPointerCount(); + focusDeltaExternal = skipNextMoveEvent ? FOCUS_DELTA_ZERO + : new PointF(currFocusInternal.x - prevFocusInternal.x, + currFocusInternal.y - prevFocusInternal.y); + + // - Don't directly use mFocusInternal (or skipping will occur). Add + // unskipped delta values to focusExternal instead. + focusExternal.x += focusDeltaExternal.x; + focusExternal.y += focusDeltaExternal.y; + } + + /** + * Determine (multi)finger focal point (a.k.a. center point between all + * fingers) + * + * @param motionEvent a {@link MotionEvent} object. + * @return PointF focal point + */ + private PointF determineFocalPoint(MotionEvent motionEvent) { + // Number of fingers on screen + final int pCount = motionEvent.getPointerCount(); + float x = 0.0f; + float y = 0.0f; + + for (int i = 0; i < pCount; i++) { + x += motionEvent.getX(i); + y += motionEvent.getY(i); } - /** - * Determine (multi)finger focal point (a.k.a. center point between all - * fingers) - * - * @param e - * @return PointF focal point - */ - private PointF determineFocalPoint(MotionEvent e) { - // Number of fingers on screen - final int pCount = e.getPointerCount(); - float x = 0.0f; - float y = 0.0f; - - for (int i = 0; i < pCount; i++) { - x += e.getX(i); - y += e.getY(i); - } - - return new PointF(x / pCount, y / pCount); - } + return new PointF(x / pCount, y / pCount); + } - public float getFocusX() { - return mFocusExternal.x; - } + public float getFocusX() { + return focusExternal.x; + } - public float getFocusY() { - return mFocusExternal.y; - } + public float getFocusY() { + return focusExternal.y; + } - public PointF getFocusDelta() { - return mFocusDeltaExternal; - } + public PointF getFocusDelta() { + return focusDeltaExternal; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/RotateGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/RotateGestureDetector.java index 124fe8509c..8c111a68df 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/RotateGestureDetector.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/RotateGestureDetector.java @@ -6,19 +6,19 @@ import android.view.MotionEvent; /** * @author Almer Thie (code.almeros.com) Copyright (c) 2013, Almer Thie * (code.almeros.com) - * + * <p> * All rights reserved. - * + * <p> * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * <p> * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * <p> * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -34,147 +34,147 @@ import android.view.MotionEvent; */ public class RotateGestureDetector extends TwoFingerGestureDetector { - /** - * Listener which must be implemented which is used by RotateGestureDetector - * to perform callbacks to any implementing class which is registered to a - * RotateGestureDetector via the constructor. - * - * @see RotateGestureDetector.SimpleOnRotateGestureListener - */ - public interface OnRotateGestureListener { - public boolean onRotate(RotateGestureDetector detector); - - public boolean onRotateBegin(RotateGestureDetector detector); + /** + * Listener which must be implemented which is used by RotateGestureDetector + * to perform callbacks to any implementing class which is registered to a + * RotateGestureDetector via the constructor. + * + * @see RotateGestureDetector.SimpleOnRotateGestureListener + */ + public interface OnRotateGestureListener { + public boolean onRotate(RotateGestureDetector detector); + + public boolean onRotateBegin(RotateGestureDetector detector); + + public void onRotateEnd(RotateGestureDetector detector); + } + + /** + * Helper class which may be extended and where the methods may be + * implemented. This way it is not necessary to implement all methods of + * OnRotateGestureListener. + */ + public static class SimpleOnRotateGestureListener implements + OnRotateGestureListener { + public boolean onRotate(RotateGestureDetector detector) { + return false; + } - public void onRotateEnd(RotateGestureDetector detector); + public boolean onRotateBegin(RotateGestureDetector detector) { + return true; } - /** - * Helper class which may be extended and where the methods may be - * implemented. This way it is not necessary to implement all methods of - * OnRotateGestureListener. - */ - public static class SimpleOnRotateGestureListener implements - OnRotateGestureListener { - public boolean onRotate(RotateGestureDetector detector) { - return false; + public void onRotateEnd(RotateGestureDetector detector) { + // Do nothing, overridden implementation may be used + } + } + + private final OnRotateGestureListener listener; + private boolean sloppyGesture; + + public RotateGestureDetector(Context context, + OnRotateGestureListener listener) { + super(context); + this.listener = listener; + } + + @Override + protected void handleStartProgressEvent(int actionCode, MotionEvent event) { + switch (actionCode) { + case MotionEvent.ACTION_POINTER_DOWN: + // At least the second finger is on screen now + + resetState(); // In case we missed an UP/CANCEL event + prevEvent = MotionEvent.obtain(event); + timeDelta = 0; + + updateStateByEvent(event); + + // See if we have a sloppy gesture + sloppyGesture = isSloppyGesture(event); + if (!sloppyGesture) { + // No, start gesture now + gestureInProgress = listener.onRotateBegin(this); } + break; - public boolean onRotateBegin(RotateGestureDetector detector) { - return true; + case MotionEvent.ACTION_MOVE: + if (!sloppyGesture) { + break; } - public void onRotateEnd(RotateGestureDetector detector) { - // Do nothing, overridden implementation may be used + // See if we still have a sloppy gesture + sloppyGesture = isSloppyGesture(event); + if (!sloppyGesture) { + // No, start normal gesture now + gestureInProgress = listener.onRotateBegin(this); } - } - private final OnRotateGestureListener mListener; - private boolean mSloppyGesture; + break; - public RotateGestureDetector(Context context, - OnRotateGestureListener listener) { - super(context); - mListener = listener; - } - - @Override - protected void handleStartProgressEvent(int actionCode, MotionEvent event) { - switch (actionCode) { - case MotionEvent.ACTION_POINTER_DOWN: - // At least the second finger is on screen now - - resetState(); // In case we missed an UP/CANCEL event - mPrevEvent = MotionEvent.obtain(event); - mTimeDelta = 0; - - updateStateByEvent(event); - - // See if we have a sloppy gesture - mSloppyGesture = isSloppyGesture(event); - if (!mSloppyGesture) { - // No, start gesture now - mGestureInProgress = mListener.onRotateBegin(this); - } - break; - - case MotionEvent.ACTION_MOVE: - if (!mSloppyGesture) { - break; - } - - // See if we still have a sloppy gesture - mSloppyGesture = isSloppyGesture(event); - if (!mSloppyGesture) { - // No, start normal gesture now - mGestureInProgress = mListener.onRotateBegin(this); - } - - break; - - case MotionEvent.ACTION_POINTER_UP: - if (!mSloppyGesture) { - break; - } - - break; + case MotionEvent.ACTION_POINTER_UP: + if (!sloppyGesture) { + break; } + + break; } + } - @Override - protected void handleInProgressEvent(int actionCode, MotionEvent event) { - switch (actionCode) { - case MotionEvent.ACTION_POINTER_UP: - // Gesture ended but - updateStateByEvent(event); - - if (!mSloppyGesture) { - mListener.onRotateEnd(this); - } - - resetState(); - break; - - case MotionEvent.ACTION_CANCEL: - if (!mSloppyGesture) { - mListener.onRotateEnd(this); - } - - resetState(); - break; - - case MotionEvent.ACTION_MOVE: - updateStateByEvent(event); - - // Only accept the event if our relative pressure is within - // a certain limit. This can help filter shaky data as a - // finger is lifted. - if (mCurrPressure / mPrevPressure > PRESSURE_THRESHOLD) { - final boolean updatePrevious = mListener.onRotate(this); - if (updatePrevious) { - mPrevEvent.recycle(); - mPrevEvent = MotionEvent.obtain(event); - } - } - break; + @Override + protected void handleInProgressEvent(int actionCode, MotionEvent event) { + switch (actionCode) { + case MotionEvent.ACTION_POINTER_UP: + // Gesture ended but + updateStateByEvent(event); + + if (!sloppyGesture) { + listener.onRotateEnd(this); } - } - @Override - protected void resetState() { - super.resetState(); - mSloppyGesture = false; - } + resetState(); + break; - /** - * Return the rotation difference from the previous rotate event to the - * current event. - * - * @return The current rotation //difference in degrees. - */ - public float getRotationDegreesDelta() { - double diffRadians = Math.atan2(mPrevFingerDiffY, mPrevFingerDiffX) - - Math.atan2(mCurrFingerDiffY, mCurrFingerDiffX); - return (float) (diffRadians * 180.0 / Math.PI); + case MotionEvent.ACTION_CANCEL: + if (!sloppyGesture) { + listener.onRotateEnd(this); + } + + resetState(); + break; + + case MotionEvent.ACTION_MOVE: + updateStateByEvent(event); + + // Only accept the event if our relative pressure is within + // a certain limit. This can help filter shaky data as a + // finger is lifted. + if (currPressure / prevPressure > PRESSURE_THRESHOLD) { + final boolean updatePrevious = listener.onRotate(this); + if (updatePrevious) { + prevEvent.recycle(); + prevEvent = MotionEvent.obtain(event); + } + } + break; } + } + + @Override + protected void resetState() { + super.resetState(); + sloppyGesture = false; + } + + /** + * Return the rotation difference from the previous rotate event to the + * current event. + * + * @return The current rotation //difference in degrees. + */ + public float getRotationDegreesDelta() { + double diffRadians = Math.atan2(prevFingerDiffY, prevFingerDiffX) + - Math.atan2(currFingerDiffY, currFingerDiffX); + return (float) (diffRadians * 180.0 / Math.PI); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/ShoveGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/ShoveGestureDetector.java index 254597105b..9396578e48 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/ShoveGestureDetector.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/ShoveGestureDetector.java @@ -5,21 +5,21 @@ import android.view.MotionEvent; /** * @author Robert Nordan (robert.nordan@norkart.no) - * + * <p> * Copyright (c) 2013, Norkart AS - * + * <p> * All rights reserved. - * + * <p> * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * <p> * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * <p> * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -35,179 +35,180 @@ import android.view.MotionEvent; */ public class ShoveGestureDetector extends TwoFingerGestureDetector { - /** - * Listener which must be implemented which is used by ShoveGestureDetector - * to perform callbacks to any implementing class which is registered to a - * ShoveGestureDetector via the constructor. - * - * @see ShoveGestureDetector.SimpleOnShoveGestureListener - */ - public interface OnShoveGestureListener { - public boolean onShove(ShoveGestureDetector detector); + /** + * Listener which must be implemented which is used by ShoveGestureDetector + * to perform callbacks to any implementing class which is registered to a + * ShoveGestureDetector via the constructor. + * + * @see ShoveGestureDetector.SimpleOnShoveGestureListener + */ + public interface OnShoveGestureListener { + public boolean onShove(ShoveGestureDetector detector); + + public boolean onShoveBegin(ShoveGestureDetector detector); + + public void onShoveEnd(ShoveGestureDetector detector); + } + + /** + * Helper class which may be extended and where the methods may be + * implemented. This way it is not necessary to implement all methods of + * OnShoveGestureListener. + */ + public static class SimpleOnShoveGestureListener implements + OnShoveGestureListener { + public boolean onShove(ShoveGestureDetector detector) { + return false; + } - public boolean onShoveBegin(ShoveGestureDetector detector); + public boolean onShoveBegin(ShoveGestureDetector detector) { + return true; + } - public void onShoveEnd(ShoveGestureDetector detector); + public void onShoveEnd(ShoveGestureDetector detector) { + // Do nothing, overridden implementation may be used } + } + + private float prevAverageY; + private float currAverageY; + + private final OnShoveGestureListener listener; + private boolean sloppyGesture; + + public ShoveGestureDetector(Context context, OnShoveGestureListener listener) { + super(context); + this.listener = listener; + } - /** - * Helper class which may be extended and where the methods may be - * implemented. This way it is not necessary to implement all methods of - * OnShoveGestureListener. - */ - public static class SimpleOnShoveGestureListener implements - OnShoveGestureListener { - public boolean onShove(ShoveGestureDetector detector) { - return false; + @Override + protected void handleStartProgressEvent(int actionCode, MotionEvent event) { + switch (actionCode) { + case MotionEvent.ACTION_POINTER_DOWN: + // At least the second finger is on screen now + + resetState(); // In case we missed an UP/CANCEL event + prevEvent = MotionEvent.obtain(event); + timeDelta = 0; + + updateStateByEvent(event); + + // See if we have a sloppy gesture + sloppyGesture = isSloppyGesture(event); + if (!sloppyGesture) { + // No, start gesture now + gestureInProgress = listener.onShoveBegin(this); } + break; - public boolean onShoveBegin(ShoveGestureDetector detector) { - return true; + case MotionEvent.ACTION_MOVE: + if (!sloppyGesture) { + break; } - public void onShoveEnd(ShoveGestureDetector detector) { - // Do nothing, overridden implementation may be used + // See if we still have a sloppy gesture + sloppyGesture = isSloppyGesture(event); + if (!sloppyGesture) { + // No, start normal gesture now + gestureInProgress = listener.onShoveBegin(this); } - } - private float mPrevAverageY; - private float mCurrAverageY; + break; - private final OnShoveGestureListener mListener; - private boolean mSloppyGesture; + case MotionEvent.ACTION_POINTER_UP: + if (!sloppyGesture) { + break; + } - public ShoveGestureDetector(Context context, OnShoveGestureListener listener) { - super(context); - mListener = listener; + break; } + } - @Override - protected void handleStartProgressEvent(int actionCode, MotionEvent event) { - switch (actionCode) { - case MotionEvent.ACTION_POINTER_DOWN: - // At least the second finger is on screen now - - resetState(); // In case we missed an UP/CANCEL event - mPrevEvent = MotionEvent.obtain(event); - mTimeDelta = 0; - - updateStateByEvent(event); - - // See if we have a sloppy gesture - mSloppyGesture = isSloppyGesture(event); - if (!mSloppyGesture) { - // No, start gesture now - mGestureInProgress = mListener.onShoveBegin(this); - } - break; - - case MotionEvent.ACTION_MOVE: - if (!mSloppyGesture) { - break; - } - - // See if we still have a sloppy gesture - mSloppyGesture = isSloppyGesture(event); - if (!mSloppyGesture) { - // No, start normal gesture now - mGestureInProgress = mListener.onShoveBegin(this); - } - - break; - - case MotionEvent.ACTION_POINTER_UP: - if (!mSloppyGesture) { - break; - } - - break; - } - } + @Override + protected void handleInProgressEvent(int actionCode, MotionEvent event) { + switch (actionCode) { + case MotionEvent.ACTION_POINTER_UP: + // Gesture ended but + updateStateByEvent(event); - @Override - protected void handleInProgressEvent(int actionCode, MotionEvent event) { - switch (actionCode) { - case MotionEvent.ACTION_POINTER_UP: - // Gesture ended but - updateStateByEvent(event); - - if (!mSloppyGesture) { - mListener.onShoveEnd(this); - } - - resetState(); - break; - - case MotionEvent.ACTION_CANCEL: - if (!mSloppyGesture) { - mListener.onShoveEnd(this); - } - - resetState(); - break; - - case MotionEvent.ACTION_MOVE: - updateStateByEvent(event); - - // Only accept the event if our relative pressure is within - // a certain limit. This can help filter shaky data as a - // finger is lifted. Also check that shove is meaningful. - if (mCurrPressure / mPrevPressure > PRESSURE_THRESHOLD - && Math.abs(getShovePixelsDelta()) > 0.5f) { - final boolean updatePrevious = mListener.onShove(this); - if (updatePrevious) { - mPrevEvent.recycle(); - mPrevEvent = MotionEvent.obtain(event); - } - } - break; + if (!sloppyGesture) { + listener.onShoveEnd(this); } - } - - @Override - protected void resetState() { - super.resetState(); - mSloppyGesture = false; - mPrevAverageY = 0.0f; - mCurrAverageY = 0.0f; - } - @Override - protected void updateStateByEvent(MotionEvent curr) { - super.updateStateByEvent(curr); + resetState(); + break; - final MotionEvent prev = mPrevEvent; - float py0 = prev.getY(0); - float py1 = prev.getY(1); - mPrevAverageY = (py0 + py1) / 2.0f; + case MotionEvent.ACTION_CANCEL: + if (!sloppyGesture) { + listener.onShoveEnd(this); + } - float cy0 = curr.getY(0); - float cy1 = curr.getY(1); - mCurrAverageY = (cy0 + cy1) / 2.0f; + resetState(); + break; + + case MotionEvent.ACTION_MOVE: + updateStateByEvent(event); + + // Only accept the event if our relative pressure is within + // a certain limit. This can help filter shaky data as a + // finger is lifted. Also check that shove is meaningful. + if (currPressure / prevPressure > PRESSURE_THRESHOLD + && Math.abs(getShovePixelsDelta()) > 0.5f) { + final boolean updatePrevious = listener.onShove(this); + if (updatePrevious) { + prevEvent.recycle(); + prevEvent = MotionEvent.obtain(event); + } + } + break; } - - @Override - protected boolean isSloppyGesture(MotionEvent event) { - boolean sloppy = super.isSloppyGesture(event); - if (sloppy) - return true; - - // If it's not traditionally sloppy, we check if the angle between - // fingers - // is acceptable. - double angle = Math.abs(Math.atan2(mCurrFingerDiffY, mCurrFingerDiffX)); - // about 20 degrees, left or right - return !((0.0f < angle && angle < 0.35f) || 2.79f < angle - && angle < Math.PI); + } + + @Override + protected void resetState() { + super.resetState(); + sloppyGesture = false; + prevAverageY = 0.0f; + currAverageY = 0.0f; + } + + @Override + protected void updateStateByEvent(MotionEvent curr) { + super.updateStateByEvent(curr); + + final MotionEvent prev = prevEvent; + float py0 = prev.getY(0); + float py1 = prev.getY(1); + prevAverageY = (py0 + py1) / 2.0f; + + float cy0 = curr.getY(0); + float cy1 = curr.getY(1); + currAverageY = (cy0 + cy1) / 2.0f; + } + + @Override + protected boolean isSloppyGesture(MotionEvent event) { + boolean sloppy = super.isSloppyGesture(event); + if (sloppy) { + return true; } - /** - * Return the distance in pixels from the previous shove event to the - * current event. - * - * @return The current distance in pixels. - */ - public float getShovePixelsDelta() { - return mCurrAverageY - mPrevAverageY; - } + // If it's not traditionally sloppy, we check if the angle between + // fingers + // is acceptable. + double angle = Math.abs(Math.atan2(currFingerDiffY, currFingerDiffX)); + // about 20 degrees, left or right + return !((0.0f < angle && angle < 0.35f) || 2.79f < angle + && angle < Math.PI); + } + + /** + * Return the distance in pixels from the previous shove event to the + * current event. + * + * @return The current distance in pixels. + */ + public float getShovePixelsDelta() { + return currAverageY - prevAverageY; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/TwoFingerGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/TwoFingerGestureDetector.java index 694bea9f30..71fb9aa168 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/TwoFingerGestureDetector.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/almeros/android/multitouch/gesturedetectors/TwoFingerGestureDetector.java @@ -9,19 +9,19 @@ import android.view.ViewConfiguration; /** * @author Almer Thie (code.almeros.com) Copyright (c) 2013, Almer Thie * (code.almeros.com) - * + * <p> * All rights reserved. - * + * <p> * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * <p> * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * <p> * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -37,189 +37,189 @@ import android.view.ViewConfiguration; */ public abstract class TwoFingerGestureDetector extends BaseGestureDetector { - private final float mEdgeSlop; - - protected float mPrevFingerDiffX; - protected float mPrevFingerDiffY; - protected float mCurrFingerDiffX; - protected float mCurrFingerDiffY; - - private float mCurrLen; - private float mPrevLen; - - private PointF mFocus; - - public TwoFingerGestureDetector(Context context) { - super(context); - - ViewConfiguration config = ViewConfiguration.get(context); - - // We divide edge slop by 2 to make rotation gesture happen more easily #6870 - mEdgeSlop = config.getScaledEdgeSlop() / 2; - } - - @Override - protected abstract void handleStartProgressEvent(int actionCode, - MotionEvent event); - - @Override - protected abstract void handleInProgressEvent(int actionCode, - MotionEvent event); - - protected void updateStateByEvent(MotionEvent curr) { - super.updateStateByEvent(curr); - - final MotionEvent prev = mPrevEvent; - - mCurrLen = -1; - mPrevLen = -1; - - // Previous - final float px0 = prev.getX(0); - final float py0 = prev.getY(0); - final float px1 = prev.getX(1); - final float py1 = prev.getY(1); - final float pvx = px1 - px0; - final float pvy = py1 - py0; - mPrevFingerDiffX = pvx; - mPrevFingerDiffY = pvy; - - // Current - final float cx0 = curr.getX(0); - final float cy0 = curr.getY(0); - final float cx1 = curr.getX(1); - final float cy1 = curr.getY(1); - final float cvx = cx1 - cx0; - final float cvy = cy1 - cy0; - mCurrFingerDiffX = cvx; - mCurrFingerDiffY = cvy; - mFocus = determineFocalPoint(curr); + private final float edgeSlop; + + protected float prevFingerDiffX; + protected float prevFingerDiffY; + protected float currFingerDiffX; + protected float currFingerDiffY; + + private float currLen; + private float prevLen; + + private PointF focus; + + public TwoFingerGestureDetector(Context context) { + super(context); + + ViewConfiguration config = ViewConfiguration.get(context); + + // We divide edge slop by 2 to make rotation gesture happen more easily #6870 + edgeSlop = config.getScaledEdgeSlop() / 2; + } + + @Override + protected abstract void handleStartProgressEvent(int actionCode, + MotionEvent event); + + @Override + protected abstract void handleInProgressEvent(int actionCode, + MotionEvent event); + + protected void updateStateByEvent(MotionEvent curr) { + super.updateStateByEvent(curr); + + final MotionEvent prev = prevEvent; + + currLen = -1; + prevLen = -1; + + // Previous + final float px0 = prev.getX(0); + final float py0 = prev.getY(0); + final float px1 = prev.getX(1); + final float py1 = prev.getY(1); + final float pvx = px1 - px0; + final float pvy = py1 - py0; + prevFingerDiffX = pvx; + prevFingerDiffY = pvy; + + // Current + final float cx0 = curr.getX(0); + final float cy0 = curr.getY(0); + final float cx1 = curr.getX(1); + final float cy1 = curr.getY(1); + final float cvx = cx1 - cx0; + final float cvy = cy1 - cy0; + currFingerDiffX = cvx; + currFingerDiffY = cvy; + focus = determineFocalPoint(curr); + } + + /** + * Return the current distance between the two pointers forming the gesture + * in progress. + * + * @return Distance between pointers in pixels. + */ + public float getCurrentSpan() { + if (currLen == -1) { + final float cvx = currFingerDiffX; + final float cvy = currFingerDiffY; + currLen = (float) Math.sqrt(cvx * cvx + cvy * cvy); } - - /** - * Return the current distance between the two pointers forming the gesture - * in progress. - * - * @return Distance between pointers in pixels. - */ - public float getCurrentSpan() { - if (mCurrLen == -1) { - final float cvx = mCurrFingerDiffX; - final float cvy = mCurrFingerDiffY; - mCurrLen = (float) Math.sqrt(cvx * cvx + cvy * cvy); - } - return mCurrLen; + return currLen; + } + + /** + * Return the previous distance between the two pointers forming the gesture + * in progress. + * + * @return Previous distance between pointers in pixels. + */ + public float getPreviousSpan() { + if (prevLen == -1) { + final float pvx = prevFingerDiffX; + final float pvy = prevFingerDiffY; + prevLen = (float) Math.sqrt(pvx * pvx + pvy * pvy); } - - /** - * Return the previous distance between the two pointers forming the gesture - * in progress. - * - * @return Previous distance between pointers in pixels. - */ - public float getPreviousSpan() { - if (mPrevLen == -1) { - final float pvx = mPrevFingerDiffX; - final float pvy = mPrevFingerDiffY; - mPrevLen = (float) Math.sqrt(pvx * pvx + pvy * pvy); - } - return mPrevLen; + return prevLen; + } + + /** + * MotionEvent has no getRawX(int) method; simulate it pending future API + * approval. + * + * @param event Motion Event + * @param pointerIndex Pointer Index + * @return Raw x value or 0 + */ + protected static float getRawX(MotionEvent event, int pointerIndex) { + float offset = event.getRawX() - event.getX(); + if (pointerIndex < event.getPointerCount()) { + return event.getX(pointerIndex) + offset; } - - /** - * MotionEvent has no getRawX(int) method; simulate it pending future API - * approval. - * - * @param event Motion Event - * @param pointerIndex Pointer Index - * @return Raw x value or 0 - */ - protected static float getRawX(MotionEvent event, int pointerIndex) { - float offset = event.getRawX() - event.getX(); - if (pointerIndex < event.getPointerCount()) { - return event.getX(pointerIndex) + offset; - } - return 0.0f; + return 0.0f; + } + + /** + * MotionEvent has no getRawY(int) method; simulate it pending future API + * approval. + * + * @param event Motion Event + * @param pointerIndex Pointer Index + * @return Raw y value or 0 + */ + protected static float getRawY(MotionEvent event, int pointerIndex) { + float offset = event.getRawY() - event.getY(); + if (pointerIndex < event.getPointerCount()) { + return event.getY(pointerIndex) + offset; } - - /** - * MotionEvent has no getRawY(int) method; simulate it pending future API - * approval. - * - * @param event Motion Event - * @param pointerIndex Pointer Index - * @return Raw y value or 0 - */ - protected static float getRawY(MotionEvent event, int pointerIndex) { - float offset = event.getRawY() - event.getY(); - if (pointerIndex < event.getPointerCount()) { - return event.getY(pointerIndex) + offset; - } - return 0.0f; + return 0.0f; + } + + /** + * Check if we have a sloppy gesture. Sloppy gestures can happen if the edge + * of the user's hand is touching the screen, for example. + * + * @param event Motion Event + * @return {@code true} if is sloppy gesture, {@code false} if not + */ + protected boolean isSloppyGesture(MotionEvent event) { + // As orientation can change, query the metrics in touch down + DisplayMetrics metrics = context.getResources().getDisplayMetrics(); + float rightSlopEdge = metrics.widthPixels - edgeSlop; + float bottomSlopEdge = metrics.heightPixels - edgeSlop; + + final float edgeSlop = this.edgeSlop; + + final float x0 = event.getRawX(); + final float y0 = event.getRawY(); + final float x1 = getRawX(event, 1); + final float y1 = getRawY(event, 1); + + boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop || x0 > rightSlopEdge + || y0 > bottomSlopEdge; + boolean p1sloppy = x1 < edgeSlop || y1 < edgeSlop || x1 > rightSlopEdge + || y1 > bottomSlopEdge; + + if (p0sloppy && p1sloppy) { + return true; + } else if (p0sloppy) { + return true; + } else if (p1sloppy) { + return true; } - - /** - * Check if we have a sloppy gesture. Sloppy gestures can happen if the edge - * of the user's hand is touching the screen, for example. - * - * @param event Motion Event - * @return {@code true} if is sloppy gesture, {@code false} if not - */ - protected boolean isSloppyGesture(MotionEvent event) { - // As orientation can change, query the metrics in touch down - DisplayMetrics metrics = mContext.getResources().getDisplayMetrics(); - float mRightSlopEdge = metrics.widthPixels - mEdgeSlop; - float mBottomSlopEdge = metrics.heightPixels - mEdgeSlop; - - final float edgeSlop = mEdgeSlop; - - final float x0 = event.getRawX(); - final float y0 = event.getRawY(); - final float x1 = getRawX(event, 1); - final float y1 = getRawY(event, 1); - - boolean p0sloppy = x0 < edgeSlop || y0 < edgeSlop || x0 > mRightSlopEdge - || y0 > mBottomSlopEdge; - boolean p1sloppy = x1 < edgeSlop || y1 < edgeSlop || x1 > mRightSlopEdge - || y1 > mBottomSlopEdge; - - if (p0sloppy && p1sloppy) { - return true; - } else if (p0sloppy) { - return true; - } else if (p1sloppy) { - return true; - } - return false; + return false; + } + + /** + * Determine (multi)finger focal point (a.k.a. center point between all + * fingers) + * + * @param motionEvent Motion Event + * @return PointF focal point + */ + public static PointF determineFocalPoint(MotionEvent motionEvent) { + // Number of fingers on screen + final int pCount = motionEvent.getPointerCount(); + float x = 0.0f; + float y = 0.0f; + + for (int i = 0; i < pCount; i++) { + x += motionEvent.getX(i); + y += motionEvent.getY(i); } - /** - * Determine (multi)finger focal point (a.k.a. center point between all - * fingers) - * - * @param e Motion Event - * @return PointF focal point - */ - public static PointF determineFocalPoint(MotionEvent e) { - // Number of fingers on screen - final int pCount = e.getPointerCount(); - float x = 0.0f; - float y = 0.0f; - - for (int i = 0; i < pCount; i++) { - x += e.getX(i); - y += e.getY(i); - } - - return new PointF(x / pCount, y / pCount); - } + return new PointF(x / pCount, y / pCount); + } - public float getFocusX() { - return mFocus.x; - } + public float getFocusX() { + return focus.x; + } - public float getFocusY() { - return mFocus.y; - } + public float getFocusY() { + return focus.y; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/MapboxAccountManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/MapboxAccountManager.java index b33d01a105..5f26228c5d 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/MapboxAccountManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/MapboxAccountManager.java @@ -13,119 +13,121 @@ import com.mapbox.mapboxsdk.telemetry.MapboxEventManager; public class MapboxAccountManager { - private static MapboxAccountManager mapboxAccountManager = null; - - private final String accessToken; - private final Context applicationContext; - - private Boolean connected = null; - - /** - * MapboxAccountManager should NOT be instantiated directly. - * Use @see MapboxAccountManager#getInstance() instead. - * - * @param applicationContext Context used to get ApplicationContext - * @param accessToken Mapbox Access Token - */ - private MapboxAccountManager(Context applicationContext, String accessToken) { - super(); - this.applicationContext = applicationContext.getApplicationContext(); - this.accessToken = accessToken; + private static MapboxAccountManager mapboxAccountManager = null; + + private final String accessToken; + private final Context applicationContext; + + private Boolean connected = null; + + /** + * MapboxAccountManager should NOT be instantiated directly. + * Use @see MapboxAccountManager#getInstance() instead. + * + * @param applicationContext Context used to get ApplicationContext + * @param accessToken Mapbox Access Token + */ + private MapboxAccountManager(Context applicationContext, String accessToken) { + super(); + this.applicationContext = applicationContext.getApplicationContext(); + this.accessToken = accessToken; + } + + /** + * Primary entry point to Mapbox for implementing developers. + * Must be configured in either Application.onCreate() or Launch Activity.onCreate() + * + * @param context Context used to get Application Context + * @param accessToken Mapbox Access Token. You can get one on the Mapbox Web site. + * @return MapboxAccountManager instance for app + */ + public static MapboxAccountManager start(Context context, String accessToken) { + if (mapboxAccountManager == null) { + //Create a new account manager + mapboxAccountManager = new MapboxAccountManager(context, accessToken); + + //Initialize the event manager + MapboxEventManager.getMapboxEventManager().initialize(context, accessToken); + + //Register a receiver to listen for connectivity updates + ConnectivityReceiver.instance(context); } - /** - * Primary entry point to Mapbox for implementing developers. - * Must be configured in either Application.onCreate() or Launch Activity.onCreate() - * - * @param context Context used to get Application Context - * @param accessToken Mapbox Access Token. You can get one on the Mapbox Web site. - * @return MapboxAccountManager instance for app - */ - public static MapboxAccountManager start(Context context, String accessToken) { - if (mapboxAccountManager == null) { - //Create a new account manager - mapboxAccountManager = new MapboxAccountManager(context, accessToken); - - //Initialize the event manager - MapboxEventManager.getMapboxEventManager().initialize(context, accessToken); - - //Register a receiver to listen for connectivity updates - ConnectivityReceiver.instance(context); - } - - return mapboxAccountManager; + return mapboxAccountManager; + } + + /** + * Internal Use Only + * Get an instance of MapboxAccountManager configured with the app's Access Token + * + * @return MapboxAccountManager instance for app. May be NULL if not configured yet. + */ + public static MapboxAccountManager getInstance() { + if (mapboxAccountManager == null) { + throw new MapboxAccountManagerNotStartedException(); } - /** - * Internal Use Only - * Get an instance of MapboxAccountManager configured with the app's Access Token - * - * @return MapboxAccountManager instance for app. May be NULL if not configured yet. - */ - public static MapboxAccountManager getInstance() { - if (mapboxAccountManager == null) { - throw new MapboxAccountManagerNotStartedException(); - } - - return mapboxAccountManager; + return mapboxAccountManager; + } + + /** + * Access Token for this application. + * + * @return Mapbox Access Token + */ + public String getAccessToken() { + return accessToken; + } + + /** + * Runtime validation of Access Token. + * + * @param accessToken Access Token to check + * @throws InvalidAccessTokenException the exception thrown + */ + public static void validateAccessToken(String accessToken) throws InvalidAccessTokenException { + if (TextUtils.isEmpty(accessToken) || (!accessToken.toLowerCase(MapboxConstants.MAPBOX_LOCALE).startsWith("pk.") + && !accessToken.toLowerCase(MapboxConstants.MAPBOX_LOCALE).startsWith("sk."))) { + throw new InvalidAccessTokenException(); } - - /** - * Access Token for this application. - * - * @return Mapbox Access Token - */ - public String getAccessToken() { - return accessToken; - } - - /** - * Runtime validation of Access Token. - * - * @param accessToken Access Token to check - * @throws InvalidAccessTokenException the exception thrown - */ - public static void validateAccessToken(String accessToken) throws InvalidAccessTokenException { - if (TextUtils.isEmpty(accessToken) || (!accessToken.toLowerCase(MapboxConstants.MAPBOX_LOCALE).startsWith("pk.") && !accessToken.toLowerCase(MapboxConstants.MAPBOX_LOCALE).startsWith("sk."))) { - throw new InvalidAccessTokenException(); - } - } - - /** - * Manually sets the connectivity state of the app. This is useful for apps that control their - * own connectivity state and want to bypass any checks to the ConnectivityManager. - * - * @param connected flag to determine the connectivity state, true for connected, false for - * disconnected, null for ConnectivityManager to determine. - */ - public void setConnected(Boolean connected) { - // Connectivity state overridden by app - this.connected = connected; - } - - /** - * Determines whether we have an Internet connection available. Please do not rely on this - * method in your apps, this method is used internally by the SDK. - * - * @return true if there is an Internet connection, false otherwise - */ - public Boolean isConnected() { - if (connected != null) { - // Connectivity state overridden by app - return connected; - } - - ConnectivityManager cm = (ConnectivityManager) applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); - return (activeNetwork != null && activeNetwork.isConnected()); + } + + /** + * Manually sets the connectivity state of the app. This is useful for apps that control their + * own connectivity state and want to bypass any checks to the ConnectivityManager. + * + * @param connected flag to determine the connectivity state, true for connected, false for + * disconnected, null for ConnectivityManager to determine. + */ + public void setConnected(Boolean connected) { + // Connectivity state overridden by app + this.connected = connected; + } + + /** + * Determines whether we have an Internet connection available. Please do not rely on this + * method in your apps, this method is used internally by the SDK. + * + * @return true if there is an Internet connection, false otherwise + */ + public Boolean isConnected() { + if (connected != null) { + // Connectivity state overridden by app + return connected; } - /** - * Not public API - * @return the Application Context - */ - public Context getApplicationContext() { - return applicationContext; - } + ConnectivityManager cm = (ConnectivityManager) applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); + return (activeNetwork != null && activeNetwork.isConnected()); + } + + /** + * Not public API + * + * @return the Application Context + */ + public Context getApplicationContext() { + return applicationContext; + } } 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 index 40b330b8c2..831c1db5a3 100644 --- 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 @@ -15,123 +15,127 @@ import com.mapbox.mapboxsdk.maps.MapboxMap; */ 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 - protected MapboxMap mapboxMap; - protected MapView mapView; + /** + * <p> + * The annotation id + * </p> + * Internal C++ id is stored as unsigned int. + */ + private long id = -1; // -1 unless added to a MapView + protected MapboxMap mapboxMap; + protected MapView mapView; - protected Annotation() { - } + 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. - * - * @return the assigned id. - */ - public long getId() { - return id; - } + /** + * <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. + * + * @return the assigned id. + */ + public long getId() { + return id; + } - /** - * Do not use this method, used internally by the SDK. - */ - public void remove() { - if (mapboxMap == null) { - return; - } - mapboxMap.removeAnnotation(this); + /** + * Do not use this method, used internally by the SDK. + */ + public void remove() { + if (mapboxMap == null) { + return; } + mapboxMap.removeAnnotation(this); + } - /** - * Do not use this method, used internally by the SDK. - * - * @param id the assigned id - */ - public void setId(long id) { - this.id = id; - } + /** + * Do not use this method, used internally by the SDK. + * + * @param id the assigned id + */ + public void setId(long id) { + this.id = id; + } - /** - * Do not use this method, used internally by the SDK. - * - * @param mapboxMap the hosting mapbox map - */ - public void setMapboxMap(MapboxMap mapboxMap) { - this.mapboxMap = mapboxMap; - } + /** + * Do not use this method, used internally by the SDK. + * + * @param mapboxMap the hosting mapbox map + */ + public void setMapboxMap(MapboxMap mapboxMap) { + this.mapboxMap = mapboxMap; + } - /** - * Gets the hosting mapbox map. - * - * @return the MapboxMap - */ - protected MapboxMap getMapboxMap() { - return mapboxMap; - } + /** + * Gets the hosting mapbox map. + * + * @return the MapboxMap + */ + protected MapboxMap getMapboxMap() { + return mapboxMap; + } - /** - * Do not use this method, used internally by the SDK. - * - * @param mapView the hosting map view - */ - public void setMapView(MapView mapView) { - this.mapView = mapView; - } + /** + * Do not use this method, used internally by the SDK. + * + * @param mapView the hosting map view + */ + public void setMapView(MapView mapView) { + this.mapView = mapView; + } - /** - * Gets the hosting map view. - * - * @return The MapView - */ - protected MapView getMapView() { - return mapView; - } + /** + * Gets the hosting map view. + * + * @return The MapView + */ + protected MapView getMapView() { + return mapView; + } - @Override - public int compareTo(@NonNull Annotation annotation) { - if (id < annotation.getId()) { - return 1; - } else if (id > annotation.getId()) { - return -1; - } - return 0; + @Override + public int compareTo(@NonNull Annotation annotation) { + if (id < annotation.getId()) { + return 1; + } else if (id > annotation.getId()) { + return -1; } + return 0; + } - /** - * Compares this {@link PolylineOptions} object with another {@link PolylineOptions} and - * determines if their color, alpha, width, and vertices match. - * - * @param o Another {@link PolylineOptions} to compare with this object. - * @return True if color, alpha, width, and vertices match this {@link PolylineOptions} object. - * Else, false. - */ - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || !(o instanceof Annotation)) return false; - Annotation that = (Annotation) o; - return id == that.getId(); + /** + * Compares this {@link PolylineOptions} object with another {@link PolylineOptions} and + * determines if their color, alpha, width, and vertices match. + * + * @param object Another {@link PolylineOptions} to compare with this object. + * @return True if color, alpha, width, and vertices match this {@link PolylineOptions} object. + * Else, false. + */ + @Override + public boolean equals(Object object) { + if (this == object) { + return true; } - - /** - * Gives an integer which can be used as the bucket number for storing elements of the set/map. - * This bucket number is the address of the element inside the set/map. There's no guarantee - * that this hash value will be consistent between different Java implementations, or even - * between different execution runs of the same program. - * - * @return integer value you can use for storing element. - */ - @Override - public int hashCode() { - return (int) (getId() ^ (getId() >>> 32)); + if (object == null || !(object instanceof Annotation)) { + return false; } + Annotation that = (Annotation) object; + return id == that.getId(); + } + + /** + * Gives an integer which can be used as the bucket number for storing elements of the set/map. + * This bucket number is the address of the element inside the set/map. There's no guarantee + * that this hash value will be consistent between different Java implementations, or even + * between different execution runs of the same program. + * + * @return integer value you can use for storing element. + */ + @Override + public int hashCode() { + return (int) (getId() ^ (getId() >>> 32)); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerOptions.java index 4e56531a7f..82868e2888 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerOptions.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerOptions.java @@ -6,7 +6,7 @@ import com.mapbox.mapboxsdk.geometry.LatLng; /** * Abstract builder class for composing custom Marker objects. - * + * <p> * Extending this class requires implementing Parceable interface. * * @param <U> Type of the marker to be composed @@ -14,107 +14,107 @@ import com.mapbox.mapboxsdk.geometry.LatLng; */ public abstract class BaseMarkerOptions<U extends Marker, T extends BaseMarkerOptions<U, T>> implements Parcelable { - protected LatLng position; - protected String snippet; - protected String title; - protected Icon icon; + protected LatLng position; + protected String snippet; + protected String title; + protected Icon icon; - /** - * Set the geographical location of the Marker. - * - * @param position the location to position the {@link Marker}. - * @return the object for which the method was called. - */ - public T position(LatLng position) { - this.position = position; - return getThis(); - } + /** + * Set the geographical location of the Marker. + * + * @param position the location to position the {@link Marker}. + * @return the object for which the method was called. + */ + public T position(LatLng position) { + this.position = position; + return getThis(); + } - /** - * Set the snippet of the Marker. - * - * @param snippet the snippet of the {@link Marker}. - * @return the object for which the method was called. - */ - public T snippet(String snippet) { - this.snippet = snippet; - return getThis(); - } + /** + * Set the snippet of the Marker. + * + * @param snippet the snippet of the {@link Marker}. + * @return the object for which the method was called. + */ + public T snippet(String snippet) { + this.snippet = snippet; + return getThis(); + } - /** - * Set the title of the Marker. - * - * @param title the title of the {@link Marker}. - * @return the object for which the method was called. - */ - public T title(String title) { - this.title = title; - return getThis(); - } + /** + * Set the title of the Marker. + * + * @param title the title of the {@link Marker}. + * @return the object for which the method was called. + */ + public T title(String title) { + this.title = title; + return getThis(); + } - /** - * Set the icon of the Marker. - * - * @param icon the icon of the {@link Marker}. - * @return the object for which the method was called. - */ - public T icon(Icon icon) { - this.icon = icon; - return getThis(); - } + /** + * Set the icon of the Marker. + * + * @param icon the icon of the {@link Marker}. + * @return the object for which the method was called. + */ + public T icon(Icon icon) { + this.icon = icon; + return getThis(); + } - /** - * Set the icon of the Marker. - * - * @param icon the icon of the {@link Marker}. - * @return the object for which the method was called. - */ - public T setIcon(Icon icon) { - return icon(icon); - } + /** + * Set the icon of the Marker. + * + * @param icon the icon of the {@link Marker}. + * @return the object for which the method was called. + */ + public T setIcon(Icon icon) { + return icon(icon); + } - /** - * Set the geographical location of the Marker. - * - * @param position the location to position the {@link Marker}. - * @return the object for which the method was called. - */ - public T setPosition(LatLng position) { - return position(position); - } + /** + * Set the geographical location of the Marker. + * + * @param position the location to position the {@link Marker}. + * @return the object for which the method was called. + */ + public T setPosition(LatLng position) { + return position(position); + } - /** - * Set the snippet of the Marker. - * - * @param snippet the snippet of the {@link Marker}. - * @return the object for which the method was called. - */ - public T setSnippet(String snippet) { - return snippet(snippet); - } + /** + * Set the snippet of the Marker. + * + * @param snippet the snippet of the {@link Marker}. + * @return the object for which the method was called. + */ + public T setSnippet(String snippet) { + return snippet(snippet); + } - /** - * Set the title of the Marker. - * - * @param title the title of the {@link Marker}. - * @return the object for which the method was called. - */ - public T setTitle(String title) { - return title(title); - } + /** + * Set the title of the Marker. + * + * @param title the title of the {@link Marker}. + * @return the object for which the method was called. + */ + public T setTitle(String title) { + return title(title); + } - /** - * Get the instance of the object for which this method was called. - * - * @return the object for which the this method was called. - */ - public abstract T getThis(); + /** + * Get the instance of the object for which this method was called. + * + * @return the object for which the this method was called. + */ + public abstract T getThis(); - /** - * Get the Marker. - * - * @return the Marker created from this builder. - */ - public abstract U getMarker(); + /** + * Get the Marker. + * + * @return the Marker created from this builder. + */ + public abstract U getMarker(); } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java index e93f2c801d..ddedf3debf 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java @@ -15,267 +15,268 @@ import com.mapbox.mapboxsdk.geometry.LatLng; * @param <U> Type of the marker view to be composed. * @param <T> Type of the builder to be used for composing. */ -public abstract class BaseMarkerViewOptions<U extends MarkerView, T extends BaseMarkerViewOptions<U, T>> implements Parcelable { +public abstract class BaseMarkerViewOptions<U extends MarkerView, T extends BaseMarkerViewOptions<U, T>> + implements Parcelable { - protected LatLng position; - protected String snippet; - protected String title; - protected Icon icon; - protected boolean flat; - protected float anchorU = 0.5f; - protected float anchorV = 1f; - protected float infoWindowAnchorU = 0.5f; - protected float infoWindowAnchorV = 0.0f; - protected float rotation; - protected boolean visible = true; - protected boolean selected; - protected float alpha = 1.0f; + protected LatLng position; + protected String snippet; + protected String title; + protected Icon icon; + protected boolean flat; + protected float anchorU = 0.5f; + protected float anchorV = 1f; + protected float infoWindowAnchorU = 0.5f; + protected float infoWindowAnchorV = 0.0f; + protected float rotation; + protected boolean visible = true; + protected boolean selected; + protected float alpha = 1.0f; - /** - * Default constructor - */ - public BaseMarkerViewOptions() { - } + /** + * Default constructor + */ + public BaseMarkerViewOptions() { + } - /** - * Set the geographical location of the MarkerView. - * - * @param position the location to position the {@link MarkerView}. - * @return the object for which the method was called. - */ - public T position(@NonNull LatLng position) { - this.position = position; - return getThis(); - } + /** + * Set the geographical location of the MarkerView. + * + * @param position the location to position the {@link MarkerView}. + * @return the object for which the method was called. + */ + public T position(@NonNull LatLng position) { + this.position = position; + return getThis(); + } - /** - * Set the snippet of the MarkerView. - * - * @param snippet the snippet of the {@link MarkerView}. - * @return the object for which the method was called. - */ - public T snippet(String snippet) { - this.snippet = snippet; - return getThis(); - } + /** + * Set the snippet of the MarkerView. + * + * @param snippet the snippet of the {@link MarkerView}. + * @return the object for which the method was called. + */ + public T snippet(String snippet) { + this.snippet = snippet; + return getThis(); + } - /** - * Set the title of the MarkerView. - * - * @param title the title of the {@link MarkerView}. - * @return the object for which the method was called. - */ - public T title(String title) { - this.title = title; - return getThis(); - } + /** + * Set the title of the MarkerView. + * + * @param title the title of the {@link MarkerView}. + * @return the object for which the method was called. + */ + public T title(String title) { + this.title = title; + return getThis(); + } - /** - * Set the icon of the MarkerView. - * - * @param icon the icon of the {@link MarkerView}. - * @return the object for which the method was called. - */ - public T icon(Icon icon) { - this.icon = icon; - return getThis(); - } + /** + * Set the icon of the MarkerView. + * + * @param icon the icon of the {@link MarkerView}. + * @return the object for which the method was called. + */ + public T icon(Icon icon) { + this.icon = icon; + return getThis(); + } - /** - * Set the flat state of the MarkerView. - * - * @param flat the flat state of the {@link MarkerView}. - * @return the object for which the method was called. - */ - public T flat(boolean flat) { - this.flat = flat; - return getThis(); - } + /** + * Set the flat state of the MarkerView. + * + * @param flat the flat state of the {@link MarkerView}. + * @return the object for which the method was called. + */ + public T flat(boolean flat) { + this.flat = flat; + return getThis(); + } - /** - * Set the anchor of the {@link MarkerView}. - * - * @param u the u-value. - * @param v the v-value. - * @return the object for which the method was called. - */ - public T anchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) { - this.anchorU = u; - this.anchorV = v; - return getThis(); - } + /** + * Set the anchor of the {@link MarkerView}. + * + * @param u the u-value. + * @param v the v-value. + * @return the object for which the method was called. + */ + public T anchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) { + this.anchorU = u; + this.anchorV = v; + return getThis(); + } - /** - * Set the InfoWindow anchor of the {@link MarkerView}. - * - * @param u the u-value. - * @param v the v-values. - * @return the object for which the method was called. - */ - public T infoWindowAnchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) { - this.infoWindowAnchorU = u; - this.infoWindowAnchorV = v; - return getThis(); - } + /** + * Set the InfoWindow anchor of the {@link MarkerView}. + * + * @param u the u-value. + * @param v the v-values. + * @return the object for which the method was called. + */ + public T infoWindowAnchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) { + this.infoWindowAnchorU = u; + this.infoWindowAnchorV = v; + return getThis(); + } - /** - * Set the rotation of the {@link MarkerView}. - * - * @param rotation the rotation value. - * @return the object for which the method was called. - */ - public T rotation(float rotation) { - this.rotation = rotation; - while (this.rotation > 360) { - this.rotation -= 360; - } - while (this.rotation < 0) { - this.rotation += 360; - } - return getThis(); + /** + * Set the rotation of the {@link MarkerView}. + * + * @param rotation the rotation value. + * @return the object for which the method was called. + */ + public T rotation(float rotation) { + this.rotation = rotation; + while (this.rotation > 360) { + this.rotation -= 360; } - - /** - * Set the visibility state of the {@link MarkerView}. - * - * @param visible the visible state. - * @return the object for which the method was called. - */ - public T visible(boolean visible) { - this.visible = visible; - return getThis(); + while (this.rotation < 0) { + this.rotation += 360; } + return getThis(); + } - /** - * Set the alpha of the {@link MarkerView}. - * - * @param alpha the alpha value. - * @return the object for which the method was called. - */ - public T alpha(float alpha) { - this.alpha = alpha; - return getThis(); - } + /** + * Set the visibility state of the {@link MarkerView}. + * + * @param visible the visible state. + * @return the object for which the method was called. + */ + public T visible(boolean visible) { + this.visible = visible; + return getThis(); + } - /** - * Get the geographical location of the {@link MarkerView}. - * - * @return the geographical location. - */ - public LatLng getPosition() { - return position; - } + /** + * Set the alpha of the {@link MarkerView}. + * + * @param alpha the alpha value. + * @return the object for which the method was called. + */ + public T alpha(float alpha) { + this.alpha = alpha; + return getThis(); + } - /** - * Get the snippet of the {@link MarkerView}. - * - * @return the snippet. - */ - public String getSnippet() { - return snippet; - } + /** + * Get the geographical location of the {@link MarkerView}. + * + * @return the geographical location. + */ + public LatLng getPosition() { + return position; + } - /** - * Get the title of the {@link MarkerView}. - * - * @return the title. - */ - public String getTitle() { - return title; - } + /** + * Get the snippet of the {@link MarkerView}. + * + * @return the snippet. + */ + public String getSnippet() { + return snippet; + } - /** - * Get the icon of the {@link MarkerView}. - * - * @return the icon. - */ - public Icon getIcon() { - return icon; - } + /** + * Get the title of the {@link MarkerView}. + * + * @return the title. + */ + public String getTitle() { + return title; + } - /** - * Get the flat state of the {@link MarkerView}. - * - * @return the flat state. - */ - public boolean isFlat() { - return flat; - } + /** + * Get the icon of the {@link MarkerView}. + * + * @return the icon. + */ + public Icon getIcon() { + return icon; + } - /** - * Get the u-value of the {@link MarkerView} anchor. - * - * @return the u-value. - */ - public float getAnchorU() { - return anchorU; - } + /** + * Get the flat state of the {@link MarkerView}. + * + * @return the flat state. + */ + public boolean isFlat() { + return flat; + } - /** - * Get the v-value of the {@link MarkerView} anchor. - * - * @return the v-value. - */ - public float getAnchorV() { - return anchorV; - } + /** + * Get the u-value of the {@link MarkerView} anchor. + * + * @return the u-value. + */ + public float getAnchorU() { + return anchorU; + } - /** - * Get the u-value of the MarkerView InfoWindow anchor. - * - * @return the u-value. - */ - public float getInfoWindowAnchorU() { - return infoWindowAnchorU; - } + /** + * Get the v-value of the {@link MarkerView} anchor. + * + * @return the v-value. + */ + public float getAnchorV() { + return anchorV; + } - /** - * Get the v-value of the MarkerView InfoWindow anchor. - * - * @return the v-value. - */ - public float getInfoWindowAnchorV() { - return infoWindowAnchorV; - } + /** + * Get the u-value of the MarkerView InfoWindow anchor. + * + * @return the u-value. + */ + public float getInfoWindowAnchorU() { + return infoWindowAnchorU; + } - /** - * Get the rotation of the MarkerView. - * - * @return the rotation value. - */ - public float getRotation() { - return rotation; - } + /** + * Get the v-value of the MarkerView InfoWindow anchor. + * + * @return the v-value. + */ + public float getInfoWindowAnchorV() { + return infoWindowAnchorV; + } - /** - * Get the visibility state of the MarkerView. - * - * @return the visibility state. - */ - public boolean isVisible() { - return visible; - } + /** + * Get the rotation of the MarkerView. + * + * @return the rotation value. + */ + public float getRotation() { + return rotation; + } - /** - * Get the alpha of the MarkerView. - * - * @return the alpha value. - */ - public float getAlpha() { - return alpha; - } + /** + * Get the visibility state of the MarkerView. + * + * @return the visibility state. + */ + public boolean isVisible() { + return visible; + } + + /** + * Get the alpha of the MarkerView. + * + * @return the alpha value. + */ + public float getAlpha() { + return alpha; + } - /** - * Get the instance of the object for which this method was called. - * - * @return the object for which the this method was called. - */ - public abstract T getThis(); + /** + * Get the instance of the object for which this method was called. + * + * @return the object for which the this method was called. + */ + public abstract T getThis(); - /** - * Get the MarkerView. - * - * @return the MarkerView created from this builder. - */ - public abstract U getMarker(); + /** + * Get the MarkerView. + * + * @return the MarkerView created from this builder. + */ + public abstract U getMarker(); } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java index ae7cf6eb8c..b1a05ec436 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java @@ -10,67 +10,73 @@ import com.mapbox.mapboxsdk.maps.MapView; * @see Marker */ public class Icon { - private Bitmap mBitmap; - private String mId; + private Bitmap mBitmap; + private String mId; - Icon(String id, Bitmap bitmap) { - mId = id; - mBitmap = bitmap; - } + Icon(String id, Bitmap bitmap) { + mId = id; + mBitmap = bitmap; + } - /** - * {@link String} identifier for this {@link Icon}. - * - * @return {@link String} identifier for this {@link Icon}. - */ - public String getId() { - return mId; - } + /** + * {@link String} identifier for this {@link Icon}. + * + * @return {@link String} identifier for this {@link Icon}. + */ + public String getId() { + return mId; + } - /** - * Get the {@link Bitmap} being used for this {@link Icon}. - * - * @return The {@link Bitmap} being used for the {@link Icon}. - */ - public Bitmap getBitmap() { - return mBitmap; - } + /** + * Get the {@link Bitmap} being used for this {@link Icon}. + * + * @return The {@link Bitmap} being used for the {@link Icon}. + */ + public Bitmap getBitmap() { + return mBitmap; + } - /** - * Compares this {@link Icon} object with another {@link Icon} and determines if they match. - * - * @param o Another {@link Icon} to compare with this object. - * @return True if the {@link Icon} being passed in matches this {@link Icon} object. Else, - * false. - */ - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + /** + * Compares this {@link Icon} object with another {@link Icon} and determines if they match. + * + * @param object Another {@link Icon} to compare with this object. + * @return True if the {@link Icon} being passed in matches this {@link Icon} object. Else, + * false. + */ + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } - Icon icon = (Icon) o; + Icon icon = (Icon) object; - if (!mBitmap.equals(icon.mBitmap)) return false; - return mId.equals(icon.mId); + if (!mBitmap.equals(icon.mBitmap)) { + return false; } + return mId.equals(icon.mId); + } - /** - * Gives an integer which can be used as the bucket number for storing elements of the set/map. - * This bucket number is the address of the element inside the set/map. There's no guarantee - * that this hash value will be consistent between different Java implementations, or even - * between different execution runs of the same program. - * - * @return integer value you can use for storing element. - */ - @Override - public int hashCode() { - int result = 0; - if (mBitmap != null) { - result = mBitmap.hashCode(); - } - if (mId != null) { - result = 31 * result + mId.hashCode(); - } - return result; + /** + * Gives an integer which can be used as the bucket number for storing elements of the set/map. + * This bucket number is the address of the element inside the set/map. There's no guarantee + * that this hash value will be consistent between different Java implementations, or even + * between different execution runs of the same program. + * + * @return integer value you can use for storing element. + */ + @Override + public int hashCode() { + int result = 0; + if (mBitmap != null) { + result = mBitmap.hashCode(); + } + if (mId != null) { + result = 31 * result + mId.hashCode(); } + return result; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/IconFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/IconFactory.java index 9427501bb8..052d5592e4 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/IconFactory.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/IconFactory.java @@ -29,205 +29,207 @@ import java.io.InputStream; */ public final class IconFactory { - private static final String ICON_ID_PREFIX = "com.mapbox.icons.icon_"; - public static final Bitmap ICON_MARKERVIEW_BITMAP = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8); - public static final String ICON_MARKERVIEW_ID = ICON_ID_PREFIX + "marker_view"; - - private Context mContext; - private static IconFactory sInstance; - private Icon mDefaultMarker; - private Icon mDefaultMarkerView; - private BitmapFactory.Options mOptions; - - private int mNextId = 0; - - public static synchronized IconFactory getInstance(@NonNull Context context) { - if (sInstance == null) { - sInstance = new IconFactory(context.getApplicationContext()); - } - return sInstance; - } + private static final String ICON_ID_PREFIX = "com.mapbox.icons.icon_"; + public static final Bitmap ICON_MARKERVIEW_BITMAP = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8); + public static final String ICON_MARKERVIEW_ID = ICON_ID_PREFIX + "marker_view"; - private IconFactory(@NonNull Context context) { - mContext = context; - DisplayMetrics realMetrics = null; - DisplayMetrics metrics = new DisplayMetrics(); - WindowManager wm = (WindowManager) context.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; - } - } + private Context mContext; + private static IconFactory sInstance; + private Icon mDefaultMarker; + private Icon mDefaultMarkerView; + private BitmapFactory.Options mOptions; - /** - * Creates an {@link Icon} from a given Bitmap image. - * - * @param bitmap image used for creating the Icon. - * @return The {@link Icon} using the given Bitmap image. - */ - public Icon fromBitmap(@NonNull Bitmap bitmap) { - if (mNextId < 0) { - throw new TooManyIconsException(); - } - String id = ICON_ID_PREFIX + ++mNextId; - return new Icon(id, bitmap); - } + private int mNextId = 0; - /** - * Create an {@link Icon} from a given {@link Drawable}. - * - * @param drawable A {@link Drawable} object used for creating the {@link Icon}. - * @return {@link Icon} with the provided {@link Drawable}. - */ - public Icon fromDrawable(@NonNull Drawable drawable) { - int width = drawable.getIntrinsicWidth(); - int height = drawable.getIntrinsicHeight(); - return fromDrawable(drawable, width, height); + public static synchronized IconFactory getInstance(@NonNull Context context) { + if (sInstance == null) { + sInstance = new IconFactory(context.getApplicationContext()); } - - /** - * Create an {@link Icon} from a given {@link Drawable}. - * - * @param drawable A {@link Drawable} object used for creating the {@link Icon}. - * @param width An integer greater then zero defining the {@link Icon} width. - * @param height An integer greater then zero defining the {@link Icon} height. - * @return {@link Icon} with the provided {@link Drawable}. - */ - public Icon fromDrawable(@NonNull 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); + return sInstance; + } + + private IconFactory(@NonNull Context context) { + mContext = context; + DisplayMetrics realMetrics = null; + DisplayMetrics metrics = new DisplayMetrics(); + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + realMetrics = new DisplayMetrics(); + wm.getDefaultDisplay().getRealMetrics(realMetrics); } - - /** - * Create an {@link Icon} using the resource ID of a Bitmap image. - * - * @param resourceId The resource ID of a Bitmap image. - * @return The {@link Icon} that was loaded from the asset or {@code null} if failed to load. - */ - public Icon fromResource(@DrawableRes int resourceId) { - Drawable drawable = ContextCompat.getDrawable(mContext, resourceId); - Bitmap bitmap; - if (drawable instanceof BitmapDrawable) { - BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; - bitmap = bitmapDrawable.getBitmap(); - } else { - if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) { - bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); - } else { - bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); - } - - Canvas canvas = new Canvas(bitmap); - drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); - drawable.draw(canvas); - } - return fromBitmap(bitmap); + 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; } - - /** - * Provides an {@link Icon} using the default marker icon used for {@link Marker}. - * - * @return An {@link Icon} with the default {@link Marker} icon. - */ - public Icon defaultMarker() { - if (mDefaultMarker == null) { - mDefaultMarker = fromResource(R.drawable.mapbox_marker_icon_default); - } - return mDefaultMarker; + } + + /** + * Creates an {@link Icon} from a given Bitmap image. + * + * @param bitmap image used for creating the Icon. + * @return The {@link Icon} using the given Bitmap image. + */ + public Icon fromBitmap(@NonNull Bitmap bitmap) { + if (mNextId < 0) { + throw new TooManyIconsException(); } - - /** - * Provides an {@link Icon} using the default marker icon used for {@link MarkerView}. - * - * @return An {@link Icon} with the default {@link MarkerView} icon. - */ - public Icon defaultMarkerView() { - if (mDefaultMarkerView == null) { - mDefaultMarkerView = fromResource(R.drawable.mapbox_markerview_icon_default); - } - return mDefaultMarkerView; + String id = ICON_ID_PREFIX + ++mNextId; + return new Icon(id, bitmap); + } + + /** + * Create an {@link Icon} from a given {@link Drawable}. + * + * @param drawable A {@link Drawable} object used for creating the {@link Icon}. + * @return {@link Icon} with the provided {@link Drawable}. + */ + public Icon fromDrawable(@NonNull Drawable drawable) { + int width = drawable.getIntrinsicWidth(); + int height = drawable.getIntrinsicHeight(); + return fromDrawable(drawable, width, height); + } + + /** + * Create an {@link Icon} from a given {@link Drawable}. + * + * @param drawable A {@link Drawable} object used for creating the {@link Icon}. + * @param width An integer greater then zero defining the {@link Icon} width. + * @param height An integer greater then zero defining the {@link Icon} height. + * @return {@link Icon} with the provided {@link Drawable}. + */ + public Icon fromDrawable(@NonNull Drawable drawable, int width, int height) { + if ((width < 0) || (height < 0)) { + return null; } - private Icon fromInputStream(@NonNull InputStream is) { - Bitmap bitmap = BitmapFactory.decodeStream(is, null, mOptions); - return fromBitmap(bitmap); + 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); + } + + /** + * Create an {@link Icon} using the resource ID of a Bitmap image. + * + * @param resourceId The resource ID of a Bitmap image. + * @return The {@link Icon} that was loaded from the asset or {@code null} if failed to load. + */ + public Icon fromResource(@DrawableRes int resourceId) { + Drawable drawable = ContextCompat.getDrawable(mContext, resourceId); + Bitmap bitmap; + if (drawable instanceof BitmapDrawable) { + BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; + bitmap = bitmapDrawable.getBitmap(); + } else { + if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) { + bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); + } else { + bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), + Bitmap.Config.ARGB_8888); + } + + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); } - - /** - * Creates an {@link Icon} using the name of a Bitmap image in the assets directory. - * - * @param assetName The name of a Bitmap image in the assets directory. - * @return The {@link Icon} that was loaded from the asset or {@code null} if failed to load. - */ - public Icon fromAsset(@NonNull String assetName) { - InputStream is; - try { - is = mContext.getAssets().open(assetName); - } catch (IOException e) { - return null; - } - return fromInputStream(is); + return fromBitmap(bitmap); + } + + /** + * Provides an {@link Icon} using the default marker icon used for {@link Marker}. + * + * @return An {@link Icon} with the default {@link Marker} icon. + */ + public Icon defaultMarker() { + if (mDefaultMarker == null) { + mDefaultMarker = fromResource(R.drawable.mapbox_marker_icon_default); } - - /** - * Creates an {@link Icon} using the absolute file path of a Bitmap image. - * - * @param absolutePath The absolute path of the Bitmap image. - * @return The {@link Icon} that was loaded from the absolute path or {@code null} if failed to - * load. - */ - public Icon fromPath(@NonNull String absolutePath) { - Bitmap bitmap = BitmapFactory.decodeFile(absolutePath, mOptions); - return fromBitmap(bitmap); + return mDefaultMarker; + } + + /** + * Provides an {@link Icon} using the default marker icon used for {@link MarkerView}. + * + * @return An {@link Icon} with the default {@link MarkerView} icon. + */ + public Icon defaultMarkerView() { + if (mDefaultMarkerView == null) { + mDefaultMarkerView = fromResource(R.drawable.mapbox_markerview_icon_default); } - - /** - * Create an {@link Icon} using the name of a Bitmap image file located in the internal storage. - * In particular, this calls {@link Context#openFileInput(String)}. - * - * @param fileName The name of the Bitmap image file. - * @return The {@link Icon} that was loaded from the asset or {@code null} if failed to load. - * @see <a href="https://developer.android.com/guide/topics/data/data-storage.html#filesInternal">Using the Internal Storage</a> - */ - public Icon fromFile(@NonNull String fileName) { - FileInputStream is; - try { - is = mContext.openFileInput(fileName); - } catch (FileNotFoundException e) { - return null; - } - return fromInputStream(is); + return mDefaultMarkerView; + } + + private Icon fromInputStream(@NonNull InputStream is) { + Bitmap bitmap = BitmapFactory.decodeStream(is, null, mOptions); + return fromBitmap(bitmap); + } + + /** + * Creates an {@link Icon} using the name of a Bitmap image in the assets directory. + * + * @param assetName The name of a Bitmap image in the assets directory. + * @return The {@link Icon} that was loaded from the asset or {@code null} if failed to load. + */ + public Icon fromAsset(@NonNull String assetName) { + InputStream is; + try { + is = mContext.getAssets().open(assetName); + } catch (IOException ioException) { + return null; } - - /** - * Create an {@link Icon} using a previously created icon identifier along with a provided - * Bitmap. - * - * @param iconId The {@link Icon} identifier you'd like to recreate. - * @param bitmap a Bitmap used to replace the current one. - * @return The {@link Icon} using the new Bitmap. - */ - public static Icon recreate(@NonNull String iconId, @NonNull Bitmap bitmap) { - return new Icon(iconId, bitmap); + return fromInputStream(is); + } + + /** + * Creates an {@link Icon} using the absolute file path of a Bitmap image. + * + * @param absolutePath The absolute path of the Bitmap image. + * @return The {@link Icon} that was loaded from the absolute path or {@code null} if failed to + * load. + */ + public Icon fromPath(@NonNull String absolutePath) { + Bitmap bitmap = BitmapFactory.decodeFile(absolutePath, mOptions); + return fromBitmap(bitmap); + } + + /** + * Create an {@link Icon} using the name of a Bitmap image file located in the internal storage. + * In particular, this calls {@link Context#openFileInput(String)}. + * + * @param fileName The name of the Bitmap image file. + * @return The {@link Icon} that was loaded from the asset or {@code null} if failed to load. + * @see <a href="https://developer.android.com/guide/topics/data/data-storage.html#filesInternal"> + * Using the Internal Storage</a> + */ + public Icon fromFile(@NonNull String fileName) { + FileInputStream is; + try { + is = mContext.openFileInput(fileName); + } catch (FileNotFoundException fileNotFoundException) { + return null; } + return fromInputStream(is); + } + + /** + * Create an {@link Icon} using a previously created icon identifier along with a provided + * Bitmap. + * + * @param iconId The {@link Icon} identifier you'd like to recreate. + * @param bitmap a Bitmap used to replace the current one. + * @return The {@link Icon} using the new Bitmap. + */ + public static Icon recreate(@NonNull String iconId, @NonNull Bitmap bitmap) { + return new Icon(iconId, bitmap); + } } 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 index b33d489da2..34d2c31139 100644 --- 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 @@ -31,270 +31,271 @@ import java.lang.ref.WeakReference; */ public class InfoWindow { - private WeakReference<Marker> mBoundMarker; - private WeakReference<MapboxMap> mMapboxMap; - protected WeakReference<View> mView; - - private float mMarkerHeightOffset; - private float mMarkerWidthOffset; - private float mViewWidthOffset; - private PointF mCoordinates; - private boolean mIsVisible; - - @LayoutRes - private int mLayoutRes; - - InfoWindow(MapView mapView, int layoutResId, MapboxMap mapboxMap) { - mLayoutRes = layoutResId; - View view = LayoutInflater.from(mapView.getContext()).inflate(layoutResId, mapView, false); - initialize(view, mapboxMap); - } + private WeakReference<Marker> boundMarker; + private WeakReference<MapboxMap> mapboxMap; + protected WeakReference<View> view; + + private float markerHeightOffset; + private float markerWidthOffset; + private float viewWidthOffset; + private PointF coordinates; + private boolean isVisible; + + @LayoutRes + private int layoutRes; + + InfoWindow(MapView mapView, int layoutResId, MapboxMap mapboxMap) { + layoutRes = layoutResId; + View view = LayoutInflater.from(mapView.getContext()).inflate(layoutResId, mapView, false); + initialize(view, mapboxMap); + } + + InfoWindow(View view, MapboxMap mapboxMap) { + initialize(view, mapboxMap); + } + + private void initialize(View view, MapboxMap mapboxMap) { + this.mapboxMap = new WeakReference<>(mapboxMap); + isVisible = false; + this.view = new WeakReference<>(view); + + view.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MapboxMap mapboxMap = InfoWindow.this.mapboxMap.get(); + if (mapboxMap != null) { + MapboxMap.OnInfoWindowClickListener onInfoWindowClickListener = mapboxMap.getOnInfoWindowClickListener(); + boolean handledDefaultClick = false; + if (onInfoWindowClickListener != null) { + handledDefaultClick = onInfoWindowClickListener.onInfoWindowClick(getBoundMarker()); + } + + if (!handledDefaultClick) { + // default behavior: close it when clicking on the tooltip: + close(); + } + } + } + }); + + view.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + MapboxMap mapboxMap = InfoWindow.this.mapboxMap.get(); + if (mapboxMap != null) { + MapboxMap.OnInfoWindowLongClickListener listener = mapboxMap.getOnInfoWindowLongClickListener(); + if (listener != null) { + listener.onInfoWindowLongClick(getBoundMarker()); + } + } + return true; + } + }); + } + + + /** + * Open the info 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 The offset of the view to the position, in pixels. This allows to offset + * the view from the object position. + * @param offsetY The offset of the view to the position, in pixels. This allows to offset + * the view from the object position. + * @return this {@link InfoWindow}. + */ + InfoWindow open(MapView mapView, Marker boundMarker, LatLng position, int offsetX, int offsetY) { + setBoundMarker(boundMarker); + + MapView.LayoutParams lp = new MapView.LayoutParams(MapView.LayoutParams.WRAP_CONTENT, + MapView.LayoutParams.WRAP_CONTENT); + + MapboxMap mapboxMap = this.mapboxMap.get(); + View view = this.view.get(); + if (view != null && mapboxMap != null) { + view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); + + // Calculate y-offset for update method + markerHeightOffset = -view.getMeasuredHeight() + offsetY; + markerWidthOffset = -offsetX; + + // Calculate default Android x,y coordinate + coordinates = mapboxMap.getProjection().toScreenLocation(position); + float x = coordinates.x - (view.getMeasuredWidth() / 2) + offsetX; + float y = coordinates.y - view.getMeasuredHeight() + offsetY; + + if (view instanceof InfoWindowView) { + // only apply repositioning/margin for InfoWindowView + Resources resources = mapView.getContext().getResources(); + + // get right/left popup window + float rightSideInfowWindow = x + view.getMeasuredWidth(); + float leftSideInfoWindow = x; + + // get right/left map view + final float mapRight = mapView.getRight(); + final float mapLeft = mapView.getLeft(); + + float marginHorizontal = resources.getDimension(R.dimen.mapbox_infowindow_margin); + float tipViewOffset = resources.getDimension(R.dimen.mapbox_infowindow_tipview_width) / 2; + float tipViewMarginLeft = view.getMeasuredWidth() / 2 - tipViewOffset; + + boolean outOfBoundsLeft = false; + boolean outOfBoundsRight = false; + + // only optimise margins if view is inside current viewport + if (coordinates.x >= 0 && coordinates.x <= mapView.getWidth() + && coordinates.y >= 0 && coordinates.y <= mapView.getHeight()) { + + // if out of bounds right + if (rightSideInfowWindow > mapRight) { + outOfBoundsRight = true; + x -= rightSideInfowWindow - mapRight; + tipViewMarginLeft += rightSideInfowWindow - mapRight + tipViewOffset; + rightSideInfowWindow = x + view.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; + } + } - InfoWindow(View view, MapboxMap mapboxMap) { - initialize(view, mapboxMap); - } + // Adjust tipView + InfoWindowView infoWindowView = (InfoWindowView) view; + infoWindowView.setTipViewMarginLeft((int) tipViewMarginLeft); + } - private void initialize(View view, MapboxMap mapboxMap) { - mMapboxMap = new WeakReference<>(mapboxMap); - mIsVisible = false; - mView = new WeakReference<>(view); - - view.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - MapboxMap mapboxMap = mMapboxMap.get(); - if (mapboxMap != null) { - MapboxMap.OnInfoWindowClickListener onInfoWindowClickListener = mapboxMap.getOnInfoWindowClickListener(); - boolean handledDefaultClick = false; - if (onInfoWindowClickListener != null) { - handledDefaultClick = onInfoWindowClickListener.onInfoWindowClick(getBoundMarker()); - } - - if (!handledDefaultClick) { - // default behavior: close it when clicking on the tooltip: - close(); - } - } - } - }); - - view.setOnLongClickListener(new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - MapboxMap mapboxMap = mMapboxMap.get(); - if (mapboxMap != null) { - MapboxMap.OnInfoWindowLongClickListener listener = mapboxMap.getOnInfoWindowLongClickListener(); - if (listener != null) { - listener.onInfoWindowLongClick(getBoundMarker()); - } - } - return true; - } - }); - } + // set anchor popupwindowview + view.setX(x); + view.setY(y); + // Calculate x-offset for update method + viewWidthOffset = x - coordinates.x - offsetX; - /** - * Open the info 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 The offset of the view to the position, in pixels. This allows to offset - * the view from the object position. - * @param offsetY The offset of the view to the position, in pixels. This allows to offset - * the view from the object position. - * @return this {@link InfoWindow}. - */ - InfoWindow open(MapView mapView, Marker boundMarker, LatLng position, int offsetX, int offsetY) { - setBoundMarker(boundMarker); - - MapView.LayoutParams lp = new MapView.LayoutParams(MapView.LayoutParams.WRAP_CONTENT, MapView.LayoutParams.WRAP_CONTENT); - - MapboxMap mapboxMap = mMapboxMap.get(); - View view = mView.get(); - if (view != null && mapboxMap != null) { - view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); - - // Calculate y-offset for update method - mMarkerHeightOffset = -view.getMeasuredHeight() + offsetY; - mMarkerWidthOffset = -offsetX; - - // Calculate default Android x,y coordinate - mCoordinates = mapboxMap.getProjection().toScreenLocation(position); - float x = mCoordinates.x - (view.getMeasuredWidth() / 2) + offsetX; - float y = mCoordinates.y - view.getMeasuredHeight() + offsetY; - - if (view instanceof InfoWindowView) { - // only apply repositioning/margin for InfoWindowView - Resources resources = mapView.getContext().getResources(); - - // get right/left popup window - float rightSideInfowWindow = x + view.getMeasuredWidth(); - float leftSideInfoWindow = x; - - // get right/left map view - final float mapRight = mapView.getRight(); - final float mapLeft = mapView.getLeft(); - - float marginHorizontal = resources.getDimension(R.dimen.mapbox_infowindow_margin); - float tipViewOffset = resources.getDimension(R.dimen.mapbox_infowindow_tipview_width) / 2; - float tipViewMarginLeft = view.getMeasuredWidth() / 2 - tipViewOffset; - - boolean outOfBoundsLeft = false; - boolean outOfBoundsRight = false; - - // only optimise margins if view is inside current viewport - if (mCoordinates.x >= 0 && mCoordinates.x <= mapView.getWidth() - && mCoordinates.y >= 0 && mCoordinates.y <= mapView.getHeight()) { - - // if out of bounds right - if (rightSideInfowWindow > mapRight) { - outOfBoundsRight = true; - x -= rightSideInfowWindow - mapRight; - tipViewMarginLeft += rightSideInfowWindow - mapRight + tipViewOffset; - rightSideInfowWindow = x + view.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) view; - infoWindowView.setTipViewMarginLeft((int) tipViewMarginLeft); - } - - // set anchor popupwindowview - view.setX(x); - view.setY(y); - - // Calculate x-offset for update method - mViewWidthOffset = x - mCoordinates.x - offsetX; - - close(); //if it was already opened - mapView.addView(view, lp); - mIsVisible = true; - } - return this; + close(); //if it was already opened + mapView.addView(view, lp); + isVisible = true; } - - /** - * Close this {@link InfoWindow} if it is visible, otherwise calling this will do nothing. - * - * @return This {@link InfoWindow} - */ - InfoWindow close() { - MapboxMap mapboxMap = mMapboxMap.get(); - if (mIsVisible && mapboxMap != null) { - mIsVisible = false; - View view = mView.get(); - if (view != null && view.getParent() != null) { - ((ViewGroup) view.getParent()).removeView(view); - } - - Marker marker = getBoundMarker(); - MapboxMap.OnInfoWindowCloseListener listener = mapboxMap.getOnInfoWindowCloseListener(); - if (listener != null) { - listener.onInfoWindowClose(marker); - } - - setBoundMarker(null); - } - return this; + return this; + } + + /** + * Close this {@link InfoWindow} if it is visible, otherwise calling this will do nothing. + * + * @return This {@link InfoWindow} + */ + InfoWindow close() { + MapboxMap mapboxMap = this.mapboxMap.get(); + if (isVisible && mapboxMap != null) { + isVisible = false; + View view = this.view.get(); + if (view != null && view.getParent() != null) { + ((ViewGroup) view.getParent()).removeView(view); + } + + Marker marker = getBoundMarker(); + MapboxMap.OnInfoWindowCloseListener listener = mapboxMap.getOnInfoWindowCloseListener(); + if (listener != null) { + listener.onInfoWindowClose(marker); + } + + setBoundMarker(null); } - - /** - * 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, MapboxMap mapboxMap, MapView mapView) { - View view = mView.get(); - if (view == null) { - view = LayoutInflater.from(mapView.getContext()).inflate(mLayoutRes, mapView, false); - initialize(view, mapboxMap); - } - mMapboxMap = new WeakReference<>(mapboxMap); - String title = overlayItem.getTitle(); - TextView titleTextView = ((TextView) view.findViewById(R.id.infowindow_title)); - if (!TextUtils.isEmpty(title)) { - titleTextView.setText(title); - titleTextView.setVisibility(View.VISIBLE); - } else { - titleTextView.setVisibility(View.GONE); - } - - String snippet = overlayItem.getSnippet(); - TextView snippetTextView = ((TextView) view.findViewById(R.id.infowindow_description)); - if (!TextUtils.isEmpty(snippet)) { - snippetTextView.setText(snippet); - snippetTextView.setVisibility(View.VISIBLE); - } else { - snippetTextView.setVisibility(View.GONE); - } + 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, MapboxMap mapboxMap, MapView mapView) { + View view = this.view.get(); + if (view == null) { + view = LayoutInflater.from(mapView.getContext()).inflate(layoutRes, mapView, false); + initialize(view, mapboxMap); } - - InfoWindow setBoundMarker(Marker boundMarker) { - mBoundMarker = new WeakReference<>(boundMarker); - return this; + this.mapboxMap = new WeakReference<>(mapboxMap); + String title = overlayItem.getTitle(); + TextView titleTextView = ((TextView) view.findViewById(R.id.infowindow_title)); + if (!TextUtils.isEmpty(title)) { + titleTextView.setText(title); + titleTextView.setVisibility(View.VISIBLE); + } else { + titleTextView.setVisibility(View.GONE); } - Marker getBoundMarker() { - if (mBoundMarker == null) { - return null; - } - return mBoundMarker.get(); + String snippet = overlayItem.getSnippet(); + TextView snippetTextView = ((TextView) view.findViewById(R.id.infowindow_description)); + if (!TextUtils.isEmpty(snippet)) { + snippetTextView.setText(snippet); + snippetTextView.setVisibility(View.VISIBLE); + } else { + snippetTextView.setVisibility(View.GONE); } + } - /** - * Will result in getting this {@link InfoWindow} and updating the view being displayed. - */ - public void update() { - MapboxMap mapboxMap = mMapboxMap.get(); - Marker marker = mBoundMarker.get(); - View view = mView.get(); - if (mapboxMap != null && marker != null && view != null) { - mCoordinates = mapboxMap.getProjection().toScreenLocation(marker.getPosition()); - - if (view instanceof InfoWindowView) { - view.setX(mCoordinates.x + mViewWidthOffset - mMarkerWidthOffset); - } else { - view.setX(mCoordinates.x - (view.getMeasuredWidth() / 2) - mMarkerWidthOffset); - } - view.setY(mCoordinates.y + mMarkerHeightOffset); - } - } + InfoWindow setBoundMarker(Marker boundMarker) { + this.boundMarker = new WeakReference<>(boundMarker); + return this; + } - /** - * Retrieve this {@link InfoWindow}'s current view being used. - * - * @return This {@link InfoWindow}'s current View. - */ - public View getView() { - return mView != null ? mView.get() : null; + Marker getBoundMarker() { + if (boundMarker == null) { + return null; } - - boolean isVisible() { - return mIsVisible; + return boundMarker.get(); + } + + /** + * Will result in getting this {@link InfoWindow} and updating the view being displayed. + */ + public void update() { + MapboxMap mapboxMap = this.mapboxMap.get(); + Marker marker = boundMarker.get(); + View view = this.view.get(); + if (mapboxMap != null && marker != null && view != null) { + coordinates = mapboxMap.getProjection().toScreenLocation(marker.getPosition()); + + if (view instanceof InfoWindowView) { + view.setX(coordinates.x + viewWidthOffset - markerWidthOffset); + } else { + view.setX(coordinates.x - (view.getMeasuredWidth() / 2) - markerWidthOffset); + } + view.setY(coordinates.y + markerHeightOffset); } + } + + /** + * Retrieve this {@link InfoWindow}'s current view being used. + * + * @return This {@link InfoWindow}'s current View. + */ + public View getView() { + return view != null ? view.get() : null; + } + + boolean isVisible() { + return isVisible; + } } 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 index 41c7fc9e97..abcebfec83 100644 --- 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 @@ -12,51 +12,51 @@ 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.mapbox_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); - } + 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.mapbox_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 index 7595073aa2..d1a59aae4e 100644 --- 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 @@ -9,30 +9,30 @@ 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.mapbox_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.mapbox_infowindow_offset); - } + 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.mapbox_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.mapbox_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 index c4d1090194..edf118205b 100644 --- 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 @@ -27,249 +27,249 @@ import com.mapbox.mapboxsdk.maps.MapboxMap; */ public class Marker extends Annotation { - private LatLng position; - private String snippet; - private Icon icon; - private String title; + private LatLng position; + private String snippet; + private Icon icon; + private String title; - private InfoWindow infoWindow; - private boolean infoWindowShown; + private InfoWindow infoWindow; + private boolean infoWindowShown; - private int topOffsetPixels; - private int rightOffsetPixels; + private int topOffsetPixels; + private int rightOffsetPixels; - /** - * Constructor - */ - Marker() { - super(); - } + /** + * Constructor + */ + Marker() { + super(); + } - /** - * Creates a instance of {@link Marker} using the builder of Marker. - * - * @param baseMarkerOptions The builder used to construct the Marker. - */ - public Marker(BaseMarkerOptions baseMarkerOptions) { - position = baseMarkerOptions.position; - snippet = baseMarkerOptions.snippet; - icon = baseMarkerOptions.icon; - title = baseMarkerOptions.title; - } + /** + * Creates a instance of {@link Marker} using the builder of Marker. + * + * @param baseMarkerOptions The builder used to construct the Marker. + */ + public Marker(BaseMarkerOptions baseMarkerOptions) { + position = baseMarkerOptions.position; + snippet = baseMarkerOptions.snippet; + icon = baseMarkerOptions.icon; + title = baseMarkerOptions.title; + } - Marker(BaseMarkerViewOptions baseMarkerViewOptions) { - position = baseMarkerViewOptions.position; - snippet = baseMarkerViewOptions.snippet; - icon = baseMarkerViewOptions.icon; - title = baseMarkerViewOptions.title; - } + Marker(BaseMarkerViewOptions baseMarkerViewOptions) { + position = baseMarkerViewOptions.position; + snippet = baseMarkerViewOptions.snippet; + icon = baseMarkerViewOptions.icon; + title = baseMarkerViewOptions.title; + } - Marker(LatLng position, Icon icon, String title, String snippet) { - this.position = position; - this.icon = icon; - this.title = title; - this.snippet = snippet; - } + Marker(LatLng position, Icon icon, String title, String snippet) { + this.position = position; + this.icon = icon; + this.title = title; + this.snippet = snippet; + } - /** - * Returns the position of the marker. - * - * @return A {@link LatLng} object specifying the marker's current position. - */ - public LatLng getPosition() { - return position; - } + /** + * Returns the position of the marker. + * + * @return A {@link LatLng} object specifying the marker's current position. + */ + public LatLng getPosition() { + return position; + } - /** - * Gets the snippet of the marker. - * - * @return A string containing the marker's snippet. - */ - public String getSnippet() { - return snippet; - } + /** + * Gets the snippet of the marker. + * + * @return A string containing the marker's snippet. + */ + public String getSnippet() { + return snippet; + } - /** - * Gets the snippet of the marker. - * - * @return A string containing the marker's snippet. - */ - public String getTitle() { - return title; - } + /** + * Gets the snippet of the marker. + * + * @return A string containing the marker's 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 void hideInfoWindow() { + if (infoWindow != null) { + infoWindow.close(); } + infoWindowShown = false; + } - /** - * Do not use this method, used internally by the SDK. - * - * @return true if the infoWindow is shown - */ - public boolean isInfoWindowShown() { - return infoWindowShown; - } + /** + * Do not use this method, used internally by the SDK. + * + * @return true if the infoWindow is shown + */ + public boolean isInfoWindowShown() { + return infoWindowShown; + } - /** - * Sets the location of the marker. - * - * @param position A {@link LatLng} defining the marker position. - */ - public void setPosition(LatLng position) { - this.position = position; - MapboxMap map = getMapboxMap(); - if (map != null) { - map.updateMarker(this); - } + /** + * Sets the location of the marker. + * + * @param position A {@link LatLng} defining the marker position. + */ + public void setPosition(LatLng position) { + this.position = position; + MapboxMap map = getMapboxMap(); + if (map != null) { + map.updateMarker(this); } + } - /** - * Sets the snippet of the marker. - * - * @param snippet A String used in the marker info window. If {@code null}, the snippet is - * cleared. - */ - public void setSnippet(String snippet) { - this.snippet = snippet; - refreshInfoWindowContent(); - } + /** + * Sets the snippet of the marker. + * + * @param snippet A String used in the marker info window. If {@code null}, the snippet is + * cleared. + */ + public void setSnippet(String snippet) { + this.snippet = snippet; + refreshInfoWindowContent(); + } - /** - * Sets the icon of the marker. - * - * @param icon The {@link Icon} to be used as Marker image - */ - public void setIcon(@Nullable Icon icon) { - this.icon = icon; - MapboxMap map = getMapboxMap(); - if (map != null) { - map.updateMarker(this); - } + /** + * Sets the icon of the marker. + * + * @param icon The {@link Icon} to be used as Marker image + */ + public void setIcon(@Nullable Icon icon) { + this.icon = icon; + MapboxMap map = getMapboxMap(); + if (map != null) { + map.updateMarker(this); } + } - /** - * Gets the {@link Icon} currently used for the marker. If no Icon was set for the marker, the - * default icon will be returned. - * - * @return The {@link Icon} the marker is using. - */ - public Icon getIcon() { - return icon; - } + /** + * Gets the {@link Icon} currently used for the marker. If no Icon was set for the marker, the + * default icon will be returned. + * + * @return The {@link Icon} the marker is using. + */ + public Icon getIcon() { + return icon; + } - /** - * Sets the title of the marker. - * - * @param title A String used in the marker info window. If {@code null}, the title is - * cleared. - */ - public void setTitle(String title) { - this.title = title; - refreshInfoWindowContent(); - } + /** + * Sets the title of the marker. + * + * @param title A String used in the marker info window. If {@code null}, the title is + * cleared. + */ + public void setTitle(String title) { + this.title = title; + refreshInfoWindowContent(); + } - /** - * Gets the {@link InfoWindow} the marker is using. If the marker hasn't had an info window - * defined, this will return {@code null}. - * - * @return - */ - @Nullable - public InfoWindow getInfoWindow() { - return infoWindow; - } + /** + * Gets the {@link InfoWindow} the marker is using. If the marker hasn't had an info window + * defined, this will return {@code null}. + * + * @return The info window the marker is using. + */ + @Nullable + public InfoWindow getInfoWindow() { + return infoWindow; + } - /** - * Update only for default Marker's InfoWindow content for Title and Snippet - */ - private void refreshInfoWindowContent() { - if (isInfoWindowShown() && mapView != null && mapboxMap != null && mapboxMap.getInfoWindowAdapter() == null) { - InfoWindow infoWindow = getInfoWindow(mapView); - if (mapView.getContext() != null) { - infoWindow.adaptDefaultMarker(this, mapboxMap, mapView); - } - MapboxMap map = getMapboxMap(); - if (map != null) { - map.updateMarker(this); - } - infoWindow.update(); - } + /** + * Update only for default Marker's InfoWindow content for Title and Snippet + */ + private void refreshInfoWindowContent() { + if (isInfoWindowShown() && mapView != null && mapboxMap != null && mapboxMap.getInfoWindowAdapter() == null) { + InfoWindow infoWindow = getInfoWindow(mapView); + if (mapView.getContext() != null) { + infoWindow.adaptDefaultMarker(this, mapboxMap, mapView); + } + MapboxMap map = getMapboxMap(); + if (map != null) { + map.updateMarker(this); + } + infoWindow.update(); } + } - /** - * Do not use this method, used internally by the SDK. Use {@link MapboxMap#selectMarker(Marker)} - * if you want to programmatically display the markers info window. - * - * @param mapboxMap The hosting mapbox map. - * @param mapView The hosting map view. - * @return The info window that was shown. - */ - public InfoWindow showInfoWindow(@NonNull MapboxMap mapboxMap, @NonNull MapView mapView) { - setMapboxMap(mapboxMap); - setMapView(mapView); - MapboxMap.InfoWindowAdapter infoWindowAdapter = getMapboxMap().getInfoWindowAdapter(); - if (infoWindowAdapter != null) { - // end developer is using a custom InfoWindowAdapter - View content = infoWindowAdapter.getInfoWindow(this); - if (content != null) { - infoWindow = new InfoWindow(content, mapboxMap); - showInfoWindow(infoWindow, mapView); - return infoWindow; - } - } - - InfoWindow infoWindow = getInfoWindow(mapView); - if (mapView.getContext() != null) { - infoWindow.adaptDefaultMarker(this, mapboxMap, mapView); - } - return showInfoWindow(infoWindow, mapView); + /** + * Do not use this method, used internally by the SDK. Use {@link MapboxMap#selectMarker(Marker)} + * if you want to programmatically display the markers info window. + * + * @param mapboxMap The hosting mapbox map. + * @param mapView The hosting map view. + * @return The info window that was shown. + */ + public InfoWindow showInfoWindow(@NonNull MapboxMap mapboxMap, @NonNull MapView mapView) { + setMapboxMap(mapboxMap); + setMapView(mapView); + MapboxMap.InfoWindowAdapter infoWindowAdapter = getMapboxMap().getInfoWindowAdapter(); + if (infoWindowAdapter != null) { + // end developer is using a custom InfoWindowAdapter + View content = infoWindowAdapter.getInfoWindow(this); + if (content != null) { + infoWindow = new InfoWindow(content, mapboxMap); + showInfoWindow(infoWindow, mapView); + return infoWindow; + } } - private InfoWindow showInfoWindow(InfoWindow iw, MapView mapView) { - iw.open(mapView, this, getPosition(), rightOffsetPixels, topOffsetPixels); - infoWindowShown = true; - return iw; + InfoWindow infoWindow = getInfoWindow(mapView); + if (mapView.getContext() != null) { + infoWindow.adaptDefaultMarker(this, mapboxMap, mapView); } + return showInfoWindow(infoWindow, mapView); + } - private InfoWindow getInfoWindow(@NonNull MapView mapView) { - if (infoWindow == null && mapView.getContext() != null) { - infoWindow = new InfoWindow(mapView, R.layout.mapbox_infowindow_view, getMapboxMap()); - } - return infoWindow; - } + private InfoWindow showInfoWindow(InfoWindow iw, MapView mapView) { + iw.open(mapView, this, getPosition(), rightOffsetPixels, topOffsetPixels); + infoWindowShown = true; + return iw; + } - /** - * Do not use this method, used internally by the SDK. - * - * @param topOffsetPixels the top offset pixels. - */ - public void setTopOffsetPixels(int topOffsetPixels) { - this.topOffsetPixels = topOffsetPixels; + private InfoWindow getInfoWindow(@NonNull MapView mapView) { + if (infoWindow == null && mapView.getContext() != null) { + infoWindow = new InfoWindow(mapView, R.layout.mapbox_infowindow_view, getMapboxMap()); } + return infoWindow; + } - /** - * Do not use this method, used internally by the SDK. - * - * @param rightOffsetPixels the right offset pixels. - */ - public void setRightOffsetPixels(int rightOffsetPixels) { - this.rightOffsetPixels = rightOffsetPixels; - } + /** + * Do not use this method, used internally by the SDK. + * + * @param topOffsetPixels the top offset pixels. + */ + public void setTopOffsetPixels(int topOffsetPixels) { + this.topOffsetPixels = topOffsetPixels; + } - /** - * Returns a String with the marker position. - * - * @return A String with the marker position. - */ - @Override - public String toString() { - return "Marker [position[" + getPosition() + "]]"; - } + /** + * Do not use this method, used internally by the SDK. + * + * @param rightOffsetPixels the right offset pixels. + */ + public void setRightOffsetPixels(int rightOffsetPixels) { + this.rightOffsetPixels = rightOffsetPixels; + } + + /** + * Returns a String with the marker position. + * + * @return A String with the marker position. + */ + @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 index 282da6407e..49d4867801 100644 --- 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 @@ -21,161 +21,168 @@ import com.mapbox.mapboxsdk.geometry.LatLng; */ public final class MarkerOptions extends BaseMarkerOptions<Marker, MarkerOptions> implements Parcelable { - /** - * Defines options for a Marker. - */ - public MarkerOptions() { + /** + * Defines options for a Marker. + */ + public MarkerOptions() { + } + + protected MarkerOptions(Parcel in) { + position((LatLng) in.readParcelable(LatLng.class.getClassLoader())); + snippet(in.readString()); + title(in.readString()); + if (in.readByte() != 0) { + // this means we have an icon + String iconId = in.readString(); + Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader()); + Icon icon = new Icon(iconId, iconBitmap); + icon(icon); } - - protected MarkerOptions(Parcel in) { - position((LatLng) in.readParcelable(LatLng.class.getClassLoader())); - snippet(in.readString()); - title(in.readString()); - if (in.readByte() != 0) { - // this means we have an icon - String iconId = in.readString(); - Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader()); - Icon icon = new Icon(iconId, iconBitmap); - icon(icon); - } + } + + @Override + public MarkerOptions getThis() { + return this; + } + + /** + * Describe the kinds of special objects contained in this Parcelable's + * marshalled representation. + * + * @return integer 0. + */ + @Override + public int describeContents() { + return 0; + } + + /** + * Flatten this object in to a Parcel. + * + * @param out The Parcel in which the object should be written. + * @param flags Additional flags about how the object should be written. May be 0 or + * {@link #PARCELABLE_WRITE_RETURN_VALUE}. + */ + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeParcelable(getPosition(), flags); + out.writeString(getSnippet()); + out.writeString(getTitle()); + Icon icon = getIcon(); + out.writeByte((byte) (icon != null ? 1 : 0)); + if (icon != null) { + out.writeString(getIcon().getId()); + out.writeParcelable(getIcon().getBitmap(), flags); } - - @Override - public MarkerOptions getThis() { - return this; + } + + /** + * Do not use this method. Used internally by the SDK. + * + * @return Marker The build marker + */ + public Marker getMarker() { + if (position == null) { + throw new InvalidMarkerPositionException(); } - /** - * Describe the kinds of special objects contained in this Parcelable's - * marshalled representation. - * - * @return integer 0. - */ - @Override - public int describeContents() { - return 0; - } + return new Marker(position, icon, title, snippet); + } + + /** + * Returns the position set for this {@link MarkerOptions} object. + * + * @return A {@link LatLng} object specifying the marker's current position. + */ + public LatLng getPosition() { + return position; + } + + /** + * Gets the snippet set for this {@link MarkerOptions} object. + * + * @return A string containing the marker's snippet. + */ + public String getSnippet() { + return snippet; + } + + /** + * Gets the title set for this {@link MarkerOptions} object. + * + * @return A string containing the marker's title. + */ + public String getTitle() { + return title; + } + + /** + * Gets the custom icon set for this {@link MarkerOptions} object. + * + * @return A {@link Icon} object that the marker is using. If the icon wasn't set, default icon + * will return. + */ + public Icon getIcon() { + return icon; + } + + 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]; + } + }; - /** - * Flatten this object in to a Parcel. - * - * @param out The Parcel in which the object should be written. - * @param flags Additional flags about how the object should be written. May be 0 or - * {@link #PARCELABLE_WRITE_RETURN_VALUE}. - */ - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeParcelable(getPosition(), flags); - out.writeString(getSnippet()); - out.writeString(getTitle()); - Icon icon = getIcon(); - out.writeByte((byte) (icon != null ? 1 : 0)); - if (icon != null) { - out.writeString(getIcon().getId()); - out.writeParcelable(getIcon().getBitmap(), flags); - } + /** + * Compares this {@link MarkerOptions} object with another {@link MarkerOptions} and + * determines if their properties match. + * + * @param o Another {@link MarkerOptions} to compare with this object. + * @return True if marker properties match this {@link MarkerOptions} object. + * Else, false. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; } - - /** - * Do not use this method. Used internally by the SDK. - * - * @return Marker The build marker - */ - public Marker getMarker() { - if (position == null) { - throw new InvalidMarkerPositionException(); - } - - return new Marker(position, icon, title, snippet); + if (o == null || getClass() != o.getClass()) { + return false; } - /** - * Returns the position set for this {@link MarkerOptions} object. - * - * @return A {@link LatLng} object specifying the marker's current position. - */ - public LatLng getPosition() { - return position; - } + MarkerOptions marker = (MarkerOptions) o; - /** - * Gets the snippet set for this {@link MarkerOptions} object. - * - * @return A string containing the marker's snippet. - */ - public String getSnippet() { - return snippet; + if (getPosition() != null ? !getPosition().equals(marker.getPosition()) : marker.getPosition() != null) { + return false; } - - /** - * Gets the title set for this {@link MarkerOptions} object. - * - * @return A string containing the marker's title. - */ - public String getTitle() { - return title; + if (getSnippet() != null ? !getSnippet().equals(marker.getSnippet()) : marker.getSnippet() != null) { + return false; } - - /** - * Gets the custom icon set for this {@link MarkerOptions} object. - * - * @return A {@link Icon} object that the marker is using. If the icon wasn't set, default icon - * will return. - */ - public Icon getIcon() { - return icon; - } - - 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]; - } - }; - - /** - * Compares this {@link MarkerOptions} object with another {@link MarkerOptions} and - * determines if their properties match. - * - * @param o Another {@link MarkerOptions} to compare with this object. - * @return True if marker properties match this {@link MarkerOptions} object. - * Else, false. - */ - @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); - } - - /** - * Gives an integer which can be used as the bucket number for storing elements of the set/map. - * This bucket number is the address of the element inside the set/map. There's no guarantee - * that this hash value will be consistent between different Java implementations, or even - * between different execution runs of the same program. - * - * @return integer value you can use for storing element. - */ - @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; + if (getIcon() != null ? !getIcon().equals(marker.getIcon()) : marker.getIcon() != null) { + return false; } + return !(getTitle() != null ? !getTitle().equals(marker.getTitle()) : marker.getTitle() != null); + } + + /** + * Gives an integer which can be used as the bucket number for storing elements of the set/map. + * This bucket number is the address of the element inside the set/map. There's no guarantee + * that this hash value will be consistent between different Java implementations, or even + * between different execution runs of the same program. + * + * @return integer value you can use for storing element. + */ + @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/MarkerView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java index a32186b52e..c1b643eb4c 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java @@ -26,382 +26,384 @@ import com.mapbox.mapboxsdk.maps.MapboxMap; */ public class MarkerView extends Marker { - private MarkerViewManager markerViewManager; - - private float width; - private float height; - - private float anchorU; - private float anchorV; - - private float offsetX = MapboxConstants.UNMEASURED; - private float offsetY = MapboxConstants.UNMEASURED; - - private float infoWindowAnchorU; - private float infoWindowAnchorV; - - private boolean flat; - private boolean visible = true; - - private float tiltValue; - private float rotation; - private float alpha = 1; - - private Icon markerViewIcon; - - private boolean selected; - - - /** - * Publicly hidden default constructor - */ - MarkerView() { - } - - /** - * Creates a instance of MarkerView using the builder of MarkerView - * - * @param baseMarkerViewOptions the builder used to construct the MarkerView - */ - public MarkerView(BaseMarkerViewOptions baseMarkerViewOptions) { - super(baseMarkerViewOptions); - this.alpha = baseMarkerViewOptions.getAlpha(); - this.anchorU = baseMarkerViewOptions.getAnchorU(); - this.anchorV = baseMarkerViewOptions.getAnchorV(); - this.infoWindowAnchorU = baseMarkerViewOptions.getInfoWindowAnchorU(); - this.infoWindowAnchorV = baseMarkerViewOptions.getInfoWindowAnchorV(); - this.flat = baseMarkerViewOptions.isFlat(); - this.rotation = baseMarkerViewOptions.getRotation(); - this.selected = baseMarkerViewOptions.selected; - } - - float getWidth() { - return width; - } - - void setWidth(float width) { - this.width = width; - } - - float getHeight() { - return height; - } - - void setHeight(float height) { - this.height = height; - } - - /** - * Specifies the anchor being set on a particular point of the MarkerView. - * <p> - * The anchor point is specified in the continuous space [0.0, 1.0] x [0.0, 1.0], where (0, 0) - * is the top-left corner of the image, and (1, 1) is the bottom-right corner. - * </p> - * - * @param u u-coordinate of the anchor, as a ratio of the image width (in the range [0, 1]). - * @param v v-coordinate of the anchor, as a ratio of the image height (in the range [0, 1]). - */ - public void setAnchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) { - this.anchorU = u; - this.anchorV = v; - setOffset(-1, -1); - } - - /** - * Get the horizontal distance, normalized to [0, 1], of the anchor from the left edge. - * - * @return The u-value of the anchor. - */ - public float getAnchorU() { - return anchorU; - } - - /** - * Get the vertical distance, normalized to [0, 1], of the anchor from the top edge. - * - * @return the v-value of the anchor. - */ - public float getAnchorV() { - return anchorV; - } - - /** - * Internal method to set the calculated offset. - * <p> - * These are calculated based on the View bounds and the provided anchor. - * </p> - * - * @param x the x-value of the offset. - * @param y the y-value of the offset. - */ - void setOffset(float x, float y) { - offsetX = x; - offsetY = y; - } - - /** - * Internal method to get the horizontal calculated offset. - * - * @return the calculated horizontal offset. - */ - float getOffsetX() { - return offsetX; - } - - /** - * Internal method to get the vertical calculated offset. - * - * @return the calculated vertical offset. - */ - float getOffsetY() { - return offsetY; - } - - /** - * Specifies the anchor point of the info window on the View of the MarkerView. - * <p> - * The anchor point is specified in the continuous space [0.0, 1.0] x [0.0, 1.0], where (0, 0) - * is the top-left corner of the image, and (1, 1) is the bottom-right corner. - * </p> - * <p> - * The default is the top middle of the View. - * </p> - * - * @param u u-coordinate of the info window anchor, as a ratio of the image width (in the range [0, 1]). - * @param v v-coordinate of the info window anchor, as a ratio of the image height (in the range [0, 1]). - * @see #setAnchor(float, float) for more details. - */ - public void setInfoWindowAnchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) { - this.infoWindowAnchorU = u; - this.infoWindowAnchorV = v; - } - - /** - * Get the horizontal distance, normalized to [0, 1], of the info window anchor from the left edge. - * - * @return the u value of the InfoWindow anchor. - */ - public float getInfoWindowAnchorU() { - return infoWindowAnchorU; - } - - /** - * Get the vertical distance, normalized to [0, 1], of the info window anchor from the top edge. - * - * @return the v value of the InfoWindow anchor. - */ - public float getInfoWindowAnchorV() { - return infoWindowAnchorV; - } - - /** - * Get the flat state of a MarkerView. - * - * @return true if the MarkerView is flat; false if the MarkerView is billboard. - */ - public boolean isFlat() { - return flat; - } - - /** - * Sets whether this MarkerView should be flat against the map (true) or a billboard facing the - * camera (false). - * - * @param flat the flat state of the MarkerView. - */ - public void setFlat(boolean flat) { - this.flat = flat; - } - - /** - * Internal method to get the current tilted value of a MarkerView. - * - * @return the tilted value. - */ - float getTilt() { - return tiltValue; - } - - /** - * Internal method to set the current titled value of a MarkerView. - * - * @param tiltValue the tilted value to set. - */ - void setTilt(@FloatRange(from = 0.0, to = MapboxConstants.MAXIMUM_TILT) float tiltValue) { - this.tiltValue = tiltValue; - } - - /** - * Set the visible state of a MarkerView. - * - * @param visible true will make the MarkerView visible, false will hide the MarkerView. - */ - public void setVisible(boolean visible) { - this.visible = visible; - if (markerViewManager != null) { - markerViewManager.animateVisible(this, visible); - } - } - - /** - * Returns the visible state of the MarkerView. - * - * @return the visible state. - */ - public boolean isVisible() { - return visible; - } - - /** - * Set the rotation value of the MarkerView in degrees. - * <p> - * Input will be limited to 0 - 360 degrees. - * </p> - * <p> - * This will result in animating the rotation of the MarkerView using an rotation animator - * from current value to the provided parameter value. - * </p> - * - * @param rotation the rotation value to animate to. - */ - public void setRotation(float rotation) { - // limit to 0 - 360 degrees - float newRotation = rotation; - while (newRotation > 360) { - newRotation -= 360; - } - while (newRotation < 0) { - newRotation += 360; - } - - this.rotation = newRotation; - if (markerViewManager != null) { - markerViewManager.animateRotationBy(this, newRotation); - } - } - - /** - * Get the rotation value of the MarkerView. - * - * @return the rotation value. - */ - public float getRotation() { - return rotation; - } - - /** - * Get the alpha value of the MarkerView. - * - * @return the alpha value. - */ - public float getAlpha() { - return alpha; - } - - /** - * Set the alpha value of the MarkerView. - * <p> - * This will result in animating the alpha of the MarkerView using an alpha animator - * from current value to the provided parameter value. - * </p> - * - * @param alpha the alpha value to animate to. - */ - public void setAlpha(@FloatRange(from = 0.0, to = 255.0) float alpha) { - this.alpha = alpha; - if (markerViewManager != null) { - markerViewManager.animateAlpha(this, alpha); - } - } - - /** - * Set the icon of the MarkerView. - * - * @param icon the {@link Icon} to be used as Marker image. - */ - @Override - public void setIcon(@Nullable Icon icon) { - if (icon != null) { - markerViewIcon = IconFactory.recreate(IconFactory.ICON_MARKERVIEW_ID, icon.getBitmap()); - } - Icon transparentIcon = IconFactory.recreate(IconFactory.ICON_MARKERVIEW_ID, - IconFactory.ICON_MARKERVIEW_BITMAP); - if (markerViewManager != null) { - markerViewManager.updateIcon(this); - } - super.setIcon(transparentIcon); - } - - /** - * Sets the location of the marker. - * - * @param position A {@link LatLng} defining the marker position. - */ - @Override - public void setPosition(LatLng position) { - super.setPosition(position); - if (markerViewManager != null) { - markerViewManager.update(); - } - } - - /** - * Determine if the {@link MarkerView} is selected or not. - * - * @return True if the MarkerView's selected, else false. - */ - public boolean isSelected() { - return selected; - } - - /** - * For internal use only, use {@link MapboxMap#selectMarker(Marker)} instead. - */ - void setSelected(boolean selected) { - this.selected = selected; - } - - /** - * Get the icon of the MarkerView. - * - * @return the icon use as Marker image. - */ - @Override - public Icon getIcon() { - return markerViewIcon; - } - - /** - * Set the MapboxMap associated tot the MapView containing the MarkerView. - * <p> - * This method is used to instantiate the MarkerView and provide an instance of {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter} - * </p> - * <p> - * This method is used to notify that a MarkerView is no longer active by setting a null value. - * </p> - * - * @param mapboxMap the MapboxMap instances. - */ - @Override - public void setMapboxMap(MapboxMap mapboxMap) { - super.setMapboxMap(mapboxMap); - if (mapboxMap != null) { - if (isFlat()) { - // initial tilt value if MapboxMap is started with a tilt attribute - tiltValue = (float) mapboxMap.getCameraPosition().tilt; - } - - markerViewManager = mapboxMap.getMarkerViewManager(); - } - } - - /** - * Get the String representation of a MarkerView. - * - * @return the String representation. - */ - @Override - public String toString() { - return "MarkerView [position[" + getPosition() + "]]"; - } + private MarkerViewManager markerViewManager; + + private float width; + private float height; + + private float anchorU; + private float anchorV; + + private float offsetX = MapboxConstants.UNMEASURED; + private float offsetY = MapboxConstants.UNMEASURED; + + private float infoWindowAnchorU; + private float infoWindowAnchorV; + + private boolean flat; + private boolean visible = true; + + private float tiltValue; + private float rotation; + private float alpha = 1; + + private Icon markerViewIcon; + + private boolean selected; + + + /** + * Publicly hidden default constructor + */ + MarkerView() { + } + + /** + * Creates a instance of MarkerView using the builder of MarkerView + * + * @param baseMarkerViewOptions the builder used to construct the MarkerView + */ + public MarkerView(BaseMarkerViewOptions baseMarkerViewOptions) { + super(baseMarkerViewOptions); + this.alpha = baseMarkerViewOptions.getAlpha(); + this.anchorU = baseMarkerViewOptions.getAnchorU(); + this.anchorV = baseMarkerViewOptions.getAnchorV(); + this.infoWindowAnchorU = baseMarkerViewOptions.getInfoWindowAnchorU(); + this.infoWindowAnchorV = baseMarkerViewOptions.getInfoWindowAnchorV(); + this.flat = baseMarkerViewOptions.isFlat(); + this.rotation = baseMarkerViewOptions.getRotation(); + this.selected = baseMarkerViewOptions.selected; + } + + float getWidth() { + return width; + } + + void setWidth(float width) { + this.width = width; + } + + float getHeight() { + return height; + } + + void setHeight(float height) { + this.height = height; + } + + /** + * Specifies the anchor being set on a particular point of the MarkerView. + * <p> + * The anchor point is specified in the continuous space [0.0, 1.0] x [0.0, 1.0], where (0, 0) + * is the top-left corner of the image, and (1, 1) is the bottom-right corner. + * </p> + * + * @param u u-coordinate of the anchor, as a ratio of the image width (in the range [0, 1]). + * @param v v-coordinate of the anchor, as a ratio of the image height (in the range [0, 1]). + */ + public void setAnchor(@FloatRange(from = 0.0, to = 1.0) float u, @FloatRange(from = 0.0, to = 1.0) float v) { + this.anchorU = u; + this.anchorV = v; + setOffset(-1, -1); + } + + /** + * Get the horizontal distance, normalized to [0, 1], of the anchor from the left edge. + * + * @return The u-value of the anchor. + */ + public float getAnchorU() { + return anchorU; + } + + /** + * Get the vertical distance, normalized to [0, 1], of the anchor from the top edge. + * + * @return the v-value of the anchor. + */ + public float getAnchorV() { + return anchorV; + } + + /** + * Internal method to set the calculated offset. + * <p> + * These are calculated based on the View bounds and the provided anchor. + * </p> + * + * @param x the x-value of the offset. + * @param y the y-value of the offset. + */ + void setOffset(float x, float y) { + offsetX = x; + offsetY = y; + } + + /** + * Internal method to get the horizontal calculated offset. + * + * @return the calculated horizontal offset. + */ + float getOffsetX() { + return offsetX; + } + + /** + * Internal method to get the vertical calculated offset. + * + * @return the calculated vertical offset. + */ + float getOffsetY() { + return offsetY; + } + + /** + * Specifies the anchor point of the info window on the View of the MarkerView. + * <p> + * The anchor point is specified in the continuous space [0.0, 1.0] x [0.0, 1.0], where (0, 0) + * is the top-left corner of the image, and (1, 1) is the bottom-right corner. + * </p> + * <p> + * The default is the top middle of the View. + * </p> + * + * @param u u-coordinate of the info window anchor, as a ratio of the image width (in the range [0, 1]). + * @param v v-coordinate of the info window anchor, as a ratio of the image height (in the range [0, 1]). + * @see #setAnchor(float, float) for more details. + */ + public void setInfoWindowAnchor(@FloatRange(from = 0.0, to = 1.0) float u, + @FloatRange(from = 0.0, to = 1.0) float v) { + this.infoWindowAnchorU = u; + this.infoWindowAnchorV = v; + } + + /** + * Get the horizontal distance, normalized to [0, 1], of the info window anchor from the left edge. + * + * @return the u value of the InfoWindow anchor. + */ + public float getInfoWindowAnchorU() { + return infoWindowAnchorU; + } + + /** + * Get the vertical distance, normalized to [0, 1], of the info window anchor from the top edge. + * + * @return the v value of the InfoWindow anchor. + */ + public float getInfoWindowAnchorV() { + return infoWindowAnchorV; + } + + /** + * Get the flat state of a MarkerView. + * + * @return true if the MarkerView is flat; false if the MarkerView is billboard. + */ + public boolean isFlat() { + return flat; + } + + /** + * Sets whether this MarkerView should be flat against the map (true) or a billboard facing the + * camera (false). + * + * @param flat the flat state of the MarkerView. + */ + public void setFlat(boolean flat) { + this.flat = flat; + } + + /** + * Internal method to get the current tilted value of a MarkerView. + * + * @return the tilted value. + */ + float getTilt() { + return tiltValue; + } + + /** + * Internal method to set the current titled value of a MarkerView. + * + * @param tiltValue the tilted value to set. + */ + void setTilt(@FloatRange(from = 0.0, to = MapboxConstants.MAXIMUM_TILT) float tiltValue) { + this.tiltValue = tiltValue; + } + + /** + * Set the visible state of a MarkerView. + * + * @param visible true will make the MarkerView visible, false will hide the MarkerView. + */ + public void setVisible(boolean visible) { + this.visible = visible; + if (markerViewManager != null) { + markerViewManager.animateVisible(this, visible); + } + } + + /** + * Returns the visible state of the MarkerView. + * + * @return the visible state. + */ + public boolean isVisible() { + return visible; + } + + /** + * Set the rotation value of the MarkerView in degrees. + * <p> + * Input will be limited to 0 - 360 degrees. + * </p> + * <p> + * This will result in animating the rotation of the MarkerView using an rotation animator + * from current value to the provided parameter value. + * </p> + * + * @param rotation the rotation value to animate to. + */ + public void setRotation(float rotation) { + // limit to 0 - 360 degrees + float newRotation = rotation; + while (newRotation > 360) { + newRotation -= 360; + } + while (newRotation < 0) { + newRotation += 360; + } + + this.rotation = newRotation; + if (markerViewManager != null) { + markerViewManager.animateRotationBy(this, newRotation); + } + } + + /** + * Get the rotation value of the MarkerView. + * + * @return the rotation value. + */ + public float getRotation() { + return rotation; + } + + /** + * Get the alpha value of the MarkerView. + * + * @return the alpha value. + */ + public float getAlpha() { + return alpha; + } + + /** + * Set the alpha value of the MarkerView. + * <p> + * This will result in animating the alpha of the MarkerView using an alpha animator + * from current value to the provided parameter value. + * </p> + * + * @param alpha the alpha value to animate to. + */ + public void setAlpha(@FloatRange(from = 0.0, to = 255.0) float alpha) { + this.alpha = alpha; + if (markerViewManager != null) { + markerViewManager.animateAlpha(this, alpha); + } + } + + /** + * Set the icon of the MarkerView. + * + * @param icon the {@link Icon} to be used as Marker image. + */ + @Override + public void setIcon(@Nullable Icon icon) { + if (icon != null) { + markerViewIcon = IconFactory.recreate(IconFactory.ICON_MARKERVIEW_ID, icon.getBitmap()); + } + Icon transparentIcon = IconFactory.recreate(IconFactory.ICON_MARKERVIEW_ID, + IconFactory.ICON_MARKERVIEW_BITMAP); + if (markerViewManager != null) { + markerViewManager.updateIcon(this); + } + super.setIcon(transparentIcon); + } + + /** + * Sets the location of the marker. + * + * @param position A {@link LatLng} defining the marker position. + */ + @Override + public void setPosition(LatLng position) { + super.setPosition(position); + if (markerViewManager != null) { + markerViewManager.update(); + } + } + + /** + * Determine if the {@link MarkerView} is selected or not. + * + * @return True if the MarkerView's selected, else false. + */ + public boolean isSelected() { + return selected; + } + + /** + * For internal use only, use {@link MapboxMap#selectMarker(Marker)} instead. + */ + void setSelected(boolean selected) { + this.selected = selected; + } + + /** + * Get the icon of the MarkerView. + * + * @return the icon use as Marker image. + */ + @Override + public Icon getIcon() { + return markerViewIcon; + } + + /** + * Set the MapboxMap associated tot the MapView containing the MarkerView. + * <p> + * This method is used to instantiate the MarkerView and provide an instance of + * {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter} + * </p> + * <p> + * This method is used to notify that a MarkerView is no longer active by setting a null value. + * </p> + * + * @param mapboxMap the MapboxMap instances. + */ + @Override + public void setMapboxMap(MapboxMap mapboxMap) { + super.setMapboxMap(mapboxMap); + if (mapboxMap != null) { + if (isFlat()) { + // initial tilt value if MapboxMap is started with a tilt attribute + tiltValue = (float) mapboxMap.getCameraPosition().tilt; + } + + markerViewManager = mapboxMap.getMarkerViewManager(); + } + } + + /** + * Get the String representation of a MarkerView. + * + * @return the String representation. + */ + @Override + public String toString() { + return "MarkerView [position[" + getPosition() + "]]"; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java index 8989bb22d7..d953bfca0c 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java @@ -32,609 +32,610 @@ import java.util.Map; */ public class MarkerViewManager implements MapView.OnMapChangedListener { - private final ViewGroup markerViewContainer; - private final Map<MarkerView, View> markerViewMap = new HashMap<>(); - private final LongSparseArray<OnMarkerViewAddedListener> markerViewAddedListenerMap = new LongSparseArray<>(); - private final List<MapboxMap.MarkerViewAdapter> markerViewAdapters = new ArrayList<>(); - - // TODO refactor MapboxMap out for Projection and Transform - // Requires removing MapboxMap from Annotations by using Peer model from #6912 - private MapboxMap mapboxMap; - - private long viewMarkerBoundsUpdateTime; - private MapboxMap.OnMarkerViewClickListener onMarkerViewClickListener; - private boolean isWaitingForRenderInvoke; - - /** - * Creates an instance of MarkerViewManager. - * - * @param container the ViewGroup associated with the MarkerViewManager - */ - public MarkerViewManager(@NonNull ViewGroup container) { - this.markerViewContainer = container; - this.markerViewAdapters.add(new ImageMarkerViewAdapter(container.getContext())); + private final ViewGroup markerViewContainer; + private final Map<MarkerView, View> markerViewMap = new HashMap<>(); + private final LongSparseArray<OnMarkerViewAddedListener> markerViewAddedListenerMap = new LongSparseArray<>(); + private final List<MapboxMap.MarkerViewAdapter> markerViewAdapters = new ArrayList<>(); + + // TODO refactor MapboxMap out for Projection and Transform + // Requires removing MapboxMap from Annotations by using Peer model from #6912 + private MapboxMap mapboxMap; + + private long viewMarkerBoundsUpdateTime; + private MapboxMap.OnMarkerViewClickListener onMarkerViewClickListener; + private boolean isWaitingForRenderInvoke; + + /** + * Creates an instance of MarkerViewManager. + * + * @param container the ViewGroup associated with the MarkerViewManager + */ + public MarkerViewManager(@NonNull ViewGroup container) { + this.markerViewContainer = container; + this.markerViewAdapters.add(new ImageMarkerViewAdapter(container.getContext())); + } + + // TODO refactor MapboxMap out for Projection and Transform + // Requires removing MapboxMap from Annotations by using Peer model from #6912 + public void bind(MapboxMap mapboxMap) { + this.mapboxMap = mapboxMap; + } + + + @Override + public void onMapChanged(@MapView.MapChange int change) { + if (isWaitingForRenderInvoke && change == MapView.DID_FINISH_RENDERING_FRAME_FULLY_RENDERED) { + isWaitingForRenderInvoke = false; + invalidateViewMarkersInVisibleRegion(); } - - // TODO refactor MapboxMap out for Projection and Transform - // Requires removing MapboxMap from Annotations by using Peer model from #6912 - public void bind(MapboxMap mapboxMap) { - this.mapboxMap = mapboxMap; + } + + public void setWaitingForRenderInvoke(boolean waitingForRenderInvoke) { + isWaitingForRenderInvoke = waitingForRenderInvoke; + } + + /** + * Animate a MarkerView to a given rotation. + * <p> + * The {@link MarkerView} will be rotated from its current rotation to the given rotation. + * </p> + * + * @param marker the MarkerView to rotate. + * @param rotation the rotation value. + */ + public void animateRotation(@NonNull MarkerView marker, float rotation) { + View convertView = markerViewMap.get(marker); + if (convertView != null) { + AnimatorUtils.rotate(convertView, rotation); } - - - @Override - public void onMapChanged(@MapView.MapChange int change) { - if (isWaitingForRenderInvoke && change == MapView.DID_FINISH_RENDERING_FRAME_FULLY_RENDERED) { - isWaitingForRenderInvoke = false; - invalidateViewMarkersInVisibleRegion(); - } + } + + /** + * Animate a MarkerView with a given rotation. + * + * @param marker the MarkerView to rotate by. + * @param rotation the rotation by value, limited to 0 - 360 degrees. + */ + public void animateRotationBy(@NonNull MarkerView marker, float rotation) { + View convertView = markerViewMap.get(marker); + if (convertView != null) { + convertView.animate().cancel(); + // calculate new direction + float diff = rotation - convertView.getRotation(); + if (diff > 180.0f) { + diff -= 360.0f; + } else if (diff < -180.0f) { + diff += 360.f; + } + AnimatorUtils.rotateBy(convertView, diff); } - - public void setWaitingForRenderInvoke(boolean waitingForRenderInvoke) { - isWaitingForRenderInvoke = waitingForRenderInvoke; + } + + /** + * Animate a MarkerView to a given alpha value. + * <p> + * The {@link MarkerView} will be transformed from its current alpha value to the given value. + * </p> + * + * @param marker the MarkerView to change its alpha value. + * @param alpha the alpha value. + */ + public void animateAlpha(@NonNull MarkerView marker, float alpha) { + View convertView = markerViewMap.get(marker); + if (convertView != null) { + AnimatorUtils.alpha(convertView, alpha); } - - /** - * Animate a MarkerView to a given rotation. - * <p> - * The {@link MarkerView} will be rotated from its current rotation to the given rotation. - * </p> - * - * @param marker the MarkerView to rotate. - * @param rotation the rotation value. - */ - public void animateRotation(@NonNull MarkerView marker, float rotation) { - View convertView = markerViewMap.get(marker); - if (convertView != null) { - AnimatorUtils.rotate(convertView, rotation); - } + } + + /** + * Animate a MarkerVIew to be visible or invisible + * <p> + * The {@link MarkerView} will be made {@link View#VISIBLE} or {@link View#GONE}. + * </p> + * + * @param marker the MarkerView to change its visibility + * @param visible the flag indicating if MarkerView is visible + */ + public void animateVisible(@NonNull MarkerView marker, boolean visible) { + View convertView = markerViewMap.get(marker); + if (convertView != null) { + convertView.setVisibility(visible ? View.VISIBLE : View.GONE); } - - /** - * Animate a MarkerView with a given rotation. - * - * @param marker the MarkerView to rotate by. - * @param rotation the rotation by value, limited to 0 - 360 degrees. - */ - public void animateRotationBy(@NonNull MarkerView marker, float rotation) { - View convertView = markerViewMap.get(marker); - if (convertView != null) { - convertView.animate().cancel(); - // calculate new direction - float diff = rotation - convertView.getRotation(); - if (diff > 180.0f) { - diff -= 360.0f; - } else if (diff < -180.0f) { - diff += 360.f; + } + + /** + * Updates the position of MarkerViews currently found in the viewport. + * <p> + * The collection of {@link MarkerView} will be iterated and each item position will be updated. + * If an item is View state is not visible and its related flag is set to visible, the + * {@link MarkerView} will be animated to visible using alpha animation. + * </p> + */ + public void update() { + for (final MarkerView marker : markerViewMap.keySet()) { + final View convertView = markerViewMap.get(marker); + if (convertView != null) { + PointF point = mapboxMap.getProjection().toScreenLocation(marker.getPosition()); + if (marker.getOffsetX() == MapboxConstants.UNMEASURED) { + // ensure view is measured first + if (marker.getWidth() == 0) { + convertView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); + if (convertView.getMeasuredWidth() != 0) { + marker.setWidth(convertView.getMeasuredWidth()); + marker.setHeight(convertView.getMeasuredHeight()); } - AnimatorUtils.rotateBy(convertView, diff); + } + } + if (marker.getWidth() != 0) { + int x = (int) (marker.getAnchorU() * marker.getWidth()); + int y = (int) (marker.getAnchorV() * marker.getHeight()); + marker.setOffset(x, y); } - } - /** - * Animate a MarkerView to a given alpha value. - * <p> - * The {@link MarkerView} will be transformed from its current alpha value to the given value. - * </p> - * - * @param marker the MarkerView to change its alpha value. - * @param alpha the alpha value. - */ - public void animateAlpha(@NonNull MarkerView marker, float alpha) { - View convertView = markerViewMap.get(marker); - if (convertView != null) { - AnimatorUtils.alpha(convertView, alpha); + convertView.setX(point.x - marker.getOffsetX()); + convertView.setY(point.y - marker.getOffsetY()); + + // animate visibility + if (marker.isVisible() && convertView.getVisibility() == View.GONE) { + animateVisible(marker, true); } + } } - - /** - * Animate a MarkerVIew to be visible or invisible - * <p> - * The {@link MarkerView} will be made {@link View#VISIBLE} or {@link View#GONE}. - * </p> - * - * @param marker the MarkerView to change its visibility - * @param visible the flag indicating if MarkerView is visible - */ - public void animateVisible(@NonNull MarkerView marker, boolean visible) { - View convertView = markerViewMap.get(marker); + } + + /** + * Set tilt on every non flat MarkerView currently shown in the Viewport. + * + * @param tilt the tilt value. + */ + public void setTilt(float tilt) { + View convertView; + for (MarkerView markerView : markerViewMap.keySet()) { + if (markerView.isFlat()) { + convertView = markerViewMap.get(markerView); if (convertView != null) { - convertView.setVisibility(visible ? View.VISIBLE : View.GONE); + markerView.setTilt(tilt); + convertView.setRotationX(tilt); } + } } - - /** - * Updates the position of MarkerViews currently found in the viewport. - * <p> - * The collection of {@link MarkerView} will be iterated and each item position will be updated. - * If an item is View state is not visible and its related flag is set to visible, the - * {@link MarkerView} will be animated to visible using alpha animation. - * </p> - */ - public void update() { - for (final MarkerView marker : markerViewMap.keySet()) { - final View convertView = markerViewMap.get(marker); - if (convertView != null) { - PointF point = mapboxMap.getProjection().toScreenLocation(marker.getPosition()); - if (marker.getOffsetX() == MapboxConstants.UNMEASURED) { - // ensure view is measured first - if (marker.getWidth() == 0) { - convertView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); - if (convertView.getMeasuredWidth() != 0) { - marker.setWidth(convertView.getMeasuredWidth()); - marker.setHeight(convertView.getMeasuredHeight()); - } - } - } - if (marker.getWidth() != 0) { - int x = (int) (marker.getAnchorU() * marker.getWidth()); - int y = (int) (marker.getAnchorV() * marker.getHeight()); - marker.setOffset(x, y); - } - - convertView.setX(point.x - marker.getOffsetX()); - convertView.setY(point.y - marker.getOffsetY()); - - // animate visibility - if (marker.isVisible() && convertView.getVisibility() == View.GONE) { - animateVisible(marker, true); - } - } - } + } + + /** + * Update and invalidate the MarkerView icon. + * + * @param markerView the marker view to updates. + */ + public void updateIcon(@NonNull MarkerView markerView) { + View convertView = markerViewMap.get(markerView); + if (convertView != null && convertView instanceof ImageView) { + ((ImageView) convertView).setImageBitmap(markerView.getIcon().getBitmap()); } - - /** - * Set tilt on every non flat MarkerView currently shown in the Viewport. - * - * @param tilt the tilt value. - */ - public void setTilt(float tilt) { - View convertView; - for (MarkerView markerView : markerViewMap.keySet()) { - if (markerView.isFlat()) { - convertView = markerViewMap.get(markerView); - if (convertView != null) { - markerView.setTilt(tilt); - convertView.setRotationX(tilt); - } - } + } + + /** + * Animate a MarkerView to a deselected state. + * <p> + * The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onDeselect(MarkerView, View)} + * will be called to execute an animation. + * </p> + * + * @param marker the MarkerView to deselect. + */ + public void deselect(@NonNull MarkerView marker) { + deselect(marker, true); + } + + /** + * Animate a MarkerView to a deselected state. + * <p> + * The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onDeselect(MarkerView, View)} + * will be called to execute an animation. + * </p> + * + * @param marker the MarkerView to deselect. + * @param callbackToMap indicates if deselect marker must be called on MapboxMap. + */ + public void deselect(@NonNull MarkerView marker, boolean callbackToMap) { + final View convertView = markerViewMap.get(marker); + if (convertView != null) { + for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) { + if (adapter.getMarkerClass().equals(marker.getClass())) { + adapter.onDeselect(marker, convertView); } + } } - - /** - * Update and invalidate the MarkerView icon. - * - * @param markerView the marker view to updates. - */ - public void updateIcon(@NonNull MarkerView markerView) { - View convertView = markerViewMap.get(markerView); - if (convertView != null && convertView instanceof ImageView) { - ((ImageView) convertView).setImageBitmap(markerView.getIcon().getBitmap()); - } + if (callbackToMap) { + mapboxMap.deselectMarker(marker); } - - /** - * Animate a MarkerView to a deselected state. - * <p> - * The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onDeselect(MarkerView, View)} - * will be called to execute an animation. - * </p> - * - * @param marker the MarkerView to deselect. - */ - public void deselect(@NonNull MarkerView marker) { - deselect(marker, true); + marker.setSelected(false); + } + + /** + * Animate a MarkerView to a selected state. + * + * @param marker the MarkerView object to select. + */ + public void select(@NonNull MarkerView marker) { + select(marker, true); + } + + /** + * Animate a MarkerView to a selected state. + * + * @param marker the MarkerView object to select. + * @param callbackToMap indicates if select marker must be called on {@link MapboxMap}. + */ + public void select(@NonNull MarkerView marker, boolean callbackToMap) { + final View convertView = markerViewMap.get(marker); + for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) { + if (adapter.getMarkerClass().equals(marker.getClass())) { + select(marker, convertView, adapter, callbackToMap); + } } - - /** - * Animate a MarkerView to a deselected state. - * <p> - * The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onDeselect(MarkerView, View)} - * will be called to execute an animation. - * </p> - * - * @param marker the MarkerView to deselect. - * @param callbackToMap indicates if deselect marker must be called on MapboxMap. - */ - public void deselect(@NonNull MarkerView marker, boolean callbackToMap) { - final View convertView = markerViewMap.get(marker); - if (convertView != null) { - for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) { - if (adapter.getMarkerClass().equals(marker.getClass())) { - adapter.onDeselect(marker, convertView); - } - } - } + } + + /** + * Animate a MarkerView to a selected state. + * <p> + * The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onSelect(MarkerView, View, boolean)} + * will be called to execute an animation. + * </p> + * + * @param marker the MarkerView object to select. + * @param convertView the View presentation of the MarkerView. + * @param adapter the adapter used to adapt the marker to the convertView. + */ + public void select(@NonNull MarkerView marker, View convertView, MapboxMap.MarkerViewAdapter adapter) { + select(marker, convertView, adapter, true); + } + + + /** + * Animate a MarkerView to a selected state. + * <p> + * The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onSelect(MarkerView, View, boolean)} + * will be called to execute an animation. + * </p> + * + * @param marker the MarkerView object to select. + * @param convertView the View presentation of the MarkerView. + * @param adapter the adapter used to adapt the marker to the convertView. + * @param callbackToMap indicates if select marker must be called on MapboxMap. + */ + public void select(@NonNull MarkerView marker, View convertView, MapboxMap.MarkerViewAdapter adapter, + boolean callbackToMap) { + if (convertView != null) { + if (adapter.onSelect(marker, convertView, false)) { if (callbackToMap) { - mapboxMap.deselectMarker(marker); + mapboxMap.selectMarker(marker); } - marker.setSelected(false); + } + marker.setSelected(true); + convertView.bringToFront(); } - - /** - * Animate a MarkerView to a selected state. - * - * @param marker the MarkerView object to select. - */ - public void select(@NonNull MarkerView marker) { - select(marker, true); + } + + /** + * Get view representation from a MarkerView. If marker is not found in current viewport, + * {@code null} is returned. + * + * @param marker the marker to get the view. + * @return the Android SDK View object. + */ + @Nullable + public View getView(MarkerView marker) { + return markerViewMap.get(marker); + } + + /** + * Get the view adapter for a marker. + * + * @param markerView the marker to get the view adapter. + * @return the MarkerView adapter. + */ + @Nullable + public MapboxMap.MarkerViewAdapter getViewAdapter(MarkerView markerView) { + MapboxMap.MarkerViewAdapter adapter = null; + for (MapboxMap.MarkerViewAdapter a : markerViewAdapters) { + if (a.getMarkerClass().equals(markerView.getClass())) { + adapter = a; + } } - - /** - * Animate a MarkerView to a selected state. - * - * @param marker the MarkerView object to select. - * @param callbackToMap indicates if select marker must be called on {@link MapboxMap}. - */ - public void select(@NonNull MarkerView marker, boolean callbackToMap) { - final View convertView = markerViewMap.get(marker); - for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) { - if (adapter.getMarkerClass().equals(marker.getClass())) { - select(marker, convertView, adapter, callbackToMap); - } + return adapter; + } + + /** + * Remove a MarkerView from a map. + * <p> + * The {@link MarkerView} will be removed using an alpha animation and related {@link View} + * will be released to the android.support.v4.util.Pools.SimplePool from the related + * {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter}. It's possible to remove + * the {@link MarkerView} from the underlying collection if needed. + * </p> + * + * @param marker the MarkerView to remove. + */ + public void removeMarkerView(MarkerView marker) { + final View viewHolder = markerViewMap.get(marker); + if (viewHolder != null && marker != null) { + for (final MapboxMap.MarkerViewAdapter<?> adapter : markerViewAdapters) { + if (adapter.getMarkerClass().equals(marker.getClass())) { + if (adapter.prepareViewForReuse(marker, viewHolder)) { + // reset offset for reuse + marker.setOffset(MapboxConstants.UNMEASURED, MapboxConstants.UNMEASURED); + adapter.releaseView(viewHolder); + } } + } } - - /** - * Animate a MarkerView to a selected state. - * <p> - * The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onSelect(MarkerView, View, boolean)} - * will be called to execute an animation. - * </p> - * - * @param marker the MarkerView object to select. - * @param convertView the View presentation of the MarkerView. - * @param adapter the adapter used to adapt the marker to the convertView. - */ - public void select(@NonNull MarkerView marker, View convertView, MapboxMap.MarkerViewAdapter adapter) { - select(marker, convertView, adapter, true); + marker.setMapboxMap(null); + markerViewMap.remove(marker); + } + + /** + * Add a MarkerViewAdapter to the MarkerViewManager. + * <p> + * The provided MarkerViewAdapter must supply a generic subclass of MarkerView. + * </p> + * + * @param markerViewAdapter the MarkerViewAdapter to add. + */ + public void addMarkerViewAdapter(MapboxMap.MarkerViewAdapter markerViewAdapter) { + if (markerViewAdapter.getMarkerClass().equals(MarkerView.class)) { + throw new RuntimeException("Providing a custom MarkerViewAdapter requires subclassing MarkerView"); } - - /** - * Animate a MarkerView to a selected state. - * <p> - * The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onSelect(MarkerView, View, boolean)} - * will be called to execute an animation. - * </p> - * - * @param marker the MarkerView object to select. - * @param convertView the View presentation of the MarkerView. - * @param adapter the adapter used to adapt the marker to the convertView. - * @param callbackToMap indicates if select marker must be called on MapboxMap. - */ - public void select(@NonNull MarkerView marker, View convertView, MapboxMap.MarkerViewAdapter adapter, boolean callbackToMap) { - if (convertView != null) { - if (adapter.onSelect(marker, convertView, false)) { - if (callbackToMap) { - mapboxMap.selectMarker(marker); - } - } - marker.setSelected(true); - convertView.bringToFront(); - } + if (!markerViewAdapters.contains(markerViewAdapter)) { + markerViewAdapters.add(markerViewAdapter); + invalidateViewMarkersInVisibleRegion(); } - - /** - * Get view representation from a MarkerView. If marker is not found in current viewport, - * {@code null} is returned. - * - * @param marker the marker to get the view. - * @return the Android SDK View object. - */ - @Nullable - public View getView(MarkerView marker) { - return markerViewMap.get(marker); + } + + /** + * Get all MarkerViewAdapters associated with this MarkerViewManager. + * + * @return a List of MarkerViewAdapters. + */ + public List<MapboxMap.MarkerViewAdapter> getMarkerViewAdapters() { + return markerViewAdapters; + } + + /** + * Register a callback to be invoked when this view is clicked. + * + * @param listener the callback to be invoked. + */ + public void setOnMarkerViewClickListener(@Nullable MapboxMap.OnMarkerViewClickListener listener) { + onMarkerViewClickListener = listener; + } + + /** + * Schedule that ViewMarkers found in the viewport are invalidated. + * <p> + * This method is rate limited, and {@link #invalidateViewMarkersInVisibleRegion} will only be called + * once each 250 ms. + * </p> + */ + public void scheduleViewMarkerInvalidation() { + if (!markerViewAdapters.isEmpty()) { + long currentTime = SystemClock.elapsedRealtime(); + if (currentTime < viewMarkerBoundsUpdateTime) { + return; + } + invalidateViewMarkersInVisibleRegion(); + viewMarkerBoundsUpdateTime = currentTime + 250; } - - /** - * Get the view adapter for a marker. - * - * @param markerView the marker to get the view adapter. - * @return the MarkerView adapter. - */ - @Nullable - public MapboxMap.MarkerViewAdapter getViewAdapter(MarkerView markerView) { - MapboxMap.MarkerViewAdapter adapter = null; - for (MapboxMap.MarkerViewAdapter a : markerViewAdapters) { - if (a.getMarkerClass().equals(markerView.getClass())) { - adapter = a; - } + } + + /** + * Invalidate the ViewMarkers found in the viewport. + * <p> + * This method will remove any markers that aren't in the viewport anymore and will add new + * ones for each found Marker in the changed viewport. + * </p> + */ + public void invalidateViewMarkersInVisibleRegion() { + RectF mapViewRect = new RectF(0, 0, markerViewContainer.getWidth(), markerViewContainer.getHeight()); + List<MarkerView> markers = mapboxMap.getMarkerViewsInRect(mapViewRect); + View convertView; + + // remove old markers + Iterator<MarkerView> iterator = markerViewMap.keySet().iterator(); + while (iterator.hasNext()) { + MarkerView marker = iterator.next(); + if (!markers.contains(marker)) { + // remove marker + convertView = markerViewMap.get(marker); + for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) { + if (adapter.getMarkerClass().equals(marker.getClass())) { + adapter.prepareViewForReuse(marker, convertView); + adapter.releaseView(convertView); + marker.setMapboxMap(null); + iterator.remove(); + } } - return adapter; + } } - /** - * Remove a MarkerView from a map. - * <p> - * The {@link MarkerView} will be removed using an alpha animation and related {@link View} - * will be released to the android.support.v4.util.Pools.SimplePool from the related - * {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter}. It's possible to remove - * the {@link MarkerView} from the underlying collection if needed. - * </p> - * - * @param marker the MarkerView to remove. - */ - public void removeMarkerView(MarkerView marker) { - final View viewHolder = markerViewMap.get(marker); - if (viewHolder != null && marker != null) { - for (final MapboxMap.MarkerViewAdapter<?> adapter : markerViewAdapters) { - if (adapter.getMarkerClass().equals(marker.getClass())) { - if (adapter.prepareViewForReuse(marker, viewHolder)) { - // reset offset for reuse - marker.setOffset(MapboxConstants.UNMEASURED, MapboxConstants.UNMEASURED); - adapter.releaseView(viewHolder); - } + // introduce new markers + for (final MarkerView marker : markers) { + if (!markerViewMap.containsKey(marker)) { + for (final MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) { + if (adapter.getMarkerClass().equals(marker.getClass())) { + + // Inflate View + convertView = (View) adapter.getViewReusePool().acquire(); + final View adaptedView = adapter.getView(marker, convertView, markerViewContainer); + if (adaptedView != null) { + adaptedView.setRotationX(marker.getTilt()); + adaptedView.setRotation(marker.getRotation()); + adaptedView.setAlpha(marker.getAlpha()); + adaptedView.setVisibility(View.GONE); + + if (mapboxMap.getSelectedMarkers().contains(marker)) { + // if a marker to be shown was selected + // replay that animation with duration 0 + if (adapter.onSelect(marker, adaptedView, true)) { + mapboxMap.selectMarker(marker); } + } + + marker.setMapboxMap(mapboxMap); + markerViewMap.put(marker, adaptedView); + if (convertView == null) { + adaptedView.setVisibility(View.GONE); + markerViewContainer.addView(adaptedView); + } } - } - marker.setMapboxMap(null); - markerViewMap.remove(marker); - } - /** - * Add a MarkerViewAdapter to the MarkerViewManager. - * <p> - * The provided MarkerViewAdapter must supply a generic subclass of MarkerView. - * </p> - * - * @param markerViewAdapter the MarkerViewAdapter to add. - */ - public void addMarkerViewAdapter(MapboxMap.MarkerViewAdapter markerViewAdapter) { - if (markerViewAdapter.getMarkerClass().equals(MarkerView.class)) { - throw new RuntimeException("Providing a custom MarkerViewAdapter requires subclassing MarkerView"); - } - - if (!markerViewAdapters.contains(markerViewAdapter)) { - markerViewAdapters.add(markerViewAdapter); - invalidateViewMarkersInVisibleRegion(); + // notify listener is marker view is rendered + OnMarkerViewAddedListener onViewAddedListener = markerViewAddedListenerMap.get(marker.getId()); + if (onViewAddedListener != null) { + onViewAddedListener.onViewAdded(marker); + markerViewAddedListenerMap.remove(marker.getId()); + } + } } + } } - /** - * Get all MarkerViewAdapters associated with this MarkerViewManager. - * - * @return a List of MarkerViewAdapters. - */ - public List<MapboxMap.MarkerViewAdapter> getMarkerViewAdapters() { - return markerViewAdapters; + // clear map, don't keep references to MarkerView listeners that are not found in the bounds of the map. + markerViewAddedListenerMap.clear(); + + // trigger update to make newly added ViewMarker visible, + // these would only be updated when the map is moved. + update(); + } + + /** + * When the provided {@link MarkerView} is clicked on by a user, we check if a custom click + * event has been created and if not, display a {@link InfoWindow}. + * + * @param markerView that the click event occurred. + */ + public boolean onClickMarkerView(MarkerView markerView) { + boolean clickHandled = false; + + MapboxMap.MarkerViewAdapter adapter = getViewAdapter(markerView); + View view = getView(markerView); + if (adapter == null || view == null) { + // not a valid state + return true; } - /** - * Register a callback to be invoked when this view is clicked. - * - * @param listener the callback to be invoked. - */ - public void setOnMarkerViewClickListener(@Nullable MapboxMap.OnMarkerViewClickListener listener) { - onMarkerViewClickListener = listener; + if (onMarkerViewClickListener != null) { + clickHandled = onMarkerViewClickListener.onMarkerClick(markerView, view, adapter); } - /** - * Schedule that ViewMarkers found in the viewport are invalidated. - * <p> - * This method is rate limited, and {@link #invalidateViewMarkersInVisibleRegion} will only be called - * once each 250 ms. - * </p> - */ - public void scheduleViewMarkerInvalidation() { - if (!markerViewAdapters.isEmpty()) { - long currentTime = SystemClock.elapsedRealtime(); - if (currentTime < viewMarkerBoundsUpdateTime) { - return; - } - invalidateViewMarkersInVisibleRegion(); - viewMarkerBoundsUpdateTime = currentTime + 250; - } + if (!clickHandled) { + ensureInfoWindowOffset(markerView); + select(markerView, view, adapter); } - /** - * Invalidate the ViewMarkers found in the viewport. - * <p> - * This method will remove any markers that aren't in the viewport anymore and will add new - * ones for each found Marker in the changed viewport. - * </p> - */ - public void invalidateViewMarkersInVisibleRegion() { - RectF mapViewRect = new RectF(0, 0, markerViewContainer.getWidth(), markerViewContainer.getHeight()); - List<MarkerView> markers = mapboxMap.getMarkerViewsInRect(mapViewRect); - View convertView; - - // remove old markers - Iterator<MarkerView> iterator = markerViewMap.keySet().iterator(); - while (iterator.hasNext()) { - MarkerView marker = iterator.next(); - if (!markers.contains(marker)) { - // remove marker - convertView = markerViewMap.get(marker); - for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) { - if (adapter.getMarkerClass().equals(marker.getClass())) { - adapter.prepareViewForReuse(marker, convertView); - adapter.releaseView(convertView); - marker.setMapboxMap(null); - iterator.remove(); - } - } - } - } - - // introduce new markers - for (final MarkerView marker : markers) { - if (!markerViewMap.containsKey(marker)) { - for (final MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) { - if (adapter.getMarkerClass().equals(marker.getClass())) { - - // Inflate View - convertView = (View) adapter.getViewReusePool().acquire(); - final View adaptedView = adapter.getView(marker, convertView, markerViewContainer); - if (adaptedView != null) { - adaptedView.setRotationX(marker.getTilt()); - adaptedView.setRotation(marker.getRotation()); - adaptedView.setAlpha(marker.getAlpha()); - adaptedView.setVisibility(View.GONE); - - if (mapboxMap.getSelectedMarkers().contains(marker)) { - // if a marker to be shown was selected - // replay that animation with duration 0 - if (adapter.onSelect(marker, adaptedView, true)) { - mapboxMap.selectMarker(marker); - } - } - - marker.setMapboxMap(mapboxMap); - markerViewMap.put(marker, adaptedView); - if (convertView == null) { - adaptedView.setVisibility(View.GONE); - markerViewContainer.addView(adaptedView); - } - } - - // notify listener is marker view is rendered - OnMarkerViewAddedListener onViewAddedListener = markerViewAddedListenerMap.get(marker.getId()); - if (onViewAddedListener != null) { - onViewAddedListener.onViewAdded(marker); - markerViewAddedListenerMap.remove(marker.getId()); - } - } - } - } + return clickHandled; + } + + /** + * Handles the {@link MarkerView}'s info window offset. + * + * @param marker that we are ensuring info window offset. + */ + public void ensureInfoWindowOffset(MarkerView marker) { + View view = null; + if (markerViewMap.containsKey(marker)) { + view = markerViewMap.get(marker); + } else { + for (final MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) { + if (adapter.getMarkerClass().equals(marker.getClass())) { + View convertView = (View) adapter.getViewReusePool().acquire(); + view = adapter.getView(marker, convertView, markerViewContainer); + break; } - - // clear map, don't keep references to MarkerView listeners that are not found in the bounds of the map. - markerViewAddedListenerMap.clear(); - - // trigger update to make newly added ViewMarker visible, - // these would only be updated when the map is moved. - update(); + } } - /** - * When the provided {@link MarkerView} is clicked on by a user, we check if a custom click - * event has been created and if not, display a {@link InfoWindow}. - * - * @param markerView that the click event occurred. - */ - public boolean onClickMarkerView(MarkerView markerView) { - boolean clickHandled = false; - - MapboxMap.MarkerViewAdapter adapter = getViewAdapter(markerView); - View view = getView(markerView); - if (adapter == null || view == null) { - // not a valid state - return true; + if (view != null) { + if (marker.getWidth() == 0) { + if (view.getMeasuredWidth() == 0) { + //Ensure the marker's view is measured first + view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); } - - if (onMarkerViewClickListener != null) { - clickHandled = onMarkerViewClickListener.onMarkerClick(markerView, view, adapter); - } - - if (!clickHandled) { - ensureInfoWindowOffset(markerView); - select(markerView, view, adapter); - } - - return clickHandled; + marker.setWidth(view.getMeasuredWidth()); + marker.setHeight(view.getMeasuredHeight()); + } + + // update position on map + if (marker.getOffsetX() == MapboxConstants.UNMEASURED) { + int x = (int) (marker.getAnchorU() * marker.getWidth()); + int y = (int) (marker.getAnchorV() * marker.getHeight()); + marker.setOffset(x, y); + } + + // InfoWindow offset + int infoWindowOffsetX = (int) ((view.getMeasuredWidth() * marker.getInfoWindowAnchorU()) - marker.getOffsetX()); + int infoWindowOffsetY = (int) ((view.getMeasuredHeight() * marker.getInfoWindowAnchorV()) - marker.getOffsetY()); + marker.setTopOffsetPixels(infoWindowOffsetY); + marker.setRightOffsetPixels(infoWindowOffsetX); } + } - /** - * Handles the {@link MarkerView}'s info window offset. - * - * @param marker that we are ensuring info window offset. - */ - public void ensureInfoWindowOffset(MarkerView marker) { - View view = null; - if (markerViewMap.containsKey(marker)) { - view = markerViewMap.get(marker); - } else { - for (final MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) { - if (adapter.getMarkerClass().equals(marker.getClass())) { - View convertView = (View) adapter.getViewReusePool().acquire(); - view = adapter.getView(marker, convertView, markerViewContainer); - break; - } - } - } + public ViewGroup getMarkerViewContainer() { + return markerViewContainer; + } - if (view != null) { - if (marker.getWidth() == 0) { - if (view.getMeasuredWidth() == 0) { - //Ensure the marker's view is measured first - view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); - } - marker.setWidth(view.getMeasuredWidth()); - marker.setHeight(view.getMeasuredHeight()); - } + public void addOnMarkerViewAddedListener(MarkerView markerView, OnMarkerViewAddedListener onMarkerViewAddedListener) { + markerViewAddedListenerMap.put(markerView.getId(), onMarkerViewAddedListener); + } - // update position on map - if (marker.getOffsetX() == MapboxConstants.UNMEASURED) { - int x = (int) (marker.getAnchorU() * marker.getWidth()); - int y = (int) (marker.getAnchorV() * marker.getHeight()); - marker.setOffset(x, y); - } + /** + * Default MarkerViewAdapter used for base class of {@link MarkerView} to adapt a MarkerView to + * an ImageView. + */ + public static class ImageMarkerViewAdapter extends MapboxMap.MarkerViewAdapter<MarkerView> { - // InfoWindow offset - int infoWindowOffsetX = (int) ((view.getMeasuredWidth() * marker.getInfoWindowAnchorU()) - marker.getOffsetX()); - int infoWindowOffsetY = (int) ((view.getMeasuredHeight() * marker.getInfoWindowAnchorV()) - marker.getOffsetY()); - marker.setTopOffsetPixels(infoWindowOffsetY); - marker.setRightOffsetPixels(infoWindowOffsetX); - } - } + private LayoutInflater inflater; - public ViewGroup getMarkerViewContainer() { - return markerViewContainer; + public ImageMarkerViewAdapter(Context context) { + super(context); + inflater = LayoutInflater.from(context); } - public void addOnMarkerViewAddedListener(MarkerView markerView, OnMarkerViewAddedListener onMarkerViewAddedListener) { - markerViewAddedListenerMap.put(markerView.getId(), onMarkerViewAddedListener); + @Nullable + @Override + public View getView(@NonNull MarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) { + ViewHolder viewHolder; + if (convertView == null) { + viewHolder = new ViewHolder(); + convertView = inflater.inflate(R.layout.mapbox_view_image_marker, parent, false); + viewHolder.imageView = (ImageView) convertView.findViewById(R.id.image); + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } + viewHolder.imageView.setImageBitmap(marker.getIcon().getBitmap()); + return convertView; } - /** - * Default MarkerViewAdapter used for base class of {@link MarkerView} to adapt a MarkerView to - * an ImageView. - */ - public static class ImageMarkerViewAdapter extends MapboxMap.MarkerViewAdapter<MarkerView> { - - private LayoutInflater inflater; - - public ImageMarkerViewAdapter(Context context) { - super(context); - inflater = LayoutInflater.from(context); - } - - @Nullable - @Override - public View getView(@NonNull MarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) { - ViewHolder viewHolder; - if (convertView == null) { - viewHolder = new ViewHolder(); - convertView = inflater.inflate(R.layout.mapbox_view_image_marker, parent, false); - viewHolder.imageView = (ImageView) convertView.findViewById(R.id.image); - convertView.setTag(viewHolder); - } else { - viewHolder = (ViewHolder) convertView.getTag(); - } - viewHolder.imageView.setImageBitmap(marker.getIcon().getBitmap()); - return convertView; - } - - private static class ViewHolder { - ImageView imageView; - } + private static class ViewHolder { + ImageView imageView; } + } + + /** + * Interface definition invoked when the View of a MarkerView has been added to the map. + * <p> + * {@link MapboxMap#addMarker(BaseMarkerOptions)} + * and only when the related MarkerView is found in the viewport of the map. + * </p> + */ + public interface OnMarkerViewAddedListener { /** - * Interface definition invoked when the View of a MarkerView has been added to the map. - * <p> - * {@link MapboxMap#addMarker(BaseMarkerOptions)} - * and only when the related MarkerView is found in the viewport of the map. - * </p> + * Invoked when the View of a MarkerView has been added to the Map. + * + * @param markerView The MarkerView the View was added for */ - public interface OnMarkerViewAddedListener { - - /** - * Invoked when the View of a MarkerView has been added to the Map. - * - * @param markerView The MarkerView the View was added for - */ - void onViewAdded(@NonNull MarkerView markerView); - } + void onViewAdded(@NonNull MarkerView markerView); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java index 1a763a72a1..2d829537fc 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java @@ -15,146 +15,150 @@ import com.mapbox.mapboxsdk.geometry.LatLng; */ public class MarkerViewOptions extends BaseMarkerViewOptions<MarkerView, MarkerViewOptions> { - private MarkerView marker; + private MarkerView marker; - /** - * Defines default options for a MarkerView. Extend {@link BaseMarkerViewOptions} if you need - * more customization. - */ - public MarkerViewOptions() { - marker = new MarkerView(); - } + /** + * Defines default options for a MarkerView. Extend {@link BaseMarkerViewOptions} if you need + * more customization. + */ + public MarkerViewOptions() { + marker = new MarkerView(); + } - protected MarkerViewOptions(Parcel in) { - marker = new MarkerView(); - position((LatLng) in.readParcelable(LatLng.class.getClassLoader())); - snippet(in.readString()); - title(in.readString()); - flat(in.readByte() != 0); - anchor(in.readFloat(), in.readFloat()); - infoWindowAnchor(in.readFloat(), in.readFloat()); - rotation(in.readFloat()); - visible(in.readByte() != 0); - alpha(in.readFloat()); - if (in.readByte() != 0) { - // this means we have an icon - String iconId = in.readString(); - Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader()); - Icon icon = new Icon(iconId, iconBitmap); - icon(icon); - } + protected MarkerViewOptions(Parcel in) { + marker = new MarkerView(); + position((LatLng) in.readParcelable(LatLng.class.getClassLoader())); + snippet(in.readString()); + title(in.readString()); + flat(in.readByte() != 0); + anchor(in.readFloat(), in.readFloat()); + infoWindowAnchor(in.readFloat(), in.readFloat()); + rotation(in.readFloat()); + visible(in.readByte() != 0); + alpha(in.readFloat()); + if (in.readByte() != 0) { + // this means we have an icon + String iconId = in.readString(); + Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader()); + Icon icon = new Icon(iconId, iconBitmap); + icon(icon); } + } - /** - * Get the instance of the object for which this method was called. - * - * @return the object for which this method was called. - */ - @Override - public MarkerViewOptions getThis() { - return this; - } + /** + * Get the instance of the object for which this method was called. + * + * @return the object for which this method was called. + */ + @Override + public MarkerViewOptions getThis() { + return this; + } - /** - * Describe the kinds of special objects contained in this Parcelable's - * marshalled representation. - * - * @return integer 0. - */ - @Override - public int describeContents() { - return 0; - } + /** + * Describe the kinds of special objects contained in this Parcelable's + * marshalled representation. + * + * @return integer 0. + */ + @Override + public int describeContents() { + return 0; + } - /** - * Flatten this object in to a Parcel. - * - * @param out The Parcel in which the object should be written. - * @param flags Additional flags about how the object should be written. May be 0 or - * {@link #PARCELABLE_WRITE_RETURN_VALUE}. - */ - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeParcelable(getPosition(), flags); - out.writeString(getSnippet()); - out.writeString(getTitle()); - out.writeByte((byte) (isFlat() ? 1 : 0)); - out.writeFloat(getAnchorU()); - out.writeFloat(getAnchorV()); - out.writeFloat(getInfoWindowAnchorU()); - out.writeFloat(getInfoWindowAnchorV()); - out.writeFloat(getRotation()); - out.writeByte((byte) (isVisible() ? 1 : 0)); - out.writeFloat(alpha); - Icon icon = getIcon(); - out.writeByte((byte) (icon != null ? 1 : 0)); - if (icon != null) { - out.writeString(getIcon().getId()); - out.writeParcelable(getIcon().getBitmap(), flags); - } + /** + * Flatten this object in to a Parcel. + * + * @param out The Parcel in which the object should be written. + * @param flags Additional flags about how the object should be written. May be 0 or + * {@link #PARCELABLE_WRITE_RETURN_VALUE}. + */ + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeParcelable(getPosition(), flags); + out.writeString(getSnippet()); + out.writeString(getTitle()); + out.writeByte((byte) (isFlat() ? 1 : 0)); + out.writeFloat(getAnchorU()); + out.writeFloat(getAnchorV()); + out.writeFloat(getInfoWindowAnchorU()); + out.writeFloat(getInfoWindowAnchorV()); + out.writeFloat(getRotation()); + out.writeByte((byte) (isVisible() ? 1 : 0)); + out.writeFloat(alpha); + Icon icon = getIcon(); + out.writeByte((byte) (icon != null ? 1 : 0)); + if (icon != null) { + out.writeString(getIcon().getId()); + out.writeParcelable(getIcon().getBitmap(), flags); } + } - /** - * Get the {@link MarkerView}. - * - * @return {@link MarkerView}. - */ - @Override - public MarkerView getMarker() { - if (position == null) { - throw new InvalidMarkerPositionException(); - } - - marker.setPosition(position); - marker.setSnippet(snippet); - marker.setTitle(title); - marker.setIcon(icon); - marker.setFlat(flat); - marker.setAnchor(anchorU, anchorV); - marker.setInfoWindowAnchor(infoWindowAnchorU, infoWindowAnchorV); - marker.setRotation(rotation); - marker.setVisible(visible); - marker.setAlpha(alpha); - return marker; + /** + * Get the {@link MarkerView}. + * + * @return {@link MarkerView}. + */ + @Override + public MarkerView getMarker() { + if (position == null) { + throw new InvalidMarkerPositionException(); } - public static final Parcelable.Creator<MarkerViewOptions> CREATOR - = new Parcelable.Creator<MarkerViewOptions>() { - public MarkerViewOptions createFromParcel(Parcel in) { - return new MarkerViewOptions(in); - } + marker.setPosition(position); + marker.setSnippet(snippet); + marker.setTitle(title); + marker.setIcon(icon); + marker.setFlat(flat); + marker.setAnchor(anchorU, anchorV); + marker.setInfoWindowAnchor(infoWindowAnchorU, infoWindowAnchorV); + marker.setRotation(rotation); + marker.setVisible(visible); + marker.setAlpha(alpha); + return marker; + } - public MarkerViewOptions[] newArray(int size) { - return new MarkerViewOptions[size]; - } + public static final Parcelable.Creator<MarkerViewOptions> CREATOR = + new Parcelable.Creator<MarkerViewOptions>() { + public MarkerViewOptions createFromParcel(Parcel in) { + return new MarkerViewOptions(in); + } + + public MarkerViewOptions[] newArray(int size) { + return new MarkerViewOptions[size]; + } }; - /** - * Compares this {@link MarkerViewOptions} object with another {@link MarkerViewOptions} and - * determines if they match. - * - * @param o Another {@link MarkerViewOptions} to compare with this object. - * @return True if the {@link MarkerViewOptions} being passed in matches this - * {@link PolylineOptions} object. Else, false. - */ - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - MarkerViewOptions that = (MarkerViewOptions) o; - return marker != null ? marker.equals(that.marker) : that.marker == null; + /** + * Compares this {@link MarkerViewOptions} object with another {@link MarkerViewOptions} and + * determines if they match. + * + * @param object Another {@link MarkerViewOptions} to compare with this object. + * @return True if the {@link MarkerViewOptions} being passed in matches this + * {@link PolylineOptions} object. Else, false. + */ + @Override + public boolean equals(Object object) { + if (this == object) { + return true; } - - /** - * Gives an integer which can be used as the bucket number for storing elements of the set/map. - * This bucket number is the address of the element inside the set/map. There's no guarantee - * that this hash value will be consistent between different Java implementations, or even - * between different execution runs of the same program. - * - * @return integer value you can use for storing element. - */ - @Override - public int hashCode() { - return marker != null ? marker.hashCode() : 0; + if (object == null || getClass() != object.getClass()) { + return false; } + MarkerViewOptions that = (MarkerViewOptions) object; + return marker != null ? marker.equals(that.marker) : that.marker == null; + } + + /** + * Gives an integer which can be used as the bucket number for storing elements of the set/map. + * This bucket number is the address of the element inside the set/map. There's no guarantee + * that this hash value will be consistent between different Java implementations, or even + * between different execution runs of the same program. + * + * @return integer value you can use for storing element. + */ + @Override + public int hashCode() { + return marker != null ? marker.hashCode() : 0; + } } 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 index 78d21db2e9..2bd3c82786 100644 --- 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 @@ -10,62 +10,62 @@ import java.util.List; */ public abstract class MultiPoint extends Annotation { - private List<LatLng> points; - private float alpha = 1.0f; + private List<LatLng> points; + private float alpha = 1.0f; - protected MultiPoint() { - super(); - points = new ArrayList<>(); - } + protected MultiPoint() { + super(); + points = new ArrayList<>(); + } - /** - * Returns a copy of the points. - * - * @return A {@link List} of points. - */ - public List<LatLng> getPoints() { - return new ArrayList<>(points); - } + /** + * Returns a copy of the points. + * + * @return A {@link List} of points. + */ + 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 A {@link List} of {@link LatLng} points making up the polyline. - */ - public void setPoints(List<LatLng> points) { - this.points = new ArrayList<>(points); - update(); - } + /** + * 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 A {@link List} of {@link LatLng} points making up the polyline. + */ + public void setPoints(List<LatLng> points) { + this.points = new ArrayList<>(points); + update(); + } - /** - * Add a point to the polyline. - * - * @param point A {@link LatLng} point to be added. - */ - public void addPoint(LatLng point) { - points.add(point); - update(); - } + /** + * Add a point to the polyline. + * + * @param point A {@link LatLng} point to be added. + */ + public void addPoint(LatLng point) { + points.add(point); + update(); + } - /** - * Value between 0 and 1 defining the polyline alpha. - * - * @return float value between 0 and 1. - */ - public float getAlpha() { - return alpha; - } + /** + * Value between 0 and 1 defining the polyline alpha. + * + * @return float value between 0 and 1. + */ + public float getAlpha() { + return alpha; + } - /** - * Set this {@link MultiPoint}s alpha. - * - * @param alpha float value between 0 and 1. - */ - public void setAlpha(float alpha) { - this.alpha = alpha; - update(); - } + /** + * Set this {@link MultiPoint}s alpha. + * + * @param alpha float value between 0 and 1. + */ + public void setAlpha(float alpha) { + this.alpha = alpha; + update(); + } - abstract void update(); + abstract void update(); } 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 index a06938e3cb..7b9de86bc4 100644 --- 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 @@ -9,56 +9,56 @@ import com.mapbox.mapboxsdk.maps.MapboxMap; */ public final class Polygon extends MultiPoint { - private int fillColor = Color.BLACK; // default fillColor is black - private int strokeColor = Color.BLACK; // default strokeColor is black + private int fillColor = Color.BLACK; // default fillColor is black + private int strokeColor = Color.BLACK; // default strokeColor is black - Polygon() { - super(); - } + Polygon() { + super(); + } - /** - * Get the color of the fill region of the polygon. - * - * @return The color of the fill. - */ - public int getFillColor() { - return fillColor; - } + /** + * Get the color of the fill region of the polygon. + * + * @return The color of the fill. + */ + public int getFillColor() { + return fillColor; + } - /** - * Get the color fo the stroke of the polygon. - * - * @return The color of the stroke. - */ - public int getStrokeColor() { - return strokeColor; - } + /** + * Get the color fo the stroke of the polygon. + * + * @return The color of the stroke. + */ + public int getStrokeColor() { + return strokeColor; + } - /** - * Sets the color of the fill region of the polygon. - * - * @param color The color in ARGB format. - */ - public void setFillColor(int color) { - fillColor = color; - update(); - } + /** + * Sets the color of the fill region of the polygon. + * + * @param color The color in ARGB format. + */ + public void setFillColor(int color) { + fillColor = color; + update(); + } - /** - * Sets the color of the stroke of the polygon. - * - * @param color The color in ARGB format. - */ - public void setStrokeColor(int color) { - strokeColor = color; - update(); - } + /** + * Sets the color of the stroke of the polygon. + * + * @param color The color in ARGB format. + */ + public void setStrokeColor(int color) { + strokeColor = color; + update(); + } - @Override - void update() { - MapboxMap mapboxMap = getMapboxMap(); - if (mapboxMap != null) { - mapboxMap.updatePolygon(this); - } + @Override + void update() { + MapboxMap mapboxMap = getMapboxMap(); + if (mapboxMap != null) { + mapboxMap.updatePolygon(this); } + } } 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 index 53a4e0995b..22f1258fc7 100644 --- 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 @@ -14,210 +14,220 @@ 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]; - } + 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()); - } - - /** - * Describe the kinds of special objects contained in this Parcelable's - * marshalled representation. - * - * @return integer 0. - */ - @Override - public int describeContents() { - return 0; - } - - /** - * Flatten this object in to a Parcel. - * - * @param out The Parcel in which the object should be written. - * @param flags Additional flags about how the object should be written. May be 0 or - * {@link #PARCELABLE_WRITE_RETURN_VALUE}. - */ - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeList(getPoints()); - out.writeFloat(getAlpha()); - out.writeInt(getFillColor()); - out.writeInt(getStrokeColor()); - } - - private Polygon polygon; - - /** - * Defines options for a polygon. - */ - public PolygonOptions() { - polygon = new Polygon(); - } - - /** - * Adds a vertex to the outline of the polygon being built. - * - * @param point {@link LatLng} point to be added to polygon geometry. - * @return This {@link PolygonOptions} object with the given point added to the outline. - */ - public PolygonOptions add(LatLng point) { - polygon.addPoint(point); - return this; - } - - /** - * Adds vertices to the outline of the polygon being built. - * - * @param points {@link LatLng} points to be added to polygon geometry. - * @return This {@link PolygonOptions} object with the given points added to the outline. - */ - public PolygonOptions add(LatLng... points) { - for (LatLng point : points) { - add(point); - } - return this; - } - - /** - * Adds vertices to the outline of the polygon being built. - * - * @param points {@link Iterable} list made up of {@link LatLng} points defining the polygon - * geometry - * @return This {@link PolygonOptions} object with the given points added to the outline. - */ - public PolygonOptions addAll(Iterable<LatLng> points) { - for (LatLng point : points) { - add(point); - } - return this; - } - - /** - * Set the alpha value of the polyline. - * - * @param alpha float value between 0 (not visible) and 1. - * @return This {@link PolygonOptions} object with the given polygon alpha value. - */ - public PolygonOptions alpha(float alpha) { - polygon.setAlpha(alpha); - return this; - } - - /** - * Gets the alpha set for this {@link PolygonOptions} object. - * - * @return float value between 0 and 1 defining the alpha. - */ - public float getAlpha() { - return polygon.getAlpha(); - } - - /** - * Specifies the polygon's fill color, as 32-bit ARGB. The default color is black. - * - * @param color 32-bit ARGB color. - * @return This {@link PolylineOptions} object with a new color set. - */ - public PolygonOptions fillColor(int color) { - polygon.setFillColor(color); - return this; - } - - /** - * Gets the fill color set for this {@link PolygonOptions} object. - * - * @return The fill color of the polygon in ARGB format. - */ - public int getFillColor() { - return polygon.getFillColor(); - } - - /** - * Do not use this method. Used internally by the SDK. - * - * @return Polygon the Polygon to return - */ - public Polygon getPolygon() { - return polygon; - } - - /** - * Specifies the polygon's stroke color, as 32-bit ARGB. The default color is black. - * - * @param color 32-bit ARGB color. - * @return This {@link PolygonOptions} object with a new stroke color set. - */ - public PolygonOptions strokeColor(int color) { - polygon.setStrokeColor(color); - return this; - } - - /** - * Gets the stroke color set for this {@link PolygonOptions} object. - * - * @return The stroke color of the polygon in ARGB format. - */ - 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(); - } - - /** - * Compares this {@link PolygonOptions} object with another {@link PolygonOptions} and - * determines if their color, alpha, stroke color, and vertices match. - * - * @param o Another {@link PolygonOptions} to compare with this object. - * @return True if color, alpha, stroke color, and vertices match this {@link PolygonOptions} - * object. Else, false. - */ - @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); - } - - /** - * Gives an integer which can be used as the bucket number for storing elements of the set/map. - * This bucket number is the address of the element inside the set/map. There's no guarantee - * that this hash value will be consistent between different Java implementations, or even - * between different execution runs of the same program. - * - * @return integer value you can use for storing element. - */ - @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; - } + 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()); + } + + /** + * Describe the kinds of special objects contained in this Parcelable's + * marshalled representation. + * + * @return integer 0. + */ + @Override + public int describeContents() { + return 0; + } + + /** + * Flatten this object in to a Parcel. + * + * @param out The Parcel in which the object should be written. + * @param flags Additional flags about how the object should be written. May be 0 or + * {@link #PARCELABLE_WRITE_RETURN_VALUE}. + */ + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeList(getPoints()); + out.writeFloat(getAlpha()); + out.writeInt(getFillColor()); + out.writeInt(getStrokeColor()); + } + + private Polygon polygon; + + /** + * Defines options for a polygon. + */ + public PolygonOptions() { + polygon = new Polygon(); + } + + /** + * Adds a vertex to the outline of the polygon being built. + * + * @param point {@link LatLng} point to be added to polygon geometry. + * @return This {@link PolygonOptions} object with the given point added to the outline. + */ + public PolygonOptions add(LatLng point) { + polygon.addPoint(point); + return this; + } + + /** + * Adds vertices to the outline of the polygon being built. + * + * @param points {@link LatLng} points to be added to polygon geometry. + * @return This {@link PolygonOptions} object with the given points added to the outline. + */ + public PolygonOptions add(LatLng... points) { + for (LatLng point : points) { + add(point); + } + return this; + } + + /** + * Adds vertices to the outline of the polygon being built. + * + * @param points {@link Iterable} list made up of {@link LatLng} points defining the polygon + * geometry + * @return This {@link PolygonOptions} object with the given points added to the outline. + */ + public PolygonOptions addAll(Iterable<LatLng> points) { + for (LatLng point : points) { + add(point); + } + return this; + } + + /** + * Set the alpha value of the polyline. + * + * @param alpha float value between 0 (not visible) and 1. + * @return This {@link PolygonOptions} object with the given polygon alpha value. + */ + public PolygonOptions alpha(float alpha) { + polygon.setAlpha(alpha); + return this; + } + + /** + * Gets the alpha set for this {@link PolygonOptions} object. + * + * @return float value between 0 and 1 defining the alpha. + */ + public float getAlpha() { + return polygon.getAlpha(); + } + + /** + * Specifies the polygon's fill color, as 32-bit ARGB. The default color is black. + * + * @param color 32-bit ARGB color. + * @return This {@link PolylineOptions} object with a new color set. + */ + public PolygonOptions fillColor(int color) { + polygon.setFillColor(color); + return this; + } + + /** + * Gets the fill color set for this {@link PolygonOptions} object. + * + * @return The fill color of the polygon in ARGB format. + */ + public int getFillColor() { + return polygon.getFillColor(); + } + + /** + * Do not use this method. Used internally by the SDK. + * + * @return Polygon the Polygon to return + */ + public Polygon getPolygon() { + return polygon; + } + + /** + * Specifies the polygon's stroke color, as 32-bit ARGB. The default color is black. + * + * @param color 32-bit ARGB color. + * @return This {@link PolygonOptions} object with a new stroke color set. + */ + public PolygonOptions strokeColor(int color) { + polygon.setStrokeColor(color); + return this; + } + + /** + * Gets the stroke color set for this {@link PolygonOptions} object. + * + * @return The stroke color of the polygon in ARGB format. + */ + 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(); + } + + /** + * Compares this {@link PolygonOptions} object with another {@link PolygonOptions} and + * determines if their color, alpha, stroke color, and vertices match. + * + * @param o Another {@link PolygonOptions} to compare with this object. + * @return True if color, alpha, stroke color, and vertices match this {@link PolygonOptions} + * object. Else, false. + */ + @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); + } + + /** + * Gives an integer which can be used as the bucket number for storing elements of the set/map. + * This bucket number is the address of the element inside the set/map. There's no guarantee + * that this hash value will be consistent between different Java implementations, or even + * between different execution runs of the same program. + * + * @return integer value you can use for storing element. + */ + @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 index 49d8d5d6e8..a430d11009 100644 --- 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 @@ -9,56 +9,56 @@ import com.mapbox.mapboxsdk.maps.MapboxMap; */ 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) + private int color = Color.BLACK; // default color is black + private float width = 10; // As specified by Google API Docs (in pixels) - Polyline() { - super(); - } + Polyline() { + super(); + } - /** - * Gets the color of this polyline. - * - * @return The color in ARGB format. - */ - public int getColor() { - return color; - } + /** + * Gets the color of this polyline. + * + * @return The color in ARGB format. + */ + public int getColor() { + return color; + } - /** - * Gets the width of this polyline. - * - * @return The width in screen pixels. - */ - public float getWidth() { - return width; - } + /** + * Gets the width of this polyline. + * + * @return The width in screen pixels. + */ + public float getWidth() { + return width; + } - /** - * Sets the color of the polyline. - * - * @param color - the color in ARGB format - */ - public void setColor(int color) { - this.color = color; - update(); - } + /** + * Sets the color of the polyline. + * + * @param color - the color in ARGB format + */ + public void setColor(int color) { + this.color = color; + update(); + } - /** - * Sets the width of the polyline. - * - * @param width in pixels - */ - public void setWidth(float width) { - this.width = width; - update(); - } + /** + * Sets the width of the polyline. + * + * @param width in pixels + */ + public void setWidth(float width) { + this.width = width; + update(); + } - @Override - void update() { - MapboxMap mapboxMap = getMapboxMap(); - if (mapboxMap != null) { - mapboxMap.updatePolyline(this); - } + @Override + void update() { + MapboxMap mapboxMap = getMapboxMap(); + if (mapboxMap != null) { + mapboxMap.updatePolyline(this); } + } } 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 index c74f6d196f..ab22109a4e 100644 --- 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 @@ -14,215 +14,225 @@ 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]; - } + 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()); - } - - /** - * Describe the kinds of special objects contained in this Parcelable's - * marshalled representation. - * - * @return integer 0. - */ - @Override - public int describeContents() { - return 0; - } - - /** - * Flatten this object in to a Parcel. - * - * @param out The Parcel in which the object should be written. - * @param flags Additional flags about how the object should be written. May be 0 or - * {@link #PARCELABLE_WRITE_RETURN_VALUE}. - */ - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeList(getPoints()); - out.writeFloat(getAlpha()); - out.writeInt(getColor()); - out.writeFloat(getWidth()); - } - - private Polyline polyline; - - /** - * Defines options for a polyline. - */ - public PolylineOptions() { - polyline = new Polyline(); - } - - /** - * Adds a vertex to the end of the polyline being built. - * - * @param point {@link LatLng} point to be added to polyline geometry. - * @return This {@link PolylineOptions} object with the given point on the end. - */ - public PolylineOptions add(LatLng point) { - polyline.addPoint(point); - return this; - } - - /** - * Adds vertices to the end of the polyline being built. - * - * @param points {@link LatLng} points defining the polyline geometry. - * @return This {@link PolylineOptions} object with the given point on the end. - */ - public PolylineOptions add(LatLng... points) { - for (LatLng point : points) { - add(point); - } - return this; - } - - /** - * Adds vertices to the end of the polyline being built. - * - * @param points {@link Iterable} list made up of {@link LatLng} points defining the polyline - * geometry - * @return This {@link PolylineOptions} object with the given points on the end. - */ - public PolylineOptions addAll(Iterable<LatLng> points) { - for (LatLng point : points) { - add(point); - } - return this; - } - - /** - * Set the alpha value of the polyline. - * - * @param alpha float value between 0 (not visible) and 1. - * @return This {@link PolylineOptions} object with the given polyline alpha value. - */ - public PolylineOptions alpha(float alpha) { - polyline.setAlpha(alpha); - return this; - } - - /** - * Gets the alpha set for this {@link PolylineOptions} object. - * - * @return float value between 0 and 1 defining the alpha. - */ - public float getAlpha() { - return polyline.getAlpha(); - } - - /** - * Sets the color of the polyline as a 32-bit ARGB color. The default color is black. - * - * @param color 32-bit ARGB color. - * @return This {@link PolylineOptions} object with a new color set. - */ - public PolylineOptions color(int color) { - polyline.setColor(color); - return this; - } - - /** - * Gets the color set for this {@link PolylineOptions} object. - * - * @return The color of the polyline in ARGB format. - */ - public int getColor() { - return polyline.getColor(); - } - - /** - * Do not use this method. Used internally by the SDK. - * - * @return PolyLine The polyline build by this class. - */ - public Polyline getPolyline() { - return polyline; - } - - /** - * Gets the width set for this {@link PolylineOptions} object. - * - * @return The width of the polyline in screen pixels. - */ - public float getWidth() { - return polyline.getWidth(); - } - - /** - * Sets the width of the polyline in screen pixels. The default is 10. - * - * @param width float value defining width of polyline using unit pixels. - * @return This {@link PolylineOptions} object with a new width set. - */ - public PolylineOptions width(float width) { - polyline.setWidth(width); - return this; - } - - /** - * Gets the points set for this {@link PolylineOptions} object. - * - * @return a {@link List} of {@link LatLng}s specifying the vertices of the polyline. - */ - public List<LatLng> getPoints() { - // the getter gives us a copy, which is the safe thing to do... - return polyline.getPoints(); - } - - /** - * Compares this {@link PolylineOptions} object with another {@link PolylineOptions} and - * determines if their color, alpha, width, and vertices match. - * - * @param o Another {@link PolylineOptions} to compare with this object. - * @return True if color, alpha, width, and vertices match this {@link PolylineOptions} object. - * Else, false. - */ - @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); - } - - /** - * Gives an integer which can be used as the bucket number for storing elements of the set/map. - * This bucket number is the address of the element inside the set/map. There's no guarantee - * that this hash value will be consistent between different Java implementations, or even - * between different execution runs of the same program. - * - * @return integer value you can use for storing element. - */ - @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; - } + 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()); + } + + /** + * Describe the kinds of special objects contained in this Parcelable's + * marshalled representation. + * + * @return integer 0. + */ + @Override + public int describeContents() { + return 0; + } + + /** + * Flatten this object in to a Parcel. + * + * @param out The Parcel in which the object should be written. + * @param flags Additional flags about how the object should be written. May be 0 or + * {@link #PARCELABLE_WRITE_RETURN_VALUE}. + */ + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeList(getPoints()); + out.writeFloat(getAlpha()); + out.writeInt(getColor()); + out.writeFloat(getWidth()); + } + + private Polyline polyline; + + /** + * Defines options for a polyline. + */ + public PolylineOptions() { + polyline = new Polyline(); + } + + /** + * Adds a vertex to the end of the polyline being built. + * + * @param point {@link LatLng} point to be added to polyline geometry. + * @return This {@link PolylineOptions} object with the given point on the end. + */ + public PolylineOptions add(LatLng point) { + polyline.addPoint(point); + return this; + } + + /** + * Adds vertices to the end of the polyline being built. + * + * @param points {@link LatLng} points defining the polyline geometry. + * @return This {@link PolylineOptions} object with the given point on the end. + */ + public PolylineOptions add(LatLng... points) { + for (LatLng point : points) { + add(point); + } + return this; + } + + /** + * Adds vertices to the end of the polyline being built. + * + * @param points {@link Iterable} list made up of {@link LatLng} points defining the polyline + * geometry + * @return This {@link PolylineOptions} object with the given points on the end. + */ + public PolylineOptions addAll(Iterable<LatLng> points) { + for (LatLng point : points) { + add(point); + } + return this; + } + + /** + * Set the alpha value of the polyline. + * + * @param alpha float value between 0 (not visible) and 1. + * @return This {@link PolylineOptions} object with the given polyline alpha value. + */ + public PolylineOptions alpha(float alpha) { + polyline.setAlpha(alpha); + return this; + } + + /** + * Gets the alpha set for this {@link PolylineOptions} object. + * + * @return float value between 0 and 1 defining the alpha. + */ + public float getAlpha() { + return polyline.getAlpha(); + } + + /** + * Sets the color of the polyline as a 32-bit ARGB color. The default color is black. + * + * @param color 32-bit ARGB color. + * @return This {@link PolylineOptions} object with a new color set. + */ + public PolylineOptions color(int color) { + polyline.setColor(color); + return this; + } + + /** + * Gets the color set for this {@link PolylineOptions} object. + * + * @return The color of the polyline in ARGB format. + */ + public int getColor() { + return polyline.getColor(); + } + + /** + * Do not use this method. Used internally by the SDK. + * + * @return PolyLine The polyline build by this class. + */ + public Polyline getPolyline() { + return polyline; + } + + /** + * Gets the width set for this {@link PolylineOptions} object. + * + * @return The width of the polyline in screen pixels. + */ + public float getWidth() { + return polyline.getWidth(); + } + + /** + * Sets the width of the polyline in screen pixels. The default is 10. + * + * @param width float value defining width of polyline using unit pixels. + * @return This {@link PolylineOptions} object with a new width set. + */ + public PolylineOptions width(float width) { + polyline.setWidth(width); + return this; + } + + /** + * Gets the points set for this {@link PolylineOptions} object. + * + * @return a {@link List} of {@link LatLng}s specifying the vertices of the polyline. + */ + public List<LatLng> getPoints() { + // the getter gives us a copy, which is the safe thing to do... + return polyline.getPoints(); + } + + /** + * Compares this {@link PolylineOptions} object with another {@link PolylineOptions} and + * determines if their color, alpha, width, and vertices match. + * + * @param o Another {@link PolylineOptions} to compare with this object. + * @return True if color, alpha, width, and vertices match this {@link PolylineOptions} object. + * Else, false. + */ + @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); + } + + /** + * Gives an integer which can be used as the bucket number for storing elements of the set/map. + * This bucket number is the address of the element inside the set/map. There's no guarantee + * that this hash value will be consistent between different Java implementations, or even + * between different execution runs of the same program. + * + * @return integer value you can use for storing element. + */ + @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/camera/CameraPosition.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java index 40e447debe..79045b68bb 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java @@ -16,304 +16,304 @@ import static com.mapbox.mapboxsdk.utils.MathUtils.convertNativeBearing; */ public final class CameraPosition implements Parcelable { - public static final CameraPosition DEFAULT = new CameraPosition(new LatLng(), 0, 0, 0); - - public static final Parcelable.Creator<CameraPosition> CREATOR - = new Parcelable.Creator<CameraPosition>() { - public CameraPosition createFromParcel(Parcel in) { - double bearing = in.readDouble(); - LatLng target = in.readParcelable(LatLng.class.getClassLoader()); - double tilt = in.readDouble(); - double zoom = in.readDouble(); - return new CameraPosition(target, zoom, tilt, bearing); - } - - public CameraPosition[] newArray(int size) { - return new CameraPosition[size]; - } + public static final CameraPosition DEFAULT = new CameraPosition(new LatLng(), 0, 0, 0); + + public static final Parcelable.Creator<CameraPosition> CREATOR = + new Parcelable.Creator<CameraPosition>() { + public CameraPosition createFromParcel(Parcel in) { + double bearing = in.readDouble(); + LatLng target = in.readParcelable(LatLng.class.getClassLoader()); + double tilt = in.readDouble(); + double zoom = in.readDouble(); + return new CameraPosition(target, zoom, tilt, bearing); + } + + public CameraPosition[] newArray(int size) { + return new CameraPosition[size]; + } }; + /** + * Direction that the camera is pointing in, in degrees clockwise from north. + */ + public final double bearing; + + /** + * The location that the camera is pointing at. + */ + public final LatLng target; + + /** + * The angle, in degrees, of the camera angle from the nadir (directly facing the Earth). + * See tilt(float) for details of restrictions on the range of values. + */ + public final double tilt; + + /** + * Zoom level near the center of the screen. See zoom(float) for the definition of the camera's + * zoom level. + */ + public final double zoom; + + /** + * Constructs a CameraPosition. + * + * @param target The target location to align with the center of the screen. + * @param zoom Zoom level at target. See zoom(float) for details of restrictions. + * @param tilt The camera angle, in degrees, from the nadir (directly down). See tilt(float) + * for details of restrictions. + * @param bearing Direction that the camera is pointing in, in degrees clockwise from north. + * This value will be normalized to be within 0 degrees inclusive and 360 degrees + * exclusive. + * @throws NullPointerException if target is null + * @throws IllegalArgumentException if tilt is outside the range of 0 to 90 degrees inclusive. + */ + CameraPosition(LatLng target, double zoom, double tilt, double bearing) { + this.target = target; + this.bearing = bearing; + this.tilt = tilt; + this.zoom = zoom; + } + + /** + * Describe the kinds of special objects contained in this Parcelable's + * marshalled representation. + * + * @return integer 0. + */ + @Override + public int describeContents() { + return 0; + } + + /** + * Flatten this object in to a Parcel. + * + * @param out The Parcel in which the object should be written. + * @param flags Additional flags about how the object should be written. May be 0 or + * {@link #PARCELABLE_WRITE_RETURN_VALUE}. + */ + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeDouble(bearing); + out.writeParcelable(target, flags); + out.writeDouble(tilt); + out.writeDouble(zoom); + } + + /** + * Returns a String with the camera target, zoom, bearing and tilt. + * + * @return A String with CameraPosition information. + */ + @Override + public String toString() { + return "Target: " + target + ", Zoom:" + zoom + ", Bearing:" + bearing + ", Tilt:" + tilt; + } + + /** + * Compares this {@link CameraPosition} object with another {@link CameraPosition} and + * determines if their target, zoom, tilt, and bearing match. + * + * @param o Another {@link CameraPosition} to compare with this object. + * @return True if target, zoom, tilt, and bearing match this {@link CameraPosition} object. + * Else, false. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + CameraPosition cameraPosition = (CameraPosition) o; + if (target != null && !target.equals(cameraPosition.target)) { + return false; + } else if (zoom != cameraPosition.zoom) { + return false; + } else if (tilt != cameraPosition.tilt) { + return false; + } else if (bearing != cameraPosition.bearing) { + return false; + } + return true; + } + + /** + * Gives an integer which can be used as the bucket number for storing elements of the set/map. + * This bucket number is the address of the element inside the set/map. There's no guarantee + * that this hash value will be consistent between different Java implementations, or even + * between different execution runs of the same program. + * + * @return integer value you can use for storing element. + */ + @Override + public int hashCode() { + int result = 1; + result = 31 * result + (target != null ? target.hashCode() : 0); + return result; + } + + /** + * Builder for composing {@link CameraPosition} objects. + */ + public static final class Builder { + + private double bearing = -1; + private LatLng target = null; + private double tilt = -1; + private double zoom = -1; + /** - * Direction that the camera is pointing in, in degrees clockwise from north. + * Creates an empty builder. */ - public final double bearing; + public Builder() { + super(); + } /** - * The location that the camera is pointing at. + * Create Builder with an existing CameraPosition data. + * + * @param previous Existing CameraPosition values to use */ - public final LatLng target; + public Builder(CameraPosition previous) { + super(); + if (previous != null) { + this.bearing = previous.bearing; + this.target = previous.target; + this.tilt = previous.tilt; + this.zoom = previous.zoom; + } + } /** - * The angle, in degrees, of the camera angle from the nadir (directly facing the Earth). - * See tilt(float) for details of restrictions on the range of values. + * Create Builder with an existing CameraPosition data. + * + * @param typedArray TypedArray containgin attribute values */ - public final double tilt; + public Builder(TypedArray typedArray) { + super(); + if (typedArray != null) { + this.bearing = typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraBearing, 0.0f); + double lat = typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraTargetLat, 0.0f); + double lng = typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraTargetLng, 0.0f); + this.target = new LatLng(lat, lng); + this.tilt = typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraTilt, 0.0f); + this.zoom = typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraZoom, 0.0f); + } + } /** - * Zoom level near the center of the screen. See zoom(float) for the definition of the camera's - * zoom level. + * Create Builder from an existing CameraPositionUpdate update. + * + * @param update Update containing camera options */ - public final double zoom; + public Builder(CameraUpdateFactory.CameraPositionUpdate update) { + super(); + if (update != null) { + bearing = update.getBearing(); + target = update.getTarget(); + tilt = update.getTilt(); + zoom = update.getZoom(); + } + } /** - * Constructs a CameraPosition. + * Create Builder from an existing CameraPositionUpdate update. * - * @param target The target location to align with the center of the screen. - * @param zoom Zoom level at target. See zoom(float) for details of restrictions. - * @param tilt The camera angle, in degrees, from the nadir (directly down). See tilt(float) - * for details of restrictions. - * @param bearing Direction that the camera is pointing in, in degrees clockwise from north. - * This value will be normalized to be within 0 degrees inclusive and 360 degrees - * exclusive. - * @throws NullPointerException if target is null - * @throws IllegalArgumentException if tilt is outside the range of 0 to 90 degrees inclusive. + * @param update Update containing camera options */ - CameraPosition(LatLng target, double zoom, double tilt, double bearing) { - this.target = target; - this.bearing = bearing; - this.tilt = tilt; - this.zoom = zoom; + public Builder(CameraUpdateFactory.ZoomUpdate update) { + super(); + if (update != null) { + this.zoom = update.getZoom(); + } } /** - * Describe the kinds of special objects contained in this Parcelable's - * marshalled representation. + * Create Builder from an existing array of doubles. + * <p> + * These values conform to map.ccp representation of a camera position. + * </p> * - * @return integer 0. + * @param nativeCameraValues Values containing target, bearing, tilt and zoom */ - @Override - public int describeContents() { - return 0; + public Builder(double[] nativeCameraValues) { + super(); + if (nativeCameraValues != null && nativeCameraValues.length == 5) { + target(new LatLng(nativeCameraValues[0], nativeCameraValues[1])); + bearing(convertNativeBearing(nativeCameraValues[2])); + tilt(nativeCameraValues[3]); + zoom(nativeCameraValues[4]); + } } /** - * Flatten this object in to a Parcel. + * Sets the direction that the camera is pointing in, in degrees clockwise from north. * - * @param out The Parcel in which the object should be written. - * @param flags Additional flags about how the object should be written. May be 0 or - * {@link #PARCELABLE_WRITE_RETURN_VALUE}. + * @param bearing Bearing + * @return Builder */ - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeDouble(bearing); - out.writeParcelable(target, flags); - out.writeDouble(tilt); - out.writeDouble(zoom); + public Builder bearing(double bearing) { + double direction = bearing; + + while (direction >= 360) { + direction -= 360; + } + while (direction < 0) { + direction += 360; + } + + this.bearing = direction; + return this; } /** - * Returns a String with the camera target, zoom, bearing and tilt. + * Builds a CameraPosition. * - * @return A String with CameraPosition information. + * @return CameraPosition */ - @Override - public String toString() { - return "Target: " + target + ", Zoom:" + zoom + ", Bearing:" + bearing + ", Tilt:" + tilt; + public CameraPosition build() { + return new CameraPosition(target, zoom, tilt, bearing); } /** - * Compares this {@link CameraPosition} object with another {@link CameraPosition} and - * determines if their target, zoom, tilt, and bearing match. + * Sets the location that the camera is pointing at. * - * @param o Another {@link CameraPosition} to compare with this object. - * @return True if target, zoom, tilt, and bearing match this {@link CameraPosition} object. - * Else, false. + * @param location Location + * @return Builder */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o == null || getClass() != o.getClass()) { - return false; - } - - CameraPosition cameraPosition = (CameraPosition) o; - if (target != null && !target.equals(cameraPosition.target)) { - return false; - } else if (zoom != cameraPosition.zoom) { - return false; - } else if (tilt != cameraPosition.tilt) { - return false; - } else if (bearing != cameraPosition.bearing) { - return false; - } - return true; + public Builder target(LatLng location) { + this.target = location; + return this; } /** - * Gives an integer which can be used as the bucket number for storing elements of the set/map. - * This bucket number is the address of the element inside the set/map. There's no guarantee - * that this hash value will be consistent between different Java implementations, or even - * between different execution runs of the same program. + * Set the tilt in degrees + * <p> + * value is clamped to 0 and 60. + * <p/> * - * @return integer value you can use for storing element. + * @param tilt Tilt value + * @return Builder */ - @Override - public int hashCode() { - int result = 1; - result = 31 * result + (target != null ? target.hashCode() : 0); - return result; + public Builder tilt(double tilt) { + this.tilt = MathUtils.clamp(tilt, MapboxConstants.MINIMUM_TILT, MapboxConstants.MAXIMUM_TILT); + return this; } /** - * Builder for composing {@link CameraPosition} objects. + * Set the zoom + * + * @param zoom Zoom value + * @return Builder */ - public static final class Builder { - - private double bearing = -1; - private LatLng target = null; - private double tilt = -1; - private double zoom = -1; - - /** - * Creates an empty builder. - */ - public Builder() { - super(); - } - - /** - * Create Builder with an existing CameraPosition data. - * - * @param previous Existing CameraPosition values to use - */ - public Builder(CameraPosition previous) { - super(); - if (previous != null) { - this.bearing = previous.bearing; - this.target = previous.target; - this.tilt = previous.tilt; - this.zoom = previous.zoom; - } - } - - /** - * Create Builder with an existing CameraPosition data. - * - * @param typedArray TypedArray containgin attribute values - */ - public Builder(TypedArray typedArray) { - super(); - if (typedArray != null) { - this.bearing = typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraBearing, 0.0f); - double lat = typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraTargetLat, 0.0f); - double lng = typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraTargetLng, 0.0f); - this.target = new LatLng(lat, lng); - this.tilt = typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraTilt, 0.0f); - this.zoom = typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraZoom, 0.0f); - } - } - - /** - * Create Builder from an existing CameraPositionUpdate update. - * - * @param update Update containing camera options - */ - public Builder(CameraUpdateFactory.CameraPositionUpdate update) { - super(); - if (update != null) { - bearing = update.getBearing(); - target = update.getTarget(); - tilt = update.getTilt(); - zoom = update.getZoom(); - } - } - - /** - * Create Builder from an existing CameraPositionUpdate update. - * - * @param update Update containing camera options - */ - public Builder(CameraUpdateFactory.ZoomUpdate update) { - super(); - if (update != null) { - this.zoom = update.getZoom(); - } - } - - /** - * Create Builder from an existing array of doubles. - * <p> - * These values conform to map.ccp representation of a camera position. - * </p> - * - * @param nativeCameraValues Values containing target, bearing, tilt and zoom - */ - public Builder(double[] nativeCameraValues) { - super(); - if (nativeCameraValues != null && nativeCameraValues.length == 5) { - target(new LatLng(nativeCameraValues[0], nativeCameraValues[1])); - bearing(convertNativeBearing(nativeCameraValues[2])); - tilt(nativeCameraValues[3]); - zoom(nativeCameraValues[4]); - } - } - - /** - * Sets the direction that the camera is pointing in, in degrees clockwise from north. - * - * @param bearing Bearing - * @return Builder - */ - public Builder bearing(double bearing) { - double direction = bearing; - - while (direction >= 360) { - direction -= 360; - } - while (direction < 0) { - direction += 360; - } - - this.bearing = direction; - return this; - } - - /** - * Builds a CameraPosition. - * - * @return CameraPosition - */ - public CameraPosition build() { - return new CameraPosition(target, zoom, tilt, bearing); - } - - /** - * Sets the location that the camera is pointing at. - * - * @param location Location - * @return Builder - */ - public Builder target(LatLng location) { - this.target = location; - return this; - } - - /** - * Set the tilt in degrees - * <p> - * value is clamped to 0 and 60. - * <p/> - * - * @param tilt Tilt value - * @return Builder - */ - public Builder tilt(double tilt) { - this.tilt = MathUtils.clamp(tilt, MapboxConstants.MINIMUM_TILT, MapboxConstants.MAXIMUM_TILT); - return this; - } - - /** - * Set the zoom - * - * @param zoom Zoom value - * @return Builder - */ - public Builder zoom(double zoom) { - this.zoom = zoom; - return this; - } + public Builder zoom(double zoom) { + this.zoom = zoom; + return this; } + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdate.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdate.java index 94ee4912ce..7e0dbf08fb 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdate.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdate.java @@ -9,6 +9,6 @@ import com.mapbox.mapboxsdk.maps.MapboxMap; */ public interface CameraUpdate { - CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap); + CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap); } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java index d568b9637d..aecc51530b 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java @@ -21,395 +21,397 @@ import java.lang.annotation.RetentionPolicy; */ public final class CameraUpdateFactory { - /** - * Returns a CameraUpdate that moves the camera to a specified CameraPosition. - * - * @param cameraPosition Camera Position to change to - * @return CameraUpdate Final Camera Position - */ - public static CameraUpdate newCameraPosition(@NonNull CameraPosition cameraPosition) { - return new CameraPositionUpdate(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt, cameraPosition.zoom); + /** + * Returns a CameraUpdate that moves the camera to a specified CameraPosition. + * + * @param cameraPosition Camera Position to change to + * @return CameraUpdate Final Camera Position + */ + public static CameraUpdate newCameraPosition(@NonNull CameraPosition cameraPosition) { + return new CameraPositionUpdate(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt, + cameraPosition.zoom); + } + + /** + * Returns a CameraUpdate that moves the center of the screen to a latitude and longitude + * specified by a LatLng object. This centers the camera on the LatLng object. + * + * @param latLng Target location to change to + * @return CameraUpdate Final Camera Position + */ + public static CameraUpdate newLatLng(@NonNull LatLng latLng) { + return new CameraPositionUpdate(-1, latLng, -1, -1); + } + + /** + * Returns a {@link CameraUpdate} that transforms the camera such that the specified + * latitude/longitude bounds are centered on screen at the greatest possible zoom level. + * You can specify padding, in order to inset the bounding box from the map view's edges. + * The returned CameraUpdate has a bearing of 0 and a tilt of 0. + * + * @param bounds Bounds to match Camera position with + * @param padding Padding added to the bounds + * @return CameraUpdate Final Camera Position + */ + public static CameraUpdate newLatLngBounds(@NonNull LatLngBounds bounds, int padding) { + return newLatLngBounds(bounds, padding, padding, padding, padding); + } + + /** + * Returns a {@link CameraUpdate} that transforms the camera such that the specified + * latitude/longitude bounds are centered on screen at the greatest possible zoom level. + * You can specify padding, in order to inset the bounding box from the map view's edges. + * The returned CameraUpdate has a bearing of 0 and a tilt of 0. + * + * @param bounds Bounds to base the Camera position out of + * @param paddingLeft Padding left of the bounds + * @param paddingTop Padding top of the bounds + * @param paddingRight Padding right of the bounds + * @param paddingBottom Padding bottom of the bounds + * @return CameraUpdate Final Camera Position + */ + public static CameraUpdate newLatLngBounds(@NonNull LatLngBounds bounds, int paddingLeft, int paddingTop, + int paddingRight, int paddingBottom) { + return new CameraBoundsUpdate(bounds, paddingLeft, paddingTop, paddingRight, paddingBottom); + } + + /** + * Returns a CameraUpdate that moves the center of the screen to a latitude and longitude + * specified by a LatLng object, and moves to the given zoom level. + * + * @param latLng Target location to change to + * @param zoom Zoom level to change to + * @return CameraUpdate Final Camera Position + */ + public static CameraUpdate newLatLngZoom(@NonNull LatLng latLng, double zoom) { + return new CameraPositionUpdate(-1, latLng, -1, zoom); + } + + /** + * Returns a CameraUpdate that scrolls the camera over the map, + * shifting the center of view by the specified number of pixels in the x and y directions. + * + * @param xPixel Amount of pixels to scroll to in x direction + * @param yPixel Amount of pixels to scroll to in y direction + * @return CameraUpdate Final Camera Position + */ + public static CameraUpdate scrollBy(float xPixel, float yPixel) { + return new CameraMoveUpdate(xPixel, yPixel); + } + + /** + * Returns a CameraUpdate that shifts the zoom level of the current camera viewpoint. + * + * @param amount Amount of zoom level to change with + * @param focus Focus point of zoom + * @return CameraUpdate Final Camera Position + */ + public static CameraUpdate zoomBy(double amount, Point focus) { + return new ZoomUpdate(amount, focus.x, focus.y); + } + + /** + * Returns a CameraUpdate that shifts the zoom level of the current camera viewpoint. + * + * @param amount Amount of zoom level to change with + * @return CameraUpdate Final Camera Position + */ + public static CameraUpdate zoomBy(double amount) { + return new ZoomUpdate(ZoomUpdate.ZOOM_BY, amount); + } + + /** + * Returns a CameraUpdate that zooms in on the map by moving the viewpoint's height closer to + * the Earth's surface. The zoom increment is 1.0. + * + * @return CameraUpdate Final Camera Position + */ + public static CameraUpdate zoomIn() { + return new ZoomUpdate(ZoomUpdate.ZOOM_IN); + } + + /** + * Returns a CameraUpdate that zooms out on the map by moving the viewpoint's height farther + * away from the Earth's surface. The zoom increment is -1.0. + * + * @return CameraUpdate Final Camera Position + */ + public static CameraUpdate zoomOut() { + return new ZoomUpdate(ZoomUpdate.ZOOM_OUT); + } + + /** + * Returns a CameraUpdate that moves the camera viewpoint to a particular zoom level. + * + * @param zoom Zoom level to change to + * @return CameraUpdate Final Camera Position + */ + public static CameraUpdate zoomTo(double zoom) { + return new ZoomUpdate(ZoomUpdate.ZOOM_TO, zoom); + } + + // + // CameraUpdate types + // + + static final class CameraPositionUpdate implements CameraUpdate { + + private final double bearing; + private final LatLng target; + private final double tilt; + private final double zoom; + + CameraPositionUpdate(double bearing, LatLng target, double tilt, double zoom) { + this.bearing = bearing; + this.target = target; + this.tilt = tilt; + this.zoom = zoom; } - /** - * Returns a CameraUpdate that moves the center of the screen to a latitude and longitude - * specified by a LatLng object. This centers the camera on the LatLng object. - * - * @param latLng Target location to change to - * @return CameraUpdate Final Camera Position - */ - public static CameraUpdate newLatLng(@NonNull LatLng latLng) { - return new CameraPositionUpdate(-1, latLng, -1, -1); + public LatLng getTarget() { + return target; } - /** - * Returns a {@link CameraUpdate} that transforms the camera such that the specified - * latitude/longitude bounds are centered on screen at the greatest possible zoom level. - * You can specify padding, in order to inset the bounding box from the map view's edges. - * The returned CameraUpdate has a bearing of 0 and a tilt of 0. - * - * @param bounds Bounds to match Camera position with - * @param padding Padding added to the bounds - * @return CameraUpdate Final Camera Position - */ - public static CameraUpdate newLatLngBounds(@NonNull LatLngBounds bounds, int padding) { - return newLatLngBounds(bounds, padding, padding, padding, padding); + public double getBearing() { + return bearing; } - /** - * Returns a {@link CameraUpdate} that transforms the camera such that the specified - * latitude/longitude bounds are centered on screen at the greatest possible zoom level. - * You can specify padding, in order to inset the bounding box from the map view's edges. - * The returned CameraUpdate has a bearing of 0 and a tilt of 0. - * - * @param bounds Bounds to base the Camera position out of - * @param paddingLeft Padding left of the bounds - * @param paddingTop Padding top of the bounds - * @param paddingRight Padding right of the bounds - * @param paddingBottom Padding bottom of the bounds - * @return CameraUpdate Final Camera Position - */ - public static CameraUpdate newLatLngBounds(@NonNull LatLngBounds bounds, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) { - return new CameraBoundsUpdate(bounds, paddingLeft, paddingTop, paddingRight, paddingBottom); + public double getTilt() { + return tilt; } - /** - * Returns a CameraUpdate that moves the center of the screen to a latitude and longitude - * specified by a LatLng object, and moves to the given zoom level. - * - * @param latLng Target location to change to - * @param zoom Zoom level to change to - * @return CameraUpdate Final Camera Position - */ - public static CameraUpdate newLatLngZoom(@NonNull LatLng latLng, double zoom) { - return new CameraPositionUpdate(-1, latLng, -1, zoom); + public double getZoom() { + return zoom; } - /** - * Returns a CameraUpdate that scrolls the camera over the map, - * shifting the center of view by the specified number of pixels in the x and y directions. - * - * @param xPixel Amount of pixels to scroll to in x direction - * @param yPixel Amount of pixels to scroll to in y direction - * @return CameraUpdate Final Camera Position - */ - public static CameraUpdate scrollBy(float xPixel, float yPixel) { - return new CameraMoveUpdate(xPixel, yPixel); + @Override + public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) { + CameraPosition previousPosition = mapboxMap.getCameraPosition(); + if (target == null) { + return new CameraPosition.Builder(this) + .target(previousPosition.target) + .build(); + } + return new CameraPosition.Builder(this).build(); } + } - /** - * Returns a CameraUpdate that shifts the zoom level of the current camera viewpoint. - * - * @param amount Amount of zoom level to change with - * @param focus Focus point of zoom - * @return CameraUpdate Final Camera Position - */ - public static CameraUpdate zoomBy(double amount, Point focus) { - return new ZoomUpdate(amount, focus.x, focus.y); + static final class CameraBoundsUpdate implements CameraUpdate { + + private LatLngBounds bounds; + private RectF padding; + + CameraBoundsUpdate(LatLngBounds bounds, RectF padding) { + this.bounds = bounds; + this.padding = padding; } - /** - * Returns a CameraUpdate that shifts the zoom level of the current camera viewpoint. - * - * @param amount Amount of zoom level to change with - * @return CameraUpdate Final Camera Position - */ - public static CameraUpdate zoomBy(double amount) { - return new ZoomUpdate(ZoomUpdate.ZOOM_BY, amount); + CameraBoundsUpdate(LatLngBounds bounds, int[] padding) { + this(bounds, new RectF(padding[0], padding[1], padding[2], padding[3])); } - /** - * Returns a CameraUpdate that zooms in on the map by moving the viewpoint's height closer to - * the Earth's surface. The zoom increment is 1.0. - * - * @return CameraUpdate Final Camera Position - */ - public static CameraUpdate zoomIn() { - return new ZoomUpdate(ZoomUpdate.ZOOM_IN); + CameraBoundsUpdate(LatLngBounds bounds, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) { + this(bounds, new int[] {paddingLeft, paddingTop, paddingRight, paddingBottom}); } - /** - * Returns a CameraUpdate that zooms out on the map by moving the viewpoint's height farther - * away from the Earth's surface. The zoom increment is -1.0. - * - * @return CameraUpdate Final Camera Position - */ - public static CameraUpdate zoomOut() { - return new ZoomUpdate(ZoomUpdate.ZOOM_OUT); + public LatLngBounds getBounds() { + return bounds; + } + + public RectF getPadding() { + return padding; + } + + @Override + public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) { + // Get required objects + Projection projection = mapboxMap.getProjection(); + UiSettings uiSettings = mapboxMap.getUiSettings(); + + // calculate correct padding + int[] mapPadding = mapboxMap.getPadding(); + RectF latLngPadding = getPadding(); + RectF padding = new RectF(latLngPadding.left + mapPadding[0], + latLngPadding.top + mapPadding[1], + latLngPadding.right + mapPadding[2], + latLngPadding.bottom + mapPadding[3]); + + // Calculate the bounds of the possibly rotated shape with respect to the viewport + PointF nePixel = new PointF(-Float.MAX_VALUE, -Float.MAX_VALUE); + PointF swPixel = new PointF(Float.MAX_VALUE, Float.MAX_VALUE); + float viewportHeight = uiSettings.getHeight(); + for (LatLng latLng : getBounds().toLatLngs()) { + PointF pixel = projection.toScreenLocation(latLng); + swPixel.x = Math.min(swPixel.x, pixel.x); + nePixel.x = Math.max(nePixel.x, pixel.x); + swPixel.y = Math.min(swPixel.y, viewportHeight - pixel.y); + nePixel.y = Math.max(nePixel.y, viewportHeight - pixel.y); + } + + // Calculate width/height + float width = nePixel.x - swPixel.x; + float height = nePixel.y - swPixel.y; + + double zoom = 0; + float minScale = 1; + // Calculate the zoom level + if (padding != null) { + float scaleX = (uiSettings.getWidth() - padding.left - padding.right) / width; + float scaleY = (uiSettings.getHeight() - padding.top - padding.bottom) / height; + minScale = scaleX < scaleY ? scaleX : scaleY; + zoom = calculateZoom(mapboxMap, minScale); + zoom = MathUtils.clamp(zoom, mapboxMap.getMinZoomLevel(), mapboxMap.getMaxZoomLevel()); + } + + // Calculate the center point + PointF paddedNEPixel = new PointF(nePixel.x + padding.right / minScale, nePixel.y + padding.top / minScale); + PointF paddedSWPixel = new PointF(swPixel.x - padding.left / minScale, swPixel.y - padding.bottom / minScale); + PointF centerPixel = new PointF((paddedNEPixel.x + paddedSWPixel.x) / 2, (paddedNEPixel.y + paddedSWPixel.y) / 2); + centerPixel.y = viewportHeight - centerPixel.y; + LatLng center = projection.fromScreenLocation(centerPixel); + + return new CameraPosition.Builder() + .target(center) + .zoom(zoom) + .tilt(0) + .bearing(0) + .build(); } /** - * Returns a CameraUpdate that moves the camera viewpoint to a particular zoom level. + * Calculates a zoom level based on minimum scale and current scale from MapView * - * @param zoom Zoom level to change to - * @return CameraUpdate Final Camera Position + * @param minScale The minimum scale to calculate the zoom level. + * @return zoom level that fits the MapView. */ - public static CameraUpdate zoomTo(double zoom) { - return new ZoomUpdate(ZoomUpdate.ZOOM_TO, zoom); + public double calculateZoom(MapboxMap mapboxMap, float minScale) { + return Math.log(mapboxMap.getCameraPosition().zoom * minScale) / Math.log(2); + } + } + + static final class CameraMoveUpdate implements CameraUpdate { + + private float x; + private float y; + + CameraMoveUpdate(float x, float y) { + this.x = x; + this.y = y; + } + + @Override + public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) { + UiSettings uiSettings = mapboxMap.getUiSettings(); + Projection projection = mapboxMap.getProjection(); + + // Calculate the new center point + float viewPortWidth = uiSettings.getWidth(); + float viewPortHeight = uiSettings.getHeight(); + PointF targetPoint = new PointF(viewPortWidth / 2 + x, viewPortHeight / 2 + y); + + // Convert point to LatLng + LatLng latLng = projection.fromScreenLocation(targetPoint); + + CameraPosition previousPosition = mapboxMap.getCameraPosition(); + return new CameraPosition.Builder() + .target(latLng != null ? latLng : previousPosition.target) + .zoom(previousPosition.zoom) + .tilt(previousPosition.tilt) + .bearing(previousPosition.bearing) + .build(); + } + } + + static final class ZoomUpdate implements CameraUpdate { + + @IntDef( {ZOOM_IN, ZOOM_OUT, ZOOM_BY, ZOOM_TO, ZOOM_TO_POINT}) + @Retention(RetentionPolicy.SOURCE) + @interface Type { + } + + static final int ZOOM_IN = 0; + static final int ZOOM_OUT = 1; + static final int ZOOM_BY = 2; + static final int ZOOM_TO = 3; + static final int ZOOM_TO_POINT = 4; + + @Type + private final int type; + private final double zoom; + private float x; + private float y; + + ZoomUpdate(@Type int type) { + this.type = type; + this.zoom = 0; + } + + ZoomUpdate(@Type int type, double zoom) { + this.type = type; + this.zoom = zoom; + } + + ZoomUpdate(double zoom, float x, float y) { + this.type = ZOOM_TO_POINT; + this.zoom = zoom; + this.x = x; + this.y = y; + } + + public double getZoom() { + return zoom; + } + + @Type + public int getType() { + return type; } - // - // CameraUpdate types - // - - static final class CameraPositionUpdate implements CameraUpdate { - - private final double bearing; - private final LatLng target; - private final double tilt; - private final double zoom; - - CameraPositionUpdate(double bearing, LatLng target, double tilt, double zoom) { - this.bearing = bearing; - this.target = target; - this.tilt = tilt; - this.zoom = zoom; - } - - public LatLng getTarget() { - return target; - } - - public double getBearing() { - return bearing; - } - - public double getTilt() { - return tilt; - } - - public double getZoom() { - return zoom; - } - - @Override - public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) { - CameraPosition previousPosition = mapboxMap.getCameraPosition(); - if (target == null) { - return new CameraPosition.Builder(this) - .target(previousPosition.target) - .build(); - } - return new CameraPosition.Builder(this).build(); - } + public float getX() { + return x; } - static final class CameraBoundsUpdate implements CameraUpdate { - - private LatLngBounds bounds; - private RectF padding; - - CameraBoundsUpdate(LatLngBounds bounds, RectF padding) { - this.bounds = bounds; - this.padding = padding; - } - - CameraBoundsUpdate(LatLngBounds bounds, int[] padding) { - this(bounds, new RectF(padding[0], padding[1], padding[2], padding[3])); - } - - CameraBoundsUpdate(LatLngBounds bounds, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) { - this(bounds, new int[]{paddingLeft, paddingTop, paddingRight, paddingBottom}); - } - - public LatLngBounds getBounds() { - return bounds; - } - - public RectF getPadding() { - return padding; - } - - @Override - public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) { - // Get required objects - Projection projection = mapboxMap.getProjection(); - UiSettings uiSettings = mapboxMap.getUiSettings(); - - // calculate correct padding - int[] mapPadding = mapboxMap.getPadding(); - RectF latLngPadding = getPadding(); - RectF padding = new RectF(latLngPadding.left + mapPadding[0], - latLngPadding.top + mapPadding[1], - latLngPadding.right + mapPadding[2], - latLngPadding.bottom + mapPadding[3]); - - // Calculate the bounds of the possibly rotated shape with respect to the viewport - PointF nePixel = new PointF(-Float.MAX_VALUE, -Float.MAX_VALUE); - PointF swPixel = new PointF(Float.MAX_VALUE, Float.MAX_VALUE); - float viewportHeight = uiSettings.getHeight(); - for (LatLng latLng : getBounds().toLatLngs()) { - PointF pixel = projection.toScreenLocation(latLng); - swPixel.x = Math.min(swPixel.x, pixel.x); - nePixel.x = Math.max(nePixel.x, pixel.x); - swPixel.y = Math.min(swPixel.y, viewportHeight - pixel.y); - nePixel.y = Math.max(nePixel.y, viewportHeight - pixel.y); - } - - // Calculate width/height - float width = nePixel.x - swPixel.x; - float height = nePixel.y - swPixel.y; - - double zoom = 0; - float minScale = 1; - // Calculate the zoom level - if (padding != null) { - float scaleX = (uiSettings.getWidth() - padding.left - padding.right) / width; - float scaleY = (uiSettings.getHeight() - padding.top - padding.bottom) / height; - minScale = scaleX < scaleY ? scaleX : scaleY; - zoom = calculateZoom(mapboxMap, minScale); - zoom = MathUtils.clamp(zoom, mapboxMap.getMinZoomLevel(), mapboxMap.getMaxZoomLevel()); - } - - // Calculate the center point - PointF paddedNEPixel = new PointF(nePixel.x + padding.right / minScale, nePixel.y + padding.top / minScale); - PointF paddedSWPixel = new PointF(swPixel.x - padding.left / minScale, swPixel.y - padding.bottom / minScale); - PointF centerPixel = new PointF((paddedNEPixel.x + paddedSWPixel.x) / 2, (paddedNEPixel.y + paddedSWPixel.y) / 2); - centerPixel.y = viewportHeight - centerPixel.y; - LatLng center = projection.fromScreenLocation(centerPixel); - - return new CameraPosition.Builder() - .target(center) - .zoom(zoom) - .tilt(0) - .bearing(0) - .build(); - } - - /** - * Calculates a zoom level based on minimum scale and current scale from MapView - * - * @param minScale The minimum scale to calculate the zoom level. - * @return zoom level that fits the MapView. - */ - public double calculateZoom(MapboxMap mapboxMap, float minScale) { - return Math.log(mapboxMap.getCameraPosition().zoom * minScale) / Math.log(2); - } + public float getY() { + return y; } - static final class CameraMoveUpdate implements CameraUpdate { - - private float x; - private float y; - - CameraMoveUpdate(float x, float y) { - this.x = x; - this.y = y; - } - - @Override - public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) { - UiSettings uiSettings = mapboxMap.getUiSettings(); - Projection projection = mapboxMap.getProjection(); - - // Calculate the new center point - float viewPortWidth = uiSettings.getWidth(); - float viewPortHeight = uiSettings.getHeight(); - PointF targetPoint = new PointF(viewPortWidth / 2 + x, viewPortHeight / 2 + y); - - // Convert point to LatLng - LatLng latLng = projection.fromScreenLocation(targetPoint); - - CameraPosition previousPosition = mapboxMap.getCameraPosition(); - return new CameraPosition.Builder() - .target(latLng != null ? latLng : previousPosition.target) - .zoom(previousPosition.zoom) - .tilt(previousPosition.tilt) - .bearing(previousPosition.bearing) - .build(); - } + double transformZoom(double currentZoom) { + switch (getType()) { + case CameraUpdateFactory.ZoomUpdate.ZOOM_IN: + currentZoom++; + break; + case CameraUpdateFactory.ZoomUpdate.ZOOM_OUT: + currentZoom--; + if (currentZoom < 0) { + currentZoom = 0; + } + break; + case CameraUpdateFactory.ZoomUpdate.ZOOM_TO: + currentZoom = getZoom(); + break; + case CameraUpdateFactory.ZoomUpdate.ZOOM_BY: + currentZoom = currentZoom + getZoom(); + break; + case CameraUpdateFactory.ZoomUpdate.ZOOM_TO_POINT: + currentZoom = currentZoom + getZoom(); + break; + } + return currentZoom; } - static final class ZoomUpdate implements CameraUpdate { - - @IntDef({ZOOM_IN, ZOOM_OUT, ZOOM_BY, ZOOM_TO, ZOOM_TO_POINT}) - @Retention(RetentionPolicy.SOURCE) - @interface Type { - } - - static final int ZOOM_IN = 0; - static final int ZOOM_OUT = 1; - static final int ZOOM_BY = 2; - static final int ZOOM_TO = 3; - static final int ZOOM_TO_POINT = 4; - - @Type - private final int type; - private final double zoom; - private float x; - private float y; - - ZoomUpdate(@Type int type) { - this.type = type; - this.zoom = 0; - } - - ZoomUpdate(@Type int type, double zoom) { - this.type = type; - this.zoom = zoom; - } - - ZoomUpdate(double zoom, float x, float y) { - this.type = ZOOM_TO_POINT; - this.zoom = zoom; - this.x = x; - this.y = y; - } - - public double getZoom() { - return zoom; - } - - @Type - public int getType() { - return type; - } - - public float getX() { - return x; - } - - public float getY() { - return y; - } - - double transformZoom(double currentZoom) { - switch (getType()) { - case CameraUpdateFactory.ZoomUpdate.ZOOM_IN: - currentZoom++; - break; - case CameraUpdateFactory.ZoomUpdate.ZOOM_OUT: - currentZoom--; - if (currentZoom < 0) { - currentZoom = 0; - } - break; - case CameraUpdateFactory.ZoomUpdate.ZOOM_TO: - currentZoom = getZoom(); - break; - case CameraUpdateFactory.ZoomUpdate.ZOOM_BY: - currentZoom = currentZoom + getZoom(); - break; - case CameraUpdateFactory.ZoomUpdate.ZOOM_TO_POINT: - currentZoom = currentZoom + getZoom(); - break; - } - return currentZoom; - } - - @Override - public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) { - CameraPosition cameraPosition = mapboxMap.getCameraPosition(); - if (getType() != CameraUpdateFactory.ZoomUpdate.ZOOM_TO_POINT) { - return new CameraPosition.Builder(cameraPosition) - .zoom(transformZoom(cameraPosition.zoom)) - .build(); - } else { - return new CameraPosition.Builder(cameraPosition) - .zoom(transformZoom(cameraPosition.zoom)) - .target(mapboxMap.getProjection().fromScreenLocation(new PointF(getX(), getY()))) - .build(); - } - } + @Override + public CameraPosition getCameraPosition(@NonNull MapboxMap mapboxMap) { + CameraPosition cameraPosition = mapboxMap.getCameraPosition(); + if (getType() != CameraUpdateFactory.ZoomUpdate.ZOOM_TO_POINT) { + return new CameraPosition.Builder(cameraPosition) + .zoom(transformZoom(cameraPosition.zoom)) + .build(); + } else { + return new CameraPosition.Builder(cameraPosition) + .zoom(transformZoom(cameraPosition.zoom)) + .target(mapboxMap.getProjection().fromScreenLocation(new PointF(getX(), getY()))) + .build(); + } } + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/GeoConstants.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/GeoConstants.java index ed6f77f419..009ae936d5 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/GeoConstants.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/GeoConstants.java @@ -5,34 +5,34 @@ package com.mapbox.mapboxsdk.constants; */ public class GeoConstants { - /** - * The <a href='http://en.wikipedia.org/wiki/Earth_radius#Equatorial_radius'>equatorial radius</a> - * value in meters - */ - public static final int RADIUS_EARTH_METERS = 6378137; + /** + * The <a href='http://en.wikipedia.org/wiki/Earth_radius#Equatorial_radius'>equatorial radius</a> + * value in meters + */ + public static final int RADIUS_EARTH_METERS = 6378137; - /** - * The minimum latitude on Earth. This is the minimum latitude representable - * by Mapbox GL's Mercator projection, because the projection distorts latitude - * near the poles towards infinity. - */ - public static final double MIN_LATITUDE = -85.05112878; + /** + * The minimum latitude on Earth. This is the minimum latitude representable + * by Mapbox GL's Mercator projection, because the projection distorts latitude + * near the poles towards infinity. + */ + public static final double MIN_LATITUDE = -85.05112878; - /** - * The maximum latitude on Earth. This is the maximum latitude representable - * by Mapbox GL's Mercator projection, because the projection distorts latitude - * near the poles towards infinity. - */ - public static final double MAX_LATITUDE = 85.05112878; + /** + * The maximum latitude on Earth. This is the maximum latitude representable + * by Mapbox GL's Mercator projection, because the projection distorts latitude + * near the poles towards infinity. + */ + public static final double MAX_LATITUDE = 85.05112878; - /** - * The minimum longitude on Earth - */ - public static final double MIN_LONGITUDE = -180; + /** + * The minimum longitude on Earth + */ + public static final double MIN_LONGITUDE = -180; - /** - * The maximum longitude on Earth - */ - public static final double MAX_LONGITUDE = 180; + /** + * The maximum longitude on Earth + */ + public static final double MAX_LONGITUDE = 180; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java index 9c5e8194dd..fb3240fd7b 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java @@ -1,6 +1,7 @@ package com.mapbox.mapboxsdk.constants; import android.content.Context; + import java.util.Locale; /** @@ -8,137 +9,140 @@ import java.util.Locale; */ public class MapboxConstants { - /** - * Default Locale for data processing (ex: String.toLowerCase(MAPBOX_LOCALE, "foo")) - */ - public static final Locale MAPBOX_LOCALE = Locale.US; - - /** - * Key used to store access token in AndroidManifest.xml - * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)} - */ - @Deprecated - public static final String KEY_META_DATA_MANIFEST = "com.mapbox.AccessToken"; - - /** - * Key used to store staging data server url in AndroidManifest.xml - */ - public static final String KEY_META_DATA_STAGING_SERVER = "com.mapbox.TestEventsServer"; - - /** - * Key used to store staging data server access token in AndroidManifest.xml - */ - public static final String KEY_META_DATA_STAGING_ACCESS_TOKEN = "com.mapbox.TestEventsAccessToken"; - - /** - * Key used to switch storage to external in AndroidManifest.xml - */ - public final static String KEY_META_DATA_SET_STORAGE_EXTERNAL = "com.mapbox.SetStorageExternal"; - - /** - * Default value for KEY_META_DATA_SET_STORAGE_EXTERNAL (default is internal storage) - */ - public final static boolean DEFAULT_SET_STORAGE_EXTERNAL = false; - - /** - * Unmeasured state - */ - public final static float UNMEASURED = -1f; - - /** - * Default animation time - */ - public static final int ANIMATION_DURATION = 300; - - /** - * Default short animation time - */ - public static final int ANIMATION_DURATION_SHORT = 150; - - /** - * Animation time of a fling gesture - */ - public static final long ANIMATION_DURATION_FLING = 350; - - /** - * The currently supported minimum zoom level. - */ - public static final float MINIMUM_ZOOM = 0.0f; - - /** - * The currently supported maximum zoom level. - */ - public static final float MAXIMUM_ZOOM = 20.0f; - - /** - * The currently supported maximum tilt value. - */ - public static final double MAXIMUM_TILT = 60; - - /** - * The currently supported minimum tilt value. - */ - public static final double MINIMUM_TILT = 0; - - /** - * The currently supported maximum direction - */ - public static final double MAXIMUM_DIRECTION = 360; - - /** - * The currently supported minimum direction - */ - public static final double MINIMUM_DIRECTION = 0; - - /** - * Fragment Argument Key for MapboxMapOptions - */ - public static final String FRAG_ARG_MAPBOXMAPOPTIONS = "MapboxMapOptions"; - - // Save instance state keys - public static final String STATE_HAS_SAVED_STATE = "savedState"; - public static final String STATE_CAMERA_POSITION = "cameraPosition"; - public static final String STATE_ZOOM_ENABLED = "zoomEnabled"; - public static final String STATE_ZOOM_ENABLED_CHANGE = "zoomEnabledChange"; - public static final String STATE_SCROLL_ENABLED = "scrollEnabled"; - public static final String STATE_SCROLL_ENABLED_CHANGE = "scrollEnabledChange"; - public static final String STATE_ROTATE_ENABLED = "rotateEnabled"; - public static final String STATE_ROTATE_ENABLED_CHANGE = "rotateEnabledChange"; - public static final String STATE_TILT_ENABLED = "tiltEnabled"; - public static final String STATE_TILT_ENABLED_CHANGE = "tiltEnabledChange"; - public static final String STATE_ZOOM_CONTROLS_ENABLED = "zoomControlsEnabled"; - public static final String STATE_DEBUG_ACTIVE = "debugActive"; - public static final String STATE_STYLE_URL = "styleUrl"; - public static final String STATE_MY_LOCATION_ENABLED = "myLocationEnabled"; - public static final String STATE_MY_LOCATION_TRACKING_MODE = "myLocationTracking"; - public static final String STATE_MY_BEARING_TRACKING_MODE = "myBearingTracking"; - public static final String STATE_MY_LOCATION_TRACKING_DISMISS = "myLocationTrackingDismiss"; - public static final String STATE_MY_BEARING_TRACKING_DISMISS = "myBearingTrackingDismiss"; - public static final String STATE_COMPASS_ENABLED = "compassEnabled"; - public static final String STATE_COMPASS_GRAVITY = "compassGravity"; - public static final String STATE_COMPASS_MARGIN_LEFT = "compassMarginLeft"; - public static final String STATE_COMPASS_MARGIN_TOP = "compassMarginTop"; - public static final String STATE_COMPASS_MARGIN_RIGHT = "compassMarginRight"; - public static final String STATE_COMPASS_MARGIN_BOTTOM = "compassMarginBottom"; - public static final String STATE_COMPASS_FADE_WHEN_FACING_NORTH = "compassFade"; - public static final String STATE_LOGO_GRAVITY = "logoGravity"; - public static final String STATE_LOGO_MARGIN_LEFT = "logoMarginLeft"; - public static final String STATE_LOGO_MARGIN_TOP = "logoMarginTop"; - public static final String STATE_LOGO_MARGIN_RIGHT = "logoMarginRight"; - public static final String STATE_LOGO_MARGIN_BOTTOM = "logoMarginBottom"; - public static final String STATE_LOGO_ENABLED = "logoEnabled"; - public static final String STATE_ATTRIBUTION_GRAVITY = "attrGravity"; - public static final String STATE_ATTRIBUTION_MARGIN_LEFT = "attrMarginLeft"; - public static final String STATE_ATTRIBUTION_MARGIN_TOP = "attrMarginTop"; - public static final String STATE_ATTRIBUTION_MARGIN_RIGHT = "attrMarginRight"; - public static final String STATE_ATTRIBUTION_MARGIN_BOTTOM = "atrrMarginBottom"; - public static final String STATE_ATTRIBUTION_ENABLED = "atrrEnabled"; - - public static final String TAG = "MapboxMap"; - - public static final String MAPBOX_SHARED_PREFERENCES_FILE = "MapboxSharedPreferences"; - public static final String MAPBOX_SHARED_PREFERENCE_KEY_VENDORID = "mapboxVendorId"; - public static final String MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_ENABLED = "mapboxTelemetryEnabled"; - public static final String MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_URL = "mapboxTelemetryStagingUrl"; - public static final String MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_ACCESS_TOKEN = "mapboxTelemetryStagingAccessToken"; + /** + * Default Locale for data processing (ex: String.toLowerCase(MAPBOX_LOCALE, "foo")) + */ + public static final Locale MAPBOX_LOCALE = Locale.US; + + /** + * Key used to store access token in AndroidManifest.xml + * + * @deprecated As of release 4.1.0, replaced by + * {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)} + */ + @Deprecated + public static final String KEY_META_DATA_MANIFEST = "com.mapbox.AccessToken"; + + /** + * Key used to store staging data server url in AndroidManifest.xml + */ + public static final String KEY_META_DATA_STAGING_SERVER = "com.mapbox.TestEventsServer"; + + /** + * Key used to store staging data server access token in AndroidManifest.xml + */ + public static final String KEY_META_DATA_STAGING_ACCESS_TOKEN = "com.mapbox.TestEventsAccessToken"; + + /** + * Key used to switch storage to external in AndroidManifest.xml + */ + public static final String KEY_META_DATA_SET_STORAGE_EXTERNAL = "com.mapbox.SetStorageExternal"; + + /** + * Default value for KEY_META_DATA_SET_STORAGE_EXTERNAL (default is internal storage) + */ + public static final boolean DEFAULT_SET_STORAGE_EXTERNAL = false; + + /** + * Unmeasured state + */ + public static final float UNMEASURED = -1f; + + /** + * Default animation time + */ + public static final int ANIMATION_DURATION = 300; + + /** + * Default short animation time + */ + public static final int ANIMATION_DURATION_SHORT = 150; + + /** + * Animation time of a fling gesture + */ + public static final long ANIMATION_DURATION_FLING = 350; + + /** + * The currently supported minimum zoom level. + */ + public static final float MINIMUM_ZOOM = 0.0f; + + /** + * The currently supported maximum zoom level. + */ + public static final float MAXIMUM_ZOOM = 20.0f; + + /** + * The currently supported maximum tilt value. + */ + public static final double MAXIMUM_TILT = 60; + + /** + * The currently supported minimum tilt value. + */ + public static final double MINIMUM_TILT = 0; + + /** + * The currently supported maximum direction + */ + public static final double MAXIMUM_DIRECTION = 360; + + /** + * The currently supported minimum direction + */ + public static final double MINIMUM_DIRECTION = 0; + + /** + * Fragment Argument Key for MapboxMapOptions + */ + public static final String FRAG_ARG_MAPBOXMAPOPTIONS = "MapboxMapOptions"; + + // Save instance state keys + public static final String STATE_HAS_SAVED_STATE = "savedState"; + public static final String STATE_CAMERA_POSITION = "cameraPosition"; + public static final String STATE_ZOOM_ENABLED = "zoomEnabled"; + public static final String STATE_ZOOM_ENABLED_CHANGE = "zoomEnabledChange"; + public static final String STATE_SCROLL_ENABLED = "scrollEnabled"; + public static final String STATE_SCROLL_ENABLED_CHANGE = "scrollEnabledChange"; + public static final String STATE_ROTATE_ENABLED = "rotateEnabled"; + public static final String STATE_ROTATE_ENABLED_CHANGE = "rotateEnabledChange"; + public static final String STATE_TILT_ENABLED = "tiltEnabled"; + public static final String STATE_TILT_ENABLED_CHANGE = "tiltEnabledChange"; + public static final String STATE_ZOOM_CONTROLS_ENABLED = "zoomControlsEnabled"; + public static final String STATE_DEBUG_ACTIVE = "debugActive"; + public static final String STATE_STYLE_URL = "styleUrl"; + public static final String STATE_MY_LOCATION_ENABLED = "myLocationEnabled"; + public static final String STATE_MY_LOCATION_TRACKING_MODE = "myLocationTracking"; + public static final String STATE_MY_BEARING_TRACKING_MODE = "myBearingTracking"; + public static final String STATE_MY_LOCATION_TRACKING_DISMISS = "myLocationTrackingDismiss"; + public static final String STATE_MY_BEARING_TRACKING_DISMISS = "myBearingTrackingDismiss"; + public static final String STATE_COMPASS_ENABLED = "compassEnabled"; + public static final String STATE_COMPASS_GRAVITY = "compassGravity"; + public static final String STATE_COMPASS_MARGIN_LEFT = "compassMarginLeft"; + public static final String STATE_COMPASS_MARGIN_TOP = "compassMarginTop"; + public static final String STATE_COMPASS_MARGIN_RIGHT = "compassMarginRight"; + public static final String STATE_COMPASS_MARGIN_BOTTOM = "compassMarginBottom"; + public static final String STATE_COMPASS_FADE_WHEN_FACING_NORTH = "compassFade"; + public static final String STATE_LOGO_GRAVITY = "logoGravity"; + public static final String STATE_LOGO_MARGIN_LEFT = "logoMarginLeft"; + public static final String STATE_LOGO_MARGIN_TOP = "logoMarginTop"; + public static final String STATE_LOGO_MARGIN_RIGHT = "logoMarginRight"; + public static final String STATE_LOGO_MARGIN_BOTTOM = "logoMarginBottom"; + public static final String STATE_LOGO_ENABLED = "logoEnabled"; + public static final String STATE_ATTRIBUTION_GRAVITY = "attrGravity"; + public static final String STATE_ATTRIBUTION_MARGIN_LEFT = "attrMarginLeft"; + public static final String STATE_ATTRIBUTION_MARGIN_TOP = "attrMarginTop"; + public static final String STATE_ATTRIBUTION_MARGIN_RIGHT = "attrMarginRight"; + public static final String STATE_ATTRIBUTION_MARGIN_BOTTOM = "atrrMarginBottom"; + public static final String STATE_ATTRIBUTION_ENABLED = "atrrEnabled"; + + public static final String TAG = "MapboxMap"; + + public static final String MAPBOX_SHARED_PREFERENCES_FILE = "MapboxSharedPreferences"; + public static final String MAPBOX_SHARED_PREFERENCE_KEY_VENDORID = "mapboxVendorId"; + public static final String MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_ENABLED = "mapboxTelemetryEnabled"; + public static final String MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_URL = "mapboxTelemetryStagingUrl"; + public static final String MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_ACCESS_TOKEN = + "mapboxTelemetryStagingAccessToken"; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java index 929df2da77..cba2fb282c 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java @@ -2,7 +2,6 @@ package com.mapbox.mapboxsdk.constants; import android.support.annotation.IntDef; -import com.mapbox.mapboxsdk.maps.MapView; import com.mapbox.mapboxsdk.maps.widgets.MyLocationView; import java.lang.annotation.Retention; @@ -11,34 +10,34 @@ import java.lang.annotation.RetentionPolicy; /** * MyBearingTracking exposes different types bearing tracking modes. * - * @see MapView#setMyBearingTrackingMode(int) + * @see com.mapbox.mapboxsdk.maps.TrackingSettings#setMyBearingTrackingMode(int) * @see MyLocationView#setMyBearingTrackingMode(int) */ public class MyBearingTracking { - /** - * Indicates the parameter accepts one of the values from {@link MyBearingTracking}. - */ - @IntDef({NONE, COMPASS, GPS, /**COMBINED**/}) - @Retention(RetentionPolicy.SOURCE) - public @interface Mode { - } - - /** - * Bearing tracking is disabled - */ - public static final int NONE = 0x00000000; - - /** - * Tracking the bearing of the user based on sensor data - */ - public static final int COMPASS = 0x00000004; - - /** - * Tracking the bearing of the user based on GPS data - */ - public static final int GPS = 0x00000008; - - //public static final int COMBINED = 0x00000012; + /** + * Indicates the parameter accepts one of the values from {@link MyBearingTracking}. + */ + @IntDef( {NONE, COMPASS, GPS, /**COMBINED**/}) + @Retention(RetentionPolicy.SOURCE) + public @interface Mode { + } + + /** + * Bearing tracking is disabled + */ + public static final int NONE = 0x00000000; + + /** + * Tracking the bearing of the user based on sensor data + */ + public static final int COMPASS = 0x00000004; + + /** + * Tracking the bearing of the user based on GPS data + */ + public static final int GPS = 0x00000008; + + //public static final int COMBINED = 0x00000012; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java index b2a49c6454..d1eaac04de 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java @@ -11,27 +11,27 @@ import java.lang.annotation.RetentionPolicy; /** * MyLocationTracking exposes different types of locational tracking modes. * - * @see MapView#setMyLocationTrackingMode(int) + * @see com.mapbox.mapboxsdk.maps.TrackingSettings#setMyLocationTrackingMode(int) * @see MyLocationView#setMyLocationTrackingMode(int) */ public class MyLocationTracking { - /** - * Indicates the parameter accepts one of the values from {@link MyLocationTracking}. - */ - @IntDef({TRACKING_NONE, TRACKING_FOLLOW}) - @Retention(RetentionPolicy.SOURCE) - public @interface Mode { - } - - /** - * Location tracking is disabled. - */ - public static final int TRACKING_NONE = 0x00000000; - - /** - * Tracking the location of the user, {@link MapView} will reposition to center of {@link MyLocationView} - */ - public static final int TRACKING_FOLLOW = 0x00000004; + /** + * Indicates the parameter accepts one of the values from {@link MyLocationTracking}. + */ + @IntDef( {TRACKING_NONE, TRACKING_FOLLOW}) + @Retention(RetentionPolicy.SOURCE) + public @interface Mode { + } + + /** + * Location tracking is disabled. + */ + public static final int TRACKING_NONE = 0x00000000; + + /** + * Tracking the location of the user, {@link MapView} will reposition to center of {@link MyLocationView} + */ + public static final int TRACKING_FOLLOW = 0x00000004; }
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java index 51eb038052..574ef4afa6 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java @@ -18,61 +18,61 @@ import java.lang.annotation.RetentionPolicy; public class Style { - /** - * Indicates the parameter accepts one of the values from {@link Style}. Using one of these - * constants means your map style will always use the latest version and may change as we - * improve the style - */ - @StringDef({MAPBOX_STREETS, OUTDOORS, EMERALD, LIGHT, DARK, SATELLITE, SATELLITE_STREETS}) - @Retention(RetentionPolicy.SOURCE) - public @interface StyleUrl { - } + /** + * Indicates the parameter accepts one of the values from {@link Style}. Using one of these + * constants means your map style will always use the latest version and may change as we + * improve the style + */ + @StringDef( {MAPBOX_STREETS, OUTDOORS, EMERALD, LIGHT, DARK, SATELLITE, SATELLITE_STREETS}) + @Retention(RetentionPolicy.SOURCE) + public @interface StyleUrl { + } - // IMPORTANT: If you change any of these you also need to edit them in strings.xml + // IMPORTANT: If you change any of these you also need to edit them in strings.xml - /** - * Mapbox Streets: A complete basemap, perfect for incorporating your own data. Using this - * constant means your map style will always use the latest version and may change as we - * improve the style. - */ - public static final String MAPBOX_STREETS = "mapbox://styles/mapbox/streets-v9"; + /** + * Mapbox Streets: A complete basemap, perfect for incorporating your own data. Using this + * constant means your map style will always use the latest version and may change as we + * improve the style. + */ + public static final String MAPBOX_STREETS = "mapbox://styles/mapbox/streets-v9"; - /** - * Outdoors: A general-purpose style tailored to outdoor activities. Using this constant means - * your map style will always use the latest version and may change as we improve the style. - */ - public static final String OUTDOORS = "mapbox://styles/mapbox/outdoors-v9"; + /** + * Outdoors: A general-purpose style tailored to outdoor activities. Using this constant means + * your map style will always use the latest version and may change as we improve the style. + */ + public static final String OUTDOORS = "mapbox://styles/mapbox/outdoors-v9"; - /** - * Emerald: A versatile style, with emphasis on road networks and public transit. - * - * @deprecated this style has been deprecated and will be removed in future versions. - */ - @Deprecated - public static final String EMERALD = "mapbox://styles/mapbox/emerald-v8"; + /** + * Emerald: A versatile style, with emphasis on road networks and public transit. + * + * @deprecated this style has been deprecated and will be removed in future versions. + */ + @Deprecated + public static final String EMERALD = "mapbox://styles/mapbox/emerald-v8"; - /** - * Light: Subtle light backdrop for data visualizations. Using this constant means your map - * style will always use the latest version and may change as we improve the style. - */ - public static final String LIGHT = "mapbox://styles/mapbox/light-v9"; + /** + * Light: Subtle light backdrop for data visualizations. Using this constant means your map + * style will always use the latest version and may change as we improve the style. + */ + public static final String LIGHT = "mapbox://styles/mapbox/light-v9"; - /** - * Dark: Subtle dark backdrop for data visualizations. Using this constant means your map style - * will always use the latest version and may change as we improve the style. - */ - public static final String DARK = "mapbox://styles/mapbox/dark-v9"; + /** + * Dark: Subtle dark backdrop for data visualizations. Using this constant means your map style + * will always use the latest version and may change as we improve the style. + */ + public static final String DARK = "mapbox://styles/mapbox/dark-v9"; - /** - * Satellite: A beautiful global satellite and aerial imagery layer. Using this constant means - * your map style will always use the latest version and may change as we improve the style. - */ - public static final String SATELLITE = "mapbox://styles/mapbox/satellite-v9"; + /** + * Satellite: A beautiful global satellite and aerial imagery layer. Using this constant means + * your map style will always use the latest version and may change as we improve the style. + */ + public static final String SATELLITE = "mapbox://styles/mapbox/satellite-v9"; - /** - * Satellite Streets: Global satellite and aerial imagery with unobtrusive labels. Using this - * constant means your map style will always use the latest version and may change as we - * improve the style. - */ - public static final String SATELLITE_STREETS = "mapbox://styles/mapbox/satellite-streets-v9"; + /** + * Satellite Streets: Global satellite and aerial imagery with unobtrusive labels. Using this + * constant means your map style will always use the latest version and may change as we + * improve the style. + */ + public static final String SATELLITE_STREETS = "mapbox://styles/mapbox/satellite-streets-v9"; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/ConversionException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/ConversionException.java index 87656db2a9..be2b586683 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/ConversionException.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/ConversionException.java @@ -5,18 +5,18 @@ package com.mapbox.mapboxsdk.exceptions; */ public class ConversionException extends RuntimeException { - public ConversionException() { - } + public ConversionException() { + } - public ConversionException(String detailMessage) { - super(detailMessage); - } + public ConversionException(String detailMessage) { + super(detailMessage); + } - public ConversionException(String detailMessage, Throwable throwable) { - super(detailMessage, throwable); - } + public ConversionException(String detailMessage, Throwable throwable) { + super(detailMessage, throwable); + } - public ConversionException(Throwable throwable) { - super(throwable); - } + public ConversionException(Throwable throwable) { + super(throwable); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/IconBitmapChangedException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/IconBitmapChangedException.java index 1be82d6178..7154049bd7 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/IconBitmapChangedException.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/IconBitmapChangedException.java @@ -19,9 +19,9 @@ import com.mapbox.mapboxsdk.maps.MapView; */ public class IconBitmapChangedException extends RuntimeException { - public IconBitmapChangedException() { - super("The added Marker has an Icon with a bitmap that has been modified. An Icon cannot be modified" + - "after it has been added to the map in a Marker."); - } + public IconBitmapChangedException() { + super("The added Marker has an Icon with a bitmap that has been modified. An Icon cannot be modified" + + "after it has been added to the map in a Marker."); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidAccessTokenException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidAccessTokenException.java index 77797ecb4f..9f95826ba3 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidAccessTokenException.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidAccessTokenException.java @@ -5,18 +5,19 @@ import android.os.Bundle; import com.mapbox.mapboxsdk.maps.MapView; /** - * A {@code InvalidAccessTokenException} is thrown by {@link com.mapbox.mapboxsdk.maps.MapboxMap} when there is either no access - * token set before {@link MapView#onCreate(Bundle)} or an invalid access token is set in {@link MapView#setAccessToken(String)} + * A {@code InvalidAccessTokenException} is thrown by {@link com.mapbox.mapboxsdk.maps.MapboxMap} when there is either + * no access token set before {@link MapView#onCreate(Bundle)} or an invalid access token is set in + * {@link MapView#setAccessToken(String)} * * @see MapView#onCreate(Bundle) * @see MapView#setAccessToken(String) */ public class InvalidAccessTokenException extends RuntimeException { - public InvalidAccessTokenException() { - super("\nUsing MapView requires setting a valid access token. Use setAccessToken on Mapview to provide one. " + - "\nPlease see https://www.mapbox.com/help/create-api-access-token/ to learn how to create one." + - "\nMore information in this guide https://www.mapbox.com/help/first-steps-android-sdk/#access-tokens."); - } + public InvalidAccessTokenException() { + super("\nUsing MapView requires setting a valid access token. Use setAccessToken on Mapview to provide one. " + + "\nPlease see https://www.mapbox.com/help/create-api-access-token/ to learn how to create one." + + "\nMore information in this guide https://www.mapbox.com/help/first-steps-android-sdk/#access-tokens."); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidLatLngBoundsException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidLatLngBoundsException.java index 92feaac64b..08a23a7373 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidLatLngBoundsException.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidLatLngBoundsException.java @@ -6,7 +6,7 @@ package com.mapbox.mapboxsdk.exceptions; */ public class InvalidLatLngBoundsException extends RuntimeException { - public InvalidLatLngBoundsException(int latLngsListSize) { - super("Cannot create a LatLngBounds from " + latLngsListSize + " items"); - } + public InvalidLatLngBoundsException(int latLngsListSize) { + super("Cannot create a LatLngBounds from " + latLngsListSize + " items"); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidMarkerPositionException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidMarkerPositionException.java index 8dc98118b1..e5a647841f 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidMarkerPositionException.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/InvalidMarkerPositionException.java @@ -2,9 +2,9 @@ package com.mapbox.mapboxsdk.exceptions; public class InvalidMarkerPositionException extends RuntimeException { - public InvalidMarkerPositionException() { - super("Adding an invalid Marker to a Map. " + - "Missing the required position field. " + - "Provide a non null LatLng as position to the Marker."); - } + public InvalidMarkerPositionException() { + super("Adding an invalid Marker to a Map. " + + "Missing the required position field. " + + "Provide a non null LatLng as position to the Marker."); + } }
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/MapboxAccountManagerNotStartedException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/MapboxAccountManagerNotStartedException.java index 4954098f15..e1179b4aa9 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/MapboxAccountManagerNotStartedException.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/MapboxAccountManagerNotStartedException.java @@ -1,7 +1,5 @@ package com.mapbox.mapboxsdk.exceptions; - -import android.content.Context; import android.os.Bundle; import com.mapbox.mapboxsdk.MapboxAccountManager; @@ -12,12 +10,13 @@ import com.mapbox.mapboxsdk.maps.MapView; * when {@link MapboxAccountManager} is not started before {@link MapView#onCreate(Bundle)}. * * @see MapView#onCreate(Bundle) - * @see MapboxAccountManager#start(Context, String) + * @see MapboxAccountManager#start(android.content.Context, String) */ public class MapboxAccountManagerNotStartedException extends RuntimeException { - public MapboxAccountManagerNotStartedException() { - super("\nMapboxAccountManager was not started correctly. Use MapboxAccountManager#start(Context, String) to initialise. " + - "\nMore information in this guide https://www.mapbox.com/help/first-steps-android-sdk/#access-tokens."); - } + public MapboxAccountManagerNotStartedException() { + super("\nMapboxAccountManager was not started correctly. Use MapboxAccountManager#start(Context, String) to" + + "initialise. " + + "\nMore information in this guide https://www.mapbox.com/help/first-steps-android-sdk/#access-tokens."); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TelemetryServiceNotConfiguredException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TelemetryServiceNotConfiguredException.java index ec2b0d792d..e2e114fa77 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TelemetryServiceNotConfiguredException.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TelemetryServiceNotConfiguredException.java @@ -12,10 +12,11 @@ import com.mapbox.mapboxsdk.maps.MapView; */ public class TelemetryServiceNotConfiguredException extends RuntimeException { - public TelemetryServiceNotConfiguredException() { - super("\nTelemetryService is not configured in your applications AndroidManifest.xml. " + - "\nPlease add \"com.mapbox.mapboxsdk.telemetry.TelemetryService\" service in your applications AndroidManifest.xml" + - "\nFor an example visit http://goo.gl/cET0Jn. For more information visit https://www.mapbox.com/android-sdk/."); - } + public TelemetryServiceNotConfiguredException() { + super("\nTelemetryService is not configured in your applications AndroidManifest.xml. " + + "\nPlease add \"com.mapbox.mapboxsdk.telemetry.TelemetryService\" service in your applications " + + "AndroidManifest.xml" + + "\nFor an example visit http://goo.gl/cET0Jn. For more information visit https://www.mapbox.com/android-sdk/."); + } }
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TooManyIconsException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TooManyIconsException.java index 4dcdea112c..8923d822f2 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TooManyIconsException.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/exceptions/TooManyIconsException.java @@ -14,8 +14,8 @@ import com.mapbox.mapboxsdk.annotations.IconFactory; */ public class TooManyIconsException extends RuntimeException { - public TooManyIconsException() { - super("Cannot create an Icon because there are already too many. Try reusing Icon objects whenever possible."); - } + public TooManyIconsException() { + super("Cannot create an Icon because there are already too many. Try reusing Icon objects whenever possible."); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ILatLng.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ILatLng.java index afd22e5ddb..1af8e7cfc7 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ILatLng.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ILatLng.java @@ -4,9 +4,9 @@ package com.mapbox.mapboxsdk.geometry; * Describes a latitude, longitude point. */ public interface ILatLng { - double getLatitude(); + double getLatitude(); - double getLongitude(); + double getLongitude(); - double getAltitude(); + double getAltitude(); } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/IProjectedMeters.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/IProjectedMeters.java index 43fe25f8e5..694c935143 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/IProjectedMeters.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/IProjectedMeters.java @@ -4,7 +4,7 @@ package com.mapbox.mapboxsdk.geometry; * Describes a projection in Mercator meters. */ public interface IProjectedMeters { - double getNorthing(); + double getNorthing(); - double getEasting(); + double getEasting(); } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java index 4449a7fe0d..b18b7e87b0 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java @@ -21,183 +21,191 @@ import com.mapbox.mapboxsdk.utils.MathUtils; */ public class LatLng implements ILatLng, Parcelable { - public static final Parcelable.Creator<LatLng> CREATOR = new Parcelable.Creator<LatLng>() { - public LatLng createFromParcel(Parcel in) { - return new LatLng(in); - } - - public LatLng[] newArray(int size) { - return new LatLng[size]; - } - }; - - private double latitude; - private double longitude; - private double altitude = 0.0; - - /** - * Construct a new latitude, longitude point at (0, 0) - */ - public LatLng() { - this.latitude = 0.0; - this.longitude = 0.0; - } - - /** - * Construct a new latitude, longitude point given float arguments - * @param latitude Latitude in degrees - * @param longitude Longitude in degrees - */ - public LatLng(double latitude, double longitude) { - this.latitude = latitude; - this.longitude = longitude; - } - - /** - * Construct a new latitude, longitude, altitude point given float arguments - * @param latitude Latitude in degrees - * @param longitude Longitude in degress - * @param altitude Altitude in meters - */ - public LatLng(double latitude, double longitude, double altitude) { - this.latitude = latitude; - this.longitude = longitude; - this.altitude = altitude; - } - - /** - * Transform a Location into a LatLng point - * @param location Android Location - */ - public LatLng(Location location) { - this(location.getLatitude(), location.getLongitude(), location.getAltitude()); - } - - /** - * Clone an existing latitude longitude point - * @param aLatLng LatLng - */ - public LatLng(LatLng aLatLng) { - this.latitude = aLatLng.latitude; - this.longitude = aLatLng.longitude; - this.altitude = aLatLng.altitude; - } - - protected LatLng(Parcel in) { - latitude = in.readDouble(); - longitude = in.readDouble(); - altitude = in.readDouble(); - } - - public void setLatitude(double latitude) { - this.latitude = latitude; - } - - @Override - public double getLatitude() { - return latitude; - } - - public void setLongitude(double longitude) { - this.longitude = longitude; - } - - @Override - public double getLongitude() { - return longitude; - } - - public void setAltitude(double altitude) { - this.altitude = altitude; - } - - @Override - public double getAltitude() { - return altitude; - } - - /** - * Return a new LatLng object with a wrapped Longitude. This allows original data object - * to remain unchanged. - * @return New LatLng object with wrapped Longitude - */ - public LatLng wrap(){ - LatLng wrappedVersion = new LatLng(this); - double lon = wrappedVersion.getLongitude(); - if (lon < GeoConstants.MIN_LONGITUDE || lon > GeoConstants.MAX_LONGITUDE) { - wrappedVersion.setLongitude(MathUtils.wrap(wrappedVersion.getLongitude(), GeoConstants.MIN_LONGITUDE, GeoConstants.MAX_LONGITUDE)); - } - return wrappedVersion; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - LatLng latLng = (LatLng) o; - - return Double.compare(latLng.altitude, altitude) == 0 && Double.compare(latLng.latitude, latitude) == 0 && Double.compare(latLng.longitude, longitude) == 0; - } - - @Override - public int hashCode() { - int result; - long temp; - temp = Double.doubleToLongBits(latitude); - result = (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(longitude); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(altitude); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - @Override - public String toString() { - return "LatLng [latitude=" + latitude + ", longitude=" + longitude + ", altitude=" + altitude + "]"; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeDouble(latitude); - out.writeDouble(longitude); - out.writeDouble(altitude); - } - - /** - * Calculate distance between two points - * @param other Other LatLng to compare to - * @return distance in meters - */ - public double distanceTo(LatLng other) { - if(latitude == other.latitude && longitude == other.longitude){ - // return 0.0 to avoid a NaN - return 0.0; - } - - final double a1 = Math.toRadians(this.latitude); - final double a2 = Math.toRadians(this.longitude); - final double b1 = Math.toRadians(other.getLatitude()); - final double b2 = Math.toRadians(other.getLongitude()); - - final double cosa1 = Math.cos(a1); - final double cosb1 = Math.cos(b1); - - final double t1 = cosa1 * Math.cos(a2) * cosb1 * Math.cos(b2); - final double t2 = cosa1 * Math.sin(a2) * cosb1 * Math.sin(b2); - final double t3 = Math.sin(a1) * Math.sin(b1); - final double tt = Math.acos(t1 + t2 + t3); - - return GeoConstants.RADIUS_EARTH_METERS * tt; - } + public static final Parcelable.Creator<LatLng> CREATOR = new Parcelable.Creator<LatLng>() { + public LatLng createFromParcel(Parcel in) { + return new LatLng(in); + } + + public LatLng[] newArray(int size) { + return new LatLng[size]; + } + }; + + private double latitude; + private double longitude; + private double altitude = 0.0; + + /** + * Construct a new latitude, longitude point at (0, 0) + */ + public LatLng() { + this.latitude = 0.0; + this.longitude = 0.0; + } + + /** + * Construct a new latitude, longitude point given float arguments + * + * @param latitude Latitude in degrees + * @param longitude Longitude in degrees + */ + public LatLng(double latitude, double longitude) { + this.latitude = latitude; + this.longitude = longitude; + } + + /** + * Construct a new latitude, longitude, altitude point given float arguments + * + * @param latitude Latitude in degrees + * @param longitude Longitude in degress + * @param altitude Altitude in meters + */ + public LatLng(double latitude, double longitude, double altitude) { + this.latitude = latitude; + this.longitude = longitude; + this.altitude = altitude; + } + + /** + * Transform a Location into a LatLng point + * + * @param location Android Location + */ + public LatLng(Location location) { + this(location.getLatitude(), location.getLongitude(), location.getAltitude()); + } + + /** + * Clone an existing latitude longitude point + * + * @param aLatLng LatLng + */ + public LatLng(LatLng aLatLng) { + this.latitude = aLatLng.latitude; + this.longitude = aLatLng.longitude; + this.altitude = aLatLng.altitude; + } + + protected LatLng(Parcel in) { + latitude = in.readDouble(); + longitude = in.readDouble(); + altitude = in.readDouble(); + } + + public void setLatitude(double latitude) { + this.latitude = latitude; + } + + @Override + public double getLatitude() { + return latitude; + } + + public void setLongitude(double longitude) { + this.longitude = longitude; + } + + @Override + public double getLongitude() { + return longitude; + } + + public void setAltitude(double altitude) { + this.altitude = altitude; + } + + @Override + public double getAltitude() { + return altitude; + } + + /** + * Return a new LatLng object with a wrapped Longitude. This allows original data object + * to remain unchanged. + * + * @return New LatLng object with wrapped Longitude + */ + public LatLng wrap() { + LatLng wrappedVersion = new LatLng(this); + double lon = wrappedVersion.getLongitude(); + if (lon < GeoConstants.MIN_LONGITUDE || lon > GeoConstants.MAX_LONGITUDE) { + wrappedVersion.setLongitude(MathUtils.wrap(wrappedVersion.getLongitude(), GeoConstants.MIN_LONGITUDE, + GeoConstants.MAX_LONGITUDE)); + } + return wrappedVersion; + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + + LatLng latLng = (LatLng) object; + + return Double.compare(latLng.altitude, altitude) == 0 && Double.compare(latLng.latitude, latitude) == 0 + && Double.compare(latLng.longitude, longitude) == 0; + } + + @Override + public int hashCode() { + int result; + long temp; + temp = Double.doubleToLongBits(latitude); + result = (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(longitude); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(altitude); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public String toString() { + return "LatLng [latitude=" + latitude + ", longitude=" + longitude + ", altitude=" + altitude + "]"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeDouble(latitude); + out.writeDouble(longitude); + out.writeDouble(altitude); + } + + /** + * Calculate distance between two points + * + * @param other Other LatLng to compare to + * @return distance in meters + */ + public double distanceTo(LatLng other) { + if (latitude == other.latitude && longitude == other.longitude) { + // return 0.0 to avoid a NaN + return 0.0; + } + + final double a1 = Math.toRadians(this.latitude); + final double a2 = Math.toRadians(this.longitude); + final double b1 = Math.toRadians(other.getLatitude()); + final double b2 = Math.toRadians(other.getLongitude()); + + final double cosa1 = Math.cos(a1); + final double cosb1 = Math.cos(b1); + + final double t1 = cosa1 * Math.cos(a2) * cosb1 * Math.cos(b2); + final double t2 = cosa1 * Math.sin(a2) * cosb1 * Math.sin(b2); + final double t3 = Math.sin(a1) * Math.sin(b1); + final double tt = Math.acos(t1 + t2 + t3); + + return GeoConstants.RADIUS_EARTH_METERS * tt; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java index 2fd28202af..3b92f0f0f5 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java @@ -14,292 +14,296 @@ import java.util.List; */ public class LatLngBounds implements Parcelable { - private final double mLatNorth; - private final double mLatSouth; - private final double mLonEast; - private final double mLonWest; - - /** - * Construct a new LatLngBounds based on its corners, given in NESW - * order. - * - * @param northLatitude Northern Latitude - * @param eastLongitude Eastern Longitude - * @param southLatitude Southern Latitude - * @param westLongitude Western Longitude - */ - LatLngBounds(final double northLatitude, final double eastLongitude, final double southLatitude, final double westLongitude) { - this.mLatNorth = northLatitude; - this.mLonEast = eastLongitude; - this.mLatSouth = southLatitude; - this.mLonWest = westLongitude; + private final double mLatNorth; + private final double mLatSouth; + private final double mLonEast; + private final double mLonWest; + + /** + * Construct a new LatLngBounds based on its corners, given in NESW + * order. + * + * @param northLatitude Northern Latitude + * @param eastLongitude Eastern Longitude + * @param southLatitude Southern Latitude + * @param westLongitude Western Longitude + */ + LatLngBounds(final double northLatitude, final double eastLongitude, final double southLatitude, + final double westLongitude) { + this.mLatNorth = northLatitude; + this.mLonEast = eastLongitude; + this.mLatSouth = southLatitude; + this.mLonWest = westLongitude; + } + + /** + * Calculates the centerpoint of this LatLngBounds by simple interpolation and returns + * it as a point. This is a non-geodesic calculation which is not the geographic center. + * + * @return LatLng center of this LatLngBounds + */ + public LatLng getCenter() { + return new LatLng((this.mLatNorth + this.mLatSouth) / 2, + (this.mLonEast + this.mLonWest) / 2); + } + + public double getLatNorth() { + return this.mLatNorth; + } + + public double getLatSouth() { + return this.mLatSouth; + } + + public double getLonEast() { + return this.mLonEast; + } + + public double getLonWest() { + return this.mLonWest; + } + + /** + * Get the area spanned by this LatLngBounds + * + * @return LatLngSpan area + */ + public LatLngSpan getSpan() { + return new LatLngSpan(getLatitudeSpan(), getLongitudeSpan()); + } + + /** + * Get the absolute distance, in degrees, between the north and + * south boundaries of this LatLngBounds + * + * @return Span distance + */ + public double getLatitudeSpan() { + return Math.abs(this.mLatNorth - this.mLatSouth); + } + + /** + * Get the absolute distance, in degrees, between the west and + * east boundaries of this LatLngBounds + * + * @return Span distance + */ + public double getLongitudeSpan() { + return Math.abs(this.mLonEast - this.mLonWest); + } + + + /** + * Validate if LatLngBounds is empty, determined if absolute distance is + * + * @return boolean indicating if span is empty + */ + public boolean isEmptySpan() { + return getLongitudeSpan() == 0.0 || getLatitudeSpan() == 0.0; + } + + @Override + public String toString() { + return "N:" + this.mLatNorth + "; E:" + this.mLonEast + "; S:" + this.mLatSouth + "; W:" + this.mLonWest; + } + + /** + * Constructs a LatLngBounds that contains all of a list of LatLng + * objects. Empty lists will yield invalid LatLngBounds. + * + * @param latLngs List of LatLng objects + * @return LatLngBounds + */ + static LatLngBounds fromLatLngs(final List<? extends ILatLng> latLngs) { + double minLat = 90; + double minLon = 180; + double maxLat = -90; + double maxLon = -180; + + for (final ILatLng gp : latLngs) { + final double latitude = gp.getLatitude(); + final double longitude = gp.getLongitude(); + + minLat = Math.min(minLat, latitude); + minLon = Math.min(minLon, longitude); + maxLat = Math.max(maxLat, latitude); + maxLon = Math.max(maxLon, longitude); } - /** - * Calculates the centerpoint of this LatLngBounds by simple interpolation and returns - * it as a point. This is a non-geodesic calculation which is not the geographic center. - * - * @return LatLng center of this LatLngBounds - */ - public LatLng getCenter() { - return new LatLng((this.mLatNorth + this.mLatSouth) / 2, - (this.mLonEast + this.mLonWest) / 2); + return new LatLngBounds(maxLat, maxLon, minLat, minLon); + } + + public LatLng[] toLatLngs() { + return new LatLng[] {new LatLng(mLatNorth, mLonEast), new LatLng(mLatSouth, mLonWest)}; + } + + /** + * Determines whether this LatLngBounds matches another one via LatLng. + * + * @param o another object + * @return a boolean indicating whether the LatLngBounds are equal + */ + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; } - - public double getLatNorth() { - return this.mLatNorth; - } - - public double getLatSouth() { - return this.mLatSouth; - } - - public double getLonEast() { - return this.mLonEast; - } - - public double getLonWest() { - return this.mLonWest; - } - - /** - * Get the area spanned by this LatLngBounds - * - * @return LatLngSpan area - */ - public LatLngSpan getSpan() { - return new LatLngSpan(getLatitudeSpan(), getLongitudeSpan()); - } - - /** - * Get the absolute distance, in degrees, between the north and - * south boundaries of this LatLngBounds - * - * @return Span distance - */ - public double getLatitudeSpan() { - return Math.abs(this.mLatNorth - this.mLatSouth); - } - - /** - * Get the absolute distance, in degrees, between the west and - * east boundaries of this LatLngBounds - * - * @return Span distance - */ - public double getLongitudeSpan() { - return Math.abs(this.mLonEast - this.mLonWest); - } - - - /** - * Validate if LatLngBounds is empty, determined if absolute distance is - * - * @return boolean indicating if span is empty - */ - public boolean isEmptySpan() { - return getLongitudeSpan() == 0.0 || getLatitudeSpan() == 0.0; - } - - @Override - public String toString() { - return "N:" + this.mLatNorth + "; E:" + this.mLonEast + "; S:" + this.mLatSouth + "; W:" + this.mLonWest; + if (o instanceof LatLngBounds) { + LatLngBounds other = (LatLngBounds) o; + return mLatNorth == other.getLatNorth() + && mLatSouth == other.getLatSouth() + && mLonEast == other.getLonEast() + && mLonWest == other.getLonWest(); } - - /** - * Constructs a LatLngBounds that contains all of a list of LatLng - * objects. Empty lists will yield invalid LatLngBounds. - * - * @param latLngs List of LatLng objects - * @return LatLngBounds - */ - static LatLngBounds fromLatLngs(final List<? extends ILatLng> latLngs) { - double minLat = 90, - minLon = 180, - maxLat = -90, - maxLon = -180; - - for (final ILatLng gp : latLngs) { - final double latitude = gp.getLatitude(); - final double longitude = gp.getLongitude(); - - minLat = Math.min(minLat, latitude); - minLon = Math.min(minLon, longitude); - maxLat = Math.max(maxLat, latitude); - maxLon = Math.max(maxLon, longitude); - } - - return new LatLngBounds(maxLat, maxLon, minLat, minLon); - } - - public LatLng[] toLatLngs() { - return new LatLng[]{new LatLng(mLatNorth, mLonEast), new LatLng(mLatSouth, mLonWest)}; - } - - /** - * Determines whether this LatLngBounds matches another one via LatLng. - * - * @param o another object - * @return a boolean indicating whether the LatLngBounds are equal - */ - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o instanceof LatLngBounds) { - LatLngBounds other = (LatLngBounds) o; - return mLatNorth == other.getLatNorth() - && mLatSouth == other.getLatSouth() - && mLonEast == other.getLonEast() - && mLonWest == other.getLonWest(); - } - return false; - } - - /** - * Determines whether this LatLngBounds contains a point and the point - * does not touch its boundary. - * - * @param latLng the point which may be contained - * @return true, if the point is contained within the box. - */ - public boolean contains(final ILatLng latLng) { - final double latitude = latLng.getLatitude(); - final double longitude = latLng.getLongitude(); - return ((latitude < this.mLatNorth) - && (latitude > this.mLatSouth)) - && ((longitude < this.mLonEast) - && (longitude > this.mLonWest)); - } - - /** - * Returns a new LatLngBounds that stretches to contain both this and another LatLngBounds. - * - * @param bounds LatLngBounds to add - * @return LatLngBounds - */ - public LatLngBounds union(LatLngBounds bounds) { - return union(bounds.getLatNorth(), bounds.getLonEast(), bounds.getLatSouth(), bounds.getLonWest()); + return false; + } + + /** + * Determines whether this LatLngBounds contains a point and the point + * does not touch its boundary. + * + * @param latLng the point which may be contained + * @return true, if the point is contained within the box. + */ + public boolean contains(final ILatLng latLng) { + final double latitude = latLng.getLatitude(); + final double longitude = latLng.getLongitude(); + return ((latitude < this.mLatNorth) + && (latitude > this.mLatSouth)) + && ((longitude < this.mLonEast) + && (longitude > this.mLonWest)); + } + + /** + * Returns a new LatLngBounds that stretches to contain both this and another LatLngBounds. + * + * @param bounds LatLngBounds to add + * @return LatLngBounds + */ + public LatLngBounds union(LatLngBounds bounds) { + return union(bounds.getLatNorth(), bounds.getLonEast(), bounds.getLatSouth(), bounds.getLonWest()); + } + + /** + * Returns a new LatLngBounds that stretches to include another LatLngBounds, + * given by corner points. + * + * @param lonNorth Northern Longitude + * @param latEast Eastern Latitude + * @param lonSouth Southern Longitude + * @param latWest Western Longitude + * @return BoundingBox + */ + public LatLngBounds union(final double lonNorth, final double latEast, final double lonSouth, final double latWest) { + return new LatLngBounds((this.mLatNorth < lonNorth) ? lonNorth : this.mLatNorth, + (this.mLonEast < latEast) ? latEast : this.mLonEast, + (this.mLatSouth > lonSouth) ? lonSouth : this.mLatSouth, + (this.mLonWest > latWest) ? latWest : this.mLonWest); + } + + /** + * Returns a new LatLngBounds that is the intersection of this with another box + * + * @param box LatLngBounds to intersect with + * @return LatLngBounds + */ + public LatLngBounds intersect(LatLngBounds box) { + double minLatWest = Math.max(getLonWest(), box.getLonWest()); + double maxLatEast = Math.min(getLonEast(), box.getLonEast()); + if (maxLatEast > minLatWest) { + double minLonSouth = Math.max(getLatSouth(), box.getLatSouth()); + double maxLonNorth = Math.min(getLatNorth(), box.getLatNorth()); + if (maxLonNorth > minLonSouth) { + return new LatLngBounds(maxLonNorth, maxLatEast, minLonSouth, minLatWest); + } } - - /** - * Returns a new LatLngBounds that stretches to include another LatLngBounds, - * given by corner points. - * - * @param lonNorth Northern Longitude - * @param latEast Eastern Latitude - * @param lonSouth Southern Longitude - * @param latWest Western Longitude - * @return BoundingBox - */ - public LatLngBounds union(final double lonNorth, final double latEast, final double lonSouth, final double latWest) { - return new LatLngBounds((this.mLatNorth < lonNorth) ? lonNorth : this.mLatNorth, - (this.mLonEast < latEast) ? latEast : this.mLonEast, - (this.mLatSouth > lonSouth) ? lonSouth : this.mLatSouth, - (this.mLonWest > latWest) ? latWest : this.mLonWest); - } - - /** - * Returns a new LatLngBounds that is the intersection of this with another box - * - * @param box LatLngBounds to intersect with - * @return LatLngBounds - */ - public LatLngBounds intersect(LatLngBounds box) { - double minLatWest = Math.max(getLonWest(), box.getLonWest()); - double maxLatEast = Math.min(getLonEast(), box.getLonEast()); - if (maxLatEast > minLatWest) { - double minLonSouth = Math.max(getLatSouth(), box.getLatSouth()); - double maxLonNorth = Math.min(getLatNorth(), box.getLatNorth()); - if (maxLonNorth > minLonSouth) { - return new LatLngBounds(maxLonNorth, maxLatEast, minLonSouth, minLatWest); - } - } - return null; - } - - /** - * Returns a new LatLngBounds that is the intersection of this with another LatLngBounds - * - * @param northLatitude Northern Longitude - * @param eastLongitude Eastern Latitude - * @param southLatitude Southern Longitude - * @param westLongitude Western Latitude - * @return LatLngBounds - */ - public LatLngBounds intersect(double northLatitude, double eastLongitude, double southLatitude, double westLongitude) { - return intersect(new LatLngBounds(northLatitude, eastLongitude, southLatitude, westLongitude)); - } - - public static final Parcelable.Creator<LatLngBounds> CREATOR = - new Parcelable.Creator<LatLngBounds>() { - @Override - public LatLngBounds createFromParcel(final Parcel in) { - return readFromParcel(in); - } - - @Override - public LatLngBounds[] newArray(final int size) { - return new LatLngBounds[size]; - } - }; - - @Override - public int hashCode() { - return (int) ((mLatNorth + 90) - + ((mLatSouth + 90) * 1000) - + ((mLonEast + 180) * 1000000) - + ((mLonEast + 180) * 1000000000)); - } - - @Override - public int describeContents() { - return 0; + return null; + } + + /** + * Returns a new LatLngBounds that is the intersection of this with another LatLngBounds + * + * @param northLatitude Northern Longitude + * @param eastLongitude Eastern Latitude + * @param southLatitude Southern Longitude + * @param westLongitude Western Latitude + * @return LatLngBounds + */ + public LatLngBounds intersect(double northLatitude, double eastLongitude, double southLatitude, + double westLongitude) { + return intersect(new LatLngBounds(northLatitude, eastLongitude, southLatitude, westLongitude)); + } + + public static final Parcelable.Creator<LatLngBounds> CREATOR = + new Parcelable.Creator<LatLngBounds>() { + @Override + public LatLngBounds createFromParcel(final Parcel in) { + return readFromParcel(in); + } + + @Override + public LatLngBounds[] newArray(final int size) { + return new LatLngBounds[size]; + } + }; + + @Override + public int hashCode() { + return (int) ((mLatNorth + 90) + + ((mLatSouth + 90) * 1000) + + ((mLonEast + 180) * 1000000) + + ((mLonEast + 180) * 1000000000)); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(final Parcel out, final int arg1) { + out.writeDouble(this.mLatNorth); + out.writeDouble(this.mLonEast); + out.writeDouble(this.mLatSouth); + out.writeDouble(this.mLonWest); + } + + private static LatLngBounds readFromParcel(final Parcel in) { + final double lonNorth = in.readDouble(); + final double latEast = in.readDouble(); + final double lonSouth = in.readDouble(); + final double latWest = in.readDouble(); + return new LatLngBounds(lonNorth, latEast, lonSouth, latWest); + } + + /** + * Builder for composing LatLngBounds objects. + */ + public static final class Builder { + + private List<LatLng> mLatLngList; + + public Builder() { + mLatLngList = new ArrayList<>(); } - @Override - public void writeToParcel(final Parcel out, final int arg1) { - out.writeDouble(this.mLatNorth); - out.writeDouble(this.mLonEast); - out.writeDouble(this.mLatSouth); - out.writeDouble(this.mLonWest); + public LatLngBounds build() { + if (mLatLngList.size() < 2) { + throw new InvalidLatLngBoundsException(mLatLngList.size()); + } + return LatLngBounds.fromLatLngs(mLatLngList); } - private static LatLngBounds readFromParcel(final Parcel in) { - final double lonNorth = in.readDouble(); - final double latEast = in.readDouble(); - final double lonSouth = in.readDouble(); - final double latWest = in.readDouble(); - return new LatLngBounds(lonNorth, latEast, lonSouth, latWest); + public Builder includes(List<LatLng> latLngs) { + for (LatLng point : latLngs) { + mLatLngList.add(point); + } + return this; } - /** - * Builder for composing LatLngBounds objects. - */ - public static final class Builder { - - private List<LatLng> mLatLngList; - - public Builder() { - mLatLngList = new ArrayList<>(); - } - - public LatLngBounds build() { - if (mLatLngList.size() < 2) { - throw new InvalidLatLngBoundsException(mLatLngList.size()); - } - return LatLngBounds.fromLatLngs(mLatLngList); - } - - public Builder includes(List<LatLng> latLngs){ - for (LatLng point : latLngs) { - mLatLngList.add(point); - } - return this; - } - - public Builder include(@NonNull LatLng latLng) { - mLatLngList.add(latLng); - return this; - } + public Builder include(@NonNull LatLng latLng) { + mLatLngList.add(latLng); + return this; } + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.java index 81e52666f6..dd7fef4d23 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.java @@ -9,93 +9,95 @@ import android.support.annotation.NonNull; */ public class LatLngSpan implements Parcelable { - private double mLatitudeSpan; - private double mLongitudeSpan; + private double mLatitudeSpan; + private double mLongitudeSpan; - private LatLngSpan(@NonNull Parcel in) { - mLatitudeSpan = in.readDouble(); - mLongitudeSpan = in.readDouble(); - } + private LatLngSpan(@NonNull Parcel in) { + mLatitudeSpan = in.readDouble(); + mLongitudeSpan = in.readDouble(); + } - /** - * Creates a LatLgnSpan. - * - * @param latitudeSpan The span used for latitude. - * @param longitudeSpan The span used for longitude. - */ - public LatLngSpan(double latitudeSpan, double longitudeSpan) { - mLatitudeSpan = latitudeSpan; - mLongitudeSpan = longitudeSpan; - } + /** + * Creates a LatLgnSpan. + * + * @param latitudeSpan The span used for latitude. + * @param longitudeSpan The span used for longitude. + */ + public LatLngSpan(double latitudeSpan, double longitudeSpan) { + mLatitudeSpan = latitudeSpan; + mLongitudeSpan = longitudeSpan; + } - /** - * Returns the latitude span. - * - * @return The latitude span. - */ - public double getLatitudeSpan() { - return mLatitudeSpan; - } + /** + * Returns the latitude span. + * + * @return The latitude span. + */ + public double getLatitudeSpan() { + return mLatitudeSpan; + } - /** - * Sets the latitude span. - * - * @param latitudeSpan The latitude span to set. - */ - public void setLatitudeSpan(double latitudeSpan) { - mLatitudeSpan = latitudeSpan; - } + /** + * Sets the latitude span. + * + * @param latitudeSpan The latitude span to set. + */ + public void setLatitudeSpan(double latitudeSpan) { + mLatitudeSpan = latitudeSpan; + } - /** - * Returns to longitude span. - * - * @return The longitude span. - */ - public double getLongitudeSpan() { - return mLongitudeSpan; - } + /** + * Returns to longitude span. + * + * @return The longitude span. + */ + public double getLongitudeSpan() { + return mLongitudeSpan; + } - /** - * Sets the longitude span. - * - * @param longitudeSpan The longitude span to set. - */ - public void setLongitudeSpan(double longitudeSpan) { - mLongitudeSpan = longitudeSpan; - } + /** + * Sets the longitude span. + * + * @param longitudeSpan The longitude span to set. + */ + public void setLongitudeSpan(double longitudeSpan) { + mLongitudeSpan = longitudeSpan; + } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o instanceof LatLngSpan) { - LatLngSpan other = (LatLngSpan) o; - return mLongitudeSpan == other.getLongitudeSpan() - && mLatitudeSpan == other.getLatitudeSpan(); - } - return false; + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o instanceof LatLngSpan) { + LatLngSpan other = (LatLngSpan) o; + return mLongitudeSpan == other.getLongitudeSpan() + && mLatitudeSpan == other.getLatitudeSpan(); } + return false; + } - public static final Parcelable.Creator<LatLngSpan> CREATOR = - new Parcelable.Creator<LatLngSpan>() { - @Override - public LatLngSpan createFromParcel(Parcel in) { - return new LatLngSpan(in); - } + public static final Parcelable.Creator<LatLngSpan> CREATOR = + new Parcelable.Creator<LatLngSpan>() { + @Override + public LatLngSpan createFromParcel(Parcel in) { + return new LatLngSpan(in); + } - @Override - public LatLngSpan[] newArray(int size) { - return new LatLngSpan[size]; - } - }; + @Override + public LatLngSpan[] newArray(int size) { + return new LatLngSpan[size]; + } + }; - @Override - public int describeContents() { - return 0; - } + @Override + public int describeContents() { + return 0; + } - @Override - public void writeToParcel(Parcel out, int arg1) { - out.writeDouble(mLatitudeSpan); - out.writeDouble(mLongitudeSpan); - } + @Override + public void writeToParcel(Parcel out, int arg1) { + out.writeDouble(mLatitudeSpan); + out.writeDouble(mLongitudeSpan); + } }
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ProjectedMeters.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ProjectedMeters.java index 1f1417b4b6..761d8f2a8b 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ProjectedMeters.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/ProjectedMeters.java @@ -13,104 +13,105 @@ import android.os.Parcelable; */ public class ProjectedMeters implements IProjectedMeters, Parcelable { - public static final Creator<ProjectedMeters> CREATOR = new Creator<ProjectedMeters>() { - public ProjectedMeters createFromParcel(Parcel in) { - return new ProjectedMeters(in); - } - - public ProjectedMeters[] newArray(int size) { - return new ProjectedMeters[size]; - } - }; - - private double northing; - private double easting; - - /** - * Creates a ProjectedMeters based on projected meters in north and east direction. - * - * @param northing the northing in meters - * @param easting the easting in meters - */ - public ProjectedMeters(double northing, double easting) { - this.northing = northing; - this.easting = easting; + public static final Creator<ProjectedMeters> CREATOR = new Creator<ProjectedMeters>() { + public ProjectedMeters createFromParcel(Parcel in) { + return new ProjectedMeters(in); } - /** - * Creates a ProjecteMeters based on another set of projected meters. - * - * @param projectedMeters The projected meters to be based on. - */ - public ProjectedMeters(ProjectedMeters projectedMeters) { - this.northing = projectedMeters.northing; - this.easting = projectedMeters.easting; + public ProjectedMeters[] newArray(int size) { + return new ProjectedMeters[size]; } - - private ProjectedMeters(Parcel in) { - northing = in.readDouble(); - easting = in.readDouble(); - } - - /** - * Get projected meters in north direction. - * - * @return Projected meters in north. - */ - @Override - public double getNorthing() { - return northing; - } - - /** - * Get projected meters in east direction. - * - * @return Projected meters in east. - */ - @Override - public double getEasting() { - return easting; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - ProjectedMeters projectedMeters = (ProjectedMeters) o; - - return Double.compare(projectedMeters.easting, easting) == 0 && Double.compare(projectedMeters.northing, northing) == 0; - - } - - @Override - public int hashCode() { - int result; - long temp; - temp = Double.doubleToLongBits(easting); - result = (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(northing); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - return result; + }; + + private double northing; + private double easting; + + /** + * Creates a ProjectedMeters based on projected meters in north and east direction. + * + * @param northing the northing in meters + * @param easting the easting in meters + */ + public ProjectedMeters(double northing, double easting) { + this.northing = northing; + this.easting = easting; + } + + /** + * Creates a ProjecteMeters based on another set of projected meters. + * + * @param projectedMeters The projected meters to be based on. + */ + public ProjectedMeters(ProjectedMeters projectedMeters) { + this.northing = projectedMeters.northing; + this.easting = projectedMeters.easting; + } + + private ProjectedMeters(Parcel in) { + northing = in.readDouble(); + easting = in.readDouble(); + } + + /** + * Get projected meters in north direction. + * + * @return Projected meters in north. + */ + @Override + public double getNorthing() { + return northing; + } + + /** + * Get projected meters in east direction. + * + * @return Projected meters in east. + */ + @Override + public double getEasting() { + return easting; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; } - - @Override - public String toString() { - return "ProjectedMeters [northing=" + northing + ", easting=" + easting + "]"; - } - - @Override - public int describeContents() { - return 0; + if (o == null || getClass() != o.getClass()) { + return false; } - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeDouble(northing); - out.writeDouble(easting); - } + ProjectedMeters projectedMeters = (ProjectedMeters) o; + + return Double.compare(projectedMeters.easting, easting) == 0 + && Double.compare(projectedMeters.northing, northing) == 0; + + } + + @Override + public int hashCode() { + int result; + long temp; + temp = Double.doubleToLongBits(easting); + result = (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(northing); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public String toString() { + return "ProjectedMeters [northing=" + northing + ", easting=" + easting + "]"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeDouble(northing); + out.writeDouble(easting); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/VisibleRegion.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/VisibleRegion.java index de562c3632..45300f248c 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/VisibleRegion.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/VisibleRegion.java @@ -12,118 +12,119 @@ import android.os.Parcelable; */ public class VisibleRegion implements Parcelable { - /** - * LatLng object that defines the far left corner of the camera. - */ - public final LatLng farLeft; - - /** - * LatLng object that defines the far right corner of the camera. - */ - public final LatLng farRight; - - /** - * LatLng object that defines the bottom left corner of the camera. - */ - public final LatLng nearLeft; - - /** - * LatLng object that defines the bottom right corner of the camera. - */ - public final LatLng nearRight; - - /** - * The smallest bounding box that includes the visible region defined in this class. - */ - public final LatLngBounds latLngBounds; - - private VisibleRegion(Parcel in) { - this.farLeft = in.readParcelable(LatLng.class.getClassLoader()); - this.farRight = in.readParcelable(LatLng.class.getClassLoader()); - this.nearLeft = in.readParcelable(LatLng.class.getClassLoader()); - this.nearRight = in.readParcelable(LatLng.class.getClassLoader()); - this.latLngBounds = in.readParcelable(LatLngBounds.class.getClassLoader()); + /** + * LatLng object that defines the far left corner of the camera. + */ + public final LatLng farLeft; + + /** + * LatLng object that defines the far right corner of the camera. + */ + public final LatLng farRight; + + /** + * LatLng object that defines the bottom left corner of the camera. + */ + public final LatLng nearLeft; + + /** + * LatLng object that defines the bottom right corner of the camera. + */ + public final LatLng nearRight; + + /** + * The smallest bounding box that includes the visible region defined in this class. + */ + public final LatLngBounds latLngBounds; + + private VisibleRegion(Parcel in) { + this.farLeft = in.readParcelable(LatLng.class.getClassLoader()); + this.farRight = in.readParcelable(LatLng.class.getClassLoader()); + this.nearLeft = in.readParcelable(LatLng.class.getClassLoader()); + this.nearRight = in.readParcelable(LatLng.class.getClassLoader()); + this.latLngBounds = in.readParcelable(LatLngBounds.class.getClassLoader()); + } + + /** + * Creates a new VisibleRegion given the four corners of the camera. + * + * @param farLeft A LatLng object containing the latitude and longitude of the near left corner of the region. + * @param farRight A LatLng object containing the latitude and longitude of the near left corner of the region. + * @param nearLeft A LatLng object containing the latitude and longitude of the near left corner of the region. + * @param nearRight A LatLng object containing the latitude and longitude of the near left corner of the region. + * @param latLngBounds The smallest bounding box that includes the visible region defined in this class. + */ + public VisibleRegion(LatLng farLeft, LatLng farRight, LatLng nearLeft, LatLng nearRight, LatLngBounds latLngBounds) { + this.farLeft = farLeft; + this.farRight = farRight; + this.nearLeft = nearLeft; + this.nearRight = nearRight; + this.latLngBounds = latLngBounds; + } + + /** + * Compares this VisibleRegion to another object. + * If the other object is actually a pointer to this object, + * or if all four corners and the bounds of the two objects are the same, + * this method returns true. Otherwise, this method returns false. + * + * @param o The Object to compare with. + * @return true if both objects are the same object. + */ + @Override + public boolean equals(Object o) { + if (!(o instanceof VisibleRegion)) { + return false; } - - /** - * Creates a new VisibleRegion given the four corners of the camera. - * - * @param farLeft A LatLng object containing the latitude and longitude of the near left corner of the region. - * @param farRight A LatLng object containing the latitude and longitude of the near left corner of the region. - * @param nearLeft A LatLng object containing the latitude and longitude of the near left corner of the region. - * @param nearRight A LatLng object containing the latitude and longitude of the near left corner of the region. - * @param latLngBounds The smallest bounding box that includes the visible region defined in this class. - */ - public VisibleRegion(LatLng farLeft, LatLng farRight, LatLng nearLeft, LatLng nearRight, LatLngBounds latLngBounds) { - this.farLeft = farLeft; - this.farRight = farRight; - this.nearLeft = nearLeft; - this.nearRight = nearRight; - this.latLngBounds = latLngBounds; - } - - /** - * Compares this VisibleRegion to another object. - * If the other object is actually a pointer to this object, - * or if all four corners and the bounds of the two objects are the same, - * this method returns true. Otherwise, this method returns false. - * - * @param o The Object to compare with. - * @return true if both objects are the same object. - */ - @Override - public boolean equals(Object o) { - if (!(o instanceof VisibleRegion)) { - return false; - } - if (o == this) { - return true; - } - - VisibleRegion visibleRegion = (VisibleRegion) o; - return farLeft.equals(visibleRegion.farLeft) - && farRight.equals(visibleRegion.farRight) - && nearLeft.equals(visibleRegion.nearLeft) - && nearRight.equals(visibleRegion.nearRight) - && latLngBounds.equals(visibleRegion.latLngBounds); - } - - @Override - public String toString() { - return "[farLeft [" + farLeft + "], farRight [" + farRight + "], nearLeft [" + nearLeft + "], nearRight [" + nearRight + "], latLngBounds [" + latLngBounds + "]]"; - } - - @Override - public int hashCode() { - return ((farLeft.hashCode() + 90) - + ((farRight.hashCode() + 90) * 1000) - + ((nearLeft.hashCode() + 180) * 1000000) - + ((nearRight.hashCode() + 180) * 1000000000)); - } - - @Override - public int describeContents() { - return 0; + if (o == this) { + return true; } - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeParcelable(farLeft, flags); - out.writeParcelable(farRight, flags); - out.writeParcelable(nearLeft, flags); - out.writeParcelable(nearRight, flags); - out.writeParcelable(latLngBounds, flags); - } - - public static final Parcelable.Creator<VisibleRegion> CREATOR - = new Parcelable.Creator<VisibleRegion>() { - public VisibleRegion createFromParcel(Parcel in) { - return new VisibleRegion(in); - } - - public VisibleRegion[] newArray(int size) { - return new VisibleRegion[size]; - } + VisibleRegion visibleRegion = (VisibleRegion) o; + return farLeft.equals(visibleRegion.farLeft) + && farRight.equals(visibleRegion.farRight) + && nearLeft.equals(visibleRegion.nearLeft) + && nearRight.equals(visibleRegion.nearRight) + && latLngBounds.equals(visibleRegion.latLngBounds); + } + + @Override + public String toString() { + return "[farLeft [" + farLeft + "], farRight [" + farRight + "], nearLeft [" + nearLeft + "], nearRight [" + + nearRight + "], latLngBounds [" + latLngBounds + "]]"; + } + + @Override + public int hashCode() { + return ((farLeft.hashCode() + 90) + + ((farRight.hashCode() + 90) * 1000) + + ((nearLeft.hashCode() + 180) * 1000000) + + ((nearRight.hashCode() + 180) * 1000000000)); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeParcelable(farLeft, flags); + out.writeParcelable(farRight, flags); + out.writeParcelable(nearLeft, flags); + out.writeParcelable(nearRight, flags); + out.writeParcelable(latLngBounds, flags); + } + + public static final Parcelable.Creator<VisibleRegion> CREATOR = + new Parcelable.Creator<VisibleRegion>() { + public VisibleRegion createFromParcel(Parcel in) { + return new VisibleRegion(in); + } + + public VisibleRegion[] newArray(int size) { + return new VisibleRegion[size]; + } }; }
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java index 991bb49ab3..ef6b9670db 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java @@ -5,6 +5,7 @@ import android.content.Context; import android.content.pm.PackageInfo; import android.os.Build; import android.text.TextUtils; + import timber.log.Timber; import com.mapbox.mapboxsdk.BuildConfig; @@ -31,172 +32,175 @@ import okhttp3.internal.Util; class HTTPRequest implements Callback { - private static OkHttpClient mClient = new OkHttpClient(); - private String USER_AGENT_STRING = null; - - private static final int CONNECTION_ERROR = 0; - private static final int TEMPORARY_ERROR = 1; - private static final int PERMANENT_ERROR = 2; - - // Reentrancy is not needed, but "Lock" is an - // abstract class. - private ReentrantLock mLock = new ReentrantLock(); - - private long mNativePtr = 0; - - private Call mCall; - private Request mRequest; - - private native void nativeOnFailure(int type, String message); - - private native void nativeOnResponse(int code, String etag, String modified, String cacheControl, String expires, String retryAfter, String xRateLimitReset, byte[] body); - - private HTTPRequest(long nativePtr, String resourceUrl, String etag, String modified) { - mNativePtr = nativePtr; - - try { - // Don't try a request if we aren't connected - if (!MapboxAccountManager.getInstance().isConnected()) { - throw new NoRouteToHostException("No Internet connection available."); - } - - HttpUrl httpUrl = HttpUrl.parse(resourceUrl); - final String host = httpUrl.host().toLowerCase(MapboxConstants.MAPBOX_LOCALE); - if (host.equals("mapbox.com") || host.endsWith(".mapbox.com") || host.equals("mapbox.cn") || host.endsWith(".mapbox.cn")) { - if (httpUrl.querySize() == 0) { - resourceUrl = resourceUrl + "?"; - } else { - resourceUrl = resourceUrl + "&"; - } - resourceUrl = resourceUrl + "events=true"; - } - - Request.Builder builder = new Request.Builder() - .url(resourceUrl) - .tag(resourceUrl.toLowerCase(MapboxConstants.MAPBOX_LOCALE)) - .addHeader("User-Agent", getUserAgent()); - if (etag.length() > 0) { - builder = builder.addHeader("If-None-Match", etag); - } else if (modified.length() > 0) { - builder = builder.addHeader("If-Modified-Since", modified); - } - mRequest = builder.build(); - mCall = mClient.newCall(mRequest); - mCall.enqueue(this); - } catch (Exception e) { - onFailure(e); - } - } + private static OkHttpClient mClient = new OkHttpClient(); + private String USER_AGENT_STRING = null; - public void cancel() { - // mCall can be null if the constructor gets aborted (e.g, under a NoRouteToHostException). - if (mCall != null) { - mCall.cancel(); - } + private static final int CONNECTION_ERROR = 0; + private static final int TEMPORARY_ERROR = 1; + private static final int PERMANENT_ERROR = 2; - // TODO: We need a lock here because we can try - // to cancel at the same time the request is getting - // answered on the OkHTTP thread. We could get rid of - // this lock by using Runnable when we move Android - // implementation of mbgl::RunLoop to Looper. - mLock.lock(); - mNativePtr = 0; - mLock.unlock(); - } + // Reentrancy is not needed, but "Lock" is an + // abstract class. + private ReentrantLock mLock = new ReentrantLock(); - @Override - public void onResponse(Call call, Response response) throws IOException { - if (response.isSuccessful()) { - Timber.v(String.format("[HTTP] Request was successful (code = %d).", response.code())); - } else { - // We don't want to call this unsuccessful because a 304 isn't really an error - String message = !TextUtils.isEmpty(response.message()) ? response.message() : "No additional information"; - Timber.d(String.format( - "[HTTP] Request with response code = %d: %s", - response.code(), message)); - } + private long mNativePtr = 0; - byte[] body; - try { - body = response.body().bytes(); - } catch (IOException e) { - onFailure(e); - //throw e; - return; - } finally { - response.body().close(); - } + private Call mCall; + private Request mRequest; - mLock.lock(); - if (mNativePtr != 0) { - nativeOnResponse(response.code(), - response.header("ETag"), - response.header("Last-Modified"), - response.header("Cache-Control"), - response.header("Expires"), - response.header("Retry-After"), - response.header("x-rate-limit-reset"), - body); - } - mLock.unlock(); - } + private native void nativeOnFailure(int type, String message); - @Override - public void onFailure(Call call, IOException e) { - onFailure(e); - } + private native void nativeOnResponse(int code, String etag, String modified, String cacheControl, String expires, + String retryAfter, String xRateLimitReset, byte[] body); - private void onFailure(Exception e) { - int type = PERMANENT_ERROR; - if ((e instanceof NoRouteToHostException) || (e instanceof UnknownHostException) || (e instanceof SocketException) || (e instanceof ProtocolException) || (e instanceof SSLException)) { - type = CONNECTION_ERROR; - } else if ((e instanceof InterruptedIOException)) { - type = TEMPORARY_ERROR; - } + private HTTPRequest(long nativePtr, String resourceUrl, String etag, String modified) { + mNativePtr = nativePtr; - String errorMessage = e.getMessage() != null ? e.getMessage() : "Error processing the request"; + try { + // Don't try a request if we aren't connected + if (!MapboxAccountManager.getInstance().isConnected()) { + throw new NoRouteToHostException("No Internet connection available."); + } - if (type == TEMPORARY_ERROR) { - Timber.d(String.format(MapboxConstants.MAPBOX_LOCALE, - "Request failed due to a temporary error: %s", errorMessage)); - } else if (type == CONNECTION_ERROR) { - Timber.i(String.format(MapboxConstants.MAPBOX_LOCALE, - "Request failed due to a connection error: %s", errorMessage)); + HttpUrl httpUrl = HttpUrl.parse(resourceUrl); + final String host = httpUrl.host().toLowerCase(MapboxConstants.MAPBOX_LOCALE); + if (host.equals("mapbox.com") || host.endsWith(".mapbox.com") || host.equals("mapbox.cn") + || host.endsWith(".mapbox.cn")) { + if (httpUrl.querySize() == 0) { + resourceUrl = resourceUrl + "?"; } else { - // PERMANENT_ERROR - Timber.w(String.format(MapboxConstants.MAPBOX_LOCALE, - "Request failed due to a permanent error: %s", errorMessage)); + resourceUrl = resourceUrl + "&"; } + resourceUrl = resourceUrl + "events=true"; + } + + Request.Builder builder = new Request.Builder() + .url(resourceUrl) + .tag(resourceUrl.toLowerCase(MapboxConstants.MAPBOX_LOCALE)) + .addHeader("User-Agent", getUserAgent()); + if (etag.length() > 0) { + builder = builder.addHeader("If-None-Match", etag); + } else if (modified.length() > 0) { + builder = builder.addHeader("If-Modified-Since", modified); + } + mRequest = builder.build(); + mCall = mClient.newCall(mRequest); + mCall.enqueue(this); + } catch (Exception exception) { + onFailure(exception); + } + } - mLock.lock(); - if (mNativePtr != 0) { - nativeOnFailure(type, errorMessage); - } - mLock.unlock(); + public void cancel() { + // mCall can be null if the constructor gets aborted (e.g, under a NoRouteToHostException). + if (mCall != null) { + mCall.cancel(); } - private String getUserAgent() { - if (USER_AGENT_STRING == null) { - return USER_AGENT_STRING = Util.toHumanReadableAscii( - String.format("%s %s (%s) Android/%s (%s)", - getApplicationIdentifier(), - BuildConfig.MAPBOX_VERSION_STRING, - BuildConfig.GIT_REVISION_SHORT, - Build.VERSION.SDK_INT, - Build.CPU_ABI) - ); - } else { - return USER_AGENT_STRING; - } + // TODO: We need a lock here because we can try + // to cancel at the same time the request is getting + // answered on the OkHTTP thread. We could get rid of + // this lock by using Runnable when we move Android + // implementation of mbgl::RunLoop to Looper. + mLock.lock(); + mNativePtr = 0; + mLock.unlock(); + } + + @Override + public void onResponse(Call call, Response response) throws IOException { + if (response.isSuccessful()) { + Timber.v(String.format("[HTTP] Request was successful (code = %d).", response.code())); + } else { + // We don't want to call this unsuccessful because a 304 isn't really an error + String message = !TextUtils.isEmpty(response.message()) ? response.message() : "No additional information"; + Timber.d(String.format( + "[HTTP] Request with response code = %d: %s", + response.code(), message)); } - private String getApplicationIdentifier() { - try { - Context context = MapboxAccountManager.getInstance().getApplicationContext(); - PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); - return String.format("%s/%s (%s)", context.getPackageName(), packageInfo.versionName, packageInfo.versionCode); - } catch (Exception e) { - return ""; - } + byte[] body; + try { + body = response.body().bytes(); + } catch (IOException ioException) { + onFailure(ioException); + //throw ioException; + return; + } finally { + response.body().close(); + } + + mLock.lock(); + if (mNativePtr != 0) { + nativeOnResponse(response.code(), + response.header("ETag"), + response.header("Last-Modified"), + response.header("Cache-Control"), + response.header("Expires"), + response.header("Retry-After"), + response.header("x-rate-limit-reset"), + body); + } + mLock.unlock(); + } + + @Override + public void onFailure(Call call, IOException e) { + onFailure(e); + } + + private void onFailure(Exception e) { + int type = PERMANENT_ERROR; + if ((e instanceof NoRouteToHostException) || (e instanceof UnknownHostException) || (e instanceof SocketException) + || (e instanceof ProtocolException) || (e instanceof SSLException)) { + type = CONNECTION_ERROR; + } else if ((e instanceof InterruptedIOException)) { + type = TEMPORARY_ERROR; + } + + String errorMessage = e.getMessage() != null ? e.getMessage() : "Error processing the request"; + + if (type == TEMPORARY_ERROR) { + Timber.d(String.format(MapboxConstants.MAPBOX_LOCALE, + "Request failed due to a temporary error: %s", errorMessage)); + } else if (type == CONNECTION_ERROR) { + Timber.i(String.format(MapboxConstants.MAPBOX_LOCALE, + "Request failed due to a connection error: %s", errorMessage)); + } else { + // PERMANENT_ERROR + Timber.w(String.format(MapboxConstants.MAPBOX_LOCALE, + "Request failed due to a permanent error: %s", errorMessage)); + } + + mLock.lock(); + if (mNativePtr != 0) { + nativeOnFailure(type, errorMessage); + } + mLock.unlock(); + } + + private String getUserAgent() { + if (USER_AGENT_STRING == null) { + return USER_AGENT_STRING = Util.toHumanReadableAscii( + String.format("%s %s (%s) Android/%s (%s)", + getApplicationIdentifier(), + BuildConfig.MAPBOX_VERSION_STRING, + BuildConfig.GIT_REVISION_SHORT, + Build.VERSION.SDK_INT, + Build.CPU_ABI) + ); + } else { + return USER_AGENT_STRING; + } + } + + private String getApplicationIdentifier() { + try { + Context context = MapboxAccountManager.getInstance().getApplicationContext(); + PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); + return String.format("%s/%s (%s)", context.getPackageName(), packageInfo.versionName, packageInfo.versionCode); + } catch (Exception exception) { + return ""; } + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationListener.java index eb8c4100dc..7d86d8b096 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationListener.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationListener.java @@ -7,10 +7,11 @@ import android.location.Location; */ public interface LocationListener { - /** - * Callback method for receiving location updates from LocationServices. - * @param location The new Location data - */ - void onLocationChanged(Location location); + /** + * Callback method for receiving location updates from LocationServices. + * + * @param location The new Location data + */ + void onLocationChanged(Location location); } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationServices.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationServices.java index 6b8cdd1b76..666dcb565f 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationServices.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationServices.java @@ -8,6 +8,7 @@ import android.location.Location; import android.location.LocationManager; import android.support.annotation.NonNull; import android.support.v4.content.ContextCompat; + import timber.log.Timber; import com.mapbox.mapboxsdk.telemetry.TelemetryLocationReceiver; @@ -19,169 +20,174 @@ import java.util.concurrent.CopyOnWriteArrayList; /** * Manages locational updates. Contains methods to register and unregister location listeners. * <ul> - * <li>You can register a {@link LocationListener} with {@link #addLocationListener(LocationListener)} to receive location updates.</li> + * <li>You can register a {@link LocationListener} with {@link #addLocationListener(LocationListener)} to receive + * location updates.</li> * <li> You can unregister a {@link LocationListener} with {@link #removeLocationListener(LocationListener)}.</li> * </ul> * <p> - * Note: If registering a listener in your Activity.onStart() implementation, you should unregister it in Activity.onStop(). - * (You won't receive location updates when paused, and this will cut down on unnecessary system overhead). - * Do not unregister in Activity.onSaveInstanceState(), because this won't be called if the user moves back in the history stack. + * Note: If registering a listener in your Activity.onStart() implementation, you should unregister it in + * Activity.onStop(). (You won't receive location updates when paused, and this will cut down on unnecessary system + * overhead). Do not unregister in Activity.onSaveInstanceState(), because this won't be called if the user moves back + * in the history stack. * </p> */ public class LocationServices implements com.mapzen.android.lost.api.LocationListener { - private static LocationServices instance; - - private Context context; - private LostApiClient locationClient; - private Location lastLocation; - - private CopyOnWriteArrayList<LocationListener> locationListeners; - - private boolean isGPSEnabled; - - /** - * Private constructor for singleton LocationServices - */ - private LocationServices(Context context) { - super(); - this.context = context; - // Setup location services - locationClient = new LostApiClient.Builder(context).build(); - locationListeners = new CopyOnWriteArrayList<>(); + private static LocationServices instance; + + private Context context; + private LostApiClient locationClient; + private Location lastLocation; + + private CopyOnWriteArrayList<LocationListener> locationListeners; + + private boolean isGpsEnabled; + + /** + * Private constructor for singleton LocationServices + */ + private LocationServices(Context context) { + super(); + this.context = context; + // Setup location services + locationClient = new LostApiClient.Builder(context).build(); + locationListeners = new CopyOnWriteArrayList<>(); + } + + /** + * Primary (singleton) access method for LocationServices + * + * @param context Context + * @return LocationServices + */ + public static LocationServices getLocationServices(@NonNull final Context context) { + if (instance == null) { + instance = new LocationServices(context.getApplicationContext()); } - - /** - * Primary (singleton) access method for LocationServices - * - * @param context Context - * @return LocationServices - */ - public static LocationServices getLocationServices(@NonNull final Context context) { - if (instance == null) { - instance = new LocationServices(context.getApplicationContext()); - } - return instance; + return instance; + } + + /** + * Enabled / Disable GPS focused location tracking + * + * @param enableGPS true if GPS is to be enabled, false if GPS is to be disabled + */ + public void toggleGPS(boolean enableGPS) { + if (!areLocationPermissionsGranted()) { + Timber.w("Location Permissions Not Granted Yet. Try again after requesting."); + return; } - /** - * Enabled / Disable GPS focused location tracking - * - * @param enableGPS true if GPS is to be enabled, false if GPS is to be disabled - */ - public void toggleGPS(boolean enableGPS) { - if (!areLocationPermissionsGranted()) { - Timber.w("Location Permissions Not Granted Yet. Try again after requesting."); - return; - } - - // Disconnect - if (locationClient.isConnected()) { - // Disconnect first to ensure that the new requests are GPS - com.mapzen.android.lost.api.LocationServices.FusedLocationApi.removeLocationUpdates(this); - locationClient.disconnect(); - } - - // Setup Fresh - locationClient.connect(); - Location lastLocation = com.mapzen.android.lost.api.LocationServices.FusedLocationApi.getLastLocation(); - if (lastLocation != null) { - this.lastLocation = lastLocation; - } - - LocationRequest locationRequest; - - if (enableGPS) { - // LocationRequest Tuned for GPS - locationRequest = LocationRequest.create() - .setFastestInterval(1000) - .setSmallestDisplacement(3.0f) - .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); - - com.mapzen.android.lost.api.LocationServices.FusedLocationApi.requestLocationUpdates(locationRequest, this); - } else { - // LocationRequest Tuned for PASSIVE - locationRequest = LocationRequest.create() - .setFastestInterval(1000) - .setSmallestDisplacement(3.0f) - .setPriority(LocationRequest.PRIORITY_NO_POWER); - - com.mapzen.android.lost.api.LocationServices.FusedLocationApi.requestLocationUpdates(locationRequest, this); - } - - isGPSEnabled = enableGPS; + // Disconnect + if (locationClient.isConnected()) { + // Disconnect first to ensure that the new requests are GPS + com.mapzen.android.lost.api.LocationServices.FusedLocationApi.removeLocationUpdates(this); + locationClient.disconnect(); } - /** - * Returns if the GPS sensor is currently enabled - * - * @return active state of the GPS - */ - public boolean isGPSEnabled() { - return isGPSEnabled; + // Setup Fresh + locationClient.connect(); + Location lastLocation = com.mapzen.android.lost.api.LocationServices.FusedLocationApi.getLastLocation(); + if (lastLocation != null) { + this.lastLocation = lastLocation; } - /** - * Called when the location has changed. - * - * @param location The updated location - */ - @Override - public void onLocationChanged(Location location) { -// Timber.d("onLocationChanged()..." + location); - this.lastLocation = location; - - // Update Listeners - for (LocationListener listener : this.locationListeners) { - listener.onLocationChanged(location); - } - - // Update the Telemetry Receiver - Intent locIntent = new Intent(TelemetryLocationReceiver.INTENT_STRING); - locIntent.putExtra(LocationManager.KEY_LOCATION_CHANGED, location); - context.sendBroadcast(locIntent); - } + LocationRequest locationRequest; - /** - * Last known location - * - * @return Last known location data - */ - public Location getLastLocation() { - return lastLocation; - } + if (enableGPS) { + // LocationRequest Tuned for GPS + locationRequest = LocationRequest.create() + .setFastestInterval(1000) + .setSmallestDisplacement(3.0f) + .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); - /** - * Registers a LocationListener to receive location updates - * - * @param locationListener LocationListener - */ - public void addLocationListener(@NonNull LocationListener locationListener) { - if (!this.locationListeners.contains(locationListener)) { - this.locationListeners.add(locationListener); - } + com.mapzen.android.lost.api.LocationServices.FusedLocationApi.requestLocationUpdates(locationRequest, this); + } else { + // LocationRequest Tuned for PASSIVE + locationRequest = LocationRequest.create() + .setFastestInterval(1000) + .setSmallestDisplacement(3.0f) + .setPriority(LocationRequest.PRIORITY_NO_POWER); + + com.mapzen.android.lost.api.LocationServices.FusedLocationApi.requestLocationUpdates(locationRequest, this); } - /** - * Unregister a LocationListener to stop receiving location updates - * - * @param locationListener LocationListener to remove - * @return True if LocationListener was found and removed, False if it was not - */ - public boolean removeLocationListener(@NonNull LocationListener locationListener) { - return this.locationListeners.remove(locationListener); + isGpsEnabled = enableGPS; + } + + /** + * Returns if the GPS sensor is currently enabled + * + * @return active state of the GPS + */ + public boolean isGpsEnabled() { + return isGpsEnabled; + } + + /** + * Called when the location has changed. + * + * @param location The updated location + */ + @Override + public void onLocationChanged(Location location) { + // Timber.d("onLocationChanged()..." + location); + this.lastLocation = location; + + // Update Listeners + for (LocationListener listener : this.locationListeners) { + listener.onLocationChanged(location); } - /** - * Check status of Location Permissions - * @return True if granted to the app, False if not - */ - public boolean areLocationPermissionsGranted() { - if ((ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) && - (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) { - Timber.w("Location Permissions Not Granted Yet. Try again after requesting."); - return false; - } - return true; + // Update the Telemetry Receiver + Intent locIntent = new Intent(TelemetryLocationReceiver.INTENT_STRING); + locIntent.putExtra(LocationManager.KEY_LOCATION_CHANGED, location); + context.sendBroadcast(locIntent); + } + + /** + * Last known location + * + * @return Last known location data + */ + public Location getLastLocation() { + return lastLocation; + } + + /** + * Registers a LocationListener to receive location updates + * + * @param locationListener LocationListener + */ + public void addLocationListener(@NonNull LocationListener locationListener) { + if (!this.locationListeners.contains(locationListener)) { + this.locationListeners.add(locationListener); + } + } + + /** + * Unregister a LocationListener to stop receiving location updates + * + * @param locationListener LocationListener to remove + * @return True if LocationListener was found and removed, False if it was not + */ + public boolean removeLocationListener(@NonNull LocationListener locationListener) { + return this.locationListeners.remove(locationListener); + } + + /** + * Check status of Location Permissions + * + * @return True if granted to the app, False if not + */ + public boolean areLocationPermissionsGranted() { + if ((ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) + != PackageManager.PERMISSION_GRANTED) + && (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) + != PackageManager.PERMISSION_GRANTED)) { + Timber.w("Location Permissions Not Granted Yet. Try again after requesting."); + return false; } + return true; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java index eb90ae764b..bffcf2fa2f 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java @@ -30,656 +30,659 @@ import java.util.List; * Responsible for referencing {@link InfoWindowManager} and {@link MarkerViewManager}. * </p> * <p> - * Exposes convenience methods to add/remove/update all subtypes of annotations found in com.mapbox.mapboxsdk.annotations. + * Exposes convenience methods to add/remove/update all subtypes of annotations found in + * com.mapbox.mapboxsdk.annotations. * </p> */ class AnnotationManager { - private final NativeMapView nativeMapView; - private final MapView mapView; - private final IconManager iconManager; - private final InfoWindowManager infoWindowManager = new InfoWindowManager(); - private final MarkerViewManager markerViewManager; - private final LongSparseArray<Annotation> annotations = new LongSparseArray<>(); - private final List<Marker> selectedMarkers = new ArrayList<>(); - - private MapboxMap mapboxMap; - - private HashMap<MarkerView, MarkerViewManager.OnMarkerViewAddedListener> markerMap = new HashMap<>(); - private MapboxMap.OnMarkerClickListener onMarkerClickListener; - - AnnotationManager(NativeMapView view, MapView mapView, MarkerViewManager markerViewManager) { - this.nativeMapView = view; - this.mapView = mapView; - this.iconManager = new IconManager(nativeMapView); - this.markerViewManager = markerViewManager; - if (view != null) { - // null checking needed for unit tests - nativeMapView.addOnMapChangedListener(markerViewManager); + private final NativeMapView nativeMapView; + private final MapView mapView; + private final IconManager iconManager; + private final InfoWindowManager infoWindowManager = new InfoWindowManager(); + private final MarkerViewManager markerViewManager; + private final LongSparseArray<Annotation> annotations = new LongSparseArray<>(); + private final List<Marker> selectedMarkers = new ArrayList<>(); + + private MapboxMap mapboxMap; + + private HashMap<MarkerView, MarkerViewManager.OnMarkerViewAddedListener> markerMap = new HashMap<>(); + private MapboxMap.OnMarkerClickListener onMarkerClickListener; + + AnnotationManager(NativeMapView view, MapView mapView, MarkerViewManager markerViewManager) { + this.nativeMapView = view; + this.mapView = mapView; + this.iconManager = new IconManager(nativeMapView); + this.markerViewManager = markerViewManager; + if (view != null) { + // null checking needed for unit tests + nativeMapView.addOnMapChangedListener(markerViewManager); + } + } + + // TODO refactor MapboxMap out for Projection and Transform + // Requires removing MapboxMap from Annotations by using Peer model from #6912 + AnnotationManager bind(MapboxMap mapboxMap) { + this.mapboxMap = mapboxMap; + this.markerViewManager.bind(mapboxMap); + return this; + } + + // + // Annotations + // + + Annotation getAnnotation(long id) { + return annotations.get(id); + } + + List<Annotation> getAnnotations() { + List<Annotation> annotations = new ArrayList<>(); + for (int i = 0; i < this.annotations.size(); i++) { + annotations.add(this.annotations.get(this.annotations.keyAt(i))); + } + return annotations; + } + + void removeAnnotation(@NonNull Annotation annotation) { + if (annotation instanceof Marker) { + Marker marker = (Marker) annotation; + marker.hideInfoWindow(); + if (marker instanceof MarkerView) { + markerViewManager.removeMarkerView((MarkerView) marker); + } + } + long id = annotation.getId(); + if (nativeMapView != null) { + nativeMapView.removeAnnotation(id); + } + annotations.remove(id); + } + + void removeAnnotation(long id) { + if (nativeMapView != null) { + nativeMapView.removeAnnotation(id); + } + annotations.remove(id); + } + + void removeAnnotations(@NonNull List<? extends Annotation> annotationList) { + int count = annotationList.size(); + long[] ids = new long[count]; + for (int i = 0; i < count; i++) { + Annotation annotation = annotationList.get(i); + if (annotation instanceof Marker) { + Marker marker = (Marker) annotation; + marker.hideInfoWindow(); + if (marker instanceof MarkerView) { + markerViewManager.removeMarkerView((MarkerView) marker); } + } + ids[i] = annotationList.get(i).getId(); } - // TODO refactor MapboxMap out for Projection and Transform - // Requires removing MapboxMap from Annotations by using Peer model from #6912 - AnnotationManager bind(MapboxMap mapboxMap) { - this.mapboxMap = mapboxMap; - this.markerViewManager.bind(mapboxMap); - return this; + if (nativeMapView != null) { + nativeMapView.removeAnnotations(ids); } - // - // Annotations - // - - Annotation getAnnotation(long id) { - return annotations.get(id); + for (long id : ids) { + annotations.remove(id); } + } - List<Annotation> getAnnotations() { - List<Annotation> annotations = new ArrayList<>(); - for (int i = 0; i < this.annotations.size(); i++) { - annotations.add(this.annotations.get(this.annotations.keyAt(i))); + void removeAnnotations() { + Annotation annotation; + int count = annotations.size(); + long[] ids = new long[count]; + for (int i = 0; i < count; i++) { + ids[i] = annotations.keyAt(i); + annotation = annotations.get(ids[i]); + if (annotation instanceof Marker) { + Marker marker = (Marker) annotation; + marker.hideInfoWindow(); + if (marker instanceof MarkerView) { + markerViewManager.removeMarkerView((MarkerView) marker); } - return annotations; + } } - void removeAnnotation(@NonNull Annotation annotation) { - if (annotation instanceof Marker) { - Marker marker = (Marker) annotation; - marker.hideInfoWindow(); - if (marker instanceof MarkerView) { - markerViewManager.removeMarkerView((MarkerView) marker); - } - } - long id = annotation.getId(); - if (nativeMapView != null) { - nativeMapView.removeAnnotation(id); - } - annotations.remove(id); + if (nativeMapView != null) { + nativeMapView.removeAnnotations(ids); } - void removeAnnotation(long id) { - if (nativeMapView != null) { - nativeMapView.removeAnnotation(id); - } - annotations.remove(id); - } - - void removeAnnotations(@NonNull List<? extends Annotation> annotationList) { - int count = annotationList.size(); - long[] ids = new long[count]; - for (int i = 0; i < count; i++) { - Annotation annotation = annotationList.get(i); - if (annotation instanceof Marker) { - Marker marker = (Marker) annotation; - marker.hideInfoWindow(); - if (marker instanceof MarkerView) { - markerViewManager.removeMarkerView((MarkerView) marker); - } - } - ids[i] = annotationList.get(i).getId(); - } - - if (nativeMapView != null) { - nativeMapView.removeAnnotations(ids); - } + annotations.clear(); + } - for (long id : ids) { - annotations.remove(id); - } - } + // + // Markers + // - void removeAnnotations() { - Annotation annotation; - int count = annotations.size(); - long[] ids = new long[count]; - for (int i = 0; i < count; i++) { - ids[i] = annotations.keyAt(i); - annotation = annotations.get(ids[i]); - if (annotation instanceof Marker) { - Marker marker = (Marker) annotation; - marker.hideInfoWindow(); - if (marker instanceof MarkerView) { - markerViewManager.removeMarkerView((MarkerView) marker); - } - } - } + List<Marker> addMarkers(@NonNull List<? extends BaseMarkerOptions> markerOptionsList, @NonNull MapboxMap mapboxMap) { + int count = markerOptionsList.size(); + List<Marker> markers = new ArrayList<>(count); + if (count > 0) { + BaseMarkerOptions markerOptions; + Marker marker; + for (int i = 0; i < count; i++) { + markerOptions = markerOptionsList.get(i); + marker = prepareMarker(markerOptions); + markers.add(marker); + } + if (markers.size() > 0) { + long[] ids = null; if (nativeMapView != null) { - nativeMapView.removeAnnotations(ids); - } - - annotations.clear(); - } - - // - // Markers - // - - Marker addMarker(@NonNull BaseMarkerOptions markerOptions, @NonNull MapboxMap mapboxMap) { - Marker marker = prepareMarker(markerOptions); - long id = nativeMapView != null ? nativeMapView.addMarker(marker) : 0; - marker.setMapboxMap(mapboxMap); - marker.setId(id); - annotations.put(id, marker); - return marker; + ids = nativeMapView.addMarkers(markers); + } + + long id = 0; + Marker m; + for (int i = 0; i < markers.size(); i++) { + m = markers.get(i); + m.setMapboxMap(mapboxMap); + if (ids != null) { + id = ids[i]; + } else { + //unit test + id++; + } + m.setId(id); + annotations.put(id, m); + } + + } + } + return markers; + } + + private Marker prepareMarker(BaseMarkerOptions markerOptions) { + Marker marker = markerOptions.getMarker(); + Icon icon = iconManager.loadIconForMarker(marker); + marker.setTopOffsetPixels(iconManager.getTopOffsetPixelsForIcon(icon)); + return marker; + } + + Marker addMarker(@NonNull BaseMarkerOptions markerOptions, @NonNull MapboxMap mapboxMap) { + Marker marker = prepareMarker(markerOptions); + long id = nativeMapView != null ? nativeMapView.addMarker(marker) : 0; + marker.setMapboxMap(mapboxMap); + marker.setId(id); + annotations.put(id, marker); + return marker; + } + + MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions, @NonNull MapboxMap mapboxMap) { + MarkerView marker = prepareViewMarker(markerOptions); + marker.setMapboxMap(mapboxMap); + long id = nativeMapView.addMarker(marker); + marker.setId(id); + annotations.put(id, marker); + return marker; + } + + public MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions, @NonNull MapboxMap mapboxMap, + final MarkerViewManager.OnMarkerViewAddedListener onMarkerViewAddedListener) { + final MarkerView marker = prepareViewMarker(markerOptions); + + // add marker to map + marker.setMapboxMap(mapboxMap); + long id = nativeMapView.addMarker(marker); + marker.setId(id); + annotations.put(id, marker); + + markerViewManager.addOnMarkerViewAddedListener(marker, onMarkerViewAddedListener); + markerViewManager.setWaitingForRenderInvoke(true); + return marker; + } + + + List<MarkerView> addMarkerViews(@NonNull List<? extends BaseMarkerViewOptions> markerViewOptions, + @NonNull MapboxMap mapboxMap) { + List<MarkerView> markers = new ArrayList<>(); + for (BaseMarkerViewOptions markerViewOption : markerViewOptions) { + // if last marker + if (markerViewOptions.indexOf(markerViewOption) == markerViewOptions.size() - 1) { + // get notified when render occurs to invalidate and draw MarkerViews + markerViewManager.setWaitingForRenderInvoke(true); + } + // add marker to map + MarkerView marker = prepareViewMarker(markerViewOption); + marker.setMapboxMap(mapboxMap); + long id = nativeMapView.addMarker(marker); + marker.setId(id); + annotations.put(id, marker); + markers.add(marker); } + markerViewManager.invalidateViewMarkersInVisibleRegion(); + return markers; + } - List<Marker> addMarkers(@NonNull List<? extends BaseMarkerOptions> markerOptionsList, @NonNull MapboxMap mapboxMap) { - int count = markerOptionsList.size(); - List<Marker> markers = new ArrayList<>(count); - if (count > 0) { - BaseMarkerOptions markerOptions; - Marker marker; - for (int i = 0; i < count; i++) { - markerOptions = markerOptionsList.get(i); - marker = prepareMarker(markerOptions); - markers.add(marker); - } - - if (markers.size() > 0) { - long[] ids = null; - if (nativeMapView != null) { - ids = nativeMapView.addMarkers(markers); - } - - long id = 0; - Marker m; - for (int i = 0; i < markers.size(); i++) { - m = markers.get(i); - m.setMapboxMap(mapboxMap); - if (ids != null) { - id = ids[i]; - } else { - //unit test - id++; - } - m.setId(id); - annotations.put(id, m); - } - - } - } - return markers; - } + private MarkerView prepareViewMarker(BaseMarkerViewOptions markerViewOptions) { + MarkerView marker = markerViewOptions.getMarker(); + iconManager.loadIconForMarkerView(marker); + return marker; + } - private Marker prepareMarker(BaseMarkerOptions markerOptions) { - Marker marker = markerOptions.getMarker(); - Icon icon = iconManager.loadIconForMarker(marker); - marker.setTopOffsetPixels(iconManager.getTopOffsetPixelsForIcon(icon)); - return marker; + void updateMarker(@NonNull Marker updatedMarker, @NonNull MapboxMap mapboxMap) { + if (updatedMarker == null) { + return; } - MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions, @NonNull MapboxMap mapboxMap) { - MarkerView marker = prepareViewMarker(markerOptions); - marker.setMapboxMap(mapboxMap); - long id = nativeMapView.addMarker(marker); - marker.setId(id); - annotations.put(id, marker); - return marker; + if (updatedMarker.getId() == -1) { + return; } - public MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions, @NonNull MapboxMap mapboxMap, final MarkerViewManager.OnMarkerViewAddedListener onMarkerViewAddedListener) { - final MarkerView marker = prepareViewMarker(markerOptions); - - // add marker to map - marker.setMapboxMap(mapboxMap); - long id = nativeMapView.addMarker(marker); - marker.setId(id); - annotations.put(id, marker); - - markerViewManager.addOnMarkerViewAddedListener(marker, onMarkerViewAddedListener); - markerViewManager.setWaitingForRenderInvoke(true); - return marker; + if (!(updatedMarker instanceof MarkerView)) { + iconManager.ensureIconLoaded(updatedMarker, mapboxMap); } + nativeMapView.updateMarker(updatedMarker); - List<MarkerView> addMarkerViews(@NonNull List<? extends BaseMarkerViewOptions> markerViewOptions, @NonNull MapboxMap mapboxMap) { - List<MarkerView> markers = new ArrayList<>(); - for (BaseMarkerViewOptions markerViewOption : markerViewOptions) { - // if last marker - if (markerViewOptions.indexOf(markerViewOption) == markerViewOptions.size() - 1) { - // get notified when render occurs to invalidate and draw MarkerViews - markerViewManager.setWaitingForRenderInvoke(true); - } - // add marker to map - MarkerView marker = prepareViewMarker(markerViewOption); - marker.setMapboxMap(mapboxMap); - long id = nativeMapView.addMarker(marker); - marker.setId(id); - annotations.put(id, marker); - markers.add(marker); - } - markerViewManager.invalidateViewMarkersInVisibleRegion(); - return markers; + int index = annotations.indexOfKey(updatedMarker.getId()); + if (index > -1) { + annotations.setValueAt(index, updatedMarker); } + } - private MarkerView prepareViewMarker(BaseMarkerViewOptions markerViewOptions) { - MarkerView marker = markerViewOptions.getMarker(); - iconManager.loadIconForMarkerView(marker); - return marker; + List<Marker> getMarkers() { + List<Marker> markers = new ArrayList<>(); + Annotation annotation; + for (int i = 0; i < annotations.size(); i++) { + annotation = annotations.get(annotations.keyAt(i)); + if (annotation instanceof Marker) { + markers.add((Marker) annotation); + } } + return markers; + } - void updateMarker(@NonNull Marker updatedMarker, @NonNull MapboxMap mapboxMap) { - if (updatedMarker == null) { - return; - } - - if (updatedMarker.getId() == -1) { - return; - } + void setOnMarkerClickListener(@Nullable MapboxMap.OnMarkerClickListener listener) { + onMarkerClickListener = listener; + } - if (!(updatedMarker instanceof MarkerView)) { - iconManager.ensureIconLoaded(updatedMarker, mapboxMap); - } - - nativeMapView.updateMarker(updatedMarker); - - int index = annotations.indexOfKey(updatedMarker.getId()); - if (index > -1) { - annotations.setValueAt(index, updatedMarker); - } + void selectMarker(@NonNull Marker marker) { + if (selectedMarkers.contains(marker)) { + return; } - List<Marker> getMarkers() { - List<Marker> markers = new ArrayList<>(); - Annotation annotation; - for (int i = 0; i < annotations.size(); i++) { - annotation = annotations.get(annotations.keyAt(i)); - if (annotation instanceof Marker) { - markers.add((Marker) annotation); - } - } - return markers; + // Need to deselect any currently selected annotation first + if (!infoWindowManager.isAllowConcurrentMultipleOpenInfoWindows()) { + deselectMarkers(); } - void setOnMarkerClickListener(@Nullable MapboxMap.OnMarkerClickListener listener) { - onMarkerClickListener = listener; + if (marker instanceof MarkerView) { + markerViewManager.select((MarkerView) marker, false); + markerViewManager.ensureInfoWindowOffset((MarkerView) marker); } - void selectMarker(@NonNull Marker marker) { - if (selectedMarkers.contains(marker)) { - return; - } - - // Need to deselect any currently selected annotation first - if (!infoWindowManager.isAllowConcurrentMultipleOpenInfoWindows()) { - deselectMarkers(); - } - - if (marker instanceof MarkerView) { - markerViewManager.select((MarkerView) marker, false); - markerViewManager.ensureInfoWindowOffset((MarkerView) marker); - } + if (infoWindowManager.isInfoWindowValidForMarker(marker) || infoWindowManager.getInfoWindowAdapter() != null) { + infoWindowManager.add(marker.showInfoWindow(mapboxMap, mapView)); + } - if (infoWindowManager.isInfoWindowValidForMarker(marker) || infoWindowManager.getInfoWindowAdapter() != null) { - infoWindowManager.add(marker.showInfoWindow(mapboxMap, mapView)); - } + // only add to selected markers if user didn't handle the click event themselves #3176 + selectedMarkers.add(marker); + } - // only add to selected markers if user didn't handle the click event themselves #3176 - selectedMarkers.add(marker); + void deselectMarkers() { + if (selectedMarkers.isEmpty()) { + return; } - void deselectMarkers() { - if (selectedMarkers.isEmpty()) { - return; - } + for (Marker marker : selectedMarkers) { + if (marker.isInfoWindowShown()) { + marker.hideInfoWindow(); + } - for (Marker marker : selectedMarkers) { - if (marker.isInfoWindowShown()) { - marker.hideInfoWindow(); - } - - if (marker instanceof MarkerView) { - markerViewManager.deselect((MarkerView) marker, false); - } - } - - // Removes all selected markers from the list - selectedMarkers.clear(); + if (marker instanceof MarkerView) { + markerViewManager.deselect((MarkerView) marker, false); + } } - void deselectMarker(@NonNull Marker marker) { - if (!selectedMarkers.contains(marker)) { - return; - } - - if (marker.isInfoWindowShown()) { - marker.hideInfoWindow(); - } + // Removes all selected markers from the list + selectedMarkers.clear(); + } - if (marker instanceof MarkerView) { - markerViewManager.deselect((MarkerView) marker, false); - } + void deselectMarker(@NonNull Marker marker) { + if (!selectedMarkers.contains(marker)) { + return; + } - selectedMarkers.remove(marker); + if (marker.isInfoWindowShown()) { + marker.hideInfoWindow(); } - List<Marker> getSelectedMarkers() { - return selectedMarkers; + if (marker instanceof MarkerView) { + markerViewManager.deselect((MarkerView) marker, false); } - public List<Marker> getMarkersInRect(@NonNull RectF rectangle) { - // convert Rectangle to be density depedent - float pixelRatio = nativeMapView.getPixelRatio(); - RectF rect = new RectF(rectangle.left / pixelRatio, - rectangle.top / pixelRatio, - rectangle.right / pixelRatio, - rectangle.bottom / pixelRatio); + selectedMarkers.remove(marker); + } - long[] ids = nativeMapView.queryPointAnnotations(rect); + List<Marker> getSelectedMarkers() { + return selectedMarkers; + } - List<Long> idsList = new ArrayList<>(ids.length); - for (long id : ids) { - idsList.add(id); - } + public List<Marker> getMarkersInRect(@NonNull RectF rectangle) { + // convert Rectangle to be density depedent + float pixelRatio = nativeMapView.getPixelRatio(); + RectF rect = new RectF(rectangle.left / pixelRatio, + rectangle.top / pixelRatio, + rectangle.right / pixelRatio, + rectangle.bottom / pixelRatio); - List<Marker> annotations = new ArrayList<>(ids.length); - List<Annotation> annotationList = getAnnotations(); - int count = annotationList.size(); - for (int i = 0; i < count; i++) { - Annotation annotation = annotationList.get(i); - if (annotation instanceof com.mapbox.mapboxsdk.annotations.Marker && idsList.contains(annotation.getId())) { - annotations.add((com.mapbox.mapboxsdk.annotations.Marker) annotation); - } - } + long[] ids = nativeMapView.queryPointAnnotations(rect); - return new ArrayList<>(annotations); + List<Long> idsList = new ArrayList<>(ids.length); + for (long id : ids) { + idsList.add(id); } - public List<MarkerView> getMarkerViewsInRect(@NonNull RectF rectangle) { - float pixelRatio = nativeMapView.getPixelRatio(); - RectF rect = new RectF(rectangle.left / pixelRatio, - rectangle.top / pixelRatio, - rectangle.right / pixelRatio, - rectangle.bottom / pixelRatio); + List<Marker> annotations = new ArrayList<>(ids.length); + List<Annotation> annotationList = getAnnotations(); + int count = annotationList.size(); + for (int i = 0; i < count; i++) { + Annotation annotation = annotationList.get(i); + if (annotation instanceof com.mapbox.mapboxsdk.annotations.Marker && idsList.contains(annotation.getId())) { + annotations.add((com.mapbox.mapboxsdk.annotations.Marker) annotation); + } + } - long[] ids = nativeMapView.queryPointAnnotations(rect); + return new ArrayList<>(annotations); + } - List<Long> idsList = new ArrayList<>(ids.length); - for (long id : ids) { - idsList.add(id); - } + public List<MarkerView> getMarkerViewsInRect(@NonNull RectF rectangle) { + float pixelRatio = nativeMapView.getPixelRatio(); + RectF rect = new RectF(rectangle.left / pixelRatio, + rectangle.top / pixelRatio, + rectangle.right / pixelRatio, + rectangle.bottom / pixelRatio); - List<MarkerView> annotations = new ArrayList<>(ids.length); - List<Annotation> annotationList = getAnnotations(); - int count = annotationList.size(); - for (int i = 0; i < count; i++) { - Annotation annotation = annotationList.get(i); - if (annotation instanceof MarkerView && idsList.contains(annotation.getId())) { - annotations.add((MarkerView) annotation); - } - } + long[] ids = nativeMapView.queryPointAnnotations(rect); - return new ArrayList<>(annotations); + List<Long> idsList = new ArrayList<>(ids.length); + for (long id : ids) { + idsList.add(id); } - // - // Polygons - // - - Polygon addPolygon(@NonNull PolygonOptions polygonOptions, @NonNull MapboxMap mapboxMap) { - Polygon polygon = polygonOptions.getPolygon(); - if (!polygon.getPoints().isEmpty()) { - long id = nativeMapView != null ? nativeMapView.addPolygon(polygon) : 0; - polygon.setId(id); - polygon.setMapboxMap(mapboxMap); - annotations.put(id, polygon); - } - return polygon; + List<MarkerView> annotations = new ArrayList<>(ids.length); + List<Annotation> annotationList = getAnnotations(); + int count = annotationList.size(); + for (int i = 0; i < count; i++) { + Annotation annotation = annotationList.get(i); + if (annotation instanceof MarkerView && idsList.contains(annotation.getId())) { + annotations.add((MarkerView) annotation); + } } - List<Polygon> addPolygons(@NonNull List<PolygonOptions> polygonOptionsList, @NonNull MapboxMap mapboxMap) { - int count = polygonOptionsList.size(); - - Polygon polygon; - List<Polygon> polygons = new ArrayList<>(count); - if (count > 0) { - for (PolygonOptions polygonOptions : polygonOptionsList) { - polygon = polygonOptions.getPolygon(); - if (!polygon.getPoints().isEmpty()) { - polygons.add(polygon); - } - } + return new ArrayList<>(annotations); + } - long[] ids = null; - if (nativeMapView != null) { - ids = nativeMapView.addPolygons(polygons); - } + // + // Polygons + // - long id = 0; - for (int i = 0; i < polygons.size(); i++) { - polygon = polygons.get(i); - polygon.setMapboxMap(mapboxMap); - if (ids != null) { - id = ids[i]; - } else { - // unit test - id++; - } - polygon.setId(id); - annotations.put(id, polygon); - } - } - return polygons; + Polygon addPolygon(@NonNull PolygonOptions polygonOptions, @NonNull MapboxMap mapboxMap) { + Polygon polygon = polygonOptions.getPolygon(); + if (!polygon.getPoints().isEmpty()) { + long id = nativeMapView != null ? nativeMapView.addPolygon(polygon) : 0; + polygon.setId(id); + polygon.setMapboxMap(mapboxMap); + annotations.put(id, polygon); } + return polygon; + } - void updatePolygon(Polygon polygon) { - if (polygon == null) { - return; - } + List<Polygon> addPolygons(@NonNull List<PolygonOptions> polygonOptionsList, @NonNull MapboxMap mapboxMap) { + int count = polygonOptionsList.size(); - if (polygon.getId() == -1) { - return; + Polygon polygon; + List<Polygon> polygons = new ArrayList<>(count); + if (count > 0) { + for (PolygonOptions polygonOptions : polygonOptionsList) { + polygon = polygonOptions.getPolygon(); + if (!polygon.getPoints().isEmpty()) { + polygons.add(polygon); } + } - nativeMapView.updatePolygon(polygon); + long[] ids = null; + if (nativeMapView != null) { + ids = nativeMapView.addPolygons(polygons); + } - int index = annotations.indexOfKey(polygon.getId()); - if (index > -1) { - annotations.setValueAt(index, polygon); + long id = 0; + for (int i = 0; i < polygons.size(); i++) { + polygon = polygons.get(i); + polygon.setMapboxMap(mapboxMap); + if (ids != null) { + id = ids[i]; + } else { + // unit test + id++; } + polygon.setId(id); + annotations.put(id, polygon); + } } + return polygons; + } - List<Polygon> getPolygons() { - List<Polygon> polygons = new ArrayList<>(); - Annotation annotation; - for (int i = 0; i < annotations.size(); i++) { - annotation = annotations.get(annotations.keyAt(i)); - if (annotation instanceof Polygon) { - polygons.add((Polygon) annotation); - } - } - return polygons; + void updatePolygon(Polygon polygon) { + if (polygon == null) { + return; } - // - // Polylines - // - - Polyline addPolyline(@NonNull PolylineOptions polylineOptions, @NonNull MapboxMap mapboxMap) { - Polyline polyline = polylineOptions.getPolyline(); - if (!polyline.getPoints().isEmpty()) { - long id = nativeMapView != null ? nativeMapView.addPolyline(polyline) : 0; - polyline.setMapboxMap(mapboxMap); - polyline.setId(id); - annotations.put(id, polyline); - } - return polyline; + if (polygon.getId() == -1) { + return; } - List<Polyline> addPolylines(@NonNull List<PolylineOptions> polylineOptionsList, @NonNull MapboxMap mapboxMap) { - int count = polylineOptionsList.size(); - Polyline polyline; - List<Polyline> polylines = new ArrayList<>(count); + nativeMapView.updatePolygon(polygon); - if (count > 0) { - for (PolylineOptions options : polylineOptionsList) { - polyline = options.getPolyline(); - if (!polyline.getPoints().isEmpty()) { - polylines.add(polyline); - } - } - - long[] ids = null; - if (nativeMapView != null) { - ids = nativeMapView.addPolylines(polylines); - } - - long id = 0; - Polyline p; - - for (int i = 0; i < polylines.size(); i++) { - p = polylines.get(i); - p.setMapboxMap(mapboxMap); - if (ids != null) { - id = ids[i]; - } else { - // unit test - id++; - } - p.setId(id); - annotations.put(id, p); - } - } - return polylines; + int index = annotations.indexOfKey(polygon.getId()); + if (index > -1) { + annotations.setValueAt(index, polygon); } + } - void updatePolyline(Polyline polyline) { - if (polyline == null) { - return; - } - - if (polyline.getId() == -1) { - return; - } - - nativeMapView.updatePolyline(polyline); - - int index = annotations.indexOfKey(polyline.getId()); - if (index > -1) { - annotations.setValueAt(index, polyline); - } + List<Polygon> getPolygons() { + List<Polygon> polygons = new ArrayList<>(); + Annotation annotation; + for (int i = 0; i < annotations.size(); i++) { + annotation = annotations.get(annotations.keyAt(i)); + if (annotation instanceof Polygon) { + polygons.add((Polygon) annotation); + } } + return polygons; + } - List<Polyline> getPolylines() { - List<Polyline> polylines = new ArrayList<>(); - Annotation annotation; - for (int i = 0; i < annotations.size(); i++) { - annotation = annotations.get(annotations.keyAt(i)); - if (annotation instanceof Polyline) { - polylines.add((Polyline) annotation); - } - } - return polylines; - } + // + // Polylines + // - InfoWindowManager getInfoWindowManager() { - return infoWindowManager; + Polyline addPolyline(@NonNull PolylineOptions polylineOptions, @NonNull MapboxMap mapboxMap) { + Polyline polyline = polylineOptions.getPolyline(); + if (!polyline.getPoints().isEmpty()) { + long id = nativeMapView != null ? nativeMapView.addPolyline(polyline) : 0; + polyline.setMapboxMap(mapboxMap); + polyline.setId(id); + annotations.put(id, polyline); } + return polyline; + } - MarkerViewManager getMarkerViewManager() { - return markerViewManager; - } - - void adjustTopOffsetPixels(MapboxMap mapboxMap) { - int count = annotations.size(); - for (int i = 0; i < count; i++) { - Annotation annotation = annotations.get(i); - if (annotation instanceof Marker) { - Marker marker = (Marker) annotation; - marker.setTopOffsetPixels( - iconManager.getTopOffsetPixelsForIcon(marker.getIcon())); - } - } + List<Polyline> addPolylines(@NonNull List<PolylineOptions> polylineOptionsList, @NonNull MapboxMap mapboxMap) { + int count = polylineOptionsList.size(); + Polyline polyline; + List<Polyline> polylines = new ArrayList<>(count); - for (Marker marker : selectedMarkers) { - if (marker.isInfoWindowShown()) { - marker.hideInfoWindow(); - marker.showInfoWindow(mapboxMap, mapView); - } + if (count > 0) { + for (PolylineOptions options : polylineOptionsList) { + polyline = options.getPolyline(); + if (!polyline.getPoints().isEmpty()) { + polylines.add(polyline); } - } + } + + long[] ids = null; + if (nativeMapView != null) { + ids = nativeMapView.addPolylines(polylines); + } + + long id = 0; + Polyline p; + + for (int i = 0; i < polylines.size(); i++) { + p = polylines.get(i); + p.setMapboxMap(mapboxMap); + if (ids != null) { + id = ids[i]; + } else { + // unit test + id++; + } + p.setId(id); + annotations.put(id, p); + } + } + return polylines; + } + + void updatePolyline(Polyline polyline) { + if (polyline == null) { + return; + } + + if (polyline.getId() == -1) { + return; + } + + nativeMapView.updatePolyline(polyline); + + int index = annotations.indexOfKey(polyline.getId()); + if (index > -1) { + annotations.setValueAt(index, polyline); + } + } + + List<Polyline> getPolylines() { + List<Polyline> polylines = new ArrayList<>(); + Annotation annotation; + for (int i = 0; i < annotations.size(); i++) { + annotation = annotations.get(annotations.keyAt(i)); + if (annotation instanceof Polyline) { + polylines.add((Polyline) annotation); + } + } + return polylines; + } + + InfoWindowManager getInfoWindowManager() { + return infoWindowManager; + } + + MarkerViewManager getMarkerViewManager() { + return markerViewManager; + } + + void adjustTopOffsetPixels(MapboxMap mapboxMap) { + int count = annotations.size(); + for (int i = 0; i < count; i++) { + Annotation annotation = annotations.get(i); + if (annotation instanceof Marker) { + Marker marker = (Marker) annotation; + marker.setTopOffsetPixels( + iconManager.getTopOffsetPixelsForIcon(marker.getIcon())); + } + } + + for (Marker marker : selectedMarkers) { + if (marker.isInfoWindowShown()) { + marker.hideInfoWindow(); + marker.showInfoWindow(mapboxMap, mapView); + } + } + } + + void reloadMarkers() { + iconManager.reloadIcons(); + int count = annotations.size(); + for (int i = 0; i < count; i++) { + Annotation annotation = annotations.get(i); + if (annotation instanceof Marker) { + Marker marker = (Marker) annotation; + nativeMapView.removeAnnotation(annotation.getId()); + long newId = nativeMapView.addMarker(marker); + marker.setId(newId); + } + } + } + + // + // Click event + // + + boolean onTap(PointF tapPoint, float screenDensity) { + float toleranceSides = 4 * screenDensity; + float toleranceTopBottom = 10 * screenDensity; + + RectF tapRect = new RectF(tapPoint.x - iconManager.getAverageIconWidth() / 2 - toleranceSides, + tapPoint.y - iconManager.getAverageIconHeight() / 2 - toleranceTopBottom, + tapPoint.x + iconManager.getAverageIconWidth() / 2 + toleranceSides, + tapPoint.y + iconManager.getAverageIconHeight() / 2 + toleranceTopBottom); + + List<Marker> nearbyMarkers = getMarkersInRect(tapRect); + long newSelectedMarkerId = -1; + + if (nearbyMarkers != null && nearbyMarkers.size() > 0) { + Collections.sort(nearbyMarkers); + for (Marker nearbyMarker : nearbyMarkers) { + boolean found = false; + for (Marker selectedMarker : selectedMarkers) { + if (selectedMarker.equals(nearbyMarker)) { + found = true; + } + } + if (!found) { + newSelectedMarkerId = nearbyMarker.getId(); + break; + } + } + } + + if (newSelectedMarkerId >= 0) { + List<Annotation> annotations = getAnnotations(); + int count = annotations.size(); + for (int i = 0; i < count; i++) { + Annotation annotation = annotations.get(i); + if (annotation instanceof Marker) { + if (annotation.getId() == newSelectedMarkerId) { + Marker marker = (Marker) annotation; + boolean handledDefaultClick = false; - void reloadMarkers() { - iconManager.reloadIcons(); - int count = annotations.size(); - for (int i = 0; i < count; i++) { - Annotation annotation = annotations.get(i); - if (annotation instanceof Marker) { - Marker marker = (Marker) annotation; - nativeMapView.removeAnnotation(annotation.getId()); - long newId = nativeMapView.addMarker(marker); - marker.setId(newId); + if (marker instanceof MarkerView) { + handledDefaultClick = markerViewManager.onClickMarkerView((MarkerView) marker); + } else { + if (onMarkerClickListener != null) { + // end developer has provided a custom click listener + handledDefaultClick = onMarkerClickListener.onMarkerClick(marker); + } } - } - } - // - // Click event - // - - boolean onTap(PointF tapPoint, float screenDensity) { - float toleranceSides = 4 * screenDensity; - float toleranceTopBottom = 10 * screenDensity; - - RectF tapRect = new RectF(tapPoint.x - iconManager.getAverageIconWidth() / 2 - toleranceSides, - tapPoint.y - iconManager.getAverageIconHeight() / 2 - toleranceTopBottom, - tapPoint.x + iconManager.getAverageIconWidth() / 2 + toleranceSides, - tapPoint.y + iconManager.getAverageIconHeight() / 2 + toleranceTopBottom); - - List<Marker> nearbyMarkers = getMarkersInRect(tapRect); - long newSelectedMarkerId = -1; - - if (nearbyMarkers != null && nearbyMarkers.size() > 0) { - Collections.sort(nearbyMarkers); - for (Marker nearbyMarker : nearbyMarkers) { - boolean found = false; - for (Marker selectedMarker : selectedMarkers) { - if (selectedMarker.equals(nearbyMarker)) { - found = true; - } - } - if (!found) { - newSelectedMarkerId = nearbyMarker.getId(); - break; - } + if (annotation instanceof MarkerView) { + markerViewManager.onClickMarkerView((MarkerView) annotation); + } else { + if (!handledDefaultClick) { + // only select marker if user didn't handle the click event themselves + selectMarker(marker); + } } - } - if (newSelectedMarkerId >= 0) { - List<Annotation> annotations = getAnnotations(); - int count = annotations.size(); - for (int i = 0; i < count; i++) { - Annotation annotation = annotations.get(i); - if (annotation instanceof Marker) { - if (annotation.getId() == newSelectedMarkerId) { - Marker marker = (Marker) annotation; - boolean handledDefaultClick = false; - - if (marker instanceof MarkerView) { - handledDefaultClick = markerViewManager.onClickMarkerView((MarkerView) marker); - } else { - if (onMarkerClickListener != null) { - // end developer has provided a custom click listener - handledDefaultClick = onMarkerClickListener.onMarkerClick(marker); - } - } - - if (annotation instanceof MarkerView) { - markerViewManager.onClickMarkerView((MarkerView) annotation); - } else { - if (!handledDefaultClick) { - // only select marker if user didn't handle the click event themselves - selectMarker(marker); - } - } - - return true; - } - } - } + return true; + } } - return false; + } } + return false; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/FocalPointChangeListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/FocalPointChangeListener.java index 5f20155119..006122a4e2 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/FocalPointChangeListener.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/FocalPointChangeListener.java @@ -4,5 +4,5 @@ import android.graphics.PointF; public interface FocalPointChangeListener { - void onFocalPointChanged(PointF pointF); + void onFocalPointChanged(PointF pointF); } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java index 71a9d4a2da..c9d81a88bc 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java @@ -26,133 +26,133 @@ import java.util.List; */ class IconManager { - private NativeMapView nativeMapView; - private List<Icon> icons; - - private int averageIconHeight; - private int averageIconWidth; - - IconManager(NativeMapView nativeMapView) { - this.nativeMapView = nativeMapView; - this.icons = new ArrayList<>(); - // load transparent icon for MarkerView to trace actual markers, see #6352 - loadIcon(IconFactory.recreate(IconFactory.ICON_MARKERVIEW_ID, IconFactory.ICON_MARKERVIEW_BITMAP)); + private NativeMapView nativeMapView; + private List<Icon> icons; + + private int averageIconHeight; + private int averageIconWidth; + + IconManager(NativeMapView nativeMapView) { + this.nativeMapView = nativeMapView; + this.icons = new ArrayList<>(); + // load transparent icon for MarkerView to trace actual markers, see #6352 + loadIcon(IconFactory.recreate(IconFactory.ICON_MARKERVIEW_ID, IconFactory.ICON_MARKERVIEW_BITMAP)); + } + + Icon loadIconForMarker(Marker marker) { + Icon icon = marker.getIcon(); + + // calculating average before adding + int iconSize = icons.size() + 1; + + // TODO replace former if case with anchor implementation, + // current workaround for having extra pixels is diving height by 2 + if (icon == null) { + icon = IconFactory.getInstance(nativeMapView.getContext()).defaultMarker(); + Bitmap bitmap = icon.getBitmap(); + averageIconHeight = averageIconHeight + (bitmap.getHeight() / 2 - averageIconHeight) / iconSize; + averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize; + marker.setIcon(icon); + } else { + Bitmap bitmap = icon.getBitmap(); + averageIconHeight = averageIconHeight + (bitmap.getHeight() - averageIconHeight) / iconSize; + averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize; } - Icon loadIconForMarker(Marker marker) { - Icon icon = marker.getIcon(); - - // calculating average before adding - int iconSize = icons.size() + 1; - - // TODO replace former if case with anchor implementation, - // current workaround for having extra pixels is diving height by 2 - if (icon == null) { - icon = IconFactory.getInstance(nativeMapView.getContext()).defaultMarker(); - Bitmap bitmap = icon.getBitmap(); - averageIconHeight = averageIconHeight + (bitmap.getHeight() / 2 - averageIconHeight) / iconSize; - averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize; - marker.setIcon(icon); - } else { - Bitmap bitmap = icon.getBitmap(); - averageIconHeight = averageIconHeight + (bitmap.getHeight() - averageIconHeight) / iconSize; - averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize; - } - - if (!icons.contains(icon)) { - icons.add(icon); - loadIcon(icon); - } else { - Icon oldIcon = icons.get(icons.indexOf(icon)); - if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) { - throw new IconBitmapChangedException(); - } - } - return icon; + if (!icons.contains(icon)) { + icons.add(icon); + loadIcon(icon); + } else { + Icon oldIcon = icons.get(icons.indexOf(icon)); + if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) { + throw new IconBitmapChangedException(); + } } - - Icon loadIconForMarkerView(MarkerView marker) { - Icon icon = marker.getIcon(); - int iconSize = icons.size() + 1; - if (icon == null) { - icon = IconFactory.getInstance(nativeMapView.getContext()).defaultMarkerView(); - marker.setIcon(icon); - } - Bitmap bitmap = icon.getBitmap(); - averageIconHeight = averageIconHeight + (bitmap.getHeight() - averageIconHeight) / iconSize; - averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize; - if (!icons.contains(icon)) { - icons.add(icon); - } else { - Icon oldIcon = icons.get(icons.indexOf(icon)); - if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) { - throw new IconBitmapChangedException(); - } - } - return icon; + return icon; + } + + Icon loadIconForMarkerView(MarkerView marker) { + Icon icon = marker.getIcon(); + int iconSize = icons.size() + 1; + if (icon == null) { + icon = IconFactory.getInstance(nativeMapView.getContext()).defaultMarkerView(); + marker.setIcon(icon); } - - int getTopOffsetPixelsForIcon(Icon icon) { - return (int) (nativeMapView.getTopOffsetPixelsForAnnotationSymbol(icon.getId()) * nativeMapView.getPixelRatio()); + Bitmap bitmap = icon.getBitmap(); + averageIconHeight = averageIconHeight + (bitmap.getHeight() - averageIconHeight) / iconSize; + averageIconWidth = averageIconWidth + (bitmap.getWidth() - averageIconWidth) / iconSize; + if (!icons.contains(icon)) { + icons.add(icon); + } else { + Icon oldIcon = icons.get(icons.indexOf(icon)); + if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) { + throw new IconBitmapChangedException(); + } } - - void loadIcon(Icon icon) { - Bitmap bitmap = icon.getBitmap(); - String id = icon.getId(); - if (bitmap.getConfig() != Bitmap.Config.ARGB_8888) { - bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false); - } - ByteBuffer buffer = ByteBuffer.allocate(bitmap.getRowBytes() * bitmap.getHeight()); - bitmap.copyPixelsToBuffer(buffer); - - float density = bitmap.getDensity(); - if (density == Bitmap.DENSITY_NONE) { - density = DisplayMetrics.DENSITY_DEFAULT; - } - float scale = density / DisplayMetrics.DENSITY_DEFAULT; - nativeMapView.addAnnotationIcon( - id, - bitmap.getWidth(), - bitmap.getHeight(), - scale, buffer.array()); + return icon; + } + + int getTopOffsetPixelsForIcon(Icon icon) { + return (int) (nativeMapView.getTopOffsetPixelsForAnnotationSymbol(icon.getId()) * nativeMapView.getPixelRatio()); + } + + void loadIcon(Icon icon) { + Bitmap bitmap = icon.getBitmap(); + String id = icon.getId(); + if (bitmap.getConfig() != Bitmap.Config.ARGB_8888) { + bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false); } + ByteBuffer buffer = ByteBuffer.allocate(bitmap.getRowBytes() * bitmap.getHeight()); + bitmap.copyPixelsToBuffer(buffer); - void reloadIcons() { - int count = icons.size(); - for (int i = 0; i < count; i++) { - Icon icon = icons.get(i); - loadIcon(icon); - } + float density = bitmap.getDensity(); + if (density == Bitmap.DENSITY_NONE) { + density = DisplayMetrics.DENSITY_DEFAULT; } - - void ensureIconLoaded(Marker marker, MapboxMap mapboxMap) { - Icon icon = marker.getIcon(); - if (icon == null) { - icon = IconFactory.getInstance(nativeMapView.getContext()).defaultMarker(); - marker.setIcon(icon); - } - if (!icons.contains(icon)) { - icons.add(icon); - loadIcon(icon); - } else { - Icon oldIcon = icons.get(icons.indexOf(icon)); - if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) { - throw new IconBitmapChangedException(); - } - } - - // this seems to be a costly operation according to the profiler so I'm trying to save some calls - Marker previousMarker = marker.getId() != -1 ? (Marker) mapboxMap.getAnnotation(marker.getId()) : null; - if (previousMarker == null || previousMarker.getIcon() == null || previousMarker.getIcon() != marker.getIcon()) { - marker.setTopOffsetPixels(getTopOffsetPixelsForIcon(icon)); - } + float scale = density / DisplayMetrics.DENSITY_DEFAULT; + nativeMapView.addAnnotationIcon( + id, + bitmap.getWidth(), + bitmap.getHeight(), + scale, buffer.array()); + } + + void reloadIcons() { + int count = icons.size(); + for (int i = 0; i < count; i++) { + Icon icon = icons.get(i); + loadIcon(icon); } + } - int getAverageIconHeight() { - return averageIconHeight; + void ensureIconLoaded(Marker marker, MapboxMap mapboxMap) { + Icon icon = marker.getIcon(); + if (icon == null) { + icon = IconFactory.getInstance(nativeMapView.getContext()).defaultMarker(); + marker.setIcon(icon); + } + if (!icons.contains(icon)) { + icons.add(icon); + loadIcon(icon); + } else { + Icon oldIcon = icons.get(icons.indexOf(icon)); + if (!oldIcon.getBitmap().sameAs(icon.getBitmap())) { + throw new IconBitmapChangedException(); + } } - int getAverageIconWidth() { - return averageIconWidth; + // this seems to be a costly operation according to the profiler so I'm trying to save some calls + Marker previousMarker = marker.getId() != -1 ? (Marker) mapboxMap.getAnnotation(marker.getId()) : null; + if (previousMarker == null || previousMarker.getIcon() == null || previousMarker.getIcon() != marker.getIcon()) { + marker.setTopOffsetPixels(getTopOffsetPixelsForIcon(icon)); } + } + + int getAverageIconHeight() { + return averageIconHeight; + } + + int getAverageIconWidth() { + return averageIconWidth; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/InfoWindowManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/InfoWindowManager.java index 791f310b4c..fc7d19c325 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/InfoWindowManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/InfoWindowManager.java @@ -15,73 +15,74 @@ import java.util.List; * <p> * Maintains a {@link List} of opened {@link InfoWindow} and tracks configurations as * allowConcurrentMultipleInfoWindows which allows to have multiple {@link InfoWindow} open at the - * same time. Responsible for managing listeners as {@link com.mapbox.mapboxsdk.maps.MapboxMap.OnInfoWindowClickListener} + * same time. Responsible for managing listeners as + * {@link com.mapbox.mapboxsdk.maps.MapboxMap.OnInfoWindowClickListener} * and {@link com.mapbox.mapboxsdk.maps.MapboxMap.OnInfoWindowLongClickListener}. * </p> */ class InfoWindowManager { - private List<InfoWindow> infoWindows; - private MapboxMap.InfoWindowAdapter infoWindowAdapter; - private boolean allowConcurrentMultipleInfoWindows; + private List<InfoWindow> infoWindows; + private MapboxMap.InfoWindowAdapter infoWindowAdapter; + private boolean allowConcurrentMultipleInfoWindows; - private MapboxMap.OnInfoWindowClickListener onInfoWindowClickListener; - private MapboxMap.OnInfoWindowLongClickListener onInfoWindowLongClickListener; - private MapboxMap.OnInfoWindowCloseListener onInfoWindowCloseListener; + private MapboxMap.OnInfoWindowClickListener onInfoWindowClickListener; + private MapboxMap.OnInfoWindowLongClickListener onInfoWindowLongClickListener; + private MapboxMap.OnInfoWindowCloseListener onInfoWindowCloseListener; - InfoWindowManager() { - this.infoWindows = new ArrayList<>(); - } + InfoWindowManager() { + this.infoWindows = new ArrayList<>(); + } - void setInfoWindowAdapter(@Nullable MapboxMap.InfoWindowAdapter infoWindowAdapter) { - this.infoWindowAdapter = infoWindowAdapter; - } + void setInfoWindowAdapter(@Nullable MapboxMap.InfoWindowAdapter infoWindowAdapter) { + this.infoWindowAdapter = infoWindowAdapter; + } - MapboxMap.InfoWindowAdapter getInfoWindowAdapter() { - return infoWindowAdapter; - } + MapboxMap.InfoWindowAdapter getInfoWindowAdapter() { + return infoWindowAdapter; + } - void setAllowConcurrentMultipleOpenInfoWindows(boolean allow) { - allowConcurrentMultipleInfoWindows = allow; - } + void setAllowConcurrentMultipleOpenInfoWindows(boolean allow) { + allowConcurrentMultipleInfoWindows = allow; + } - boolean isAllowConcurrentMultipleOpenInfoWindows() { - return allowConcurrentMultipleInfoWindows; - } + boolean isAllowConcurrentMultipleOpenInfoWindows() { + return allowConcurrentMultipleInfoWindows; + } - List<InfoWindow> getInfoWindows() { - return infoWindows; - } + List<InfoWindow> getInfoWindows() { + return infoWindows; + } - boolean isInfoWindowValidForMarker(@NonNull Marker marker) { - return !TextUtils.isEmpty(marker.getTitle()) || !TextUtils.isEmpty(marker.getSnippet()); - } + boolean isInfoWindowValidForMarker(@NonNull Marker marker) { + return !TextUtils.isEmpty(marker.getTitle()) || !TextUtils.isEmpty(marker.getSnippet()); + } - void setOnInfoWindowClickListener(@Nullable MapboxMap.OnInfoWindowClickListener listener) { - onInfoWindowClickListener = listener; - } + void setOnInfoWindowClickListener(@Nullable MapboxMap.OnInfoWindowClickListener listener) { + onInfoWindowClickListener = listener; + } - MapboxMap.OnInfoWindowClickListener getOnInfoWindowClickListener() { - return onInfoWindowClickListener; - } + MapboxMap.OnInfoWindowClickListener getOnInfoWindowClickListener() { + return onInfoWindowClickListener; + } - void setOnInfoWindowLongClickListener(@Nullable MapboxMap.OnInfoWindowLongClickListener listener) { - onInfoWindowLongClickListener = listener; - } + void setOnInfoWindowLongClickListener(@Nullable MapboxMap.OnInfoWindowLongClickListener listener) { + onInfoWindowLongClickListener = listener; + } - MapboxMap.OnInfoWindowLongClickListener getOnInfoWindowLongClickListener() { - return onInfoWindowLongClickListener; - } + MapboxMap.OnInfoWindowLongClickListener getOnInfoWindowLongClickListener() { + return onInfoWindowLongClickListener; + } - void setOnInfoWindowCloseListener(@Nullable MapboxMap.OnInfoWindowCloseListener listener) { - onInfoWindowCloseListener = listener; - } + void setOnInfoWindowCloseListener(@Nullable MapboxMap.OnInfoWindowCloseListener listener) { + onInfoWindowCloseListener = listener; + } - MapboxMap.OnInfoWindowCloseListener getOnInfoWindowCloseListener() { - return onInfoWindowCloseListener; - } + MapboxMap.OnInfoWindowCloseListener getOnInfoWindowCloseListener() { + return onInfoWindowCloseListener; + } - public void add(InfoWindow infoWindow) { - infoWindows.add(infoWindow); - } + public void add(InfoWindow infoWindow) { + infoWindows.add(infoWindow); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java index 4524a59f0d..18b4c294e5 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java @@ -35,196 +35,197 @@ import com.mapbox.mapboxsdk.exceptions.InvalidAccessTokenException; */ public final class MapFragment extends Fragment { - private MapView map; - private OnMapReadyCallback onMapReadyCallback; - - /** - * Creates a MapFragment instance - * - * @param mapboxMapOptions The configuration options to be used. - * @return MapFragment created. - */ - public static MapFragment newInstance(@Nullable MapboxMapOptions mapboxMapOptions) { - MapFragment mapFragment = new MapFragment(); - Bundle bundle = new Bundle(); - bundle.putParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS, mapboxMapOptions); - mapFragment.setArguments(bundle); - return mapFragment; + private MapView map; + private OnMapReadyCallback onMapReadyCallback; + + /** + * Creates a MapFragment instance + * + * @param mapboxMapOptions The configuration options to be used. + * @return MapFragment created. + */ + public static MapFragment newInstance(@Nullable MapboxMapOptions mapboxMapOptions) { + MapFragment mapFragment = new MapFragment(); + Bundle bundle = new Bundle(); + bundle.putParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS, mapboxMapOptions); + mapFragment.setArguments(bundle); + return mapFragment; + } + + /** + * Creates the fragment view hierarchy. + * + * @param inflater Inflater used to inflate content. + * @param container The parent layout for the map fragment. + * @param savedInstanceState The saved instance state for the map fragment. + * @return The view created + */ + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + Context context = inflater.getContext(); + MapboxMapOptions options = null; + + // Get bundle + Bundle bundle = getArguments(); + if (bundle != null && bundle.containsKey(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS)) { + options = bundle.getParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS); } - /** - * Creates the fragment view hierarchy. - * - * @param inflater Inflater used to inflate content. - * @param container The parent layout for the map fragment. - * @param savedInstanceState The saved instance state for the map fragment. - * @return The view created - */ - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - super.onCreateView(inflater, container, savedInstanceState); - Context context = inflater.getContext(); - MapboxMapOptions options = null; - - // Get bundle - Bundle bundle = getArguments(); - if (bundle != null && bundle.containsKey(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS)) { - options = bundle.getParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS); - } - - // Assign an AccessToken if needed - if (options == null || options.getAccessToken() == null) { - String token = null; - if (MapboxAccountManager.getInstance() != null) { - token = MapboxAccountManager.getInstance().getAccessToken(); - } else { - token = getToken(inflater.getContext()); - } - if (TextUtils.isEmpty(token)) { - throw new InvalidAccessTokenException(); - } - if (options == null) { - options = new MapboxMapOptions().accessToken(token); - } else { - options.accessToken(token); - } - } - - Drawable foregroundDrawable = options.getMyLocationForegroundDrawable(); - Drawable foregroundBearingDrawable = options.getMyLocationForegroundBearingDrawable(); - if (foregroundDrawable == null || foregroundBearingDrawable == null) { - if (foregroundDrawable == null) { - foregroundDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_icon_default); - } - if (foregroundBearingDrawable == null) { - foregroundBearingDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_icon_bearing); - } - options.myLocationForegroundDrawables(foregroundDrawable, foregroundBearingDrawable); - } - - if (options.getMyLocationBackgroundDrawable() == null) { - options.myLocationBackgroundDrawable(ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_bg_shape)); - } - - return map = new MapView(inflater.getContext(), options); + // Assign an AccessToken if needed + if (options == null || options.getAccessToken() == null) { + String token = null; + if (MapboxAccountManager.getInstance() != null) { + token = MapboxAccountManager.getInstance().getAccessToken(); + } else { + token = getToken(inflater.getContext()); + } + if (TextUtils.isEmpty(token)) { + throw new InvalidAccessTokenException(); + } + if (options == null) { + options = new MapboxMapOptions().accessToken(token); + } else { + options.accessToken(token); + } } - /** - * <p> - * Returns the Mapbox access token set in the app resources. - * </p> - * It will first search the application manifest for a {@link MapboxConstants#KEY_META_DATA_MANIFEST} - * meta-data value. If not found it will then attempt to load the access token from the - * {@code res/raw/token.txt} development file. - * - * @param context The {@link Context} of the {@link android.app.Activity} or {@link android.app.Fragment}. - * @return The Mapbox access token or null if not found. - * @see MapboxConstants#KEY_META_DATA_MANIFEST - * - * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)} - */ - @Deprecated - private String getToken(@NonNull Context context) { - try { - // read out AndroidManifest - PackageManager packageManager = context.getPackageManager(); - ApplicationInfo appInfo = packageManager.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA); - String token = appInfo.metaData.getString(MapboxConstants.KEY_META_DATA_MANIFEST); - if (token == null || token.isEmpty()) { - throw new IllegalArgumentException(); - } - return token; - } catch (Exception e) { - // use fallback on string resource, used for development - int tokenResId = context.getResources().getIdentifier("mapbox_access_token", "string", context.getPackageName()); - return tokenResId != 0 ? context.getString(tokenResId) : null; - } + Drawable foregroundDrawable = options.getMyLocationForegroundDrawable(); + Drawable foregroundBearingDrawable = options.getMyLocationForegroundBearingDrawable(); + if (foregroundDrawable == null || foregroundBearingDrawable == null) { + if (foregroundDrawable == null) { + foregroundDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_icon_default); + } + if (foregroundBearingDrawable == null) { + foregroundBearingDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_icon_bearing); + } + options.myLocationForegroundDrawables(foregroundDrawable, foregroundBearingDrawable); } - /** - * Called when the fragment view hierarchy is created. - * - * @param view The content view of the fragment - * @param savedInstanceState THe saved instance state of the framgnt - */ - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - map.onCreate(savedInstanceState); + if (options.getMyLocationBackgroundDrawable() == null) { + options.myLocationBackgroundDrawable(ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_bg_shape)); } - /** - * Called when the fragment is visible for the users. - */ - @Override - public void onStart() { - super.onStart(); - map.onStart(); - map.getMapAsync(onMapReadyCallback); - } - - /** - * Called when the fragment is ready to be interacted with. - */ - @Override - public void onResume() { - super.onResume(); - map.onResume(); - } - - /** - * Called when the fragment is pausing. - */ - @Override - public void onPause() { - super.onPause(); - map.onPause(); - } - - /** - * Called when the fragment state needs to be saved. - * - * @param outState The saved state - */ - @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - map.onSaveInstanceState(outState); - } - - /** - * Called when the fragment is no longer visible for the user. - */ - @Override - public void onStop() { - super.onStop(); - map.onStop(); - } - - /** - * Called when the fragment receives onLowMemory call from the hosting Activity. - */ - @Override - public void onLowMemory() { - super.onLowMemory(); - map.onLowMemory(); - } - - /** - * Called when the fragment is view hiearchy is being destroyed. - */ - @Override - public void onDestroyView() { - super.onDestroyView(); - map.onDestroy(); - } - - /** - * Sets a callback object which will be triggered when the MapboxMap instance is ready to be used. - * - * @param onMapReadyCallback The callback to be invoked. - */ - public void getMapAsync(@NonNull final OnMapReadyCallback onMapReadyCallback) { - this.onMapReadyCallback = onMapReadyCallback; + return map = new MapView(inflater.getContext(), options); + } + + /** + * <p> + * Returns the Mapbox access token set in the app resources. + * </p> + * It will first search the application manifest for a {@link MapboxConstants#KEY_META_DATA_MANIFEST} + * meta-data value. If not found it will then attempt to load the access token from the + * {@code res/raw/token.txt} development file. + * + * @param context The {@link Context} of the {@link android.app.Activity} or {@link android.app.Fragment}. + * @return The Mapbox access token or null if not found. + * @see MapboxConstants#KEY_META_DATA_MANIFEST + * @deprecated As of release 4.1.0, replaced by + * {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)} + */ + @Deprecated + private String getToken(@NonNull Context context) { + try { + // read out AndroidManifest + PackageManager packageManager = context.getPackageManager(); + ApplicationInfo appInfo = packageManager.getApplicationInfo(context.getPackageName(), + PackageManager.GET_META_DATA); + String token = appInfo.metaData.getString(MapboxConstants.KEY_META_DATA_MANIFEST); + if (token == null || token.isEmpty()) { + throw new IllegalArgumentException(); + } + return token; + } catch (Exception exception) { + // use fallback on string resource, used for development + int tokenResId = context.getResources().getIdentifier("mapbox_access_token", "string", context.getPackageName()); + return tokenResId != 0 ? context.getString(tokenResId) : null; } + } + + /** + * Called when the fragment view hierarchy is created. + * + * @param view The content view of the fragment + * @param savedInstanceState THe saved instance state of the framgnt + */ + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + map.onCreate(savedInstanceState); + } + + /** + * Called when the fragment is visible for the users. + */ + @Override + public void onStart() { + super.onStart(); + map.onStart(); + map.getMapAsync(onMapReadyCallback); + } + + /** + * Called when the fragment is ready to be interacted with. + */ + @Override + public void onResume() { + super.onResume(); + map.onResume(); + } + + /** + * Called when the fragment is pausing. + */ + @Override + public void onPause() { + super.onPause(); + map.onPause(); + } + + /** + * Called when the fragment state needs to be saved. + * + * @param outState The saved state + */ + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + map.onSaveInstanceState(outState); + } + + /** + * Called when the fragment is no longer visible for the user. + */ + @Override + public void onStop() { + super.onStop(); + map.onStop(); + } + + /** + * Called when the fragment receives onLowMemory call from the hosting Activity. + */ + @Override + public void onLowMemory() { + super.onLowMemory(); + map.onLowMemory(); + } + + /** + * Called when the fragment is view hiearchy is being destroyed. + */ + @Override + public void onDestroyView() { + super.onDestroyView(); + map.onDestroy(); + } + + /** + * Sets a callback object which will be triggered when the MapboxMap instance is ready to be used. + * + * @param onMapReadyCallback The callback to be invoked. + */ + public void getMapAsync(@NonNull final OnMapReadyCallback onMapReadyCallback) { + this.onMapReadyCallback = onMapReadyCallback; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java index 157a1c4a19..398093344b 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java @@ -24,577 +24,585 @@ import com.mapbox.mapboxsdk.telemetry.MapboxEvent; */ final class MapGestureDetector { - private final Transform transform; - private final Projection projection; - private final UiSettings uiSettings; - private final TrackingSettings trackingSettings; - private final AnnotationManager annotationManager; - - private final GestureDetectorCompat gestureDetector; - private final ScaleGestureDetector scaleGestureDetector; - private final RotateGestureDetector rotateGestureDetector; - private final ShoveGestureDetector shoveGestureDetector; - - private MapboxMap.OnMapClickListener onMapClickListener; - private MapboxMap.OnMapLongClickListener onMapLongClickListener; - private MapboxMap.OnFlingListener onFlingListener; - private MapboxMap.OnScrollListener onScrollListener; - - private PointF focalPoint; - - private boolean twoTap = false; - private boolean zoomStarted = false; - private boolean dragStarted = false; - private boolean quickZoom = false; - private boolean scrollInProgress = false; - - MapGestureDetector(Context context, Transform transform, Projection projection, UiSettings uiSettings, - TrackingSettings trackingSettings, AnnotationManager annotationManager) { - this.annotationManager = annotationManager; - this.transform = transform; - this.projection = projection; - this.uiSettings = uiSettings; - this.trackingSettings = trackingSettings; - - // Touch gesture detectors - gestureDetector = new GestureDetectorCompat(context, new GestureListener()); - gestureDetector.setIsLongpressEnabled(true); - scaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureListener()); - ScaleGestureDetectorCompat.setQuickScaleEnabled(scaleGestureDetector, true); - rotateGestureDetector = new RotateGestureDetector(context, new RotateGestureListener()); - shoveGestureDetector = new ShoveGestureDetector(context, new ShoveGestureListener()); + private final Transform transform; + private final Projection projection; + private final UiSettings uiSettings; + private final TrackingSettings trackingSettings; + private final AnnotationManager annotationManager; + + private final GestureDetectorCompat gestureDetector; + private final ScaleGestureDetector scaleGestureDetector; + private final RotateGestureDetector rotateGestureDetector; + private final ShoveGestureDetector shoveGestureDetector; + + private MapboxMap.OnMapClickListener onMapClickListener; + private MapboxMap.OnMapLongClickListener onMapLongClickListener; + private MapboxMap.OnFlingListener onFlingListener; + private MapboxMap.OnScrollListener onScrollListener; + + private PointF focalPoint; + + private boolean twoTap = false; + private boolean zoomStarted = false; + private boolean dragStarted = false; + private boolean quickZoom = false; + private boolean scrollInProgress = false; + + MapGestureDetector(Context context, Transform transform, Projection projection, UiSettings uiSettings, + TrackingSettings trackingSettings, AnnotationManager annotationManager) { + this.annotationManager = annotationManager; + this.transform = transform; + this.projection = projection; + this.uiSettings = uiSettings; + this.trackingSettings = trackingSettings; + + // Touch gesture detectors + gestureDetector = new GestureDetectorCompat(context, new GestureListener()); + gestureDetector.setIsLongpressEnabled(true); + scaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureListener()); + ScaleGestureDetectorCompat.setQuickScaleEnabled(scaleGestureDetector, true); + rotateGestureDetector = new RotateGestureDetector(context, new RotateGestureListener()); + shoveGestureDetector = new ShoveGestureDetector(context, new ShoveGestureListener()); + } + + /** + * Set the gesture focal point. + * <p> + * this is the center point used for calculate transformations from gestures, value is + * overridden if end user provides his own through {@link UiSettings#setFocalPoint(PointF)}. + * </p> + * + * @param focalPoint the center point for gestures + */ + void setFocalPoint(PointF focalPoint) { + if (focalPoint == null) { + // resetting focal point, + if (uiSettings.getFocalPoint() != null) { + // using user provided one to reset + focalPoint = uiSettings.getFocalPoint(); + } + } + this.focalPoint = focalPoint; + } + + + /** + * Called when user touches the screen, all positions are absolute. + * <p> + * Forwards event to the related gesture detectors. + * </p> + * + * @param event the MotionEvent + * @return True if touch event is handled + */ + boolean onTouchEvent(@NonNull MotionEvent event) { + // Check and ignore non touch or left clicks + if ((event.getButtonState() != 0) && (event.getButtonState() != MotionEvent.BUTTON_PRIMARY)) { + return false; } - /** - * Set the gesture focal point. - * <p> - * this is the center point used for calculate transformations from gestures, value is - * overridden if end user provides his own through {@link UiSettings#setFocalPoint(PointF)}. - * </p> - * - * @param focalPoint the center point for gestures - */ - void setFocalPoint(PointF focalPoint) { - if (focalPoint == null) { - // resetting focal point, - if (uiSettings.getFocalPoint() != null) { - // using user provided one to reset - focalPoint = uiSettings.getFocalPoint(); - } + // Check two finger gestures first + rotateGestureDetector.onTouchEvent(event); + scaleGestureDetector.onTouchEvent(event); + shoveGestureDetector.onTouchEvent(event); + + // Handle two finger tap + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + // First pointer down + transform.setGestureInProgress(true); + break; + + case MotionEvent.ACTION_POINTER_DOWN: + // Second pointer down + twoTap = event.getPointerCount() == 2 + && uiSettings.isZoomGesturesEnabled(); + if (twoTap) { + // Confirmed 2nd Finger Down + MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_TWO_FINGER_SINGLETAP, event.getX(), + event.getY(), transform.getZoom()); + } + break; + + case MotionEvent.ACTION_POINTER_UP: + // Second pointer up + break; + + case MotionEvent.ACTION_UP: + // First pointer up + long tapInterval = event.getEventTime() - event.getDownTime(); + boolean isTap = tapInterval <= ViewConfiguration.getTapTimeout(); + boolean inProgress = rotateGestureDetector.isInProgress() + || scaleGestureDetector.isInProgress() + || shoveGestureDetector.isInProgress(); + + if (twoTap && isTap && !inProgress) { + if (focalPoint != null) { + transform.zoom(false, focalPoint.x, focalPoint.y); + } else { + PointF focalPoint = TwoFingerGestureDetector.determineFocalPoint(event); + transform.zoom(false, focalPoint.x, focalPoint.y); + } + twoTap = false; + return true; + } + + // Scroll / Pan Has Stopped + if (scrollInProgress) { + MapboxEvent.trackGestureDragEndEvent(projection, event.getX(), event.getY(), transform.getZoom()); + scrollInProgress = false; } - this.focalPoint = focalPoint; - } + twoTap = false; + transform.setGestureInProgress(false); + break; - /** - * Called when user touches the screen, all positions are absolute. - * <p> - * Forwards event to the related gesture detectors. - * </p> - * - * @param event the MotionEvent - * @return True if touch event is handled - */ - boolean onTouchEvent(@NonNull MotionEvent event) { - // Check and ignore non touch or left clicks - if ((event.getButtonState() != 0) && (event.getButtonState() != MotionEvent.BUTTON_PRIMARY)) { + case MotionEvent.ACTION_CANCEL: + twoTap = false; + transform.setGestureInProgress(false); + break; + } + + return gestureDetector.onTouchEvent(event); + } + + /** + * Called for events that don't fit the other handlers. + * <p> + * Examples of such events are mouse scroll events, mouse moves, joystick & trackpad. + * </p> + * + * @param event The MotionEvent occured + * @return True is the event is handled + */ + boolean onGenericMotionEvent(MotionEvent event) { + // Mouse events + //if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { // this is not available before API 18 + if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == InputDevice.SOURCE_CLASS_POINTER) { + // Choose the action + switch (event.getActionMasked()) { + // Mouse scrolls + case MotionEvent.ACTION_SCROLL: + if (!uiSettings.isZoomGesturesEnabled()) { return false; - } + } - // Check two finger gestures first - rotateGestureDetector.onTouchEvent(event); - scaleGestureDetector.onTouchEvent(event); - shoveGestureDetector.onTouchEvent(event); - - // Handle two finger tap - switch (event.getActionMasked()) { - case MotionEvent.ACTION_DOWN: - // First pointer down - transform.setGestureInProgress(true); - break; - - case MotionEvent.ACTION_POINTER_DOWN: - // Second pointer down - twoTap = event.getPointerCount() == 2 - && uiSettings.isZoomGesturesEnabled(); - if (twoTap) { - // Confirmed 2nd Finger Down - MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_TWO_FINGER_SINGLETAP, event.getX(), event.getY(), transform.getZoom()); - } - break; - - case MotionEvent.ACTION_POINTER_UP: - // Second pointer up - break; - - case MotionEvent.ACTION_UP: - // First pointer up - long tapInterval = event.getEventTime() - event.getDownTime(); - boolean isTap = tapInterval <= ViewConfiguration.getTapTimeout(); - boolean inProgress = rotateGestureDetector.isInProgress() - || scaleGestureDetector.isInProgress() - || shoveGestureDetector.isInProgress(); - - if (twoTap && isTap && !inProgress) { - if (focalPoint != null) { - transform.zoom(false, focalPoint.x, focalPoint.y); - } else { - PointF focalPoint = TwoFingerGestureDetector.determineFocalPoint(event); - transform.zoom(false, focalPoint.x, focalPoint.y); - } - twoTap = false; - return true; - } - - // Scroll / Pan Has Stopped - if (scrollInProgress) { - MapboxEvent.trackGestureDragEndEvent(projection, event.getX(), event.getY(), transform.getZoom()); - scrollInProgress = false; - } - - twoTap = false; - transform.setGestureInProgress(false); - break; - - case MotionEvent.ACTION_CANCEL: - twoTap = false; - transform.setGestureInProgress(false); - break; - } + // Cancel any animation + transform.cancelTransitions(); + + // Get the vertical scroll amount, one click = 1 + float scrollDist = event.getAxisValue(MotionEvent.AXIS_VSCROLL); - return gestureDetector.onTouchEvent(event); + // Scale the map by the appropriate power of two factor + transform.zoomBy(Math.pow(2.0, scrollDist), event.getX(), event.getY()); + + return true; + + default: + // We are not interested in this event + return false; + } } - /** - * Called for events that don't fit the other handlers. - * <p> - * Examples of such events are mouse scroll events, mouse moves, joystick & trackpad. - * </p> - * - * @param event The MotionEvent occured - * @return True is the event is handled - */ - boolean onGenericMotionEvent(MotionEvent event) { - // Mouse events - //if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { // this is not available before API 18 - if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == InputDevice.SOURCE_CLASS_POINTER) { - // Choose the action - switch (event.getActionMasked()) { - // Mouse scrolls - case MotionEvent.ACTION_SCROLL: - if (!uiSettings.isZoomGesturesEnabled()) { - return false; - } - - // Cancel any animation - transform.cancelTransitions(); - - // Get the vertical scroll amount, one click = 1 - float scrollDist = event.getAxisValue(MotionEvent.AXIS_VSCROLL); - - // Scale the map by the appropriate power of two factor - transform.zoomBy(Math.pow(2.0, scrollDist), event.getX(), event.getY()); - - return true; - - default: - // We are not interested in this event - return false; - } - } + // We are not interested in this event + return false; + } + + + /** + * Responsible for handling one finger gestures. + */ + private class GestureListener extends android.view.GestureDetector.SimpleOnGestureListener { - // We are not interested in this event + @Override + public boolean onDown(MotionEvent event) { + return true; + } + + @Override + public boolean onDoubleTapEvent(MotionEvent motionEvent) { + if (!uiSettings.isZoomGesturesEnabled()) { return false; + } + + switch (motionEvent.getAction()) { + case MotionEvent.ACTION_DOWN: + break; + case MotionEvent.ACTION_MOVE: + break; + case MotionEvent.ACTION_UP: + if (quickZoom) { + // insert here? + quickZoom = false; + break; + } + + // Single finger double tap + if (focalPoint != null) { + // User provided focal point + transform.zoom(true, focalPoint.x, focalPoint.y); + } else { + // Zoom in on gesture + transform.zoom(true, motionEvent.getX(), motionEvent.getY()); + } + break; + } + + MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_DOUBLETAP, motionEvent.getX(), motionEvent.getY(), + transform.getZoom()); + + return true; } + @Override + public boolean onSingleTapUp(MotionEvent motionEvent) { + // Cancel any animation + transform.cancelTransitions(); + return true; + } - /** - * Responsible for handling one finger gestures. - */ - private class GestureListener extends android.view.GestureDetector.SimpleOnGestureListener { + @Override + public boolean onSingleTapConfirmed(MotionEvent motionEvent) { + PointF tapPoint = new PointF(motionEvent.getX(), motionEvent.getY()); + boolean tapHandled = annotationManager.onTap(tapPoint, uiSettings.getPixelRatio()); - @Override - public boolean onDown(MotionEvent event) { - return true; + if (!tapHandled) { + if (uiSettings.isDeselectMarkersOnTap()) { + // deselect any selected marker + annotationManager.deselectMarkers(); } - @Override - public boolean onDoubleTapEvent(MotionEvent e) { - if (!uiSettings.isZoomGesturesEnabled()) { - return false; - } - - switch (e.getAction()) { - case MotionEvent.ACTION_DOWN: - break; - case MotionEvent.ACTION_MOVE: - break; - case MotionEvent.ACTION_UP: - if (quickZoom) { - // insert here? - quickZoom = false; - break; - } - - // Single finger double tap - if (focalPoint != null) { - // User provided focal point - transform.zoom(true, focalPoint.x, focalPoint.y); - } else { - // Zoom in on gesture - transform.zoom(true, e.getX(), e.getY()); - } - break; - } - - MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_DOUBLETAP, e.getX(), e.getY(), transform.getZoom()); - - return true; + // notify app of map click + if (onMapClickListener != null) { + onMapClickListener.onMapClick(projection.fromScreenLocation(tapPoint)); } + } - @Override - public boolean onSingleTapUp(MotionEvent motionEvent) { - // Cancel any animation - transform.cancelTransitions(); - return true; - } + MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_SINGLETAP, motionEvent.getX(), motionEvent.getY(), + transform.getZoom()); + return true; + } - @Override - public boolean onSingleTapConfirmed(MotionEvent motionEvent) { - PointF tapPoint = new PointF(motionEvent.getX(), motionEvent.getY()); - boolean tapHandled = annotationManager.onTap(tapPoint, uiSettings.getPixelRatio()); - - if (!tapHandled) { - if (uiSettings.isDeselectMarkersOnTap()) { - // deselect any selected marker - annotationManager.deselectMarkers(); - } - - // notify app of map click - if (onMapClickListener != null) { - onMapClickListener.onMapClick(projection.fromScreenLocation(tapPoint)); - } - } - - MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_SINGLETAP, motionEvent.getX(), motionEvent.getY(), transform.getZoom()); - return true; - } + @Override + public void onLongPress(MotionEvent motionEvent) { + if (onMapLongClickListener != null && !quickZoom) { + onMapLongClickListener.onMapLongClick(projection.fromScreenLocation(new PointF(motionEvent.getX(), + motionEvent.getY()))); + } + } - @Override - public void onLongPress(MotionEvent motionEvent) { - if (onMapLongClickListener != null && !quickZoom) { - onMapLongClickListener.onMapLongClick(projection.fromScreenLocation(new PointF(motionEvent.getX(), motionEvent.getY()))); - } - } + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + if (!trackingSettings.isScrollGestureCurrentlyEnabled()) { + return false; + } - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { - if (!trackingSettings.isScrollGestureCurrentlyEnabled()) { - return false; - } + trackingSettings.resetTrackingModesIfRequired(true, false); - trackingSettings.resetTrackingModesIfRequired(true, false); + // Cancel any animation + transform.cancelTransitions(); - // Cancel any animation - transform.cancelTransitions(); + float screenDensity = uiSettings.getPixelRatio(); - float screenDensity = uiSettings.getPixelRatio(); + double tilt = transform.getTilt(); + // tilt results in a bigger translation, need to limit input #5281, limitFactor ranges from 2 -> 8 + double limitFactor = 2 + ((tilt != 0) ? (tilt / 10) : 0); + double offsetX = velocityX / limitFactor / screenDensity; + double offsetY = velocityY / limitFactor / screenDensity; - double tilt = transform.getTilt(); - // tilt results in a bigger translation, need to limit input #5281, limitFactor ranges from 2 -> 8 - double limitFactor = 2 + ((tilt != 0) ? (tilt / 10) : 0); - double offsetX = velocityX / limitFactor / screenDensity; - double offsetY = velocityY / limitFactor / screenDensity; + transform.setGestureInProgress(true); + transform.moveBy(offsetX, offsetY, MapboxConstants.ANIMATION_DURATION_FLING); + transform.setGestureInProgress(false); - transform.setGestureInProgress(true); - transform.moveBy(offsetX, offsetY, MapboxConstants.ANIMATION_DURATION_FLING); - transform.setGestureInProgress(false); + if (onFlingListener != null) { + onFlingListener.onFling(); + } - if (onFlingListener != null) { - onFlingListener.onFling(); - } + MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_PAN_START, e1.getX(), e1.getY(), + transform.getZoom()); + return true; + } - MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_PAN_START, e1.getX(), e1.getY(), transform.getZoom()); - return true; - } + // Called for drags + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + if (!scrollInProgress) { + scrollInProgress = true; + } + if (!trackingSettings.isScrollGestureCurrentlyEnabled()) { + return false; + } - // Called for drags - @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { - if (!scrollInProgress) { - scrollInProgress = true; - } - if (!trackingSettings.isScrollGestureCurrentlyEnabled()) { - return false; - } - - if (dragStarted) { - return false; - } - - // reset tracking if needed - trackingSettings.resetTrackingModesIfRequired(true, false); - // Cancel any animation - transform.cancelTransitions(); - - // Scroll the map - transform.moveBy(-distanceX, -distanceY, 0 /*no duration*/); - - if (onScrollListener != null) { - onScrollListener.onScroll(); - } - return true; - } + if (dragStarted) { + return false; + } + + // reset tracking if needed + trackingSettings.resetTrackingModesIfRequired(true, false); + // Cancel any animation + transform.cancelTransitions(); + + // Scroll the map + transform.moveBy(-distanceX, -distanceY, 0 /*no duration*/); + + if (onScrollListener != null) { + onScrollListener.onScroll(); + } + return true; } + } - /** - * Responsible for handling two finger gestures and double-tap drag gestures. - */ - private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { + /** + * Responsible for handling two finger gestures and double-tap drag gestures. + */ + private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { - long beginTime = 0; - float scaleFactor = 1.0f; + long beginTime = 0; + float scaleFactor = 1.0f; - // Called when two fingers first touch the screen - @Override - public boolean onScaleBegin(ScaleGestureDetector detector) { - if (!uiSettings.isZoomGesturesEnabled()) { - return false; - } + // Called when two fingers first touch the screen + @Override + public boolean onScaleBegin(ScaleGestureDetector detector) { + if (!uiSettings.isZoomGesturesEnabled()) { + return false; + } - beginTime = detector.getEventTime(); - MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_PINCH_START, detector.getFocusX(), detector.getFocusY(), transform.getZoom()); - return true; - } + beginTime = detector.getEventTime(); + MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_PINCH_START, detector.getFocusX(), + detector.getFocusY(), transform.getZoom()); + return true; + } - // Called when fingers leave screen - @Override - public void onScaleEnd(ScaleGestureDetector detector) { - beginTime = 0; - scaleFactor = 1.0f; - zoomStarted = false; - } + // Called when fingers leave screen + @Override + public void onScaleEnd(ScaleGestureDetector detector) { + beginTime = 0; + scaleFactor = 1.0f; + zoomStarted = false; + } - // Called each time a finger moves - // Called for pinch zooms and quickzooms/quickscales - @Override - public boolean onScale(ScaleGestureDetector detector) { - if (!uiSettings.isZoomGesturesEnabled()) { - return super.onScale(detector); - } - - // If scale is large enough ignore a tap - scaleFactor *= detector.getScaleFactor(); - if ((scaleFactor > 1.05f) || (scaleFactor < 0.95f)) { - zoomStarted = true; - } - - // Ignore short touches in case it is a tap - // Also ignore small scales - long time = detector.getEventTime(); - long interval = time - beginTime; - if (!zoomStarted && (interval <= ViewConfiguration.getTapTimeout())) { - return false; - } - - if (!zoomStarted) { - return false; - } - - if (dragStarted) { - return false; - } - - // Cancel any animation - transform.cancelTransitions(); - - // Gesture is a quickzoom if there aren't two fingers - quickZoom = !twoTap; - - // make an assumption here; if the zoom center is specified by the gesture, it's NOT going - // to be in the center of the map. Therefore the zoom will translate the map center, so tracking - // should be disabled. - - trackingSettings.resetTrackingModesIfRequired(!quickZoom, false); - // Scale the map - if (focalPoint != null) { - // arround user provided focal point - transform.zoomBy(detector.getScaleFactor(), focalPoint.x, focalPoint.y); - } else if (quickZoom) { - // around center map - transform.zoomBy(detector.getScaleFactor(), uiSettings.getWidth() / 2, uiSettings.getHeight() / 2); - } else { - // around gesture - transform.zoomBy(detector.getScaleFactor(), detector.getFocusX(), detector.getFocusY()); - } - - return true; - } + // Called each time a finger moves + // Called for pinch zooms and quickzooms/quickscales + @Override + public boolean onScale(ScaleGestureDetector detector) { + if (!uiSettings.isZoomGesturesEnabled()) { + return super.onScale(detector); + } + + // If scale is large enough ignore a tap + scaleFactor *= detector.getScaleFactor(); + if ((scaleFactor > 1.05f) || (scaleFactor < 0.95f)) { + zoomStarted = true; + } + + // Ignore short touches in case it is a tap + // Also ignore small scales + long time = detector.getEventTime(); + long interval = time - beginTime; + if (!zoomStarted && (interval <= ViewConfiguration.getTapTimeout())) { + return false; + } + + if (!zoomStarted) { + return false; + } + + if (dragStarted) { + return false; + } + + // Cancel any animation + transform.cancelTransitions(); + + // Gesture is a quickzoom if there aren't two fingers + quickZoom = !twoTap; + + // make an assumption here; if the zoom center is specified by the gesture, it's NOT going + // to be in the center of the map. Therefore the zoom will translate the map center, so tracking + // should be disabled. + + trackingSettings.resetTrackingModesIfRequired(!quickZoom, false); + // Scale the map + if (focalPoint != null) { + // arround user provided focal point + transform.zoomBy(detector.getScaleFactor(), focalPoint.x, focalPoint.y); + } else if (quickZoom) { + // around center map + transform.zoomBy(detector.getScaleFactor(), uiSettings.getWidth() / 2, uiSettings.getHeight() / 2); + } else { + // around gesture + transform.zoomBy(detector.getScaleFactor(), detector.getFocusX(), detector.getFocusY()); + } + + return true; } + } - /** - * Responsible for handling rotation gestures. - */ - private class RotateGestureListener extends RotateGestureDetector.SimpleOnRotateGestureListener { - - long beginTime = 0; - float totalAngle = 0.0f; - boolean started = false; - - // Called when two fingers first touch the screen - @Override - public boolean onRotateBegin(RotateGestureDetector detector) { - if (!trackingSettings.isRotateGestureCurrentlyEnabled()) { - return false; - } - - beginTime = detector.getEventTime(); - MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_ROTATION_START, detector.getFocusX(), detector.getFocusY(), transform.getZoom()); - return true; - } + /** + * Responsible for handling rotation gestures. + */ + private class RotateGestureListener extends RotateGestureDetector.SimpleOnRotateGestureListener { - // Called when the fingers leave the screen - @Override - public void onRotateEnd(RotateGestureDetector detector) { - beginTime = 0; - totalAngle = 0.0f; - started = false; - } + long beginTime = 0; + float totalAngle = 0.0f; + boolean started = false; - // Called each time one of the two fingers moves - // Called for rotation - @Override - public boolean onRotate(RotateGestureDetector detector) { - if (!trackingSettings.isRotateGestureCurrentlyEnabled() || dragStarted) { - return false; - } - - // If rotate is large enough ignore a tap - // Also is zoom already started, don't rotate - totalAngle += detector.getRotationDegreesDelta(); - if (!zoomStarted && ((totalAngle > 20.0f) || (totalAngle < -20.0f))) { - started = true; - } - - // Ignore short touches in case it is a tap - // Also ignore small rotate - long time = detector.getEventTime(); - long interval = time - beginTime; - if (!started && (interval <= ViewConfiguration.getTapTimeout())) { - return false; - } - - if (!started) { - return false; - } - - // Cancel any animation - transform.cancelTransitions(); - - // rotation constitutes translation of anything except the center of - // rotation, so cancel both location and bearing tracking if required - - trackingSettings.resetTrackingModesIfRequired(true, true); - - // Get rotate value - double bearing = transform.getRawBearing(); - bearing += detector.getRotationDegreesDelta(); - - // Rotate the map - if (focalPoint != null) { - // User provided focal point - transform.setBearing(bearing, focalPoint.x, focalPoint.y); - } else { - // around gesture - transform.setBearing(bearing, detector.getFocusX(), detector.getFocusY()); - } - return true; - } + // Called when two fingers first touch the screen + @Override + public boolean onRotateBegin(RotateGestureDetector detector) { + if (!trackingSettings.isRotateGestureCurrentlyEnabled()) { + return false; + } + + beginTime = detector.getEventTime(); + MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_ROTATION_START, detector.getFocusX(), + detector.getFocusY(), transform.getZoom()); + return true; } - /** - * Responsible for handling 2 finger shove gestures. - */ - private class ShoveGestureListener implements ShoveGestureDetector.OnShoveGestureListener { + // Called when the fingers leave the screen + @Override + public void onRotateEnd(RotateGestureDetector detector) { + beginTime = 0; + totalAngle = 0.0f; + started = false; + } - long beginTime = 0; - float totalDelta = 0.0f; - boolean started = false; + // Called each time one of the two fingers moves + // Called for rotation + @Override + public boolean onRotate(RotateGestureDetector detector) { + if (!trackingSettings.isRotateGestureCurrentlyEnabled() || dragStarted) { + return false; + } + + // If rotate is large enough ignore a tap + // Also is zoom already started, don't rotate + totalAngle += detector.getRotationDegreesDelta(); + if (!zoomStarted && ((totalAngle > 20.0f) || (totalAngle < -20.0f))) { + started = true; + } + + // Ignore short touches in case it is a tap + // Also ignore small rotate + long time = detector.getEventTime(); + long interval = time - beginTime; + if (!started && (interval <= ViewConfiguration.getTapTimeout())) { + return false; + } - @Override - public boolean onShoveBegin(ShoveGestureDetector detector) { - if (!uiSettings.isTiltGesturesEnabled()) { - return false; - } + if (!started) { + return false; + } - beginTime = detector.getEventTime(); - MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_PITCH_START, detector.getFocusX(), detector.getFocusY(), transform.getZoom()); - return true; - } + // Cancel any animation + transform.cancelTransitions(); - @Override - public void onShoveEnd(ShoveGestureDetector detector) { - beginTime = 0; - totalDelta = 0.0f; - started = false; - dragStarted = false; - } + // rotation constitutes translation of anything except the center of + // rotation, so cancel both location and bearing tracking if required - @Override - public boolean onShove(ShoveGestureDetector detector) { - if (!uiSettings.isTiltGesturesEnabled()) { - return false; - } - - // If tilt is large enough ignore a tap - // Also if zoom already started, don't tilt - totalDelta += detector.getShovePixelsDelta(); - if (!zoomStarted && ((totalDelta > 10.0f) || (totalDelta < -10.0f))) { - started = true; - } - - // Ignore short touches in case it is a tap - // Also ignore small tilt - long time = detector.getEventTime(); - long interval = time - beginTime; - if (!started && (interval <= ViewConfiguration.getTapTimeout())) { - return false; - } - - if (!started) { - return false; - } - - // Cancel any animation - transform.cancelTransitions(); - - // Get tilt value (scale and clamp) - double pitch = transform.getTilt(); - pitch -= 0.1 * detector.getShovePixelsDelta(); - pitch = Math.max(MapboxConstants.MINIMUM_TILT, Math.min(MapboxConstants.MAXIMUM_TILT, pitch)); - - // Tilt the map - transform.setTilt(pitch); - - dragStarted = true; - - return true; - } - } + trackingSettings.resetTrackingModesIfRequired(true, true); - void setOnMapClickListener(MapboxMap.OnMapClickListener onMapClickListener) { - this.onMapClickListener = onMapClickListener; + // Get rotate value + double bearing = transform.getRawBearing(); + bearing += detector.getRotationDegreesDelta(); + + // Rotate the map + if (focalPoint != null) { + // User provided focal point + transform.setBearing(bearing, focalPoint.x, focalPoint.y); + } else { + // around gesture + transform.setBearing(bearing, detector.getFocusX(), detector.getFocusY()); + } + return true; } + } + + /** + * Responsible for handling 2 finger shove gestures. + */ + private class ShoveGestureListener implements ShoveGestureDetector.OnShoveGestureListener { + + long beginTime = 0; + float totalDelta = 0.0f; + boolean started = false; + + @Override + public boolean onShoveBegin(ShoveGestureDetector detector) { + if (!uiSettings.isTiltGesturesEnabled()) { + return false; + } - void setOnMapLongClickListener(MapboxMap.OnMapLongClickListener onMapLongClickListener) { - this.onMapLongClickListener = onMapLongClickListener; + beginTime = detector.getEventTime(); + MapboxEvent.trackGestureEvent(projection, MapboxEvent.GESTURE_PITCH_START, detector.getFocusX(), + detector.getFocusY(), transform.getZoom()); + return true; } - void setOnFlingListener(MapboxMap.OnFlingListener onFlingListener) { - this.onFlingListener = onFlingListener; + @Override + public void onShoveEnd(ShoveGestureDetector detector) { + beginTime = 0; + totalDelta = 0.0f; + started = false; + dragStarted = false; } - void setOnScrollListener(MapboxMap.OnScrollListener onScrollListener) { - this.onScrollListener = onScrollListener; + @Override + public boolean onShove(ShoveGestureDetector detector) { + if (!uiSettings.isTiltGesturesEnabled()) { + return false; + } + + // If tilt is large enough ignore a tap + // Also if zoom already started, don't tilt + totalDelta += detector.getShovePixelsDelta(); + if (!zoomStarted && ((totalDelta > 10.0f) || (totalDelta < -10.0f))) { + started = true; + } + + // Ignore short touches in case it is a tap + // Also ignore small tilt + long time = detector.getEventTime(); + long interval = time - beginTime; + if (!started && (interval <= ViewConfiguration.getTapTimeout())) { + return false; + } + + if (!started) { + return false; + } + + // Cancel any animation + transform.cancelTransitions(); + + // Get tilt value (scale and clamp) + double pitch = transform.getTilt(); + pitch -= 0.1 * detector.getShovePixelsDelta(); + pitch = Math.max(MapboxConstants.MINIMUM_TILT, Math.min(MapboxConstants.MAXIMUM_TILT, pitch)); + + // Tilt the map + transform.setTilt(pitch); + + dragStarted = true; + + return true; } + } + + void setOnMapClickListener(MapboxMap.OnMapClickListener onMapClickListener) { + this.onMapClickListener = onMapClickListener; + } + + void setOnMapLongClickListener(MapboxMap.OnMapLongClickListener onMapLongClickListener) { + this.onMapLongClickListener = onMapLongClickListener; + } + + void setOnFlingListener(MapboxMap.OnFlingListener onFlingListener) { + this.onFlingListener = onFlingListener; + } + + void setOnScrollListener(MapboxMap.OnScrollListener onScrollListener) { + this.onScrollListener = onScrollListener; + } }
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java index 09b4a2c9ca..c993cd3ec6 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java @@ -18,247 +18,248 @@ import android.view.ViewConfiguration; */ final class MapKeyListener { - private final TrackingSettings trackingSettings; - private final Transform transform; - private final UiSettings uiSettings; + private final TrackingSettings trackingSettings; + private final Transform transform; + private final UiSettings uiSettings; + + private TrackballLongPressTimeOut currentTrackballLongPressTimeOut; + + MapKeyListener(@NonNull Transform transform, @NonNull TrackingSettings trackingSettings, + @NonNull UiSettings uiSettings) { + this.transform = transform; + this.trackingSettings = trackingSettings; + this.uiSettings = uiSettings; + } + + /** + * Called when the user presses a key, alse called for repeated keys held down. + * + * @param keyCode the id of the pressed key + * @param event the related key event + * @return true if the wevent is handled + */ + boolean onKeyDown(int keyCode, @NonNull KeyEvent event) { + // If the user has held the scroll key down for a while then accelerate + // the scroll speed + double scrollDist = event.getRepeatCount() >= 5 ? 50.0 : 10.0; + + // Check which key was pressed via hardware/real key code + switch (keyCode) { + // Tell the system to track these keys for long presses on + // onKeyLongPress is fired + case KeyEvent.KEYCODE_ENTER: + case KeyEvent.KEYCODE_DPAD_CENTER: + event.startTracking(); + return true; + + case KeyEvent.KEYCODE_DPAD_LEFT: + if (!trackingSettings.isScrollGestureCurrentlyEnabled()) { + return false; + } - private TrackballLongPressTimeOut currentTrackballLongPressTimeOut; + // Cancel any animation + transform.cancelTransitions(); - MapKeyListener(@NonNull Transform transform, @NonNull TrackingSettings trackingSettings, @NonNull UiSettings uiSettings) { - this.transform = transform; - this.trackingSettings = trackingSettings; - this.uiSettings = uiSettings; - } + // Move left + transform.moveBy(scrollDist, 0.0, 0 /*no animation*/); + return true; - /** - * Called when the user presses a key, alse called for repeated keys held down. - * - * @param keyCode the id of the pressed key - * @param event the related key event - * @return true if the wevent is handled - */ - boolean onKeyDown(int keyCode, @NonNull KeyEvent event) { - // If the user has held the scroll key down for a while then accelerate - // the scroll speed - double scrollDist = event.getRepeatCount() >= 5 ? 50.0 : 10.0; - - // Check which key was pressed via hardware/real key code - switch (keyCode) { - // Tell the system to track these keys for long presses on - // onKeyLongPress is fired - case KeyEvent.KEYCODE_ENTER: - case KeyEvent.KEYCODE_DPAD_CENTER: - event.startTracking(); - return true; - - case KeyEvent.KEYCODE_DPAD_LEFT: - if (!trackingSettings.isScrollGestureCurrentlyEnabled()) { - return false; - } - - // Cancel any animation - transform.cancelTransitions(); - - // Move left - transform.moveBy(scrollDist, 0.0, 0 /*no animation*/); - return true; - - case KeyEvent.KEYCODE_DPAD_RIGHT: - if (!trackingSettings.isScrollGestureCurrentlyEnabled()) { - return false; - } - - // Cancel any animation - transform.cancelTransitions(); - - // Move right - transform.moveBy(-scrollDist, 0.0, 0 /*no animation*/); - return true; - - case KeyEvent.KEYCODE_DPAD_UP: - if (!trackingSettings.isScrollGestureCurrentlyEnabled()) { - return false; - } - - // Cancel any animation - transform.cancelTransitions(); - - // Move up - transform.moveBy(0.0, scrollDist, 0 /*no animation*/); - return true; - - case KeyEvent.KEYCODE_DPAD_DOWN: - if (!trackingSettings.isScrollGestureCurrentlyEnabled()) { - return false; - } - - // Cancel any animation - transform.cancelTransitions(); - - // Move down - transform.moveBy(0.0, -scrollDist, 0 /*no animation*/); - return true; - - default: - // We are not interested in this key - return false; + case KeyEvent.KEYCODE_DPAD_RIGHT: + if (!trackingSettings.isScrollGestureCurrentlyEnabled()) { + return false; } - } - /** - * Called when the user long presses a key that is being tracked. - * - * @param keyCode the id of the long pressed key - * @param event the related key event - * @return true if event is handled - */ - boolean onKeyLongPress(int keyCode, KeyEvent event) { - // Check which key was pressed via hardware/real key code - switch (keyCode) { - // Tell the system to track these keys for long presses on - // onKeyLongPress is fired - case KeyEvent.KEYCODE_ENTER: - case KeyEvent.KEYCODE_DPAD_CENTER: - if (!uiSettings.isZoomGesturesEnabled()) { - return false; - } - - // Zoom out - transform.zoom(false, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2); - return true; - - default: - // We are not interested in this key - return false; + // Cancel any animation + transform.cancelTransitions(); + + // Move right + transform.moveBy(-scrollDist, 0.0, 0 /*no animation*/); + return true; + + case KeyEvent.KEYCODE_DPAD_UP: + if (!trackingSettings.isScrollGestureCurrentlyEnabled()) { + return false; } - } - /** - * Called when the user releases a key. - * - * @param keyCode the id of the released key - * @param event the related key event - * @return true if the event is handled - */ - boolean onKeyUp(int keyCode, KeyEvent event) { - // Check if the key action was canceled (used for virtual keyboards) - if (event.isCanceled()) { - return false; + // Cancel any animation + transform.cancelTransitions(); + + // Move up + transform.moveBy(0.0, scrollDist, 0 /*no animation*/); + return true; + + case KeyEvent.KEYCODE_DPAD_DOWN: + if (!trackingSettings.isScrollGestureCurrentlyEnabled()) { + return false; } - // Check which key was pressed via hardware/real key code - // Note if keyboard does not have physical key (ie primary non-shifted - // key) then it will not appear here - // Must use the key character map as physical to character is not - // fixed/guaranteed - switch (keyCode) { - case KeyEvent.KEYCODE_ENTER: - case KeyEvent.KEYCODE_DPAD_CENTER: - if (!uiSettings.isZoomGesturesEnabled()) { - return false; - } - - // Zoom in - transform.zoom(true, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2); - return true; + // Cancel any animation + transform.cancelTransitions(); + + // Move down + transform.moveBy(0.0, -scrollDist, 0 /*no animation*/); + return true; + + default: + // We are not interested in this key + return false; + } + } + + /** + * Called when the user long presses a key that is being tracked. + * + * @param keyCode the id of the long pressed key + * @param event the related key event + * @return true if event is handled + */ + boolean onKeyLongPress(int keyCode, KeyEvent event) { + // Check which key was pressed via hardware/real key code + switch (keyCode) { + // Tell the system to track these keys for long presses on + // onKeyLongPress is fired + case KeyEvent.KEYCODE_ENTER: + case KeyEvent.KEYCODE_DPAD_CENTER: + if (!uiSettings.isZoomGesturesEnabled()) { + return false; } + // Zoom out + transform.zoom(false, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2); + return true; + + default: // We are not interested in this key return false; } + } + + /** + * Called when the user releases a key. + * + * @param keyCode the id of the released key + * @param event the related key event + * @return true if the event is handled + */ + boolean onKeyUp(int keyCode, KeyEvent event) { + // Check if the key action was canceled (used for virtual keyboards) + if (event.isCanceled()) { + return false; + } - /** - * Called for trackball events, all motions are relative in device specific units. - * - * @param event the related motion event - * @return true if the event is handled - */ - boolean onTrackballEvent(MotionEvent event) { - // Choose the action - switch (event.getActionMasked()) { - // The trackball was rotated - case MotionEvent.ACTION_MOVE: - if (!trackingSettings.isScrollGestureCurrentlyEnabled()) { - return false; - } - - // Cancel any animation - transform.cancelTransitions(); - - // Scroll the map - transform.moveBy(-10.0 * event.getX(), -10.0 * event.getY(), 0 /*no animation*/); - return true; - - // Trackball was pushed in so start tracking and tell system we are - // interested - // We will then get the up action - case MotionEvent.ACTION_DOWN: - // Set up a delayed callback to check if trackball is still - // After waiting the system long press time out - if (currentTrackballLongPressTimeOut != null) { - currentTrackballLongPressTimeOut.cancel(); - currentTrackballLongPressTimeOut = null; - } - currentTrackballLongPressTimeOut = new TrackballLongPressTimeOut(); - new Handler().postDelayed(currentTrackballLongPressTimeOut, - ViewConfiguration.getLongPressTimeout()); - return true; - - // Trackball was released - case MotionEvent.ACTION_UP: - if (!uiSettings.isZoomGesturesEnabled()) { - return false; - } - - // Only handle if we have not already long pressed - if (currentTrackballLongPressTimeOut != null) { - // Zoom in - transform.zoom(true, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2); - } - return true; - - // Trackball was cancelled - case MotionEvent.ACTION_CANCEL: - if (currentTrackballLongPressTimeOut != null) { - currentTrackballLongPressTimeOut.cancel(); - currentTrackballLongPressTimeOut = null; - } - return true; - - default: - // We are not interested in this event - return false; + // Check which key was pressed via hardware/real key code + // Note if keyboard does not have physical key (ie primary non-shifted + // key) then it will not appear here + // Must use the key character map as physical to character is not + // fixed/guaranteed + switch (keyCode) { + case KeyEvent.KEYCODE_ENTER: + case KeyEvent.KEYCODE_DPAD_CENTER: + if (!uiSettings.isZoomGesturesEnabled()) { + return false; } - } - /** - * This class implements the trackball long press time out callback - */ - private class TrackballLongPressTimeOut implements Runnable { + // Zoom in + transform.zoom(true, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2); + return true; + } - // Track if we have been cancelled - private boolean cancelled; + // We are not interested in this key + return false; + } + + /** + * Called for trackball events, all motions are relative in device specific units. + * + * @param event the related motion event + * @return true if the event is handled + */ + boolean onTrackballEvent(MotionEvent event) { + // Choose the action + switch (event.getActionMasked()) { + // The trackball was rotated + case MotionEvent.ACTION_MOVE: + if (!trackingSettings.isScrollGestureCurrentlyEnabled()) { + return false; + } - TrackballLongPressTimeOut() { - cancelled = false; + // Cancel any animation + transform.cancelTransitions(); + + // Scroll the map + transform.moveBy(-10.0 * event.getX(), -10.0 * event.getY(), 0 /*no animation*/); + return true; + + // Trackball was pushed in so start tracking and tell system we are + // interested + // We will then get the up action + case MotionEvent.ACTION_DOWN: + // Set up a delayed callback to check if trackball is still + // After waiting the system long press time out + if (currentTrackballLongPressTimeOut != null) { + currentTrackballLongPressTimeOut.cancel(); + currentTrackballLongPressTimeOut = null; + } + currentTrackballLongPressTimeOut = new TrackballLongPressTimeOut(); + new Handler().postDelayed(currentTrackballLongPressTimeOut, + ViewConfiguration.getLongPressTimeout()); + return true; + + // Trackball was released + case MotionEvent.ACTION_UP: + if (!uiSettings.isZoomGesturesEnabled()) { + return false; } - // Cancel the timeout - public void cancel() { - cancelled = true; + // Only handle if we have not already long pressed + if (currentTrackballLongPressTimeOut != null) { + // Zoom in + transform.zoom(true, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2); } + return true; - // Called when long press time out expires - @Override - public void run() { - // Check if the trackball is still pressed - if (!cancelled) { - // Zoom out - transform.zoom(false, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2); - - // Ensure the up action is not run - currentTrackballLongPressTimeOut = null; - } + // Trackball was cancelled + case MotionEvent.ACTION_CANCEL: + if (currentTrackballLongPressTimeOut != null) { + currentTrackballLongPressTimeOut.cancel(); + currentTrackballLongPressTimeOut = null; } + return true; + + default: + // We are not interested in this event + return false; + } + } + + /** + * This class implements the trackball long press time out callback + */ + private class TrackballLongPressTimeOut implements Runnable { + + // Track if we have been cancelled + private boolean cancelled; + + TrackballLongPressTimeOut() { + cancelled = false; + } + + // Cancel the timeout + public void cancel() { + cancelled = true; + } + + // Called when long press time out expires + @Override + public void run() { + // Check if the trackball is still pressed + if (!cancelled) { + // Zoom out + transform.zoom(false, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2); + + // Ensure the up action is not run + currentTrackballLongPressTimeOut = null; + } } + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java index 58144d7a2c..5bbba8682a 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java @@ -46,7 +46,6 @@ import com.mapbox.mapboxsdk.annotations.InfoWindow; import com.mapbox.mapboxsdk.annotations.MarkerViewManager; import com.mapbox.mapboxsdk.camera.CameraPosition; import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; -import com.mapbox.mapboxsdk.constants.MapboxConstants; import com.mapbox.mapboxsdk.constants.MyBearingTracking; import com.mapbox.mapboxsdk.constants.MyLocationTracking; import com.mapbox.mapboxsdk.constants.Style; @@ -67,6 +66,45 @@ import java.util.List; import timber.log.Timber; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.ANIMATION_DURATION; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_ATTRIBUTION_ENABLED; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_ATTRIBUTION_GRAVITY; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_ATTRIBUTION_MARGIN_BOTTOM; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_ATTRIBUTION_MARGIN_LEFT; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_ATTRIBUTION_MARGIN_RIGHT; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_ATTRIBUTION_MARGIN_TOP; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_CAMERA_POSITION; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_COMPASS_ENABLED; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_COMPASS_FADE_WHEN_FACING_NORTH; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_COMPASS_GRAVITY; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_COMPASS_MARGIN_BOTTOM; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_COMPASS_MARGIN_LEFT; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_COMPASS_MARGIN_RIGHT; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_COMPASS_MARGIN_TOP; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_DEBUG_ACTIVE; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_HAS_SAVED_STATE; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_LOGO_ENABLED; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_LOGO_GRAVITY; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_LOGO_MARGIN_BOTTOM; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_LOGO_MARGIN_LEFT; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_LOGO_MARGIN_RIGHT; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_LOGO_MARGIN_TOP; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_MY_BEARING_TRACKING_DISMISS; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_MY_BEARING_TRACKING_MODE; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_MY_LOCATION_ENABLED; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_MY_LOCATION_TRACKING_DISMISS; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_MY_LOCATION_TRACKING_MODE; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_ROTATE_ENABLED; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_ROTATE_ENABLED_CHANGE; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_SCROLL_ENABLED; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_SCROLL_ENABLED_CHANGE; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_STYLE_URL; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_TILT_ENABLED; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_TILT_ENABLED_CHANGE; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_ZOOM_CONTROLS_ENABLED; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_ZOOM_ENABLED; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.STATE_ZOOM_ENABLED_CHANGE; + /** * <p> * A {@code MapView} provides an embeddable map interface. @@ -83,1272 +121,1277 @@ import timber.log.Timber; */ public class MapView extends FrameLayout { - private MapboxMap mapboxMap; + private MapboxMap mapboxMap; - private boolean initialLoad; - private boolean destroyed; + private boolean initialLoad; + private boolean destroyed; - private NativeMapView nativeMapView; - private boolean hasSurface = false; + private NativeMapView nativeMapView; + private boolean hasSurface = false; - private CompassView compassView; - private MyLocationView myLocationView; - private LocationListener myLocationListener; + private CompassView compassView; + private MyLocationView myLocationView; + private LocationListener myLocationListener; - private MapGestureDetector mapGestureDetector; - private MapKeyListener mapKeyListener; + private MapGestureDetector mapGestureDetector; + private MapKeyListener mapKeyListener; - private ConnectivityReceiver connectivityReceiver; + private ConnectivityReceiver connectivityReceiver; - private List<OnMapReadyCallback> onMapReadyCallbackList = new ArrayList<>(); - private SnapshotRequest snapshotRequest; - private ZoomButtonsController zoomButtonsController; + private List<OnMapReadyCallback> onMapReadyCallbackList = new ArrayList<>(); + private SnapshotRequest snapshotRequest; + private ZoomButtonsController zoomButtonsController; - private boolean onStartCalled; - private boolean onStopCalled; + private boolean onStartCalled; + private boolean onStopCalled; - @UiThread - public MapView(@NonNull Context context) { - super(context); - initialize(context, MapboxMapOptions.createFromAttributes(context, null)); - } + @UiThread + public MapView(@NonNull Context context) { + super(context); + initialize(context, MapboxMapOptions.createFromAttributes(context, null)); + } - @UiThread - public MapView(@NonNull Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - initialize(context, MapboxMapOptions.createFromAttributes(context, attrs)); - } + @UiThread + public MapView(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + initialize(context, MapboxMapOptions.createFromAttributes(context, attrs)); + } - @UiThread - public MapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - initialize(context, MapboxMapOptions.createFromAttributes(context, attrs)); - } + @UiThread + public MapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(context, MapboxMapOptions.createFromAttributes(context, attrs)); + } - @UiThread - public MapView(@NonNull Context context, @NonNull MapboxMapOptions options) { - super(context); - initialize(context, options); - } - - private void initialize(@NonNull final Context context, @NonNull final MapboxMapOptions options) { - if (isInEditMode()) { - // if we are in an editor mode we show an image of a map - LayoutInflater.from(context).inflate(R.layout.mapbox_mapview_preview, this); - return; - } - - // TODO distill into singular purpose methods/classes - initialLoad = true; - View view = LayoutInflater.from(context).inflate(R.layout.mapbox_mapview_internal, this); - setWillNotDraw(false); - - if (options.getTextureMode()) { - TextureView textureView = new TextureView(context); - textureView.setSurfaceTextureListener(new SurfaceTextureListener()); - addView(textureView, 0); - } else { - SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView); - surfaceView.getHolder().addCallback(new SurfaceCallback()); - surfaceView.setVisibility(View.VISIBLE); - } + @UiThread + public MapView(@NonNull Context context, @NonNull MapboxMapOptions options) { + super(context); + initialize(context, options); + } - nativeMapView = new NativeMapView(this); - - // inflate overlain Views - compassView = (CompassView) view.findViewById(R.id.compassView); - myLocationView = (MyLocationView) view.findViewById(R.id.userLocationView); - ImageView logoView = (ImageView) view.findViewById(R.id.logoView); - ImageView attributionsView = (ImageView) view.findViewById(R.id.attributionView); - attributionsView.setOnClickListener(new AttributionOnClickListener(this)); - ViewGroup markerViewContainer = (ViewGroup) findViewById(R.id.markerViewContainer); - - // interface for focal point invalidation - FocalPointInvalidator focalPointInvalidator = new FocalPointInvalidator(); - - // interface for registering touch listeners - RegisterTouchListener registerTouchListener = new RegisterTouchListener(); - - // setup components for MapboxMap creation - Projection projection = new Projection(nativeMapView); - UiSettings uiSettings = new UiSettings(projection, focalPointInvalidator, compassView, attributionsView, logoView); - TrackingSettings trackingSettings = new TrackingSettings(myLocationView, uiSettings, focalPointInvalidator); - MyLocationViewSettings myLocationViewSettings = new MyLocationViewSettings(myLocationView, projection, focalPointInvalidator); - MarkerViewManager markerViewManager = new MarkerViewManager(markerViewContainer); - AnnotationManager annotationManager = new AnnotationManager(nativeMapView, this, markerViewManager); - Transform transform = new Transform(nativeMapView, annotationManager.getMarkerViewManager(), trackingSettings); - mapboxMap = new MapboxMap(nativeMapView, transform, uiSettings, trackingSettings, myLocationViewSettings, projection, registerTouchListener, annotationManager); - - // active user input - mapGestureDetector = new MapGestureDetector(context, mapboxMap.getTransform(), projection, uiSettings, trackingSettings, annotationManager); - mapKeyListener = new MapKeyListener(mapboxMap.getTransform(), trackingSettings, uiSettings); - - // attach widgets to MapboxMap - compassView.setMapboxMap(mapboxMap); - myLocationView.setMapboxMap(mapboxMap); - - // Ensure this view is interactable - setClickable(true); - setLongClickable(true); - setFocusable(true); - setFocusableInTouchMode(true); - requestDisallowInterceptTouchEvent(true); - requestFocus(); - - // Connectivity - onConnectivityChanged(isConnected()); - - // configure the zoom button controller - zoomButtonsController = new ZoomButtonsController(MapView.this); - zoomButtonsController.setZoomSpeed(MapboxConstants.ANIMATION_DURATION); - zoomButtonsController.setOnZoomListener(new OnZoomListener(mapboxMap)); - - mapboxMap.initialise(context, options); - - // Shows the zoom controls - if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)) { - uiSettings.setZoomControlsEnabled(true); - } + private void initialize(@NonNull final Context context, @NonNull final MapboxMapOptions options) { + if (isInEditMode()) { + // if we are in an editor mode we show an image of a map + LayoutInflater.from(context).inflate(R.layout.mapbox_mapview_preview, this); + return; } - // - // Lifecycle events - // - - /** - * <p> - * You must call this method from the parent's {@link android.app.Activity#onCreate(Bundle)} or - * {@link android.app.Fragment#onCreate(Bundle)}. - * </p> - * You must set a valid access token with {@link MapView#setAccessToken(String)} before you this method - * or an exception will be thrown. - * - * @param savedInstanceState Pass in the parent's savedInstanceState. - * @see MapView#setAccessToken(String) - */ - @UiThread - public void onCreate(@Nullable Bundle savedInstanceState) { - // TODO distill into singular purpose methods/classes - String accessToken = mapboxMap.getAccessToken(); - if (TextUtils.isEmpty(accessToken)) { - accessToken = MapboxAccountManager.getInstance().getAccessToken(); - nativeMapView.setAccessToken(accessToken); - } else { - // user provided access token through xml attributes, need to start MapboxAccountManager - MapboxAccountManager.start(getContext(), accessToken); - nativeMapView.setAccessToken(accessToken); - } - - // Force a check for an access token - MapboxAccountManager.validateAccessToken(accessToken); - nativeMapView.setAccessToken(accessToken); - - if (savedInstanceState != null && savedInstanceState.getBoolean(MapboxConstants.STATE_HAS_SAVED_STATE)) { + // TODO distill into singular purpose methods/classes + initialLoad = true; + View view = LayoutInflater.from(context).inflate(R.layout.mapbox_mapview_internal, this); + setWillNotDraw(false); + + if (options.getTextureMode()) { + TextureView textureView = new TextureView(context); + textureView.setSurfaceTextureListener(new SurfaceTextureListener()); + addView(textureView, 0); + } else { + SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView); + surfaceView.getHolder().addCallback(new SurfaceCallback()); + surfaceView.setVisibility(View.VISIBLE); + } - // Get previous camera position - CameraPosition cameraPosition = savedInstanceState.getParcelable(MapboxConstants.STATE_CAMERA_POSITION); - if (cameraPosition != null) { - mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder(cameraPosition).build())); - } + nativeMapView = new NativeMapView(this); + + // inflate overlain Views + compassView = (CompassView) view.findViewById(R.id.compassView); + myLocationView = (MyLocationView) view.findViewById(R.id.userLocationView); + ImageView logoView = (ImageView) view.findViewById(R.id.logoView); + ImageView attributionsView = (ImageView) view.findViewById(R.id.attributionView); + attributionsView.setOnClickListener(new AttributionOnClickListener(this)); + ViewGroup markerViewContainer = (ViewGroup) findViewById(R.id.markerViewContainer); + + // interface for focal point invalidation + FocalPointInvalidator focalPointInvalidator = new FocalPointInvalidator(); + + // interface for registering touch listeners + RegisterTouchListener registerTouchListener = new RegisterTouchListener(); + + // setup components for MapboxMap creation + Projection projection = new Projection(nativeMapView); + UiSettings uiSettings = new UiSettings(projection, focalPointInvalidator, compassView, attributionsView, logoView); + TrackingSettings trackingSettings = new TrackingSettings(myLocationView, uiSettings, focalPointInvalidator); + MyLocationViewSettings myLocationViewSettings = new MyLocationViewSettings(myLocationView, projection, + focalPointInvalidator); + MarkerViewManager markerViewManager = new MarkerViewManager(markerViewContainer); + AnnotationManager annotationManager = new AnnotationManager(nativeMapView, this, markerViewManager); + Transform transform = new Transform(nativeMapView, annotationManager.getMarkerViewManager(), trackingSettings); + mapboxMap = new MapboxMap(nativeMapView, transform, uiSettings, trackingSettings, myLocationViewSettings, + projection, registerTouchListener, annotationManager); + + // active user input + mapGestureDetector = new MapGestureDetector(context, mapboxMap.getTransform(), projection, uiSettings, + trackingSettings, annotationManager); + mapKeyListener = new MapKeyListener(mapboxMap.getTransform(), trackingSettings, uiSettings); + + // attach widgets to MapboxMap + compassView.setMapboxMap(mapboxMap); + myLocationView.setMapboxMap(mapboxMap); + + // Ensure this view is interactable + setClickable(true); + setLongClickable(true); + setFocusable(true); + setFocusableInTouchMode(true); + requestDisallowInterceptTouchEvent(true); + requestFocus(); + + // Connectivity + onConnectivityChanged(isConnected()); + + // configure the zoom button controller + zoomButtonsController = new ZoomButtonsController(MapView.this); + zoomButtonsController.setZoomSpeed(ANIMATION_DURATION); + zoomButtonsController.setOnZoomListener(new OnZoomListener(mapboxMap)); + + mapboxMap.initialise(context, options); + + // Shows the zoom controls + if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)) { + uiSettings.setZoomControlsEnabled(true); + } + } + + // + // Lifecycle events + // + + /** + * <p> + * You must call this method from the parent's {@link android.app.Activity#onCreate(Bundle)} or + * {@link android.app.Fragment#onCreate(Bundle)}. + * </p> + * You must set a valid access token with {@link MapView#setAccessToken(String)} before you this method + * or an exception will be thrown. + * + * @param savedInstanceState Pass in the parent's savedInstanceState. + * @see MapView#setAccessToken(String) + */ + @UiThread + public void onCreate(@Nullable Bundle savedInstanceState) { + // TODO distill into singular purpose methods/classes + String accessToken = mapboxMap.getAccessToken(); + if (TextUtils.isEmpty(accessToken)) { + accessToken = MapboxAccountManager.getInstance().getAccessToken(); + nativeMapView.setAccessToken(accessToken); + } else { + // user provided access token through xml attributes, need to start MapboxAccountManager + MapboxAccountManager.start(getContext(), accessToken); + nativeMapView.setAccessToken(accessToken); + } - UiSettings uiSettings = mapboxMap.getUiSettings(); - uiSettings.setZoomGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ZOOM_ENABLED)); - uiSettings.setZoomGestureChangeAllowed(savedInstanceState.getBoolean(MapboxConstants.STATE_ZOOM_ENABLED_CHANGE)); - uiSettings.setScrollGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_SCROLL_ENABLED)); - uiSettings.setScrollGestureChangeAllowed(savedInstanceState.getBoolean(MapboxConstants.STATE_SCROLL_ENABLED_CHANGE)); - uiSettings.setRotateGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ROTATE_ENABLED)); - uiSettings.setRotateGestureChangeAllowed(savedInstanceState.getBoolean(MapboxConstants.STATE_ROTATE_ENABLED_CHANGE)); - uiSettings.setTiltGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_TILT_ENABLED)); - uiSettings.setTiltGestureChangeAllowed(savedInstanceState.getBoolean(MapboxConstants.STATE_TILT_ENABLED_CHANGE)); - uiSettings.setZoomControlsEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ZOOM_CONTROLS_ENABLED)); - - // Compass - uiSettings.setCompassEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_COMPASS_ENABLED)); - uiSettings.setCompassGravity(savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_GRAVITY)); - uiSettings.setCompassMargins(savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_LEFT), - savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_TOP), - savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_RIGHT), - savedInstanceState.getInt(MapboxConstants.STATE_COMPASS_MARGIN_BOTTOM)); - uiSettings.setCompassFadeFacingNorth(savedInstanceState.getBoolean(MapboxConstants.STATE_COMPASS_FADE_WHEN_FACING_NORTH)); - - // Logo - uiSettings.setLogoEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_LOGO_ENABLED)); - uiSettings.setLogoGravity(savedInstanceState.getInt(MapboxConstants.STATE_LOGO_GRAVITY)); - uiSettings.setLogoMargins(savedInstanceState.getInt(MapboxConstants.STATE_LOGO_MARGIN_LEFT) - , savedInstanceState.getInt(MapboxConstants.STATE_LOGO_MARGIN_TOP) - , savedInstanceState.getInt(MapboxConstants.STATE_LOGO_MARGIN_RIGHT) - , savedInstanceState.getInt(MapboxConstants.STATE_LOGO_MARGIN_BOTTOM)); - - // Attribution - uiSettings.setAttributionEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ATTRIBUTION_ENABLED)); - uiSettings.setAttributionGravity(savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_GRAVITY)); - uiSettings.setAttributionMargins(savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_LEFT) - , savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_TOP) - , savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_RIGHT) - , savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_BOTTOM)); - - mapboxMap.setDebugActive(savedInstanceState.getBoolean(MapboxConstants.STATE_DEBUG_ACTIVE)); - - String styleUrl = savedInstanceState.getString(MapboxConstants.STATE_STYLE_URL); - if (!TextUtils.isEmpty(styleUrl)) { - nativeMapView.setStyleUrl(savedInstanceState.getString(MapboxConstants.STATE_STYLE_URL)); - } + // Force a check for an access token + MapboxAccountManager.validateAccessToken(accessToken); + nativeMapView.setAccessToken(accessToken); + + if (savedInstanceState != null && savedInstanceState.getBoolean(STATE_HAS_SAVED_STATE)) { + + // Get previous camera position + CameraPosition cameraPosition = savedInstanceState.getParcelable(STATE_CAMERA_POSITION); + if (cameraPosition != null) { + mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder(cameraPosition).build())); + } + + UiSettings uiSettings = mapboxMap.getUiSettings(); + uiSettings.setZoomGesturesEnabled(savedInstanceState.getBoolean(STATE_ZOOM_ENABLED)); + uiSettings.setZoomGestureChangeAllowed(savedInstanceState.getBoolean(STATE_ZOOM_ENABLED_CHANGE)); + uiSettings.setScrollGesturesEnabled(savedInstanceState.getBoolean(STATE_SCROLL_ENABLED)); + uiSettings.setScrollGestureChangeAllowed(savedInstanceState.getBoolean(STATE_SCROLL_ENABLED_CHANGE)); + uiSettings.setRotateGesturesEnabled(savedInstanceState.getBoolean(STATE_ROTATE_ENABLED)); + uiSettings.setRotateGestureChangeAllowed(savedInstanceState.getBoolean(STATE_ROTATE_ENABLED_CHANGE)); + uiSettings.setTiltGesturesEnabled(savedInstanceState.getBoolean(STATE_TILT_ENABLED)); + uiSettings.setTiltGestureChangeAllowed(savedInstanceState.getBoolean(STATE_TILT_ENABLED_CHANGE)); + uiSettings.setZoomControlsEnabled(savedInstanceState.getBoolean(STATE_ZOOM_CONTROLS_ENABLED)); + + // Compass + uiSettings.setCompassEnabled(savedInstanceState.getBoolean(STATE_COMPASS_ENABLED)); + uiSettings.setCompassGravity(savedInstanceState.getInt(STATE_COMPASS_GRAVITY)); + uiSettings.setCompassMargins(savedInstanceState.getInt(STATE_COMPASS_MARGIN_LEFT), + savedInstanceState.getInt(STATE_COMPASS_MARGIN_TOP), + savedInstanceState.getInt(STATE_COMPASS_MARGIN_RIGHT), + savedInstanceState.getInt(STATE_COMPASS_MARGIN_BOTTOM)); + uiSettings.setCompassFadeFacingNorth(savedInstanceState.getBoolean(STATE_COMPASS_FADE_WHEN_FACING_NORTH)); + + // Logo + uiSettings.setLogoEnabled(savedInstanceState.getBoolean(STATE_LOGO_ENABLED)); + uiSettings.setLogoGravity(savedInstanceState.getInt(STATE_LOGO_GRAVITY)); + uiSettings.setLogoMargins(savedInstanceState.getInt(STATE_LOGO_MARGIN_LEFT), + savedInstanceState.getInt(STATE_LOGO_MARGIN_TOP), + savedInstanceState.getInt(STATE_LOGO_MARGIN_RIGHT), + savedInstanceState.getInt(STATE_LOGO_MARGIN_BOTTOM)); + + // Attribution + uiSettings.setAttributionEnabled(savedInstanceState.getBoolean(STATE_ATTRIBUTION_ENABLED)); + uiSettings.setAttributionGravity(savedInstanceState.getInt(STATE_ATTRIBUTION_GRAVITY)); + uiSettings.setAttributionMargins(savedInstanceState.getInt(STATE_ATTRIBUTION_MARGIN_LEFT), + savedInstanceState.getInt(STATE_ATTRIBUTION_MARGIN_TOP), + savedInstanceState.getInt(STATE_ATTRIBUTION_MARGIN_RIGHT), + savedInstanceState.getInt(STATE_ATTRIBUTION_MARGIN_BOTTOM)); + + mapboxMap.setDebugActive(savedInstanceState.getBoolean(STATE_DEBUG_ACTIVE)); + + String styleUrl = savedInstanceState.getString(STATE_STYLE_URL); + if (!TextUtils.isEmpty(styleUrl)) { + nativeMapView.setStyleUrl(savedInstanceState.getString(STATE_STYLE_URL)); + } + + // User location + try { + mapboxMap.setMyLocationEnabled(savedInstanceState.getBoolean(STATE_MY_LOCATION_ENABLED)); + } catch (SecurityException ignore) { + // User did not accept location permissions + } + + TrackingSettings trackingSettings = mapboxMap.getTrackingSettings(); + //noinspection ResourceType + trackingSettings.setMyLocationTrackingMode( + savedInstanceState.getInt(STATE_MY_LOCATION_TRACKING_MODE, MyLocationTracking.TRACKING_NONE)); + //noinspection ResourceType + trackingSettings.setMyBearingTrackingMode( + savedInstanceState.getInt(STATE_MY_BEARING_TRACKING_MODE, MyBearingTracking.NONE)); + trackingSettings.setDismissLocationTrackingOnGesture( + savedInstanceState.getBoolean(STATE_MY_LOCATION_TRACKING_DISMISS, true)); + trackingSettings.setDismissBearingTrackingOnGesture( + savedInstanceState.getBoolean(STATE_MY_BEARING_TRACKING_DISMISS, true)); + } else if (savedInstanceState == null) { + // Start Telemetry (authorization determined in initial MapboxEventManager constructor) + Timber.i("MapView start Telemetry..."); + MapboxEventManager eventManager = MapboxEventManager.getMapboxEventManager(); + eventManager.initialize(getContext(), getAccessToken()); + } - // User location - try { - mapboxMap.setMyLocationEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_MY_LOCATION_ENABLED)); - } catch (SecurityException ignore) { - // User did not accept location permissions + // Initialize EGL + nativeMapView.initializeDisplay(); + nativeMapView.initializeContext(); + + // Add annotation deselection listener + addOnMapChangedListener(new OnMapChangedListener() { + @Override + public void onMapChanged(@MapChange int change) { + + // TODO extract logic into separate OnMapReady and Update Component + if (change == DID_FINISH_LOADING_STYLE && initialLoad) { + initialLoad = false; + mapboxMap.getAnnotationManager().reloadMarkers(); + mapboxMap.getAnnotationManager().adjustTopOffsetPixels(mapboxMap); + + // Notify listeners the map is ready + if (onMapReadyCallbackList.size() > 0) { + Iterator<OnMapReadyCallback> iterator = onMapReadyCallbackList.iterator(); + while (iterator.hasNext()) { + OnMapReadyCallback callback = iterator.next(); + callback.onMapReady(mapboxMap); + iterator.remove(); } + } - TrackingSettings trackingSettings = mapboxMap.getTrackingSettings(); - //noinspection ResourceType - trackingSettings.setMyLocationTrackingMode( - savedInstanceState.getInt(MapboxConstants.STATE_MY_LOCATION_TRACKING_MODE, MyLocationTracking.TRACKING_NONE)); - //noinspection ResourceType - trackingSettings.setMyBearingTrackingMode( - savedInstanceState.getInt(MapboxConstants.STATE_MY_BEARING_TRACKING_MODE, MyBearingTracking.NONE)); - trackingSettings.setDismissLocationTrackingOnGesture( - savedInstanceState.getBoolean(MapboxConstants.STATE_MY_LOCATION_TRACKING_DISMISS, true)); - trackingSettings.setDismissBearingTrackingOnGesture( - savedInstanceState.getBoolean(MapboxConstants.STATE_MY_BEARING_TRACKING_DISMISS, true)); - } else if (savedInstanceState == null) { - // Start Telemetry (authorization determined in initial MapboxEventManager constructor) - Timber.i("MapView start Telemetry..."); - MapboxEventManager eventManager = MapboxEventManager.getMapboxEventManager(); - eventManager.initialize(getContext(), getAccessToken()); - } + // invalidate camera to update overlain views with correct tilt value + mapboxMap.invalidateCameraPosition(); - // Initialize EGL - nativeMapView.initializeDisplay(); - nativeMapView.initializeContext(); - - // Add annotation deselection listener - addOnMapChangedListener(new OnMapChangedListener() { - @Override - public void onMapChanged(@MapChange int change) { - - // TODO extract logic into separate OnMapReady and Update Component - if (change == DID_FINISH_LOADING_STYLE && initialLoad) { - initialLoad = false; - mapboxMap.getAnnotationManager().reloadMarkers(); - mapboxMap.getAnnotationManager().adjustTopOffsetPixels(mapboxMap); - - // Notify listeners the map is ready - if (onMapReadyCallbackList.size() > 0) { - Iterator<OnMapReadyCallback> iterator = onMapReadyCallbackList.iterator(); - while (iterator.hasNext()) { - OnMapReadyCallback callback = iterator.next(); - callback.onMapReady(mapboxMap); - iterator.remove(); - } - } - - // invalidate camera to update overlain views with correct tilt value - mapboxMap.invalidateCameraPosition(); - - } else if (change == REGION_IS_CHANGING || change == REGION_DID_CHANGE || change == DID_FINISH_LOADING_MAP) { - mapboxMap.getMarkerViewManager().scheduleViewMarkerInvalidation(); - - compassView.update(mapboxMap.getTransform().getBearing()); - myLocationView.update(); - mapboxMap.getMarkerViewManager().update(); - - for (InfoWindow infoWindow : mapboxMap.getInfoWindows()) { - infoWindow.update(); - } - } + } else if (change == REGION_IS_CHANGING || change == REGION_DID_CHANGE || change == DID_FINISH_LOADING_MAP) { + mapboxMap.getMarkerViewManager().scheduleViewMarkerInvalidation(); - } - }); + compassView.update(mapboxMap.getTransform().getBearing()); + myLocationView.update(); + mapboxMap.getMarkerViewManager().update(); - // Fire MapLoad - if (savedInstanceState == null) { - Hashtable<String, Object> evt = new Hashtable<>(); - evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_LOAD); - evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate()); - MapboxEventManager.getMapboxEventManager().pushEvent(evt); + for (InfoWindow infoWindow : mapboxMap.getInfoWindows()) { + infoWindow.update(); + } } - } - /** - * You must call this method from the parent's {@link android.app.Activity#onSaveInstanceState(Bundle)} - * or {@link android.app.Fragment#onSaveInstanceState(Bundle)}. - * - * @param outState Pass in the parent's outState. - */ + } + }); - @UiThread - public void onSaveInstanceState(@NonNull Bundle outState) { - outState.putBoolean(MapboxConstants.STATE_HAS_SAVED_STATE, true); - outState.putParcelable(MapboxConstants.STATE_CAMERA_POSITION, mapboxMap.getCameraPosition()); - outState.putBoolean(MapboxConstants.STATE_DEBUG_ACTIVE, mapboxMap.isDebugActive()); - outState.putString(MapboxConstants.STATE_STYLE_URL, nativeMapView.getStyleUrl()); - outState.putBoolean(MapboxConstants.STATE_MY_LOCATION_ENABLED, mapboxMap.isMyLocationEnabled()); - - // TrackingSettings - TrackingSettings trackingSettings = mapboxMap.getTrackingSettings(); - outState.putInt(MapboxConstants.STATE_MY_LOCATION_TRACKING_MODE, trackingSettings.getMyLocationTrackingMode()); - outState.putInt(MapboxConstants.STATE_MY_BEARING_TRACKING_MODE, trackingSettings.getMyBearingTrackingMode()); - outState.putBoolean(MapboxConstants.STATE_MY_LOCATION_TRACKING_DISMISS, trackingSettings.isDismissLocationTrackingOnGesture()); - outState.putBoolean(MapboxConstants.STATE_MY_BEARING_TRACKING_DISMISS, trackingSettings.isDismissBearingTrackingOnGesture()); - - // UiSettings - UiSettings uiSettings = mapboxMap.getUiSettings(); - outState.putBoolean(MapboxConstants.STATE_ZOOM_ENABLED, uiSettings.isZoomGesturesEnabled()); - outState.putBoolean(MapboxConstants.STATE_ZOOM_ENABLED_CHANGE, uiSettings.isZoomGestureChangeAllowed()); - outState.putBoolean(MapboxConstants.STATE_SCROLL_ENABLED, uiSettings.isScrollGesturesEnabled()); - outState.putBoolean(MapboxConstants.STATE_SCROLL_ENABLED_CHANGE, uiSettings.isScrollGestureChangeAllowed()); - outState.putBoolean(MapboxConstants.STATE_ROTATE_ENABLED, uiSettings.isRotateGesturesEnabled()); - outState.putBoolean(MapboxConstants.STATE_ROTATE_ENABLED_CHANGE, uiSettings.isRotateGestureChangeAllowed()); - outState.putBoolean(MapboxConstants.STATE_TILT_ENABLED, uiSettings.isTiltGesturesEnabled()); - outState.putBoolean(MapboxConstants.STATE_TILT_ENABLED_CHANGE, uiSettings.isTiltGestureChangeAllowed()); - outState.putBoolean(MapboxConstants.STATE_ZOOM_CONTROLS_ENABLED, uiSettings.isZoomControlsEnabled()); - - // UiSettings - Compass - outState.putBoolean(MapboxConstants.STATE_COMPASS_ENABLED, uiSettings.isCompassEnabled()); - outState.putInt(MapboxConstants.STATE_COMPASS_GRAVITY, uiSettings.getCompassGravity()); - outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_LEFT, uiSettings.getCompassMarginLeft()); - outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_TOP, uiSettings.getCompassMarginTop()); - outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_BOTTOM, uiSettings.getCompassMarginBottom()); - outState.putInt(MapboxConstants.STATE_COMPASS_MARGIN_RIGHT, uiSettings.getCompassMarginRight()); - outState.putBoolean(MapboxConstants.STATE_COMPASS_FADE_WHEN_FACING_NORTH, uiSettings.isCompassFadeWhenFacingNorth()); - - // UiSettings - Logo - outState.putInt(MapboxConstants.STATE_LOGO_GRAVITY, uiSettings.getLogoGravity()); - outState.putInt(MapboxConstants.STATE_LOGO_MARGIN_LEFT, uiSettings.getLogoMarginLeft()); - outState.putInt(MapboxConstants.STATE_LOGO_MARGIN_TOP, uiSettings.getLogoMarginTop()); - outState.putInt(MapboxConstants.STATE_LOGO_MARGIN_RIGHT, uiSettings.getLogoMarginRight()); - outState.putInt(MapboxConstants.STATE_LOGO_MARGIN_BOTTOM, uiSettings.getLogoMarginBottom()); - outState.putBoolean(MapboxConstants.STATE_LOGO_ENABLED, uiSettings.isLogoEnabled()); - - // UiSettings - Attribution - outState.putInt(MapboxConstants.STATE_ATTRIBUTION_GRAVITY, uiSettings.getAttributionGravity()); - outState.putInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_LEFT, uiSettings.getAttributionMarginLeft()); - outState.putInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_TOP, uiSettings.getAttributionMarginTop()); - outState.putInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_RIGHT, uiSettings.getAttributionMarginRight()); - outState.putInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_BOTTOM, uiSettings.getAttributionMarginBottom()); - outState.putBoolean(MapboxConstants.STATE_ATTRIBUTION_ENABLED, uiSettings.isAttributionEnabled()); + // Fire MapLoad + if (savedInstanceState == null) { + Hashtable<String, Object> evt = new Hashtable<>(); + evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_LOAD); + evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate()); + MapboxEventManager.getMapboxEventManager().pushEvent(evt); } - - /** - * You must call this method from the parent's {@link Activity#onStart()} or {@link Fragment#onStart()} - */ - @UiThread - public void onStart() { - onStartCalled = true; - - // Register for connectivity changes - connectivityReceiver = new ConnectivityReceiver(); - getContext().registerReceiver(connectivityReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); - - nativeMapView.update(); - myLocationView.onStart(); - - if (TextUtils.isEmpty(nativeMapView.getStyleUrl())) { - // if user hasn't loaded a Style yet, load default for them instead - nativeMapView.setStyleUrl(Style.MAPBOX_STREETS); - } + } + + /** + * You must call this method from the parent's {@link android.app.Activity#onSaveInstanceState(Bundle)} + * or {@link android.app.Fragment#onSaveInstanceState(Bundle)}. + * + * @param outState Pass in the parent's outState. + */ + + @UiThread + public void onSaveInstanceState(@NonNull Bundle outState) { + outState.putBoolean(STATE_HAS_SAVED_STATE, true); + outState.putParcelable(STATE_CAMERA_POSITION, mapboxMap.getCameraPosition()); + outState.putBoolean(STATE_DEBUG_ACTIVE, mapboxMap.isDebugActive()); + outState.putString(STATE_STYLE_URL, nativeMapView.getStyleUrl()); + outState.putBoolean(STATE_MY_LOCATION_ENABLED, mapboxMap.isMyLocationEnabled()); + + // TrackingSettings + TrackingSettings trackingSettings = mapboxMap.getTrackingSettings(); + outState.putInt(STATE_MY_LOCATION_TRACKING_MODE, trackingSettings.getMyLocationTrackingMode()); + outState.putInt(STATE_MY_BEARING_TRACKING_MODE, trackingSettings.getMyBearingTrackingMode()); + outState.putBoolean(STATE_MY_LOCATION_TRACKING_DISMISS, trackingSettings.isDismissLocationTrackingOnGesture()); + outState.putBoolean(STATE_MY_BEARING_TRACKING_DISMISS, trackingSettings.isDismissBearingTrackingOnGesture()); + + // UiSettings + UiSettings uiSettings = mapboxMap.getUiSettings(); + outState.putBoolean(STATE_ZOOM_ENABLED, uiSettings.isZoomGesturesEnabled()); + outState.putBoolean(STATE_ZOOM_ENABLED_CHANGE, uiSettings.isZoomGestureChangeAllowed()); + outState.putBoolean(STATE_SCROLL_ENABLED, uiSettings.isScrollGesturesEnabled()); + outState.putBoolean(STATE_SCROLL_ENABLED_CHANGE, uiSettings.isScrollGestureChangeAllowed()); + outState.putBoolean(STATE_ROTATE_ENABLED, uiSettings.isRotateGesturesEnabled()); + outState.putBoolean(STATE_ROTATE_ENABLED_CHANGE, uiSettings.isRotateGestureChangeAllowed()); + outState.putBoolean(STATE_TILT_ENABLED, uiSettings.isTiltGesturesEnabled()); + outState.putBoolean(STATE_TILT_ENABLED_CHANGE, uiSettings.isTiltGestureChangeAllowed()); + outState.putBoolean(STATE_ZOOM_CONTROLS_ENABLED, uiSettings.isZoomControlsEnabled()); + + // UiSettings - Compass + outState.putBoolean(STATE_COMPASS_ENABLED, uiSettings.isCompassEnabled()); + outState.putInt(STATE_COMPASS_GRAVITY, uiSettings.getCompassGravity()); + outState.putInt(STATE_COMPASS_MARGIN_LEFT, uiSettings.getCompassMarginLeft()); + outState.putInt(STATE_COMPASS_MARGIN_TOP, uiSettings.getCompassMarginTop()); + outState.putInt(STATE_COMPASS_MARGIN_BOTTOM, uiSettings.getCompassMarginBottom()); + outState.putInt(STATE_COMPASS_MARGIN_RIGHT, uiSettings.getCompassMarginRight()); + outState.putBoolean(STATE_COMPASS_FADE_WHEN_FACING_NORTH, uiSettings.isCompassFadeWhenFacingNorth()); + + // UiSettings - Logo + outState.putInt(STATE_LOGO_GRAVITY, uiSettings.getLogoGravity()); + outState.putInt(STATE_LOGO_MARGIN_LEFT, uiSettings.getLogoMarginLeft()); + outState.putInt(STATE_LOGO_MARGIN_TOP, uiSettings.getLogoMarginTop()); + outState.putInt(STATE_LOGO_MARGIN_RIGHT, uiSettings.getLogoMarginRight()); + outState.putInt(STATE_LOGO_MARGIN_BOTTOM, uiSettings.getLogoMarginBottom()); + outState.putBoolean(STATE_LOGO_ENABLED, uiSettings.isLogoEnabled()); + + // UiSettings - Attribution + outState.putInt(STATE_ATTRIBUTION_GRAVITY, uiSettings.getAttributionGravity()); + outState.putInt(STATE_ATTRIBUTION_MARGIN_LEFT, uiSettings.getAttributionMarginLeft()); + outState.putInt(STATE_ATTRIBUTION_MARGIN_TOP, uiSettings.getAttributionMarginTop()); + outState.putInt(STATE_ATTRIBUTION_MARGIN_RIGHT, uiSettings.getAttributionMarginRight()); + outState.putInt(STATE_ATTRIBUTION_MARGIN_BOTTOM, uiSettings.getAttributionMarginBottom()); + outState.putBoolean(STATE_ATTRIBUTION_ENABLED, uiSettings.isAttributionEnabled()); + } + + /** + * You must call this method from the parent's {@link Activity#onStart()} or {@link Fragment#onStart()} + */ + @UiThread + public void onStart() { + onStartCalled = true; + + // Register for connectivity changes + connectivityReceiver = new ConnectivityReceiver(); + getContext().registerReceiver(connectivityReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); + + nativeMapView.update(); + myLocationView.onStart(); + + if (TextUtils.isEmpty(nativeMapView.getStyleUrl())) { + // if user hasn't loaded a Style yet, load default for them instead + nativeMapView.setStyleUrl(Style.MAPBOX_STREETS); } - - /** - * You must call this method from the parent's {@link Activity#onResume()} or {@link Fragment#onResume()}. - */ - @UiThread - public void onResume() { - if (!onStartCalled) { - // TODO: 26/10/16, can be removed after 5.0.0 release - throw new IllegalStateException("MapView#onStart() was not called. " + - "You must call this method from the parent's {@link Activity#onStart()} or {@link Fragment#onStart()}."); - } + } + + /** + * You must call this method from the parent's {@link Activity#onResume()} or {@link Fragment#onResume()}. + */ + @UiThread + public void onResume() { + if (!onStartCalled) { + // TODO: 26/10/16, can be removed after 5.0.0 release + throw new IllegalStateException("MapView#onStart() was not called. " + + "You must call this method from the parent's {@link Activity#onStart()} or {@link Fragment#onStart()}."); } - - /** - * You must call this method from the parent's {@link Activity#onPause()} or {@link Fragment#onPause()}. - */ - @UiThread - public void onPause() { - // replaced by onStop in v5.0.0, keep around for future development + } + + /** + * You must call this method from the parent's {@link Activity#onPause()} or {@link Fragment#onPause()}. + */ + @UiThread + public void onPause() { + // replaced by onStop in v5.0.0, keep around for future development + } + + /** + * You must call this method from the parent's {@link Activity#onStop()} or {@link Fragment#onStop()}. + */ + @UiThread + public void onStop() { + onStopCalled = true; + + // Unregister for connectivity changes + if (connectivityReceiver != null) { + getContext().unregisterReceiver(connectivityReceiver); + connectivityReceiver = null; } - /** - * You must call this method from the parent's {@link Activity#onStop()} or {@link Fragment#onStop()}. - */ - @UiThread - public void onStop() { - onStopCalled = true; - - // Unregister for connectivity changes - if (connectivityReceiver != null) { - getContext().unregisterReceiver(connectivityReceiver); - connectivityReceiver = null; - } + myLocationView.onStop(); + } + + /** + * You must call this method from the parent's {@link Activity#onDestroy()} or {@link Fragment#onDestroy()}. + */ + @UiThread + public void onDestroy() { + if (!onStopCalled) { + // TODO: 26/10/16, can be removed after 5.0.0 release + throw new IllegalStateException("MapView#onStop() was not called. " + + "You must call this method from the parent's {@link Activity#onStop()} or {@link Fragment#onStop()}."); + } - myLocationView.onStop(); + destroyed = true; + nativeMapView.terminateContext(); + nativeMapView.terminateDisplay(); + nativeMapView.destroySurface(); + nativeMapView.destroy(); + nativeMapView = null; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (mapboxMap.getUiSettings().isZoomControlsEnabled()) { + zoomButtonsController.setVisible(true); + } } + return mapGestureDetector.onTouchEvent(event) || super.onTouchEvent(event); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + return mapKeyListener.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event); + } + + @Override + public boolean onKeyLongPress(int keyCode, KeyEvent event) { + return mapKeyListener.onKeyLongPress(keyCode, event) || super.onKeyLongPress(keyCode, event); + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + return mapKeyListener.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event); + } + + @Override + public boolean onTrackballEvent(MotionEvent event) { + return mapKeyListener.onTrackballEvent(event) || super.onTrackballEvent(event); + } + + @Override + public boolean onGenericMotionEvent(MotionEvent event) { + return mapGestureDetector.onGenericMotionEvent(event) || super.onGenericMotionEvent(event); + } + + @Override + public boolean onHoverEvent(MotionEvent event) { + switch (event.getActionMasked()) { + case MotionEvent.ACTION_HOVER_ENTER: + case MotionEvent.ACTION_HOVER_MOVE: + // Show the zoom controls + if (mapboxMap.getUiSettings().isZoomControlsEnabled()) { + zoomButtonsController.setVisible(true); + } + return true; - /** - * You must call this method from the parent's {@link Activity#onDestroy()} or {@link Fragment#onDestroy()}. - */ - @UiThread - public void onDestroy() { - if (!onStopCalled) { - // TODO: 26/10/16, can be removed after 5.0.0 release - throw new IllegalStateException("MapView#onStop() was not called. " + - "You must call this method from the parent's {@link Activity#onStop()} or {@link Fragment#onStop()}."); + case MotionEvent.ACTION_HOVER_EXIT: + // Hide the zoom controls + if (mapboxMap.getUiSettings().isZoomControlsEnabled()) { + zoomButtonsController.setVisible(false); } + return true; - destroyed = true; - nativeMapView.terminateContext(); - nativeMapView.terminateDisplay(); - nativeMapView.destroySurface(); - nativeMapView.destroy(); - nativeMapView = null; + default: + // We are not interested in this event + return false; } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_DOWN) { - if (mapboxMap.getUiSettings().isZoomControlsEnabled()) { - zoomButtonsController.setVisible(true); - } + } + + /** + * You must call this method from the parent's {@link Activity#onLowMemory()} or {@link Fragment#onLowMemory()}. + */ + @UiThread + public void onLowMemory() { + nativeMapView.onLowMemory(); + } + + // Called when debug mode is enabled to update a FPS counter + // Called via JNI from NativeMapView + // Forward to any listener + protected void onFpsChanged(final double fps) { + post(new Runnable() { + @Override + public void run() { + MapboxMap.OnFpsChangedListener listener = mapboxMap.getOnFpsChangedListener(); + if (listener != null) { + listener.onFpsChanged(fps); } - return mapGestureDetector.onTouchEvent(event) || super.onTouchEvent(event); + } + }); + } + + /** + * <p> + * Loads a new map style from the specified URL. + * </p> + * {@code url} can take the following forms: + * <ul> + * <li>{@code Style.*}: load one of the bundled styles in {@link Style}.</li> + * <li>{@code mapbox://styles/<user>/<style>}: + * retrieves the style from a <a href="https://www.mapbox.com/account/">Mapbox account.</a> + * {@code user} is your username. {@code style} is the ID of your custom + * style created in <a href="https://www.mapbox.com/studio">Mapbox Studio</a>.</li> + * <li>{@code http://...} or {@code https://...}: + * retrieves the style over the Internet from any web server.</li> + * <li>{@code asset://...}: + * reads the style from the APK {@code assets/} directory. + * This is used to load a style bundled with your app.</li> + * <li>{@code null}: loads the default {@link Style#MAPBOX_STREETS} style.</li> + * </ul> + * <p> + * This method is asynchronous and will return immediately before the style finishes loading. + * If you wish to wait for the map to finish loading listen for the {@link MapView#DID_FINISH_LOADING_MAP} event. + * </p> + * If the style fails to load or an invalid style URL is set, the map view will become blank. + * An error message will be logged in the Android logcat and {@link MapView#DID_FAIL_LOADING_MAP} event will be sent. + * + * @param url The URL of the map style + * @see Style + */ + public void setStyleUrl(@NonNull String url) { + if (destroyed) { + return; } - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - return mapKeyListener.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event); + // stopgap for https://github.com/mapbox/mapbox-gl-native/issues/6242 + if (TextUtils.isEmpty(nativeMapView.getAccessToken())) { + setAccessToken(MapboxAccountManager.getInstance().getAccessToken()); } - @Override - public boolean onKeyLongPress(int keyCode, KeyEvent event) { - return mapKeyListener.onKeyLongPress(keyCode, event) || super.onKeyLongPress(keyCode, event); + nativeMapView.setStyleUrl(url); + } + + /** + * <p> + * DEPRECATED @see MapboxAccountManager#start(String) + * </p> + * <p> + * Sets the current Mapbox access token used to load map styles and tiles. + * </p> + * <p> + * You must set a valid access token before you call {@link MapView#onCreate(Bundle)} + * or an exception will be thrown. + * </p> + * + * @param accessToken Your public Mapbox access token. + * @see MapView#onCreate(Bundle) + * @deprecated As of release 4.1.0, replaced by + * {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)} + */ + @Deprecated + @UiThread + public void setAccessToken(@NonNull String accessToken) { + if (destroyed) { + return; } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - return mapKeyListener.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event); + // validateAccessToken does the null check + if (!TextUtils.isEmpty(accessToken)) { + accessToken = accessToken.trim(); } - - @Override - public boolean onTrackballEvent(MotionEvent event) { - return mapKeyListener.onTrackballEvent(event) || super.onTrackballEvent(event); + MapboxAccountManager.validateAccessToken(accessToken); + nativeMapView.setAccessToken(accessToken); + } + + /** + * <p> + * DEPRECATED @see MapboxAccountManager#getAccessToken() + * </p> + * <p> + * Returns the current Mapbox access token used to load map styles and tiles. + * </p> + * + * @return The current Mapbox access token. + * @deprecated As of release 4.1.0, replaced by {@link MapboxAccountManager#getAccessToken()} + */ + @Deprecated + @UiThread + @Nullable + public String getAccessToken() { + if (destroyed) { + return ""; } - - @Override - public boolean onGenericMotionEvent(MotionEvent event) { - return mapGestureDetector.onGenericMotionEvent(event) || super.onGenericMotionEvent(event); + return nativeMapView.getAccessToken(); + } + + // + // Rendering + // + + // Called when the map needs to be rerendered + // Called via JNI from NativeMapView + protected void onInvalidate() { + postInvalidate(); + } + + @Override + public void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (isInEditMode()) { + return; } - @Override - public boolean onHoverEvent(MotionEvent event) { - switch (event.getActionMasked()) { - case MotionEvent.ACTION_HOVER_ENTER: - case MotionEvent.ACTION_HOVER_MOVE: - // Show the zoom controls - if (mapboxMap.getUiSettings().isZoomControlsEnabled()) { - zoomButtonsController.setVisible(true); - } - return true; - - case MotionEvent.ACTION_HOVER_EXIT: - // Hide the zoom controls - if (mapboxMap.getUiSettings().isZoomControlsEnabled()) { - zoomButtonsController.setVisible(false); - } - return true; - - default: - // We are not interested in this event - return false; - } + if (destroyed) { + return; } - /** - * You must call this method from the parent's {@link Activity#onLowMemory()} or {@link Fragment#onLowMemory()}. - */ - @UiThread - public void onLowMemory() { - nativeMapView.onLowMemory(); - } - - // Called when debug mode is enabled to update a FPS counter - // Called via JNI from NativeMapView - // Forward to any listener - protected void onFpsChanged(final double fps) { - post(new Runnable() { - @Override - public void run() { - MapboxMap.OnFpsChangedListener listener = mapboxMap.getOnFpsChangedListener(); - if (listener != null) { - listener.onFpsChanged(fps); - } - } - }); + if (!hasSurface) { + return; } - /** - * <p> - * Loads a new map style from the specified URL. - * </p> - * {@code url} can take the following forms: - * <ul> - * <li>{@code Style.*}: load one of the bundled styles in {@link Style}.</li> - * <li>{@code mapbox://styles/<user>/<style>}: - * retrieves the style from a <a href="https://www.mapbox.com/account/">Mapbox account.</a> - * {@code user} is your username. {@code style} is the ID of your custom - * style created in <a href="https://www.mapbox.com/studio">Mapbox Studio</a>.</li> - * <li>{@code http://...} or {@code https://...}: - * retrieves the style over the Internet from any web server.</li> - * <li>{@code asset://...}: - * reads the style from the APK {@code assets/} directory. - * This is used to load a style bundled with your app.</li> - * <li>{@code null}: loads the default {@link Style#MAPBOX_STREETS} style.</li> - * </ul> - * <p> - * This method is asynchronous and will return immediately before the style finishes loading. - * If you wish to wait for the map to finish loading listen for the {@link MapView#DID_FINISH_LOADING_MAP} event. - * </p> - * If the style fails to load or an invalid style URL is set, the map view will become blank. - * An error message will be logged in the Android logcat and {@link MapView#DID_FAIL_LOADING_MAP} event will be sent. - * - * @param url The URL of the map style - * @see Style - */ - public void setStyleUrl(@NonNull String url) { - if (destroyed) { - return; - } + nativeMapView.render(); + } - // stopgap for https://github.com/mapbox/mapbox-gl-native/issues/6242 - if (TextUtils.isEmpty(nativeMapView.getAccessToken())) { - setAccessToken(MapboxAccountManager.getInstance().getAccessToken()); - } - - nativeMapView.setStyleUrl(url); + @Override + protected void onSizeChanged(int width, int height, int oldw, int oldh) { + if (destroyed) { + return; } - /** - * <p> - * DEPRECATED @see MapboxAccountManager#start(String) - * </p> - * <p> - * Sets the current Mapbox access token used to load map styles and tiles. - * </p> - * <p> - * You must set a valid access token before you call {@link MapView#onCreate(Bundle)} - * or an exception will be thrown. - * </p> - * - * @param accessToken Your public Mapbox access token. - * @see MapView#onCreate(Bundle) - * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)} - */ - @Deprecated - @UiThread - public void setAccessToken(@NonNull String accessToken) { - if (destroyed) { - return; - } - // validateAccessToken does the null check - if (!TextUtils.isEmpty(accessToken)) { - accessToken = accessToken.trim(); - } - MapboxAccountManager.validateAccessToken(accessToken); - nativeMapView.setAccessToken(accessToken); + if (!isInEditMode()) { + nativeMapView.resizeView(width, height); } + } - /** - * <p> - * DEPRECATED @see MapboxAccountManager#getAccessToken() - * </p> - * <p> - * Returns the current Mapbox access token used to load map styles and tiles. - * </p> - * - * @return The current Mapbox access token. - * @deprecated As of release 4.1.0, replaced by {@link MapboxAccountManager#getAccessToken()} - */ - @Deprecated - @UiThread - @Nullable - public String getAccessToken() { - if (destroyed) { - return ""; - } - return nativeMapView.getAccessToken(); - } + private class SurfaceCallback implements SurfaceHolder.Callback { - // - // Rendering - // + private Surface surface; - // Called when the map needs to be rerendered - // Called via JNI from NativeMapView - protected void onInvalidate() { - postInvalidate(); + @Override + public void surfaceCreated(SurfaceHolder holder) { + nativeMapView.createSurface(surface = holder.getSurface()); + hasSurface = true; } @Override - public void onDraw(Canvas canvas) { - super.onDraw(canvas); - if (isInEditMode()) { - return; - } - - if (destroyed) { - return; - } - - if (!hasSurface) { - return; - } - - nativeMapView.render(); + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + if (destroyed) { + return; + } + nativeMapView.resizeFramebuffer(width, height); } @Override - protected void onSizeChanged(int width, int height, int oldw, int oldh) { - if (destroyed) { - return; - } + public void surfaceDestroyed(SurfaceHolder holder) { + hasSurface = false; - if (!isInEditMode()) { - nativeMapView.resizeView(width, height); - } + if (nativeMapView != null) { + nativeMapView.destroySurface(); + } + surface.release(); } + } - private class SurfaceCallback implements SurfaceHolder.Callback { - - private Surface surface; - - @Override - public void surfaceCreated(SurfaceHolder holder) { - nativeMapView.createSurface(surface = holder.getSurface()); - hasSurface = true; - } - - @Override - public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { - if (destroyed) { - return; - } - nativeMapView.resizeFramebuffer(width, height); - } + // This class handles TextureView callbacks + private class SurfaceTextureListener implements TextureView.SurfaceTextureListener { - @Override - public void surfaceDestroyed(SurfaceHolder holder) { - hasSurface = false; + private Surface surface; - if (nativeMapView != null) { - nativeMapView.destroySurface(); - } - surface.release(); - } + // Called when the native surface texture has been created + // Must do all EGL/GL ES initialization here + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { + nativeMapView.createSurface(this.surface = new Surface(surface)); + nativeMapView.resizeFramebuffer(width, height); + hasSurface = true; } - // This class handles TextureView callbacks - private class SurfaceTextureListener implements TextureView.SurfaceTextureListener { - - private Surface surface; - - // Called when the native surface texture has been created - // Must do all EGL/GL ES initialization here - @Override - public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { - nativeMapView.createSurface(this.surface = new Surface(surface)); - nativeMapView.resizeFramebuffer(width, height); - hasSurface = true; - } - - // Called when the native surface texture has been destroyed - // Must do all EGL/GL ES destruction here - @Override - public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { - hasSurface = false; - - if (nativeMapView != null) { - nativeMapView.destroySurface(); - } - this.surface.release(); - return true; - } - - // Called when the format or size of the native surface texture has been changed - // Must handle window resizing here. - @Override - public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { - if (destroyed) { - return; - } - - nativeMapView.resizeFramebuffer(width, height); - } - - // Called when the SurfaceTexure frame is drawn to screen - // Must sync with UI here - @Override - public void onSurfaceTextureUpdated(SurfaceTexture surface) { - if (destroyed) { - return; - } - // TODO move to transform. java - compassView.update(mapboxMap.getTransform().getBearing()); - myLocationView.update(); - mapboxMap.getMarkerViewManager().update(); + // Called when the native surface texture has been destroyed + // Must do all EGL/GL ES destruction here + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { + hasSurface = false; - for (InfoWindow infoWindow : mapboxMap.getInfoWindows()) { - infoWindow.update(); - } - } + if (nativeMapView != null) { + nativeMapView.destroySurface(); + } + this.surface.release(); + return true; } - // - // View events - // - - // Called when view is no longer connected + // Called when the format or size of the native surface texture has been changed + // Must handle window resizing here. @Override - @CallSuper - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - // Required by ZoomButtonController (from Android SDK documentation) - if (mapboxMap.getUiSettings().isZoomControlsEnabled()) { - zoomButtonsController.setVisible(false); - } + public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { + if (destroyed) { + return; + } - // make sure we don't leak location listener - if (myLocationListener != null) { - // cleanup to prevent memory leak - LocationServices services = LocationServices.getLocationServices(getContext()); - services.removeLocationListener(myLocationListener); - myLocationListener = null; - } + nativeMapView.resizeFramebuffer(width, height); } - // Called when view is hidden and shown + // Called when the SurfaceTexure frame is drawn to screen + // Must sync with UI here @Override - protected void onVisibilityChanged(@NonNull View changedView, int visibility) { - if (isInEditMode()) { - return; - } - - if (mapboxMap != null && mapboxMap.getUiSettings().isZoomControlsEnabled()) { - zoomButtonsController.setVisible(visibility == View.VISIBLE); - } + public void onSurfaceTextureUpdated(SurfaceTexture surface) { + if (destroyed) { + return; + } + // TODO move to transform. java + compassView.update(mapboxMap.getTransform().getBearing()); + myLocationView.update(); + mapboxMap.getMarkerViewManager().update(); + + for (InfoWindow infoWindow : mapboxMap.getInfoWindows()) { + infoWindow.update(); + } + } + } + + // + // View events + // + + // Called when view is no longer connected + @Override + @CallSuper + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + // Required by ZoomButtonController (from Android SDK documentation) + if (mapboxMap.getUiSettings().isZoomControlsEnabled()) { + zoomButtonsController.setVisible(false); } - // - // Connectivity events - // - - // This class handles connectivity changes - private class ConnectivityReceiver extends BroadcastReceiver { - - // Called when an action we are listening to in the manifest has been sent - @Override - public void onReceive(Context context, Intent intent) { - if (!destroyed && intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) { - boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); - onConnectivityChanged(!noConnectivity); - } - } + // make sure we don't leak location listener + if (myLocationListener != null) { + // cleanup to prevent memory leak + LocationServices services = LocationServices.getLocationServices(getContext()); + services.removeLocationListener(myLocationListener); + myLocationListener = null; } + } - // Called when MapView is being created - private boolean isConnected() { - Context appContext = getContext().getApplicationContext(); - ConnectivityManager connectivityManager = (ConnectivityManager) appContext.getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo(); - return (activeNetwork != null) && activeNetwork.isConnectedOrConnecting(); + // Called when view is hidden and shown + @Override + protected void onVisibilityChanged(@NonNull View changedView, int visibility) { + if (isInEditMode()) { + return; } - // Called when our Internet connectivity has changed - private void onConnectivityChanged(boolean isConnected) { - nativeMapView.setReachability(isConnected); + if (mapboxMap != null && mapboxMap.getUiSettings().isZoomControlsEnabled()) { + zoomButtonsController.setVisible(visibility == View.VISIBLE); } + } - // - // Map events - // + // + // Connectivity events + // - /** - * <p> - * Add a callback that's invoked when the displayed map view changes. - * </p> - * To remove the callback, use {@link MapView#removeOnMapChangedListener(OnMapChangedListener)}. - * - * @param listener The callback that's invoked on every frame rendered to the map view. - * @see MapView#removeOnMapChangedListener(OnMapChangedListener) - */ - public void addOnMapChangedListener(@Nullable OnMapChangedListener listener) { - if (listener != null) { - nativeMapView.addOnMapChangedListener(listener); - } - } + // This class handles connectivity changes + private class ConnectivityReceiver extends BroadcastReceiver { - /** - * Remove a callback added with {@link MapView#addOnMapChangedListener(OnMapChangedListener)} - * - * @param listener The previously added callback to remove. - * @see MapView#addOnMapChangedListener(OnMapChangedListener) - */ - public void removeOnMapChangedListener(@Nullable OnMapChangedListener listener) { - if (listener != null) { - nativeMapView.removeOnMapChangedListener(listener); - } + // Called when an action we are listening to in the manifest has been sent + @Override + public void onReceive(Context context, Intent intent) { + if (!destroyed && intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) { + boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); + onConnectivityChanged(!noConnectivity); + } } - - // Called when the map view transformation has changed - // Called via JNI from NativeMapView - // Forward to any listeners - protected void onMapChanged(int mapChange) { - nativeMapView.onMapChangedEventDispatch(mapChange); + } + + // Called when MapView is being created + private boolean isConnected() { + Context appContext = getContext().getApplicationContext(); + ConnectivityManager connectivityManager = (ConnectivityManager) + appContext.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo(); + return (activeNetwork != null) && activeNetwork.isConnectedOrConnecting(); + } + + // Called when our Internet connectivity has changed + private void onConnectivityChanged(boolean isConnected) { + nativeMapView.setReachability(isConnected); + } + + // + // Map events + // + + /** + * <p> + * Add a callback that's invoked when the displayed map view changes. + * </p> + * To remove the callback, use {@link MapView#removeOnMapChangedListener(OnMapChangedListener)}. + * + * @param listener The callback that's invoked on every frame rendered to the map view. + * @see MapView#removeOnMapChangedListener(OnMapChangedListener) + */ + public void addOnMapChangedListener(@Nullable OnMapChangedListener listener) { + if (listener != null) { + nativeMapView.addOnMapChangedListener(listener); } - - - /** - * Sets a callback object which will be triggered when the {@link MapboxMap} instance is ready to be used. - * - * @param callback The callback object that will be triggered when the map is ready to be used. - */ - @UiThread - public void getMapAsync(final OnMapReadyCallback callback) { - if (!initialLoad && callback != null) { - callback.onMapReady(mapboxMap); - } else { - if (callback != null) { - onMapReadyCallbackList.add(callback); - } - } + } + + /** + * Remove a callback added with {@link MapView#addOnMapChangedListener(OnMapChangedListener)} + * + * @param listener The previously added callback to remove. + * @see MapView#addOnMapChangedListener(OnMapChangedListener) + */ + public void removeOnMapChangedListener(@Nullable OnMapChangedListener listener) { + if (listener != null) { + nativeMapView.removeOnMapChangedListener(listener); } - - MapboxMap getMapboxMap() { - return mapboxMap; + } + + // Called when the map view transformation has changed + // Called via JNI from NativeMapView + // Forward to any listeners + protected void onMapChanged(int mapChange) { + nativeMapView.onMapChangedEventDispatch(mapChange); + } + + + /** + * Sets a callback object which will be triggered when the {@link MapboxMap} instance is ready to be used. + * + * @param callback The callback object that will be triggered when the map is ready to be used. + */ + @UiThread + public void getMapAsync(final OnMapReadyCallback callback) { + if (!initialLoad && callback != null) { + callback.onMapReady(mapboxMap); + } else { + if (callback != null) { + onMapReadyCallbackList.add(callback); + } } - - void setMapboxMap(MapboxMap mapboxMap) { - this.mapboxMap = mapboxMap; + } + + MapboxMap getMapboxMap() { + return mapboxMap; + } + + void setMapboxMap(MapboxMap mapboxMap) { + this.mapboxMap = mapboxMap; + } + + // + // Snapshot API + // + + @UiThread + void snapshot(@NonNull final MapboxMap.SnapshotReadyCallback callback, @Nullable final Bitmap bitmap) { + snapshotRequest = new SnapshotRequest(bitmap, callback); + nativeMapView.scheduleTakeSnapshot(); + nativeMapView.render(); + } + + // Called when the snapshot method was executed + // Called via JNI from NativeMapView + // Forward to any listeners + protected void onSnapshotReady(byte[] bytes) { + if (snapshotRequest != null && bytes != null) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inBitmap = snapshotRequest.getBitmap(); // the old Bitmap to be reused + options.inMutable = true; + options.inSampleSize = 1; + Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options); + + MapboxMap.SnapshotReadyCallback callback = snapshotRequest.getCallback(); + if (callback != null) { + callback.onSnapshotReady(bitmap); + } } + } - // - // Snapshot API - // + private class SnapshotRequest { + private Bitmap bitmap; + private MapboxMap.SnapshotReadyCallback callback; - @UiThread - void snapshot(@NonNull final MapboxMap.SnapshotReadyCallback callback, @Nullable final Bitmap bitmap) { - snapshotRequest = new SnapshotRequest(bitmap, callback); - nativeMapView.scheduleTakeSnapshot(); - nativeMapView.render(); + SnapshotRequest(Bitmap bitmap, MapboxMap.SnapshotReadyCallback callback) { + this.bitmap = bitmap; + this.callback = callback; } - // Called when the snapshot method was executed - // Called via JNI from NativeMapView - // Forward to any listeners - protected void onSnapshotReady(byte[] bytes) { - if (snapshotRequest != null && bytes != null) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inBitmap = snapshotRequest.getBitmap(); // the old Bitmap to be reused - options.inMutable = true; - options.inSampleSize = 1; - Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options); - - MapboxMap.SnapshotReadyCallback callback = snapshotRequest.getCallback(); - if (callback != null) { - callback.onSnapshotReady(bitmap); - } - } + public Bitmap getBitmap() { + return bitmap; } - private class SnapshotRequest { - private Bitmap bitmap; - private MapboxMap.SnapshotReadyCallback callback; - - SnapshotRequest(Bitmap bitmap, MapboxMap.SnapshotReadyCallback callback) { - this.bitmap = bitmap; - this.callback = callback; - } - - public Bitmap getBitmap() { - return bitmap; - } - - public MapboxMap.SnapshotReadyCallback getCallback() { - return callback; - } + public MapboxMap.SnapshotReadyCallback getCallback() { + return callback; } + } - private static class AttributionOnClickListener implements View.OnClickListener, DialogInterface.OnClickListener { + private static class AttributionOnClickListener implements View.OnClickListener, DialogInterface.OnClickListener { - private static final int ATTRIBUTION_INDEX_IMPROVE_THIS_MAP = 2; - private static final int ATTRIBUTION_INDEX_TELEMETRY_SETTINGS = 3; - private MapView mapView; + private static final int ATTRIBUTION_INDEX_IMPROVE_THIS_MAP = 2; + private static final int ATTRIBUTION_INDEX_TELEMETRY_SETTINGS = 3; + private MapView mapView; - AttributionOnClickListener(MapView mapView) { - super(); - this.mapView = mapView; - } + AttributionOnClickListener(MapView mapView) { + super(); + this.mapView = mapView; + } - // Called when someone presses the attribution icon - @Override - public void onClick(View view) { - AlertDialog.Builder builder = new AlertDialog.Builder(mapView.getContext(), R.style.mapbox_AlertDialogStyle); - builder.setTitle(R.string.mapbox_attributionsDialogTitle); - String[] items = mapView.getContext().getResources().getStringArray(R.array.mapbox_attribution_names); - builder.setAdapter(new ArrayAdapter<>(mapView.getContext(), R.layout.mapbox_attribution_list_item, items), this); - builder.show(); - } + // Called when someone presses the attribution icon + @Override + public void onClick(View view) { + AlertDialog.Builder builder = new AlertDialog.Builder(mapView.getContext(), R.style.mapbox_AlertDialogStyle); + builder.setTitle(R.string.mapbox_attributionsDialogTitle); + String[] items = mapView.getContext().getResources().getStringArray(R.array.mapbox_attribution_names); + builder.setAdapter(new ArrayAdapter<>(mapView.getContext(), R.layout.mapbox_attribution_list_item, items), this); + builder.show(); + } - // Called when someone selects an attribution, 'Improve this map' adds location data to the url - @Override - public void onClick(DialogInterface dialog, int which) { - final Context context = ((Dialog) dialog).getContext(); - if (which == ATTRIBUTION_INDEX_TELEMETRY_SETTINGS) { - AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.mapbox_AlertDialogStyle); - builder.setTitle(R.string.mapbox_attributionTelemetryTitle); - builder.setMessage(R.string.mapbox_attributionTelemetryMessage); - builder.setPositiveButton(R.string.mapbox_attributionTelemetryPositive, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - MapboxEventManager.getMapboxEventManager().setTelemetryEnabled(true); - dialog.cancel(); - } - }); - builder.setNeutralButton(R.string.mapbox_attributionTelemetryNeutral, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - String url = context.getResources().getStringArray(R.array.mapbox_attribution_links)[3]; - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(url)); - context.startActivity(intent); - dialog.cancel(); - } - }); - builder.setNegativeButton(R.string.mapbox_attributionTelemetryNegative, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - MapboxEventManager.getMapboxEventManager().setTelemetryEnabled(false); - dialog.cancel(); - } - }); - - builder.show(); - return; - } - String url = context.getResources().getStringArray(R.array.mapbox_attribution_links)[which]; - if (which == ATTRIBUTION_INDEX_IMPROVE_THIS_MAP) { - CameraPosition cameraPosition = mapView.getMapboxMap().getCameraPosition(); - if (cameraPosition != null) { - url = String.format(url, cameraPosition.target.getLongitude(), - cameraPosition.target.getLatitude(), (int) cameraPosition.zoom); - } - } + // Called when someone selects an attribution, 'Improve this map' adds location data to the url + @Override + public void onClick(DialogInterface dialog, int which) { + final Context context = ((Dialog) dialog).getContext(); + if (which == ATTRIBUTION_INDEX_TELEMETRY_SETTINGS) { + AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.mapbox_AlertDialogStyle); + builder.setTitle(R.string.mapbox_attributionTelemetryTitle); + builder.setMessage(R.string.mapbox_attributionTelemetryMessage); + builder.setPositiveButton(R.string.mapbox_attributionTelemetryPositive, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + MapboxEventManager.getMapboxEventManager().setTelemetryEnabled(true); + dialog.cancel(); + } + }); + builder.setNeutralButton(R.string.mapbox_attributionTelemetryNeutral, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String url = context.getResources().getStringArray(R.array.mapbox_attribution_links)[3]; Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); context.startActivity(intent); - } - } + dialog.cancel(); + } + }); + builder.setNegativeButton(R.string.mapbox_attributionTelemetryNegative, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + MapboxEventManager.getMapboxEventManager().setTelemetryEnabled(false); + dialog.cancel(); + } + }); - /** - * Definition of a map change event. - * - * @see MapView.OnMapChangedListener#onMapChanged(int) - */ - @IntDef({REGION_WILL_CHANGE, - REGION_WILL_CHANGE_ANIMATED, - REGION_IS_CHANGING, - REGION_DID_CHANGE, - REGION_DID_CHANGE_ANIMATED, - WILL_START_LOADING_MAP, - DID_FINISH_LOADING_MAP, - DID_FAIL_LOADING_MAP, - WILL_START_RENDERING_FRAME, - DID_FINISH_RENDERING_FRAME, - DID_FINISH_RENDERING_FRAME_FULLY_RENDERED, - WILL_START_RENDERING_MAP, - DID_FINISH_RENDERING_MAP, - DID_FINISH_RENDERING_MAP_FULLY_RENDERED, - DID_FINISH_LOADING_STYLE, - SOURCE_DID_CHANGE - }) - @Retention(RetentionPolicy.SOURCE) - public @interface MapChange { + builder.show(); + return; + } + String url = context.getResources().getStringArray(R.array.mapbox_attribution_links)[which]; + if (which == ATTRIBUTION_INDEX_IMPROVE_THIS_MAP) { + CameraPosition cameraPosition = mapView.getMapboxMap().getCameraPosition(); + if (cameraPosition != null) { + url = String.format(url, cameraPosition.target.getLongitude(), + cameraPosition.target.getLatitude(), (int) cameraPosition.zoom); + } + } + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse(url)); + context.startActivity(intent); } - - /** - * This event is triggered whenever the currently displayed map region is about to changing - * without an animation. - * <p> - * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. - * </p> - * - * @see MapChange - * @see MapView.OnMapChangedListener - */ - public static final int REGION_WILL_CHANGE = 0; - - /** - * This event is triggered whenever the currently displayed map region is about to changing - * with an animation. - * <p - * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)} - * </p> - * - * @see MapChange - * @see MapView.OnMapChangedListener - */ - public static final int REGION_WILL_CHANGE_ANIMATED = 1; - - /** - * This event is triggered whenever the currently displayed map region is changing. - * <p> - * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. - * </p> - * - * @see MapChange - * @see MapView.OnMapChangedListener - */ - public static final int REGION_IS_CHANGING = 2; - - /** - * This event is triggered whenever the currently displayed map region finished changing - * without an animation. - * <p> - * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. - * </p> - * - * @see MapChange - * @see MapView.OnMapChangedListener - */ - public static final int REGION_DID_CHANGE = 3; - - /** - * This event is triggered whenever the currently displayed map region finished changing - * with an animation. - * <p> - * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. - * </p> - * - * @see MapChange - * @see MapView.OnMapChangedListener - */ - public static final int REGION_DID_CHANGE_ANIMATED = 4; - - /** - * This event is triggered when the map is about to start loading a new map style. - * <p> - * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. - * </p> - * - * @see MapChange - * @see MapView.OnMapChangedListener - */ - public static final int WILL_START_LOADING_MAP = 5; - - /** - * This is triggered when the map has successfully loaded a new map style. - * <p> - * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. - * </p> - * - * @see MapChange - * @see MapView.OnMapChangedListener - */ - public static final int DID_FINISH_LOADING_MAP = 6; - - /** - * This event is triggered when the map has failed to load a new map style. - * <p> - * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. - * </p> - * - * @see MapChange - * @see MapView.OnMapChangedListener - */ - public static final int DID_FAIL_LOADING_MAP = 7; - - /** - * This event is triggered when the map will start rendering a frame. - * <p> - * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. - * </p> - * - * @see MapChange - * @see MapView.OnMapChangedListener - */ - public static final int WILL_START_RENDERING_FRAME = 8; - - /** - * This event is triggered when the map finished rendering a frame. - * <p> - * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. - * </p> - * - * @see MapChange - * @see MapView.OnMapChangedListener - */ - public static final int DID_FINISH_RENDERING_FRAME = 9; - - /** - * This event is triggered when the map finished rendeirng the frame fully. - * <p> - * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. - * </p> - * - * @see MapChange - * @see MapView.OnMapChangedListener - */ - public static final int DID_FINISH_RENDERING_FRAME_FULLY_RENDERED = 10; - - /** - * This event is triggered when the map will start rendering the map. - * <p> - * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. - * </p> - * - * @see MapChange - * @see MapView.OnMapChangedListener - */ - public static final int WILL_START_RENDERING_MAP = 11; - - /** - * This event is triggered when the map finished rendering the map. - * <p> - * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. - * </p> - * - * @see MapChange - * @see MapView.OnMapChangedListener - */ - public static final int DID_FINISH_RENDERING_MAP = 12; - - /** - * This event is triggered when the map is fully rendered. - * <p> - * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. - * </p> - * - * @see MapChange - * @see MapView.OnMapChangedListener - */ - public static final int DID_FINISH_RENDERING_MAP_FULLY_RENDERED = 13; - - + } + + /** + * Definition of a map change event. + * + * @see MapView.OnMapChangedListener#onMapChanged(int) + */ + @IntDef( {REGION_WILL_CHANGE, + REGION_WILL_CHANGE_ANIMATED, + REGION_IS_CHANGING, + REGION_DID_CHANGE, + REGION_DID_CHANGE_ANIMATED, + WILL_START_LOADING_MAP, + DID_FINISH_LOADING_MAP, + DID_FAIL_LOADING_MAP, + WILL_START_RENDERING_FRAME, + DID_FINISH_RENDERING_FRAME, + DID_FINISH_RENDERING_FRAME_FULLY_RENDERED, + WILL_START_RENDERING_MAP, + DID_FINISH_RENDERING_MAP, + DID_FINISH_RENDERING_MAP_FULLY_RENDERED, + DID_FINISH_LOADING_STYLE, + SOURCE_DID_CHANGE + }) + @Retention(RetentionPolicy.SOURCE) + public @interface MapChange { + } + + /** + * This event is triggered whenever the currently displayed map region is about to changing + * without an animation. + * <p> + * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. + * </p> + * + * @see MapChange + * @see MapView.OnMapChangedListener + */ + public static final int REGION_WILL_CHANGE = 0; + + /** + * This event is triggered whenever the currently displayed map region is about to changing + * with an animation. + * <p> + * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)} + * </p> + * + * @see MapChange + * @see MapView.OnMapChangedListener + */ + public static final int REGION_WILL_CHANGE_ANIMATED = 1; + + /** + * This event is triggered whenever the currently displayed map region is changing. + * <p> + * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. + * </p> + * + * @see MapChange + * @see MapView.OnMapChangedListener + */ + public static final int REGION_IS_CHANGING = 2; + + /** + * This event is triggered whenever the currently displayed map region finished changing + * without an animation. + * <p> + * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. + * </p> + * + * @see MapChange + * @see MapView.OnMapChangedListener + */ + public static final int REGION_DID_CHANGE = 3; + + /** + * This event is triggered whenever the currently displayed map region finished changing + * with an animation. + * <p> + * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. + * </p> + * + * @see MapChange + * @see MapView.OnMapChangedListener + */ + public static final int REGION_DID_CHANGE_ANIMATED = 4; + + /** + * This event is triggered when the map is about to start loading a new map style. + * <p> + * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. + * </p> + * + * @see MapChange + * @see MapView.OnMapChangedListener + */ + public static final int WILL_START_LOADING_MAP = 5; + + /** + * This is triggered when the map has successfully loaded a new map style. + * <p> + * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. + * </p> + * + * @see MapChange + * @see MapView.OnMapChangedListener + */ + public static final int DID_FINISH_LOADING_MAP = 6; + + /** + * This event is triggered when the map has failed to load a new map style. + * <p> + * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. + * </p> + * + * @see MapChange + * @see MapView.OnMapChangedListener + */ + public static final int DID_FAIL_LOADING_MAP = 7; + + /** + * This event is triggered when the map will start rendering a frame. + * <p> + * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. + * </p> + * + * @see MapChange + * @see MapView.OnMapChangedListener + */ + public static final int WILL_START_RENDERING_FRAME = 8; + + /** + * This event is triggered when the map finished rendering a frame. + * <p> + * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. + * </p> + * + * @see MapChange + * @see MapView.OnMapChangedListener + */ + public static final int DID_FINISH_RENDERING_FRAME = 9; + + /** + * This event is triggered when the map finished rendeirng the frame fully. + * <p> + * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. + * </p> + * + * @see MapChange + * @see MapView.OnMapChangedListener + */ + public static final int DID_FINISH_RENDERING_FRAME_FULLY_RENDERED = 10; + + /** + * This event is triggered when the map will start rendering the map. + * <p> + * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. + * </p> + * + * @see MapChange + * @see MapView.OnMapChangedListener + */ + public static final int WILL_START_RENDERING_MAP = 11; + + /** + * This event is triggered when the map finished rendering the map. + * <p> + * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. + * </p> + * + * @see MapChange + * @see MapView.OnMapChangedListener + */ + public static final int DID_FINISH_RENDERING_MAP = 12; + + /** + * This event is triggered when the map is fully rendered. + * <p> + * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. + * </p> + * + * @see MapChange + * @see MapView.OnMapChangedListener + */ + public static final int DID_FINISH_RENDERING_MAP_FULLY_RENDERED = 13; + + + /** + * This {@link MapChange} is triggered when a style has finished loading. + * <p> + * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. + * </p> + * + * @see MapChange + * @see MapView.OnMapChangedListener + */ + public static final int DID_FINISH_LOADING_STYLE = 14; + + + /** + * This {@link MapChange} is triggered when a source attribution changes. + * <p> + * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. + * </p> + * + * @see MapChange + * @see MapView.OnMapChangedListener + */ + public static final int SOURCE_DID_CHANGE = 15; + + /** + * Interface definition for a callback to be invoked when the displayed map view changes. + * <p> + * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. + * </p> + * + * @see MapView#addOnMapChangedListener(OnMapChangedListener) + * @see MapView.MapChange + */ + public interface OnMapChangedListener { /** - * This {@link MapChange} is triggered when a style has finished loading. - * <p> - * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. - * </p> + * Called when the displayed map view changes. * - * @see MapChange - * @see MapView.OnMapChangedListener + * @param change Type of map change event, one of {@link #REGION_WILL_CHANGE}, + * {@link #REGION_WILL_CHANGE_ANIMATED}, + * {@link #REGION_IS_CHANGING}, + * {@link #REGION_DID_CHANGE}, + * {@link #REGION_DID_CHANGE_ANIMATED}, + * {@link #WILL_START_LOADING_MAP}, + * {@link #DID_FAIL_LOADING_MAP}, + * {@link #DID_FINISH_LOADING_MAP}, + * {@link #WILL_START_RENDERING_FRAME}, + * {@link #DID_FINISH_RENDERING_FRAME}, + * {@link #DID_FINISH_RENDERING_FRAME_FULLY_RENDERED}, + * {@link #WILL_START_RENDERING_MAP}, + * {@link #DID_FINISH_RENDERING_MAP}, + * {@link #DID_FINISH_RENDERING_MAP_FULLY_RENDERED}. */ - public static final int DID_FINISH_LOADING_STYLE = 14; + void onMapChanged(@MapChange int change); + } + // This class handles input events from the zoom control buttons + // Zoom controls allow single touch only devices to zoom in and out + private class OnZoomListener implements ZoomButtonsController.OnZoomListener { - /** - * This {@link MapChange} is triggered when a source attribution changes. - * <p> - * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. - * </p> - * - * @see MapChange - * @see MapView.OnMapChangedListener - */ - public static final int SOURCE_DID_CHANGE = 15; + private UiSettings uiSettings; + private Transform transform; - /** - * Interface definition for a callback to be invoked when the displayed map view changes. - * <p> - * Register to {@link MapChange} events with {@link MapView#addOnMapChangedListener(OnMapChangedListener)}. - * </p> - * - * @see MapView#addOnMapChangedListener(OnMapChangedListener) - * @see MapView.MapChange - */ - public interface OnMapChangedListener { - /** - * Called when the displayed map view changes. - * - * @param change Type of map change event, one of {@link #REGION_WILL_CHANGE}, - * {@link #REGION_WILL_CHANGE_ANIMATED}, - * {@link #REGION_IS_CHANGING}, - * {@link #REGION_DID_CHANGE}, - * {@link #REGION_DID_CHANGE_ANIMATED}, - * {@link #WILL_START_LOADING_MAP}, - * {@link #DID_FAIL_LOADING_MAP}, - * {@link #DID_FINISH_LOADING_MAP}, - * {@link #WILL_START_RENDERING_FRAME}, - * {@link #DID_FINISH_RENDERING_FRAME}, - * {@link #DID_FINISH_RENDERING_FRAME_FULLY_RENDERED}, - * {@link #WILL_START_RENDERING_MAP}, - * {@link #DID_FINISH_RENDERING_MAP}, - * {@link #DID_FINISH_RENDERING_MAP_FULLY_RENDERED}. - */ - void onMapChanged(@MapChange int change); + OnZoomListener(MapboxMap mapboxMap) { + this.uiSettings = mapboxMap.getUiSettings(); + this.transform = mapboxMap.getTransform(); } - // This class handles input events from the zoom control buttons - // Zoom controls allow single touch only devices to zoom in and out - private class OnZoomListener implements ZoomButtonsController.OnZoomListener { - - private UiSettings uiSettings; - private Transform transform; - - OnZoomListener(MapboxMap mapboxMap) { - this.uiSettings = mapboxMap.getUiSettings(); - this.transform = mapboxMap.getTransform(); - } - - // Not used - @Override - public void onVisibilityChanged(boolean visible) { - // Ignore - } + // Not used + @Override + public void onVisibilityChanged(boolean visible) { + // Ignore + } - // Called when user pushes a zoom button - @Override - public void onZoom(boolean zoomIn) { - if (!uiSettings.isZoomGesturesEnabled()) { - return; - } - transform.zoom(zoomIn); - } + // Called when user pushes a zoom button + @Override + public void onZoom(boolean zoomIn) { + if (!uiSettings.isZoomGesturesEnabled()) { + return; + } + transform.zoom(zoomIn); } + } - private class FocalPointInvalidator implements FocalPointChangeListener { + private class FocalPointInvalidator implements FocalPointChangeListener { - @Override - public void onFocalPointChanged(PointF pointF) { - mapGestureDetector.setFocalPoint(pointF); - } + @Override + public void onFocalPointChanged(PointF pointF) { + mapGestureDetector.setFocalPoint(pointF); } + } - private class RegisterTouchListener implements MapboxMap.OnRegisterTouchListener { + private class RegisterTouchListener implements MapboxMap.OnRegisterTouchListener { - @Override - public void onRegisterMapClickListener(MapboxMap.OnMapClickListener listener) { - mapGestureDetector.setOnMapClickListener(listener); - } - - @Override - public void onRegisterMapLongClickListener(MapboxMap.OnMapLongClickListener listener) { - mapGestureDetector.setOnMapLongClickListener(listener); - } + @Override + public void onRegisterMapClickListener(MapboxMap.OnMapClickListener listener) { + mapGestureDetector.setOnMapClickListener(listener); + } - @Override - public void onRegisterScrollListener(MapboxMap.OnScrollListener listener) { - mapGestureDetector.setOnScrollListener(listener); - } + @Override + public void onRegisterMapLongClickListener(MapboxMap.OnMapLongClickListener listener) { + mapGestureDetector.setOnMapLongClickListener(listener); + } - @Override - public void onRegisterFlingListener(MapboxMap.OnFlingListener listener) { - mapGestureDetector.setOnFlingListener(listener); - } + @Override + public void onRegisterScrollListener(MapboxMap.OnScrollListener listener) { + mapGestureDetector.setOnScrollListener(listener); } - NativeMapView getNativeMapView() { - return nativeMapView; + @Override + public void onRegisterFlingListener(MapboxMap.OnFlingListener listener) { + mapGestureDetector.setOnFlingListener(listener); } + } + + NativeMapView getNativeMapView() { + return nativeMapView; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java index 7459256869..eabdfb34b8 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java @@ -59,1906 +59,1913 @@ import timber.log.Timber; */ public final class MapboxMap { - private final NativeMapView nativeMapView; - private final UiSettings uiSettings; - private final TrackingSettings trackingSettings; - private final Projection projection; - private final Transform transform; - private final AnnotationManager annotationManager; - private final MyLocationViewSettings myLocationViewSettings; - private final OnRegisterTouchListener onRegisterTouchListener; - - private MapboxMap.OnFpsChangedListener onFpsChangedListener; - - MapboxMap(NativeMapView map, Transform transform, UiSettings ui, TrackingSettings tracking, MyLocationViewSettings myLocationView, - Projection projection, OnRegisterTouchListener listener, AnnotationManager annotations) { - this.nativeMapView = map; - this.uiSettings = ui; - this.trackingSettings = tracking; - this.projection = projection; - this.myLocationViewSettings = myLocationView; - this.annotationManager = annotations.bind(this); - this.transform = transform; - this.onRegisterTouchListener = listener; - } - - void initialise(@NonNull Context context, @NonNull MapboxMapOptions options) { - transform.initialise(this, options); - uiSettings.initialise(context, options); - myLocationViewSettings.initialise(options); - setMyLocationEnabled(options.getLocationEnabled()); - - // api base url - setDebugActive(options.getDebugActive()); - setApiBaseUrl(options); - setAccessToken(options); - setStyleUrl(options); - } - - // Style - - @Nullable - @UiThread - public Layer getLayer(@NonNull String layerId) { - return nativeMapView.getLayer(layerId); - } - - /** - * Tries to cast the Layer to T, returns null if it's another type. - * - * @param layerId the layer id used to look up a layer - * @param <T> the generic attribute of a Layer - * @return the casted Layer, null if another type - */ - @Nullable - @UiThread - public <T extends Layer> T getLayerAs(@NonNull String layerId) { - try { - //noinspection unchecked - return (T) nativeMapView.getLayer(layerId); - } catch (ClassCastException e) { - Timber.e(String.format("Layer: %s is a different type: %s", layerId, e.getMessage())); - return null; - } - } - - /** - * Adds the layer to the map. The layer must be newly created and not added to the map before - * - * @param layer the layer to add - */ - @UiThread - public void addLayer(@NonNull Layer layer) { - addLayer(layer, null); - } - - /** - * Adds the layer to the map. The layer must be newly created and not added to the map before - * - * @param layer the layer to add - * @param before the layer id to add this layer before - */ - @UiThread - public void addLayer(@NonNull Layer layer, String before) { - nativeMapView.addLayer(layer, before); - } - - /** - * Removes the layer. Any references to the layer become invalid and should not be used anymore - * - * @param layerId the layer to remove - * @throws NoSuchLayerException - */ - @UiThread - public void removeLayer(@NonNull String layerId) throws NoSuchLayerException { - nativeMapView.removeLayer(layerId); - } - - /** - * Removes the layer. The reference is re-usable after this and can be re-added - * - * @param layer the layer to remove - * @throws NoSuchLayerException - */ - @UiThread - public void removeLayer(@NonNull Layer layer) throws NoSuchLayerException { - nativeMapView.removeLayer(layer); - } - - @Nullable - @UiThread - public Source getSource(@NonNull String sourceId) { - return nativeMapView.getSource(sourceId); - } - - /** - * Tries to cast the Source to T, returns null if it's another type. - * - * @param sourceId the id used to look up a layer - * @param <T> the generic type of a Source - * @return the casted Source, null if another type - */ - @Nullable - @UiThread - public <T extends Source> T getSourceAs(@NonNull String sourceId) { - try { - //noinspection unchecked - return (T) nativeMapView.getSource(sourceId); - } catch (ClassCastException e) { - Timber.e(String.format("Source: %s is a different type: %s", sourceId, e.getMessage())); - return null; - } - } - - /** - * Adds the source to the map. The source must be newly created and not added to the map before - * - * @param source the source to add - */ - @UiThread - public void addSource(@NonNull Source source) { - nativeMapView.addSource(source); - } - - /** - * Removes the source. Any references to the source become invalid and should not be used anymore - * - * @param sourceId the source to remove - * @throws NoSuchSourceException - */ - @UiThread - public void removeSource(@NonNull String sourceId) throws NoSuchSourceException { - nativeMapView.removeSource(sourceId); - } - - /** - * Removes the source, preserving the reverence for re-use - * - * @param source the source to remove - * @throws NoSuchSourceException - */ - @UiThread - public void removeSource(@NonNull Source source) throws NoSuchSourceException { - nativeMapView.removeSource(source); - } - - /** - * Adds an image to be used in the map's style - * - * @param name the name of the image - * @param image the pre-multiplied Bitmap - */ - @UiThread - public void addImage(@NonNull String name, @NonNull Bitmap image) { - nativeMapView.addImage(name, image); - } - - /** - * Removes an image from the map's style - * - * @param name the name of the image to remove - */ - @UiThread - public void removeImage(String name) { - nativeMapView.removeImage(name); - } - - // - // MinZoom - // - - /** - * <p> - * Sets the minimum zoom level the map can be displayed at. - * </p> - * - * @param minZoom The new minimum zoom level. - */ - @UiThread - public void setMinZoomPreference( - @FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double minZoom) { - transform.setMinZoom(minZoom); - } - - /** - * <p> - * Gets the maximum zoom level the map can be displayed at. - * </p> - * - * @return The minimum zoom level. - */ - @UiThread - public double getMinZoomLevel() { - return transform.getMinZoom(); - } - - // - // MaxZoom - // - - /** - * <p> - * Sets the maximum zoom level the map can be displayed at. - * </p> - * - * @param maxZoom The new maximum zoom level. - */ - @UiThread - public void setMaxZoomPreference(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double maxZoom) { - transform.setMaxZoom(maxZoom); - } - - /** - * <p> - * Gets the maximum zoom level the map can be displayed at. - * </p> - * - * @return The maximum zoom level. - */ - @UiThread - public double getMaxZoomLevel() { - return transform.getMaxZoom(); - } - - // - // UiSettings - // - - /** - * Gets the user interface settings for the map. - * - * @return the UiSettings associated with this map - */ - public UiSettings getUiSettings() { - return uiSettings; - } - - // - // TrackingSettings - // - - /** - * Gets the tracking interface settings for the map. - * - * @return the TrackingSettings asssociated with this map - */ - public TrackingSettings getTrackingSettings() { - return trackingSettings; - } - - // - // MyLocationViewSettings - // - - /** - * Gets the settings of the user location for the map. - * - * @return the MyLocationViewSettings associated with this map - */ - public MyLocationViewSettings getMyLocationViewSettings() { - return myLocationViewSettings; - } - - // - // Projection - // - - /** - * Get the Projection object that you can use to convert between screen coordinates and latitude/longitude - * coordinates. - * - * @return the Projection associated with this map - */ - public Projection getProjection() { - return projection; - } - - // - // Camera API - // - - /** - * Cancels ongoing animations. - * <p> - * This invokes the {@link CancelableCallback} for ongoing camera updates. - * </p> - */ - public void cancelTransitions() { - transform.cancelTransitions(); - } - - /** - * Gets the current position of the camera. - * The CameraPosition returned is a snapshot of the current position, and will not automatically update when the - * camera moves. - * - * @return The current position of the Camera. - */ - public final CameraPosition getCameraPosition() { - return transform.getCameraPosition(); - } - - /** - * Repositions the camera according to the cameraPosition. - * The move is instantaneous, and a subsequent getCameraPosition() will reflect the new position. - * See CameraUpdateFactory for a set of updates. - * - * @param cameraPosition the camera position to set - */ - public void setCameraPosition(@NonNull CameraPosition cameraPosition) { - moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), null); - } - - /** - * Repositions the camera according to the instructions defined in the update. - * The move is instantaneous, and a subsequent getCameraPosition() will reflect the new position. - * See CameraUpdateFactory for a set of updates. - * - * @param update The change that should be applied to the camera. - */ - @UiThread - public final void moveCamera(CameraUpdate update) { - moveCamera(update, null); - // MapChange.REGION_DID_CHANGE_ANIMATED is not called for `jumpTo` - // invalidate camera position to provide OnCameraChange event. - invalidateCameraPosition(); - } - - /** - * Repositions the camera according to the instructions defined in the update. - * The move is instantaneous, and a subsequent getCameraPosition() will reflect the new position. - * See CameraUpdateFactory for a set of updates. - * - * @param update The change that should be applied to the camera - * @param callback the callback to be invoked when an animation finishes or is canceled - */ - @UiThread - public final void moveCamera(final CameraUpdate update, final MapboxMap.CancelableCallback callback) { - new Handler().post(new Runnable() { - @Override - public void run() { - transform.moveCamera(MapboxMap.this, update, callback); - } - }); - } - - /** - * Gradually move the camera by the default duration, zoom will not be affected unless specified - * within {@link CameraUpdate}. If {@link #getCameraPosition()} is called during the animation, - * it will return the current location of the camera in flight. - * - * @param update The change that should be applied to the camera. - * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates. - */ - @UiThread - public final void easeCamera(CameraUpdate update) { - easeCamera(update, MapboxConstants.ANIMATION_DURATION); - } - - /** - * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected - * unless specified within {@link CameraUpdate}. If {@link #getCameraPosition()} is called - * during the animation, it will return the current location of the camera in flight. - * - * @param update The change that should be applied to the camera. - * @param durationMs The duration of the animation in milliseconds. This must be strictly - * positive, otherwise an IllegalArgumentException will be thrown. - * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates. - */ - @UiThread - public final void easeCamera(CameraUpdate update, int durationMs) { - easeCamera(update, durationMs, null); - } - - /** - * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected - * unless specified within {@link CameraUpdate}. A callback can be used to be notified when - * easing the camera stops. If {@link #getCameraPosition()} is called during the animation, it - * will return the current location of the camera in flight. - * <p> - * Note that this will cancel location tracking mode if enabled. - * </p> - * - * @param update The change that should be applied to the camera. - * @param durationMs The duration of the animation in milliseconds. This must be strictly - * positive, otherwise an IllegalArgumentException will be thrown. - * @param callback An optional callback to be notified from the main thread when the animation - * stops. If the animation stops due to its natural completion, the callback - * will be notified with onFinish(). If the animation stops due to interruption - * by a later camera movement or a user gesture, onCancel() will be called. - * Do not update or ease the camera from within onCancel(). - * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates. - */ - @UiThread - public final void easeCamera(CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) { - easeCamera(update, durationMs, true, callback); - } - - /** - * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected - * unless specified within {@link CameraUpdate}. A callback can be used to be notified when - * easing the camera stops. If {@link #getCameraPosition()} is called during the animation, it - * will return the current location of the camera in flight. - * <p> - * Note that this will cancel location tracking mode if enabled. - * </p> - * - * @param update The change that should be applied to the camera. - * @param durationMs The duration of the animation in milliseconds. This must be strictly - * positive, otherwise an IllegalArgumentException will be thrown. - * @param easingInterpolator True for easing interpolator, false for linear. - */ - @UiThread - public final void easeCamera(CameraUpdate update, int durationMs, boolean easingInterpolator) { - easeCamera(update, durationMs, easingInterpolator, null); - } - - /** - * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected - * unless specified within {@link CameraUpdate}. A callback can be used to be notified when - * easing the camera stops. If {@link #getCameraPosition()} is called during the animation, it - * will return the current location of the camera in flight. - * <p> - * Note that this will cancel location tracking mode if enabled. - * </p> - * - * @param update The change that should be applied to the camera. - * @param durationMs The duration of the animation in milliseconds. This must be strictly - * positive, otherwise an IllegalArgumentException will be thrown. - * @param easingInterpolator True for easing interpolator, false for linear. - * @param callback An optional callback to be notified from the main thread when the animation - * stops. If the animation stops due to its natural completion, the callback - * will be notified with onFinish(). If the animation stops due to interruption - * by a later camera movement or a user gesture, onCancel() will be called. - * Do not update or ease the camera from within onCancel(). - */ - @UiThread - public final void easeCamera( - CameraUpdate update, int durationMs, boolean easingInterpolator, final MapboxMap.CancelableCallback callback) { - // dismiss tracking, moving camera is equal to a gesture - easeCamera(update, durationMs, easingInterpolator, true, callback); - } - - /** - * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected - * unless specified within {@link CameraUpdate}. A callback can be used to be notified when - * easing the camera stops. If {@link #getCameraPosition()} is called during the animation, it - * will return the current location of the camera in flight. - * <p> - * Note that this will cancel location tracking mode if enabled. - * </p> - * - * @param update The change that should be applied to the camera. - * @param durationMs The duration of the animation in milliseconds. This must be strictly - * positive, otherwise an IllegalArgumentException will be thrown. - * @param resetTrackingMode True to reset tracking modes if required, false to ignore - * @param easingInterpolator True for easing interpolator, false for linear. - * @param callback An optional callback to be notified from the main thread when the animation - * stops. If the animation stops due to its natural completion, the callback - * will be notified with onFinish(). If the animation stops due to interruption - * by a later camera movement or a user gesture, onCancel() will be called. - * Do not update or ease the camera from within onCancel(). - */ - @UiThread - public final void easeCamera(final CameraUpdate update, final int durationMs, final boolean easingInterpolator, final boolean resetTrackingMode, final MapboxMap.CancelableCallback callback) { - new Handler().post(new Runnable() { - @Override - public void run() { - transform.easeCamera(MapboxMap.this, update, durationMs, easingInterpolator, resetTrackingMode, callback); - } - }); - } - - /** - * Animate the camera to a new location defined within {@link CameraUpdate} using a transition - * animation that evokes powered flight. The animation will last the default amount of time. - * During the animation, a call to {@link #getCameraPosition()} returns an intermediate location - * of the camera in flight. - * - * @param update The change that should be applied to the camera. - * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates. - */ - @UiThread - public final void animateCamera(CameraUpdate update) { - animateCamera(update, MapboxConstants.ANIMATION_DURATION, null); - } - - /** - * Animate the camera to a new location defined within {@link CameraUpdate} using a transition - * animation that evokes powered flight. The animation will last the default amount of time. A - * callback can be used to be notified when animating the camera stops. During the animation, a - * call to {@link #getCameraPosition()} returns an intermediate location of the camera in flight. - * - * @param update The change that should be applied to the camera. - * @param callback The callback to invoke from the main thread when the animation stops. If the - * animation completes normally, onFinish() is called; otherwise, onCancel() is - * called. Do not update or animate the camera from within onCancel(). - * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates. - */ - @UiThread - public final void animateCamera(CameraUpdate update, MapboxMap.CancelableCallback callback) { - animateCamera(update, MapboxConstants.ANIMATION_DURATION, callback); - } - - /** - * Animate the camera to a new location defined within {@link CameraUpdate} using a transition - * animation that evokes powered flight. The animation will last a specified amount of time - * given in milliseconds. During the animation, a call to {@link #getCameraPosition()} returns - * an intermediate location of the camera in flight. - * - * @param update The change that should be applied to the camera. - * @param durationMs The duration of the animation in milliseconds. This must be strictly - * positive, otherwise an IllegalArgumentException will be thrown. - * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates. - */ - @UiThread - public final void animateCamera(CameraUpdate update, int durationMs) { - animateCamera(update, durationMs, null); - } - - /** - * Animate the camera to a new location defined within {@link CameraUpdate} using a transition - * animation that evokes powered flight. The animation will last a specified amount of time - * given in milliseconds. A callback can be used to be notified when animating the camera stops. - * During the animation, a call to {@link #getCameraPosition()} returns an intermediate location - * of the camera in flight. - * - * @param update The change that should be applied to the camera. - * @param durationMs The duration of the animation in milliseconds. This must be strictly - * positive, otherwise an IllegalArgumentException will be thrown. - * @param callback An optional callback to be notified from the main thread when the animation - * stops. If the animation stops due to its natural completion, the callback - * will be notified with onFinish(). If the animation stops due to interruption - * by a later camera movement or a user gesture, onCancel() will be called. - * Do not update or animate the camera from within onCancel(). If a callback - * isn't required, leave it as null. - * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates. - */ - @UiThread - public final void animateCamera(final CameraUpdate update, final int durationMs, final MapboxMap.CancelableCallback callback) { - new Handler().post(new Runnable() { - @Override - public void run() { - transform.animateCamera(MapboxMap.this, update, durationMs, callback); - } - }); - } - - /** - * Invalidates the current camera position by reconstructing it from mbgl - */ - void invalidateCameraPosition() { - CameraPosition cameraPosition = transform.invalidateCameraPosition(); - if (cameraPosition != null) { - transform.updateCameraPosition(cameraPosition); - } - } - - // - // Reset North - // - - /** - * Resets the map view to face north. - */ - public void resetNorth() { - transform.resetNorth(); - } - - // - // Debug - // - - /** - * Returns whether the map debug information is currently shown. - * - * @return If true, map debug information is currently shown. - */ - @UiThread - public boolean isDebugActive() { - return nativeMapView.getDebug(); - } - - /** - * <p> - * Changes whether the map debug information is shown. - * </p> - * The default value is false. - * - * @param debugActive If true, map debug information is shown. - */ - @UiThread - public void setDebugActive(boolean debugActive) { - nativeMapView.setDebug(debugActive); - } - - /** - * <p> - * Cycles through the map debug options. - * </p> - * The value of isDebugActive reflects whether there are - * any map debug options enabled or disabled. - * - * @see #isDebugActive() - */ - @UiThread - public void cycleDebugOptions() { - nativeMapView.cycleDebugOptions(); - } - - // - // API endpoint config - // - - private void setApiBaseUrl(@NonNull MapboxMapOptions options) { - String apiBaseUrl = options.getApiBaseUrl(); - if (!TextUtils.isEmpty(apiBaseUrl)) { - nativeMapView.setApiBaseUrl(apiBaseUrl); - } - } - - // - // Styling - // - - /** - * <p> - * Loads a new map style from the specified URL. - * </p> - * {@code url} can take the following forms: - * <ul> - * <li>{@code Style.*}: load one of the bundled styles in {@link Style}.</li> - * <li>{@code mapbox://styles/<user>/<style>}: - * retrieves the style from a <a href="https://www.mapbox.com/account/">Mapbox account.</a> - * {@code user} is your username. {@code style} is the ID of your custom - * style created in <a href="https://www.mapbox.com/studio">Mapbox Studio</a>.</li> - * <li>{@code http://...} or {@code https://...}: - * retrieves the style over the Internet from any web server.</li> - * <li>{@code asset://...}: - * reads the style from the APK {@code assets/} directory. - * This is used to load a style bundled with your app.</li> - * <li>{@code null}: loads the default {@link Style#MAPBOX_STREETS} style.</li> - * </ul> - * <p> - * This method is asynchronous and will return immediately before the style finishes loading. - * If you wish to wait for the map to finish loading listen for the {@link MapView#DID_FINISH_LOADING_MAP} event. - * </p> - * If the style fails to load or an invalid style URL is set, the map view will become blank. - * An error message will be logged in the Android logcat and {@link MapView#DID_FAIL_LOADING_MAP} event will be - * sent. - * - * @param url The URL of the map style - * @see Style - */ - @UiThread - public void setStyleUrl(@NonNull String url) { - nativeMapView.setStyleUrl(url); - } - - /** - * <p> - * Loads a new map style from the specified bundled style. - * </p> - * <p> - * This method is asynchronous and will return immediately before the style finishes loading. - * If you wish to wait for the map to finish loading listen for the {@link MapView#DID_FINISH_LOADING_MAP} event. - * </p> - * If the style fails to load or an invalid style URL is set, the map view will become blank. - * An error message will be logged in the Android logcat and {@link MapView#DID_FAIL_LOADING_MAP} event will be - * sent. - * - * @param style The bundled style. Accepts one of the values from {@link Style}. - * @see Style - * @deprecated use {@link #setStyleUrl(String)} instead with versioned url methods from {@link Style} - */ - @UiThread - @Deprecated - public void setStyle(@Style.StyleUrl String style) { - setStyleUrl(style); - } - - /** - * Loads a new map style from MapboxMapOptions if available. - * - * @param options the object containing the style url - */ - private void setStyleUrl(@NonNull MapboxMapOptions options) { - String style = options.getStyle(); - if (!TextUtils.isEmpty(style)) { - setStyleUrl(style); - } - } - - /** - * <p> - * Returns the map style currently displayed in the map view. - * </p> - * If the default style is currently displayed, a URL will be returned instead of null. - * - * @return The URL of the map style. - */ - @UiThread - @NonNull - public String getStyleUrl() { - return nativeMapView.getStyleUrl(); - } - - // - // Access token - // - - /** - * <p> - * DEPRECATED @see MapboxAccountManager#start(String) - * </p> - * <p> - * Sets the current Mapbox access token used to load map styles and tiles. - * </p> - * - * @param accessToken Your public Mapbox access token. - * @see MapView#setAccessToken(String) - * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)} - */ - @Deprecated - @UiThread - public void setAccessToken(@NonNull String accessToken) { - nativeMapView.setAccessToken(accessToken); - } - - /** - * <p> - * DEPRECATED @see MapboxAccountManager#getAccessToken() - * </p> - * <p> - * Returns the current Mapbox access token used to load map styles and tiles. - * </p> - * - * @return The current Mapbox access token. - * @deprecated As of release 4.1.0, replaced by {@link MapboxAccountManager#getAccessToken()} - */ - @Deprecated - @UiThread - @Nullable - public String getAccessToken() { - return nativeMapView.getAccessToken(); - } - - private void setAccessToken(@NonNull MapboxMapOptions options) { - String accessToken = options.getAccessToken(); - if (!TextUtils.isEmpty(accessToken)) { - nativeMapView.setAccessToken(accessToken); - } else { - nativeMapView.setAccessToken(MapboxAccountManager.getInstance().getAccessToken()); - } - } - - // - // Annotations - // - - /** - * <p> - * Adds a marker to this map. - * </p> - * The marker's icon is rendered on the map at the location {@code Marker.position}. - * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet. - * - * @param markerOptions A marker options object that defines how to render the marker. - * @return The {@code Marker} that was added to the map. - */ - @UiThread - @NonNull - public Marker addMarker(@NonNull MarkerOptions markerOptions) { - return annotationManager.addMarker(markerOptions, this); - } - - /** - * <p> - * Adds a marker to this map. - * </p> - * The marker's icon is rendered on the map at the location {@code Marker.position}. - * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet. - * - * @param markerOptions A marker options object that defines how to render the marker. - * @return The {@code Marker} that was added to the map. - */ - @UiThread - @NonNull - public Marker addMarker(@NonNull BaseMarkerOptions markerOptions) { - return annotationManager.addMarker(markerOptions, this); - } - - /** - * <p> - * Adds a marker to this map. - * </p> - * The marker's icon is rendered on the map at the location {@code Marker.position}. - * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet. - * - * @param markerOptions A marker options object that defines how to render the marker. - * @return The {@code Marker} that was added to the map. - */ - @UiThread - @NonNull - public MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions) { - return annotationManager.addMarker(markerOptions, this, null); - } + private final NativeMapView nativeMapView; + private final UiSettings uiSettings; + private final TrackingSettings trackingSettings; + private final Projection projection; + private final Transform transform; + private final AnnotationManager annotationManager; + private final MyLocationViewSettings myLocationViewSettings; + private final OnRegisterTouchListener onRegisterTouchListener; + + private MapboxMap.OnFpsChangedListener onFpsChangedListener; + + MapboxMap(NativeMapView map, Transform transform, UiSettings ui, TrackingSettings tracking, + MyLocationViewSettings myLocationView, Projection projection, OnRegisterTouchListener listener, + AnnotationManager annotations) { + this.nativeMapView = map; + this.uiSettings = ui; + this.trackingSettings = tracking; + this.projection = projection; + this.myLocationViewSettings = myLocationView; + this.annotationManager = annotations.bind(this); + this.transform = transform; + this.onRegisterTouchListener = listener; + } + + void initialise(@NonNull Context context, @NonNull MapboxMapOptions options) { + transform.initialise(this, options); + uiSettings.initialise(context, options); + myLocationViewSettings.initialise(options); + setMyLocationEnabled(options.getLocationEnabled()); + + // api base url + setDebugActive(options.getDebugActive()); + setApiBaseUrl(options); + setAccessToken(options); + setStyleUrl(options); + } + + // Style + + @Nullable + @UiThread + public Layer getLayer(@NonNull String layerId) { + return nativeMapView.getLayer(layerId); + } + + /** + * Tries to cast the Layer to T, returns null if it's another type. + * + * @param layerId the layer id used to look up a layer + * @param <T> the generic attribute of a Layer + * @return the casted Layer, null if another type + */ + @Nullable + @UiThread + public <T extends Layer> T getLayerAs(@NonNull String layerId) { + try { + //noinspection unchecked + return (T) nativeMapView.getLayer(layerId); + } catch (ClassCastException classCastException) { + Timber.e(String.format("Layer: %s is a different type: %s", layerId, classCastException.getMessage())); + return null; + } + } + + /** + * Adds the layer to the map. The layer must be newly created and not added to the map before + * + * @param layer the layer to add + */ + @UiThread + public void addLayer(@NonNull Layer layer) { + addLayer(layer, null); + } + + /** + * Adds the layer to the map. The layer must be newly created and not added to the map before + * + * @param layer the layer to add + * @param before the layer id to add this layer before + */ + @UiThread + public void addLayer(@NonNull Layer layer, String before) { + nativeMapView.addLayer(layer, before); + } + + /** + * Removes the layer. Any references to the layer become invalid and should not be used anymore + * + * @param layerId the layer to remove + * @throws NoSuchLayerException Thrown when the layer doesn't exist. + */ + @UiThread + public void removeLayer(@NonNull String layerId) throws NoSuchLayerException { + nativeMapView.removeLayer(layerId); + } + + /** + * Removes the layer. The reference is re-usable after this and can be re-added + * + * @param layer the layer to remove + * @throws NoSuchLayerException Thrown when the layer doesn't exist. + */ + @UiThread + public void removeLayer(@NonNull Layer layer) throws NoSuchLayerException { + nativeMapView.removeLayer(layer); + } + + @Nullable + @UiThread + public Source getSource(@NonNull String sourceId) { + return nativeMapView.getSource(sourceId); + } + + /** + * Tries to cast the Source to T, returns null if it's another type. + * + * @param sourceId the id used to look up a layer + * @param <T> the generic type of a Source + * @return the casted Source, null if another type + */ + @Nullable + @UiThread + public <T extends Source> T getSourceAs(@NonNull String sourceId) { + try { + //noinspection unchecked + return (T) nativeMapView.getSource(sourceId); + } catch (ClassCastException classCastException) { + Timber.e(String.format("Source: %s is a different type: %s", sourceId, classCastException.getMessage())); + return null; + } + } + + /** + * Adds the source to the map. The source must be newly created and not added to the map before + * + * @param source the source to add + */ + @UiThread + public void addSource(@NonNull Source source) { + nativeMapView.addSource(source); + } + + /** + * Removes the source. Any references to the source become invalid and should not be used anymore + * + * @param sourceId the source to remove + * @throws NoSuchSourceException Thrown when the source doesn't exist. + */ + @UiThread + public void removeSource(@NonNull String sourceId) throws NoSuchSourceException { + nativeMapView.removeSource(sourceId); + } + + /** + * Removes the source, preserving the reverence for re-use + * + * @param source the source to remove + * @throws NoSuchSourceException Thrown when the source doesn't exist. + */ + @UiThread + public void removeSource(@NonNull Source source) throws NoSuchSourceException { + nativeMapView.removeSource(source); + } + + /** + * Adds an image to be used in the map's style + * + * @param name the name of the image + * @param image the pre-multiplied Bitmap + */ + @UiThread + public void addImage(@NonNull String name, @NonNull Bitmap image) { + nativeMapView.addImage(name, image); + } + + /** + * Removes an image from the map's style + * + * @param name the name of the image to remove + */ + @UiThread + public void removeImage(String name) { + nativeMapView.removeImage(name); + } + + // + // MinZoom + // + + /** + * <p> + * Sets the minimum zoom level the map can be displayed at. + * </p> + * + * @param minZoom The new minimum zoom level. + */ + @UiThread + public void setMinZoomPreference( + @FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double minZoom) { + transform.setMinZoom(minZoom); + } + + /** + * <p> + * Gets the maximum zoom level the map can be displayed at. + * </p> + * + * @return The minimum zoom level. + */ + @UiThread + public double getMinZoomLevel() { + return transform.getMinZoom(); + } + + // + // MaxZoom + // + + /** + * <p> + * Sets the maximum zoom level the map can be displayed at. + * </p> + * + * @param maxZoom The new maximum zoom level. + */ + @UiThread + public void setMaxZoomPreference(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to + = MapboxConstants.MAXIMUM_ZOOM) double maxZoom) { + transform.setMaxZoom(maxZoom); + } + + /** + * <p> + * Gets the maximum zoom level the map can be displayed at. + * </p> + * + * @return The maximum zoom level. + */ + @UiThread + public double getMaxZoomLevel() { + return transform.getMaxZoom(); + } + + // + // UiSettings + // + + /** + * Gets the user interface settings for the map. + * + * @return the UiSettings associated with this map + */ + public UiSettings getUiSettings() { + return uiSettings; + } + + // + // TrackingSettings + // + + /** + * Gets the tracking interface settings for the map. + * + * @return the TrackingSettings asssociated with this map + */ + public TrackingSettings getTrackingSettings() { + return trackingSettings; + } + + // + // MyLocationViewSettings + // + + /** + * Gets the settings of the user location for the map. + * + * @return the MyLocationViewSettings associated with this map + */ + public MyLocationViewSettings getMyLocationViewSettings() { + return myLocationViewSettings; + } + + // + // Projection + // + + /** + * Get the Projection object that you can use to convert between screen coordinates and latitude/longitude + * coordinates. + * + * @return the Projection associated with this map + */ + public Projection getProjection() { + return projection; + } + + // + // Camera API + // + + /** + * Cancels ongoing animations. + * <p> + * This invokes the {@link CancelableCallback} for ongoing camera updates. + * </p> + */ + public void cancelTransitions() { + transform.cancelTransitions(); + } + + /** + * Gets the current position of the camera. + * The CameraPosition returned is a snapshot of the current position, and will not automatically update when the + * camera moves. + * + * @return The current position of the Camera. + */ + public final CameraPosition getCameraPosition() { + return transform.getCameraPosition(); + } + + /** + * Repositions the camera according to the cameraPosition. + * The move is instantaneous, and a subsequent getCameraPosition() will reflect the new position. + * See CameraUpdateFactory for a set of updates. + * + * @param cameraPosition the camera position to set + */ + public void setCameraPosition(@NonNull CameraPosition cameraPosition) { + moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), null); + } + + /** + * Repositions the camera according to the instructions defined in the update. + * The move is instantaneous, and a subsequent getCameraPosition() will reflect the new position. + * See CameraUpdateFactory for a set of updates. + * + * @param update The change that should be applied to the camera. + */ + @UiThread + public final void moveCamera(CameraUpdate update) { + moveCamera(update, null); + // MapChange.REGION_DID_CHANGE_ANIMATED is not called for `jumpTo` + // invalidate camera position to provide OnCameraChange event. + invalidateCameraPosition(); + } + + /** + * Repositions the camera according to the instructions defined in the update. + * The move is instantaneous, and a subsequent getCameraPosition() will reflect the new position. + * See CameraUpdateFactory for a set of updates. + * + * @param update The change that should be applied to the camera + * @param callback the callback to be invoked when an animation finishes or is canceled + */ + @UiThread + public final void moveCamera(final CameraUpdate update, final MapboxMap.CancelableCallback callback) { + new Handler().post(new Runnable() { + @Override + public void run() { + transform.moveCamera(MapboxMap.this, update, callback); + } + }); + } + + /** + * Gradually move the camera by the default duration, zoom will not be affected unless specified + * within {@link CameraUpdate}. If {@link #getCameraPosition()} is called during the animation, + * it will return the current location of the camera in flight. + * + * @param update The change that should be applied to the camera. + * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates. + */ + @UiThread + public final void easeCamera(CameraUpdate update) { + easeCamera(update, MapboxConstants.ANIMATION_DURATION); + } + + /** + * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected + * unless specified within {@link CameraUpdate}. If {@link #getCameraPosition()} is called + * during the animation, it will return the current location of the camera in flight. + * + * @param update The change that should be applied to the camera. + * @param durationMs The duration of the animation in milliseconds. This must be strictly + * positive, otherwise an IllegalArgumentException will be thrown. + * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates. + */ + @UiThread + public final void easeCamera(CameraUpdate update, int durationMs) { + easeCamera(update, durationMs, null); + } + + /** + * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected + * unless specified within {@link CameraUpdate}. A callback can be used to be notified when + * easing the camera stops. If {@link #getCameraPosition()} is called during the animation, it + * will return the current location of the camera in flight. + * <p> + * Note that this will cancel location tracking mode if enabled. + * </p> + * + * @param update The change that should be applied to the camera. + * @param durationMs The duration of the animation in milliseconds. This must be strictly + * positive, otherwise an IllegalArgumentException will be thrown. + * @param callback An optional callback to be notified from the main thread when the animation + * stops. If the animation stops due to its natural completion, the callback + * will be notified with onFinish(). If the animation stops due to interruption + * by a later camera movement or a user gesture, onCancel() will be called. + * Do not update or ease the camera from within onCancel(). + * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates. + */ + @UiThread + public final void easeCamera(CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) { + easeCamera(update, durationMs, true, callback); + } + + /** + * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected + * unless specified within {@link CameraUpdate}. A callback can be used to be notified when + * easing the camera stops. If {@link #getCameraPosition()} is called during the animation, it + * will return the current location of the camera in flight. + * <p> + * Note that this will cancel location tracking mode if enabled. + * </p> + * + * @param update The change that should be applied to the camera. + * @param durationMs The duration of the animation in milliseconds. This must be strictly + * positive, otherwise an IllegalArgumentException will be thrown. + * @param easingInterpolator True for easing interpolator, false for linear. + */ + @UiThread + public final void easeCamera(CameraUpdate update, int durationMs, boolean easingInterpolator) { + easeCamera(update, durationMs, easingInterpolator, null); + } + + /** + * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected + * unless specified within {@link CameraUpdate}. A callback can be used to be notified when + * easing the camera stops. If {@link #getCameraPosition()} is called during the animation, it + * will return the current location of the camera in flight. + * <p> + * Note that this will cancel location tracking mode if enabled. + * </p> + * + * @param update The change that should be applied to the camera. + * @param durationMs The duration of the animation in milliseconds. This must be strictly + * positive, otherwise an IllegalArgumentException will be thrown. + * @param easingInterpolator True for easing interpolator, false for linear. + * @param callback An optional callback to be notified from the main thread when the animation + * stops. If the animation stops due to its natural completion, the callback + * will be notified with onFinish(). If the animation stops due to interruption + * by a later camera movement or a user gesture, onCancel() will be called. + * Do not update or ease the camera from within onCancel(). + */ + @UiThread + public final void easeCamera( + CameraUpdate update, int durationMs, boolean easingInterpolator, final MapboxMap.CancelableCallback callback) { + // dismiss tracking, moving camera is equal to a gesture + easeCamera(update, durationMs, easingInterpolator, true, callback); + } + + /** + * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected + * unless specified within {@link CameraUpdate}. A callback can be used to be notified when + * easing the camera stops. If {@link #getCameraPosition()} is called during the animation, it + * will return the current location of the camera in flight. + * <p> + * Note that this will cancel location tracking mode if enabled. + * </p> + * + * @param update The change that should be applied to the camera. + * @param durationMs The duration of the animation in milliseconds. This must be strictly + * positive, otherwise an IllegalArgumentException will be thrown. + * @param resetTrackingMode True to reset tracking modes if required, false to ignore + * @param easingInterpolator True for easing interpolator, false for linear. + * @param callback An optional callback to be notified from the main thread when the animation + * stops. If the animation stops due to its natural completion, the callback + * will be notified with onFinish(). If the animation stops due to interruption + * by a later camera movement or a user gesture, onCancel() will be called. + * Do not update or ease the camera from within onCancel(). + */ + @UiThread + public final void easeCamera(final CameraUpdate update, final int durationMs, final boolean easingInterpolator, + final boolean resetTrackingMode, final MapboxMap.CancelableCallback callback) { + new Handler().post(new Runnable() { + @Override + public void run() { + transform.easeCamera(MapboxMap.this, update, durationMs, easingInterpolator, resetTrackingMode, callback); + } + }); + } + + /** + * Animate the camera to a new location defined within {@link CameraUpdate} using a transition + * animation that evokes powered flight. The animation will last the default amount of time. + * During the animation, a call to {@link #getCameraPosition()} returns an intermediate location + * of the camera in flight. + * + * @param update The change that should be applied to the camera. + * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates. + */ + @UiThread + public final void animateCamera(CameraUpdate update) { + animateCamera(update, MapboxConstants.ANIMATION_DURATION, null); + } + + /** + * Animate the camera to a new location defined within {@link CameraUpdate} using a transition + * animation that evokes powered flight. The animation will last the default amount of time. A + * callback can be used to be notified when animating the camera stops. During the animation, a + * call to {@link #getCameraPosition()} returns an intermediate location of the camera in flight. + * + * @param update The change that should be applied to the camera. + * @param callback The callback to invoke from the main thread when the animation stops. If the + * animation completes normally, onFinish() is called; otherwise, onCancel() is + * called. Do not update or animate the camera from within onCancel(). + * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates. + */ + @UiThread + public final void animateCamera(CameraUpdate update, MapboxMap.CancelableCallback callback) { + animateCamera(update, MapboxConstants.ANIMATION_DURATION, callback); + } + + /** + * Animate the camera to a new location defined within {@link CameraUpdate} using a transition + * animation that evokes powered flight. The animation will last a specified amount of time + * given in milliseconds. During the animation, a call to {@link #getCameraPosition()} returns + * an intermediate location of the camera in flight. + * + * @param update The change that should be applied to the camera. + * @param durationMs The duration of the animation in milliseconds. This must be strictly + * positive, otherwise an IllegalArgumentException will be thrown. + * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates. + */ + @UiThread + public final void animateCamera(CameraUpdate update, int durationMs) { + animateCamera(update, durationMs, null); + } + + /** + * Animate the camera to a new location defined within {@link CameraUpdate} using a transition + * animation that evokes powered flight. The animation will last a specified amount of time + * given in milliseconds. A callback can be used to be notified when animating the camera stops. + * During the animation, a call to {@link #getCameraPosition()} returns an intermediate location + * of the camera in flight. + * + * @param update The change that should be applied to the camera. + * @param durationMs The duration of the animation in milliseconds. This must be strictly + * positive, otherwise an IllegalArgumentException will be thrown. + * @param callback An optional callback to be notified from the main thread when the animation + * stops. If the animation stops due to its natural completion, the callback + * will be notified with onFinish(). If the animation stops due to interruption + * by a later camera movement or a user gesture, onCancel() will be called. + * Do not update or animate the camera from within onCancel(). If a callback + * isn't required, leave it as null. + * @see com.mapbox.mapboxsdk.camera.CameraUpdateFactory for a set of updates. + */ + @UiThread + public final void animateCamera(final CameraUpdate update, final int durationMs, + final MapboxMap.CancelableCallback callback) { + new Handler().post(new Runnable() { + @Override + public void run() { + transform.animateCamera(MapboxMap.this, update, durationMs, callback); + } + }); + } + + /** + * Invalidates the current camera position by reconstructing it from mbgl + */ + void invalidateCameraPosition() { + CameraPosition cameraPosition = transform.invalidateCameraPosition(); + if (cameraPosition != null) { + transform.updateCameraPosition(cameraPosition); + } + } + + // + // Reset North + // + + /** + * Resets the map view to face north. + */ + public void resetNorth() { + transform.resetNorth(); + } + + // + // Debug + // + + /** + * Returns whether the map debug information is currently shown. + * + * @return If true, map debug information is currently shown. + */ + @UiThread + public boolean isDebugActive() { + return nativeMapView.getDebug(); + } + + /** + * <p> + * Changes whether the map debug information is shown. + * </p> + * The default value is false. + * + * @param debugActive If true, map debug information is shown. + */ + @UiThread + public void setDebugActive(boolean debugActive) { + nativeMapView.setDebug(debugActive); + } + + /** + * <p> + * Cycles through the map debug options. + * </p> + * The value of isDebugActive reflects whether there are + * any map debug options enabled or disabled. + * + * @see #isDebugActive() + */ + @UiThread + public void cycleDebugOptions() { + nativeMapView.cycleDebugOptions(); + } + + // + // API endpoint config + // + + private void setApiBaseUrl(@NonNull MapboxMapOptions options) { + String apiBaseUrl = options.getApiBaseUrl(); + if (!TextUtils.isEmpty(apiBaseUrl)) { + nativeMapView.setApiBaseUrl(apiBaseUrl); + } + } + + // + // Styling + // + + /** + * <p> + * Loads a new map style from the specified bundled style. + * </p> + * <p> + * This method is asynchronous and will return immediately before the style finishes loading. + * If you wish to wait for the map to finish loading listen for the {@link MapView#DID_FINISH_LOADING_MAP} event. + * </p> + * If the style fails to load or an invalid style URL is set, the map view will become blank. + * An error message will be logged in the Android logcat and {@link MapView#DID_FAIL_LOADING_MAP} event will be + * sent. + * + * @param style The bundled style. Accepts one of the values from {@link Style}. + * @see Style + * @deprecated use {@link #setStyleUrl(String)} instead with versioned url methods from {@link Style} + */ + @UiThread + @Deprecated + public void setStyle(@Style.StyleUrl String style) { + setStyleUrl(style); + } + + /** + * <p> + * Loads a new map style from the specified URL. + * </p> + * {@code url} can take the following forms: + * <ul> + * <li>{@code Style.*}: load one of the bundled styles in {@link Style}.</li> + * <li>{@code mapbox://styles/<user>/<style>}: + * retrieves the style from a <a href="https://www.mapbox.com/account/">Mapbox account.</a> + * {@code user} is your username. {@code style} is the ID of your custom + * style created in <a href="https://www.mapbox.com/studio">Mapbox Studio</a>.</li> + * <li>{@code http://...} or {@code https://...}: + * retrieves the style over the Internet from any web server.</li> + * <li>{@code asset://...}: + * reads the style from the APK {@code assets/} directory. + * This is used to load a style bundled with your app.</li> + * <li>{@code null}: loads the default {@link Style#MAPBOX_STREETS} style.</li> + * </ul> + * <p> + * This method is asynchronous and will return immediately before the style finishes loading. + * If you wish to wait for the map to finish loading listen for the {@link MapView#DID_FINISH_LOADING_MAP} event. + * </p> + * If the style fails to load or an invalid style URL is set, the map view will become blank. + * An error message will be logged in the Android logcat and {@link MapView#DID_FAIL_LOADING_MAP} event will be + * sent. + * + * @param url The URL of the map style + * @see Style + */ + @UiThread + public void setStyleUrl(@NonNull String url) { + nativeMapView.setStyleUrl(url); + } + + /** + * Loads a new map style from MapboxMapOptions if available. + * + * @param options the object containing the style url + */ + private void setStyleUrl(@NonNull MapboxMapOptions options) { + String style = options.getStyle(); + if (!TextUtils.isEmpty(style)) { + setStyleUrl(style); + } + } + + /** + * <p> + * Returns the map style currently displayed in the map view. + * </p> + * If the default style is currently displayed, a URL will be returned instead of null. + * + * @return The URL of the map style. + */ + @UiThread + @NonNull + public String getStyleUrl() { + return nativeMapView.getStyleUrl(); + } + + // + // Access token + // + + /** + * <p> + * DEPRECATED @see MapboxAccountManager#getAccessToken() + * </p> + * <p> + * Returns the current Mapbox access token used to load map styles and tiles. + * </p> + * + * @return The current Mapbox access token. + * @deprecated As of release 4.1.0, replaced by {@link MapboxAccountManager#getAccessToken()} + */ + @Deprecated + @UiThread + @Nullable + public String getAccessToken() { + return nativeMapView.getAccessToken(); + } + + /** + * <p> + * DEPRECATED @see MapboxAccountManager#start(String) + * </p> + * <p> + * Sets the current Mapbox access token used to load map styles and tiles. + * </p> + * + * @param accessToken Your public Mapbox access token. + * @see MapView#setAccessToken(String) + * @deprecated As of release 4.1.0, replaced by + * {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)} + */ + @Deprecated + @UiThread + public void setAccessToken(@NonNull String accessToken) { + nativeMapView.setAccessToken(accessToken); + } + + private void setAccessToken(@NonNull MapboxMapOptions options) { + String accessToken = options.getAccessToken(); + if (!TextUtils.isEmpty(accessToken)) { + nativeMapView.setAccessToken(accessToken); + } else { + nativeMapView.setAccessToken(MapboxAccountManager.getInstance().getAccessToken()); + } + } + + // + // Annotations + // + + /** + * <p> + * Adds a marker to this map. + * </p> + * The marker's icon is rendered on the map at the location {@code Marker.position}. + * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet. + * + * @param markerOptions A marker options object that defines how to render the marker. + * @return The {@code Marker} that was added to the map. + */ + @UiThread + @NonNull + public Marker addMarker(@NonNull MarkerOptions markerOptions) { + return annotationManager.addMarker(markerOptions, this); + } + + /** + * <p> + * Adds a marker to this map. + * </p> + * The marker's icon is rendered on the map at the location {@code Marker.position}. + * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet. + * + * @param markerOptions A marker options object that defines how to render the marker. + * @return The {@code Marker} that was added to the map. + */ + @UiThread + @NonNull + public Marker addMarker(@NonNull BaseMarkerOptions markerOptions) { + return annotationManager.addMarker(markerOptions, this); + } + + /** + * <p> + * Adds a marker to this map. + * </p> + * The marker's icon is rendered on the map at the location {@code Marker.position}. + * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet. + * + * @param markerOptions A marker options object that defines how to render the marker. + * @return The {@code Marker} that was added to the map. + */ + @UiThread + @NonNull + public MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions) { + return annotationManager.addMarker(markerOptions, this, null); + } + + + /** + * <p> + * Adds a marker to this map. + * </p> + * The marker's icon is rendered on the map at the location {@code Marker.position}. + * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet. + * + * @param markerOptions A marker options object that defines how to render the marker. + * @param onMarkerViewAddedListener Callback invoked when the View has been added to the map. + * @return The {@code Marker} that was added to the map. + */ + @UiThread + @NonNull + public MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions, + final MarkerViewManager.OnMarkerViewAddedListener onMarkerViewAddedListener) { + return annotationManager.addMarker(markerOptions, this, onMarkerViewAddedListener); + } + + @UiThread + @NonNull + public List<MarkerView> addMarkerViews(@NonNull List<? extends + BaseMarkerViewOptions> markerViewOptions) { + return annotationManager.addMarkerViews(markerViewOptions, this); + } + + @UiThread + @NonNull + public List<MarkerView> getMarkerViewsInRect(@NonNull RectF rect) { + return annotationManager.getMarkerViewsInRect(rect); + } + + /** + * <p> + * Adds multiple markers to this map. + * </p> + * The marker's icon is rendered on the map at the location {@code Marker.position}. + * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet. + * + * @param markerOptionsList A list of marker options objects that defines how to render the markers. + * @return A list of the {@code Marker}s that were added to the map. + */ + @UiThread + @NonNull + public List<Marker> addMarkers(@NonNull List<? extends + BaseMarkerOptions> markerOptionsList) { + return annotationManager.addMarkers(markerOptionsList, this); + } + + /** + * <p> + * Updates a marker on this map. Does nothing if the marker isn't already added. + * </p> + * + * @param updatedMarker An updated marker object. + */ + @UiThread + public void updateMarker(@NonNull Marker updatedMarker) { + annotationManager.updateMarker(updatedMarker, this); + } + + /** + * Adds a polyline to this map. + * + * @param polylineOptions A polyline options object that defines how to render the polyline. + * @return The {@code Polyine} that was added to the map. + */ + @UiThread + @NonNull + public Polyline addPolyline(@NonNull PolylineOptions polylineOptions) { + return annotationManager.addPolyline(polylineOptions, this); + } + + /** + * Adds multiple polylines to this map. + * + * @param polylineOptionsList A list of polyline options objects that defines how to render the polylines. + * @return A list of the {@code Polyline}s that were added to the map. + */ + @UiThread + @NonNull + public List<Polyline> addPolylines(@NonNull List<PolylineOptions> polylineOptionsList) { + return annotationManager.addPolylines(polylineOptionsList, this); + } + + /** + * Update a polyline on this map. + * + * @param polyline An updated polyline object. + */ + @UiThread + public void updatePolyline(Polyline polyline) { + annotationManager.updatePolyline(polyline); + } + + /** + * Adds a polygon to this map. + * + * @param polygonOptions A polygon options object that defines how to render the polygon. + * @return The {@code Polygon} that was added to the map. + */ + @UiThread + @NonNull + public Polygon addPolygon(@NonNull PolygonOptions polygonOptions) { + return annotationManager.addPolygon(polygonOptions, this); + } + + /** + * Adds multiple polygons to this map. + * + * @param polygonOptionsList A list of polygon options objects that defines how to render the polygons. + * @return A list of the {@code Polygon}s that were added to the map. + */ + @UiThread + @NonNull + public List<Polygon> addPolygons(@NonNull List<PolygonOptions> polygonOptionsList) { + return annotationManager.addPolygons(polygonOptionsList, this); + } + + + /** + * Update a polygon on this map. + * + * @param polygon An updated polygon object. + */ + @UiThread + public void updatePolygon(Polygon polygon) { + annotationManager.updatePolygon(polygon); + } + + /** + * <p> + * Convenience method for removing a Marker from the map. + * </p> + * Calls removeAnnotation() internally + * + * @param marker Marker to remove + */ + @UiThread + public void removeMarker(@NonNull Marker marker) { + annotationManager.removeAnnotation(marker); + } + + /** + * <p> + * Convenience method for removing a Polyline from the map. + * </p> + * Calls removeAnnotation() internally + * + * @param polyline Polyline to remove + */ + @UiThread + public void removePolyline(@NonNull Polyline polyline) { + annotationManager.removeAnnotation(polyline); + } + + /** + * <p> + * Convenience method for removing a Polygon from the map. + * </p> + * Calls removeAnnotation() internally + * + * @param polygon Polygon to remove + */ + @UiThread + public void removePolygon(@NonNull Polygon polygon) { + annotationManager.removeAnnotation(polygon); + } + + /** + * Removes an annotation from the map. + * + * @param annotation The annotation object to remove. + */ + @UiThread + public void removeAnnotation(@NonNull Annotation annotation) { + annotationManager.removeAnnotation(annotation); + } + + /** + * Removes an annotation from the map + * + * @param id The identifier associated to the annotation to be removed + */ + @UiThread + public void removeAnnotation(long id) { + annotationManager.removeAnnotation(id); + } + + /** + * Removes multiple annotations from the map. + * + * @param annotationList A list of annotation objects to remove. + */ + @UiThread + public void removeAnnotations(@NonNull List<? extends Annotation> annotationList) { + annotationManager.removeAnnotations(annotationList); + } + + /** + * Removes all annotations from the map. + */ + @UiThread + public void removeAnnotations() { + annotationManager.removeAnnotations(); + } + + /** + * Removes all markers, polylines, polygons, overlays, etc from the map. + */ + @UiThread + public void clear() { + annotationManager.removeAnnotations(); + } + + /** + * Return a annotation based on its id. + * + * @param id the id used to look up an annotation + * @return An annotation with a matched id, null is returned if no match was found + */ + @Nullable + public Annotation getAnnotation(long id) { + return annotationManager.getAnnotation(id); + } + + /** + * Returns a list of all the annotations on the map. + * + * @return A list of all the annotation objects. The returned object is a copy so modifying this + * list will not update the map + */ + @NonNull + public List<Annotation> getAnnotations() { + return annotationManager.getAnnotations(); + } + + /** + * Returns a list of all the markers on the map. + * + * @return A list of all the markers objects. The returned object is a copy so modifying this + * list will not update the map. + */ + @NonNull + public List<Marker> getMarkers() { + return annotationManager.getMarkers(); + } + + /** + * Returns a list of all the polygons on the map. + * + * @return A list of all the polygon objects. The returned object is a copy so modifying this + * list will not update the map. + */ + @NonNull + public List<Polygon> getPolygons() { + return annotationManager.getPolygons(); + } + + /** + * Returns a list of all the polylines on the map. + * + * @return A list of all the polylines objects. The returned object is a copy so modifying this + * list will not update the map. + */ + @NonNull + public List<Polyline> getPolylines() { + return annotationManager.getPolylines(); + } + + /** + * Sets a callback that's invoked when the user clicks on a marker. + * + * @param listener The callback that's invoked when the user clicks on a marker. + * To unset the callback, use null. + */ + @UiThread + public void setOnMarkerClickListener(@Nullable OnMarkerClickListener listener) { + annotationManager.setOnMarkerClickListener(listener); + } + + /** + * <p> + * Selects a marker. The selected marker will have it's info window opened. + * Any other open info windows will be closed unless isAllowConcurrentMultipleOpenInfoWindows() + * is true. + * </p> + * Selecting an already selected marker will have no effect. + * + * @param marker The marker to select. + */ + @UiThread + public void selectMarker(@NonNull Marker marker) { + if (marker == null) { + Timber.w("marker was null, so just returning"); + return; + } + annotationManager.selectMarker(marker); + } + + /** + * Deselects any currently selected marker. All markers will have it's info window closed. + */ + @UiThread + public void deselectMarkers() { + annotationManager.deselectMarkers(); + } + + /** + * Deselects a currently selected marker. The selected marker will have it's info window closed. + * + * @param marker the marker to deselect + */ + @UiThread + public void deselectMarker(@NonNull Marker marker) { + annotationManager.deselectMarker(marker); + } + + /** + * Gets the currently selected marker. + * + * @return The currently selected marker. + */ + @UiThread + public List<Marker> getSelectedMarkers() { + return annotationManager.getSelectedMarkers(); + } + + /** + * Get the MarkerViewManager associated to the MapView. + * + * @return the associated MarkerViewManager + */ + public MarkerViewManager getMarkerViewManager() { + return annotationManager.getMarkerViewManager(); + } + + // + // InfoWindow + // + + /** + * <p> + * Sets a custom renderer for the contents of info window. + * </p> + * When set your callback is invoked when an info window is about to be shown. By returning + * a custom {@link View}, the default info window will be replaced. + * + * @param infoWindowAdapter The callback to be invoked when an info window will be shown. + * To unset the callback, use null. + */ + @UiThread + public void setInfoWindowAdapter(@Nullable InfoWindowAdapter infoWindowAdapter) { + annotationManager.getInfoWindowManager().setInfoWindowAdapter(infoWindowAdapter); + } + + /** + * Gets the callback to be invoked when an info window will be shown. + * + * @return The callback to be invoked when an info window will be shown. + */ + @UiThread + @Nullable + public InfoWindowAdapter getInfoWindowAdapter() { + return annotationManager.getInfoWindowManager().getInfoWindowAdapter(); + } + + /** + * Changes whether the map allows concurrent multiple infowindows to be shown. + * + * @param allow If true, map allows concurrent multiple infowindows to be shown. + */ + @UiThread + public void setAllowConcurrentMultipleOpenInfoWindows(boolean allow) { + annotationManager.getInfoWindowManager().setAllowConcurrentMultipleOpenInfoWindows(allow); + } + + /** + * Returns whether the map allows concurrent multiple infowindows to be shown. + * + * @return If true, map allows concurrent multiple infowindows to be shown. + */ + @UiThread + public boolean isAllowConcurrentMultipleOpenInfoWindows() { + return annotationManager.getInfoWindowManager().isAllowConcurrentMultipleOpenInfoWindows(); + } + + // Internal API + List<InfoWindow> getInfoWindows() { + return annotationManager.getInfoWindowManager().getInfoWindows(); + } + + AnnotationManager getAnnotationManager() { + return annotationManager; + } + + Transform getTransform() { + return transform; + } + + + // + // Padding + // + + /** + * <p> + * Sets the distance from the edges of the map view’s frame to the edges of the map + * view’s logical viewport. + * </p> + * <p> + * When the value of this property is equal to {0,0,0,0}, viewport + * properties such as `centerCoordinate` assume a viewport that matches the map + * view’s frame. Otherwise, those properties are inset, excluding part of the + * frame from the viewport. For instance, if the only the top edge is inset, the + * map center is effectively shifted downward. + * </p> + * + * @param left The left margin in pixels. + * @param top The top margin in pixels. + * @param right The right margin in pixels. + * @param bottom The bottom margin in pixels. + */ + public void setPadding(int left, int top, int right, int bottom) { + projection.setContentPadding(new int[] {left, top, right, bottom}, myLocationViewSettings.getPadding()); + uiSettings.invalidate(); + } + + /** + * Returns the current configured content padding on map view. + * + * @return An array with length 4 in the LTRB order. + */ + public int[] getPadding() { + return projection.getContentPadding(); + } + + // + // Map events + // + + /** + * Sets a callback that's invoked on every change in camera position. + * + * @param listener The callback that's invoked on every camera change position. + * To unset the callback, use null. + */ + @UiThread + public void setOnCameraChangeListener(@Nullable OnCameraChangeListener listener) { + transform.setOnCameraChangeListener(listener); + } + + /** + * Sets a callback that's invoked on every frame rendered to the map view. + * + * @param listener The callback that's invoked on every frame rendered to the map view. + * To unset the callback, use null. + */ + @UiThread + public void setOnFpsChangedListener(@Nullable OnFpsChangedListener listener) { + onFpsChangedListener = listener; + } + + // used by MapView + OnFpsChangedListener getOnFpsChangedListener() { + return onFpsChangedListener; + } + + /** + * Sets a callback that's invoked when the map is scrolled. + * + * @param listener The callback that's invoked when the map is scrolled. + * To unset the callback, use null. + */ + @UiThread + public void setOnScrollListener(@Nullable OnScrollListener listener) { + onRegisterTouchListener.onRegisterScrollListener(listener); + } + + /** + * Sets a callback that's invoked when the map is flinged. + * + * @param listener The callback that's invoked when the map is flinged. + * To unset the callback, use null. + */ + @UiThread + public void setOnFlingListener(@Nullable OnFlingListener listener) { + onRegisterTouchListener.onRegisterFlingListener(listener); + } + + /** + * Sets a callback that's invoked when the user clicks on the map view. + * + * @param listener The callback that's invoked when the user clicks on the map view. + * To unset the callback, use null. + */ + @UiThread + public void setOnMapClickListener(@Nullable OnMapClickListener listener) { + onRegisterTouchListener.onRegisterMapClickListener(listener); + } + + /** + * Sets a callback that's invoked when the user long clicks on the map view. + * + * @param listener The callback that's invoked when the user long clicks on the map view. + * To unset the callback, use null. + */ + @UiThread + public void setOnMapLongClickListener(@Nullable OnMapLongClickListener listener) { + onRegisterTouchListener.onRegisterMapLongClickListener(listener); + } + + /** + * Sets a callback that's invoked when the user clicks on an info window. + * + * @param listener The callback that's invoked when the user clicks on an info window. + * To unset the callback, use null. + */ + @UiThread + public void setOnInfoWindowClickListener(@Nullable OnInfoWindowClickListener listener) { + getAnnotationManager().getInfoWindowManager().setOnInfoWindowClickListener(listener); + } + + /** + * Return the InfoWindow click listener + * + * @return Current active InfoWindow Click Listener + */ + @UiThread + public OnInfoWindowClickListener getOnInfoWindowClickListener() { + return getAnnotationManager().getInfoWindowManager().getOnInfoWindowClickListener(); + } + + /** + * Sets a callback that's invoked when a marker's info window is long pressed. + * + * @param listener The callback that's invoked when a marker's info window is long pressed. To unset the callback, + * use null. + */ + @UiThread + public void setOnInfoWindowLongClickListener(@Nullable OnInfoWindowLongClickListener + listener) { + getAnnotationManager().getInfoWindowManager().setOnInfoWindowLongClickListener(listener); + } + + /** + * Return the InfoWindow long click listener + * + * @return Current active InfoWindow long Click Listener + */ + public OnInfoWindowLongClickListener getOnInfoWindowLongClickListener() { + return getAnnotationManager().getInfoWindowManager().getOnInfoWindowLongClickListener(); + } + + public void setOnInfoWindowCloseListener(@Nullable OnInfoWindowCloseListener listener) { + getAnnotationManager().getInfoWindowManager().setOnInfoWindowCloseListener(listener); + } + + /** + * Return the InfoWindow close listener + * + * @return Current active InfoWindow Close Listener + */ + @UiThread + public OnInfoWindowCloseListener getOnInfoWindowCloseListener() { + return getAnnotationManager().getInfoWindowManager().getOnInfoWindowCloseListener(); + } + + // + // User location + // + + /** + * Returns the status of the my-location layer. + * + * @return True if the my-location layer is enabled, false otherwise. + */ + @UiThread + public boolean isMyLocationEnabled() { + return trackingSettings.isMyLocationEnabled(); + } + + /** + * Enables or disables the my-location layer. + * While enabled, the my-location layer continuously draws an indication of a user's current + * location and bearing. + * <p> + * In order to use the my-location layer feature you need to request permission for either + * {@code ACCESS_COARSE_LOCATION} or {@code ACCESS_FINE_LOCATION}. + * </p> + * + * @param enabled True to enable; false to disable. + */ + @UiThread + public void setMyLocationEnabled(boolean enabled) { + trackingSettings.setMyLocationEnabled(enabled); + } + + /** + * Returns the currently displayed user location, or null if there is no location data available. + * + * @return The currently displayed user location. + */ + @UiThread + @Nullable + public Location getMyLocation() { + return trackingSettings.getMyLocation(); + } + + /** + * Sets a callback that's invoked when the the My Location view + * (which signifies the user's location) changes location. + * + * @param listener The callback that's invoked when the user clicks on a marker. + * To unset the callback, use null. + */ + @UiThread + public void setOnMyLocationChangeListener(@Nullable MapboxMap.OnMyLocationChangeListener + listener) { + trackingSettings.setOnMyLocationChangeListener(listener); + } + + /** + * Sets a callback that's invoked when the location tracking mode changes. + * + * @param listener The callback that's invoked when the location tracking mode changes. + * To unset the callback, use null. + */ + @UiThread + public void setOnMyLocationTrackingModeChangeListener( + @Nullable MapboxMap.OnMyLocationTrackingModeChangeListener listener) { + trackingSettings.setOnMyLocationTrackingModeChangeListener(listener); + } + + /** + * Sets a callback that's invoked when the bearing tracking mode changes. + * + * @param listener The callback that's invoked when the bearing tracking mode changes. + * To unset the callback, use null. + */ + @UiThread + public void setOnMyBearingTrackingModeChangeListener(@Nullable OnMyBearingTrackingModeChangeListener listener) { + trackingSettings.setOnMyBearingTrackingModeChangeListener(listener); + } + + // + // Invalidate + // + + /** + * Takes a snapshot of the map. + * + * @param callback Callback method invoked when the snapshot is taken. + * @param bitmap A pre-allocated bitmap. + */ + @UiThread + public void snapshot(@NonNull SnapshotReadyCallback callback, @Nullable final Bitmap bitmap) { + // FIXME 12/02/2016 + //mapView.snapshot(callback, bitmap); + } + + /** + * Takes a snapshot of the map. + * + * @param callback Callback method invoked when the snapshot is taken. + */ + @UiThread + public void snapshot(@NonNull SnapshotReadyCallback callback) { + // FIXME 12/02/2016 + //mapView.snapshot(callback, null); + } + + /** + * Queries the map for rendered features + * + * @param coordinates the point to query + * @param layerIds optionally - only query these layers + * @return the list of feature + */ + @UiThread + @NonNull + public List<Feature> queryRenderedFeatures(@NonNull PointF coordinates, @Nullable String... + layerIds) { + return nativeMapView.queryRenderedFeatures(coordinates, layerIds); + } + + /** + * Queries the map for rendered features + * + * @param coordinates the box to query + * @param layerIds optionally - only query these layers + * @return the list of feature + */ + @UiThread + @NonNull + public List<Feature> queryRenderedFeatures(@NonNull RectF coordinates, @Nullable String... + layerIds) { + return nativeMapView.queryRenderedFeatures(coordinates, layerIds); + } + + // + // Interfaces + // + + /** + * Interface definition for a callback to be invoked when the map is flinged. + * + * @see MapboxMap#setOnFlingListener(OnFlingListener) + */ + public interface OnFlingListener { + /** + * Called when the map is flinged. + */ + void onFling(); + } + + /** + * Interface definition for a callback to be invoked when the map is scrolled. + * + * @see MapboxMap#setOnScrollListener(OnScrollListener) + */ + public interface OnScrollListener { + /** + * Called when the map is scrolled. + */ + void onScroll(); + } + + /** + * Interface definition for a callback to be invoked when the camera changes position. + */ + public interface OnCameraChangeListener { + /** + * Called after the camera position has changed. During an animation, + * this listener may not be notified of intermediate camera positions. + * It is always called for the final position in the animation. + * + * @param position The CameraPosition at the end of the last camera change. + */ + void onCameraChange(CameraPosition position); + } + + /** + * Interface definition for a callback to be invoked when a frame is rendered to the map view. + * + * @see MapboxMap#setOnFpsChangedListener(OnFpsChangedListener) + */ + public interface OnFpsChangedListener { + /** + * Called for every frame rendered to the map view. + * + * @param fps The average number of frames rendered over the last second. + */ + void onFpsChanged(double fps); + } + + /** + * Interface definition for a callback to be invoked when a user registers an listener that is + * related to touch and click events. + */ + interface OnRegisterTouchListener { + void onRegisterMapClickListener(OnMapClickListener listener); + + void onRegisterMapLongClickListener(OnMapLongClickListener listener); + + void onRegisterScrollListener(OnScrollListener listener); + void onRegisterFlingListener(OnFlingListener listener); + } + /** + * Interface definition for a callback to be invoked when the user clicks on the map view. + * + * @see MapboxMap#setOnMapClickListener(OnMapClickListener) + */ + public interface OnMapClickListener { /** - * <p> - * Adds a marker to this map. - * </p> - * The marker's icon is rendered on the map at the location {@code Marker.position}. - * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet. + * Called when the user clicks on the map view. * - * @param markerOptions A marker options object that defines how to render the marker. - * @param onMarkerViewAddedListener Callback invoked when the View has been added to the map. - * @return The {@code Marker} that was added to the map. + * @param point The projected map coordinate the user clicked on. */ - @UiThread - @NonNull - public MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions, final MarkerViewManager.OnMarkerViewAddedListener onMarkerViewAddedListener) { - return annotationManager.addMarker(markerOptions, this, onMarkerViewAddedListener); - } - - @UiThread - @NonNull - public List<MarkerView> addMarkerViews(@NonNull List<? extends - BaseMarkerViewOptions> markerViewOptions) { - return annotationManager.addMarkerViews(markerViewOptions, this); - } - - @UiThread - @NonNull - public List<MarkerView> getMarkerViewsInRect(@NonNull RectF rect) { - return annotationManager.getMarkerViewsInRect(rect); - } + void onMapClick(@NonNull LatLng point); + } + /** + * Interface definition for a callback to be invoked when the user long clicks on the map view. + * + * @see MapboxMap#setOnMapLongClickListener(OnMapLongClickListener) + */ + public interface OnMapLongClickListener { /** - * <p> - * Adds multiple markers to this map. - * </p> - * The marker's icon is rendered on the map at the location {@code Marker.position}. - * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet. + * Called when the user long clicks on the map view. * - * @param markerOptionsList A list of marker options objects that defines how to render the markers. - * @return A list of the {@code Marker}s that were added to the map. + * @param point The projected map coordinate the user long clicked on. */ - @UiThread - @NonNull - public List<Marker> addMarkers(@NonNull List<? extends - BaseMarkerOptions> markerOptionsList) { - return annotationManager.addMarkers(markerOptionsList, this); - } + void onMapLongClick(@NonNull LatLng point); + } + /** + * Interface definition for a callback to be invoked when the user clicks on a marker. + * + * @see MapboxMap#setOnMarkerClickListener(OnMarkerClickListener) + */ + public interface OnMarkerClickListener { /** - * <p> - * Updates a marker on this map. Does nothing if the marker isn't already added. - * </p> + * Called when the user clicks on a marker. * - * @param updatedMarker An updated marker object. + * @param marker The marker the user clicked on. + * @return If true the listener has consumed the event and the info window will not be shown. */ - @UiThread - public void updateMarker(@NonNull Marker updatedMarker) { - annotationManager.updateMarker(updatedMarker, this); - } + boolean onMarkerClick(@NonNull Marker marker); + } + /** + * Interface definition for a callback to be invoked when the user clicks on an info window. + * + * @see MapboxMap#setOnInfoWindowClickListener(OnInfoWindowClickListener) + */ + public interface OnInfoWindowClickListener { /** - * Adds a polyline to this map. + * Called when the user clicks on an info window. * - * @param polylineOptions A polyline options object that defines how to render the polyline. - * @return The {@code Polyine} that was added to the map. + * @param marker The marker of the info window the user clicked on. + * @return If true the listener has consumed the event and the info window will not be closed. */ - @UiThread - @NonNull - public Polyline addPolyline(@NonNull PolylineOptions polylineOptions) { - return annotationManager.addPolyline(polylineOptions, this); - } + boolean onInfoWindowClick(@NonNull Marker marker); + } - /** - * Adds multiple polylines to this map. - * - * @param polylineOptionsList A list of polyline options objects that defines how to render the polylines. - * @return A list of the {@code Polyline}s that were added to the map. - */ - @UiThread - @NonNull - public List<Polyline> addPolylines(@NonNull List<PolylineOptions> polylineOptionsList) { - return annotationManager.addPolylines(polylineOptionsList, this); - } + /** + * Interface definition for a callback to be invoked when the user long presses on a marker's info window. + * + * @see MapboxMap#setOnInfoWindowClickListener(OnInfoWindowClickListener) + */ + public interface OnInfoWindowLongClickListener { /** - * Update a polyline on this map. + * Called when the user makes a long-press gesture on the marker's info window. * - * @param polyline An updated polyline object. + * @param marker The marker were the info window is attached to */ - @UiThread - public void updatePolyline(Polyline polyline) { - annotationManager.updatePolyline(polyline); - } + void onInfoWindowLongClick(Marker marker); + } - /** - * Adds a polygon to this map. - * - * @param polygonOptions A polygon options object that defines how to render the polygon. - * @return The {@code Polygon} that was added to the map. - */ - @UiThread - @NonNull - public Polygon addPolygon(@NonNull PolygonOptions polygonOptions) { - return annotationManager.addPolygon(polygonOptions, this); - } + /** + * Interface definition for a callback to be invoked when a marker's info window is closed. + * + * @see MapboxMap#setOnInfoWindowCloseListener(OnInfoWindowCloseListener) + */ + public interface OnInfoWindowCloseListener { /** - * Adds multiple polygons to this map. + * Called when the marker's info window is closed. * - * @param polygonOptionsList A list of polygon options objects that defines how to render the polygons. - * @return A list of the {@code Polygon}s that were added to the map. + * @param marker The marker of the info window that was closed. */ - @UiThread - @NonNull - public List<Polygon> addPolygons(@NonNull List<PolygonOptions> polygonOptionsList) { - return annotationManager.addPolygons(polygonOptionsList, this); - } - + void onInfoWindowClose(Marker marker); + } + /** + * Interface definition for a callback to be invoked when an info window will be shown. + * + * @see MapboxMap#setInfoWindowAdapter(InfoWindowAdapter) + */ + public interface InfoWindowAdapter { /** - * Update a polygon on this map. - * - * @param polygon An updated polygon object. - */ - @UiThread - public void updatePolygon(Polygon polygon) { - annotationManager.updatePolygon(polygon); - } - - /** - * <p> - * Convenience method for removing a Marker from the map. - * </p> - * Calls removeAnnotation() internally + * Called when an info window will be shown as a result of a marker click. * - * @param marker Marker to remove - */ - @UiThread - public void removeMarker(@NonNull Marker marker) { - annotationManager.removeAnnotation(marker); - } - - /** - * <p> - * Convenience method for removing a Polyline from the map. - * </p> - * Calls removeAnnotation() internally - * - * @param polyline Polyline to remove - */ - @UiThread - public void removePolyline(@NonNull Polyline polyline) { - annotationManager.removeAnnotation(polyline); - } - - /** - * <p> - * Convenience method for removing a Polygon from the map. - * </p> - * Calls removeAnnotation() internally - * - * @param polygon Polygon to remove - */ - @UiThread - public void removePolygon(@NonNull Polygon polygon) { - annotationManager.removeAnnotation(polygon); - } - - /** - * Removes an annotation from the map. - * - * @param annotation The annotation object to remove. - */ - @UiThread - public void removeAnnotation(@NonNull Annotation annotation) { - annotationManager.removeAnnotation(annotation); - } - - /** - * Removes an annotation from the map - * - * @param id The identifier associated to the annotation to be removed - */ - @UiThread - public void removeAnnotation(long id) { - annotationManager.removeAnnotation(id); - } - - /** - * Removes multiple annotations from the map. - * - * @param annotationList A list of annotation objects to remove. - */ - @UiThread - public void removeAnnotations(@NonNull List<? extends Annotation> annotationList) { - annotationManager.removeAnnotations(annotationList); - } - - /** - * Removes all annotations from the map. - */ - @UiThread - public void removeAnnotations() { - annotationManager.removeAnnotations(); - } - - /** - * Removes all markers, polylines, polygons, overlays, etc from the map. - */ - @UiThread - public void clear() { - annotationManager.removeAnnotations(); - } - - /** - * Return a annotation based on its id. - * - * @param id the id used to look up an annotation - * @return An annotation with a matched id, null is returned if no match was found + * @param marker The marker the user clicked on. + * @return View to be shown as a info window. If null is returned the default + * info window will be shown. */ @Nullable - public Annotation getAnnotation(long id) { - return annotationManager.getAnnotation(id); - } - - /** - * Returns a list of all the annotations on the map. - * - * @return A list of all the annotation objects. The returned object is a copy so modifying this - * list will not update the map - */ - @NonNull - public List<Annotation> getAnnotations() { - return annotationManager.getAnnotations(); - } - - /** - * Returns a list of all the markers on the map. - * - * @return A list of all the markers objects. The returned object is a copy so modifying this - * list will not update the map. - */ - @NonNull - public List<Marker> getMarkers() { - return annotationManager.getMarkers(); - } - - /** - * Returns a list of all the polygons on the map. - * - * @return A list of all the polygon objects. The returned object is a copy so modifying this - * list will not update the map. - */ - @NonNull - public List<Polygon> getPolygons() { - return annotationManager.getPolygons(); - } - - /** - * Returns a list of all the polylines on the map. - * - * @return A list of all the polylines objects. The returned object is a copy so modifying this - * list will not update the map. - */ - @NonNull - public List<Polyline> getPolylines() { - return annotationManager.getPolylines(); - } - - /** - * Sets a callback that's invoked when the user clicks on a marker. - * - * @param listener The callback that's invoked when the user clicks on a marker. - * To unset the callback, use null. - */ - @UiThread - public void setOnMarkerClickListener(@Nullable OnMarkerClickListener listener) { - annotationManager.setOnMarkerClickListener(listener); - } - - /** - * <p> - * Selects a marker. The selected marker will have it's info window opened. - * Any other open info windows will be closed unless isAllowConcurrentMultipleOpenInfoWindows() - * is true. - * </p> - * Selecting an already selected marker will have no effect. - * - * @param marker The marker to select. - */ - @UiThread - public void selectMarker(@NonNull Marker marker) { - if (marker == null) { - Timber.w("marker was null, so just returning"); - return; - } - annotationManager.selectMarker(marker); - } - - /** - * Deselects any currently selected marker. All markers will have it's info window closed. - */ - @UiThread - public void deselectMarkers() { - annotationManager.deselectMarkers(); - } + View getInfoWindow(@NonNull Marker marker); + } - /** - * Deselects a currently selected marker. The selected marker will have it's info window closed. - * - * @param marker the marker to deselect - */ - @UiThread - public void deselectMarker(@NonNull Marker marker) { - annotationManager.deselectMarker(marker); - } + /** + * Interface definition for a callback to be invoked when an MarkerView will be shown. + * + * @param <U> the instance type of MarkerView + */ + public abstract static class MarkerViewAdapter<U extends MarkerView> { - /** - * Gets the currently selected marker. - * - * @return The currently selected marker. - */ - @UiThread - public List<Marker> getSelectedMarkers() { - return annotationManager.getSelectedMarkers(); - } + private Context context; + private final Class<U> persistentClass; + private final Pools.SimplePool<View> viewReusePool; /** - * Get the MarkerViewManager associated to the MapView. - * - * @return the associated MarkerViewManager - */ - public MarkerViewManager getMarkerViewManager() { - return annotationManager.getMarkerViewManager(); - } - - // - // InfoWindow - // - - /** - * <p> - * Sets a custom renderer for the contents of info window. - * </p> - * When set your callback is invoked when an info window is about to be shown. By returning - * a custom {@link View}, the default info window will be replaced. + * Create an instance of MarkerViewAdapter. * - * @param infoWindowAdapter The callback to be invoked when an info window will be shown. - * To unset the callback, use null. + * @param context the context associated to a MapView */ - @UiThread - public void setInfoWindowAdapter(@Nullable InfoWindowAdapter infoWindowAdapter) { - annotationManager.getInfoWindowManager().setInfoWindowAdapter(infoWindowAdapter); + @SuppressWarnings("unchecked") + public MarkerViewAdapter(Context context) { + this.context = context; + persistentClass = (Class<U>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; + viewReusePool = new Pools.SimplePool<>(10000); } /** - * Gets the callback to be invoked when an info window will be shown. + * Called when an MarkerView will be added to the MapView. * - * @return The callback to be invoked when an info window will be shown. + * @param marker the model representing the MarkerView + * @param convertView the reusable view + * @param parent the parent ViewGroup of the convertview + * @return the View that is adapted to the contents of MarkerView */ - @UiThread @Nullable - public InfoWindowAdapter getInfoWindowAdapter() { - return annotationManager.getInfoWindowManager().getInfoWindowAdapter(); - } - - /** - * Changes whether the map allows concurrent multiple infowindows to be shown. - * - * @param allow If true, map allows concurrent multiple infowindows to be shown. - */ - @UiThread - public void setAllowConcurrentMultipleOpenInfoWindows(boolean allow) { - annotationManager.getInfoWindowManager().setAllowConcurrentMultipleOpenInfoWindows(allow); - } - - /** - * Returns whether the map allows concurrent multiple infowindows to be shown. - * - * @return If true, map allows concurrent multiple infowindows to be shown. - */ - @UiThread - public boolean isAllowConcurrentMultipleOpenInfoWindows() { - return annotationManager.getInfoWindowManager().isAllowConcurrentMultipleOpenInfoWindows(); - } - - // Internal API - List<InfoWindow> getInfoWindows() { - return annotationManager.getInfoWindowManager().getInfoWindows(); - } - - AnnotationManager getAnnotationManager() { - return annotationManager; - } - - Transform getTransform() { - return transform; - } - - - // - // Padding - // + public abstract View getView(@NonNull U marker, @Nullable View convertView, @NonNull ViewGroup parent); /** + * Called when an MarkerView is removed from the MapView or the View object is going to be reused. * <p> - * Sets the distance from the edges of the map view’s frame to the edges of the map - * view’s logical viewport. + * This method should be used to reset an animated view back to it's original state for view reuse. * </p> * <p> - * When the value of this property is equal to {0,0,0,0}, viewport - * properties such as `centerCoordinate` assume a viewport that matches the map - * view’s frame. Otherwise, those properties are inset, excluding part of the - * frame from the viewport. For instance, if the only the top edge is inset, the - * map center is effectively shifted downward. + * Returning true indicates you want to the view reuse to be handled automatically. + * Returning false indicates you want to perform an animation and you are required calling + * {@link #releaseView(View)} yourself. * </p> * - * @param left The left margin in pixels. - * @param top The top margin in pixels. - * @param right The right margin in pixels. - * @param bottom The bottom margin in pixels. + * @param marker the model representing the MarkerView + * @param convertView the reusable view + * @return true if you want reuse to occur automatically, false if you want to manage this yourself. */ - public void setPadding(int left, int top, int right, int bottom) { - projection.setContentPadding(new int[]{left, top, right, bottom}, myLocationViewSettings.getPadding()); - uiSettings.invalidate(); - } - - /** - * Returns the current configured content padding on map view. - * - * @return An array with length 4 in the LTRB order. - */ - public int[] getPadding() { - return projection.getContentPadding(); - } - - // - // Map events - // - - /** - * Sets a callback that's invoked on every change in camera position. - * - * @param listener The callback that's invoked on every camera change position. - * To unset the callback, use null. - */ - @UiThread - public void setOnCameraChangeListener(@Nullable OnCameraChangeListener listener) { - transform.setOnCameraChangeListener(listener); - } - - /** - * Sets a callback that's invoked on every frame rendered to the map view. - * - * @param listener The callback that's invoked on every frame rendered to the map view. - * To unset the callback, use null. - */ - @UiThread - public void setOnFpsChangedListener(@Nullable OnFpsChangedListener listener) { - onFpsChangedListener = listener; - } - - // used by MapView - OnFpsChangedListener getOnFpsChangedListener() { - return onFpsChangedListener; - } - - /** - * Sets a callback that's invoked when the map is scrolled. - * - * @param listener The callback that's invoked when the map is scrolled. - * To unset the callback, use null. - */ - @UiThread - public void setOnScrollListener(@Nullable OnScrollListener listener) { - onRegisterTouchListener.onRegisterScrollListener(listener); - } - - /** - * Sets a callback that's invoked when the map is flinged. - * - * @param listener The callback that's invoked when the map is flinged. - * To unset the callback, use null. - */ - @UiThread - public void setOnFlingListener(@Nullable OnFlingListener listener) { - onRegisterTouchListener.onRegisterFlingListener(listener); - } - - /** - * Sets a callback that's invoked when the user clicks on the map view. - * - * @param listener The callback that's invoked when the user clicks on the map view. - * To unset the callback, use null. - */ - @UiThread - public void setOnMapClickListener(@Nullable OnMapClickListener listener) { - onRegisterTouchListener.onRegisterMapClickListener(listener); - } - - /** - * Sets a callback that's invoked when the user long clicks on the map view. - * - * @param listener The callback that's invoked when the user long clicks on the map view. - * To unset the callback, use null. - */ - @UiThread - public void setOnMapLongClickListener(@Nullable OnMapLongClickListener listener) { - onRegisterTouchListener.onRegisterMapLongClickListener(listener); - } - - /** - * Sets a callback that's invoked when the user clicks on an info window. - * - * @param listener The callback that's invoked when the user clicks on an info window. - * To unset the callback, use null. - */ - @UiThread - public void setOnInfoWindowClickListener(@Nullable OnInfoWindowClickListener listener) { - getAnnotationManager().getInfoWindowManager().setOnInfoWindowClickListener(listener); - } - - /** - * Return the InfoWindow click listener - * - * @return Current active InfoWindow Click Listener - */ - @UiThread - public OnInfoWindowClickListener getOnInfoWindowClickListener() { - return getAnnotationManager().getInfoWindowManager().getOnInfoWindowClickListener(); - } - - /** - * Sets a callback that's invoked when a marker's info window is long pressed. - * - * @param listener The callback that's invoked when a marker's info window is long pressed. To unset the callback, - * use null. - */ - @UiThread - public void setOnInfoWindowLongClickListener(@Nullable OnInfoWindowLongClickListener - listener) { - getAnnotationManager().getInfoWindowManager().setOnInfoWindowLongClickListener(listener); - } - - /** - * Return the InfoWindow long click listener - * - * @return Current active InfoWindow long Click Listener - */ - public OnInfoWindowLongClickListener getOnInfoWindowLongClickListener() { - return getAnnotationManager().getInfoWindowManager().getOnInfoWindowLongClickListener(); - } - - public void setOnInfoWindowCloseListener(@Nullable OnInfoWindowCloseListener listener) { - getAnnotationManager().getInfoWindowManager().setOnInfoWindowCloseListener(listener); - } - - /** - * Return the InfoWindow close listener - * - * @return Current active InfoWindow Close Listener - */ - @UiThread - public OnInfoWindowCloseListener getOnInfoWindowCloseListener() { - return getAnnotationManager().getInfoWindowManager().getOnInfoWindowCloseListener(); - } - - // - // User location - // - - /** - * Returns the status of the my-location layer. - * - * @return True if the my-location layer is enabled, false otherwise. - */ - @UiThread - public boolean isMyLocationEnabled() { - return trackingSettings.isMyLocationEnabled(); + public boolean prepareViewForReuse(@NonNull MarkerView marker, @NonNull View convertView) { + return true; } /** + * Called when a MarkerView is selected from the MapView. * <p> - * Enables or disables the my-location layer. - * While enabled, the my-location layer continuously draws an indication of a user's current - * location and bearing. + * Returning true from this method indicates you want to move the MarkerView to the selected state. + * Returning false indicates you want to animate the View first an manually select the MarkerView when appropriate. * </p> - * In order to use the my-location layer feature you need to request permission for either - * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} - * or @link android.Manifest.permission#ACCESS_FINE_LOCATION. * - * @param enabled True to enable; false to disable. + * @param marker the model representing the MarkerView + * @param convertView the reusable view + * @param reselectionFromRecycling indicates if the onSelect callback is the initial selection + * callback or that selection occurs due to recreation of selected marker + * @return true if you want to select the Marker immediately, false if you want to manage this yourself. */ - @UiThread - public void setMyLocationEnabled(boolean enabled) { - trackingSettings.setMyLocationEnabled(enabled); + public boolean onSelect(@NonNull U marker, @NonNull View convertView, boolean reselectionFromRecycling) { + return true; } /** - * Returns the currently displayed user location, or null if there is no location data available. + * Called when a MarkerView is deselected from the MapView. * - * @return The currently displayed user location. + * @param marker the model representing the MarkerView + * @param convertView the reusable view */ - @UiThread - @Nullable - public Location getMyLocation() { - return trackingSettings.getMyLocation(); + public void onDeselect(@NonNull U marker, @NonNull View convertView) { } /** - * Sets a callback that's invoked when the the My Location view - * (which signifies the user's location) changes location. + * Returns the generic type of the used MarkerView. * - * @param listener The callback that's invoked when the user clicks on a marker. - * To unset the callback, use null. + * @return the generic type */ - @UiThread - public void setOnMyLocationChangeListener(@Nullable MapboxMap.OnMyLocationChangeListener - listener) { - trackingSettings.setOnMyLocationChangeListener(listener); + public final Class<U> getMarkerClass() { + return persistentClass; } /** - * Sets a callback that's invoked when the location tracking mode changes. + * Returns the pool used to store reusable Views. * - * @param listener The callback that's invoked when the location tracking mode changes. - * To unset the callback, use null. + * @return the pool associated to this adapter */ - @UiThread - public void setOnMyLocationTrackingModeChangeListener(@Nullable MapboxMap.OnMyLocationTrackingModeChangeListener listener) { - trackingSettings.setOnMyLocationTrackingModeChangeListener(listener); + public final Pools.SimplePool<View> getViewReusePool() { + return viewReusePool; } /** - * Sets a callback that's invoked when the bearing tracking mode changes. + * Returns the context associated to the hosting MapView. * - * @param listener The callback that's invoked when the bearing tracking mode changes. - * To unset the callback, use null. + * @return the context used */ - @UiThread - public void setOnMyBearingTrackingModeChangeListener(@Nullable OnMyBearingTrackingModeChangeListener listener) { - trackingSettings.setOnMyBearingTrackingModeChangeListener(listener); + public final Context getContext() { + return context; } - // - // Invalidate - // - /** - * Takes a snapshot of the map. + * Release a View to the ViewPool. * - * @param callback Callback method invoked when the snapshot is taken. - * @param bitmap A pre-allocated bitmap. + * @param view the view to be released */ - @UiThread - public void snapshot(@NonNull SnapshotReadyCallback callback, @Nullable final Bitmap bitmap) { - // FIXME 12/02/2016 - //mapView.snapshot(callback, bitmap); + public final void releaseView(View view) { + view.setVisibility(View.GONE); + viewReusePool.release(view); } + } - /** - * Takes a snapshot of the map. - * - * @param callback Callback method invoked when the snapshot is taken. - */ - @UiThread - public void snapshot(@NonNull SnapshotReadyCallback callback) { - // FIXME 12/02/2016 - //mapView.snapshot(callback, null); - } + /** + * Interface definition for a callback to be invoked when the user clicks on a MarkerView. + */ + public interface OnMarkerViewClickListener { /** - * Queries the map for rendered features + * Called when the user clicks on a MarkerView. * - * @param coordinates the point to query - * @param layerIds optionally - only query these layers - * @return the list of feature + * @param marker the MarkerView associated to the clicked View + * @param view the clicked View + * @param adapter the adapter used to adapt the MarkerView to the View + * @return If true the listener has consumed the event and the info window will not be shown */ - @UiThread - @NonNull - public List<Feature> queryRenderedFeatures(@NonNull PointF coordinates, @Nullable String... - layerIds) { - return nativeMapView.queryRenderedFeatures(coordinates, layerIds); - } - - /** - * Queries the map for rendered features - * - * @param coordinates the box to query - * @param layerIds optionally - only query these layers - * @return the list of feature - */ - @UiThread - @NonNull - public List<Feature> queryRenderedFeatures(@NonNull RectF coordinates, @Nullable String... - layerIds) { - return nativeMapView.queryRenderedFeatures(coordinates, layerIds); - } - - // - // Interfaces - // - - /** - * Interface definition for a callback to be invoked when the map is flinged. - * - * @see MapboxMap#setOnFlingListener(OnFlingListener) - */ - public interface OnFlingListener { - /** - * Called when the map is flinged. - */ - void onFling(); - } - - /** - * Interface definition for a callback to be invoked when the map is scrolled. - * - * @see MapboxMap#setOnScrollListener(OnScrollListener) - */ - public interface OnScrollListener { - /** - * Called when the map is scrolled. - */ - void onScroll(); - } - - /** - * Interface definition for a callback to be invoked when the camera changes position. - */ - public interface OnCameraChangeListener { - /** - * Called after the camera position has changed. During an animation, - * this listener may not be notified of intermediate camera positions. - * It is always called for the final position in the animation. - * - * @param position The CameraPosition at the end of the last camera change. - */ - void onCameraChange(CameraPosition position); - } - - /** - * Interface definition for a callback to be invoked when a frame is rendered to the map view. - * - * @see MapboxMap#setOnFpsChangedListener(OnFpsChangedListener) - */ - public interface OnFpsChangedListener { - /** - * Called for every frame rendered to the map view. - * - * @param fps The average number of frames rendered over the last second. - */ - void onFpsChanged(double fps); - } - - /** - * Interface definition for a callback to be invoked when a user registers an listener that is - * related to touch and click events. - */ - interface OnRegisterTouchListener { - void onRegisterMapClickListener(OnMapClickListener listener); - - void onRegisterMapLongClickListener(OnMapLongClickListener listener); - - void onRegisterScrollListener(OnScrollListener listener); - - void onRegisterFlingListener(OnFlingListener listener); - } - - /** - * Interface definition for a callback to be invoked when the user clicks on the map view. - * - * @see MapboxMap#setOnMapClickListener(OnMapClickListener) - */ - public interface OnMapClickListener { - /** - * Called when the user clicks on the map view. - * - * @param point The projected map coordinate the user clicked on. - */ - void onMapClick(@NonNull LatLng point); - } + boolean onMarkerClick(@NonNull Marker marker, @NonNull View view, @NonNull MarkerViewAdapter adapter); + } + /** + * Interface definition for a callback to be invoked when the the My Location view changes location. + * + * @see MapboxMap#setOnMyLocationChangeListener(OnMyLocationChangeListener) + */ + public interface OnMyLocationChangeListener { /** - * Interface definition for a callback to be invoked when the user long clicks on the map view. + * Called when the location of the My Location view has changed + * (be it latitude/longitude, bearing or accuracy). * - * @see MapboxMap#setOnMapLongClickListener(OnMapLongClickListener) + * @param location The current location of the My Location view The type of map change event. */ - public interface OnMapLongClickListener { - /** - * Called when the user long clicks on the map view. - * - * @param point The projected map coordinate the user long clicked on. - */ - void onMapLongClick(@NonNull LatLng point); - } + void onMyLocationChange(@Nullable Location location); + } - /** - * Interface definition for a callback to be invoked when the user clicks on a marker. - * - * @see MapboxMap#setOnMarkerClickListener(OnMarkerClickListener) - */ - public interface OnMarkerClickListener { - /** - * Called when the user clicks on a marker. - * - * @param marker The marker the user clicked on. - * @return If true the listener has consumed the event and the info window will not be shown. - */ - boolean onMarkerClick(@NonNull Marker marker); - } + /** + * Interface definition for a callback to be invoked when the the My Location tracking mode changes. + * + * @see TrackingSettings#setMyLocationTrackingMode(int) + */ + public interface OnMyLocationTrackingModeChangeListener { /** - * Interface definition for a callback to be invoked when the user clicks on an info window. + * Called when the tracking mode of My Location tracking has changed * - * @see MapboxMap#setOnInfoWindowClickListener(OnInfoWindowClickListener) + * @param myLocationTrackingMode the current active location tracking mode */ - public interface OnInfoWindowClickListener { - /** - * Called when the user clicks on an info window. - * - * @param marker The marker of the info window the user clicked on. - * @return If true the listener has consumed the event and the info window will not be closed. - */ - boolean onInfoWindowClick(@NonNull Marker marker); - } + void onMyLocationTrackingModeChange(@MyLocationTracking.Mode int myLocationTrackingMode); + } - /** - * Interface definition for a callback to be invoked when the user long presses on a marker's info window. - * - * @see MapboxMap#setOnInfoWindowClickListener(OnInfoWindowClickListener) - */ - public interface OnInfoWindowLongClickListener { - - /** - * Called when the user makes a long-press gesture on the marker's info window. - * - * @param marker The marker were the info window is attached to - */ - void onInfoWindowLongClick(Marker marker); - } - - /** - * Interface definition for a callback to be invoked when a marker's info window is closed. - * - * @see MapboxMap#setOnInfoWindowCloseListener(OnInfoWindowCloseListener) - */ - public interface OnInfoWindowCloseListener { - - /** - * Called when the marker's info window is closed. - * - * @param marker The marker of the info window that was closed. - */ - void onInfoWindowClose(Marker marker); - } - - /** - * Interface definition for a callback to be invoked when an info window will be shown. - * - * @see MapboxMap#setInfoWindowAdapter(InfoWindowAdapter) - */ - public interface InfoWindowAdapter { - /** - * Called when an info window will be shown as a result of a marker click. - * - * @param marker The marker the user clicked on. - * @return View to be shown as a info window. If null is returned the default - * info window will be shown. - */ - @Nullable - View getInfoWindow(@NonNull Marker marker); - } + /** + * Interface definition for a callback to be invoked when the the My Location tracking mode changes. + * + * @see TrackingSettings#setMyLocationTrackingMode(int) + */ + public interface OnMyBearingTrackingModeChangeListener { /** - * Interface definition for a callback to be invoked when an MarkerView will be shown. + * Called when the tracking mode of My Bearing tracking has changed * - * @param <U> the instance type of MarkerView - */ - public abstract static class MarkerViewAdapter<U extends MarkerView> { - - private Context context; - private final Class<U> persistentClass; - private final Pools.SimplePool<View> viewReusePool; - - /** - * Create an instance of MarkerViewAdapter. - * - * @param context the context associated to a MapView - */ - @SuppressWarnings("unchecked") - public MarkerViewAdapter(Context context) { - this.context = context; - persistentClass = (Class<U>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; - viewReusePool = new Pools.SimplePool<>(10000); - } - - /** - * Called when an MarkerView will be added to the MapView. - * - * @param marker the model representing the MarkerView - * @param convertView the reusable view - * @param parent the parent ViewGroup of the convertview - * @return the View that is adapted to the contents of MarkerView - */ - @Nullable - public abstract View getView(@NonNull U marker, @Nullable View convertView, @NonNull ViewGroup parent); - - /** - * Called when an MarkerView is removed from the MapView or the View object is going to be reused. - * <p> - * This method should be used to reset an animated view back to it's original state for view reuse. - * </p> - * <p> - * Returning true indicates you want to the view reuse to be handled automatically. - * Returning false indicates you want to perform an animation and you are required calling {@link #releaseView(View)} yourself. - * </p> - * - * @param marker the model representing the MarkerView - * @param convertView the reusable view - * @return true if you want reuse to occur automatically, false if you want to manage this yourself. - */ - public boolean prepareViewForReuse(@NonNull MarkerView marker, @NonNull View convertView) { - return true; - } - - /** - * Called when a MarkerView is selected from the MapView. - * <p> - * Returning true from this method indicates you want to move the MarkerView to the selected state. - * Returning false indicates you want to animate the View first an manually select the MarkerView when appropriate. - * </p> - * - * @param marker the model representing the MarkerView - * @param convertView the reusable view - * @param reselectionFromRecycling indicates if the onSelect callback is the initial selection - * callback or that selection occurs due to recreation of selected marker - * @return true if you want to select the Marker immediately, false if you want to manage this yourself. - */ - public boolean onSelect(@NonNull U marker, @NonNull View convertView, boolean reselectionFromRecycling) { - return true; - } - - /** - * Called when a MarkerView is deselected from the MapView. - * - * @param marker the model representing the MarkerView - * @param convertView the reusable view - */ - public void onDeselect(@NonNull U marker, @NonNull View convertView) { - } - - /** - * Returns the generic type of the used MarkerView. - * - * @return the generic type - */ - public final Class<U> getMarkerClass() { - return persistentClass; - } - - /** - * Returns the pool used to store reusable Views. - * - * @return the pool associated to this adapter - */ - public final Pools.SimplePool<View> getViewReusePool() { - return viewReusePool; - } - - /** - * Returns the context associated to the hosting MapView. - * - * @return the context used - */ - public final Context getContext() { - return context; - } - - /** - * Release a View to the ViewPool. - * - * @param view the view to be released - */ - public final void releaseView(View view) { - view.setVisibility(View.GONE); - viewReusePool.release(view); - } - } - - /** - * Interface definition for a callback to be invoked when the user clicks on a MarkerView. + * @param myBearingTrackingMode the current active bearing tracking mode */ - public interface OnMarkerViewClickListener { - - /** - * Called when the user clicks on a MarkerView. - * - * @param marker the MarkerView associated to the clicked View - * @param view the clicked View - * @param adapter the adapter used to adapt the MarkerView to the View - * @return If true the listener has consumed the event and the info window will not be shown - */ - boolean onMarkerClick(@NonNull Marker marker, @NonNull View view, @NonNull MarkerViewAdapter adapter); - } + void onMyBearingTrackingModeChange(@MyBearingTracking.Mode int myBearingTrackingMode); + } + /** + * Interface definition for a callback to be invoked when a task is complete or cancelled. + */ + public interface CancelableCallback { /** - * Interface definition for a callback to be invoked when the the My Location view changes location. - * - * @see MapboxMap#setOnMyLocationChangeListener(OnMyLocationChangeListener) + * Invoked when a task is cancelled. */ - public interface OnMyLocationChangeListener { - /** - * Called when the location of the My Location view has changed - * (be it latitude/longitude, bearing or accuracy). - * - * @param location The current location of the My Location view The type of map change event. - */ - void onMyLocationChange(@Nullable Location location); - } + void onCancel(); /** - * Interface definition for a callback to be invoked when the the My Location tracking mode changes. - * - * @see TrackingSettings#setMyLocationTrackingMode(int) + * Invoked when a task is complete. */ - public interface OnMyLocationTrackingModeChangeListener { - - /** - * Called when the tracking mode of My Location tracking has changed - * - * @param myLocationTrackingMode the current active location tracking mode - */ - void onMyLocationTrackingModeChange(@MyLocationTracking.Mode int myLocationTrackingMode); - } + void onFinish(); + } + /** + * Interface definition for a callback to be invoked when the snapshot has been taken. + */ + public interface SnapshotReadyCallback { /** - * Interface definition for a callback to be invoked when the the My Location tracking mode changes. + * Invoked when the snapshot has been taken. * - * @see TrackingSettings#setMyLocationTrackingMode(int) + * @param snapshot the snapshot bitmap */ - public interface OnMyBearingTrackingModeChangeListener { - - /** - * Called when the tracking mode of My Bearing tracking has changed - * - * @param myBearingTrackingMode the current active bearing tracking mode - */ - void onMyBearingTrackingModeChange(@MyBearingTracking.Mode int myBearingTrackingMode); - } - - /** - * Interface definition for a callback to be invoked when a task is complete or cancelled. - */ - public interface CancelableCallback { - /** - * Invoked when a task is cancelled. - */ - void onCancel(); - - /** - * Invoked when a task is complete. - */ - void onFinish(); - } - - /** - * Interface definition for a callback to be invoked when the snapshot has been taken. - */ - public interface SnapshotReadyCallback { - /** - * Invoked when the snapshot has been taken. - * - * @param snapshot the snapshot bitmap - */ - void onSnapshotReady(Bitmap snapshot); - } + void onSnapshotReady(Bitmap snapshot); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java index 2b0659322f..95bd943eca 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java @@ -34,1054 +34,1172 @@ import java.util.Arrays; */ public class MapboxMapOptions implements Parcelable { - private static final float DIMENSION_SEVEN_DP = 7f; - private static final float DIMENSION_TEN_DP = 10f; - private static final float DIMENSION_SIXTEEN_DP = 16f; - private static final float DIMENSION_SEVENTY_SIX_DP = 76f; - - private CameraPosition cameraPosition; - - private boolean debugActive; - - private boolean compassEnabled = true; - private boolean fadeCompassFacingNorth = true; - private int compassGravity = Gravity.TOP | Gravity.END; - private int[] compassMargins; - - private boolean logoEnabled = true; - private int logoGravity = Gravity.BOTTOM | Gravity.START; - private int[] logoMargins; - - @ColorInt - private int attributionTintColor = -1; - private boolean attributionEnabled = true; - private int attributionGravity = Gravity.BOTTOM; - private int[] attributionMargins; - - private double minZoom = MapboxConstants.MINIMUM_ZOOM; - private double maxZoom = MapboxConstants.MAXIMUM_ZOOM; - - private boolean rotateGesturesEnabled = true; - private boolean scrollGesturesEnabled = true; - private boolean tiltGesturesEnabled = true; - private boolean zoomGesturesEnabled = true; - private boolean zoomControlsEnabled = false; - - private boolean myLocationEnabled; - private Drawable myLocationForegroundDrawable; - private Drawable myLocationForegroundBearingDrawable; - private Drawable myLocationBackgroundDrawable; - private int myLocationForegroundTintColor; - private int myLocationBackgroundTintColor; - private int[] myLocationBackgroundPadding; - private int myLocationAccuracyTintColor; - private int myLocationAccuracyAlpha; - - private String apiBaseUrl; - - @Deprecated - private boolean textureMode; - - private String style; - @Deprecated - private String accessToken; - - /** - * Creates a new MapboxMapOptions object. - */ - public MapboxMapOptions() { - } - - private MapboxMapOptions(Parcel in) { - cameraPosition = in.readParcelable(CameraPosition.class.getClassLoader()); - debugActive = in.readByte() != 0; - - compassEnabled = in.readByte() != 0; - compassGravity = in.readInt(); - compassMargins = in.createIntArray(); - fadeCompassFacingNorth = in.readByte() != 0; - - logoEnabled = in.readByte() != 0; - logoGravity = in.readInt(); - logoMargins = in.createIntArray(); - - attributionEnabled = in.readByte() != 0; - attributionGravity = in.readInt(); - attributionMargins = in.createIntArray(); - attributionTintColor = in.readInt(); - - minZoom = in.readDouble(); - maxZoom = in.readDouble(); - - rotateGesturesEnabled = in.readByte() != 0; - scrollGesturesEnabled = in.readByte() != 0; - tiltGesturesEnabled = in.readByte() != 0; - zoomControlsEnabled = in.readByte() != 0; - zoomGesturesEnabled = in.readByte() != 0; - - myLocationEnabled = in.readByte() != 0; - - Bitmap foregroundBitmap = in.readParcelable(getClass().getClassLoader()); - if (foregroundBitmap != null) { - myLocationForegroundDrawable = new BitmapDrawable(foregroundBitmap); - } - - Bitmap foregroundBearingBitmap = in.readParcelable(getClass().getClassLoader()); - if (foregroundBearingBitmap != null) { - myLocationForegroundBearingDrawable = new BitmapDrawable(foregroundBearingBitmap); - } - - Bitmap backgroundBitmap = in.readParcelable(getClass().getClassLoader()); - if (backgroundBitmap != null) { - myLocationBackgroundDrawable = new BitmapDrawable(backgroundBitmap); - } - - myLocationForegroundTintColor = in.readInt(); - myLocationBackgroundTintColor = in.readInt(); - myLocationBackgroundPadding = in.createIntArray(); - myLocationAccuracyAlpha = in.readInt(); - myLocationAccuracyTintColor = in.readInt(); - - style = in.readString(); - accessToken = in.readString(); - apiBaseUrl = in.readString(); - textureMode = in.readByte() != 0; - } - - public static Bitmap getBitmapFromDrawable(Drawable drawable) { - if (drawable instanceof BitmapDrawable) { - return ((BitmapDrawable) drawable).getBitmap(); - } else { - Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); - drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); - drawable.draw(canvas); - return bitmap; - } - } - - /** - * Creates a MapboxMapsOptions from the attribute set.s - * - * @param context Context related to a map view. - * @param attrs Attributeset containing configuration - * @return the MapboxMapOptions created from attributes - */ - public static MapboxMapOptions createFromAttributes(@NonNull Context context, @Nullable AttributeSet attrs) { - MapboxMapOptions mapboxMapOptions = new MapboxMapOptions(); - float screenDensity = context.getResources().getDisplayMetrics().density; - TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.mapbox_MapView, 0, 0); - try { - mapboxMapOptions.camera(new CameraPosition.Builder(typedArray).build()); - - mapboxMapOptions.accessToken(typedArray.getString(R.styleable.mapbox_MapView_mapbox_accessToken)); - mapboxMapOptions.styleUrl(typedArray.getString(R.styleable.mapbox_MapView_mapbox_styleUrl)); - mapboxMapOptions.apiBaseUrl(typedArray.getString(R.styleable.mapbox_MapView_mapbox_apiBaseUrl)); - - mapboxMapOptions.zoomGesturesEnabled(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiZoomGestures, true)); - mapboxMapOptions.scrollGesturesEnabled(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiScrollGestures, true)); - mapboxMapOptions.rotateGesturesEnabled(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiRotateGestures, true)); - mapboxMapOptions.tiltGesturesEnabled(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiTiltGestures, true)); - mapboxMapOptions.zoomControlsEnabled(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiZoomControls, false)); - - mapboxMapOptions.maxZoomPreference(typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraZoomMax, MapboxConstants.MAXIMUM_ZOOM)); - mapboxMapOptions.minZoomPreference(typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_cameraZoomMin, MapboxConstants.MINIMUM_ZOOM)); - - mapboxMapOptions.compassEnabled(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiCompass, true)); - mapboxMapOptions.compassGravity(typedArray.getInt(R.styleable.mapbox_MapView_mapbox_uiCompassGravity, Gravity.TOP | Gravity.END)); - mapboxMapOptions.compassMargins(new int[]{(int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiCompassMarginLeft, DIMENSION_TEN_DP * screenDensity)) - , ((int) typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiCompassMarginTop, DIMENSION_TEN_DP * screenDensity)) - , ((int) typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiCompassMarginRight, DIMENSION_TEN_DP * screenDensity)) - , ((int) typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiCompassMarginBottom, DIMENSION_TEN_DP * screenDensity))}); - mapboxMapOptions.compassFadesWhenFacingNorth(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiCompassFadeFacingNorth, true)); - - mapboxMapOptions.logoEnabled(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiLogo, true)); - mapboxMapOptions.logoGravity(typedArray.getInt(R.styleable.mapbox_MapView_mapbox_uiLogoGravity, Gravity.BOTTOM | Gravity.START)); - mapboxMapOptions.logoMargins(new int[]{(int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiLogoMarginLeft, DIMENSION_SIXTEEN_DP * screenDensity)) - , (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiLogoMarginTop, DIMENSION_SIXTEEN_DP * screenDensity)) - , (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiLogoMarginRight, DIMENSION_SIXTEEN_DP * screenDensity)) - , (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiLogoMarginBottom, DIMENSION_SIXTEEN_DP * screenDensity))}); - - mapboxMapOptions.attributionTintColor(typedArray.getColor(R.styleable.mapbox_MapView_mapbox_uiAttributionTintColor, -1)); - mapboxMapOptions.attributionEnabled(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiAttribution, true)); - mapboxMapOptions.attributionGravity(typedArray.getInt(R.styleable.mapbox_MapView_mapbox_uiAttributionGravity, Gravity.BOTTOM)); - mapboxMapOptions.attributionMargins(new int[]{(int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginLeft, DIMENSION_SEVENTY_SIX_DP) * screenDensity) - , (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginTop, DIMENSION_SEVEN_DP * screenDensity)) - , (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginRight, DIMENSION_SEVEN_DP * screenDensity)) - , (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginBottom, DIMENSION_SEVEN_DP * screenDensity))}); - - mapboxMapOptions.locationEnabled(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_myLocation, false)); - mapboxMapOptions.myLocationForegroundTintColor(typedArray.getColor(R.styleable.mapbox_MapView_mapbox_myLocationTintColor, ColorUtils.getPrimaryColor(context))); - mapboxMapOptions.myLocationBackgroundTintColor(typedArray.getColor(R.styleable.mapbox_MapView_mapbox_myLocationBackgroundTintColor, Color.WHITE)); - - Drawable foregroundDrawable = typedArray.getDrawable(R.styleable.mapbox_MapView_mapbox_myLocationDrawable); - if (foregroundDrawable == null) { - foregroundDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_icon_default); - } - - Drawable foregroundBearingDrawable = typedArray.getDrawable(R.styleable.mapbox_MapView_mapbox_myLocationBearingDrawable); - if (foregroundBearingDrawable == null) { - foregroundBearingDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_icon_bearing); - } - - Drawable backgroundDrawable = typedArray.getDrawable(R.styleable.mapbox_MapView_mapbox_myLocationBackgroundDrawable); - if (backgroundDrawable == null) { - backgroundDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_bg_shape); - } - - mapboxMapOptions.myLocationForegroundDrawables(foregroundDrawable, foregroundBearingDrawable); - mapboxMapOptions.myLocationBackgroundDrawable(backgroundDrawable); - mapboxMapOptions.myLocationBackgroundPadding(new int[]{(int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_myLocationBackgroundMarginLeft, 0) * screenDensity) - , (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_myLocationBackgroundMarginTop, 0) * screenDensity) - , (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_myLocationBackgroundMarginRight, 0) * screenDensity) - , (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_myLocationBackgroundMarginBottom, 0) * screenDensity)}); - mapboxMapOptions.myLocationAccuracyAlpha(typedArray.getInt(R.styleable.mapbox_MapView_mapbox_myLocationAccuracyAlpha, 100)); - mapboxMapOptions.myLocationAccuracyTint(typedArray.getColor(R.styleable.mapbox_MapView_mapbox_myLocationAccuracyTintColor, ColorUtils.getPrimaryColor(context))); - mapboxMapOptions.textureMode(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_renderTextureMode, false)); - } finally { - typedArray.recycle(); - } - return mapboxMapOptions; - } - - /** - * Specifies the URL used for API endpoint. - * - * @param apiBaseUrl The base of our API endpoint - * @return This - */ - public MapboxMapOptions apiBaseUrl(String apiBaseUrl) { - this.apiBaseUrl = apiBaseUrl; - return this; - } - - /** - * Specifies a the initial camera position for the map view. - * - * @param cameraPosition Inital camera position - * @return This - */ - public MapboxMapOptions camera(CameraPosition cameraPosition) { - this.cameraPosition = cameraPosition; - return this; - } - - /** - * <p> - * DEPRECATED @see MapboxAccountManager#start(String) - * </p> - * Specifies the accesstoken associated with a map view. - * - * @param accessToken Token to be used to access the service - * @return This - * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)} - */ - @Deprecated - public MapboxMapOptions accessToken(String accessToken) { - this.accessToken = accessToken; - return this; - } - - /** - * Specifies the style url associated with a map view. - * - * @param styleUrl Url to be used to load a style - * @return This - */ - public MapboxMapOptions styleUrl(String styleUrl) { - style = styleUrl; - return this; - } - - /** - * Specifies the used debug type for a map view. - * - * @param enabled True is debug is enabled - * @return This - */ - public MapboxMapOptions debugActive(boolean enabled) { - debugActive = enabled; - return this; - } - - /** - * Specifies the used minimum zoom level for a map view. - * - * @param minZoom Zoom level to be used - * @return This - */ - public MapboxMapOptions minZoomPreference(double minZoom) { - this.minZoom = minZoom; - return this; - } - - /** - * Specifies the used maximum zoom level for a map view. - * - * @param maxZoom Zoom level to be used - * @return This - */ - public MapboxMapOptions maxZoomPreference(double maxZoom) { - this.maxZoom = maxZoom; - return this; - } - - /** - * Specifies the visibility state of a mapbox_compass_icon for a map view. - * - * @param enabled True and mapbox_compass_icon is shown - * @return This - */ - public MapboxMapOptions compassEnabled(boolean enabled) { - compassEnabled = enabled; - return this; - } - - /** - * Specifies the gravity state of mapbox_compass_icon for a map view. - * - * @param gravity see {@link android.view.Gravity} - * @return This - */ - public MapboxMapOptions compassGravity(int gravity) { - compassGravity = gravity; - return this; - } - - /** - * Specifies the margin state of mapbox_compass_icon for a map view - * - * @param margins 4 long array for LTRB margins - * @return This - */ - public MapboxMapOptions compassMargins(int[] margins) { - compassMargins = margins; - return this; - } - - /** - * Specifies if the mapbox_compass_icon fades to invisible when facing north. - * <p> - * By default this value is true. - * </p> - * - * @param compassFadeWhenFacingNorth true is mapbox_compass_icon fades to invisble - * @return This - */ - public MapboxMapOptions compassFadesWhenFacingNorth(boolean compassFadeWhenFacingNorth) { - this.fadeCompassFacingNorth = compassFadeWhenFacingNorth; - return this; - } - - /** - * Specifies the visibility state of a logo for a map view. - * - * @param enabled True and logo is shown - * @return This - */ - public MapboxMapOptions logoEnabled(boolean enabled) { - logoEnabled = enabled; - return this; - } + private static final float DIMENSION_SEVEN_DP = 7f; + private static final float DIMENSION_TEN_DP = 10f; + private static final float DIMENSION_SIXTEEN_DP = 16f; + private static final float DIMENSION_SEVENTY_SIX_DP = 76f; - /** - * Specifies the gravity state of logo for a map view. - * - * @param gravity see {@link android.view.Gravity} - * @return This - */ - public MapboxMapOptions logoGravity(int gravity) { - logoGravity = gravity; - return this; - } - - /** - * Specifies the margin state of logo for a map view - * - * @param margins 4 long array for LTRB margins - * @return This - */ - public MapboxMapOptions logoMargins(int[] margins) { - logoMargins = margins; - return this; - } - - /** - * Specifies the visibility state of a attribution for a map view. - * - * @param enabled True and attribution is shown - * @return This - */ - public MapboxMapOptions attributionEnabled(boolean enabled) { - attributionEnabled = enabled; - return this; - } - - /** - * Specifies the gravity state of attribution for a map view. - * - * @param gravity see {@link android.view.Gravity} - * @return This - */ - public MapboxMapOptions attributionGravity(int gravity) { - attributionGravity = gravity; - return this; - } - - /** - * Specifies the margin state of attribution for a map view - * - * @param margins 4 long array for LTRB margins - * @return This - */ - public MapboxMapOptions attributionMargins(int[] margins) { - attributionMargins = margins; - return this; - } - - /** - * Specifies the tint color of the attribution for a map view - * - * @param color integer resembling a color - * @return This - */ - public MapboxMapOptions attributionTintColor(@ColorInt int color) { - attributionTintColor = color; - return this; - } - - /** - * Specifies if the rotate gesture is enabled for a map view. - * - * @param enabled True and gesture will be enabled - * @return This - */ - public MapboxMapOptions rotateGesturesEnabled(boolean enabled) { - rotateGesturesEnabled = enabled; - return this; - } - - /** - * Specifies if the scroll gesture is enabled for a map view. - * - * @param enabled True and gesture will be enabled - * @return This - */ - public MapboxMapOptions scrollGesturesEnabled(boolean enabled) { - scrollGesturesEnabled = enabled; - return this; - } + private CameraPosition cameraPosition; - /** - * Specifies if the tilt gesture is enabled for a map view. - * - * @param enabled True and gesture will be enabled - * @return This - */ - public MapboxMapOptions tiltGesturesEnabled(boolean enabled) { - tiltGesturesEnabled = enabled; - return this; - } + private boolean debugActive; - /** - * Specifies if the zoom controls are enabled for a map view. - * - * @param enabled True and gesture will be enabled - * @return This - */ - public MapboxMapOptions zoomControlsEnabled(boolean enabled) { - zoomControlsEnabled = enabled; - return this; - } - - /** - * Specifies if the zoom gesture is enabled for a map view. - * - * @param enabled True and gesture will be enabled - * @return This - */ - public MapboxMapOptions zoomGesturesEnabled(boolean enabled) { - zoomGesturesEnabled = enabled; - return this; - } - - /** - * Specifies if the user location view is enabled for a map view. - * - * @param locationEnabled True and gesture will be enabled - * @return This - */ - public MapboxMapOptions locationEnabled(boolean locationEnabled) { - this.myLocationEnabled = locationEnabled; - return this; - } - - /** - * Set the foreground drawables of the MyLocationView. - * - * @param myLocationForegroundDrawable the drawable to show as foreground without bearing - * @param myLocationBearingDrawable the drawable to show as foreground when bearing is disabled - * @return This - */ - public MapboxMapOptions myLocationForegroundDrawables(Drawable myLocationForegroundDrawable, Drawable myLocationBearingDrawable) { - this.myLocationForegroundDrawable = myLocationForegroundDrawable; - this.myLocationForegroundBearingDrawable = myLocationBearingDrawable; - return this; - } - - /** - * Set the foreground drawable of the MyLocationView. - * <p> - * The same drawable will be used for both bearing as non bearing modes. - * </p> - * - * @param myLocationForegroundDrawable the drawable to show as foreground - * @return This - */ - public MapboxMapOptions myLocationForegroundDrawable(Drawable myLocationForegroundDrawable) { - this.myLocationForegroundDrawable = myLocationForegroundDrawable; - return this; - } - - /** - * Set the background drawable of MyLocationView. - * <p> - * Padding can be added to provide an offset to the background. - * </p> - * - * @param myLocationBackgroundDrawable the drawable to show as background - * @return This - */ - public MapboxMapOptions myLocationBackgroundDrawable(Drawable myLocationBackgroundDrawable) { - this.myLocationBackgroundDrawable = myLocationBackgroundDrawable; - return this; - } - - /** - * Set the foreground tint color of MyLocationView. - * <p> - * The color will tint both the foreground and the bearing foreground drawable. - * </p> - * - * @param myLocationForegroundTintColor the color to tint the foreground drawable - * @return This - */ - public MapboxMapOptions myLocationForegroundTintColor(@ColorInt int myLocationForegroundTintColor) { - this.myLocationForegroundTintColor = myLocationForegroundTintColor; - return this; - } - - /** - * Set the background tint color of MyLocationView. - * - * @param myLocationBackgroundTintColor the color to tint the background - * @return This - */ - public MapboxMapOptions myLocationBackgroundTintColor(@ColorInt int myLocationBackgroundTintColor) { - this.myLocationBackgroundTintColor = myLocationBackgroundTintColor; - return this; - } + private boolean compassEnabled = true; + private boolean fadeCompassFacingNorth = true; + private int compassGravity = Gravity.TOP | Gravity.END; + private int[] compassMargins; - /** - * Set the MyLocationView padding. - * - * @param myLocationBackgroundPadding the color to tint the background - * @return This - */ - public MapboxMapOptions myLocationBackgroundPadding(int[] myLocationBackgroundPadding) { - this.myLocationBackgroundPadding = myLocationBackgroundPadding; - return this; - } - - /** - * Set the MyLocationView accuracy circle tint color. - * - * @param myLocationAccuracyTintColor the color to tint the accuracy circle - * @return This - */ - public MapboxMapOptions myLocationAccuracyTint(@ColorInt int myLocationAccuracyTintColor) { - this.myLocationAccuracyTintColor = myLocationAccuracyTintColor; - return this; - } - - /** - * Set the MyLocationView accuracy alpha value. - * - * @param alpha the alpha value - * @return This - */ - public MapboxMapOptions myLocationAccuracyAlpha(@IntRange(from = 0, to = 255) int alpha) { - this.myLocationAccuracyAlpha = alpha; - return this; - } - - /** - * Enable TextureView as rendered surface. - * <p> - * Since the 4.2.0 release we replaced our TextureView with an SurfaceView implemenation. - * Enabling this option will use the deprecated TextureView instead. - * </p> - * - * @param textureMode True to enable texture mode - * @return This - * @deprecated As of the 4.2.0 release, using TextureView is deprecated. - */ - public MapboxMapOptions textureMode(boolean textureMode) { - this.textureMode = textureMode; - return this; - } - - /** - * Get the current configured API endpoint base URL. - * - * @return Base URL to be used API endpoint. - */ - public String getApiBaseUrl() { - return apiBaseUrl; - } - - /** - * Get the current configured initial camera position for a map view. - * - * @return CameraPosition to be initially used. - */ - public CameraPosition getCamera() { - return cameraPosition; - } - - /** - * Get the current configured min zoom for a map view. - * - * @return Mininum zoom level to be used. - */ - public double getMinZoomPreference() { - return minZoom; - } - - /** - * Get the current configured maximum zoom for a map view. - * - * @return Maximum zoom to be used. - */ - public double getMaxZoomPreference() { - return maxZoom; - } - - /** - * Get the current configured visibility state for mapbox_compass_icon for a map view. - * - * @return Visibility state of the mapbox_compass_icon - */ - public boolean getCompassEnabled() { - return compassEnabled; - } - - /** - * Get the current configured gravity state for mapbox_compass_icon for a map view. - * - * @return Gravity state of the mapbox_compass_icon - */ - public int getCompassGravity() { - return compassGravity; - } - - /** - * Get the current configured margins for mapbox_compass_icon for a map view. - * - * @return Margins state of the mapbox_compass_icon - */ - public int[] getCompassMargins() { - return compassMargins; - } - - /** - * Get the current configured state for fading the mapbox_compass_icon when facing north. - * - * @return True if mapbox_compass_icon fades to invisible when facing north - */ - public boolean getCompassFadeFacingNorth() { - return fadeCompassFacingNorth; - } - - /** - * Get the current configured visibility state for mapbox_compass_icon for a map view. - * - * @return Visibility state of the mapbox_compass_icon - */ - public boolean getLogoEnabled() { - return logoEnabled; - } - - /** - * Get the current configured gravity state for logo for a map view. - * - * @return Gravity state of the logo - */ - public int getLogoGravity() { - return logoGravity; - } - - /** - * Get the current configured margins for logo for a map view. - * - * @return Margins state of the logo - */ - public int[] getLogoMargins() { - return logoMargins; - } - - /** - * <p> - * DEPRECATED @see MapboxAccountManager#start(String) - * </p> - * Get the current configured access token for a map view. - * - * @return Access token to be used. - */ - @Deprecated - public String getAccessToken() { - return accessToken; - } + private boolean logoEnabled = true; + private int logoGravity = Gravity.BOTTOM | Gravity.START; + private int[] logoMargins; + + @ColorInt + private int attributionTintColor = -1; + private boolean attributionEnabled = true; + private int attributionGravity = Gravity.BOTTOM; + private int[] attributionMargins; + + private double minZoom = MapboxConstants.MINIMUM_ZOOM; + private double maxZoom = MapboxConstants.MAXIMUM_ZOOM; + + private boolean rotateGesturesEnabled = true; + private boolean scrollGesturesEnabled = true; + private boolean tiltGesturesEnabled = true; + private boolean zoomGesturesEnabled = true; + private boolean zoomControlsEnabled = false; + + private boolean myLocationEnabled; + private Drawable myLocationForegroundDrawable; + private Drawable myLocationForegroundBearingDrawable; + private Drawable myLocationBackgroundDrawable; + private int myLocationForegroundTintColor; + private int myLocationBackgroundTintColor; + private int[] myLocationBackgroundPadding; + private int myLocationAccuracyTintColor; + private int myLocationAccuracyAlpha; + + private String apiBaseUrl; + + @Deprecated + private boolean textureMode; + + private String style; + @Deprecated + private String accessToken; + + /** + * Creates a new MapboxMapOptions object. + */ + public MapboxMapOptions() { + } + + private MapboxMapOptions(Parcel in) { + cameraPosition = in.readParcelable(CameraPosition.class.getClassLoader()); + debugActive = in.readByte() != 0; + + compassEnabled = in.readByte() != 0; + compassGravity = in.readInt(); + compassMargins = in.createIntArray(); + fadeCompassFacingNorth = in.readByte() != 0; + + logoEnabled = in.readByte() != 0; + logoGravity = in.readInt(); + logoMargins = in.createIntArray(); + + attributionEnabled = in.readByte() != 0; + attributionGravity = in.readInt(); + attributionMargins = in.createIntArray(); + attributionTintColor = in.readInt(); + + minZoom = in.readDouble(); + maxZoom = in.readDouble(); + + rotateGesturesEnabled = in.readByte() != 0; + scrollGesturesEnabled = in.readByte() != 0; + tiltGesturesEnabled = in.readByte() != 0; + zoomControlsEnabled = in.readByte() != 0; + zoomGesturesEnabled = in.readByte() != 0; + + myLocationEnabled = in.readByte() != 0; + + Bitmap foregroundBitmap = in.readParcelable(getClass().getClassLoader()); + if (foregroundBitmap != null) { + myLocationForegroundDrawable = new BitmapDrawable(foregroundBitmap); + } + + Bitmap foregroundBearingBitmap = in.readParcelable(getClass().getClassLoader()); + if (foregroundBearingBitmap != null) { + myLocationForegroundBearingDrawable = new BitmapDrawable(foregroundBearingBitmap); + } + + Bitmap backgroundBitmap = in.readParcelable(getClass().getClassLoader()); + if (backgroundBitmap != null) { + myLocationBackgroundDrawable = new BitmapDrawable(backgroundBitmap); + } + + myLocationForegroundTintColor = in.readInt(); + myLocationBackgroundTintColor = in.readInt(); + myLocationBackgroundPadding = in.createIntArray(); + myLocationAccuracyAlpha = in.readInt(); + myLocationAccuracyTintColor = in.readInt(); + + style = in.readString(); + accessToken = in.readString(); + apiBaseUrl = in.readString(); + textureMode = in.readByte() != 0; + } + + public static Bitmap getBitmapFromDrawable(Drawable drawable) { + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable) drawable).getBitmap(); + } else { + Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), + Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + return bitmap; + } + } + + /** + * Creates a MapboxMapsOptions from the attribute set.s + * + * @param context Context related to a map view. + * @param attrs Attributeset containing configuration + * @return the MapboxMapOptions created from attributes + */ + public static MapboxMapOptions createFromAttributes(@NonNull Context context, @Nullable AttributeSet attrs) { + MapboxMapOptions mapboxMapOptions = new MapboxMapOptions(); + float screenDensity = context.getResources().getDisplayMetrics().density; + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.mapbox_MapView, 0, 0); + try { + mapboxMapOptions.camera(new CameraPosition.Builder(typedArray).build()); + + mapboxMapOptions.accessToken(typedArray.getString(R.styleable.mapbox_MapView_mapbox_accessToken)); + mapboxMapOptions.styleUrl(typedArray.getString(R.styleable.mapbox_MapView_mapbox_styleUrl)); + mapboxMapOptions.apiBaseUrl(typedArray.getString(R.styleable.mapbox_MapView_mapbox_apiBaseUrl)); + + mapboxMapOptions.zoomGesturesEnabled(typedArray.getBoolean( + R.styleable.mapbox_MapView_mapbox_uiZoomGestures, true)); + mapboxMapOptions.scrollGesturesEnabled(typedArray.getBoolean( + R.styleable.mapbox_MapView_mapbox_uiScrollGestures, true)); + mapboxMapOptions.rotateGesturesEnabled(typedArray.getBoolean( + R.styleable.mapbox_MapView_mapbox_uiRotateGestures, true)); + mapboxMapOptions.tiltGesturesEnabled(typedArray.getBoolean( + R.styleable.mapbox_MapView_mapbox_uiTiltGestures, true)); + mapboxMapOptions.zoomControlsEnabled(typedArray.getBoolean( + R.styleable.mapbox_MapView_mapbox_uiZoomControls, false)); + + mapboxMapOptions.maxZoomPreference(typedArray.getFloat( + R.styleable.mapbox_MapView_mapbox_cameraZoomMax, MapboxConstants.MAXIMUM_ZOOM)); + mapboxMapOptions.minZoomPreference(typedArray.getFloat( + R.styleable.mapbox_MapView_mapbox_cameraZoomMin, MapboxConstants.MINIMUM_ZOOM)); + + mapboxMapOptions.compassEnabled(typedArray.getBoolean( + R.styleable.mapbox_MapView_mapbox_uiCompass, true)); + mapboxMapOptions.compassGravity(typedArray.getInt( + R.styleable.mapbox_MapView_mapbox_uiCompassGravity, Gravity.TOP | Gravity.END)); + mapboxMapOptions.compassMargins( + new int[] {(int) (typedArray.getDimension( + R.styleable.mapbox_MapView_mapbox_uiCompassMarginLeft, DIMENSION_TEN_DP * screenDensity)), + ((int) typedArray.getDimension( + R.styleable.mapbox_MapView_mapbox_uiCompassMarginTop, DIMENSION_TEN_DP * screenDensity)), + ((int) typedArray.getDimension( + R.styleable.mapbox_MapView_mapbox_uiCompassMarginRight, DIMENSION_TEN_DP * screenDensity)), + ((int) typedArray.getDimension( + R.styleable.mapbox_MapView_mapbox_uiCompassMarginBottom, DIMENSION_TEN_DP * screenDensity))}); + mapboxMapOptions.compassFadesWhenFacingNorth( + typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiCompassFadeFacingNorth, true)); + + mapboxMapOptions.logoEnabled(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiLogo, true)); + mapboxMapOptions.logoGravity(typedArray.getInt( + R.styleable.mapbox_MapView_mapbox_uiLogoGravity, Gravity.BOTTOM | Gravity.START)); + mapboxMapOptions.logoMargins(new int[] {(int) ( + typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiLogoMarginLeft, DIMENSION_SIXTEEN_DP + * screenDensity)), + (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiLogoMarginTop, DIMENSION_SIXTEEN_DP + * screenDensity)), + (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiLogoMarginRight, DIMENSION_SIXTEEN_DP + * screenDensity)), + (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiLogoMarginBottom, DIMENSION_SIXTEEN_DP + * screenDensity))}); + + mapboxMapOptions.attributionTintColor( + typedArray.getColor(R.styleable.mapbox_MapView_mapbox_uiAttributionTintColor, -1)); + mapboxMapOptions.attributionEnabled( + typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_uiAttribution, true)); + mapboxMapOptions.attributionGravity( + typedArray.getInt(R.styleable.mapbox_MapView_mapbox_uiAttributionGravity, Gravity.BOTTOM)); + mapboxMapOptions.attributionMargins( + new int[] {(int) ( + typedArray.getDimension( + R.styleable.mapbox_MapView_mapbox_uiAttributionMarginLeft, DIMENSION_SEVENTY_SIX_DP) + * screenDensity), + (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginTop, DIMENSION_SEVEN_DP + * screenDensity)), + (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginRight, DIMENSION_SEVEN_DP + * screenDensity)), + (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginBottom, DIMENSION_SEVEN_DP + * screenDensity))}); + + mapboxMapOptions.locationEnabled( + typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_myLocation, false)); + mapboxMapOptions.myLocationForegroundTintColor( + typedArray.getColor(R.styleable.mapbox_MapView_mapbox_myLocationTintColor, + ColorUtils.getPrimaryColor(context))); + mapboxMapOptions.myLocationBackgroundTintColor( + typedArray.getColor(R.styleable.mapbox_MapView_mapbox_myLocationBackgroundTintColor, Color.WHITE)); + + Drawable foregroundDrawable = typedArray.getDrawable(R.styleable.mapbox_MapView_mapbox_myLocationDrawable); + if (foregroundDrawable == null) { + foregroundDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_icon_default); + } + + Drawable foregroundBearingDrawable = typedArray.getDrawable( + R.styleable.mapbox_MapView_mapbox_myLocationBearingDrawable); + if (foregroundBearingDrawable == null) { + foregroundBearingDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_icon_bearing); + } + + Drawable backgroundDrawable = typedArray.getDrawable( + R.styleable.mapbox_MapView_mapbox_myLocationBackgroundDrawable); + if (backgroundDrawable == null) { + backgroundDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_bg_shape); + } + + mapboxMapOptions.myLocationForegroundDrawables(foregroundDrawable, foregroundBearingDrawable); + mapboxMapOptions.myLocationBackgroundDrawable(backgroundDrawable); + mapboxMapOptions.myLocationBackgroundPadding(new int[] { + (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_myLocationBackgroundMarginLeft, 0) + * screenDensity), + (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_myLocationBackgroundMarginTop, 0) + * screenDensity), + (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_myLocationBackgroundMarginRight, 0) + * screenDensity), + (int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_myLocationBackgroundMarginBottom, 0) + * screenDensity)}); + mapboxMapOptions.myLocationAccuracyAlpha(typedArray.getInt( + R.styleable.mapbox_MapView_mapbox_myLocationAccuracyAlpha, 100)); + mapboxMapOptions.myLocationAccuracyTint(typedArray.getColor( + R.styleable.mapbox_MapView_mapbox_myLocationAccuracyTintColor, ColorUtils.getPrimaryColor(context))); + mapboxMapOptions.textureMode(typedArray.getBoolean( + R.styleable.mapbox_MapView_mapbox_renderTextureMode, false)); + } finally { + typedArray.recycle(); + } + return mapboxMapOptions; + } + + /** + * Specifies the URL used for API endpoint. + * + * @param apiBaseUrl The base of our API endpoint + * @return This + */ + public MapboxMapOptions apiBaseUrl(String apiBaseUrl) { + this.apiBaseUrl = apiBaseUrl; + return this; + } + + /** + * Specifies a the initial camera position for the map view. + * + * @param cameraPosition Inital camera position + * @return This + */ + public MapboxMapOptions camera(CameraPosition cameraPosition) { + this.cameraPosition = cameraPosition; + return this; + } + + /** + * <p> + * DEPRECATED @see MapboxAccountManager#start(String) + * </p> + * Specifies the accesstoken associated with a map view. + * + * @param accessToken Token to be used to access the service + * @return This + * @deprecated As of release 4.1.0, replaced by + * {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)} + */ + @Deprecated + public MapboxMapOptions accessToken(String accessToken) { + this.accessToken = accessToken; + return this; + } + + /** + * Specifies the style url associated with a map view. + * + * @param styleUrl Url to be used to load a style + * @return This + */ + public MapboxMapOptions styleUrl(String styleUrl) { + style = styleUrl; + return this; + } + + /** + * Specifies the used debug type for a map view. + * + * @param enabled True is debug is enabled + * @return This + */ + public MapboxMapOptions debugActive(boolean enabled) { + debugActive = enabled; + return this; + } + + /** + * Specifies the used minimum zoom level for a map view. + * + * @param minZoom Zoom level to be used + * @return This + */ + public MapboxMapOptions minZoomPreference(double minZoom) { + this.minZoom = minZoom; + return this; + } + + /** + * Specifies the used maximum zoom level for a map view. + * + * @param maxZoom Zoom level to be used + * @return This + */ + public MapboxMapOptions maxZoomPreference(double maxZoom) { + this.maxZoom = maxZoom; + return this; + } + + /** + * Specifies the visibility state of a mapbox_compass_icon for a map view. + * + * @param enabled True and mapbox_compass_icon is shown + * @return This + */ + public MapboxMapOptions compassEnabled(boolean enabled) { + compassEnabled = enabled; + return this; + } + + /** + * Specifies the gravity state of mapbox_compass_icon for a map view. + * + * @param gravity see {@link android.view.Gravity} + * @return This + */ + public MapboxMapOptions compassGravity(int gravity) { + compassGravity = gravity; + return this; + } + + /** + * Specifies the margin state of mapbox_compass_icon for a map view + * + * @param margins 4 long array for LTRB margins + * @return This + */ + public MapboxMapOptions compassMargins(int[] margins) { + compassMargins = margins; + return this; + } + + /** + * Specifies if the mapbox_compass_icon fades to invisible when facing north. + * <p> + * By default this value is true. + * </p> + * + * @param compassFadeWhenFacingNorth true is mapbox_compass_icon fades to invisble + * @return This + */ + public MapboxMapOptions compassFadesWhenFacingNorth(boolean compassFadeWhenFacingNorth) { + this.fadeCompassFacingNorth = compassFadeWhenFacingNorth; + return this; + } + + /** + * Specifies the visibility state of a logo for a map view. + * + * @param enabled True and logo is shown + * @return This + */ + public MapboxMapOptions logoEnabled(boolean enabled) { + logoEnabled = enabled; + return this; + } + + /** + * Specifies the gravity state of logo for a map view. + * + * @param gravity see {@link android.view.Gravity} + * @return This + */ + public MapboxMapOptions logoGravity(int gravity) { + logoGravity = gravity; + return this; + } + + /** + * Specifies the margin state of logo for a map view + * + * @param margins 4 long array for LTRB margins + * @return This + */ + public MapboxMapOptions logoMargins(int[] margins) { + logoMargins = margins; + return this; + } + + /** + * Specifies the visibility state of a attribution for a map view. + * + * @param enabled True and attribution is shown + * @return This + */ + public MapboxMapOptions attributionEnabled(boolean enabled) { + attributionEnabled = enabled; + return this; + } + + /** + * Specifies the gravity state of attribution for a map view. + * + * @param gravity see {@link android.view.Gravity} + * @return This + */ + public MapboxMapOptions attributionGravity(int gravity) { + attributionGravity = gravity; + return this; + } + + /** + * Specifies the margin state of attribution for a map view + * + * @param margins 4 long array for LTRB margins + * @return This + */ + public MapboxMapOptions attributionMargins(int[] margins) { + attributionMargins = margins; + return this; + } + + /** + * Specifies the tint color of the attribution for a map view + * + * @param color integer resembling a color + * @return This + */ + public MapboxMapOptions attributionTintColor(@ColorInt int color) { + attributionTintColor = color; + return this; + } + + /** + * Specifies if the rotate gesture is enabled for a map view. + * + * @param enabled True and gesture will be enabled + * @return This + */ + public MapboxMapOptions rotateGesturesEnabled(boolean enabled) { + rotateGesturesEnabled = enabled; + return this; + } + + /** + * Specifies if the scroll gesture is enabled for a map view. + * + * @param enabled True and gesture will be enabled + * @return This + */ + public MapboxMapOptions scrollGesturesEnabled(boolean enabled) { + scrollGesturesEnabled = enabled; + return this; + } + + /** + * Specifies if the tilt gesture is enabled for a map view. + * + * @param enabled True and gesture will be enabled + * @return This + */ + public MapboxMapOptions tiltGesturesEnabled(boolean enabled) { + tiltGesturesEnabled = enabled; + return this; + } + + /** + * Specifies if the zoom controls are enabled for a map view. + * + * @param enabled True and gesture will be enabled + * @return This + */ + public MapboxMapOptions zoomControlsEnabled(boolean enabled) { + zoomControlsEnabled = enabled; + return this; + } + + /** + * Specifies if the zoom gesture is enabled for a map view. + * + * @param enabled True and gesture will be enabled + * @return This + */ + public MapboxMapOptions zoomGesturesEnabled(boolean enabled) { + zoomGesturesEnabled = enabled; + return this; + } + + /** + * Specifies if the user location view is enabled for a map view. + * + * @param locationEnabled True and gesture will be enabled + * @return This + */ + public MapboxMapOptions locationEnabled(boolean locationEnabled) { + this.myLocationEnabled = locationEnabled; + return this; + } + + /** + * Set the foreground drawables of the MyLocationView. + * + * @param myLocationForegroundDrawable the drawable to show as foreground without bearing + * @param myLocationBearingDrawable the drawable to show as foreground when bearing is disabled + * @return This + */ + public MapboxMapOptions myLocationForegroundDrawables(Drawable myLocationForegroundDrawable, + Drawable myLocationBearingDrawable) { + this.myLocationForegroundDrawable = myLocationForegroundDrawable; + this.myLocationForegroundBearingDrawable = myLocationBearingDrawable; + return this; + } + + /** + * Set the foreground drawable of the MyLocationView. + * <p> + * The same drawable will be used for both bearing as non bearing modes. + * </p> + * + * @param myLocationForegroundDrawable the drawable to show as foreground + * @return This + */ + public MapboxMapOptions myLocationForegroundDrawable(Drawable myLocationForegroundDrawable) { + this.myLocationForegroundDrawable = myLocationForegroundDrawable; + return this; + } + + /** + * Set the background drawable of MyLocationView. + * <p> + * Padding can be added to provide an offset to the background. + * </p> + * + * @param myLocationBackgroundDrawable the drawable to show as background + * @return This + */ + public MapboxMapOptions myLocationBackgroundDrawable(Drawable myLocationBackgroundDrawable) { + this.myLocationBackgroundDrawable = myLocationBackgroundDrawable; + return this; + } + + /** + * Set the foreground tint color of MyLocationView. + * <p> + * The color will tint both the foreground and the bearing foreground drawable. + * </p> + * + * @param myLocationForegroundTintColor the color to tint the foreground drawable + * @return This + */ + public MapboxMapOptions myLocationForegroundTintColor(@ColorInt int myLocationForegroundTintColor) { + this.myLocationForegroundTintColor = myLocationForegroundTintColor; + return this; + } + + /** + * Set the background tint color of MyLocationView. + * + * @param myLocationBackgroundTintColor the color to tint the background + * @return This + */ + public MapboxMapOptions myLocationBackgroundTintColor(@ColorInt int myLocationBackgroundTintColor) { + this.myLocationBackgroundTintColor = myLocationBackgroundTintColor; + return this; + } + + /** + * Set the MyLocationView padding. + * + * @param myLocationBackgroundPadding the color to tint the background + * @return This + */ + public MapboxMapOptions myLocationBackgroundPadding(int[] myLocationBackgroundPadding) { + this.myLocationBackgroundPadding = myLocationBackgroundPadding; + return this; + } + + /** + * Set the MyLocationView accuracy circle tint color. + * + * @param myLocationAccuracyTintColor the color to tint the accuracy circle + * @return This + */ + public MapboxMapOptions myLocationAccuracyTint(@ColorInt int myLocationAccuracyTintColor) { + this.myLocationAccuracyTintColor = myLocationAccuracyTintColor; + return this; + } + + /** + * Set the MyLocationView accuracy alpha value. + * + * @param alpha the alpha value + * @return This + */ + public MapboxMapOptions myLocationAccuracyAlpha(@IntRange(from = 0, to = 255) int alpha) { + this.myLocationAccuracyAlpha = alpha; + return this; + } + + /** + * Enable TextureView as rendered surface. + * <p> + * Since the 4.2.0 release we replaced our TextureView with an SurfaceView implemenation. + * Enabling this option will use the deprecated TextureView instead. + * </p> + * + * @param textureMode True to enable texture mode + * @return This + * @deprecated As of the 4.2.0 release, using TextureView is deprecated. + */ + public MapboxMapOptions textureMode(boolean textureMode) { + this.textureMode = textureMode; + return this; + } + + /** + * Get the current configured API endpoint base URL. + * + * @return Base URL to be used API endpoint. + */ + public String getApiBaseUrl() { + return apiBaseUrl; + } + + /** + * Get the current configured initial camera position for a map view. + * + * @return CameraPosition to be initially used. + */ + public CameraPosition getCamera() { + return cameraPosition; + } + + /** + * Get the current configured min zoom for a map view. + * + * @return Mininum zoom level to be used. + */ + public double getMinZoomPreference() { + return minZoom; + } + + /** + * Get the current configured maximum zoom for a map view. + * + * @return Maximum zoom to be used. + */ + public double getMaxZoomPreference() { + return maxZoom; + } + + /** + * Get the current configured visibility state for mapbox_compass_icon for a map view. + * + * @return Visibility state of the mapbox_compass_icon + */ + public boolean getCompassEnabled() { + return compassEnabled; + } + + /** + * Get the current configured gravity state for mapbox_compass_icon for a map view. + * + * @return Gravity state of the mapbox_compass_icon + */ + public int getCompassGravity() { + return compassGravity; + } + + /** + * Get the current configured margins for mapbox_compass_icon for a map view. + * + * @return Margins state of the mapbox_compass_icon + */ + public int[] getCompassMargins() { + return compassMargins; + } + + /** + * Get the current configured state for fading the mapbox_compass_icon when facing north. + * + * @return True if mapbox_compass_icon fades to invisible when facing north + */ + public boolean getCompassFadeFacingNorth() { + return fadeCompassFacingNorth; + } + + /** + * Get the current configured visibility state for mapbox_compass_icon for a map view. + * + * @return Visibility state of the mapbox_compass_icon + */ + public boolean getLogoEnabled() { + return logoEnabled; + } + + /** + * Get the current configured gravity state for logo for a map view. + * + * @return Gravity state of the logo + */ + public int getLogoGravity() { + return logoGravity; + } + + /** + * Get the current configured margins for logo for a map view. + * + * @return Margins state of the logo + */ + public int[] getLogoMargins() { + return logoMargins; + } + + /** + * <p> + * DEPRECATED @see MapboxAccountManager#start(String) + * </p> + * Get the current configured access token for a map view. + * + * @return Access token to be used. + */ + @Deprecated + public String getAccessToken() { + return accessToken; + } + + /** + * Get the current configured style url for a map view. + * + * @return Style url to be used. + */ + public String getStyle() { + return style; + } + + /** + * Get the current configured rotate gesture state for a map view. + * + * @return True indicates gesture is enabled + */ + public boolean getRotateGesturesEnabled() { + return rotateGesturesEnabled; + } + + /** + * Get the current configured scroll gesture state for a map view. + * + * @return True indicates gesture is enabled + */ + public boolean getScrollGesturesEnabled() { + return scrollGesturesEnabled; + } + + /** + * Get the current configured tilt gesture state for a map view. + * + * @return True indicates gesture is enabled + */ + public boolean getTiltGesturesEnabled() { + return tiltGesturesEnabled; + } + + /** + * Get the current configured zoom controls state for a map view. + * + * @return True indicates gesture is enabled + */ + public boolean getZoomControlsEnabled() { + return zoomControlsEnabled; + } + + /** + * Get the current configured zoom gesture state for a map view. + * + * @return True indicates gesture is enabled + */ + public boolean getZoomGesturesEnabled() { + return zoomGesturesEnabled; + } + + /** + * Get the current configured visibility state for attribution for a map view. + * + * @return Visibility state of the attribution + */ + public boolean getAttributionEnabled() { + return attributionEnabled; + } + + /** + * Get the current configured gravity state for attribution for a map view. + * + * @return Gravity state of the logo + */ + public int getAttributionGravity() { + return attributionGravity; + } + + /** + * Get the current configured margins for attribution for a map view. + * + * @return Margins state of the logo + */ + public int[] getAttributionMargins() { + return attributionMargins; + } + + /** + * Get the current configured tint color for attribution for a map view. + * + * @return the tint color + */ + @ColorInt + public int getAttributionTintColor() { + return attributionTintColor; + } + + /** + * Get the current configured user location view state for a map view. + * + * @return True and user location will be shown + */ + public boolean getLocationEnabled() { + return myLocationEnabled; + } + + /** + * Get the current configured MyLocationView foreground drawable. + * + * @return the drawable used as foreground + */ + public Drawable getMyLocationForegroundDrawable() { + return myLocationForegroundDrawable; + } + + /** + * Get the current configured MyLocationView foreground bearing drawable. + * + * @return the drawable used as foreground when bearing is enabled + */ + public Drawable getMyLocationForegroundBearingDrawable() { + return myLocationForegroundBearingDrawable; + } + + /** + * Get the current configured MyLocationView background drawable. + * + * @return the drawable used as background + */ + public Drawable getMyLocationBackgroundDrawable() { + return myLocationBackgroundDrawable; + } + + /** + * Get the current configured MyLocationView foreground tint color. + * + * @return the tint color + */ + public int getMyLocationForegroundTintColor() { + return myLocationForegroundTintColor; + } + + /** + * Get the current configured MyLocationView background tint color. + * + * @return the tint color + */ + public int getMyLocationBackgroundTintColor() { + return myLocationBackgroundTintColor; + } + + /** + * Get the current configured MyLocationView background padding. + * + * @return an array describing the padding in a LTRB manner + */ + public int[] getMyLocationBackgroundPadding() { + return myLocationBackgroundPadding; + } + + /** + * Get the current configured MyLocationView accuracy circle color tint value. + * + * @return the tint color + */ + public int getMyLocationAccuracyTintColor() { + return myLocationAccuracyTintColor; + } + + /** + * Get the current configured MyLocationView accuracy circle alpha value. + * + * @return the alpha value + */ + public int getMyLocationAccuracyAlpha() { + return myLocationAccuracyAlpha; + } + + /** + * Get the current configured debug state for a map view. + * + * @return True indicates debug is enabled. + */ + public boolean getDebugActive() { + return debugActive; + } + + /** + * Returns true if TextureView is being used a render view. + * + * @return True if TextureView is used. + * @deprecated As of the 4.2.0 release, using TextureView is deprecated. + */ + public boolean getTextureMode() { + return textureMode; + } + + public static final Parcelable.Creator<MapboxMapOptions> CREATOR = + new Parcelable.Creator<MapboxMapOptions>() { + public MapboxMapOptions createFromParcel(Parcel in) { + return new MapboxMapOptions(in); + } + + public MapboxMapOptions[] newArray(int size) { + return new MapboxMapOptions[size]; + } + }; - /** - * Get the current configured style url for a map view. - * - * @return Style url to be used. - */ - public String getStyle() { - return style; - } + @Override + public int describeContents() { + return 0; + } - /** - * Get the current configured rotate gesture state for a map view. - * - * @return True indicates gesture is enabled - */ - public boolean getRotateGesturesEnabled() { - return rotateGesturesEnabled; - } + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(cameraPosition, flags); + dest.writeByte((byte) (debugActive ? 1 : 0)); - /** - * Get the current configured scroll gesture state for a map view. - * - * @return True indicates gesture is enabled - */ - public boolean getScrollGesturesEnabled() { - return scrollGesturesEnabled; - } + dest.writeByte((byte) (compassEnabled ? 1 : 0)); + dest.writeInt(compassGravity); + dest.writeIntArray(compassMargins); + dest.writeByte((byte) (fadeCompassFacingNorth ? 1 : 0)); - /** - * Get the current configured tilt gesture state for a map view. - * - * @return True indicates gesture is enabled - */ - public boolean getTiltGesturesEnabled() { - return tiltGesturesEnabled; - } + dest.writeByte((byte) (logoEnabled ? 1 : 0)); + dest.writeInt(logoGravity); + dest.writeIntArray(logoMargins); - /** - * Get the current configured zoom controls state for a map view. - * - * @return True indicates gesture is enabled - */ - public boolean getZoomControlsEnabled() { - return zoomControlsEnabled; - } + dest.writeByte((byte) (attributionEnabled ? 1 : 0)); + dest.writeInt(attributionGravity); + dest.writeIntArray(attributionMargins); + dest.writeInt(attributionTintColor); - /** - * Get the current configured zoom gesture state for a map view. - * - * @return True indicates gesture is enabled - */ - public boolean getZoomGesturesEnabled() { - return zoomGesturesEnabled; - } + dest.writeDouble(minZoom); + dest.writeDouble(maxZoom); - /** - * Get the current configured visibility state for attribution for a map view. - * - * @return Visibility state of the attribution - */ - public boolean getAttributionEnabled() { - return attributionEnabled; - } + dest.writeByte((byte) (rotateGesturesEnabled ? 1 : 0)); + dest.writeByte((byte) (scrollGesturesEnabled ? 1 : 0)); + dest.writeByte((byte) (tiltGesturesEnabled ? 1 : 0)); + dest.writeByte((byte) (zoomControlsEnabled ? 1 : 0)); + dest.writeByte((byte) (zoomGesturesEnabled ? 1 : 0)); - /** - * Get the current configured gravity state for attribution for a map view. - * - * @return Gravity state of the logo - */ - public int getAttributionGravity() { - return attributionGravity; - } - - /** - * Get the current configured margins for attribution for a map view. - * - * @return Margins state of the logo - */ - public int[] getAttributionMargins() { - return attributionMargins; - } + dest.writeByte((byte) (myLocationEnabled ? 1 : 0)); - /** - * Get the current configured tint color for attribution for a map view. - * - * @return the tint color - */ - @ColorInt - public int getAttributionTintColor() { - return attributionTintColor; - } + dest.writeParcelable(myLocationForegroundDrawable != null + ? getBitmapFromDrawable(myLocationForegroundDrawable) : null, flags); + dest.writeParcelable(myLocationForegroundBearingDrawable != null + ? getBitmapFromDrawable(myLocationForegroundBearingDrawable) : null, flags); + dest.writeParcelable(myLocationBackgroundDrawable != null + ? getBitmapFromDrawable(myLocationBackgroundDrawable) : null, flags); + dest.writeInt(myLocationForegroundTintColor); + dest.writeInt(myLocationBackgroundTintColor); + dest.writeIntArray(myLocationBackgroundPadding); + dest.writeInt(myLocationAccuracyAlpha); + dest.writeInt(myLocationAccuracyTintColor); - /** - * Get the current configured user location view state for a map view. - * - * @return True and user location will be shown - */ - public boolean getLocationEnabled() { - return myLocationEnabled; - } - - /** - * Get the current configured MyLocationView foreground drawable. - * - * @return the drawable used as foreground - */ - public Drawable getMyLocationForegroundDrawable() { - return myLocationForegroundDrawable; - } + dest.writeString(style); + dest.writeString(accessToken); + dest.writeString(apiBaseUrl); + dest.writeByte((byte) (textureMode ? 1 : 0)); + } - /** - * Get the current configured MyLocationView foreground bearing drawable. - * - * @return the drawable used as foreground when bearing is enabled - */ - public Drawable getMyLocationForegroundBearingDrawable() { - return myLocationForegroundBearingDrawable; + @Override + public boolean equals(Object object) { + if (this == object) { + return true; } - - /** - * Get the current configured MyLocationView background drawable. - * - * @return the drawable used as background - */ - public Drawable getMyLocationBackgroundDrawable() { - return myLocationBackgroundDrawable; + if (object == null || getClass() != object.getClass()) { + return false; } - /** - * Get the current configured MyLocationView foreground tint color. - * - * @return the tint color - */ - public int getMyLocationForegroundTintColor() { - return myLocationForegroundTintColor; - } + MapboxMapOptions options = (MapboxMapOptions) object; - /** - * Get the current configured MyLocationView background tint color. - * - * @return the tint color - */ - public int getMyLocationBackgroundTintColor() { - return myLocationBackgroundTintColor; + if (debugActive != options.debugActive) { + return false; } - - /** - * Get the current configured MyLocationView background padding. - * - * @return an array describing the padding in a LTRB manner - */ - public int[] getMyLocationBackgroundPadding() { - return myLocationBackgroundPadding; + if (compassEnabled != options.compassEnabled) { + return false; } - - /** - * Get the current configured MyLocationView accuracy circle color tint value. - * - * @return the tint color - */ - public int getMyLocationAccuracyTintColor() { - return myLocationAccuracyTintColor; + if (fadeCompassFacingNorth != options.fadeCompassFacingNorth) { + return false; } - - /** - * Get the current configured MyLocationView accuracy circle alpha value. - * - * @return the alpha value - */ - public int getMyLocationAccuracyAlpha() { - return myLocationAccuracyAlpha; + if (compassGravity != options.compassGravity) { + return false; } - - /** - * Get the current configured debug state for a map view. - * - * @return True indicates debug is enabled. - */ - public boolean getDebugActive() { - return debugActive; + if (logoEnabled != options.logoEnabled) { + return false; } - - /** - * Returns true if TextureView is being used a render view. - * - * @return True if TextureView is used. - * @deprecated As of the 4.2.0 release, using TextureView is deprecated. - */ - public boolean getTextureMode() { - return textureMode; + if (logoGravity != options.logoGravity) { + return false; } - - public static final Parcelable.Creator<MapboxMapOptions> CREATOR - = new Parcelable.Creator<MapboxMapOptions>() { - public MapboxMapOptions createFromParcel(Parcel in) { - return new MapboxMapOptions(in); - } - - public MapboxMapOptions[] newArray(int size) { - return new MapboxMapOptions[size]; - } - }; - - @Override - public int describeContents() { - return 0; + if (attributionTintColor != options.attributionTintColor) { + return false; } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeParcelable(cameraPosition, flags); - dest.writeByte((byte) (debugActive ? 1 : 0)); - - dest.writeByte((byte) (compassEnabled ? 1 : 0)); - dest.writeInt(compassGravity); - dest.writeIntArray(compassMargins); - dest.writeByte((byte) (fadeCompassFacingNorth ? 1 : 0)); - - dest.writeByte((byte) (logoEnabled ? 1 : 0)); - dest.writeInt(logoGravity); - dest.writeIntArray(logoMargins); - - dest.writeByte((byte) (attributionEnabled ? 1 : 0)); - dest.writeInt(attributionGravity); - dest.writeIntArray(attributionMargins); - dest.writeInt(attributionTintColor); - - dest.writeDouble(minZoom); - dest.writeDouble(maxZoom); - - dest.writeByte((byte) (rotateGesturesEnabled ? 1 : 0)); - dest.writeByte((byte) (scrollGesturesEnabled ? 1 : 0)); - dest.writeByte((byte) (tiltGesturesEnabled ? 1 : 0)); - dest.writeByte((byte) (zoomControlsEnabled ? 1 : 0)); - dest.writeByte((byte) (zoomGesturesEnabled ? 1 : 0)); - - dest.writeByte((byte) (myLocationEnabled ? 1 : 0)); - - dest.writeParcelable(myLocationForegroundDrawable != null ? getBitmapFromDrawable(myLocationForegroundDrawable) : null, flags); - dest.writeParcelable(myLocationForegroundBearingDrawable != null ? getBitmapFromDrawable(myLocationForegroundBearingDrawable) : null, flags); - dest.writeParcelable(myLocationBackgroundDrawable != null ? getBitmapFromDrawable(myLocationBackgroundDrawable) : null, flags); - dest.writeInt(myLocationForegroundTintColor); - dest.writeInt(myLocationBackgroundTintColor); - dest.writeIntArray(myLocationBackgroundPadding); - dest.writeInt(myLocationAccuracyAlpha); - dest.writeInt(myLocationAccuracyTintColor); - - dest.writeString(style); - dest.writeString(accessToken); - dest.writeString(apiBaseUrl); - dest.writeByte((byte) (textureMode ? 1 : 0)); + if (attributionEnabled != options.attributionEnabled) { + return false; } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - MapboxMapOptions options = (MapboxMapOptions) o; - - if (debugActive != options.debugActive) return false; - if (compassEnabled != options.compassEnabled) return false; - if (fadeCompassFacingNorth != options.fadeCompassFacingNorth) return false; - if (compassGravity != options.compassGravity) return false; - if (logoEnabled != options.logoEnabled) return false; - if (logoGravity != options.logoGravity) return false; - if (attributionTintColor != options.attributionTintColor) return false; - if (attributionEnabled != options.attributionEnabled) return false; - if (attributionGravity != options.attributionGravity) return false; - if (Double.compare(options.minZoom, minZoom) != 0) return false; - if (Double.compare(options.maxZoom, maxZoom) != 0) return false; - if (rotateGesturesEnabled != options.rotateGesturesEnabled) return false; - if (scrollGesturesEnabled != options.scrollGesturesEnabled) return false; - if (tiltGesturesEnabled != options.tiltGesturesEnabled) return false; - if (zoomGesturesEnabled != options.zoomGesturesEnabled) return false; - if (zoomControlsEnabled != options.zoomControlsEnabled) return false; - if (myLocationEnabled != options.myLocationEnabled) return false; - if (myLocationForegroundTintColor != options.myLocationForegroundTintColor) return false; - if (myLocationBackgroundTintColor != options.myLocationBackgroundTintColor) return false; - if (myLocationAccuracyTintColor != options.myLocationAccuracyTintColor) return false; - if (myLocationAccuracyAlpha != options.myLocationAccuracyAlpha) return false; - if (cameraPosition != null ? !cameraPosition.equals(options.cameraPosition) : options.cameraPosition != null) - return false; - if (!Arrays.equals(compassMargins, options.compassMargins)) return false; - if (!Arrays.equals(logoMargins, options.logoMargins)) return false; - if (!Arrays.equals(attributionMargins, options.attributionMargins)) return false; - if (myLocationForegroundDrawable != null ? !myLocationForegroundDrawable.equals(options.myLocationForegroundDrawable) : options.myLocationForegroundDrawable != null) - return false; - if (myLocationForegroundBearingDrawable != null ? !myLocationForegroundBearingDrawable.equals(options.myLocationForegroundBearingDrawable) : options.myLocationForegroundBearingDrawable != null) - return false; - if (myLocationBackgroundDrawable != null ? !myLocationBackgroundDrawable.equals(options.myLocationBackgroundDrawable) : options.myLocationBackgroundDrawable != null) - return false; - if (!Arrays.equals(myLocationBackgroundPadding, options.myLocationBackgroundPadding)) - return false; - if (style != null ? !style.equals(options.style) : options.style != null) return false; - if (apiBaseUrl != null ? !apiBaseUrl.equals(options.apiBaseUrl) : options.apiBaseUrl != null) - return false; - return accessToken != null ? accessToken.equals(options.accessToken) : options.accessToken == null; - + if (attributionGravity != options.attributionGravity) { + return false; } - - @Override - public int hashCode() { - int result; - long temp; - result = cameraPosition != null ? cameraPosition.hashCode() : 0; - result = 31 * result + (debugActive ? 1 : 0); - result = 31 * result + (compassEnabled ? 1 : 0); - result = 31 * result + (fadeCompassFacingNorth ? 1 : 0); - result = 31 * result + compassGravity; - result = 31 * result + Arrays.hashCode(compassMargins); - result = 31 * result + (logoEnabled ? 1 : 0); - result = 31 * result + logoGravity; - result = 31 * result + Arrays.hashCode(logoMargins); - result = 31 * result + attributionTintColor; - result = 31 * result + (attributionEnabled ? 1 : 0); - result = 31 * result + attributionGravity; - result = 31 * result + Arrays.hashCode(attributionMargins); - temp = Double.doubleToLongBits(minZoom); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(maxZoom); - result = 31 * result + (int) (temp ^ (temp >>> 32)); - result = 31 * result + (rotateGesturesEnabled ? 1 : 0); - result = 31 * result + (scrollGesturesEnabled ? 1 : 0); - result = 31 * result + (tiltGesturesEnabled ? 1 : 0); - result = 31 * result + (zoomGesturesEnabled ? 1 : 0); - result = 31 * result + (zoomControlsEnabled ? 1 : 0); - result = 31 * result + (myLocationEnabled ? 1 : 0); - result = 31 * result + (myLocationForegroundDrawable != null ? myLocationForegroundDrawable.hashCode() : 0); - result = 31 * result + (myLocationForegroundBearingDrawable != null ? myLocationForegroundBearingDrawable.hashCode() : 0); - result = 31 * result + (myLocationBackgroundDrawable != null ? myLocationBackgroundDrawable.hashCode() : 0); - result = 31 * result + myLocationForegroundTintColor; - result = 31 * result + myLocationBackgroundTintColor; - result = 31 * result + Arrays.hashCode(myLocationBackgroundPadding); - result = 31 * result + myLocationAccuracyTintColor; - result = 31 * result + myLocationAccuracyAlpha; - result = 31 * result + (apiBaseUrl != null ? apiBaseUrl.hashCode() : 0); - result = 31 * result + (textureMode ? 1 : 0); - result = 31 * result + (style != null ? style.hashCode() : 0); - result = 31 * result + (accessToken != null ? accessToken.hashCode() : 0); - return result; + if (Double.compare(options.minZoom, minZoom) != 0) { + return false; } + if (Double.compare(options.maxZoom, maxZoom) != 0) { + return false; + } + if (rotateGesturesEnabled != options.rotateGesturesEnabled) { + return false; + } + if (scrollGesturesEnabled != options.scrollGesturesEnabled) { + return false; + } + if (tiltGesturesEnabled != options.tiltGesturesEnabled) { + return false; + } + if (zoomGesturesEnabled != options.zoomGesturesEnabled) { + return false; + } + if (zoomControlsEnabled != options.zoomControlsEnabled) { + return false; + } + if (myLocationEnabled != options.myLocationEnabled) { + return false; + } + if (myLocationForegroundTintColor != options.myLocationForegroundTintColor) { + return false; + } + if (myLocationBackgroundTintColor != options.myLocationBackgroundTintColor) { + return false; + } + if (myLocationAccuracyTintColor != options.myLocationAccuracyTintColor) { + return false; + } + if (myLocationAccuracyAlpha != options.myLocationAccuracyAlpha) { + return false; + } + if (cameraPosition != null ? !cameraPosition.equals(options.cameraPosition) : options.cameraPosition != null) { + return false; + } + if (!Arrays.equals(compassMargins, options.compassMargins)) { + return false; + } + if (!Arrays.equals(logoMargins, options.logoMargins)) { + return false; + } + if (!Arrays.equals(attributionMargins, options.attributionMargins)) { + return false; + } + if (myLocationForegroundDrawable != null + ? !myLocationForegroundDrawable.equals(options.myLocationForegroundDrawable) + : options.myLocationForegroundDrawable != null) { + return false; + } + if (myLocationForegroundBearingDrawable != null + ? !myLocationForegroundBearingDrawable.equals(options.myLocationForegroundBearingDrawable) + : options.myLocationForegroundBearingDrawable != null) { + return false; + } + if (myLocationBackgroundDrawable != null + ? !myLocationBackgroundDrawable.equals(options.myLocationBackgroundDrawable) + : options.myLocationBackgroundDrawable != null) { + return false; + } + if (!Arrays.equals(myLocationBackgroundPadding, options.myLocationBackgroundPadding)) { + return false; + } + if (style != null ? !style.equals(options.style) : options.style != null) { + return false; + } + if (apiBaseUrl != null ? !apiBaseUrl.equals(options.apiBaseUrl) : options.apiBaseUrl != null) { + return false; + } + return accessToken != null ? accessToken.equals(options.accessToken) : options.accessToken == null; + + } + + @Override + public int hashCode() { + int result; + long temp; + result = cameraPosition != null ? cameraPosition.hashCode() : 0; + result = 31 * result + (debugActive ? 1 : 0); + result = 31 * result + (compassEnabled ? 1 : 0); + result = 31 * result + (fadeCompassFacingNorth ? 1 : 0); + result = 31 * result + compassGravity; + result = 31 * result + Arrays.hashCode(compassMargins); + result = 31 * result + (logoEnabled ? 1 : 0); + result = 31 * result + logoGravity; + result = 31 * result + Arrays.hashCode(logoMargins); + result = 31 * result + attributionTintColor; + result = 31 * result + (attributionEnabled ? 1 : 0); + result = 31 * result + attributionGravity; + result = 31 * result + Arrays.hashCode(attributionMargins); + temp = Double.doubleToLongBits(minZoom); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(maxZoom); + result = 31 * result + (int) (temp ^ (temp >>> 32)); + result = 31 * result + (rotateGesturesEnabled ? 1 : 0); + result = 31 * result + (scrollGesturesEnabled ? 1 : 0); + result = 31 * result + (tiltGesturesEnabled ? 1 : 0); + result = 31 * result + (zoomGesturesEnabled ? 1 : 0); + result = 31 * result + (zoomControlsEnabled ? 1 : 0); + result = 31 * result + (myLocationEnabled ? 1 : 0); + result = 31 * result + (myLocationForegroundDrawable != null ? myLocationForegroundDrawable.hashCode() : 0); + result = 31 * result + (myLocationForegroundBearingDrawable != null + ? myLocationForegroundBearingDrawable.hashCode() : 0); + result = 31 * result + (myLocationBackgroundDrawable != null ? myLocationBackgroundDrawable.hashCode() : 0); + result = 31 * result + myLocationForegroundTintColor; + result = 31 * result + myLocationBackgroundTintColor; + result = 31 * result + Arrays.hashCode(myLocationBackgroundPadding); + result = 31 * result + myLocationAccuracyTintColor; + result = 31 * result + myLocationAccuracyAlpha; + result = 31 * result + (apiBaseUrl != null ? apiBaseUrl.hashCode() : 0); + result = 31 * result + (textureMode ? 1 : 0); + result = 31 * result + (style != null ? style.hashCode() : 0); + result = 31 * result + (accessToken != null ? accessToken.hashCode() : 0); + return result; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java index 6189087686..95c0ae5327 100755 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java @@ -35,796 +35,809 @@ import timber.log.Timber; // Class that wraps the native methods for convenience final class NativeMapView { - // Flag to indicating destroy was called - private boolean destroyed = false; + // Flag to indicating destroy was called + private boolean destroyed = false; - // Holds the pointer to JNI NativeMapView - private long nativeMapViewPtr = 0; + // Holds the pointer to JNI NativeMapView + private long nativeMapViewPtr = 0; - // Used for callbacks - private MapView mapView; + // Used for callbacks + private MapView mapView; - // Device density - private final float pixelRatio; + // Device density + private final float pixelRatio; - // Listeners for Map change events - private CopyOnWriteArrayList<MapView.OnMapChangedListener> onMapChangedListeners; + // Listeners for Map change events + private CopyOnWriteArrayList<MapView.OnMapChangedListener> onMapChangedListeners; - // - // Static methods - // + // + // Static methods + // - static { - System.loadLibrary("mapbox-gl"); - } + static { + System.loadLibrary("mapbox-gl"); + } - // - // Constructors - // - - public NativeMapView(MapView mapView) { - Context context = mapView.getContext(); - String dataPath = OfflineManager.getDatabasePath(context); - - // With the availability of offline, we're unifying the ambient (cache) and the offline - // databases to be in the same folder, outside cache, to avoid automatic deletion from - // the system - String cachePath = dataPath; - - pixelRatio = context.getResources().getDisplayMetrics().density; - String apkPath = context.getPackageCodePath(); - int availableProcessors = Runtime.getRuntime().availableProcessors(); - ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); - ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); - activityManager.getMemoryInfo(memoryInfo); - long totalMemory = memoryInfo.availMem; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - totalMemory = memoryInfo.totalMem; - } - - if (availableProcessors < 0) { - throw new IllegalArgumentException("availableProcessors cannot be negative."); - } - - if (totalMemory < 0) { - throw new IllegalArgumentException("totalMemory cannot be negative."); - } - onMapChangedListeners = new CopyOnWriteArrayList<>(); - this.mapView = mapView; - nativeMapViewPtr = nativeCreate(cachePath, dataPath, apkPath, pixelRatio, availableProcessors, totalMemory); - } + // + // Constructors + // - // - // Methods - // + public NativeMapView(MapView mapView) { + Context context = mapView.getContext(); + String dataPath = OfflineManager.getDatabasePath(context); - public void destroy() { - nativeDestroy(nativeMapViewPtr); - nativeMapViewPtr = 0; - mapView = null; - destroyed = true; - } + // With the availability of offline, we're unifying the ambient (cache) and the offline + // databases to be in the same folder, outside cache, to avoid automatic deletion from + // the system + String cachePath = dataPath; - public boolean wasDestroyed() { - return destroyed; + pixelRatio = context.getResources().getDisplayMetrics().density; + String apkPath = context.getPackageCodePath(); + int availableProcessors = Runtime.getRuntime().availableProcessors(); + ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); + ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + activityManager.getMemoryInfo(memoryInfo); + long totalMemory = memoryInfo.availMem; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + totalMemory = memoryInfo.totalMem; } - public void initializeDisplay() { - nativeInitializeDisplay(nativeMapViewPtr); + if (availableProcessors < 0) { + throw new IllegalArgumentException("availableProcessors cannot be negative."); } - public void terminateDisplay() { - nativeTerminateDisplay(nativeMapViewPtr); + if (totalMemory < 0) { + throw new IllegalArgumentException("totalMemory cannot be negative."); } + onMapChangedListeners = new CopyOnWriteArrayList<>(); + this.mapView = mapView; + nativeMapViewPtr = nativeCreate(cachePath, dataPath, apkPath, pixelRatio, availableProcessors, totalMemory); + } - public void initializeContext() { - nativeInitializeContext(nativeMapViewPtr); - } + // + // Methods + // - public void terminateContext() { - nativeTerminateContext(nativeMapViewPtr); - } + public void destroy() { + nativeDestroy(nativeMapViewPtr); + nativeMapViewPtr = 0; + mapView = null; + destroyed = true; + } - public void createSurface(Surface surface) { - nativeCreateSurface(nativeMapViewPtr, surface); - } + public boolean wasDestroyed() { + return destroyed; + } - public void destroySurface() { - nativeDestroySurface(nativeMapViewPtr); - } + public void initializeDisplay() { + nativeInitializeDisplay(nativeMapViewPtr); + } - public void update() { - nativeUpdate(nativeMapViewPtr); - } + public void terminateDisplay() { + nativeTerminateDisplay(nativeMapViewPtr); + } - public void render() { - nativeRender(nativeMapViewPtr); - } + public void initializeContext() { + nativeInitializeContext(nativeMapViewPtr); + } - public void resizeView(int width, int height) { - width = (int) (width / pixelRatio); - height = (int) (height / pixelRatio); - - if (width < 0) { - throw new IllegalArgumentException("width cannot be negative."); - } - - if (height < 0) { - throw new IllegalArgumentException("height cannot be negative."); - } - - if (width > 65535) { - // we have seen edge cases where devices return incorrect values #6111 - Timber.e("Device returned an out of range width size, " + - "capping value at 65535 instead of " + width); - width = 65535; - } - - if (height > 65535) { - // we have seen edge cases where devices return incorrect values #6111 - Timber.e("Device returned an out of range height size, " + - "capping value at 65535 instead of " + height); - height = 65535; - } - nativeViewResize(nativeMapViewPtr, width, height); - } + public void terminateContext() { + nativeTerminateContext(nativeMapViewPtr); + } - public void resizeFramebuffer(int fbWidth, int fbHeight) { - if (fbWidth < 0) { - throw new IllegalArgumentException("fbWidth cannot be negative."); - } - - if (fbHeight < 0) { - throw new IllegalArgumentException("fbHeight cannot be negative."); - } - - if (fbWidth > 65535) { - throw new IllegalArgumentException( - "fbWidth cannot be greater than 65535."); - } - - if (fbHeight > 65535) { - throw new IllegalArgumentException( - "fbHeight cannot be greater than 65535."); - } - nativeFramebufferResize(nativeMapViewPtr, fbWidth, fbHeight); - } + public void createSurface(Surface surface) { + nativeCreateSurface(nativeMapViewPtr, surface); + } - public void addClass(String clazz) { - nativeAddClass(nativeMapViewPtr, clazz); - } + public void destroySurface() { + nativeDestroySurface(nativeMapViewPtr); + } - public void removeClass(String clazz) { - nativeRemoveClass(nativeMapViewPtr, clazz); - } + public void update() { + nativeUpdate(nativeMapViewPtr); + } - public boolean hasClass(String clazz) { - return nativeHasClass(nativeMapViewPtr, clazz); - } + public void render() { + nativeRender(nativeMapViewPtr); + } - public void setClasses(List<String> classes) { - nativeSetClasses(nativeMapViewPtr, classes); - } + public void resizeView(int width, int height) { + width = (int) (width / pixelRatio); + height = (int) (height / pixelRatio); - public List<String> getClasses() { - return nativeGetClasses(nativeMapViewPtr); + if (width < 0) { + throw new IllegalArgumentException("width cannot be negative."); } - public void setStyleUrl(String url) { - nativeSetStyleUrl(nativeMapViewPtr, url); + if (height < 0) { + throw new IllegalArgumentException("height cannot be negative."); } - public String getStyleUrl() { - return nativeGetStyleUrl(nativeMapViewPtr); + if (width > 65535) { + // we have seen edge cases where devices return incorrect values #6111 + Timber.e("Device returned an out of range width size, " + + "capping value at 65535 instead of " + width); + width = 65535; } - public void setStyleJson(String newStyleJson) { - nativeSetStyleJson(nativeMapViewPtr, newStyleJson); + if (height > 65535) { + // we have seen edge cases where devices return incorrect values #6111 + Timber.e("Device returned an out of range height size, " + + "capping value at 65535 instead of " + height); + height = 65535; } + nativeViewResize(nativeMapViewPtr, width, height); + } - public String getStyleJson() { - return nativeGetStyleJson(nativeMapViewPtr); + public void resizeFramebuffer(int fbWidth, int fbHeight) { + if (fbWidth < 0) { + throw new IllegalArgumentException("fbWidth cannot be negative."); } - public void setAccessToken(String accessToken) { - nativeSetAccessToken(nativeMapViewPtr, accessToken); + if (fbHeight < 0) { + throw new IllegalArgumentException("fbHeight cannot be negative."); } - public String getAccessToken() { - return nativeGetAccessToken(nativeMapViewPtr); + if (fbWidth > 65535) { + throw new IllegalArgumentException( + "fbWidth cannot be greater than 65535."); } - public void cancelTransitions() { - nativeCancelTransitions(nativeMapViewPtr); + if (fbHeight > 65535) { + throw new IllegalArgumentException( + "fbHeight cannot be greater than 65535."); } + nativeFramebufferResize(nativeMapViewPtr, fbWidth, fbHeight); + } - public void setGestureInProgress(boolean inProgress) { - nativeSetGestureInProgress(nativeMapViewPtr, inProgress); - } + public void addClass(String clazz) { + nativeAddClass(nativeMapViewPtr, clazz); + } - public void moveBy(double dx, double dy) { - moveBy(dx, dy, 0); - } + public void removeClass(String clazz) { + nativeRemoveClass(nativeMapViewPtr, clazz); + } - public void moveBy(double dx, double dy, long duration) { - nativeMoveBy(nativeMapViewPtr, dx / pixelRatio, dy / pixelRatio, duration); - } + public boolean hasClass(String clazz) { + return nativeHasClass(nativeMapViewPtr, clazz); + } - public void setLatLng(LatLng latLng) { - setLatLng(latLng, 0); - } + public void setClasses(List<String> classes) { + nativeSetClasses(nativeMapViewPtr, classes); + } - public void setLatLng(LatLng latLng, long duration) { - nativeSetLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude(), duration); - } + public List<String> getClasses() { + return nativeGetClasses(nativeMapViewPtr); + } - public LatLng getLatLng() { - return nativeGetLatLng(nativeMapViewPtr); - } + public void setStyleUrl(String url) { + nativeSetStyleUrl(nativeMapViewPtr, url); + } - public void resetPosition() { - nativeResetPosition(nativeMapViewPtr); - } + public String getStyleUrl() { + return nativeGetStyleUrl(nativeMapViewPtr); + } - public double getPitch() { - return nativeGetPitch(nativeMapViewPtr); - } + public void setStyleJson(String newStyleJson) { + nativeSetStyleJson(nativeMapViewPtr, newStyleJson); + } - public void setPitch(double pitch, long duration) { - nativeSetPitch(nativeMapViewPtr, pitch, duration); - } + public String getStyleJson() { + return nativeGetStyleJson(nativeMapViewPtr); + } - public void scaleBy(double ds) { - scaleBy(ds, Double.NaN, Double.NaN); - } + public void setAccessToken(String accessToken) { + nativeSetAccessToken(nativeMapViewPtr, accessToken); + } - public void scaleBy(double ds, double cx, double cy) { - scaleBy(ds, cx, cy, 0); - } + public String getAccessToken() { + return nativeGetAccessToken(nativeMapViewPtr); + } - public void scaleBy(double ds, double cx, double cy, long duration) { - nativeScaleBy(nativeMapViewPtr, ds, cx / pixelRatio, cy / pixelRatio, duration); - } + public void cancelTransitions() { + nativeCancelTransitions(nativeMapViewPtr); + } - public void setScale(double scale) { - setScale(scale, Double.NaN, Double.NaN); - } + public void setGestureInProgress(boolean inProgress) { + nativeSetGestureInProgress(nativeMapViewPtr, inProgress); + } - public void setScale(double scale, double cx, double cy) { - setScale(scale, cx, cy, 0); - } + public void moveBy(double dx, double dy) { + moveBy(dx, dy, 0); + } - public void setScale(double scale, double cx, double cy, long duration) { - nativeSetScale(nativeMapViewPtr, scale, cx / pixelRatio, cy / pixelRatio, duration); - } + public void moveBy(double dx, double dy, long duration) { + nativeMoveBy(nativeMapViewPtr, dx / pixelRatio, dy / pixelRatio, duration); + } - public double getScale() { - return nativeGetScale(nativeMapViewPtr); - } + public void setLatLng(LatLng latLng) { + setLatLng(latLng, 0); + } - public void setZoom(double zoom) { - setZoom(zoom, 0); - } + public void setLatLng(LatLng latLng, long duration) { + nativeSetLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude(), duration); + } - public void setZoom(double zoom, long duration) { - nativeSetZoom(nativeMapViewPtr, zoom, duration); - } + public LatLng getLatLng() { + return nativeGetLatLng(nativeMapViewPtr); + } - public double getZoom() { - return nativeGetZoom(nativeMapViewPtr); - } + public void resetPosition() { + nativeResetPosition(nativeMapViewPtr); + } - public void resetZoom() { - nativeResetZoom(nativeMapViewPtr); - } + public double getPitch() { + return nativeGetPitch(nativeMapViewPtr); + } - public void setMinZoom(double zoom) { - nativeSetMinZoom(nativeMapViewPtr, zoom); - } + public void setPitch(double pitch, long duration) { + nativeSetPitch(nativeMapViewPtr, pitch, duration); + } - public double getMinZoom() { - return nativeGetMinZoom(nativeMapViewPtr); - } + public void scaleBy(double ds) { + scaleBy(ds, Double.NaN, Double.NaN); + } - public void setMaxZoom(double zoom) { - nativeSetMaxZoom(nativeMapViewPtr, zoom); - } + public void scaleBy(double ds, double cx, double cy) { + scaleBy(ds, cx, cy, 0); + } - public double getMaxZoom() { - return nativeGetMaxZoom(nativeMapViewPtr); - } + public void scaleBy(double ds, double cx, double cy, long duration) { + nativeScaleBy(nativeMapViewPtr, ds, cx / pixelRatio, cy / pixelRatio, duration); + } + + public void setScale(double scale) { + setScale(scale, Double.NaN, Double.NaN); + } + + public void setScale(double scale, double cx, double cy) { + setScale(scale, cx, cy, 0); + } + + public void setScale(double scale, double cx, double cy, long duration) { + nativeSetScale(nativeMapViewPtr, scale, cx / pixelRatio, cy / pixelRatio, duration); + } + + public double getScale() { + return nativeGetScale(nativeMapViewPtr); + } + + public void setZoom(double zoom) { + setZoom(zoom, 0); + } + + public void setZoom(double zoom, long duration) { + nativeSetZoom(nativeMapViewPtr, zoom, duration); + } + + public double getZoom() { + return nativeGetZoom(nativeMapViewPtr); + } + + public void resetZoom() { + nativeResetZoom(nativeMapViewPtr); + } + + public void setMinZoom(double zoom) { + nativeSetMinZoom(nativeMapViewPtr, zoom); + } + + public double getMinZoom() { + return nativeGetMinZoom(nativeMapViewPtr); + } + + public void setMaxZoom(double zoom) { + nativeSetMaxZoom(nativeMapViewPtr, zoom); + } + + public double getMaxZoom() { + return nativeGetMaxZoom(nativeMapViewPtr); + } + + public void rotateBy(double sx, double sy, double ex, double ey) { + rotateBy(sx, sy, ex, ey, 0); + } + + public void rotateBy(double sx, double sy, double ex, double ey, + long duration) { + nativeRotateBy(nativeMapViewPtr, sx / pixelRatio, sy / pixelRatio, ex, ey, duration); + } + + public void setContentPadding(int[] padding) { + nativeSetContentPadding(nativeMapViewPtr, + padding[1] / pixelRatio, + padding[0] / pixelRatio, + padding[3] / pixelRatio, + padding[2] / pixelRatio); + } + + public void setBearing(double degrees) { + setBearing(degrees, 0); + } + + public void setBearing(double degrees, long duration) { + nativeSetBearing(nativeMapViewPtr, degrees, duration); + } + + public void setBearing(double degrees, double cx, double cy) { + nativeSetBearingXY(nativeMapViewPtr, degrees, cx / pixelRatio, cy / pixelRatio); + } + + public double getBearing() { + return nativeGetBearing(nativeMapViewPtr); + } + + public void resetNorth() { + nativeResetNorth(nativeMapViewPtr); + } + + public long addMarker(Marker marker) { + Marker[] markers = {marker}; + return nativeAddMarkers(nativeMapViewPtr, markers)[0]; + } + + public long[] addMarkers(List<Marker> markers) { + return nativeAddMarkers(nativeMapViewPtr, markers.toArray(new Marker[markers.size()])); + } + + public long addPolyline(Polyline polyline) { + Polyline[] polylines = {polyline}; + return nativeAddPolylines(nativeMapViewPtr, polylines)[0]; + } + + public long[] addPolylines(List<Polyline> polylines) { + return nativeAddPolylines(nativeMapViewPtr, polylines.toArray(new Polyline[polylines.size()])); + } + + public long addPolygon(Polygon polygon) { + Polygon[] polygons = {polygon}; + return nativeAddPolygons(nativeMapViewPtr, polygons)[0]; + } + + public long[] addPolygons(List<Polygon> polygons) { + return nativeAddPolygons(nativeMapViewPtr, polygons.toArray(new Polygon[polygons.size()])); + } + + public void updateMarker(Marker marker) { + LatLng position = marker.getPosition(); + Icon icon = marker.getIcon(); + nativeUpdateMarker(nativeMapViewPtr, marker.getId(), position.getLatitude(), position.getLongitude(), icon.getId()); + } + + public void updatePolygon(Polygon polygon) { + nativeUpdatePolygon(nativeMapViewPtr, polygon.getId(), polygon); + } + + public void updatePolyline(Polyline polyline) { + nativeUpdatePolyline(nativeMapViewPtr, polyline.getId(), polyline); + } + + public void removeAnnotation(long id) { + long[] ids = {id}; + removeAnnotations(ids); + } + + public void removeAnnotations(long[] ids) { + nativeRemoveAnnotations(nativeMapViewPtr, ids); + } + + public long[] queryPointAnnotations(RectF rect) { + return nativeQueryPointAnnotations(nativeMapViewPtr, rect); + } + + public void addAnnotationIcon(String symbol, int width, int height, float scale, byte[] pixels) { + nativeAddAnnotationIcon(nativeMapViewPtr, symbol, width, height, scale, pixels); + } + + public void setVisibleCoordinateBounds(LatLng[] coordinates, RectF padding, double direction, long duration) { + nativeSetVisibleCoordinateBounds(nativeMapViewPtr, coordinates, padding, direction, duration); + } + + public void onLowMemory() { + nativeOnLowMemory(nativeMapViewPtr); + } + + public void setDebug(boolean debug) { + nativeSetDebug(nativeMapViewPtr, debug); + } + + public void cycleDebugOptions() { + nativeToggleDebug(nativeMapViewPtr); + } + + public boolean getDebug() { + return nativeGetDebug(nativeMapViewPtr); + } + + public boolean isFullyLoaded() { + return nativeIsFullyLoaded(nativeMapViewPtr); + } + + public void setReachability(boolean status) { + nativeSetReachability(nativeMapViewPtr, status); + } + + public double getMetersPerPixelAtLatitude(double lat) { + return nativeGetMetersPerPixelAtLatitude(nativeMapViewPtr, lat, getZoom()); + } + + public ProjectedMeters projectedMetersForLatLng(LatLng latLng) { + return nativeProjectedMetersForLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude()); + } + + public LatLng latLngForProjectedMeters(ProjectedMeters projectedMeters) { + return nativeLatLngForProjectedMeters(nativeMapViewPtr, projectedMeters.getNorthing(), + projectedMeters.getEasting()); + } + + public PointF pixelForLatLng(LatLng latLng) { + PointF pointF = nativePixelForLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude()); + pointF.set(pointF.x * pixelRatio, pointF.y * pixelRatio); + return pointF; + } + + public LatLng latLngForPixel(PointF pixel) { + return nativeLatLngForPixel(nativeMapViewPtr, pixel.x / pixelRatio, pixel.y / pixelRatio); + } + + public double getTopOffsetPixelsForAnnotationSymbol(String symbolName) { + return nativeGetTopOffsetPixelsForAnnotationSymbol(nativeMapViewPtr, symbolName); + } + + public void jumpTo(double angle, LatLng center, double pitch, double zoom) { + nativeJumpTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), pitch, zoom); + } + + public void easeTo(double angle, LatLng center, long duration, double pitch, double zoom, + boolean easingInterpolator) { + nativeEaseTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), duration, pitch, zoom, + easingInterpolator); + } + + public void flyTo(double angle, LatLng center, long duration, double pitch, double zoom) { + nativeFlyTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), duration, pitch, zoom); + } + + public double[] getCameraValues() { + return nativeGetCameraValues(nativeMapViewPtr); + } + + // Runtime style Api + + public Layer getLayer(String layerId) { + return nativeGetLayer(nativeMapViewPtr, layerId); + } + + public void addLayer(@NonNull Layer layer, @Nullable String before) { + nativeAddLayer(nativeMapViewPtr, layer.getNativePtr(), before); + } + + public void removeLayer(@NonNull String layerId) throws NoSuchLayerException { + nativeRemoveLayerById(nativeMapViewPtr, layerId); + } + + public void removeLayer(@NonNull Layer layer) throws NoSuchLayerException { + nativeRemoveLayer(nativeMapViewPtr, layer.getNativePtr()); + } + + public Source getSource(@NonNull String sourceId) { + return nativeGetSource(nativeMapViewPtr, sourceId); + } + + public void addSource(@NonNull Source source) { + nativeAddSource(nativeMapViewPtr, source.getNativePtr()); + } - public void rotateBy(double sx, double sy, double ex, double ey) { - rotateBy(sx, sy, ex, ey, 0); - } + public void removeSource(@NonNull String sourceId) throws NoSuchSourceException { + nativeRemoveSourceById(nativeMapViewPtr, sourceId); + } - public void rotateBy(double sx, double sy, double ex, double ey, - long duration) { - nativeRotateBy(nativeMapViewPtr, sx/pixelRatio, sy/pixelRatio, ex, ey, duration); - } + public void removeSource(@NonNull Source source) throws NoSuchSourceException { + nativeRemoveSource(nativeMapViewPtr, source.getNativePtr()); + } - public void setContentPadding(int[] padding) { - nativeSetContentPadding(nativeMapViewPtr, - padding[1] / pixelRatio, - padding[0] / pixelRatio, - padding[3] / pixelRatio, - padding[2] / pixelRatio); + public void addImage(@NonNull String name, @NonNull Bitmap image) { + //Check/correct config + if (image.getConfig() != Bitmap.Config.ARGB_8888) { + image = image.copy(Bitmap.Config.ARGB_8888, false); } - public void setBearing(double degrees) { - setBearing(degrees, 0); - } + //Get pixels + ByteBuffer buffer = ByteBuffer.allocate(image.getByteCount()); + image.copyPixelsToBuffer(buffer); - public void setBearing(double degrees, long duration) { - nativeSetBearing(nativeMapViewPtr, degrees, duration); - } + //Determine pixel ratio + float density = image.getDensity() == Bitmap.DENSITY_NONE ? Bitmap.DENSITY_NONE : image.getDensity(); + float pixelRatio = density / DisplayMetrics.DENSITY_DEFAULT; - public void setBearing(double degrees, double cx, double cy) { - nativeSetBearingXY(nativeMapViewPtr, degrees, cx/pixelRatio, cy/pixelRatio); - } + nativeAddImage(nativeMapViewPtr, name, image.getWidth(), image.getHeight(), pixelRatio, buffer.array()); + } - public double getBearing() { - return nativeGetBearing(nativeMapViewPtr); - } + public void removeImage(String name) { + nativeRemoveImage(nativeMapViewPtr, name); + } - public void resetNorth() { - nativeResetNorth(nativeMapViewPtr); - } + // Feature querying - public long addMarker(Marker marker) { - Marker[] markers = {marker}; - return nativeAddMarkers(nativeMapViewPtr, markers)[0]; - } + @NonNull + public List<Feature> queryRenderedFeatures(PointF coordinates, String... layerIds) { + Feature[] features = nativeQueryRenderedFeaturesForPoint(nativeMapViewPtr, coordinates.x / pixelRatio, + coordinates.y / pixelRatio, layerIds); + return features != null ? Arrays.asList(features) : new ArrayList<Feature>(); + } - public long[] addMarkers(List<Marker> markers) { - return nativeAddMarkers(nativeMapViewPtr, markers.toArray(new Marker[markers.size()])); - } + @NonNull + public List<Feature> queryRenderedFeatures(RectF coordinates, String... layerIds) { + Feature[] features = nativeQueryRenderedFeaturesForBox( + nativeMapViewPtr, + coordinates.left / pixelRatio, + coordinates.top / pixelRatio, + coordinates.right / pixelRatio, + coordinates.bottom / pixelRatio, + layerIds); + return features != null ? Arrays.asList(features) : new ArrayList<Feature>(); + } - public long addPolyline(Polyline polyline) { - Polyline[] polylines = {polyline}; - return nativeAddPolylines(nativeMapViewPtr, polylines)[0]; - } + public void scheduleTakeSnapshot() { + nativeScheduleTakeSnapshot(nativeMapViewPtr); + } - public long[] addPolylines(List<Polyline> polylines) { - return nativeAddPolylines(nativeMapViewPtr, polylines.toArray(new Polyline[polylines.size()])); - } + public void setApiBaseUrl(String baseUrl) { + nativeSetAPIBaseURL(nativeMapViewPtr, baseUrl); + } - public long addPolygon(Polygon polygon) { - Polygon[] polygons = {polygon}; - return nativeAddPolygons(nativeMapViewPtr, polygons)[0]; - } + public float getPixelRatio() { + return pixelRatio; + } - public long[] addPolygons(List<Polygon> polygons) { - return nativeAddPolygons(nativeMapViewPtr, polygons.toArray(new Polygon[polygons.size()])); - } + public Context getContext() { + return mapView.getContext(); + } - public void updateMarker(Marker marker) { - LatLng position = marker.getPosition(); - Icon icon = marker.getIcon(); - nativeUpdateMarker(nativeMapViewPtr, marker.getId(), position.getLatitude(), position.getLongitude(), icon.getId()); - } + // + // Callbacks + // - public void updatePolygon(Polygon polygon) { - nativeUpdatePolygon(nativeMapViewPtr, polygon.getId(), polygon); - } + protected void onInvalidate() { + mapView.onInvalidate(); + } - public void updatePolyline(Polyline polyline) { - nativeUpdatePolyline(nativeMapViewPtr, polyline.getId(), polyline); - } + protected void onMapChanged(int rawChange) { + mapView.onMapChanged(rawChange); + } - public void removeAnnotation(long id) { - long[] ids = {id}; - removeAnnotations(ids); - } + protected void onFpsChanged(double fps) { + mapView.onFpsChanged(fps); + } - public void removeAnnotations(long[] ids) { - nativeRemoveAnnotations(nativeMapViewPtr, ids); - } + protected void onSnapshotReady(byte[] bytes) { + mapView.onSnapshotReady(bytes); + } - public long[] queryPointAnnotations(RectF rect) { - return nativeQueryPointAnnotations(nativeMapViewPtr, rect); - } + // + // JNI methods + // - public void addAnnotationIcon(String symbol, int width, int height, float scale, byte[] pixels) { - nativeAddAnnotationIcon(nativeMapViewPtr, symbol, width, height, scale, pixels); - } + private native long nativeCreate(String cachePath, String dataPath, String apkPath, float pixelRatio, + int availableProcessors, long totalMemory); - public void setVisibleCoordinateBounds(LatLng[] coordinates, RectF padding, double direction, long duration) { - nativeSetVisibleCoordinateBounds(nativeMapViewPtr, coordinates, padding, direction, duration); - } + private native void nativeDestroy(long nativeMapViewPtr); - public void onLowMemory() { - nativeOnLowMemory(nativeMapViewPtr); - } + private native void nativeInitializeDisplay(long nativeMapViewPtr); - public void setDebug(boolean debug) { - nativeSetDebug(nativeMapViewPtr, debug); - } + private native void nativeTerminateDisplay(long nativeMapViewPtr); - public void cycleDebugOptions() { - nativeToggleDebug(nativeMapViewPtr); - } + private native void nativeInitializeContext(long nativeMapViewPtr); - public boolean getDebug() { - return nativeGetDebug(nativeMapViewPtr); - } + private native void nativeTerminateContext(long nativeMapViewPtr); - public boolean isFullyLoaded() { - return nativeIsFullyLoaded(nativeMapViewPtr); - } + private native void nativeCreateSurface(long nativeMapViewPtr, + Surface surface); - public void setReachability(boolean status) { - nativeSetReachability(nativeMapViewPtr, status); - } + private native void nativeDestroySurface(long nativeMapViewPtr); - public double getMetersPerPixelAtLatitude(double lat) { - return nativeGetMetersPerPixelAtLatitude(nativeMapViewPtr, lat, getZoom()); - } + private native void nativeUpdate(long nativeMapViewPtr); - public ProjectedMeters projectedMetersForLatLng(LatLng latLng) { - return nativeProjectedMetersForLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude()); - } + private native void nativeRender(long nativeMapViewPtr); - public LatLng latLngForProjectedMeters(ProjectedMeters projectedMeters) { - return nativeLatLngForProjectedMeters(nativeMapViewPtr, projectedMeters.getNorthing(), projectedMeters.getEasting()); - } + private native void nativeViewResize(long nativeMapViewPtr, int width, int height); - public PointF pixelForLatLng(LatLng latLng) { - PointF pointF = nativePixelForLatLng(nativeMapViewPtr, latLng.getLatitude(), latLng.getLongitude()); - pointF.set(pointF.x * pixelRatio, pointF.y * pixelRatio); - return pointF; - } + private native void nativeFramebufferResize(long nativeMapViewPtr, int fbWidth, int fbHeight); - public LatLng latLngForPixel(PointF pixel) { - return nativeLatLngForPixel(nativeMapViewPtr, pixel.x / pixelRatio, pixel.y / pixelRatio); - } + private native void nativeAddClass(long nativeMapViewPtr, String clazz); - public double getTopOffsetPixelsForAnnotationSymbol(String symbolName) { - return nativeGetTopOffsetPixelsForAnnotationSymbol(nativeMapViewPtr, symbolName); - } + private native void nativeRemoveClass(long nativeMapViewPtr, String clazz); - public void jumpTo(double angle, LatLng center, double pitch, double zoom) { - nativeJumpTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), pitch, zoom); - } + private native boolean nativeHasClass(long nativeMapViewPtr, String clazz); - public void easeTo(double angle, LatLng center, long duration, double pitch, double zoom, boolean easingInterpolator) { - nativeEaseTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), duration, pitch, zoom, easingInterpolator); - } + private native void nativeSetClasses(long nativeMapViewPtr, + List<String> classes); - public void flyTo(double angle, LatLng center, long duration, double pitch, double zoom) { - nativeFlyTo(nativeMapViewPtr, angle, center.getLatitude(), center.getLongitude(), duration, pitch, zoom); - } + private native List<String> nativeGetClasses(long nativeMapViewPtr); - public double[] getCameraValues() { - return nativeGetCameraValues(nativeMapViewPtr); - } + private native void nativeSetStyleUrl(long nativeMapViewPtr, String url); - // Runtime style Api + private native String nativeGetStyleUrl(long nativeMapViewPtr); - public Layer getLayer(String layerId) { - return nativeGetLayer(nativeMapViewPtr, layerId); - } - - public void addLayer(@NonNull Layer layer, @Nullable String before) { - nativeAddLayer(nativeMapViewPtr, layer.getNativePtr(), before); - } + private native void nativeSetStyleJson(long nativeMapViewPtr, String newStyleJson); - public void removeLayer(@NonNull String layerId) throws NoSuchLayerException { - nativeRemoveLayerById(nativeMapViewPtr, layerId); - } + private native String nativeGetStyleJson(long nativeMapViewPtr); - public void removeLayer(@NonNull Layer layer) throws NoSuchLayerException { - nativeRemoveLayer(nativeMapViewPtr, layer.getNativePtr()); - } + private native void nativeSetAccessToken(long nativeMapViewPtr, String accessToken); - public Source getSource(@NonNull String sourceId) { - return nativeGetSource(nativeMapViewPtr, sourceId); - } + private native String nativeGetAccessToken(long nativeMapViewPtr); - public void addSource(@NonNull Source source) { - nativeAddSource(nativeMapViewPtr, source.getNativePtr()); - } + private native void nativeCancelTransitions(long nativeMapViewPtr); - public void removeSource(@NonNull String sourceId) throws NoSuchSourceException { - nativeRemoveSourceById(nativeMapViewPtr, sourceId); - } - - public void removeSource(@NonNull Source source) throws NoSuchSourceException { - nativeRemoveSource(nativeMapViewPtr, source.getNativePtr()); - } - - public void addImage(@NonNull String name, @NonNull Bitmap image) { - //Check/correct config - if (image.getConfig() != Bitmap.Config.ARGB_8888) { - image = image.copy(Bitmap.Config.ARGB_8888, false); - } - - //Get pixels - ByteBuffer buffer = ByteBuffer.allocate(image.getByteCount()); - image.copyPixelsToBuffer(buffer); - - //Determine pixel ratio - float density = image.getDensity() == Bitmap.DENSITY_NONE ? Bitmap.DENSITY_NONE : image.getDensity(); - float pixelRatio = density / DisplayMetrics.DENSITY_DEFAULT; - - nativeAddImage(nativeMapViewPtr, name, image.getWidth(), image.getHeight(), pixelRatio, buffer.array()); - } - - public void removeImage(String name) { - nativeRemoveImage(nativeMapViewPtr, name); - } + private native void nativeSetGestureInProgress(long nativeMapViewPtr, boolean inProgress); - // Feature querying + private native void nativeMoveBy(long nativeMapViewPtr, double dx, + double dy, long duration); - @NonNull - public List<Feature> queryRenderedFeatures(PointF coordinates, String... layerIds) { - Feature[] features = nativeQueryRenderedFeaturesForPoint(nativeMapViewPtr, coordinates.x / pixelRatio, coordinates.y / pixelRatio, layerIds); - return features != null ? Arrays.asList(features) : new ArrayList<Feature>(); - } - - @NonNull - public List<Feature> queryRenderedFeatures(RectF coordinates, String... layerIds) { - Feature[] features = nativeQueryRenderedFeaturesForBox( - nativeMapViewPtr, - coordinates.left / pixelRatio, - coordinates.top / pixelRatio, - coordinates.right / pixelRatio, - coordinates.bottom / pixelRatio, - layerIds); - return features != null ? Arrays.asList(features) : new ArrayList<Feature>(); - } - - public void scheduleTakeSnapshot() { - nativeScheduleTakeSnapshot(nativeMapViewPtr); - } - - public void setApiBaseUrl(String baseUrl) { - nativeSetAPIBaseURL(nativeMapViewPtr, baseUrl); - } - - public float getPixelRatio() { - return pixelRatio; - } - - public Context getContext() { - return mapView.getContext(); - } - - // - // Callbacks - // - - protected void onInvalidate() { - mapView.onInvalidate(); - } - - protected void onMapChanged(int rawChange) { - mapView.onMapChanged(rawChange); - } - - protected void onFpsChanged(double fps) { - mapView.onFpsChanged(fps); - } - - protected void onSnapshotReady(byte[] bytes) { - mapView.onSnapshotReady(bytes); - } - - // - // JNI methods - // - - private native long nativeCreate(String cachePath, String dataPath, String apkPath, float pixelRatio, int availableProcessors, long totalMemory); - - private native void nativeDestroy(long nativeMapViewPtr); - - private native void nativeInitializeDisplay(long nativeMapViewPtr); - - private native void nativeTerminateDisplay(long nativeMapViewPtr); - - private native void nativeInitializeContext(long nativeMapViewPtr); - - private native void nativeTerminateContext(long nativeMapViewPtr); - - private native void nativeCreateSurface(long nativeMapViewPtr, - Surface surface); - - private native void nativeDestroySurface(long nativeMapViewPtr); - - private native void nativeUpdate(long nativeMapViewPtr); - - private native void nativeRender(long nativeMapViewPtr); - - private native void nativeViewResize(long nativeMapViewPtr, int width, int height); - - private native void nativeFramebufferResize(long nativeMapViewPtr, int fbWidth, int fbHeight); - - private native void nativeAddClass(long nativeMapViewPtr, String clazz); - - private native void nativeRemoveClass(long nativeMapViewPtr, String clazz); - - private native boolean nativeHasClass(long nativeMapViewPtr, String clazz); - - private native void nativeSetClasses(long nativeMapViewPtr, - List<String> classes); - - private native List<String> nativeGetClasses(long nativeMapViewPtr); - - private native void nativeSetStyleUrl(long nativeMapViewPtr, String url); - - private native String nativeGetStyleUrl(long nativeMapViewPtr); - - private native void nativeSetStyleJson(long nativeMapViewPtr, String newStyleJson); - - private native String nativeGetStyleJson(long nativeMapViewPtr); - - private native void nativeSetAccessToken(long nativeMapViewPtr, String accessToken); - - private native String nativeGetAccessToken(long nativeMapViewPtr); - - private native void nativeCancelTransitions(long nativeMapViewPtr); + private native void nativeSetLatLng(long nativeMapViewPtr, double latitude, double longitude, + long duration); - private native void nativeSetGestureInProgress(long nativeMapViewPtr, boolean inProgress); + private native LatLng nativeGetLatLng(long nativeMapViewPtr); - private native void nativeMoveBy(long nativeMapViewPtr, double dx, - double dy, long duration); + private native void nativeResetPosition(long nativeMapViewPtr); - private native void nativeSetLatLng(long nativeMapViewPtr, double latitude, double longitude, - long duration); + private native double nativeGetPitch(long nativeMapViewPtr); - private native LatLng nativeGetLatLng(long nativeMapViewPtr); + private native void nativeSetPitch(long nativeMapViewPtr, double pitch, long duration); - private native void nativeResetPosition(long nativeMapViewPtr); + private native void nativeScaleBy(long nativeMapViewPtr, double ds, + double cx, double cy, long duration); - private native double nativeGetPitch(long nativeMapViewPtr); + private native void nativeSetScale(long nativeMapViewPtr, double scale, + double cx, double cy, long duration); - private native void nativeSetPitch(long nativeMapViewPtr, double pitch, long duration); + private native double nativeGetScale(long nativeMapViewPtr); - private native void nativeScaleBy(long nativeMapViewPtr, double ds, - double cx, double cy, long duration); + private native void nativeSetZoom(long nativeMapViewPtr, double zoom, + long duration); - private native void nativeSetScale(long nativeMapViewPtr, double scale, - double cx, double cy, long duration); + private native double nativeGetZoom(long nativeMapViewPtr); - private native double nativeGetScale(long nativeMapViewPtr); + private native void nativeResetZoom(long nativeMapViewPtr); - private native void nativeSetZoom(long nativeMapViewPtr, double zoom, - long duration); + private native void nativeSetMinZoom(long nativeMapViewPtr, double zoom); - private native double nativeGetZoom(long nativeMapViewPtr); + private native double nativeGetMinZoom(long nativeMapViewPtr); - private native void nativeResetZoom(long nativeMapViewPtr); + private native void nativeSetMaxZoom(long nativeMapViewPtr, double zoom); - private native void nativeSetMinZoom(long nativeMapViewPtr, double zoom); + private native double nativeGetMaxZoom(long nativeMapViewPtr); - private native double nativeGetMinZoom(long nativeMapViewPtr); + private native void nativeRotateBy(long nativeMapViewPtr, double sx, + double sy, double ex, double ey, long duration); - private native void nativeSetMaxZoom(long nativeMapViewPtr, double zoom); + private native void nativeSetContentPadding(long nativeMapViewPtr, double top, double left, double bottom, + double right); - private native double nativeGetMaxZoom(long nativeMapViewPtr); + private native void nativeSetBearing(long nativeMapViewPtr, double degrees, + long duration); - private native void nativeRotateBy(long nativeMapViewPtr, double sx, - double sy, double ex, double ey, long duration); + private native void nativeSetBearingXY(long nativeMapViewPtr, double degrees, + double cx, double cy); - private native void nativeSetContentPadding(long nativeMapViewPtr, double top, double left, double bottom, double right); + private native double nativeGetBearing(long nativeMapViewPtr); - private native void nativeSetBearing(long nativeMapViewPtr, double degrees, - long duration); + private native void nativeResetNorth(long nativeMapViewPtr); - private native void nativeSetBearingXY(long nativeMapViewPtr, double degrees, - double cx, double cy); + private native void nativeUpdateMarker(long nativeMapViewPtr, long markerId, double lat, double lon, String iconId); - private native double nativeGetBearing(long nativeMapViewPtr); + private native long[] nativeAddMarkers(long nativeMapViewPtr, Marker[] markers); - private native void nativeResetNorth(long nativeMapViewPtr); + private native long[] nativeAddPolylines(long nativeMapViewPtr, Polyline[] polylines); - private native void nativeUpdateMarker(long nativeMapViewPtr, long markerId, double lat, double lon, String iconId); + private native long[] nativeAddPolygons(long nativeMapViewPtr, Polygon[] polygons); - private native long[] nativeAddMarkers(long nativeMapViewPtr, Marker[] markers); + private native void nativeRemoveAnnotations(long nativeMapViewPtr, long[] id); - private native long[] nativeAddPolylines(long nativeMapViewPtr, Polyline[] polylines); + private native long[] nativeQueryPointAnnotations(long nativeMapViewPtr, RectF rect); - private native long[] nativeAddPolygons(long nativeMapViewPtr, Polygon[] polygons); + private native void nativeAddAnnotationIcon(long nativeMapViewPtr, String symbol, + int width, int height, float scale, byte[] pixels); - private native void nativeRemoveAnnotations(long nativeMapViewPtr, long[] id); + private native void nativeSetVisibleCoordinateBounds(long nativeMapViewPtr, LatLng[] coordinates, + RectF padding, double direction, long duration); - private native long[] nativeQueryPointAnnotations(long nativeMapViewPtr, RectF rect); + private native void nativeOnLowMemory(long nativeMapViewPtr); - private native void nativeAddAnnotationIcon(long nativeMapViewPtr, String symbol, - int width, int height, float scale, byte[] pixels); + private native void nativeSetDebug(long nativeMapViewPtr, boolean debug); - private native void nativeSetVisibleCoordinateBounds(long nativeMapViewPtr, LatLng[] coordinates, - RectF padding, double direction, long duration); + private native void nativeToggleDebug(long nativeMapViewPtr); - private native void nativeOnLowMemory(long nativeMapViewPtr); + private native boolean nativeGetDebug(long nativeMapViewPtr); - private native void nativeSetDebug(long nativeMapViewPtr, boolean debug); + private native boolean nativeIsFullyLoaded(long nativeMapViewPtr); - private native void nativeToggleDebug(long nativeMapViewPtr); + private native void nativeSetReachability(long nativeMapViewPtr, boolean status); - private native boolean nativeGetDebug(long nativeMapViewPtr); + private native double nativeGetMetersPerPixelAtLatitude(long nativeMapViewPtr, double lat, double zoom); - private native boolean nativeIsFullyLoaded(long nativeMapViewPtr); + private native ProjectedMeters nativeProjectedMetersForLatLng(long nativeMapViewPtr, double latitude, + double longitude); - private native void nativeSetReachability(long nativeMapViewPtr, boolean status); + private native LatLng nativeLatLngForProjectedMeters(long nativeMapViewPtr, double northing, double easting); - private native double nativeGetMetersPerPixelAtLatitude(long nativeMapViewPtr, double lat, double zoom); + private native PointF nativePixelForLatLng(long nativeMapViewPtr, double lat, double lon); - private native ProjectedMeters nativeProjectedMetersForLatLng(long nativeMapViewPtr, double latitude, double longitude); + private native LatLng nativeLatLngForPixel(long nativeMapViewPtr, float x, float y); - private native LatLng nativeLatLngForProjectedMeters(long nativeMapViewPtr, double northing, double easting); + private native double nativeGetTopOffsetPixelsForAnnotationSymbol(long nativeMapViewPtr, String symbolName); - private native PointF nativePixelForLatLng(long nativeMapViewPtr, double lat, double lon); + private native void nativeJumpTo(long nativeMapViewPtr, double angle, double latitude, double longitude, + double pitch, double zoom); - private native LatLng nativeLatLngForPixel(long nativeMapViewPtr, float x, float y); + private native void nativeEaseTo(long nativeMapViewPtr, double angle, double latitude, double longitude, + long duration, double pitch, double zoom, boolean easingInterpolator); - private native double nativeGetTopOffsetPixelsForAnnotationSymbol(long nativeMapViewPtr, String symbolName); + private native void nativeFlyTo(long nativeMapViewPtr, double angle, double latitude, double longitude, + long duration, double pitch, double zoom); - private native void nativeJumpTo(long nativeMapViewPtr, double angle, double latitude, double longitude, double pitch, double zoom); + private native double[] nativeGetCameraValues(long nativeMapViewPtr); - private native void nativeEaseTo(long nativeMapViewPtr, double angle, double latitude, double longitude, long duration, double pitch, double zoom, boolean easingInterpolator); + private native Layer nativeGetLayer(long nativeMapViewPtr, String layerId); - private native void nativeFlyTo(long nativeMapViewPtr, double angle, double latitude, double longitude, long duration, double pitch, double zoom); + private native void nativeAddLayer(long nativeMapViewPtr, long layerPtr, String before); - private native double[] nativeGetCameraValues(long nativeMapViewPtr); + private native void nativeRemoveLayerById(long nativeMapViewPtr, String layerId) throws NoSuchLayerException; - private native Layer nativeGetLayer(long nativeMapViewPtr, String layerId); + private native void nativeRemoveLayer(long nativeMapViewPtr, long layerId) throws NoSuchLayerException; - private native void nativeAddLayer(long nativeMapViewPtr, long layerPtr, String before); + private native Source nativeGetSource(long nativeMapViewPtr, String sourceId); - private native void nativeRemoveLayerById(long nativeMapViewPtr, String layerId) throws NoSuchLayerException; + private native void nativeAddSource(long nativeMapViewPtr, long nativeSourcePtr); - private native void nativeRemoveLayer(long nativeMapViewPtr, long layerId) throws NoSuchLayerException; + private native void nativeRemoveSourceById(long nativeMapViewPtr, String sourceId) throws NoSuchSourceException; - private native Source nativeGetSource(long nativeMapViewPtr, String sourceId); + private native void nativeRemoveSource(long nativeMapViewPtr, long sourcePtr) throws NoSuchSourceException; - private native void nativeAddSource(long nativeMapViewPtr, long nativeSourcePtr); + private native void nativeAddImage(long nativeMapViewPtr, String name, int width, int height, float pixelRatio, + byte[] array); - private native void nativeRemoveSourceById(long nativeMapViewPtr, String sourceId) throws NoSuchSourceException; + private native void nativeRemoveImage(long nativeMapViewPtr, String name); - private native void nativeRemoveSource(long nativeMapViewPtr, long sourcePtr) throws NoSuchSourceException; + private native void nativeUpdatePolygon(long nativeMapViewPtr, long polygonId, Polygon polygon); - private native void nativeAddImage(long nativeMapViewPtr, String name, int width, int height, float pixelRatio, byte[] array); + private native void nativeUpdatePolyline(long nativeMapviewPtr, long polylineId, Polyline polyline); - private native void nativeRemoveImage(long nativeMapViewPtr, String name); + private native void nativeScheduleTakeSnapshot(long nativeMapViewPtr); - private native void nativeUpdatePolygon(long nativeMapViewPtr, long polygonId, Polygon polygon); + private native Feature[] nativeQueryRenderedFeaturesForPoint(long nativeMapViewPtr, float x, float y, String[] + layerIds); - private native void nativeUpdatePolyline(long nativeMapviewPtr, long polylineId, Polyline polyline); + private native Feature[] nativeQueryRenderedFeaturesForBox(long nativeMapViewPtr, float left, float top, float right, + float bottom, String[] layerIds); - private native void nativeScheduleTakeSnapshot(long nativeMapViewPtr); + private native void nativeSetAPIBaseURL(long nativeMapViewPtr, String baseUrl); - private native Feature[] nativeQueryRenderedFeaturesForPoint(long nativeMapViewPtr, float x, float y, String[] layerIds); + int getWidth() { + return mapView.getWidth(); + } - private native Feature[] nativeQueryRenderedFeaturesForBox(long nativeMapViewPtr, float left, float top, float right, float bottom, String[] layerIds); + int getHeight() { + return mapView.getHeight(); + } - private native void nativeSetAPIBaseURL(long nativeMapViewPtr, String baseUrl); + // + // MapChangeEvents + // - int getWidth() { - return mapView.getWidth(); - } - - int getHeight() { - return mapView.getHeight(); - } + void addOnMapChangedListener(@NonNull MapView.OnMapChangedListener listener) { + onMapChangedListeners.add(listener); + } - // - // MapChangeEvents - // - - void addOnMapChangedListener(@NonNull MapView.OnMapChangedListener listener) { - onMapChangedListeners.add(listener); - } - - void removeOnMapChangedListener(@NonNull MapView.OnMapChangedListener listener) { - onMapChangedListeners.remove(listener); - } + void removeOnMapChangedListener(@NonNull MapView.OnMapChangedListener listener) { + onMapChangedListeners.remove(listener); + } - void onMapChangedEventDispatch(int mapChange) { - if (onMapChangedListeners != null) { - for (MapView.OnMapChangedListener onMapChangedListener : onMapChangedListeners) { - onMapChangedListener.onMapChanged(mapChange); - } - } + void onMapChangedEventDispatch(int mapChange) { + if (onMapChangedListeners != null) { + for (MapView.OnMapChangedListener onMapChangedListener : onMapChangedListeners) { + onMapChangedListener.onMapChanged(mapChange); + } } + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/OnMapReadyCallback.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/OnMapReadyCallback.java index 7ace9ec2d3..fc92e5028b 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/OnMapReadyCallback.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/OnMapReadyCallback.java @@ -4,16 +4,17 @@ package com.mapbox.mapboxsdk.maps; * Interface definition for a callback to be invoked when the map is ready to be used. * <p> * Once an instance of this interface is set on a {@link MapFragment} or {@link MapView} object, - * the onMapReady(MapboxMap) method is triggered when the map is ready to be used and provides an instance of {@link MapboxMap}. + * the onMapReady(MapboxMap) method is triggered when the map is ready to be used and provides an instance of + * {@link MapboxMap}. * </p> */ public interface OnMapReadyCallback { - /** - * Called when the map is ready to be used. - * - * @param mapboxMap An instance of MapboxMap associated with the {@link MapFragment} or - * {@link MapView} that defines the callback. - */ - void onMapReady(MapboxMap mapboxMap); + /** + * Called when the map is ready to be used. + * + * @param mapboxMap An instance of MapboxMap associated with the {@link MapFragment} or + * {@link MapView} that defines the callback. + */ + void onMapReady(MapboxMap mapboxMap); } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java index 5a28d0c7a0..b7f93cc913 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java @@ -7,7 +7,6 @@ import android.support.annotation.NonNull; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLngBounds; import com.mapbox.mapboxsdk.geometry.VisibleRegion; -import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings; /** * A projection is used to translate between on screen location and geographic coordinates on @@ -16,106 +15,106 @@ import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings; */ public class Projection { - private final NativeMapView nativeMapView; - private int[] contentPadding; - - Projection(@NonNull NativeMapView nativeMapView) { - this.nativeMapView = nativeMapView; - this.contentPadding = new int[]{0, 0, 0, 0}; - } - - void setContentPadding(int[] contentPadding, int[] userLocationViewPadding) { - this.contentPadding = contentPadding; - - int[] padding = new int[]{ - contentPadding[0] + userLocationViewPadding[0], - contentPadding[1] + userLocationViewPadding[1], - contentPadding[2] + userLocationViewPadding[2], - contentPadding[3] + userLocationViewPadding[3] - }; - - nativeMapView.setContentPadding(padding); - } - - int[] getContentPadding() { - return contentPadding; - } - - public void invalidateContentPadding(int[] userLocationViewPadding) { - setContentPadding(contentPadding, userLocationViewPadding); - } - - /** - * <p> - * Returns the distance spanned by one pixel at the specified latitude and current zoom level. - * </p> - * The distance between pixels decreases as the latitude approaches the poles. - * This relationship parallels the relationship between longitudinal coordinates at different latitudes. - * - * @param latitude The latitude for which to return the value. - * @return The distance measured in meters. - */ - public double getMetersPerPixelAtLatitude(@FloatRange(from = -90, to = 90) double latitude) { - return nativeMapView.getMetersPerPixelAtLatitude(latitude); - } - - /** - * Returns the geographic location that corresponds to a screen location. - * The screen location is specified in screen pixels (not display pixels) relative to the - * top left of the map (not the top left of the whole screen). - * - * @param point A Point on the screen in screen pixels. - * @return The LatLng corresponding to the point on the screen, or null if the ray through - * the given screen point does not intersect the ground plane. - */ - public LatLng fromScreenLocation(PointF point) { - return nativeMapView.latLngForPixel(point); - } - - /** - * Gets a projection of the viewing frustum for converting between screen coordinates and - * geo-latitude/longitude coordinates. - * - * @return The projection of the viewing frustum in its current state. - */ - public VisibleRegion getVisibleRegion() { - LatLngBounds.Builder builder = new LatLngBounds.Builder(); - - float left = contentPadding[0]; - float right = nativeMapView.getWidth() - contentPadding[2]; - float top = contentPadding[1]; - float bottom = nativeMapView.getHeight() - contentPadding[3]; - - LatLng topLeft = fromScreenLocation(new PointF(left, top)); - LatLng topRight = fromScreenLocation(new PointF(right, top)); - LatLng bottomRight = fromScreenLocation(new PointF(right, bottom)); - LatLng bottomLeft = fromScreenLocation(new PointF(left, bottom)); - - builder.include(topLeft) - .include(topRight) - .include(bottomRight) - .include(bottomLeft); - - return new VisibleRegion(topLeft, topRight, bottomLeft, bottomRight, builder.build()); - } - - /** - * Returns a screen location that corresponds to a geographical coordinate (LatLng). - * The screen location is in screen pixels (not display pixels) relative to the top left - * of the map (not of the whole screen). - * - * @param location A LatLng on the map to convert to a screen location. - * @return A Point representing the screen location in screen pixels. - */ - public PointF toScreenLocation(LatLng location) { - return nativeMapView.pixelForLatLng(location); - } - - float getHeight() { - return nativeMapView.getHeight(); - } - - float getWidth() { - return nativeMapView.getWidth(); - } + private final NativeMapView nativeMapView; + private int[] contentPadding; + + Projection(@NonNull NativeMapView nativeMapView) { + this.nativeMapView = nativeMapView; + this.contentPadding = new int[] {0, 0, 0, 0}; + } + + void setContentPadding(int[] contentPadding, int[] userLocationViewPadding) { + this.contentPadding = contentPadding; + + int[] padding = new int[] { + contentPadding[0] + userLocationViewPadding[0], + contentPadding[1] + userLocationViewPadding[1], + contentPadding[2] + userLocationViewPadding[2], + contentPadding[3] + userLocationViewPadding[3] + }; + + nativeMapView.setContentPadding(padding); + } + + int[] getContentPadding() { + return contentPadding; + } + + public void invalidateContentPadding(int[] userLocationViewPadding) { + setContentPadding(contentPadding, userLocationViewPadding); + } + + /** + * <p> + * Returns the distance spanned by one pixel at the specified latitude and current zoom level. + * </p> + * The distance between pixels decreases as the latitude approaches the poles. + * This relationship parallels the relationship between longitudinal coordinates at different latitudes. + * + * @param latitude The latitude for which to return the value. + * @return The distance measured in meters. + */ + public double getMetersPerPixelAtLatitude(@FloatRange(from = -90, to = 90) double latitude) { + return nativeMapView.getMetersPerPixelAtLatitude(latitude); + } + + /** + * Returns the geographic location that corresponds to a screen location. + * The screen location is specified in screen pixels (not display pixels) relative to the + * top left of the map (not the top left of the whole screen). + * + * @param point A Point on the screen in screen pixels. + * @return The LatLng corresponding to the point on the screen, or null if the ray through + * the given screen point does not intersect the ground plane. + */ + public LatLng fromScreenLocation(PointF point) { + return nativeMapView.latLngForPixel(point); + } + + /** + * Gets a projection of the viewing frustum for converting between screen coordinates and + * geo-latitude/longitude coordinates. + * + * @return The projection of the viewing frustum in its current state. + */ + public VisibleRegion getVisibleRegion() { + LatLngBounds.Builder builder = new LatLngBounds.Builder(); + + float left = contentPadding[0]; + float right = nativeMapView.getWidth() - contentPadding[2]; + float top = contentPadding[1]; + float bottom = nativeMapView.getHeight() - contentPadding[3]; + + LatLng topLeft = fromScreenLocation(new PointF(left, top)); + LatLng topRight = fromScreenLocation(new PointF(right, top)); + LatLng bottomRight = fromScreenLocation(new PointF(right, bottom)); + LatLng bottomLeft = fromScreenLocation(new PointF(left, bottom)); + + builder.include(topLeft) + .include(topRight) + .include(bottomRight) + .include(bottomLeft); + + return new VisibleRegion(topLeft, topRight, bottomLeft, bottomRight, builder.build()); + } + + /** + * Returns a screen location that corresponds to a geographical coordinate (LatLng). + * The screen location is in screen pixels (not display pixels) relative to the top left + * of the map (not of the whole screen). + * + * @param location A LatLng on the map to convert to a screen location. + * @return A Point representing the screen location in screen pixels. + */ + public PointF toScreenLocation(LatLng location) { + return nativeMapView.pixelForLatLng(location); + } + + float getHeight() { + return nativeMapView.getHeight(); + } + + float getWidth() { + return nativeMapView.getWidth(); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java index 75d6a01191..c0052f8364 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java @@ -35,204 +35,206 @@ import com.mapbox.mapboxsdk.exceptions.InvalidAccessTokenException; */ public class SupportMapFragment extends Fragment { - private MapView map; - private OnMapReadyCallback onMapReadyCallback; - - /** - * Creates a MapFragment instance - * - * @return MapFragment created - */ - public static SupportMapFragment newInstance() { - return new SupportMapFragment(); + private MapView map; + private OnMapReadyCallback onMapReadyCallback; + + /** + * Creates a MapFragment instance + * + * @return MapFragment created + */ + public static SupportMapFragment newInstance() { + return new SupportMapFragment(); + } + + /** + * Creates a MapFragment instance + * + * @param mapboxMapOptions The configuration options to be used. + * @return MapFragment created. + */ + public static SupportMapFragment newInstance(@Nullable MapboxMapOptions mapboxMapOptions) { + SupportMapFragment mapFragment = new SupportMapFragment(); + Bundle bundle = new Bundle(); + bundle.putParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS, mapboxMapOptions); + mapFragment.setArguments(bundle); + return mapFragment; + } + + /** + * Creates the fragment view hierarchy. + * + * @param inflater Inflater used to inflate content. + * @param container The parent layout for the map fragment. + * @param savedInstanceState The saved instance state for the map fragment. + * @return The view created + */ + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + Context context = inflater.getContext(); + MapboxMapOptions options = null; + + // Get bundle + Bundle bundle = getArguments(); + if (bundle != null && bundle.containsKey(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS)) { + options = bundle.getParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS); } - /** - * Creates a MapFragment instance - * - * @param mapboxMapOptions The configuration options to be used. - * @return MapFragment created. - */ - public static SupportMapFragment newInstance(@Nullable MapboxMapOptions mapboxMapOptions) { - SupportMapFragment mapFragment = new SupportMapFragment(); - Bundle bundle = new Bundle(); - bundle.putParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS, mapboxMapOptions); - mapFragment.setArguments(bundle); - return mapFragment; + // Assign an AccessToken if needed + if (options == null || options.getAccessToken() == null) { + String token = null; + if (MapboxAccountManager.getInstance() != null) { + token = MapboxAccountManager.getInstance().getAccessToken(); + } else { + token = getToken(inflater.getContext()); + } + if (TextUtils.isEmpty(token)) { + throw new InvalidAccessTokenException(); + } + if (options == null) { + options = new MapboxMapOptions().accessToken(token); + } else { + options.accessToken(token); + } } - /** - * Creates the fragment view hierarchy. - * - * @param inflater Inflater used to inflate content. - * @param container The parent layout for the map fragment. - * @param savedInstanceState The saved instance state for the map fragment. - * @return The view created - */ - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - super.onCreateView(inflater, container, savedInstanceState); - Context context = inflater.getContext(); - MapboxMapOptions options = null; - - // Get bundle - Bundle bundle = getArguments(); - if (bundle != null && bundle.containsKey(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS)) { - options = bundle.getParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS); - } - - // Assign an AccessToken if needed - if (options == null || options.getAccessToken() == null) { - String token = null; - if (MapboxAccountManager.getInstance() != null) { - token = MapboxAccountManager.getInstance().getAccessToken(); - } else { - token = getToken(inflater.getContext()); - } - if (TextUtils.isEmpty(token)) { - throw new InvalidAccessTokenException(); - } - if (options == null) { - options = new MapboxMapOptions().accessToken(token); - } else { - options.accessToken(token); - } - } - - Drawable foregroundDrawable = options.getMyLocationForegroundDrawable(); - Drawable foregroundBearingDrawable = options.getMyLocationForegroundBearingDrawable(); - if (foregroundDrawable == null || foregroundBearingDrawable == null) { - if (foregroundDrawable == null) { - foregroundDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_icon_default); - } - if (foregroundBearingDrawable == null) { - foregroundBearingDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_icon_bearing); - } - options.myLocationForegroundDrawables(foregroundDrawable, foregroundBearingDrawable); - } - - if (options.getMyLocationBackgroundDrawable() == null) { - options.myLocationBackgroundDrawable(ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_bg_shape)); - } - - return map = new MapView(inflater.getContext(), options); + Drawable foregroundDrawable = options.getMyLocationForegroundDrawable(); + Drawable foregroundBearingDrawable = options.getMyLocationForegroundBearingDrawable(); + if (foregroundDrawable == null || foregroundBearingDrawable == null) { + if (foregroundDrawable == null) { + foregroundDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_icon_default); + } + if (foregroundBearingDrawable == null) { + foregroundBearingDrawable = ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_icon_bearing); + } + options.myLocationForegroundDrawables(foregroundDrawable, foregroundBearingDrawable); } - /** - * <p> - * Returns the Mapbox access token set in the app resources. - * </p> - * It will first search the application manifest for a {@link MapboxConstants#KEY_META_DATA_MANIFEST} - * meta-data value. If not found it will then attempt to load the access token from the - * {@code res/raw/token.txt} development file. - * - * @param context The {@link Context} of the {@link android.app.Activity} or {@link android.app.Fragment}. - * @return The Mapbox access token or null if not found. - * @see MapboxConstants#KEY_META_DATA_MANIFEST - * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)} - */ - @Deprecated - private String getToken(@NonNull Context context) { - try { - // read out AndroidManifest - PackageManager packageManager = context.getPackageManager(); - ApplicationInfo appInfo = packageManager.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA); - String token = appInfo.metaData.getString(MapboxConstants.KEY_META_DATA_MANIFEST); - if (token == null || token.isEmpty()) { - throw new IllegalArgumentException(); - } - return token; - } catch (Exception exception) { - // use fallback on string resource, used for development - int tokenResId = context.getResources().getIdentifier("mapbox_access_token", "string", context.getPackageName()); - return tokenResId != 0 ? context.getString(tokenResId) : null; - } + if (options.getMyLocationBackgroundDrawable() == null) { + options.myLocationBackgroundDrawable(ContextCompat.getDrawable(context, R.drawable.mapbox_mylocation_bg_shape)); } - /** - * Called when the fragment view hierarchy is created. - * - * @param view The content view of the fragment - * @param savedInstanceState THe saved instance state of the framgnt - */ - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - map.onCreate(savedInstanceState); - } - - /** - * Called when the fragment is visible for the users. - */ - @Override - public void onStart() { - super.onStart(); - map.onStart(); - map.getMapAsync(onMapReadyCallback); - } - - /** - * Called when the fragment is ready to be interacted with. - */ - @Override - public void onResume() { - super.onResume(); - map.onResume(); - } - - /** - * Called when the fragment is pausing. - */ - @Override - public void onPause() { - super.onPause(); - map.onPause(); - } - - /** - * Called when the fragment state needs to be saved. - * - * @param outState The saved state - */ - @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - super.onSaveInstanceState(outState); - map.onSaveInstanceState(outState); - } - - /** - * Called when the fragment is no longer visible for the user. - */ - @Override - public void onStop() { - super.onStop(); - map.onStop(); - } - - /** - * Called when the fragment receives onLowMemory call from the hosting Activity. - */ - @Override - public void onLowMemory() { - super.onLowMemory(); - map.onLowMemory(); - } - - /** - * Called when the fragment is view hiearchy is being destroyed. - */ - @Override - public void onDestroyView() { - super.onDestroyView(); - map.onDestroy(); - } - - /** - * Sets a callback object which will be triggered when the MapboxMap instance is ready to be used. - * - * @param onMapReadyCallback The callback to be invoked. - */ - public void getMapAsync(@NonNull final OnMapReadyCallback onMapReadyCallback) { - this.onMapReadyCallback = onMapReadyCallback; + return map = new MapView(inflater.getContext(), options); + } + + /** + * <p> + * Returns the Mapbox access token set in the app resources. + * </p> + * It will first search the application manifest for a {@link MapboxConstants#KEY_META_DATA_MANIFEST} + * meta-data value. If not found it will then attempt to load the access token from the + * {@code res/raw/token.txt} development file. + * + * @param context The {@link Context} of the {@link android.app.Activity} or {@link android.app.Fragment}. + * @return The Mapbox access token or null if not found. + * @see MapboxConstants#KEY_META_DATA_MANIFEST + * @deprecated As of release 4.1.0, replaced by + * {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)} + */ + @Deprecated + private String getToken(@NonNull Context context) { + try { + // read out AndroidManifest + PackageManager packageManager = context.getPackageManager(); + ApplicationInfo appInfo = packageManager.getApplicationInfo(context.getPackageName(), + PackageManager.GET_META_DATA); + String token = appInfo.metaData.getString(MapboxConstants.KEY_META_DATA_MANIFEST); + if (token == null || token.isEmpty()) { + throw new IllegalArgumentException(); + } + return token; + } catch (Exception exception) { + // use fallback on string resource, used for development + int tokenResId = context.getResources().getIdentifier("mapbox_access_token", "string", context.getPackageName()); + return tokenResId != 0 ? context.getString(tokenResId) : null; } + } + + /** + * Called when the fragment view hierarchy is created. + * + * @param view The content view of the fragment + * @param savedInstanceState THe saved instance state of the framgnt + */ + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + map.onCreate(savedInstanceState); + } + + /** + * Called when the fragment is visible for the users. + */ + @Override + public void onStart() { + super.onStart(); + map.onStart(); + map.getMapAsync(onMapReadyCallback); + } + + /** + * Called when the fragment is ready to be interacted with. + */ + @Override + public void onResume() { + super.onResume(); + map.onResume(); + } + + /** + * Called when the fragment is pausing. + */ + @Override + public void onPause() { + super.onPause(); + map.onPause(); + } + + /** + * Called when the fragment state needs to be saved. + * + * @param outState The saved state + */ + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + map.onSaveInstanceState(outState); + } + + /** + * Called when the fragment is no longer visible for the user. + */ + @Override + public void onStop() { + super.onStop(); + map.onStop(); + } + + /** + * Called when the fragment receives onLowMemory call from the hosting Activity. + */ + @Override + public void onLowMemory() { + super.onLowMemory(); + map.onLowMemory(); + } + + /** + * Called when the fragment is view hiearchy is being destroyed. + */ + @Override + public void onDestroyView() { + super.onDestroyView(); + map.onDestroy(); + } + + /** + * Sets a callback object which will be triggered when the MapboxMap instance is ready to be used. + * + * @param onMapReadyCallback The callback to be invoked. + */ + public void getMapAsync(@NonNull final OnMapReadyCallback onMapReadyCallback) { + this.onMapReadyCallback = onMapReadyCallback; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java index 201cbe3c6b..3faebf591a 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java @@ -23,295 +23,298 @@ import timber.log.Timber; */ public final class TrackingSettings { - private final MyLocationView myLocationView; - private final UiSettings uiSettings; - private final FocalPointChangeListener focalPointChangedListener; - private LocationListener myLocationListener; - - private boolean myLocationEnabled; - private boolean dismissLocationTrackingOnGesture = true; - private boolean dismissBearingTrackingOnGesture = true; - - private MapboxMap.OnMyLocationTrackingModeChangeListener onMyLocationTrackingModeChangeListener; - private MapboxMap.OnMyBearingTrackingModeChangeListener onMyBearingTrackingModeChangeListener; - - TrackingSettings(@NonNull MyLocationView myLocationView, UiSettings uiSettings, FocalPointChangeListener focalPointChangedListener) { - this.myLocationView = myLocationView; - this.focalPointChangedListener = focalPointChangedListener; - this.uiSettings = uiSettings; + private final MyLocationView myLocationView; + private final UiSettings uiSettings; + private final FocalPointChangeListener focalPointChangedListener; + private LocationListener myLocationListener; + + private boolean myLocationEnabled; + private boolean dismissLocationTrackingOnGesture = true; + private boolean dismissBearingTrackingOnGesture = true; + + private MapboxMap.OnMyLocationTrackingModeChangeListener onMyLocationTrackingModeChangeListener; + private MapboxMap.OnMyBearingTrackingModeChangeListener onMyBearingTrackingModeChangeListener; + + TrackingSettings(@NonNull MyLocationView myLocationView, UiSettings uiSettings, + FocalPointChangeListener focalPointChangedListener) { + this.myLocationView = myLocationView; + this.focalPointChangedListener = focalPointChangedListener; + this.uiSettings = uiSettings; + } + + /** + * <p> + * Set the current my location tracking mode. + * </p> + * <p> + * Will enable my location if not active. + * </p> + * See {@link MyLocationTracking} for different values. + * + * @param myLocationTrackingMode The location tracking mode to be used. + * @throws SecurityException if no suitable permission is present + * @see MyLocationTracking + */ + @UiThread + public void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) { + myLocationView.setMyLocationTrackingMode(myLocationTrackingMode); + + if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { + focalPointChangedListener.onFocalPointChanged(new PointF(myLocationView.getCenterX(), + myLocationView.getCenterY())); + } else { + focalPointChangedListener.onFocalPointChanged(null); } - /** - * <p> - * Set the current my location tracking mode. - * </p> - * <p> - * Will enable my location if not active. - * </p> - * See {@link MyLocationTracking} for different values. - * - * @param myLocationTrackingMode The location tracking mode to be used. - * @throws SecurityException if no suitable permission is present - * @see MyLocationTracking - */ - @UiThread - public void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) { - myLocationView.setMyLocationTrackingMode(myLocationTrackingMode); - - if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { - focalPointChangedListener.onFocalPointChanged(new PointF(myLocationView.getCenterX(), myLocationView.getCenterY())); - } else { - focalPointChangedListener.onFocalPointChanged(null); - } - - if (onMyLocationTrackingModeChangeListener != null) { - onMyLocationTrackingModeChangeListener.onMyLocationTrackingModeChange(myLocationTrackingMode); - } - } - - /** - * Returns the current user location tracking mode. - * - * @return The current user location tracking mode. - * One of the values from {@link MyLocationTracking.Mode}. - * @see MyLocationTracking.Mode - */ - @UiThread - @MyLocationTracking.Mode - public int getMyLocationTrackingMode() { - return myLocationView.getMyLocationTrackingMode(); - } - - /** - * <p> - * Set the current my bearing tracking mode. - * </p> - * Shows the direction the user is heading. - * <p> - * When location tracking is disabled the direction of {@link MyLocationView} is rotated. When - * location tracking is enabled the {@link MapView} is rotated based on the bearing value. - * </p> - * See {@link MyBearingTracking} for different values. - * - * @param myBearingTrackingMode The bearing tracking mode to be used. - * @throws SecurityException if no suitable permission is present - * @see MyBearingTracking - */ - @UiThread - public void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) { - myLocationView.setMyBearingTrackingMode(myBearingTrackingMode); - if (onMyBearingTrackingModeChangeListener != null) { - onMyBearingTrackingModeChangeListener.onMyBearingTrackingModeChange(myBearingTrackingMode); - } - } - - /** - * Returns the current user bearing tracking mode. - * See {@link MyBearingTracking} for possible return values. - * - * @return the current user bearing tracking mode. - * @see MyBearingTracking - */ - @UiThread - @MyBearingTracking.Mode - public int getMyBearingTrackingMode() { - return myLocationView.getMyBearingTrackingMode(); + if (onMyLocationTrackingModeChangeListener != null) { + onMyLocationTrackingModeChangeListener.onMyLocationTrackingModeChange(myLocationTrackingMode); } - - /** - * Returns if the tracking modes will be dismissed when a gesture occurs. - * - * @return True to indicate the tracking modes will be dismissed. - * @deprecated use @link #isAllDismissTrackingOnGestureinstead - */ - @Deprecated - public boolean isDismissTrackingOnGesture() { - return dismissLocationTrackingOnGesture && dismissBearingTrackingOnGesture; + } + + /** + * Returns the current user location tracking mode. + * + * @return The current user location tracking mode. + * One of the values from {@link MyLocationTracking.Mode}. + * @see MyLocationTracking.Mode + */ + @UiThread + @MyLocationTracking.Mode + public int getMyLocationTrackingMode() { + return myLocationView.getMyLocationTrackingMode(); + } + + /** + * <p> + * Set the current my bearing tracking mode. + * </p> + * Shows the direction the user is heading. + * <p> + * When location tracking is disabled the direction of {@link MyLocationView} is rotated. When + * location tracking is enabled the {@link MapView} is rotated based on the bearing value. + * </p> + * See {@link MyBearingTracking} for different values. + * + * @param myBearingTrackingMode The bearing tracking mode to be used. + * @throws SecurityException if no suitable permission is present + * @see MyBearingTracking + */ + @UiThread + public void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) { + myLocationView.setMyBearingTrackingMode(myBearingTrackingMode); + if (onMyBearingTrackingModeChangeListener != null) { + onMyBearingTrackingModeChangeListener.onMyBearingTrackingModeChange(myBearingTrackingMode); } - - /** - * Returns if all tracking modes will be dismissed when a gesture occurs. - * - * @return True to indicate that location and bearing tracking will be dismissed. - */ - public boolean isAllDismissTrackingOnGesture() { - return dismissLocationTrackingOnGesture && dismissBearingTrackingOnGesture; - } - - /** - * Set the dismissal of the tracking modes if a gesture occurs. - * - * @param dismissTrackingOnGesture True to dismiss the tracking modes. - * @deprecated use @link #setDismissAllTrackingOnGesture instead - */ - @Deprecated - public void setDismissTrackingOnGesture(boolean dismissTrackingOnGesture) { - setDismissAllTrackingOnGesture(dismissTrackingOnGesture); + } + + /** + * Returns the current user bearing tracking mode. + * See {@link MyBearingTracking} for possible return values. + * + * @return the current user bearing tracking mode. + * @see MyBearingTracking + */ + @UiThread + @MyBearingTracking.Mode + public int getMyBearingTrackingMode() { + return myLocationView.getMyBearingTrackingMode(); + } + + /** + * Returns if the tracking modes will be dismissed when a gesture occurs. + * + * @return True to indicate the tracking modes will be dismissed. + * @deprecated use @link #isAllDismissTrackingOnGestureinstead + */ + @Deprecated + public boolean isDismissTrackingOnGesture() { + return dismissLocationTrackingOnGesture && dismissBearingTrackingOnGesture; + } + + /** + * Returns if all tracking modes will be dismissed when a gesture occurs. + * + * @return True to indicate that location and bearing tracking will be dismissed. + */ + public boolean isAllDismissTrackingOnGesture() { + return dismissLocationTrackingOnGesture && dismissBearingTrackingOnGesture; + } + + /** + * Set the dismissal of the tracking modes if a gesture occurs. + * + * @param dismissTrackingOnGesture True to dismiss the tracking modes. + * @deprecated use @link #setDismissAllTrackingOnGesture instead + */ + @Deprecated + public void setDismissTrackingOnGesture(boolean dismissTrackingOnGesture) { + setDismissAllTrackingOnGesture(dismissTrackingOnGesture); + } + + /** + * Set the dismissal of the tracking modes if a gesture occurs. + * + * @param dismissTrackingOnGesture True to dismiss all the tracking modes. + */ + public void setDismissAllTrackingOnGesture(boolean dismissTrackingOnGesture) { + dismissLocationTrackingOnGesture = dismissTrackingOnGesture; + dismissBearingTrackingOnGesture = dismissTrackingOnGesture; + } + + /** + * Set the dismissal of the tracking modes if a gesture occurs. + * + * @param dismissLocationTrackingOnGesture True to dismiss the location tracking mode. + */ + public void setDismissLocationTrackingOnGesture(boolean dismissLocationTrackingOnGesture) { + this.dismissLocationTrackingOnGesture = dismissLocationTrackingOnGesture; + } + + /** + * Returns if the location tracking will be disabled when a gesture occurs + * + * @return True if location tracking will be disabled. + */ + public boolean isDismissLocationTrackingOnGesture() { + return dismissLocationTrackingOnGesture; + } + + /** + * Set the dismissal of the bearing tracking modes if a gesture occurs. + * + * @param dismissBearingTrackingOnGesture True to dimsiss the bearinf tracking mode + */ + public void setDismissBearingTrackingOnGesture(boolean dismissBearingTrackingOnGesture) { + this.dismissBearingTrackingOnGesture = dismissBearingTrackingOnGesture; + } + + /** + * Returns if bearing will disabled when a gesture occurs + * + * @return True if bearing tracking will be disabled + */ + public boolean isDismissBearingTrackingOnGesture() { + return dismissBearingTrackingOnGesture; + } + + /** + * Returns if location tracking is disabled + * + * @return True if location tracking is disabled. + */ + public boolean isLocationTrackingDisabled() { + return myLocationView.getMyLocationTrackingMode() == MyLocationTracking.TRACKING_NONE; + } + + /** + * Returns if bearing tracking disabled + * + * @return True if bearing tracking is disabled. + */ + public boolean isBearingTrackingDisabled() { + return myLocationView.getMyBearingTrackingMode() == MyBearingTracking.NONE; + } + + /** + * Returns if rotate gesture are currently enabled. + * + * @return True if rotate gestures are currently enabled. + */ + public boolean isRotateGestureCurrentlyEnabled() { + // rotate gestures are recognised if: + // The user settings are enabled AND; + // EITHER bearing tracking is dismissed on gesture OR there is no bearing tracking + return uiSettings.isRotateGesturesEnabled() + && (dismissBearingTrackingOnGesture + || myLocationView.getMyBearingTrackingMode() == MyBearingTracking.NONE + || myLocationView.getMyLocationTrackingMode() == MyLocationTracking.TRACKING_NONE); + } + + /** + * Returns if scroll gesture are currently enabled. + * + * @return True if scroll gestures are currently enabled. + */ + public boolean isScrollGestureCurrentlyEnabled() { + return uiSettings.isScrollGesturesEnabled() + && (dismissLocationTrackingOnGesture + || myLocationView.getMyLocationTrackingMode() == MyLocationTracking.TRACKING_NONE); + } + + /** + * Reset the tracking modes as necessary. Location tracking is reset if the map center is changed, + * bearing tracking if there is a rotation. + */ + void resetTrackingModesIfRequired(boolean translate, boolean rotate) { + // if tracking is on, and we should dismiss tracking with gestures, and this is a scroll action, turn tracking off + if (translate && !isLocationTrackingDisabled() && isDismissLocationTrackingOnGesture()) { + setMyLocationTrackingMode(MyLocationTracking.TRACKING_NONE); } - /** - * Set the dismissal of the tracking modes if a gesture occurs. - * - * @param dismissTrackingOnGesture True to dismiss all the tracking modes. - */ - public void setDismissAllTrackingOnGesture(boolean dismissTrackingOnGesture) { - dismissLocationTrackingOnGesture = dismissTrackingOnGesture; - dismissBearingTrackingOnGesture = dismissTrackingOnGesture; + // reset bearing tracking only on rotate + if (rotate && !isBearingTrackingDisabled() && isDismissBearingTrackingOnGesture()) { + setMyBearingTrackingMode(MyBearingTracking.NONE); } - - /** - * Set the dismissal of the tracking modes if a gesture occurs. - * - * @param dismissLocationTrackingOnGesture True to dismiss the location tracking mode. - */ - public void setDismissLocationTrackingOnGesture(boolean dismissLocationTrackingOnGesture) { - this.dismissLocationTrackingOnGesture = dismissLocationTrackingOnGesture; - } - - /** - * Returns if the location tracking will be disabled when a gesture occurs - * - * @return True if location tracking will be disabled. - */ - public boolean isDismissLocationTrackingOnGesture() { - return dismissLocationTrackingOnGesture; - } - - /** - * Set the dismissal of the bearing tracking modes if a gesture occurs. - * - * @param dismissBearingTrackingOnGesture True to dimsiss the bearinf tracking mode - */ - public void setDismissBearingTrackingOnGesture(boolean dismissBearingTrackingOnGesture) { - this.dismissBearingTrackingOnGesture = dismissBearingTrackingOnGesture; - } - - /** - * Returns if bearing will disabled when a gesture occurs - * - * @return True if bearing tracking will be disabled - */ - public boolean isDismissBearingTrackingOnGesture() { - return dismissBearingTrackingOnGesture; - } - - /** - * Returns if location tracking is disabled - * - * @return True if location tracking is disabled. - */ - public boolean isLocationTrackingDisabled() { - return myLocationView.getMyLocationTrackingMode() == MyLocationTracking.TRACKING_NONE; - } - - /** - * Returns if bearing tracking disabled - * - * @return True if bearing tracking is disabled. - */ - public boolean isBearingTrackingDisabled() { - return myLocationView.getMyBearingTrackingMode() == MyBearingTracking.NONE; - } - - /** - * Returns if rotate gesture are currently enabled. - * - * @return True if rotate gestures are currently enabled. - */ - public boolean isRotateGestureCurrentlyEnabled() { - // rotate gestures are recognised if: - // The user settings are enabled AND; - // EITHER bearing tracking is dismissed on gesture OR there is no bearing tracking - return uiSettings.isRotateGesturesEnabled() && - (dismissBearingTrackingOnGesture - || myLocationView.getMyBearingTrackingMode() == MyBearingTracking.NONE - || myLocationView.getMyLocationTrackingMode() == MyLocationTracking.TRACKING_NONE); - } - - /** - * Returns if scroll gesture are currently enabled. - * - * @return True if scroll gestures are currently enabled. - */ - public boolean isScrollGestureCurrentlyEnabled() { - return uiSettings.isScrollGesturesEnabled() && - (dismissLocationTrackingOnGesture - || myLocationView.getMyLocationTrackingMode() == MyLocationTracking.TRACKING_NONE); - } - - /** - * Reset the tracking modes as necessary. Location tracking is reset if the map center is changed, - * bearing tracking if there is a rotation. - * - * @param translate - * @param rotate - */ - void resetTrackingModesIfRequired(boolean translate, boolean rotate) { - // if tracking is on, and we should dismiss tracking with gestures, and this is a scroll action, turn tracking off - if (translate && !isLocationTrackingDisabled() && isDismissLocationTrackingOnGesture()) { - setMyLocationTrackingMode(MyLocationTracking.TRACKING_NONE); - } - - // reset bearing tracking only on rotate - if (rotate && !isBearingTrackingDisabled() && isDismissBearingTrackingOnGesture()) { - setMyBearingTrackingMode(MyBearingTracking.NONE); - } - } - - void resetTrackingModesIfRequired(CameraPosition cameraPosition) { - resetTrackingModesIfRequired(cameraPosition.target != null, cameraPosition.bearing != -1); - } - - Location getMyLocation() { - return myLocationView.getLocation(); - } - - void setOnMyLocationChangeListener(@Nullable final MapboxMap.OnMyLocationChangeListener listener) { - if (listener != null) { - myLocationListener = new LocationListener() { - @Override - public void onLocationChanged(Location location) { - if (listener != null) { - listener.onMyLocationChange(location); - } - } - }; - LocationServices.getLocationServices(myLocationView.getContext()).addLocationListener(myLocationListener); - } else { - LocationServices.getLocationServices(myLocationView.getContext()).removeLocationListener(myLocationListener); - myLocationListener = null; + } + + void resetTrackingModesIfRequired(CameraPosition cameraPosition) { + resetTrackingModesIfRequired(cameraPosition.target != null, cameraPosition.bearing != -1); + } + + Location getMyLocation() { + return myLocationView.getLocation(); + } + + void setOnMyLocationChangeListener(@Nullable final MapboxMap.OnMyLocationChangeListener listener) { + if (listener != null) { + myLocationListener = new LocationListener() { + @Override + public void onLocationChanged(Location location) { + if (listener != null) { + listener.onMyLocationChange(location); + } } + }; + LocationServices.getLocationServices(myLocationView.getContext()).addLocationListener(myLocationListener); + } else { + LocationServices.getLocationServices(myLocationView.getContext()).removeLocationListener(myLocationListener); + myLocationListener = null; } - - boolean isPermissionsAccepted() { - return (ContextCompat.checkSelfPermission(myLocationView.getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) || - ContextCompat.checkSelfPermission(myLocationView.getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; - } - - void setOnMyLocationTrackingModeChangeListener(MapboxMap.OnMyLocationTrackingModeChangeListener onMyLocationTrackingModeChangeListener) { - this.onMyLocationTrackingModeChangeListener = onMyLocationTrackingModeChangeListener; - } - - void setOnMyBearingTrackingModeChangeListener(MapboxMap.OnMyBearingTrackingModeChangeListener onMyBearingTrackingModeChangeListener) { - this.onMyBearingTrackingModeChangeListener = onMyBearingTrackingModeChangeListener; - } - - MyLocationView getMyLocationView() { - return myLocationView; - } - - - boolean isMyLocationEnabled() { - return myLocationEnabled; - } - - void setMyLocationEnabled(boolean locationEnabled) { - if (!isPermissionsAccepted()) { - Timber.e("Could not activate user location tracking: " - + "user did not accept the permission or permissions were not requested."); - return; - } - myLocationEnabled = locationEnabled; - myLocationView.setEnabled(locationEnabled); + } + + boolean isPermissionsAccepted() { + return (ContextCompat.checkSelfPermission(myLocationView.getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) + == PackageManager.PERMISSION_GRANTED) + || ContextCompat.checkSelfPermission(myLocationView.getContext(), Manifest.permission.ACCESS_FINE_LOCATION) + == PackageManager.PERMISSION_GRANTED; + } + + void setOnMyLocationTrackingModeChangeListener( + MapboxMap.OnMyLocationTrackingModeChangeListener onMyLocationTrackingModeChangeListener) { + this.onMyLocationTrackingModeChangeListener = onMyLocationTrackingModeChangeListener; + } + + void setOnMyBearingTrackingModeChangeListener( + MapboxMap.OnMyBearingTrackingModeChangeListener onMyBearingTrackingModeChangeListener) { + this.onMyBearingTrackingModeChangeListener = onMyBearingTrackingModeChangeListener; + } + + MyLocationView getMyLocationView() { + return myLocationView; + } + + + boolean isMyLocationEnabled() { + return myLocationEnabled; + } + + void setMyLocationEnabled(boolean locationEnabled) { + if (!isPermissionsAccepted()) { + Timber.e("Could not activate user location tracking: " + + "user did not accept the permission or permissions were not requested."); + return; } + myLocationEnabled = locationEnabled; + myLocationView.setEnabled(locationEnabled); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java index 2babc59f1b..88acc13356 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java @@ -21,275 +21,280 @@ import static com.mapbox.mapboxsdk.maps.MapView.REGION_DID_CHANGE_ANIMATED; /** * Resembles the current Map transformation. * <p> - * Responsible for synchronising {@link CameraPosition} state and notifying {@link com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraChangeListener}. + * Responsible for synchronising {@link CameraPosition} state and notifying + * {@link com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraChangeListener}. * </p> */ final class Transform implements MapView.OnMapChangedListener { - private final NativeMapView mapView; - private final MarkerViewManager markerViewManager; - private final TrackingSettings trackingSettings; - private final MyLocationView myLocationView; - - private CameraPosition cameraPosition; - private MapboxMap.CancelableCallback cameraCancelableCallback; - private MapboxMap.OnCameraChangeListener onCameraChangeListener; - - Transform(NativeMapView mapView, MarkerViewManager markerViewManager, TrackingSettings trackingSettings) { - this.mapView = mapView; - this.markerViewManager = markerViewManager; - this.trackingSettings = trackingSettings; - this.myLocationView = trackingSettings.getMyLocationView(); + private final NativeMapView mapView; + private final MarkerViewManager markerViewManager; + private final TrackingSettings trackingSettings; + private final MyLocationView myLocationView; + + private CameraPosition cameraPosition; + private MapboxMap.CancelableCallback cameraCancelableCallback; + private MapboxMap.OnCameraChangeListener onCameraChangeListener; + + Transform(NativeMapView mapView, MarkerViewManager markerViewManager, TrackingSettings trackingSettings) { + this.mapView = mapView; + this.markerViewManager = markerViewManager; + this.trackingSettings = trackingSettings; + this.myLocationView = trackingSettings.getMyLocationView(); + } + + void initialise(@NonNull MapboxMap mapboxMap, @NonNull MapboxMapOptions options) { + CameraPosition position = options.getCamera(); + if (position != null && !position.equals(CameraPosition.DEFAULT)) { + moveCamera(mapboxMap, CameraUpdateFactory.newCameraPosition(position), null); + } + } + + // + // Camera API + // + + @UiThread + public final CameraPosition getCameraPosition() { + if (cameraPosition == null) { + cameraPosition = invalidateCameraPosition(); + } + return cameraPosition; + } + + @UiThread + void updateCameraPosition(@NonNull CameraPosition position) { + if (myLocationView != null) { + myLocationView.setCameraPosition(position); + } + markerViewManager.setTilt((float) position.tilt); + } + + @Override + public void onMapChanged(@MapView.MapChange int change) { + if (change == REGION_DID_CHANGE_ANIMATED && cameraCancelableCallback != null) { + invalidateCameraPosition(); + if (cameraCancelableCallback != null) { + cameraCancelableCallback.onFinish(); + cameraCancelableCallback = null; + } + mapView.removeOnMapChangedListener(this); + } + } + + @UiThread + final void moveCamera(MapboxMap mapboxMap, CameraUpdate update, MapboxMap.CancelableCallback callback) { + cameraPosition = update.getCameraPosition(mapboxMap); + trackingSettings.resetTrackingModesIfRequired(cameraPosition); + cancelTransitions(); + mapView.jumpTo(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt, cameraPosition.zoom); + if (callback != null) { + callback.onFinish(); + } + } + + @UiThread + final void easeCamera(MapboxMap mapboxMap, CameraUpdate update, int durationMs, boolean easingInterpolator, + boolean resetTrackingMode, final MapboxMap.CancelableCallback callback) { + cameraPosition = update.getCameraPosition(mapboxMap); + if (resetTrackingMode) { + trackingSettings.resetTrackingModesIfRequired(cameraPosition); } - void initialise(@NonNull MapboxMap mapboxMap, @NonNull MapboxMapOptions options) { - CameraPosition position = options.getCamera(); - if (position != null && !position.equals(CameraPosition.DEFAULT)) { - moveCamera(mapboxMap, CameraUpdateFactory.newCameraPosition(position), null); - } - } + cancelTransitions(); + if (callback != null) { + cameraCancelableCallback = callback; + mapView.addOnMapChangedListener(this); + } + + mapView.easeTo(cameraPosition.bearing, cameraPosition.target, getDurationNano(durationMs), cameraPosition.tilt, + cameraPosition.zoom, easingInterpolator); + } - // - // Camera API - // + @UiThread + final void animateCamera(MapboxMap mapboxMap, CameraUpdate update, int durationMs, + final MapboxMap.CancelableCallback callback) { + cameraPosition = update.getCameraPosition(mapboxMap); + trackingSettings.resetTrackingModesIfRequired(cameraPosition); - @UiThread - public final CameraPosition getCameraPosition() { - if (cameraPosition == null) { - cameraPosition = invalidateCameraPosition(); - } - return cameraPosition; + cancelTransitions(); + if (callback != null) { + cameraCancelableCallback = callback; + mapView.addOnMapChangedListener(this); } - @UiThread - void updateCameraPosition(@NonNull CameraPosition position) { - if (myLocationView != null) { - myLocationView.setCameraPosition(position); - } - markerViewManager.setTilt((float) position.tilt); - } + mapView.flyTo(cameraPosition.bearing, cameraPosition.target, getDurationNano(durationMs), cameraPosition.tilt, + cameraPosition.zoom); + } - @Override - public void onMapChanged(@MapView.MapChange int change) { - if (change == REGION_DID_CHANGE_ANIMATED && cameraCancelableCallback != null) { - invalidateCameraPosition(); - if (cameraCancelableCallback != null) { - cameraCancelableCallback.onFinish(); - cameraCancelableCallback = null; - } - mapView.removeOnMapChangedListener(this); - } + @UiThread + @Nullable + CameraPosition invalidateCameraPosition() { + if (mapView != null) { + cameraPosition = new CameraPosition.Builder(mapView.getCameraValues()).build(); + if (onCameraChangeListener != null) { + onCameraChangeListener.onCameraChange(this.cameraPosition); + } } + return cameraPosition; + } - @UiThread - final void moveCamera(MapboxMap mapboxMap, CameraUpdate update, MapboxMap.CancelableCallback callback) { - cameraPosition = update.getCameraPosition(mapboxMap); - trackingSettings.resetTrackingModesIfRequired(cameraPosition); - cancelTransitions(); - mapView.jumpTo(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt, cameraPosition.zoom); - if (callback != null) { - callback.onFinish(); - } + void cancelTransitions() { + if (cameraCancelableCallback != null) { + cameraCancelableCallback.onCancel(); + cameraCancelableCallback = null; } + mapView.cancelTransitions(); + } - @UiThread - final void easeCamera(MapboxMap mapboxMap, CameraUpdate update, int durationMs, boolean easingInterpolator, boolean resetTrackingMode, final MapboxMap.CancelableCallback callback) { - cameraPosition = update.getCameraPosition(mapboxMap); - if (resetTrackingMode) { - trackingSettings.resetTrackingModesIfRequired(cameraPosition); - } + @UiThread + void resetNorth() { + cancelTransitions(); + mapView.resetNorth(); + } - cancelTransitions(); - if (callback != null) { - cameraCancelableCallback = callback; - mapView.addOnMapChangedListener(this); - } + void setOnCameraChangeListener(@Nullable MapboxMap.OnCameraChangeListener listener) { + this.onCameraChangeListener = listener; + } - mapView.easeTo(cameraPosition.bearing, cameraPosition.target, getDurationNano(durationMs), cameraPosition.tilt, cameraPosition.zoom, easingInterpolator); - } + private long getDurationNano(long durationMs) { + return durationMs > 0 ? TimeUnit.NANOSECONDS.convert(durationMs, TimeUnit.MILLISECONDS) : 0; + } - @UiThread - final void animateCamera(MapboxMap mapboxMap, CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) { - cameraPosition = update.getCameraPosition(mapboxMap); - trackingSettings.resetTrackingModesIfRequired(cameraPosition); + // + // non Camera API + // - cancelTransitions(); - if (callback != null) { - cameraCancelableCallback = callback; - mapView.addOnMapChangedListener(this); - } + // Zoom in or out - mapView.flyTo(cameraPosition.bearing, cameraPosition.target, getDurationNano(durationMs), cameraPosition.tilt, cameraPosition.zoom); - } + double getZoom() { + return cameraPosition.zoom; + } - @UiThread - @Nullable - CameraPosition invalidateCameraPosition() { - if (mapView != null) { - cameraPosition = new CameraPosition.Builder(mapView.getCameraValues()).build(); - if (onCameraChangeListener != null) { - onCameraChangeListener.onCameraChange(this.cameraPosition); - } - } - return cameraPosition; - } + void zoom(boolean zoomIn) { + zoom(zoomIn, -1.0f, -1.0f); + } - void cancelTransitions() { - if (cameraCancelableCallback != null) { - cameraCancelableCallback.onCancel(); - cameraCancelableCallback = null; - } - mapView.cancelTransitions(); - } + void zoom(boolean zoomIn, float x, float y) { + // Cancel any animation + cancelTransitions(); - @UiThread - void resetNorth() { - cancelTransitions(); - mapView.resetNorth(); + if (zoomIn) { + mapView.scaleBy(2.0, x, y, MapboxConstants.ANIMATION_DURATION); + } else { + mapView.scaleBy(0.5, x, y, MapboxConstants.ANIMATION_DURATION); } + } - void setOnCameraChangeListener(@Nullable MapboxMap.OnCameraChangeListener listener) { - this.onCameraChangeListener = listener; - } + // Direction + double getBearing() { + double direction = -mapView.getBearing(); - private long getDurationNano(long durationMs) { - return durationMs > 0 ? TimeUnit.NANOSECONDS.convert(durationMs, TimeUnit.MILLISECONDS) : 0; + while (direction > 360) { + direction -= 360; } - - // - // non Camera API - // - - // Zoom in or out - - double getZoom() { - return cameraPosition.zoom; + while (direction < 0) { + direction += 360; } - void zoom(boolean zoomIn) { - zoom(zoomIn, -1.0f, -1.0f); - } + return direction; + } - void zoom(boolean zoomIn, float x, float y) { - // Cancel any animation - cancelTransitions(); + double getRawBearing() { + return mapView.getBearing(); + } - if (zoomIn) { - mapView.scaleBy(2.0, x, y, MapboxConstants.ANIMATION_DURATION); - } else { - mapView.scaleBy(0.5, x, y, MapboxConstants.ANIMATION_DURATION); - } + void setBearing(double bearing) { + if (myLocationView != null) { + myLocationView.setBearing(bearing); } + mapView.setBearing(bearing); + } - // Direction - double getBearing() { - double direction = -mapView.getBearing(); - - while (direction > 360) { - direction -= 360; - } - while (direction < 0) { - direction += 360; - } - - return direction; + void setBearing(double bearing, float focalX, float focalY) { + if (myLocationView != null) { + myLocationView.setBearing(bearing); } + mapView.setBearing(bearing, focalX, focalY); + } - double getRawBearing(){ - return mapView.getBearing(); - } - - void setBearing(double bearing) { - if (myLocationView != null) { - myLocationView.setBearing(bearing); - } - mapView.setBearing(bearing); - } - void setBearing(double bearing, float focalX, float focalY) { - if (myLocationView != null) { - myLocationView.setBearing(bearing); - } - mapView.setBearing(bearing, focalX, focalY); - } + // + // LatLng / CenterCoordinate + // + LatLng getLatLng() { + return mapView.getLatLng(); + } - // - // LatLng / CenterCoordinate - // - - LatLng getLatLng() { - return mapView.getLatLng(); - } - - // - // Pitch / Tilt - // + // + // Pitch / Tilt + // - double getTilt() { - return mapView.getPitch(); - } + double getTilt() { + return mapView.getPitch(); + } - void setTilt(Double pitch) { - if (myLocationView != null) { - myLocationView.setTilt(pitch); - } - markerViewManager.setTilt(pitch.floatValue()); - mapView.setPitch(pitch, 0); + void setTilt(Double pitch) { + if (myLocationView != null) { + myLocationView.setTilt(pitch); } + markerViewManager.setTilt(pitch.floatValue()); + mapView.setPitch(pitch, 0); + } - // - // Center coordinate - // + // + // Center coordinate + // - LatLng getCenterCoordinate() { - return mapView.getLatLng(); - } + LatLng getCenterCoordinate() { + return mapView.getLatLng(); + } - void setCenterCoordinate(LatLng centerCoordinate) { - mapView.setLatLng(centerCoordinate); - } + void setCenterCoordinate(LatLng centerCoordinate) { + mapView.setLatLng(centerCoordinate); + } - void setGestureInProgress(boolean gestureInProgress) { - mapView.setGestureInProgress(gestureInProgress); - if (!gestureInProgress) { - invalidateCameraPosition(); - } + void setGestureInProgress(boolean gestureInProgress) { + mapView.setGestureInProgress(gestureInProgress); + if (!gestureInProgress) { + invalidateCameraPosition(); } + } - void zoomBy(double pow, float x, float y) { - mapView.scaleBy(pow, x, y); - } + void zoomBy(double pow, float x, float y) { + mapView.scaleBy(pow, x, y); + } - void moveBy(double offsetX, double offsetY, long duration) { - mapView.moveBy(offsetX, offsetY, duration); - } + void moveBy(double offsetX, double offsetY, long duration) { + mapView.moveBy(offsetX, offsetY, duration); + } - // - // Min & Max ZoomLevel - // + // + // Min & Max ZoomLevel + // - void setMinZoom(double minZoom) { - if ((minZoom < MapboxConstants.MINIMUM_ZOOM) || (minZoom > MapboxConstants.MAXIMUM_ZOOM)) { - Timber.e("Not setting minZoomPreference, value is in unsupported range: " + minZoom); - return; - } - mapView.setMinZoom(minZoom); + void setMinZoom(double minZoom) { + if ((minZoom < MapboxConstants.MINIMUM_ZOOM) || (minZoom > MapboxConstants.MAXIMUM_ZOOM)) { + Timber.e("Not setting minZoomPreference, value is in unsupported range: " + minZoom); + return; } + mapView.setMinZoom(minZoom); + } - double getMinZoom() { - return mapView.getMinZoom(); - } + double getMinZoom() { + return mapView.getMinZoom(); + } - void setMaxZoom(double maxZoom) { - if ((maxZoom < MapboxConstants.MINIMUM_ZOOM) || (maxZoom > MapboxConstants.MAXIMUM_ZOOM)) { - Timber.e("Not setting maxZoomPreference, value is in unsupported range: " + maxZoom); - return; - } - mapView.setMaxZoom(maxZoom); + void setMaxZoom(double maxZoom) { + if ((maxZoom < MapboxConstants.MINIMUM_ZOOM) || (maxZoom > MapboxConstants.MAXIMUM_ZOOM)) { + Timber.e("Not setting maxZoomPreference, value is in unsupported range: " + maxZoom); + return; } + mapView.setMaxZoom(maxZoom); + } - double getMaxZoom() { - return mapView.getMaxZoom(); - } + double getMaxZoom() { + return mapView.getMaxZoom(); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java index 91d1c243f9..b58d5bfc0e 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java @@ -23,697 +23,700 @@ import com.mapbox.mapboxsdk.utils.ColorUtils; */ public final class UiSettings { - private final FocalPointChangeListener focalPointChangeListener; - private final Projection projection; - private final CompassView compassView; - private final ImageView attributionsView; - private final View logoView; - private float pixelRatio; - - private boolean rotateGesturesEnabled = true; - private boolean rotateGestureChangeAllowed = true; - - private boolean tiltGesturesEnabled = true; - private boolean tiltGestureChangeAllowed = true; - - private boolean zoomGesturesEnabled = true; - private boolean zoomGestureChangeAllowed = true; - - private boolean scrollGesturesEnabled = true; - private boolean scrollGestureChangeAllowed = true; - - private boolean zoomControlsEnabled; - - private boolean deselectMarkersOnTap = true; - - private PointF userProvidedFocalPoint; - - UiSettings(@NonNull Projection projection, @NonNull FocalPointChangeListener listener, @NonNull CompassView compassView, @NonNull ImageView attributionsView, @NonNull View logoView) { - this.projection = projection; - this.focalPointChangeListener = listener; - this.compassView = compassView; - this.attributionsView = attributionsView; - this.logoView = logoView; - if (logoView.getResources() != null) { - this.pixelRatio = logoView.getResources().getDisplayMetrics().density; - } - } - - void initialise(@NonNull Context context, @NonNull MapboxMapOptions options) { - Resources resources = context.getResources(); - initialiseGestures(options); - initialiseCompass(options, resources); - initialiseLogo(options, resources); - initialiseAttribution(context, options); - } - - private void initialiseGestures(MapboxMapOptions options) { - setZoomGesturesEnabled(options.getZoomGesturesEnabled()); - setZoomGestureChangeAllowed(options.getZoomGesturesEnabled()); - setScrollGesturesEnabled(options.getScrollGesturesEnabled()); - setScrollGestureChangeAllowed(options.getScrollGesturesEnabled()); - setRotateGesturesEnabled(options.getRotateGesturesEnabled()); - setRotateGestureChangeAllowed(options.getRotateGesturesEnabled()); - setTiltGesturesEnabled(options.getTiltGesturesEnabled()); - setTiltGestureChangeAllowed(options.getTiltGesturesEnabled()); - setZoomControlsEnabled(options.getZoomControlsEnabled()); - } - - private void initialiseCompass(MapboxMapOptions options, Resources resources) { - setCompassEnabled(options.getCompassEnabled()); - setCompassGravity(options.getCompassGravity()); - int[] compassMargins = options.getCompassMargins(); - if (compassMargins != null) { - setCompassMargins(compassMargins[0], compassMargins[1], compassMargins[2], compassMargins[3]); - } else { - int tenDp = (int) resources.getDimension(R.dimen.mapbox_ten_dp); - setCompassMargins(tenDp, tenDp, tenDp, tenDp); - } - setCompassFadeFacingNorth(options.getCompassFadeFacingNorth()); - } - - private void initialiseLogo(MapboxMapOptions options, Resources resources) { - setLogoEnabled(options.getLogoEnabled()); - setLogoGravity(options.getLogoGravity()); - int[] logoMargins = options.getLogoMargins(); - if (logoMargins != null) { - setLogoMargins(logoMargins[0], logoMargins[1], logoMargins[2], logoMargins[3]); - } else { - int sixteenDp = (int) resources.getDimension(R.dimen.mapbox_sixteen_dp); - setLogoMargins(sixteenDp, sixteenDp, sixteenDp, sixteenDp); - } - } - - private void initialiseAttribution(Context context, MapboxMapOptions options) { - Resources resources = context.getResources(); - setAttributionEnabled(options.getAttributionEnabled()); - setAttributionGravity(options.getAttributionGravity()); - int[] attributionMargins = options.getAttributionMargins(); - if (attributionMargins != null) { - setAttributionMargins(attributionMargins[0], attributionMargins[1], attributionMargins[2], attributionMargins[3]); - } else { - int sevenDp = (int) resources.getDimension(R.dimen.mapbox_seven_dp); - int seventySixDp = (int) resources.getDimension(R.dimen.mapbox_seventy_six_dp); - setAttributionMargins(seventySixDp, sevenDp, sevenDp, sevenDp); - } - - int attributionTintColor = options.getAttributionTintColor(); - setAttributionTintColor(attributionTintColor != -1 - ? attributionTintColor : ColorUtils.getPrimaryColor(context)); - } - - /** - * <p> - * Enables or disables the compass. The compass is an icon on the map that indicates the - * direction of north on the map. When a user clicks - * the compass, the camera orients itself to its default orientation and fades away shortly - * after. If disabled, the compass will never be displayed. - * </p> - * By default, the compass is enabled. - * - * @param compassEnabled True to enable the compass; false to disable the compass. - */ - public void setCompassEnabled(boolean compassEnabled) { - compassView.setEnabled(compassEnabled); - } - - /** - * Returns whether the compass is enabled. - * - * @return True if the compass is enabled; false if the compass is disabled. - */ - public boolean isCompassEnabled() { - return compassView.isEnabled(); - } - - /** - * <p> - * Sets the gravity of the compass view. Use this to change the corner of the map view that the - * compass is displayed in. - * </p> - * By default, the compass is in the top right corner. - * - * @param gravity One of the values from {@link Gravity}. - * @see Gravity - */ - @UiThread - public void setCompassGravity(int gravity) { - setWidgetGravity(compassView, gravity); - } - - /** - * Enables or disables fading of the compass when facing north. - * <p> - * By default this feature is enabled - * </p> - * - * @param compassFadeFacingNorth True to enable the fading animation; false to disable it - */ - public void setCompassFadeFacingNorth(boolean compassFadeFacingNorth) { - compassView.fadeCompassViewFacingNorth(compassFadeFacingNorth); - } - - /** - * Returns whether the compass performs a fading animation out when facing north. - * - * @return True if the compass will fade, false if it remains visible - */ - public boolean isCompassFadeWhenFacingNorth() { - return compassView.isFadeCompassViewFacingNorth(); - } - - /** - * Returns the gravity value of the CompassView - * - * @return The gravity - */ - public int getCompassGravity() { - return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).gravity; - } - - /** - * Sets the margins of the compass view. Use this to change the distance of the compass from the - * map view edge. - * - * @param left The left margin in pixels. - * @param top The top margin in pixels. - * @param right The right margin in pixels. - * @param bottom The bottom margin in pixels. - */ - @UiThread - public void setCompassMargins(int left, int top, int right, int bottom) { - setWidgetMargins(compassView, left, top, right, bottom); - } - - /** - * Returns the left side margin of CompassView - * - * @return The left margin in pixels - */ - public int getCompassMarginLeft() { - return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).leftMargin; - } - - /** - * Returns the top side margin of CompassView - * - * @return The top margin in pixels - */ - public int getCompassMarginTop() { - return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).topMargin; - } - - /** - * Returns the right side margin of CompassView - * - * @return The right margin in pixels - */ - public int getCompassMarginRight() { - return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).rightMargin; - } - - /** - * Returns the bottom side margin of CompassView - * - * @return The bottom margin in pixels - */ - public int getCompassMarginBottom() { - return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).bottomMargin; - } - - /** - * <p> - * Enables or disables the Mapbox logo. - * </p> - * By default, the compass is enabled. - * - * @param enabled True to enable the logo; false to disable the logo. - */ - public void setLogoEnabled(boolean enabled) { - logoView.setVisibility(enabled ? View.VISIBLE : View.GONE); - } - - /** - * Returns whether the logo is enabled. - * - * @return True if the logo is enabled; false if the logo is disabled. - */ - public boolean isLogoEnabled() { - return logoView.getVisibility() == View.VISIBLE; - } - - /** - * <p> - * Sets the gravity of the logo view. Use this to change the corner of the map view that the - * Mapbox logo is displayed in. - * </p> - * By default, the logo is in the bottom left corner. - * - * @param gravity One of the values from {@link Gravity}. - * @see Gravity - */ - public void setLogoGravity(int gravity) { - setWidgetGravity(logoView, gravity); - } - - /** - * Returns the gravity value of the logo - * - * @return The gravity - */ - public int getLogoGravity() { - return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).gravity; - } - - /** - * Sets the margins of the logo view. Use this to change the distance of the Mapbox logo from the - * map view edge. - * - * @param left The left margin in pixels. - * @param top The top margin in pixels. - * @param right The right margin in pixels. - * @param bottom The bottom margin in pixels. - */ - public void setLogoMargins(int left, int top, int right, int bottom) { - setWidgetMargins(logoView, left, top, right, bottom); - } - - /** - * Returns the left side margin of the logo - * - * @return The left margin in pixels - */ - public int getLogoMarginLeft() { - return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).leftMargin; - } - - /** - * Returns the top side margin of the logo - * - * @return The top margin in pixels - */ - public int getLogoMarginTop() { - return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).topMargin; - } - - /** - * Returns the right side margin of the logo - * - * @return The right margin in pixels - */ - public int getLogoMarginRight() { - return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).rightMargin; - } - - /** - * Returns the bottom side margin of the logo - * - * @return The bottom margin in pixels - */ - public int getLogoMarginBottom() { - return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).bottomMargin; - } - - /** - * <p> - * Enables or disables the attribution. - * </p> - * By default, the attribution is enabled. - * - * @param enabled True to enable the attribution; false to disable the attribution. - */ - public void setAttributionEnabled(boolean enabled) { - attributionsView.setVisibility(enabled ? View.VISIBLE : View.GONE); - } - - /** - * Returns whether the attribution is enabled. - * - * @return True if the attribution is enabled; false if the attribution is disabled. - */ - public boolean isAttributionEnabled() { - return attributionsView.getVisibility() == View.VISIBLE; - } - - /** - * <p> - * Sets the gravity of the attribution. - * </p> - * By default, the attribution is in the bottom left corner next to the Mapbox logo. - * - * @param gravity One of the values from {@link Gravity}. - * @see Gravity - */ - public void setAttributionGravity(int gravity) { - setWidgetGravity(attributionsView, gravity); - } - - /** - * Returns the gravity value of the logo - * - * @return The gravity - */ - public int getAttributionGravity() { - return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).gravity; - } - - /** - * Sets the margins of the attribution view. - * - * @param left The left margin in pixels. - * @param top The top margin in pixels. - * @param right The right margin in pixels. - * @param bottom The bottom margin in pixels. - */ - public void setAttributionMargins(int left, int top, int right, int bottom) { - setWidgetMargins(attributionsView, left, top, right, bottom); - } - - /** - * <p> - * Sets the tint of the attribution view. Use this to change the color of the attribution. - * </p> - * By default, the logo is tinted with the primary color of your theme. - * - * @param tintColor Color to tint the attribution. - */ - public void setAttributionTintColor(@ColorInt int tintColor) { - // Check that the tint color being passed in isn't transparent. - if (Color.alpha(tintColor) == 0) { - ColorUtils.setTintList(attributionsView, ContextCompat.getColor(attributionsView.getContext(), R.color.mapbox_blue)); - } else { - ColorUtils.setTintList(attributionsView, tintColor); - } - } - - /** - * Returns the left side margin of the attribution view. - * - * @return The left margin in pixels - */ - public int getAttributionMarginLeft() { - return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).leftMargin; - } - - /** - * Returns the top side margin of the attribution view. - * - * @return The top margin in pixels - */ - public int getAttributionMarginTop() { - return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).topMargin; - } - - /** - * Returns the right side margin of the attribution view. - * - * @return The right margin in pixels - */ - public int getAttributionMarginRight() { - return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).rightMargin; - } - - /** - * Returns the bottom side margin of the logo - * - * @return The bottom margin in pixels - */ - public int getAttributionMarginBottom() { - return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).bottomMargin; - } - - /** - * <p> - * Changes whether the user may rotate the map. - * </p> - * <p> - * This setting controls only user interactions with the map. If you set the value to false, - * you may still change the map location programmatically. - * </p> - * The default value is true. - * - * @param rotateGesturesEnabled If true, rotating is enabled. - */ - public void setRotateGesturesEnabled(boolean rotateGesturesEnabled) { - if (rotateGestureChangeAllowed) { - this.rotateGesturesEnabled = rotateGesturesEnabled; - } - } - - /** - * Returns whether the user may rotate the map. - * - * @return If true, rotating is enabled. - */ - public boolean isRotateGesturesEnabled() { - return rotateGesturesEnabled; - } - - void setRotateGestureChangeAllowed(boolean rotateGestureChangeAllowed) { - this.rotateGestureChangeAllowed = rotateGestureChangeAllowed; - } - - boolean isRotateGestureChangeAllowed() { - return rotateGestureChangeAllowed; - } - - /** - * <p> - * Changes whether the user may tilt the map. - * </p> - * <p> - * This setting controls only user interactions with the map. If you set the value to false, - * you may still change the map location programmatically. - * </p> - * The default value is true. - * - * @param tiltGesturesEnabled If true, tilting is enabled. - */ - public void setTiltGesturesEnabled(boolean tiltGesturesEnabled) { - if (tiltGestureChangeAllowed) { - this.tiltGesturesEnabled = tiltGesturesEnabled; - } - } - - /** - * Returns whether the user may tilt the map. - * - * @return If true, tilting is enabled. - */ - public boolean isTiltGesturesEnabled() { - return tiltGesturesEnabled; - } - - void setTiltGestureChangeAllowed(boolean tiltGestureChangeAllowed) { - this.tiltGestureChangeAllowed = tiltGestureChangeAllowed; - } - - boolean isTiltGestureChangeAllowed() { - return tiltGestureChangeAllowed; - } - - /** - * <p> - * Changes whether the user may zoom the map. - * </p> - * <p> - * This setting controls only user interactions with the map. If you set the value to false, - * you may still change the map location programmatically. - * </p> - * The default value is true. - * - * @param zoomGesturesEnabled If true, zooming is enabled. - */ - public void setZoomGesturesEnabled(boolean zoomGesturesEnabled) { - if (zoomGestureChangeAllowed) { - this.zoomGesturesEnabled = zoomGesturesEnabled; - } - } - - /** - * Returns whether the user may zoom the map. - * - * @return If true, zooming is enabled. - */ - public boolean isZoomGesturesEnabled() { - return zoomGesturesEnabled; - } - - void setZoomGestureChangeAllowed(boolean zoomGestureChangeAllowed) { - this.zoomGestureChangeAllowed = zoomGestureChangeAllowed; - } - - boolean isZoomGestureChangeAllowed() { - return zoomGestureChangeAllowed; - } - - /** - * <p> - * Sets whether the zoom controls are enabled. - * If enabled, the zoom controls are a pair of buttons - * (one for zooming in, one for zooming out) that appear on the screen. - * When pressed, they cause the camera to zoom in (or out) by one zoom level. - * If disabled, the zoom controls are not shown. - * </p> - * By default the zoom controls are enabled if the device is only single touch capable; - * - * @param zoomControlsEnabled If true, the zoom controls are enabled. - */ - public void setZoomControlsEnabled(boolean zoomControlsEnabled) { - this.zoomControlsEnabled = zoomControlsEnabled; - } - - /** - * Gets whether the zoom controls are enabled. - * - * @return If true, the zoom controls are enabled. - */ - public boolean isZoomControlsEnabled() { - return zoomControlsEnabled; - } - - /** - * Gets whether the markers are automatically deselected (and therefore, their infowindows - * closed) when a map tap is detected. - * - * @return If true, markers are deselected on a map tap. - */ - public boolean isDeselectMarkersOnTap() { - return deselectMarkersOnTap; - } - - /** - * Sets whether the markers are automatically deselected (and therefore, their infowindows - * closed) when a map tap is detected. - * - * @param deselectMarkersOnTap determines if markers should be deslected on tap - */ - public void setDeselectMarkersOnTap(boolean deselectMarkersOnTap) { - this.deselectMarkersOnTap = deselectMarkersOnTap; - } - - /** - * <p> - * Changes whether the user may scroll around the map. - * </p> - * <p> - * This setting controls only user interactions with the map. If you set the value to false, - * you may still change the map location programmatically. - * </p> - * The default value is true. - * - * @param scrollGesturesEnabled If true, scrolling is enabled. - */ - public void setScrollGesturesEnabled(boolean scrollGesturesEnabled) { - if (scrollGestureChangeAllowed) { - this.scrollGesturesEnabled = scrollGesturesEnabled; - } - } - - /** - * Returns whether the user may scroll around the map. - * - * @return If true, scrolling is enabled. - */ - public boolean isScrollGesturesEnabled() { - return scrollGesturesEnabled; - } - - void setScrollGestureChangeAllowed(boolean scrollGestureChangeAllowed) { - this.scrollGestureChangeAllowed = scrollGestureChangeAllowed; - } - - boolean isScrollGestureChangeAllowed() { - return scrollGestureChangeAllowed; - } - - /** - * <p> - * Sets the preference for whether all gestures should be enabled or disabled. - * </p> - * <p> - * This setting controls only user interactions with the map. If you set the value to false, - * you may still change the map location programmatically. - * </p> - * The default value is true. - * - * @param enabled If true, all gestures are available; otherwise, all gestures are disabled. - * @see #setZoomGesturesEnabled(boolean) ) - * @see #setScrollGesturesEnabled(boolean) - * @see #setRotateGesturesEnabled(boolean) - * @see #setTiltGesturesEnabled(boolean) - */ - public void setAllGesturesEnabled(boolean enabled) { - setScrollGesturesEnabled(enabled); - setRotateGesturesEnabled(enabled); - setTiltGesturesEnabled(enabled); - setZoomGesturesEnabled(enabled); - } - - /** - * Sets the focal point used as center for a gesture - * - * @param focalPoint the focal point to be used. - */ - public void setFocalPoint(@Nullable PointF focalPoint) { - this.userProvidedFocalPoint = focalPoint; - focalPointChangeListener.onFocalPointChanged(focalPoint); - } - - /** - * Returns the gesture focal point - * - * @return The focal point - */ - public PointF getFocalPoint() { - return userProvidedFocalPoint; - } - - /** - * Returns the measured height of the MapView - * - * @return height in pixels - */ - public float getHeight() { - return projection.getHeight(); - } - - /** - * Returns the measured width of the MapView - * - * @return widht in pixels - */ - public float getWidth() { - return projection.getWidth(); - } - - float getPixelRatio() { - return pixelRatio; - } - - /** - * Invalidates the ViewSettings instances shown on top of the MapView - */ - public void invalidate() { - setLogoMargins(getLogoMarginLeft(), getLogoMarginTop(), getLogoMarginRight(), getLogoMarginBottom()); - setCompassMargins(getCompassMarginLeft(), getCompassMarginTop(), getCompassMarginRight(), getCompassMarginBottom()); - setAttributionMargins(getAttributionMarginLeft(), getAttributionMarginTop(), getAttributionMarginRight(), getAttributionMarginBottom()); - } - - private void setWidgetGravity(@NonNull final View view, int gravity) { - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) view.getLayoutParams(); - layoutParams.gravity = gravity; - view.setLayoutParams(layoutParams); - } - - private void setWidgetMargins(@NonNull final View view, int left, int top, int right, int bottom) { - int contentPadding[] = projection.getContentPadding(); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) view.getLayoutParams(); - left += contentPadding[0]; - top += contentPadding[1]; - right += contentPadding[2]; - bottom += contentPadding[3]; - layoutParams.setMargins(left, top, right, bottom); - view.setLayoutParams(layoutParams); - } + private final FocalPointChangeListener focalPointChangeListener; + private final Projection projection; + private final CompassView compassView; + private final ImageView attributionsView; + private final View logoView; + private float pixelRatio; + + private boolean rotateGesturesEnabled = true; + private boolean rotateGestureChangeAllowed = true; + + private boolean tiltGesturesEnabled = true; + private boolean tiltGestureChangeAllowed = true; + + private boolean zoomGesturesEnabled = true; + private boolean zoomGestureChangeAllowed = true; + + private boolean scrollGesturesEnabled = true; + private boolean scrollGestureChangeAllowed = true; + + private boolean zoomControlsEnabled; + + private boolean deselectMarkersOnTap = true; + + private PointF userProvidedFocalPoint; + + UiSettings(@NonNull Projection projection, @NonNull FocalPointChangeListener listener, + @NonNull CompassView compassView, @NonNull ImageView attributionsView, @NonNull View logoView) { + this.projection = projection; + this.focalPointChangeListener = listener; + this.compassView = compassView; + this.attributionsView = attributionsView; + this.logoView = logoView; + if (logoView.getResources() != null) { + this.pixelRatio = logoView.getResources().getDisplayMetrics().density; + } + } + + void initialise(@NonNull Context context, @NonNull MapboxMapOptions options) { + Resources resources = context.getResources(); + initialiseGestures(options); + initialiseCompass(options, resources); + initialiseLogo(options, resources); + initialiseAttribution(context, options); + } + + private void initialiseGestures(MapboxMapOptions options) { + setZoomGesturesEnabled(options.getZoomGesturesEnabled()); + setZoomGestureChangeAllowed(options.getZoomGesturesEnabled()); + setScrollGesturesEnabled(options.getScrollGesturesEnabled()); + setScrollGestureChangeAllowed(options.getScrollGesturesEnabled()); + setRotateGesturesEnabled(options.getRotateGesturesEnabled()); + setRotateGestureChangeAllowed(options.getRotateGesturesEnabled()); + setTiltGesturesEnabled(options.getTiltGesturesEnabled()); + setTiltGestureChangeAllowed(options.getTiltGesturesEnabled()); + setZoomControlsEnabled(options.getZoomControlsEnabled()); + } + + private void initialiseCompass(MapboxMapOptions options, Resources resources) { + setCompassEnabled(options.getCompassEnabled()); + setCompassGravity(options.getCompassGravity()); + int[] compassMargins = options.getCompassMargins(); + if (compassMargins != null) { + setCompassMargins(compassMargins[0], compassMargins[1], compassMargins[2], compassMargins[3]); + } else { + int tenDp = (int) resources.getDimension(R.dimen.mapbox_ten_dp); + setCompassMargins(tenDp, tenDp, tenDp, tenDp); + } + setCompassFadeFacingNorth(options.getCompassFadeFacingNorth()); + } + + private void initialiseLogo(MapboxMapOptions options, Resources resources) { + setLogoEnabled(options.getLogoEnabled()); + setLogoGravity(options.getLogoGravity()); + int[] logoMargins = options.getLogoMargins(); + if (logoMargins != null) { + setLogoMargins(logoMargins[0], logoMargins[1], logoMargins[2], logoMargins[3]); + } else { + int sixteenDp = (int) resources.getDimension(R.dimen.mapbox_sixteen_dp); + setLogoMargins(sixteenDp, sixteenDp, sixteenDp, sixteenDp); + } + } + + private void initialiseAttribution(Context context, MapboxMapOptions options) { + Resources resources = context.getResources(); + setAttributionEnabled(options.getAttributionEnabled()); + setAttributionGravity(options.getAttributionGravity()); + int[] attributionMargins = options.getAttributionMargins(); + if (attributionMargins != null) { + setAttributionMargins(attributionMargins[0], attributionMargins[1], attributionMargins[2], attributionMargins[3]); + } else { + int sevenDp = (int) resources.getDimension(R.dimen.mapbox_seven_dp); + int seventySixDp = (int) resources.getDimension(R.dimen.mapbox_seventy_six_dp); + setAttributionMargins(seventySixDp, sevenDp, sevenDp, sevenDp); + } + + int attributionTintColor = options.getAttributionTintColor(); + setAttributionTintColor(attributionTintColor != -1 + ? attributionTintColor : ColorUtils.getPrimaryColor(context)); + } + + /** + * <p> + * Enables or disables the compass. The compass is an icon on the map that indicates the + * direction of north on the map. When a user clicks + * the compass, the camera orients itself to its default orientation and fades away shortly + * after. If disabled, the compass will never be displayed. + * </p> + * By default, the compass is enabled. + * + * @param compassEnabled True to enable the compass; false to disable the compass. + */ + public void setCompassEnabled(boolean compassEnabled) { + compassView.setEnabled(compassEnabled); + } + + /** + * Returns whether the compass is enabled. + * + * @return True if the compass is enabled; false if the compass is disabled. + */ + public boolean isCompassEnabled() { + return compassView.isEnabled(); + } + + /** + * <p> + * Sets the gravity of the compass view. Use this to change the corner of the map view that the + * compass is displayed in. + * </p> + * By default, the compass is in the top right corner. + * + * @param gravity One of the values from {@link Gravity}. + * @see Gravity + */ + @UiThread + public void setCompassGravity(int gravity) { + setWidgetGravity(compassView, gravity); + } + + /** + * Enables or disables fading of the compass when facing north. + * <p> + * By default this feature is enabled + * </p> + * + * @param compassFadeFacingNorth True to enable the fading animation; false to disable it + */ + public void setCompassFadeFacingNorth(boolean compassFadeFacingNorth) { + compassView.fadeCompassViewFacingNorth(compassFadeFacingNorth); + } + + /** + * Returns whether the compass performs a fading animation out when facing north. + * + * @return True if the compass will fade, false if it remains visible + */ + public boolean isCompassFadeWhenFacingNorth() { + return compassView.isFadeCompassViewFacingNorth(); + } + + /** + * Returns the gravity value of the CompassView + * + * @return The gravity + */ + public int getCompassGravity() { + return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).gravity; + } + + /** + * Sets the margins of the compass view. Use this to change the distance of the compass from the + * map view edge. + * + * @param left The left margin in pixels. + * @param top The top margin in pixels. + * @param right The right margin in pixels. + * @param bottom The bottom margin in pixels. + */ + @UiThread + public void setCompassMargins(int left, int top, int right, int bottom) { + setWidgetMargins(compassView, left, top, right, bottom); + } + + /** + * Returns the left side margin of CompassView + * + * @return The left margin in pixels + */ + public int getCompassMarginLeft() { + return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).leftMargin; + } + + /** + * Returns the top side margin of CompassView + * + * @return The top margin in pixels + */ + public int getCompassMarginTop() { + return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).topMargin; + } + + /** + * Returns the right side margin of CompassView + * + * @return The right margin in pixels + */ + public int getCompassMarginRight() { + return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).rightMargin; + } + + /** + * Returns the bottom side margin of CompassView + * + * @return The bottom margin in pixels + */ + public int getCompassMarginBottom() { + return ((FrameLayout.LayoutParams) compassView.getLayoutParams()).bottomMargin; + } + + /** + * <p> + * Enables or disables the Mapbox logo. + * </p> + * By default, the compass is enabled. + * + * @param enabled True to enable the logo; false to disable the logo. + */ + public void setLogoEnabled(boolean enabled) { + logoView.setVisibility(enabled ? View.VISIBLE : View.GONE); + } + + /** + * Returns whether the logo is enabled. + * + * @return True if the logo is enabled; false if the logo is disabled. + */ + public boolean isLogoEnabled() { + return logoView.getVisibility() == View.VISIBLE; + } + + /** + * <p> + * Sets the gravity of the logo view. Use this to change the corner of the map view that the + * Mapbox logo is displayed in. + * </p> + * By default, the logo is in the bottom left corner. + * + * @param gravity One of the values from {@link Gravity}. + * @see Gravity + */ + public void setLogoGravity(int gravity) { + setWidgetGravity(logoView, gravity); + } + + /** + * Returns the gravity value of the logo + * + * @return The gravity + */ + public int getLogoGravity() { + return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).gravity; + } + + /** + * Sets the margins of the logo view. Use this to change the distance of the Mapbox logo from the + * map view edge. + * + * @param left The left margin in pixels. + * @param top The top margin in pixels. + * @param right The right margin in pixels. + * @param bottom The bottom margin in pixels. + */ + public void setLogoMargins(int left, int top, int right, int bottom) { + setWidgetMargins(logoView, left, top, right, bottom); + } + + /** + * Returns the left side margin of the logo + * + * @return The left margin in pixels + */ + public int getLogoMarginLeft() { + return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).leftMargin; + } + + /** + * Returns the top side margin of the logo + * + * @return The top margin in pixels + */ + public int getLogoMarginTop() { + return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).topMargin; + } + + /** + * Returns the right side margin of the logo + * + * @return The right margin in pixels + */ + public int getLogoMarginRight() { + return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).rightMargin; + } + + /** + * Returns the bottom side margin of the logo + * + * @return The bottom margin in pixels + */ + public int getLogoMarginBottom() { + return ((FrameLayout.LayoutParams) logoView.getLayoutParams()).bottomMargin; + } + + /** + * <p> + * Enables or disables the attribution. + * </p> + * By default, the attribution is enabled. + * + * @param enabled True to enable the attribution; false to disable the attribution. + */ + public void setAttributionEnabled(boolean enabled) { + attributionsView.setVisibility(enabled ? View.VISIBLE : View.GONE); + } + + /** + * Returns whether the attribution is enabled. + * + * @return True if the attribution is enabled; false if the attribution is disabled. + */ + public boolean isAttributionEnabled() { + return attributionsView.getVisibility() == View.VISIBLE; + } + + /** + * <p> + * Sets the gravity of the attribution. + * </p> + * By default, the attribution is in the bottom left corner next to the Mapbox logo. + * + * @param gravity One of the values from {@link Gravity}. + * @see Gravity + */ + public void setAttributionGravity(int gravity) { + setWidgetGravity(attributionsView, gravity); + } + + /** + * Returns the gravity value of the logo + * + * @return The gravity + */ + public int getAttributionGravity() { + return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).gravity; + } + + /** + * Sets the margins of the attribution view. + * + * @param left The left margin in pixels. + * @param top The top margin in pixels. + * @param right The right margin in pixels. + * @param bottom The bottom margin in pixels. + */ + public void setAttributionMargins(int left, int top, int right, int bottom) { + setWidgetMargins(attributionsView, left, top, right, bottom); + } + + /** + * <p> + * Sets the tint of the attribution view. Use this to change the color of the attribution. + * </p> + * By default, the logo is tinted with the primary color of your theme. + * + * @param tintColor Color to tint the attribution. + */ + public void setAttributionTintColor(@ColorInt int tintColor) { + // Check that the tint color being passed in isn't transparent. + if (Color.alpha(tintColor) == 0) { + ColorUtils.setTintList(attributionsView, ContextCompat.getColor(attributionsView.getContext(), + R.color.mapbox_blue)); + } else { + ColorUtils.setTintList(attributionsView, tintColor); + } + } + + /** + * Returns the left side margin of the attribution view. + * + * @return The left margin in pixels + */ + public int getAttributionMarginLeft() { + return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).leftMargin; + } + + /** + * Returns the top side margin of the attribution view. + * + * @return The top margin in pixels + */ + public int getAttributionMarginTop() { + return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).topMargin; + } + + /** + * Returns the right side margin of the attribution view. + * + * @return The right margin in pixels + */ + public int getAttributionMarginRight() { + return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).rightMargin; + } + + /** + * Returns the bottom side margin of the logo + * + * @return The bottom margin in pixels + */ + public int getAttributionMarginBottom() { + return ((FrameLayout.LayoutParams) attributionsView.getLayoutParams()).bottomMargin; + } + + /** + * <p> + * Changes whether the user may rotate the map. + * </p> + * <p> + * This setting controls only user interactions with the map. If you set the value to false, + * you may still change the map location programmatically. + * </p> + * The default value is true. + * + * @param rotateGesturesEnabled If true, rotating is enabled. + */ + public void setRotateGesturesEnabled(boolean rotateGesturesEnabled) { + if (rotateGestureChangeAllowed) { + this.rotateGesturesEnabled = rotateGesturesEnabled; + } + } + + /** + * Returns whether the user may rotate the map. + * + * @return If true, rotating is enabled. + */ + public boolean isRotateGesturesEnabled() { + return rotateGesturesEnabled; + } + + void setRotateGestureChangeAllowed(boolean rotateGestureChangeAllowed) { + this.rotateGestureChangeAllowed = rotateGestureChangeAllowed; + } + + boolean isRotateGestureChangeAllowed() { + return rotateGestureChangeAllowed; + } + + /** + * <p> + * Changes whether the user may tilt the map. + * </p> + * <p> + * This setting controls only user interactions with the map. If you set the value to false, + * you may still change the map location programmatically. + * </p> + * The default value is true. + * + * @param tiltGesturesEnabled If true, tilting is enabled. + */ + public void setTiltGesturesEnabled(boolean tiltGesturesEnabled) { + if (tiltGestureChangeAllowed) { + this.tiltGesturesEnabled = tiltGesturesEnabled; + } + } + + /** + * Returns whether the user may tilt the map. + * + * @return If true, tilting is enabled. + */ + public boolean isTiltGesturesEnabled() { + return tiltGesturesEnabled; + } + + void setTiltGestureChangeAllowed(boolean tiltGestureChangeAllowed) { + this.tiltGestureChangeAllowed = tiltGestureChangeAllowed; + } + + boolean isTiltGestureChangeAllowed() { + return tiltGestureChangeAllowed; + } + + /** + * <p> + * Changes whether the user may zoom the map. + * </p> + * <p> + * This setting controls only user interactions with the map. If you set the value to false, + * you may still change the map location programmatically. + * </p> + * The default value is true. + * + * @param zoomGesturesEnabled If true, zooming is enabled. + */ + public void setZoomGesturesEnabled(boolean zoomGesturesEnabled) { + if (zoomGestureChangeAllowed) { + this.zoomGesturesEnabled = zoomGesturesEnabled; + } + } + + /** + * Returns whether the user may zoom the map. + * + * @return If true, zooming is enabled. + */ + public boolean isZoomGesturesEnabled() { + return zoomGesturesEnabled; + } + + void setZoomGestureChangeAllowed(boolean zoomGestureChangeAllowed) { + this.zoomGestureChangeAllowed = zoomGestureChangeAllowed; + } + + boolean isZoomGestureChangeAllowed() { + return zoomGestureChangeAllowed; + } + + /** + * <p> + * Sets whether the zoom controls are enabled. + * If enabled, the zoom controls are a pair of buttons + * (one for zooming in, one for zooming out) that appear on the screen. + * When pressed, they cause the camera to zoom in (or out) by one zoom level. + * If disabled, the zoom controls are not shown. + * </p> + * By default the zoom controls are enabled if the device is only single touch capable; + * + * @param zoomControlsEnabled If true, the zoom controls are enabled. + */ + public void setZoomControlsEnabled(boolean zoomControlsEnabled) { + this.zoomControlsEnabled = zoomControlsEnabled; + } + + /** + * Gets whether the zoom controls are enabled. + * + * @return If true, the zoom controls are enabled. + */ + public boolean isZoomControlsEnabled() { + return zoomControlsEnabled; + } + + /** + * Gets whether the markers are automatically deselected (and therefore, their infowindows + * closed) when a map tap is detected. + * + * @return If true, markers are deselected on a map tap. + */ + public boolean isDeselectMarkersOnTap() { + return deselectMarkersOnTap; + } + + /** + * Sets whether the markers are automatically deselected (and therefore, their infowindows + * closed) when a map tap is detected. + * + * @param deselectMarkersOnTap determines if markers should be deslected on tap + */ + public void setDeselectMarkersOnTap(boolean deselectMarkersOnTap) { + this.deselectMarkersOnTap = deselectMarkersOnTap; + } + + /** + * <p> + * Changes whether the user may scroll around the map. + * </p> + * <p> + * This setting controls only user interactions with the map. If you set the value to false, + * you may still change the map location programmatically. + * </p> + * The default value is true. + * + * @param scrollGesturesEnabled If true, scrolling is enabled. + */ + public void setScrollGesturesEnabled(boolean scrollGesturesEnabled) { + if (scrollGestureChangeAllowed) { + this.scrollGesturesEnabled = scrollGesturesEnabled; + } + } + + /** + * Returns whether the user may scroll around the map. + * + * @return If true, scrolling is enabled. + */ + public boolean isScrollGesturesEnabled() { + return scrollGesturesEnabled; + } + + void setScrollGestureChangeAllowed(boolean scrollGestureChangeAllowed) { + this.scrollGestureChangeAllowed = scrollGestureChangeAllowed; + } + + boolean isScrollGestureChangeAllowed() { + return scrollGestureChangeAllowed; + } + + /** + * <p> + * Sets the preference for whether all gestures should be enabled or disabled. + * </p> + * <p> + * This setting controls only user interactions with the map. If you set the value to false, + * you may still change the map location programmatically. + * </p> + * The default value is true. + * + * @param enabled If true, all gestures are available; otherwise, all gestures are disabled. + * @see #setZoomGesturesEnabled(boolean) ) + * @see #setScrollGesturesEnabled(boolean) + * @see #setRotateGesturesEnabled(boolean) + * @see #setTiltGesturesEnabled(boolean) + */ + public void setAllGesturesEnabled(boolean enabled) { + setScrollGesturesEnabled(enabled); + setRotateGesturesEnabled(enabled); + setTiltGesturesEnabled(enabled); + setZoomGesturesEnabled(enabled); + } + + /** + * Sets the focal point used as center for a gesture + * + * @param focalPoint the focal point to be used. + */ + public void setFocalPoint(@Nullable PointF focalPoint) { + this.userProvidedFocalPoint = focalPoint; + focalPointChangeListener.onFocalPointChanged(focalPoint); + } + + /** + * Returns the gesture focal point + * + * @return The focal point + */ + public PointF getFocalPoint() { + return userProvidedFocalPoint; + } + + /** + * Returns the measured height of the MapView + * + * @return height in pixels + */ + public float getHeight() { + return projection.getHeight(); + } + + /** + * Returns the measured width of the MapView + * + * @return widht in pixels + */ + public float getWidth() { + return projection.getWidth(); + } + + float getPixelRatio() { + return pixelRatio; + } + + /** + * Invalidates the ViewSettings instances shown on top of the MapView + */ + public void invalidate() { + setLogoMargins(getLogoMarginLeft(), getLogoMarginTop(), getLogoMarginRight(), getLogoMarginBottom()); + setCompassMargins(getCompassMarginLeft(), getCompassMarginTop(), getCompassMarginRight(), getCompassMarginBottom()); + setAttributionMargins(getAttributionMarginLeft(), getAttributionMarginTop(), getAttributionMarginRight(), + getAttributionMarginBottom()); + } + + private void setWidgetGravity(@NonNull final View view, int gravity) { + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) view.getLayoutParams(); + layoutParams.gravity = gravity; + view.setLayoutParams(layoutParams); + } + + private void setWidgetMargins(@NonNull final View view, int left, int top, int right, int bottom) { + int[] contentPadding = projection.getContentPadding(); + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) view.getLayoutParams(); + left += contentPadding[0]; + top += contentPadding[1]; + right += contentPadding[2]; + bottom += contentPadding[3]; + layoutParams.setMargins(left, top, right, bottom); + view.setLayoutParams(layoutParams); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java index 4d9a60ed66..dc4a21f2fe 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java @@ -27,140 +27,140 @@ import java.lang.ref.WeakReference; */ public final class CompassView extends ImageView implements Runnable { - private static final long TIME_WAIT_IDLE = 500; - private static final long TIME_FADE_ANIMATION = TIME_WAIT_IDLE; - private static final long TIME_MAP_NORTH_ANIMATION = 150; - - private double direction = 0.0; - private boolean fadeCompassViewFacingNorth = true; - private ViewPropertyAnimatorCompat fadeAnimator; - - public CompassView(Context context) { - super(context); - initialize(context); + private static final long TIME_WAIT_IDLE = 500; + private static final long TIME_FADE_ANIMATION = TIME_WAIT_IDLE; + private static final long TIME_MAP_NORTH_ANIMATION = 150; + + private double direction = 0.0; + private boolean fadeCompassViewFacingNorth = true; + private ViewPropertyAnimatorCompat fadeAnimator; + + public CompassView(Context context) { + super(context); + initialize(context); + } + + public CompassView(Context context, AttributeSet attrs) { + super(context, attrs); + initialize(context); + } + + public CompassView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(context); + } + + private void initialize(Context context) { + setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.mapbox_compass_icon)); + setContentDescription(getResources().getString(R.string.mapbox_compassContentDescription)); + setEnabled(false); + + // Layout params + float screenDensity = context.getResources().getDisplayMetrics().density; + ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams((int) (48 * screenDensity), (int) (48 * screenDensity)); + setLayoutParams(lp); + } + + // TODO refactor MapboxMap and replace with interface + public void setMapboxMap(@NonNull MapboxMap mapboxMap) { + setOnClickListener(new CompassClickListener(mapboxMap, this)); + } + + private void resetAnimation() { + if (fadeAnimator != null) { + fadeAnimator.cancel(); } - - public CompassView(Context context, AttributeSet attrs) { - super(context, attrs); - initialize(context); + fadeAnimator = null; + } + + public boolean isHidden() { + return fadeCompassViewFacingNorth && isFacingNorth(); + } + + public boolean isFacingNorth() { + // increase range more than just 0.0 + return direction >= 359.0 || direction <= 1.0; + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + if (enabled && !isHidden()) { + resetAnimation(); + setAlpha(1.0f); + setVisibility(View.VISIBLE); + } else { + resetAnimation(); + setAlpha(0.0f); + setVisibility(View.INVISIBLE); } + } - public CompassView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - initialize(context); - } + public void update(final double direction) { + this.direction = direction; - private void initialize(Context context) { - setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.mapbox_compass_icon)); - setContentDescription(getResources().getString(R.string.mapbox_compassContentDescription)); - setEnabled(false); - - // Layout params - float screenDensity = context.getResources().getDisplayMetrics().density; - ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams((int) (48 * screenDensity), (int) (48 * screenDensity)); - setLayoutParams(lp); + if (!isEnabled()) { + return; } - // TODO refactor MapboxMap and replace with interface - public void setMapboxMap(@NonNull MapboxMap mapboxMap) { - setOnClickListener(new CompassClickListener(mapboxMap, this)); + if (isHidden()) { + if (getVisibility() == View.INVISIBLE || fadeAnimator != null) { + return; + } + postDelayed(this, TIME_WAIT_IDLE); + return; + } else { + resetAnimation(); + setAlpha(1.0f); + setVisibility(View.VISIBLE); } - private void resetAnimation() { - if (fadeAnimator != null) { - fadeAnimator.cancel(); - } - fadeAnimator = null; - } + setRotation((float) direction); + } - public boolean isHidden() { - return fadeCompassViewFacingNorth && isFacingNorth(); - } + public void fadeCompassViewFacingNorth(boolean compassFadeFacingNorth) { + fadeCompassViewFacingNorth = compassFadeFacingNorth; + } - public boolean isFacingNorth() { - // increase range more than just 0.0 - return direction >= 359.0 || direction <= 1.0; - } + public boolean isFadeCompassViewFacingNorth() { + return fadeCompassViewFacingNorth; + } - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - if (enabled && !isHidden()) { - resetAnimation(); - setAlpha(1.0f); - setVisibility(View.VISIBLE); - } else { - resetAnimation(); - setAlpha(0.0f); - setVisibility(View.INVISIBLE); + @Override + public void run() { + if (isFacingNorth() && fadeCompassViewFacingNorth) { + resetAnimation(); + setLayerType(View.LAYER_TYPE_HARDWARE, null); + fadeAnimator = ViewCompat.animate(CompassView.this).alpha(0.0f).setDuration(TIME_FADE_ANIMATION); + fadeAnimator.setListener(new ViewPropertyAnimatorListenerAdapter() { + @Override + public void onAnimationEnd(View view) { + setLayerType(LAYER_TYPE_NONE, null); + setVisibility(View.INVISIBLE); + resetAnimation(); } + }); } + } - public void update(final double direction) { - this.direction = direction; + static class CompassClickListener implements View.OnClickListener { - if (!isEnabled()) { - return; - } - - if (isHidden()) { - if (getVisibility() == View.INVISIBLE || fadeAnimator != null) { - return; - } - postDelayed(this, TIME_WAIT_IDLE); - return; - } else { - resetAnimation(); - setAlpha(1.0f); - setVisibility(View.VISIBLE); - } + private WeakReference<MapboxMap> mapboxMap; + private WeakReference<CompassView> compassView; - setRotation((float) direction); - } - - public void fadeCompassViewFacingNorth(boolean compassFadeFacingNorth) { - fadeCompassViewFacingNorth = compassFadeFacingNorth; - } - - public boolean isFadeCompassViewFacingNorth(){ - return fadeCompassViewFacingNorth; + CompassClickListener(final MapboxMap mapboxMap, CompassView compassView) { + this.mapboxMap = new WeakReference<>(mapboxMap); + this.compassView = new WeakReference<>(compassView); } @Override - public void run() { - if (isFacingNorth() && fadeCompassViewFacingNorth) { - resetAnimation(); - setLayerType(View.LAYER_TYPE_HARDWARE, null); - fadeAnimator = ViewCompat.animate(CompassView.this).alpha(0.0f).setDuration(TIME_FADE_ANIMATION); - fadeAnimator.setListener(new ViewPropertyAnimatorListenerAdapter() { - @Override - public void onAnimationEnd(View view) { - setLayerType(LAYER_TYPE_NONE, null); - setVisibility(View.INVISIBLE); - resetAnimation(); - } - }); - } - } - - static class CompassClickListener implements View.OnClickListener { - - private WeakReference<MapboxMap> mapboxMap; - private WeakReference<CompassView> compassView; - - CompassClickListener(final MapboxMap mapboxMap, CompassView compassView) { - this.mapboxMap = new WeakReference<>(mapboxMap); - this.compassView = new WeakReference<>(compassView); - } - - @Override - public void onClick(View view) { - final MapboxMap mapboxMap = this.mapboxMap.get(); - final CompassView compassView = this.compassView.get(); - if (mapboxMap != null && compassView != null) { - mapboxMap.resetNorth(); - compassView.postDelayed(compassView, TIME_WAIT_IDLE + TIME_MAP_NORTH_ANIMATION); - } - } + public void onClick(View view) { + final MapboxMap mapboxMap = this.mapboxMap.get(); + final CompassView compassView = this.compassView.get(); + if (mapboxMap != null && compassView != null) { + mapboxMap.resetNorth(); + compassView.postDelayed(compassView, TIME_WAIT_IDLE + TIME_MAP_NORTH_ANIMATION); + } } + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java index 677b59bea8..d34b0f693d 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java @@ -4,7 +4,6 @@ import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Camera; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PointF; @@ -44,745 +43,753 @@ import java.lang.ref.WeakReference; */ public class MyLocationView extends View { - private MyLocationBehavior myLocationBehavior; - private MapboxMap mapboxMap; + private MyLocationBehavior myLocationBehavior; + private MapboxMap mapboxMap; - private Projection projection; - private float[] projectedCoordinate = new float[2]; - private float projectedX; - private float projectedY; + private Projection projection; + private float[] projectedCoordinate = new float[2]; + private float projectedX; + private float projectedY; - private float contentPaddingX; - private float contentPaddingY; + private float contentPaddingX; + private float contentPaddingY; - private LatLng latLng; - private Location location; - private long locationUpdateTimestamp; - private float previousDirection; + private LatLng latLng; + private Location location; + private long locationUpdateTimestamp; + private float previousDirection; - private float accuracy; - private Paint accuracyPaint; + private float accuracy; + private Paint accuracyPaint; - private ValueAnimator locationChangeAnimator; - private ValueAnimator accuracyAnimator; - private ValueAnimator directionAnimator; + private ValueAnimator locationChangeAnimator; + private ValueAnimator accuracyAnimator; + private ValueAnimator directionAnimator; - private ValueAnimator.AnimatorUpdateListener invalidateSelfOnUpdateListener = - new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - invalidate(); - } - }; - - private Drawable foregroundDrawable; - private Drawable foregroundBearingDrawable; - private Drawable backgroundDrawable; - - private Rect foregroundBounds; - private Rect backgroundBounds; - - private int backgroundOffsetLeft; - private int backgroundOffsetTop; - private int backgroundOffsetRight; - private int backgroundOffsetBottom; - - private Matrix matrix; - private Camera camera; - private PointF screenLocation; + private ValueAnimator.AnimatorUpdateListener invalidateSelfOnUpdateListener = + new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + invalidate(); + } + }; - // camera vars - private double tilt; - private double bearing; - private float magneticHeading; + private Drawable foregroundDrawable; + private Drawable foregroundBearingDrawable; + private Drawable backgroundDrawable; - // Controls the compass update rate in milliseconds - private static final int COMPASS_UPDATE_RATE_MS = 500; + private Rect foregroundBounds; + private Rect backgroundBounds; - @MyLocationTracking.Mode - private int myLocationTrackingMode; + private int backgroundOffsetLeft; + private int backgroundOffsetTop; + private int backgroundOffsetRight; + private int backgroundOffsetBottom; - @MyBearingTracking.Mode - private int myBearingTrackingMode; + private Matrix matrix; + private Camera camera; + private PointF screenLocation; - private GpsLocationListener userLocationListener; - private CompassListener compassListener; + // camera vars + private double tilt; + private double bearing; + private float magneticHeading; - public MyLocationView(Context context) { - super(context); - init(context); - } + // Controls the compass update rate in milliseconds + private static final int COMPASS_UPDATE_RATE_MS = 500; - public MyLocationView(Context context, AttributeSet attrs) { - super(context, attrs); - init(context); - } + @MyLocationTracking.Mode + private int myLocationTrackingMode; - public MyLocationView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context); - } + @MyBearingTracking.Mode + private int myBearingTrackingMode; - private void init(Context context) { - if (isInEditMode()) { - return; - } + private GpsLocationListener userLocationListener; + private CompassListener compassListener; - setEnabled(false); + public MyLocationView(Context context) { + super(context); + init(context); + } - // setup LayoutParams - ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT); - setLayoutParams(lp); + public MyLocationView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + } - matrix = new Matrix(); - camera = new Camera(); - camera.setLocation(0, 0, -1000); - accuracyPaint = new Paint(); + public MyLocationView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context); + } - myLocationBehavior = new MyLocationBehaviorFactory().getBehavioralModel(MyLocationTracking.TRACKING_NONE); - compassListener = new CompassListener(context); + private void init(Context context) { + if (isInEditMode()) { + return; } - public final void setForegroundDrawables(Drawable defaultDrawable, Drawable bearingDrawable) { - if (defaultDrawable == null) { - return; - } + setEnabled(false); - if (bearingDrawable == null) { - // if user only provided one resource - // use same for bearing mode - bearingDrawable = defaultDrawable.getConstantState().newDrawable(); - } + // setup LayoutParams + ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT); + setLayoutParams(lp); - if (backgroundDrawable == null) { - // if the user didn't provide a background resource we will use the foreground resource instead, - // we need to create a new drawable to handle tinting correctly - backgroundDrawable = defaultDrawable.getConstantState().newDrawable(); - } + matrix = new Matrix(); + camera = new Camera(); + camera.setLocation(0, 0, -1000); + accuracyPaint = new Paint(); - if (defaultDrawable.getIntrinsicWidth() != bearingDrawable.getIntrinsicWidth() || defaultDrawable.getIntrinsicHeight() != bearingDrawable.getIntrinsicHeight()) { - throw new RuntimeException("The dimensions from location and bearing drawables should be match"); - } + myLocationBehavior = new MyLocationBehaviorFactory().getBehavioralModel(MyLocationTracking.TRACKING_NONE); + compassListener = new CompassListener(context); + } - foregroundDrawable = defaultDrawable; - foregroundBearingDrawable = bearingDrawable; + public final void setForegroundDrawables(Drawable defaultDrawable, Drawable bearingDrawable) { + if (defaultDrawable == null) { + return; + } - invalidateBounds(); + if (bearingDrawable == null) { + // if user only provided one resource + // use same for bearing mode + bearingDrawable = defaultDrawable.getConstantState().newDrawable(); } - public final void setForegroundDrawableTint(@ColorInt int color) { - if (foregroundDrawable != null) { - foregroundDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN); - } - if (foregroundBearingDrawable != null) { - foregroundBearingDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN); - } - invalidate(); + if (backgroundDrawable == null) { + // if the user didn't provide a background resource we will use the foreground resource instead, + // we need to create a new drawable to handle tinting correctly + backgroundDrawable = defaultDrawable.getConstantState().newDrawable(); } - public final void setShadowDrawable(Drawable drawable) { - setShadowDrawable(drawable, 0, 0, 0, 0); + if (defaultDrawable.getIntrinsicWidth() != bearingDrawable.getIntrinsicWidth() + || defaultDrawable.getIntrinsicHeight() != bearingDrawable.getIntrinsicHeight()) { + throw new RuntimeException("The dimensions from location and bearing drawables should be match"); } - public final void setShadowDrawable(Drawable drawable, int left, int top, int right, int bottom) { - if (drawable != null) { - backgroundDrawable = drawable; - } + foregroundDrawable = defaultDrawable; + foregroundBearingDrawable = bearingDrawable; - backgroundOffsetLeft = left; - backgroundOffsetTop = top; - backgroundOffsetRight = right; - backgroundOffsetBottom = bottom; + invalidateBounds(); + } - invalidateBounds(); + public final void setForegroundDrawableTint(@ColorInt int color) { + if (foregroundDrawable != null) { + foregroundDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN); } - - public final void setShadowDrawableTint(@ColorInt int color) { - if (backgroundDrawable == null) { - return; - } - backgroundDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN); - invalidate(); + if (foregroundBearingDrawable != null) { + foregroundBearingDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN); } + invalidate(); + } - public final void setAccuracyTint(@ColorInt int color) { - int alpha = accuracyPaint.getAlpha(); - accuracyPaint.setColor(color); - accuracyPaint.setAlpha(alpha); - invalidate(); - } + public final void setShadowDrawable(Drawable drawable) { + setShadowDrawable(drawable, 0, 0, 0, 0); + } - public final void setAccuracyAlpha(@IntRange(from = 0, to = 255) int alpha) { - accuracyPaint.setAlpha(alpha); - invalidate(); + public final void setShadowDrawable(Drawable drawable, int left, int top, int right, int bottom) { + if (drawable != null) { + backgroundDrawable = drawable; } - private void invalidateBounds() { - if (backgroundDrawable == null || foregroundDrawable == null || foregroundBearingDrawable == null) { - return; - } - - int backgroundWidth = backgroundDrawable.getIntrinsicWidth(); - int backgroundHeight = backgroundDrawable.getIntrinsicHeight(); - int horizontalOffset = backgroundOffsetLeft - backgroundOffsetRight; - int verticalOffset = backgroundOffsetTop - backgroundOffsetBottom; - backgroundBounds = new Rect(-backgroundWidth / 2 + horizontalOffset, -backgroundHeight / 2 + verticalOffset, backgroundWidth / 2 + horizontalOffset, backgroundHeight / 2 + verticalOffset); - backgroundDrawable.setBounds(backgroundBounds); + backgroundOffsetLeft = left; + backgroundOffsetTop = top; + backgroundOffsetRight = right; + backgroundOffsetBottom = bottom; - int foregroundWidth = foregroundDrawable.getIntrinsicWidth(); - int foregroundHeight = foregroundDrawable.getIntrinsicHeight(); - foregroundBounds = new Rect(-foregroundWidth / 2, -foregroundHeight / 2, foregroundWidth / 2, foregroundHeight / 2); - foregroundDrawable.setBounds(foregroundBounds); - foregroundBearingDrawable.setBounds(foregroundBounds); + invalidateBounds(); + } - // invoke a new draw - invalidate(); + public final void setShadowDrawableTint(@ColorInt int color) { + if (backgroundDrawable == null) { + return; } + backgroundDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN); + invalidate(); + } - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - if (location == null || foregroundBounds == null || backgroundBounds == null || accuracyAnimator == null || screenLocation == null) { - // Not ready yet - return; - } - - final PointF pointF = screenLocation; - float metersPerPixel = (float) projection.getMetersPerPixelAtLatitude(location.getLatitude()); - float accuracyPixels = (Float) accuracyAnimator.getAnimatedValue() / metersPerPixel / 2; - float maxRadius = getWidth() / 2; - accuracyPixels = accuracyPixels <= maxRadius ? accuracyPixels : maxRadius; - - // reset - matrix.reset(); - projectedCoordinate[0] = 0; - projectedCoordinate[1] = 0; + public final void setAccuracyTint(@ColorInt int color) { + int alpha = accuracyPaint.getAlpha(); + accuracyPaint.setColor(color); + accuracyPaint.setAlpha(alpha); + invalidate(); + } - // put camera in position - camera.save(); - camera.rotate((float) tilt, 0, 0); - camera.getMatrix(matrix); + public final void setAccuracyAlpha(@IntRange(from = 0, to = 255) int alpha) { + accuracyPaint.setAlpha(alpha); + invalidate(); + } - if (myBearingTrackingMode != MyBearingTracking.NONE && directionAnimator != null) { - matrix.preRotate((Float) directionAnimator.getAnimatedValue()); - } - - matrix.preTranslate(0, contentPaddingY); - matrix.postTranslate(pointF.x, pointF.y - contentPaddingY); - - // concat our matrix on canvas - canvas.concat(matrix); + private void invalidateBounds() { + if (backgroundDrawable == null || foregroundDrawable == null || foregroundBearingDrawable == null) { + return; + } - // calculate focal point - matrix.mapPoints(projectedCoordinate); - projectedX = pointF.x - projectedCoordinate[0]; - projectedY = pointF.y - projectedCoordinate[1]; + int backgroundWidth = backgroundDrawable.getIntrinsicWidth(); + int backgroundHeight = backgroundDrawable.getIntrinsicHeight(); + int horizontalOffset = backgroundOffsetLeft - backgroundOffsetRight; + int verticalOffset = backgroundOffsetTop - backgroundOffsetBottom; + backgroundBounds = new Rect(-backgroundWidth / 2 + horizontalOffset, + -backgroundHeight / 2 + verticalOffset, backgroundWidth / 2 + horizontalOffset, backgroundHeight / 2 + + verticalOffset); + backgroundDrawable.setBounds(backgroundBounds); - // restore orientation from camera - camera.restore(); + int foregroundWidth = foregroundDrawable.getIntrinsicWidth(); + int foregroundHeight = foregroundDrawable.getIntrinsicHeight(); + foregroundBounds = new Rect(-foregroundWidth / 2, -foregroundHeight / 2, foregroundWidth / 2, foregroundHeight / 2); + foregroundDrawable.setBounds(foregroundBounds); + foregroundBearingDrawable.setBounds(foregroundBounds); - // draw circle - canvas.drawCircle(0, 0, accuracyPixels, accuracyPaint); + // invoke a new draw + invalidate(); + } - // draw shadow - if (backgroundDrawable != null) { - backgroundDrawable.draw(canvas); - } + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); - // draw foreground - if (myBearingTrackingMode == MyBearingTracking.NONE) { - if (foregroundDrawable != null) { - foregroundDrawable.draw(canvas); - } - } else if (foregroundBearingDrawable != null && foregroundBounds != null) { - foregroundBearingDrawable.draw(canvas); - } + if (location == null || foregroundBounds == null || backgroundBounds == null || accuracyAnimator == null + || screenLocation == null) { + // Not ready yet + return; } - public void setTilt(@FloatRange(from = 0, to = 60.0f) double tilt) { - this.tilt = tilt; - if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { - mapboxMap.getUiSettings().setFocalPoint(new PointF(getCenterX(), getCenterY())); - } - } + final PointF pointF = screenLocation; + float metersPerPixel = (float) projection.getMetersPerPixelAtLatitude(location.getLatitude()); + float accuracyPixels = (Float) accuracyAnimator.getAnimatedValue() / metersPerPixel / 2; + float maxRadius = getWidth() / 2; + accuracyPixels = accuracyPixels <= maxRadius ? accuracyPixels : maxRadius; - public void setBearing(double bearing) { - this.bearing = bearing; - if (myLocationTrackingMode == MyLocationTracking.TRACKING_NONE) { - if (myBearingTrackingMode == MyBearingTracking.GPS) { - setCompass(location.getBearing() - bearing); - } else if (myBearingTrackingMode == MyBearingTracking.COMPASS) { - setCompass(magneticHeading - bearing); - } - } - } + // reset + matrix.reset(); + projectedCoordinate[0] = 0; + projectedCoordinate[1] = 0; - public void setCameraPosition(CameraPosition position) { - if (position != null) { - setTilt(position.tilt); - setBearing(position.bearing); - } - } + // put camera in position + camera.save(); + camera.rotate((float) tilt, 0, 0); + camera.getMatrix(matrix); - public void onStart() { - if (myBearingTrackingMode == MyBearingTracking.COMPASS) { - compassListener.onResume(); - } - if (isEnabled()) { - toggleGps(true); - } + if (myBearingTrackingMode != MyBearingTracking.NONE && directionAnimator != null) { + matrix.preRotate((Float) directionAnimator.getAnimatedValue()); } - public void onStop() { - compassListener.onPause(); - toggleGps(false); - } + matrix.preTranslate(0, contentPaddingY); + matrix.postTranslate(pointF.x, pointF.y - contentPaddingY); - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - // cleanup to prevent memory leaks - if (locationChangeAnimator != null) { - locationChangeAnimator.cancel(); - locationChangeAnimator = null; - } + // concat our matrix on canvas + canvas.concat(matrix); - if (accuracyAnimator != null) { - accuracyAnimator.cancel(); - accuracyAnimator = null; - } + // calculate focal point + matrix.mapPoints(projectedCoordinate); + projectedX = pointF.x - projectedCoordinate[0]; + projectedY = pointF.y - projectedCoordinate[1]; - if (directionAnimator != null) { - directionAnimator.cancel(); - directionAnimator = null; - } + // restore orientation from camera + camera.restore(); - if (userLocationListener != null) { - LocationServices services = LocationServices.getLocationServices(getContext()); - services.removeLocationListener(userLocationListener); - userLocationListener = null; - } - } + // draw circle + canvas.drawCircle(0, 0, accuracyPixels, accuracyPaint); - public void update() { - if (isEnabled()) { - myLocationBehavior.invalidate(); - } else { - setVisibility(View.INVISIBLE); - } + // draw shadow + if (backgroundDrawable != null) { + backgroundDrawable.draw(canvas); } - // TODO refactor MapboxMap out - public void setMapboxMap(MapboxMap mapboxMap) { - this.mapboxMap = mapboxMap; - this.projection = mapboxMap.getProjection(); - } + // draw foreground + if (myBearingTrackingMode == MyBearingTracking.NONE) { + if (foregroundDrawable != null) { + foregroundDrawable.draw(canvas); + } + } else if (foregroundBearingDrawable != null && foregroundBounds != null) { + foregroundBearingDrawable.draw(canvas); + } + } + + public void setTilt(@FloatRange(from = 0, to = 60.0f) double tilt) { + this.tilt = tilt; + if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { + mapboxMap.getUiSettings().setFocalPoint(new PointF(getCenterX(), getCenterY())); + } + } + + public void setBearing(double bearing) { + this.bearing = bearing; + if (myLocationTrackingMode == MyLocationTracking.TRACKING_NONE) { + if (myBearingTrackingMode == MyBearingTracking.GPS) { + setCompass(location.getBearing() - bearing); + } else if (myBearingTrackingMode == MyBearingTracking.COMPASS) { + setCompass(magneticHeading - bearing); + } + } + } + + public void setCameraPosition(CameraPosition position) { + if (position != null) { + setTilt(position.tilt); + setBearing(position.bearing); + } + } + + public void onStart() { + if (myBearingTrackingMode == MyBearingTracking.COMPASS) { + compassListener.onResume(); + } + if (isEnabled()) { + toggleGps(true); + } + } - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - setVisibility(enabled ? View.VISIBLE : View.INVISIBLE); - toggleGps(enabled); + public void onStop() { + compassListener.onPause(); + toggleGps(false); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + // cleanup to prevent memory leaks + if (locationChangeAnimator != null) { + locationChangeAnimator.cancel(); + locationChangeAnimator = null; } - @Override - protected Parcelable onSaveInstanceState() { - Bundle bundle = new Bundle(); - bundle.putParcelable("superState", super.onSaveInstanceState()); - bundle.putDouble("tilt", tilt); - return bundle; + if (accuracyAnimator != null) { + accuracyAnimator.cancel(); + accuracyAnimator = null; + } + + if (directionAnimator != null) { + directionAnimator.cancel(); + directionAnimator = null; + } + + if (userLocationListener != null) { + LocationServices services = LocationServices.getLocationServices(getContext()); + services.removeLocationListener(userLocationListener); + userLocationListener = null; + } + } + + public void update() { + if (isEnabled()) { + myLocationBehavior.invalidate(); + } else { + setVisibility(View.INVISIBLE); + } + } + + // TODO refactor MapboxMap out + public void setMapboxMap(MapboxMap mapboxMap) { + this.mapboxMap = mapboxMap; + this.projection = mapboxMap.getProjection(); + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + setVisibility(enabled ? View.VISIBLE : View.INVISIBLE); + toggleGps(enabled); + } + + @Override + protected Parcelable onSaveInstanceState() { + Bundle bundle = new Bundle(); + bundle.putParcelable("superState", super.onSaveInstanceState()); + bundle.putDouble("tilt", tilt); + return bundle; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + if (state instanceof Bundle) { + Bundle bundle = (Bundle) state; + tilt = bundle.getDouble("tilt"); + state = bundle.getParcelable("superState"); + } + super.onRestoreInstanceState(state); + } + + /** + * Enabled / Disable GPS location updates along with updating the UI + * + * @param enableGps true if GPS is to be enabled, false if GPS is to be disabled + */ + private void toggleGps(boolean enableGps) { + LocationServices locationServices = LocationServices.getLocationServices(getContext()); + if (enableGps) { + // Set an initial location if one available + Location lastLocation = locationServices.getLastLocation(); + + if (lastLocation != null) { + setLocation(lastLocation); + } + + if (userLocationListener == null) { + userLocationListener = new GpsLocationListener(this); + } + + locationServices.addLocationListener(userLocationListener); + } else { + // Disable location and user dot + location = null; + locationServices.removeLocationListener(userLocationListener); + } + + locationServices.toggleGPS(enableGps); + } + + public Location getLocation() { + return location; + } + + public void setLocation(Location location) { + if (location == null) { + this.location = null; + return; + } + + this.location = location; + myLocationBehavior.updateLatLng(location); + } + + public void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) { + this.myBearingTrackingMode = myBearingTrackingMode; + if (myBearingTrackingMode == MyBearingTracking.COMPASS) { + compassListener.onResume(); + } else { + compassListener.onPause(); + if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { + // always face north + setCompass(0); + } else { + myLocationBehavior.invalidate(); + } + } + invalidate(); + } + + public void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) { + MyLocationBehaviorFactory factory = new MyLocationBehaviorFactory(); + myLocationBehavior = factory.getBehavioralModel(myLocationTrackingMode); + + if (location != null) { + if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { + // center map directly + mapboxMap.easeCamera(CameraUpdateFactory.newLatLng(new LatLng(location)), 0, false /*linear interpolator*/, + false /*do not disable tracking*/, null); + } else { + // do not use interpolated location from tracking mode + latLng = null; + } + myLocationBehavior.updateLatLng(location); + } + + this.myLocationTrackingMode = myLocationTrackingMode; + invalidate(); + } + + @MyLocationTracking.Mode + public int getMyLocationTrackingMode() { + return myLocationTrackingMode; + } + + + @MyBearingTracking.Mode + public int getMyBearingTrackingMode() { + return myBearingTrackingMode; + } + + private void setCompass(double bearing) { + setCompass(bearing, 0 /* no animation */); + } + + private void setCompass(double bearing, long duration) { + float oldDir = previousDirection; + if (directionAnimator != null) { + oldDir = (Float) directionAnimator.getAnimatedValue(); + directionAnimator.end(); + directionAnimator = null; + } + + float newDir = (float) bearing; + float diff = oldDir - newDir; + if (diff > 180.0f) { + newDir += 360.0f; + } else if (diff < -180.0f) { + newDir -= 360.f; } + previousDirection = newDir; - @Override - public void onRestoreInstanceState(Parcelable state) { - if (state instanceof Bundle) { - Bundle bundle = (Bundle) state; - tilt = bundle.getDouble("tilt"); - state = bundle.getParcelable("superState"); - } - super.onRestoreInstanceState(state); - } + directionAnimator = ValueAnimator.ofFloat(oldDir, newDir); + directionAnimator.setDuration(duration); + directionAnimator.addUpdateListener(invalidateSelfOnUpdateListener); + directionAnimator.start(); + } - /** - * Enabled / Disable GPS location updates along with updating the UI - * - * @param enableGps true if GPS is to be enabled, false if GPS is to be disabled - */ - private void toggleGps(boolean enableGps) { - LocationServices locationServices = LocationServices.getLocationServices(getContext()); - if (enableGps) { - // Set an initial location if one available - Location lastLocation = locationServices.getLastLocation(); - - if (lastLocation != null) { - setLocation(lastLocation); - } + public float getCenterX() { + return (getX() + getMeasuredWidth()) / 2 + contentPaddingX - projectedX; + } - if (userLocationListener == null) { - userLocationListener = new GpsLocationListener(this); - } + public float getCenterY() { + return (getY() + getMeasuredHeight()) / 2 + contentPaddingY - projectedY; + } - locationServices.addLocationListener(userLocationListener); - } else { - // Disable location and user dot - location = null; - locationServices.removeLocationListener(userLocationListener); - } + public void setContentPadding(int[] padding) { + contentPaddingX = (padding[0] - padding[2]) / 2; + contentPaddingY = (padding[1] - padding[3]) / 2; + } + + private static class GpsLocationListener implements LocationListener { - locationServices.toggleGPS(enableGps); + private WeakReference<MyLocationView> userLocationView; + + GpsLocationListener(MyLocationView myLocationView) { + userLocationView = new WeakReference<>(myLocationView); } - public Location getLocation() { - return location; + /** + * Callback method for receiving location updates from LocationServices. + * + * @param location The new Location data + */ + @Override + public void onLocationChanged(Location location) { + MyLocationView locationView = userLocationView.get(); + if (locationView != null) { + locationView.setLocation(location); + } } + } - public void setLocation(Location location) { - if (location == null) { - this.location = null; - return; - } + private class CompassListener implements SensorEventListener { - this.location = location; - myLocationBehavior.updateLatLng(location); - } + private final SensorManager sensorManager; - public void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) { - this.myBearingTrackingMode = myBearingTrackingMode; - if (myBearingTrackingMode == MyBearingTracking.COMPASS) { - compassListener.onResume(); - } else { - compassListener.onPause(); - if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { - // always face north - setCompass(0); - } else { - myLocationBehavior.invalidate(); - } - } - invalidate(); - } + private Sensor rotationVectorSensor; + float[] matrix = new float[9]; + float[] orientation = new float[3]; - public void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) { - MyLocationBehaviorFactory factory = new MyLocationBehaviorFactory(); - myLocationBehavior = factory.getBehavioralModel(myLocationTrackingMode); + // Compass data + private long compassUpdateNextTimestamp = 0; - if (location != null) { - if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { - // center map directly - mapboxMap.easeCamera(CameraUpdateFactory.newLatLng(new LatLng(location)), 0, false /*linear interpolator*/, false /*do not disable tracking*/, null); - } else { - // do not use interpolated location from tracking mode - latLng = null; - } - myLocationBehavior.updateLatLng(location); - } + CompassListener(Context context) { + sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); + rotationVectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR); + } - this.myLocationTrackingMode = myLocationTrackingMode; - invalidate(); + public void onResume() { + sensorManager.registerListener(this, rotationVectorSensor, SensorManager.SENSOR_DELAY_GAME); } - @MyLocationTracking.Mode - public int getMyLocationTrackingMode() { - return myLocationTrackingMode; + public void onPause() { + sensorManager.unregisterListener(this, rotationVectorSensor); } + @Override + public void onSensorChanged(SensorEvent event) { - @MyBearingTracking.Mode - public int getMyBearingTrackingMode() { - return myBearingTrackingMode; - } + // check when the last time the compass was updated, return if too soon. + long currentTime = SystemClock.elapsedRealtime(); + if (currentTime < compassUpdateNextTimestamp) { + return; + } - private void setCompass(double bearing) { - setCompass(bearing, 0 /* no animation */); - } + if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) { - private void setCompass(double bearing, long duration) { - float oldDir = previousDirection; - if (directionAnimator != null) { - oldDir = (Float) directionAnimator.getAnimatedValue(); - directionAnimator.end(); - directionAnimator = null; - } + // calculate the rotation matrix + SensorManager.getRotationMatrixFromVector(matrix, event.values); + SensorManager.getOrientation(matrix, orientation); - float newDir = (float) bearing; - float diff = oldDir - newDir; - if (diff > 180.0f) { - newDir += 360.0f; - } else if (diff < -180.0f) { - newDir -= 360.f; + magneticHeading = (float) Math.toDegrees(SensorManager.getOrientation(matrix, orientation)[0]); + if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { + // Change the user location view orientation to reflect the device orientation + rotateCamera(magneticHeading); + setCompass(0, COMPASS_UPDATE_RATE_MS); + } else { + // Change compass direction + setCompass(magneticHeading - bearing, COMPASS_UPDATE_RATE_MS); } - previousDirection = newDir; - - directionAnimator = ValueAnimator.ofFloat(oldDir, newDir); - directionAnimator.setDuration(duration); - directionAnimator.addUpdateListener(invalidateSelfOnUpdateListener); - directionAnimator.start(); - } - public float getCenterX() { - return (getX() + getMeasuredWidth()) / 2 + contentPaddingX - projectedX; + compassUpdateNextTimestamp = currentTime + COMPASS_UPDATE_RATE_MS; + } } - public float getCenterY() { - return (getY() + getMeasuredHeight()) / 2 + contentPaddingY - projectedY; + private void rotateCamera(float rotation) { + CameraPosition.Builder builder = new CameraPosition.Builder(); + builder.bearing(rotation); + mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(builder.build()), COMPASS_UPDATE_RATE_MS, + false /*linear interpolator*/, false /*do not disable tracking*/, null); } - public void setContentPadding(int[] padding) { - contentPaddingX = (padding[0] - padding[2]) / 2; - contentPaddingY = (padding[1] - padding[3]) / 2; + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { } - private static class GpsLocationListener implements LocationListener { + } - private WeakReference<MyLocationView> userLocationView; + private class MarkerCoordinateAnimatorListener implements ValueAnimator.AnimatorUpdateListener { - GpsLocationListener(MyLocationView myLocationView) { - userLocationView = new WeakReference<>(myLocationView); - } + private MyLocationBehavior behavior; + private double fromLat; + private double fromLng; + private double toLat; + private double toLng; - /** - * Callback method for receiving location updates from LocationServices. - * - * @param location The new Location data - */ - @Override - public void onLocationChanged(Location location) { - MyLocationView locationView = userLocationView.get(); - if (locationView != null) { - locationView.setLocation(location); - } - } + private MarkerCoordinateAnimatorListener(MyLocationBehavior myLocationBehavior, LatLng from, LatLng to) { + behavior = myLocationBehavior; + fromLat = from.getLatitude(); + fromLng = from.getLongitude(); + toLat = to.getLatitude(); + toLng = to.getLongitude(); } - private class CompassListener implements SensorEventListener { - - private final SensorManager sensorManager; - - private Sensor rotationVectorSensor; - float[] matrix = new float[9]; - float[] orientation = new float[3]; - - // Compass data - private long compassUpdateNextTimestamp = 0; - - CompassListener(Context context) { - sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); - rotationVectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR); - } - - public void onResume() { - sensorManager.registerListener(this, rotationVectorSensor, SensorManager.SENSOR_DELAY_GAME); - } - - public void onPause() { - sensorManager.unregisterListener(this, rotationVectorSensor); - } - - @Override - public void onSensorChanged(SensorEvent event) { - - // check when the last time the compass was updated, return if too soon. - long currentTime = SystemClock.elapsedRealtime(); - if (currentTime < compassUpdateNextTimestamp) { - return; - } - - if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) { - - // calculate the rotation matrix - SensorManager.getRotationMatrixFromVector(matrix, event.values); - SensorManager.getOrientation(matrix, orientation); - - magneticHeading = (float) Math.toDegrees(SensorManager.getOrientation(matrix, orientation)[0]); - if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { - // Change the user location view orientation to reflect the device orientation - rotateCamera(magneticHeading); - setCompass(0, COMPASS_UPDATE_RATE_MS); - } else { - // Change compass direction - setCompass(magneticHeading - bearing, COMPASS_UPDATE_RATE_MS); - } - - compassUpdateNextTimestamp = currentTime + COMPASS_UPDATE_RATE_MS; - } - } - - private void rotateCamera(float rotation) { - CameraPosition.Builder builder = new CameraPosition.Builder(); - builder.bearing(rotation); - mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(builder.build()), COMPASS_UPDATE_RATE_MS, false /*linear interpolator*/, false /*do not disable tracking*/, null); - } + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float frac = animation.getAnimatedFraction(); + double latitude = fromLat + (toLat - fromLat) * frac; + double longitude = fromLng + (toLng - fromLng) * frac; + behavior.updateLatLng(latitude, longitude); + update(); + } + } - @Override - public void onAccuracyChanged(Sensor sensor, int accuracy) { - } + private class MyLocationBehaviorFactory { + MyLocationBehavior getBehavioralModel(@MyLocationTracking.Mode int mode) { + if (mode == MyLocationTracking.TRACKING_NONE) { + return new MyLocationShowBehavior(); + } else { + return new MyLocationTrackingBehavior(); + } } + } - private class MarkerCoordinateAnimatorListener implements ValueAnimator.AnimatorUpdateListener { + private abstract class MyLocationBehavior { - private MyLocationBehavior behavior; - private double fromLat; - private double fromLng; - private double toLat; - private double toLng; - - private MarkerCoordinateAnimatorListener(MyLocationBehavior myLocationBehavior, LatLng from, LatLng to) { - behavior = myLocationBehavior; - fromLat = from.getLatitude(); - fromLng = from.getLongitude(); - toLat = to.getLatitude(); - toLng = to.getLongitude(); - } + void updateLatLng(@NonNull Location newLocation) { + location = newLocation; + } - @Override - public void onAnimationUpdate(ValueAnimator animation) { - float frac = animation.getAnimatedFraction(); - double latitude = fromLat + (toLat - fromLat) * frac; - double longitude = fromLng + (toLng - fromLng) * frac; - behavior.updateLatLng(latitude, longitude); - update(); - } + void updateLatLng(double lat, double lon) { + if (latLng != null) { + latLng.setLatitude(lat); + latLng.setLongitude(lon); + } } - private class MyLocationBehaviorFactory { + void updateAccuracy(@NonNull Location location) { + if (accuracyAnimator != null && accuracyAnimator.isRunning()) { + // use current accuracy as a starting point + accuracy = (Float) accuracyAnimator.getAnimatedValue(); + accuracyAnimator.end(); + } - MyLocationBehavior getBehavioralModel(@MyLocationTracking.Mode int mode) { - if (mode == MyLocationTracking.TRACKING_NONE) { - return new MyLocationShowBehavior(); - } else { - return new MyLocationTrackingBehavior(); - } - } + accuracyAnimator = ValueAnimator.ofFloat(accuracy * 10, location.getAccuracy() * 10); + accuracyAnimator.setDuration(750); + accuracyAnimator.start(); + accuracy = location.getAccuracy(); } - private abstract class MyLocationBehavior { + abstract void invalidate(); + } - void updateLatLng(@NonNull Location newLocation) { - location = newLocation; - } + private class MyLocationTrackingBehavior extends MyLocationBehavior { - void updateLatLng(double lat, double lon) { - if (latLng != null) { - latLng.setLatitude(lat); - latLng.setLongitude(lon); - } - } + @Override + void updateLatLng(@NonNull Location location) { + super.updateLatLng(location); + if (latLng == null) { + // first location fix + latLng = new LatLng(location); + locationUpdateTimestamp = SystemClock.elapsedRealtime(); + } + + // updateLatLng timestamp + float previousUpdateTimeStamp = locationUpdateTimestamp; + locationUpdateTimestamp = SystemClock.elapsedRealtime(); + + // calculate animation duration + float animationDuration; + if (previousUpdateTimeStamp == 0) { + animationDuration = 0; + } else { + animationDuration = (locationUpdateTimestamp - previousUpdateTimeStamp) * 1.1f + /*make animation slightly longer*/; + } + + // calculate interpolated location + latLng = new LatLng(location); + CameraPosition.Builder builder = new CameraPosition.Builder().target(latLng); + + // add direction + if (myBearingTrackingMode == MyBearingTracking.GPS) { + if (location.hasBearing()) { + builder.bearing(location.getBearing()); + } + setCompass(0, COMPASS_UPDATE_RATE_MS); + } + + // accuracy + updateAccuracy(location); + + // ease to new camera position with a linear interpolator + mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(builder.build()), (int) animationDuration, + false /*linear interpolator*/, false /*do not disable tracking*/, null); + } - void updateAccuracy(@NonNull Location location) { - if (accuracyAnimator != null && accuracyAnimator.isRunning()) { - // use current accuracy as a starting point - accuracy = (Float) accuracyAnimator.getAnimatedValue(); - accuracyAnimator.end(); - } - - accuracyAnimator = ValueAnimator.ofFloat(accuracy * 10, location.getAccuracy() * 10); - accuracyAnimator.setDuration(750); - accuracyAnimator.start(); - accuracy = location.getAccuracy(); - } + @Override + void invalidate() { + int[] mapPadding = mapboxMap.getPadding(); + float x = (getWidth() + mapPadding[0] - mapPadding[2]) / 2 + contentPaddingX; + float y = (getHeight() - mapPadding[3] + mapPadding[1]) / 2 + contentPaddingY; + screenLocation = new PointF(x, y); + MyLocationView.this.invalidate(); + } + } - abstract void invalidate(); - } - - private class MyLocationTrackingBehavior extends MyLocationBehavior { - - @Override - void updateLatLng(@NonNull Location location) { - super.updateLatLng(location); - if (latLng == null) { - // first location fix - latLng = new LatLng(location); - locationUpdateTimestamp = SystemClock.elapsedRealtime(); - } - - // updateLatLng timestamp - float previousUpdateTimeStamp = locationUpdateTimestamp; - locationUpdateTimestamp = SystemClock.elapsedRealtime(); - - // calculate animation duration - float animationDuration; - if (previousUpdateTimeStamp == 0) { - animationDuration = 0; - } else { - animationDuration = (locationUpdateTimestamp - previousUpdateTimeStamp) * 1.1f /*make animation slightly longer*/; - } - - // calculate interpolated location - latLng = new LatLng(location); - CameraPosition.Builder builder = new CameraPosition.Builder().target(latLng); - - // add direction - if (myBearingTrackingMode == MyBearingTracking.GPS) { - if (location.hasBearing()) { - builder.bearing(location.getBearing()); - } - setCompass(0, COMPASS_UPDATE_RATE_MS); - } - - // accuracy - updateAccuracy(location); - - // ease to new camera position with a linear interpolator - mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(builder.build()), (int) animationDuration, false /*linear interpolator*/, false /*do not disable tracking*/, null); - } + private class MyLocationShowBehavior extends MyLocationBehavior { - @Override - void invalidate() { - int[] mapPadding = mapboxMap.getPadding(); - float x = (getWidth() + mapPadding[0] - mapPadding[2]) / 2 + contentPaddingX; - float y = (getHeight() - mapPadding[3] + mapPadding[1]) / 2 + contentPaddingY; - screenLocation = new PointF(x, y); - MyLocationView.this.invalidate(); - } + @Override + void updateLatLng(@NonNull final Location location) { + super.updateLatLng(location); + if (latLng == null) { + // first location update + latLng = new LatLng(location); + locationUpdateTimestamp = SystemClock.elapsedRealtime(); + } + + // update LatLng location + LatLng newLocation = new LatLng(location); + + // update LatLng accuracy + updateAccuracy(location); + + // calculate updateLatLng time + add some extra offset to improve animation + long previousUpdateTimeStamp = locationUpdateTimestamp; + locationUpdateTimestamp = SystemClock.elapsedRealtime(); + long locationUpdateDuration = (long) ((locationUpdateTimestamp - previousUpdateTimeStamp) * 1.2f); + + // animate changes + if (locationChangeAnimator != null) { + locationChangeAnimator.end(); + locationChangeAnimator = null; + } + + locationChangeAnimator = ValueAnimator.ofFloat(0.0f, 1.0f); + locationChangeAnimator.setDuration(locationUpdateDuration); + locationChangeAnimator.addUpdateListener(new MarkerCoordinateAnimatorListener(this, + latLng, newLocation + )); + locationChangeAnimator.start(); + latLng = newLocation; } - private class MyLocationShowBehavior extends MyLocationBehavior { - - @Override - void updateLatLng(@NonNull final Location location) { - super.updateLatLng(location); - if (latLng == null) { - // first location update - latLng = new LatLng(location); - locationUpdateTimestamp = SystemClock.elapsedRealtime(); - } - - // update LatLng location - LatLng newLocation = new LatLng(location); - - // update LatLng accuracy - updateAccuracy(location); - - // calculate updateLatLng time + add some extra offset to improve animation - long previousUpdateTimeStamp = locationUpdateTimestamp; - locationUpdateTimestamp = SystemClock.elapsedRealtime(); - long locationUpdateDuration = (long) ((locationUpdateTimestamp - previousUpdateTimeStamp) * 1.2f); - - // animate changes - if (locationChangeAnimator != null) { - locationChangeAnimator.end(); - locationChangeAnimator = null; - } - - locationChangeAnimator = ValueAnimator.ofFloat(0.0f, 1.0f); - locationChangeAnimator.setDuration(locationUpdateDuration); - locationChangeAnimator.addUpdateListener(new MarkerCoordinateAnimatorListener(this, - latLng, newLocation - )); - locationChangeAnimator.start(); - latLng = newLocation; - } - - @Override - void invalidate() { - if (latLng != null) { - screenLocation = projection.toScreenLocation(latLng); - } - MyLocationView.this.invalidate(); - } + @Override + void invalidate() { + if (latLng != null) { + screenLocation = projection.toScreenLocation(latLng); + } + MyLocationView.this.invalidate(); } + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java index e85ed96927..6cfbfed733 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java @@ -17,280 +17,282 @@ import com.mapbox.mapboxsdk.maps.Projection; */ public class MyLocationViewSettings { - private Projection projection; - private MyLocationView myLocationView; - private FocalPointChangeListener focalPointChangeListener; - - // - // State - // - - private boolean enabled; - - // - // Foreground - // - - private Drawable foregroundDrawable; - private Drawable foregroundBearingDrawable; - - @ColorInt - private int foregroundTintColor; - - // - // Background - // - - private Drawable backgroundDrawable; - private int[] backgroundOffset = new int[4]; - - @ColorInt - private int backgroundTintColor; - - // - // Accuracy - // - - private int accuracyAlpha; - - @ColorInt - private int accuracyTintColor; - - // - // Padding - // - - private int[] padding = new int[4]; - - /** - * Creates an instance of MyLocationViewSettings - * <p> - * - * @param myLocationView the MyLocationView to apply the settings to - * @param projection the MapView projection - * @param focalPointChangedListener the interface to be invoked when focal points changes - * @see MyLocationView - */ - public MyLocationViewSettings(MyLocationView myLocationView, Projection projection, FocalPointChangeListener focalPointChangedListener) { - this.myLocationView = myLocationView; - this.projection = projection; - this.focalPointChangeListener = focalPointChangedListener; - } - - public void initialise(@NonNull MapboxMapOptions options) { - CameraPosition position = options.getCamera(); - if (position != null && !position.equals(CameraPosition.DEFAULT)) { - setTilt(position.tilt); - } - setForegroundDrawable(options.getMyLocationForegroundDrawable(), options.getMyLocationForegroundBearingDrawable()); - setForegroundTintColor(options.getMyLocationForegroundTintColor()); - setBackgroundDrawable(options.getMyLocationBackgroundDrawable(), options.getMyLocationBackgroundPadding()); - setBackgroundTintColor(options.getMyLocationBackgroundTintColor()); - setAccuracyAlpha(options.getMyLocationAccuracyAlpha()); - setAccuracyTintColor(options.getMyLocationAccuracyTintColor()); - } - - /** - * Returns if the MyLocationView is enabled - * - * @return true if MyLocationView is enabled, - */ - public boolean isEnabled() { - return enabled; - } - - /** - * Set the enabled state of MyLocationView - * - * @param enabled true shows the MyLocationView on the map - */ - public void setEnabled(boolean enabled) { - this.enabled = enabled; - myLocationView.setEnabled(enabled); - } - - /** - * Set the foreground drawable of the MyLocationView - * <p> - * The foreground drawable is the image visible on screen - * </p> - * - * @param foregroundDrawable the drawable to show as foreground without bearing - * @param foregroundBearingDrawable the drawable to show as foreground when bearing is enabled - */ - public void setForegroundDrawable(Drawable foregroundDrawable, Drawable foregroundBearingDrawable) { - this.foregroundDrawable = foregroundDrawable; - this.foregroundBearingDrawable = foregroundBearingDrawable; - myLocationView.setForegroundDrawables(foregroundDrawable, foregroundBearingDrawable); - } - - /** - * Get the foreground drawable when bearing is disabled. - * - * @return the drawable used as foreground - */ - public Drawable getForegroundDrawable() { - return foregroundDrawable; - } - - /** - * Get the foreground drawable when bearing is enabled. - * - * @return the bearing drawable used as foreground - */ - public Drawable getForegroundBearingDrawable() { - return foregroundBearingDrawable; - } - - /** - * Set the foreground tint color. - * <p> - * The color will tint both the foreground and the bearing foreground drawable. - * </p> - * - * @param foregroundTintColor the color to tint the foreground drawable - */ - public void setForegroundTintColor(@ColorInt int foregroundTintColor) { - this.foregroundTintColor = foregroundTintColor; - myLocationView.setForegroundDrawableTint(foregroundTintColor); - } - - /** - * Get the foreground tint color. - * - * @return the foreground tint color - */ - public int getForegroundTintColor() { - return foregroundTintColor; - } - - /** - * Set the background drawable of MyLocationView - * <p> - * Padding can be added to provide an offset to the background - * </p> - * - * @param backgroundDrawable the drawable to show as background - * @param padding the padding added to the background - */ - public void setBackgroundDrawable(Drawable backgroundDrawable, int[] padding) { - this.backgroundDrawable = backgroundDrawable; - this.backgroundOffset = padding; - if (padding != null && padding.length == 4) { - myLocationView.setShadowDrawable(backgroundDrawable, padding[0], padding[1], padding[2], padding[3]); - } else { - myLocationView.setShadowDrawable(backgroundDrawable); - } - } - - /** - * Get the background drawable of MyLocationView. - * - * @return the drawable used as background - */ - public Drawable getBackgroundDrawable() { - return backgroundDrawable; + private Projection projection; + private MyLocationView myLocationView; + private FocalPointChangeListener focalPointChangeListener; + + // + // State + // + + private boolean enabled; + + // + // Foreground + // + + private Drawable foregroundDrawable; + private Drawable foregroundBearingDrawable; + + @ColorInt + private int foregroundTintColor; + + // + // Background + // + + private Drawable backgroundDrawable; + private int[] backgroundOffset = new int[4]; + + @ColorInt + private int backgroundTintColor; + + // + // Accuracy + // + + private int accuracyAlpha; + + @ColorInt + private int accuracyTintColor; + + // + // Padding + // + + private int[] padding = new int[4]; + + /** + * Creates an instance of MyLocationViewSettings + * <p> + * + * @param myLocationView the MyLocationView to apply the settings to + * @param projection the MapView projection + * @param focalPointChangedListener the interface to be invoked when focal points changes + * @see MyLocationView + */ + public MyLocationViewSettings(MyLocationView myLocationView, Projection projection, FocalPointChangeListener + focalPointChangedListener) { + this.myLocationView = myLocationView; + this.projection = projection; + this.focalPointChangeListener = focalPointChangedListener; + } + + public void initialise(@NonNull MapboxMapOptions options) { + CameraPosition position = options.getCamera(); + if (position != null && !position.equals(CameraPosition.DEFAULT)) { + setTilt(position.tilt); } - - /** - * Set the background tint color. - * - * @param backgroundTintColor the color to tint the background - */ - public void setBackgroundTintColor(@ColorInt int backgroundTintColor) { - this.backgroundTintColor = backgroundTintColor; - myLocationView.setShadowDrawableTint(backgroundTintColor); - } - - /** - * Get the background tint color. - * - * @return the background tint color - */ - public int getBackgroundTintColor() { - return backgroundTintColor; - } - - /** - * Get the background offset. - * - * @return the background offset - */ - public int[] getBackgroundOffset() { - return backgroundOffset; - } - - /** - * Set the MyLocationView padding. - * - * @param left the padding left of MyLocationView - * @param top the padding top of MyLocationView - * @param right the padding right of MyLocationView - * @param bottom the padding bottom of MyLocaionView - */ - public void setPadding(int left, int top, int right, int bottom) { - padding = new int[]{left, top, right, bottom}; - myLocationView.setContentPadding(padding); - projection.invalidateContentPadding(padding); - invalidateFocalPointForTracking(myLocationView); + setForegroundDrawable(options.getMyLocationForegroundDrawable(), options.getMyLocationForegroundBearingDrawable()); + setForegroundTintColor(options.getMyLocationForegroundTintColor()); + setBackgroundDrawable(options.getMyLocationBackgroundDrawable(), options.getMyLocationBackgroundPadding()); + setBackgroundTintColor(options.getMyLocationBackgroundTintColor()); + setAccuracyAlpha(options.getMyLocationAccuracyAlpha()); + setAccuracyTintColor(options.getMyLocationAccuracyTintColor()); + } + + /** + * Returns if the MyLocationView is enabled + * + * @return true if MyLocationView is enabled, + */ + public boolean isEnabled() { + return enabled; + } + + /** + * Set the enabled state of MyLocationView + * + * @param enabled true shows the MyLocationView on the map + */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + myLocationView.setEnabled(enabled); + } + + /** + * Set the foreground drawable of the MyLocationView + * <p> + * The foreground drawable is the image visible on screen + * </p> + * + * @param foregroundDrawable the drawable to show as foreground without bearing + * @param foregroundBearingDrawable the drawable to show as foreground when bearing is enabled + */ + public void setForegroundDrawable(Drawable foregroundDrawable, Drawable foregroundBearingDrawable) { + this.foregroundDrawable = foregroundDrawable; + this.foregroundBearingDrawable = foregroundBearingDrawable; + myLocationView.setForegroundDrawables(foregroundDrawable, foregroundBearingDrawable); + } + + /** + * Get the foreground drawable when bearing is disabled. + * + * @return the drawable used as foreground + */ + public Drawable getForegroundDrawable() { + return foregroundDrawable; + } + + /** + * Get the foreground drawable when bearing is enabled. + * + * @return the bearing drawable used as foreground + */ + public Drawable getForegroundBearingDrawable() { + return foregroundBearingDrawable; + } + + /** + * Set the foreground tint color. + * <p> + * The color will tint both the foreground and the bearing foreground drawable. + * </p> + * + * @param foregroundTintColor the color to tint the foreground drawable + */ + public void setForegroundTintColor(@ColorInt int foregroundTintColor) { + this.foregroundTintColor = foregroundTintColor; + myLocationView.setForegroundDrawableTint(foregroundTintColor); + } + + /** + * Get the foreground tint color. + * + * @return the foreground tint color + */ + public int getForegroundTintColor() { + return foregroundTintColor; + } + + /** + * Set the background drawable of MyLocationView + * <p> + * Padding can be added to provide an offset to the background + * </p> + * + * @param backgroundDrawable the drawable to show as background + * @param padding the padding added to the background + */ + public void setBackgroundDrawable(Drawable backgroundDrawable, int[] padding) { + this.backgroundDrawable = backgroundDrawable; + this.backgroundOffset = padding; + if (padding != null && padding.length == 4) { + myLocationView.setShadowDrawable(backgroundDrawable, padding[0], padding[1], padding[2], padding[3]); + } else { + myLocationView.setShadowDrawable(backgroundDrawable); } - - /** - * Get the MyLocationView padding. - * - * @return an array describing the padding in a LTRB manner - */ - public int[] getPadding() { - return padding; - } - - /** - * Get the alpha value of the accuracy circle of MyLocationView - * - * @return the alpha value - */ - public int getAccuracyAlpha() { - return accuracyAlpha; - } - - /** - * Set the alpha value of the accuracy circle of MyLocationView - * - * @param accuracyAlpha the alpha value to set - */ - public void setAccuracyAlpha(@IntRange(from = 0, to = 255) int accuracyAlpha) { - this.accuracyAlpha = accuracyAlpha; - myLocationView.setAccuracyAlpha(accuracyAlpha); - } - - /** - * Get the accuracy tint color of MyLocationView. - * - * @return the tint color used for accuracy - */ - public int getAccuracyTintColor() { - return accuracyTintColor; - } - - /** - * Set the accuracy tint color of MyLocationView. - * - * @param accuracyTintColor the accuracy tint color - */ - public void setAccuracyTintColor(@ColorInt int accuracyTintColor) { - this.accuracyTintColor = accuracyTintColor; - myLocationView.setAccuracyTint(accuracyTintColor); - } - - public void setTilt(double tilt) { - myLocationView.setTilt(tilt); - } - - private void invalidateFocalPointForTracking(MyLocationView myLocationView) { - if (!(myLocationView.getMyLocationTrackingMode() == MyLocationTracking.TRACKING_NONE)) { - focalPointChangeListener.onFocalPointChanged(new PointF(myLocationView.getCenterX(), myLocationView.getCenterY())); - } else { - focalPointChangeListener.onFocalPointChanged(null); - } + } + + /** + * Get the background drawable of MyLocationView. + * + * @return the drawable used as background + */ + public Drawable getBackgroundDrawable() { + return backgroundDrawable; + } + + /** + * Set the background tint color. + * + * @param backgroundTintColor the color to tint the background + */ + public void setBackgroundTintColor(@ColorInt int backgroundTintColor) { + this.backgroundTintColor = backgroundTintColor; + myLocationView.setShadowDrawableTint(backgroundTintColor); + } + + /** + * Get the background tint color. + * + * @return the background tint color + */ + public int getBackgroundTintColor() { + return backgroundTintColor; + } + + /** + * Get the background offset. + * + * @return the background offset + */ + public int[] getBackgroundOffset() { + return backgroundOffset; + } + + /** + * Set the MyLocationView padding. + * + * @param left the padding left of MyLocationView + * @param top the padding top of MyLocationView + * @param right the padding right of MyLocationView + * @param bottom the padding bottom of MyLocaionView + */ + public void setPadding(int left, int top, int right, int bottom) { + padding = new int[] {left, top, right, bottom}; + myLocationView.setContentPadding(padding); + projection.invalidateContentPadding(padding); + invalidateFocalPointForTracking(myLocationView); + } + + /** + * Get the MyLocationView padding. + * + * @return an array describing the padding in a LTRB manner + */ + public int[] getPadding() { + return padding; + } + + /** + * Get the alpha value of the accuracy circle of MyLocationView + * + * @return the alpha value + */ + public int getAccuracyAlpha() { + return accuracyAlpha; + } + + /** + * Set the alpha value of the accuracy circle of MyLocationView + * + * @param accuracyAlpha the alpha value to set + */ + public void setAccuracyAlpha(@IntRange(from = 0, to = 255) int accuracyAlpha) { + this.accuracyAlpha = accuracyAlpha; + myLocationView.setAccuracyAlpha(accuracyAlpha); + } + + /** + * Get the accuracy tint color of MyLocationView. + * + * @return the tint color used for accuracy + */ + public int getAccuracyTintColor() { + return accuracyTintColor; + } + + /** + * Set the accuracy tint color of MyLocationView. + * + * @param accuracyTintColor the accuracy tint color + */ + public void setAccuracyTintColor(@ColorInt int accuracyTintColor) { + this.accuracyTintColor = accuracyTintColor; + myLocationView.setAccuracyTint(accuracyTintColor); + } + + public void setTilt(double tilt) { + myLocationView.setTilt(tilt); + } + + private void invalidateFocalPointForTracking(MyLocationView myLocationView) { + if (!(myLocationView.getMyLocationTrackingMode() == MyLocationTracking.TRACKING_NONE)) { + focalPointChangeListener.onFocalPointChanged(new PointF(myLocationView.getCenterX(), + myLocationView.getCenterY())); + } else { + focalPointChangeListener.onFocalPointChanged(null); } + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityListener.java index 0528194528..8f1046c79a 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityListener.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityListener.java @@ -5,6 +5,6 @@ package com.mapbox.mapboxsdk.net; */ public interface ConnectivityListener { - void onNetworkStateChanged(boolean connected); + void onNetworkStateChanged(boolean connected); } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityReceiver.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityReceiver.java index 7278cdd673..63d9254306 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityReceiver.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/ConnectivityReceiver.java @@ -7,6 +7,7 @@ import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.support.annotation.NonNull; + import timber.log.Timber; import com.mapbox.mapboxsdk.MapboxAccountManager; @@ -19,77 +20,77 @@ import java.util.concurrent.CopyOnWriteArrayList; * Not public api. */ public class ConnectivityReceiver extends BroadcastReceiver { - private static ConnectivityReceiver INSTANCE; - - /** - * Get or create the singleton instance - */ - public static synchronized ConnectivityReceiver instance(Context context) { - if (INSTANCE == null) { - //Register new instance - INSTANCE = new ConnectivityReceiver(); - context.registerReceiver(INSTANCE, new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE")); - - //Add default listeners - INSTANCE.addListener(new NativeConnectivityListener()); - } - - return INSTANCE; + private static ConnectivityReceiver INSTANCE; + + /** + * Get or create the singleton instance + */ + public static synchronized ConnectivityReceiver instance(Context context) { + if (INSTANCE == null) { + //Register new instance + INSTANCE = new ConnectivityReceiver(); + context.registerReceiver(INSTANCE, new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE")); + + //Add default listeners + INSTANCE.addListener(new NativeConnectivityListener()); } - private List<ConnectivityListener> listeners = new CopyOnWriteArrayList<>(); + return INSTANCE; + } - private ConnectivityReceiver() { - } + private List<ConnectivityListener> listeners = new CopyOnWriteArrayList<>(); - /** - * @see BroadcastReceiver#onReceive(Context, Intent) - */ - @Override - public void onReceive(Context context, Intent intent) { - boolean connected = isConnected(context); - Timber.v("Connected: " + connected); - - //Loop over listeners - for (ConnectivityListener listener : listeners) { - listener.onNetworkStateChanged(connected); - } - } + private ConnectivityReceiver() { + } - /** - * Add a listener to be notified - * - * @param listener the listener to add - */ - public void addListener(@NonNull ConnectivityListener listener) { - listeners.add(listener); - } + /** + * @see BroadcastReceiver#onReceive(Context, Intent) + */ + @Override + public void onReceive(Context context, Intent intent) { + boolean connected = isConnected(context); + Timber.v("Connected: " + connected); - /** - * Remove a listener - * - * @param listener the listener to remove - */ - public void removeListener(@NonNull ConnectivityListener listener) { - listeners.remove(listener); + //Loop over listeners + for (ConnectivityListener listener : listeners) { + listener.onNetworkStateChanged(connected); } - - /** - * Get current connectivity state - * - * @param context current Context - * @return true if connected - */ - public boolean isConnected(Context context) { - Boolean connected = MapboxAccountManager.getInstance().isConnected(); - if (connected != null) { - // Connectivity state overridden by app - return connected; - } - - ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); - return (activeNetwork != null && activeNetwork.isConnected()); + } + + /** + * Add a listener to be notified + * + * @param listener the listener to add + */ + public void addListener(@NonNull ConnectivityListener listener) { + listeners.add(listener); + } + + /** + * Remove a listener + * + * @param listener the listener to remove + */ + public void removeListener(@NonNull ConnectivityListener listener) { + listeners.remove(listener); + } + + /** + * Get current connectivity state + * + * @param context current Context + * @return true if connected + */ + public boolean isConnected(Context context) { + Boolean connected = MapboxAccountManager.getInstance().isConnected(); + if (connected != null) { + // Connectivity state overridden by app + return connected; } + ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); + return (activeNetwork != null && activeNetwork.isConnected()); + } + } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/NativeConnectivityListener.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/NativeConnectivityListener.java index 8b9307465c..76ce1de9d7 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/NativeConnectivityListener.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/net/NativeConnectivityListener.java @@ -5,30 +5,30 @@ package com.mapbox.mapboxsdk.net; */ class NativeConnectivityListener implements ConnectivityListener { - static { - System.loadLibrary("mapbox-gl"); - } + static { + System.loadLibrary("mapbox-gl"); + } - private long nativePtr; - private boolean invalidated; + private long nativePtr; + private boolean invalidated; - NativeConnectivityListener(long nativePtr) { - this.nativePtr = nativePtr; - } + NativeConnectivityListener(long nativePtr) { + this.nativePtr = nativePtr; + } - NativeConnectivityListener() { - initialize(); - } + NativeConnectivityListener() { + initialize(); + } - @Override - public void onNetworkStateChanged(boolean connected) { - nativeOnConnectivityStateChanged(connected); - } + @Override + public void onNetworkStateChanged(boolean connected) { + nativeOnConnectivityStateChanged(connected); + } - protected native void nativeOnConnectivityStateChanged(boolean connected); + protected native void nativeOnConnectivityStateChanged(boolean connected); - protected native void initialize(); + protected native void initialize(); - @Override - protected native void finalize() throws Throwable; + @Override + protected native void finalize() throws Throwable; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java index 2ecc23a420..58093f285b 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java @@ -7,6 +7,7 @@ import android.os.Environment; import android.os.Handler; import android.os.Looper; import android.support.annotation.NonNull; + import timber.log.Timber; import com.mapbox.mapboxsdk.MapboxAccountManager; @@ -20,311 +21,310 @@ import java.io.File; */ public class OfflineManager { - // - // Static methods - // + // + // Static methods + // - static { - System.loadLibrary("mapbox-gl"); - } + static { + System.loadLibrary("mapbox-gl"); + } - // Default database name - private final static String DATABASE_NAME = "mbgl-offline.db"; + // Default database name + private static final String DATABASE_NAME = "mbgl-offline.db"; - /* - * The maximumCacheSize parameter is a limit applied to non-offline resources only, - * i.e. resources added to the database for the "ambient use" caching functionality. - * There is no size limit for offline resources. - */ - private final static long DEFAULT_MAX_CACHE_SIZE = 50 * 1024 * 1024; + /* + * The maximumCacheSize parameter is a limit applied to non-offline resources only, + * i.e. resources added to the database for the "ambient use" caching functionality. + * There is no size limit for offline resources. + */ + private static final long DEFAULT_MAX_CACHE_SIZE = 50 * 1024 * 1024; - // Holds the pointer to JNI DefaultFileSource - private long mDefaultFileSourcePtr = 0; + // Holds the pointer to JNI DefaultFileSource + private long mDefaultFileSourcePtr = 0; - // Makes sure callbacks come back to the main thread - private Handler handler; + // Makes sure callbacks come back to the main thread + private Handler handler; - // This object is implemented as a singleton - private static OfflineManager instance; + // This object is implemented as a singleton + private static OfflineManager instance; + /** + * This callback receives an asynchronous response containing a list of all + * {@link OfflineRegion} in the database, or an error message otherwise. + */ + public interface ListOfflineRegionsCallback { /** - * This callback receives an asynchronous response containing a list of all - * {@link OfflineRegion} in the database, or an error message otherwise. + * Receives the list of offline regions. + * + * @param offlineRegions the offline region array */ - public interface ListOfflineRegionsCallback { - /** - * Receives the list of offline regions. - * - * @param offlineRegions the offline region array - */ - void onList(OfflineRegion[] offlineRegions); - - /** - * Receives the error message. - * - * @param error the error message - */ - void onError(String error); - } + void onList(OfflineRegion[] offlineRegions); /** - * This callback receives an asynchronous response containing the newly created - * {@link OfflineRegion} in the database, or an error message otherwise. + * Receives the error message. + * + * @param error the error message */ - public interface CreateOfflineRegionCallback { - /** - * Receives the newly created offline region. - * - * @param offlineRegion the offline region to create - */ - void onCreate(OfflineRegion offlineRegion); - - /** - * Receives the error message. - * - * @param error the error message to be shown - */ - void onError(String error); - } - - /* - * Constructors + void onError(String error); + } + + /** + * This callback receives an asynchronous response containing the newly created + * {@link OfflineRegion} in the database, or an error message otherwise. + */ + public interface CreateOfflineRegionCallback { + /** + * Receives the newly created offline region. + * + * @param offlineRegion the offline region to create */ - - private OfflineManager(Context context) { - // Get a pointer to the DefaultFileSource instance - String assetRoot = getDatabasePath(context); - String cachePath = assetRoot + File.separator + DATABASE_NAME; - mDefaultFileSourcePtr = createDefaultFileSource(cachePath, assetRoot, DEFAULT_MAX_CACHE_SIZE); - - if (MapboxAccountManager.getInstance() != null) { - setAccessToken(mDefaultFileSourcePtr, MapboxAccountManager.getInstance().getAccessToken()); - } - - // Delete any existing previous ambient cache database - deleteAmbientDatabase(context); - } - - public static String getDatabasePath(Context context) { - // Default value - boolean setStorageExternal = MapboxConstants.DEFAULT_SET_STORAGE_EXTERNAL; - - try { - // Try getting a custom value from the app Manifest - ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo( - context.getPackageName(), PackageManager.GET_META_DATA); - setStorageExternal = appInfo.metaData.getBoolean( - MapboxConstants.KEY_META_DATA_SET_STORAGE_EXTERNAL, - MapboxConstants.DEFAULT_SET_STORAGE_EXTERNAL); - } catch (PackageManager.NameNotFoundException e) { - Timber.e("Failed to read the package metadata: " + e.getMessage()); - } catch (Exception e) { - Timber.e("Failed to read the storage key: " + e.getMessage()); - } - - String databasePath = null; - if (setStorageExternal && isExternalStorageReadable()) { - try { - // Try getting the external storage path - databasePath = context.getExternalFilesDir(null).getAbsolutePath(); - } catch (NullPointerException e) { - Timber.e("Failed to obtain the external storage path: " + e.getMessage()); - } - } - - if (databasePath == null) { - // Default to internal storage - databasePath = context.getFilesDir().getAbsolutePath(); - } - - return databasePath; - } + void onCreate(OfflineRegion offlineRegion); /** - * Checks if external storage is available to at least read. In order for this to work, make - * sure you include <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> - * (or WRITE_EXTERNAL_STORAGE) for API level < 18 in your app Manifest. - * <p> - * Code from https://developer.android.com/guide/topics/data/data-storage.html#filesExternal - * </p> + * Receives the error message. * - * @return true if external storage is readable + * @param error the error message to be shown */ - public static boolean isExternalStorageReadable() { - String state = Environment.getExternalStorageState(); - if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { - return true; - } + void onError(String error); + } - Timber.w("External storage was requested but it isn't readable. For API level < 18" - + " make sure you've requested READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE" - + " permissions in your app Manifest (defaulting to internal storage)."); + /* + * Constructors + */ - return false; - } + private OfflineManager(Context context) { + // Get a pointer to the DefaultFileSource instance + String assetRoot = getDatabasePath(context); + String cachePath = assetRoot + File.separator + DATABASE_NAME; + mDefaultFileSourcePtr = createDefaultFileSource(cachePath, assetRoot, DEFAULT_MAX_CACHE_SIZE); - private void deleteAmbientDatabase(final Context context) { - // Delete the file in a separate thread to avoid affecting the UI - new Thread(new Runnable() { - @Override - public void run() { - try { - String path = context.getCacheDir().getAbsolutePath() + File.separator + "mbgl-cache.db"; - File file = new File(path); - if (file.exists()) { - file.delete(); - Timber.d("Old ambient cache database deleted to save space: " + path); - } - } catch (Exception e) { - Timber.e("Failed to delete old ambient cache database: " + e.getMessage()); - } - } - }).start(); + if (MapboxAccountManager.getInstance() != null) { + setAccessToken(mDefaultFileSourcePtr, MapboxAccountManager.getInstance().getAccessToken()); } - public static synchronized OfflineManager getInstance(Context context) { - if (instance == null) { - instance = new OfflineManager(context); - } + // Delete any existing previous ambient cache database + deleteAmbientDatabase(context); + } + + public static String getDatabasePath(Context context) { + // Default value + boolean setStorageExternal = MapboxConstants.DEFAULT_SET_STORAGE_EXTERNAL; + + try { + // Try getting a custom value from the app Manifest + ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo( + context.getPackageName(), PackageManager.GET_META_DATA); + setStorageExternal = appInfo.metaData.getBoolean( + MapboxConstants.KEY_META_DATA_SET_STORAGE_EXTERNAL, + MapboxConstants.DEFAULT_SET_STORAGE_EXTERNAL); + } catch (PackageManager.NameNotFoundException nameNotFoundException) { + Timber.e("Failed to read the package metadata: " + nameNotFoundException.getMessage()); + } catch (Exception exception) { + Timber.e("Failed to read the storage key: " + exception.getMessage()); + } - return instance; + String databasePath = null; + if (setStorageExternal && isExternalStorageReadable()) { + try { + // Try getting the external storage path + databasePath = context.getExternalFilesDir(null).getAbsolutePath(); + } catch (NullPointerException nullPointerException) { + Timber.e("Failed to obtain the external storage path: " + nullPointerException.getMessage()); + } } - /** - * Access token getter/setter - * - * @param accessToken the accessToken to be used by the offline manager. - * @deprecated As of release 4.1.0, replaced by {@link MapboxAccountManager#start(Context, String)} ()} - */ - @Deprecated - public void setAccessToken(String accessToken) { - setAccessToken(mDefaultFileSourcePtr, accessToken); + if (databasePath == null) { + // Default to internal storage + databasePath = context.getFilesDir().getAbsolutePath(); } - /** - * Get Access Token - * - * @return Access Token - * @deprecated As of release 4.1.0, replaced by {@link MapboxAccountManager#getAccessToken()} - */ - @Deprecated - public String getAccessToken() { - return getAccessToken(mDefaultFileSourcePtr); + return databasePath; + } + + /** + * Checks if external storage is available to at least read. In order for this to work, make + * sure you include <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> + * (or WRITE_EXTERNAL_STORAGE) for API level < 18 in your app Manifest. + * <p> + * Code from https://developer.android.com/guide/topics/data/data-storage.html#filesExternal + * </p> + * + * @return true if external storage is readable + */ + public static boolean isExternalStorageReadable() { + String state = Environment.getExternalStorageState(); + if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { + return true; } - private Handler getHandler() { - if (handler == null) { - handler = new Handler(Looper.getMainLooper()); + Timber.w("External storage was requested but it isn't readable. For API level < 18" + + " make sure you've requested READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE" + + " permissions in your app Manifest (defaulting to internal storage)."); + + return false; + } + + private void deleteAmbientDatabase(final Context context) { + // Delete the file in a separate thread to avoid affecting the UI + new Thread(new Runnable() { + @Override + public void run() { + try { + String path = context.getCacheDir().getAbsolutePath() + File.separator + "mbgl-cache.db"; + File file = new File(path); + if (file.exists()) { + file.delete(); + Timber.d("Old ambient cache database deleted to save space: " + path); + } + } catch (Exception exception) { + Timber.e("Failed to delete old ambient cache database: " + exception.getMessage()); } + } + }).start(); + } - return handler; + public static synchronized OfflineManager getInstance(Context context) { + if (instance == null) { + instance = new OfflineManager(context); } - - /** - * Retrieve all regions in the offline database. - * <p> - * The query will be executed asynchronously and the results passed to the given - * callback on the main thread. - * </p> - * - * @param callback the callback to be invoked - */ - public void listOfflineRegions(@NonNull final ListOfflineRegionsCallback callback) { - listOfflineRegions(mDefaultFileSourcePtr, new ListOfflineRegionsCallback() { - @Override - public void onList(final OfflineRegion[] offlineRegions) { - getHandler().post(new Runnable() { - @Override - public void run() { - callback.onList(offlineRegions); - } - }); - } - - @Override - public void onError(final String error) { - getHandler().post(new Runnable() { - @Override - public void run() { - callback.onError(error); - } - }); - } - }); + return instance; + } + + /** + * Access token getter/setter + * + * @param accessToken the accessToken to be used by the offline manager. + * @deprecated As of release 4.1.0, replaced by {@link MapboxAccountManager#start(Context, String)} ()} + */ + @Deprecated + public void setAccessToken(String accessToken) { + setAccessToken(mDefaultFileSourcePtr, accessToken); + } + + /** + * Get Access Token + * + * @return Access Token + * @deprecated As of release 4.1.0, replaced by {@link MapboxAccountManager#getAccessToken()} + */ + @Deprecated + public String getAccessToken() { + return getAccessToken(mDefaultFileSourcePtr); + } + + private Handler getHandler() { + if (handler == null) { + handler = new Handler(Looper.getMainLooper()); } - /** - * Create an offline region in the database. - * <p> - * When the initial database queries have completed, the provided callback will be - * executed on the main thread. - * </p> - * <p> - * Note that the resulting region will be in an inactive download state; to begin - * downloading resources, call `OfflineRegion.setDownloadState(DownloadState.STATE_ACTIVE)`, - * optionally registering an `OfflineRegionObserver` beforehand. - * </p> - * - * @param definition the offline region definition - * @param metadata the metadata in bytes - * @param callback the callback to be invoked - */ - public void createOfflineRegion( - @NonNull OfflineRegionDefinition definition, - @NonNull byte[] metadata, - @NonNull final CreateOfflineRegionCallback callback) { - - createOfflineRegion(mDefaultFileSourcePtr, definition, metadata, new CreateOfflineRegionCallback() { - @Override - public void onCreate(final OfflineRegion offlineRegion) { - getHandler().post(new Runnable() { - @Override - public void run() { - callback.onCreate(offlineRegion); - } - }); - } - - @Override - public void onError(final String error) { - getHandler().post(new Runnable() { - @Override - public void run() { - callback.onError(error); - } - }); - } + return handler; + } + + /** + * Retrieve all regions in the offline database. + * <p> + * The query will be executed asynchronously and the results passed to the given + * callback on the main thread. + * </p> + * + * @param callback the callback to be invoked + */ + public void listOfflineRegions(@NonNull final ListOfflineRegionsCallback callback) { + listOfflineRegions(mDefaultFileSourcePtr, new ListOfflineRegionsCallback() { + @Override + public void onList(final OfflineRegion[] offlineRegions) { + getHandler().post(new Runnable() { + @Override + public void run() { + callback.onList(offlineRegions); + } }); - } + } + + @Override + public void onError(final String error) { + getHandler().post(new Runnable() { + @Override + public void run() { + callback.onError(error); + } + }); + } + }); + } + + /** + * Create an offline region in the database. + * <p> + * When the initial database queries have completed, the provided callback will be + * executed on the main thread. + * </p> + * <p> + * Note that the resulting region will be in an inactive download state; to begin + * downloading resources, call `OfflineRegion.setDownloadState(DownloadState.STATE_ACTIVE)`, + * optionally registering an `OfflineRegionObserver` beforehand. + * </p> + * + * @param definition the offline region definition + * @param metadata the metadata in bytes + * @param callback the callback to be invoked + */ + public void createOfflineRegion( + @NonNull OfflineRegionDefinition definition, + @NonNull byte[] metadata, + @NonNull final CreateOfflineRegionCallback callback) { + + createOfflineRegion(mDefaultFileSourcePtr, definition, metadata, new CreateOfflineRegionCallback() { + @Override + public void onCreate(final OfflineRegion offlineRegion) { + getHandler().post(new Runnable() { + @Override + public void run() { + callback.onCreate(offlineRegion); + } + }); + } + + @Override + public void onError(final String error) { + getHandler().post(new Runnable() { + @Override + public void run() { + callback.onError(error); + } + }); + } + }); + } - /* - * Changing or bypassing this limit without permission from Mapbox is prohibited - * by the Mapbox Terms of Service. - */ - public void setOfflineMapboxTileCountLimit(long limit) { - setOfflineMapboxTileCountLimit(mDefaultFileSourcePtr, limit); - } + /* + * Changing or bypassing this limit without permission from Mapbox is prohibited + * by the Mapbox Terms of Service. + */ + public void setOfflineMapboxTileCountLimit(long limit) { + setOfflineMapboxTileCountLimit(mDefaultFileSourcePtr, limit); + } - /* - * Native methods - */ + /* + * Native methods + */ - private native long createDefaultFileSource( - String cachePath, String assetRoot, long maximumCacheSize); + private native long createDefaultFileSource( + String cachePath, String assetRoot, long maximumCacheSize); - private native void setAccessToken(long defaultFileSourcePtr, String accessToken); + private native void setAccessToken(long defaultFileSourcePtr, String accessToken); - private native String getAccessToken(long defaultFileSourcePtr); + private native String getAccessToken(long defaultFileSourcePtr); - private native void listOfflineRegions( - long defaultFileSourcePtr, ListOfflineRegionsCallback callback); + private native void listOfflineRegions( + long defaultFileSourcePtr, ListOfflineRegionsCallback callback); - private native void createOfflineRegion( - long defaultFileSourcePtr, OfflineRegionDefinition definition, - byte[] metadata, CreateOfflineRegionCallback callback); + private native void createOfflineRegion( + long defaultFileSourcePtr, OfflineRegionDefinition definition, + byte[] metadata, CreateOfflineRegionCallback callback); - private native void setOfflineMapboxTileCountLimit( - long defaultFileSourcePtr, long limit); + private native void setOfflineMapboxTileCountLimit( + long defaultFileSourcePtr, long limit); } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java index 0dcd34b6e6..a4d8a646d3 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java @@ -4,6 +4,7 @@ import android.os.Handler; import android.os.Looper; import android.support.annotation.IntDef; import android.support.annotation.NonNull; + import timber.log.Timber; import java.lang.annotation.Retention; @@ -16,414 +17,418 @@ import java.lang.annotation.RetentionPolicy; */ public class OfflineRegion { - // - // Static methods - // + // + // Static methods + // - static { - System.loadLibrary("mapbox-gl"); - } + static { + System.loadLibrary("mapbox-gl"); + } - // Parent OfflineManager - private OfflineManager offlineManager; + // Parent OfflineManager + private OfflineManager offlineManager; - // Members - private long mId = 0; - private OfflineRegionDefinition mDefinition = null; + // Members + private long mId = 0; + private OfflineRegionDefinition mDefinition = null; - /** - * Arbitrary binary region metadata. The contents are opaque to the SDK implementation; - * it just stores and retrieves a byte[]. Check the `OfflineActivity` in the TestApp - * for a sample implementation that uses JSON to store an offline region name. - */ - private byte[] mMetadata = null; + /** + * Arbitrary binary region metadata. The contents are opaque to the SDK implementation; + * it just stores and retrieves a byte[]. Check the `OfflineActivity` in the TestApp + * for a sample implementation that uses JSON to store an offline region name. + */ + private byte[] mMetadata = null; - // Holds the pointer to JNI OfflineRegion - private long mOfflineRegionPtr = 0; + // Holds the pointer to JNI OfflineRegion + private long mOfflineRegionPtr = 0; - // Makes sure callbacks come back to the main thread - private Handler handler; + // Makes sure callbacks come back to the main thread + private Handler handler; + /** + * A region can have a single observer, which gets notified whenever a change + * to the region's status occurs. + */ + public interface OfflineRegionObserver { /** - * A region can have a single observer, which gets notified whenever a change - * to the region's status occurs. + * Implement this method to be notified of a change in the status of an + * offline region. Status changes include any change in state of the members + * of OfflineRegionStatus. + * <p> + * This method will be executed on the main thread. + * </p> + * + * @param status the changed status */ - public interface OfflineRegionObserver { - /** - * Implement this method to be notified of a change in the status of an - * offline region. Status changes include any change in state of the members - * of OfflineRegionStatus. - * <p> - * This method will be executed on the main thread. - * </p> - * - * @param status the changed status - */ - void onStatusChanged(OfflineRegionStatus status); - - /** - * Implement this method to be notified of errors encountered while downloading - * regional resources. Such errors may be recoverable; for example the implementation - * will attempt to re-request failed resources based on an exponential backoff - * algorithm, or when it detects that network access has been restored. - * <p> - * This method will be executed on the main thread. - * </p> - * - * @param error the offline region error message - */ - void onError(OfflineRegionError error); - - /* - * Implement this method to be notified when the limit on the number of Mapbox - * tiles stored for offline regions has been reached. - * - * Once the limit has been reached, the SDK will not download further offline - * tiles from Mapbox APIs until existing tiles have been removed. Contact your - * Mapbox sales representative to raise the limit. - * - * This limit does not apply to non-Mapbox tile sources. - * - * This method will be executed on the main thread. - */ - void mapboxTileCountLimitExceeded(long limit); - } + void onStatusChanged(OfflineRegionStatus status); /** - * This callback receives an asynchronous response containing the {@link OfflineRegionStatus} - * of the offline region, or a {@link String} error message otherwise. + * Implement this method to be notified of errors encountered while downloading + * regional resources. Such errors may be recoverable; for example the implementation + * will attempt to re-request failed resources based on an exponential backoff + * algorithm, or when it detects that network access has been restored. + * <p> + * This method will be executed on the main thread. + * </p> + * + * @param error the offline region error message */ - public interface OfflineRegionStatusCallback { - /** - * Receives the status - * - * @param status the offline region status - */ - void onStatus(OfflineRegionStatus status); - - /** - * Receives the error message - * - * @param error the error message - */ - void onError(String error); - } + void onError(OfflineRegionError error); + /* + * Implement this method to be notified when the limit on the number of Mapbox + * tiles stored for offline regions has been reached. + * + * Once the limit has been reached, the SDK will not download further offline + * tiles from Mapbox APIs until existing tiles have been removed. Contact your + * Mapbox sales representative to raise the limit. + * + * This limit does not apply to non-Mapbox tile sources. + * + * This method will be executed on the main thread. + */ + void mapboxTileCountLimitExceeded(long limit); + } + + /** + * This callback receives an asynchronous response containing the {@link OfflineRegionStatus} + * of the offline region, or a {@link String} error message otherwise. + */ + public interface OfflineRegionStatusCallback { /** - * This callback receives an asynchronous response containing a notification when - * an offline region has been deleted, or a {@link String} error message otherwise. + * Receives the status + * + * @param status the offline region status */ - public interface OfflineRegionDeleteCallback { - /** - * Receives the delete notification - */ - void onDelete(); - - /** - * Receives the error message - * - * @param error the error message - */ - void onError(String error); - } + void onStatus(OfflineRegionStatus status); /** - * This callback receives an asynchronous response containing the newly update - * OfflineMetadata in the database, or an error message otherwise. + * Receives the error message + * + * @param error the error message */ - public interface OfflineRegionUpdateMetadataCallback { - /** - * Receives the newly update offline region metadata. - * - * @param metadata the offline metadata to u[date - */ - void onUpdate(byte[] metadata); - - /** - * Receives the error message. - * - * @param error the error message to be shown - */ - void onError(String error); - } - + void onError(String error); + } + + /** + * This callback receives an asynchronous response containing a notification when + * an offline region has been deleted, or a {@link String} error message otherwise. + */ + public interface OfflineRegionDeleteCallback { /** - * A region is either inactive (not downloading, but previously-downloaded - * resources are available for use), or active (resources are being downloaded - * or will be downloaded, if necessary, when network access is available). - * <p> - * This state is independent of whether or not the complete set of resources - * is currently available for offline use. To check if that is the case, use - * `OfflineRegionStatus.isComplete()`. - * </p> + * Receives the delete notification */ - - @IntDef({STATE_INACTIVE, STATE_ACTIVE}) - @Retention(RetentionPolicy.SOURCE) - public @interface DownloadState { - } - - public static final int STATE_INACTIVE = 0; - public static final int STATE_ACTIVE = 1; - - // Keep track of the region state - private int state = STATE_INACTIVE; - - private boolean deliverInactiveMessages = false; + void onDelete(); /** - * Gets whether or not the `OfflineRegionObserver` will continue to deliver messages even if - * the region state has been set as STATE_INACTIVE. + * Receives the error message * - * @return true if delivering inactive messages + * @param error the error message */ - public boolean isDeliveringInactiveMessages() { - return deliverInactiveMessages; - } + void onError(String error); + } + + /** + * This callback receives an asynchronous response containing the newly update + * OfflineMetadata in the database, or an error message otherwise. + */ + public interface OfflineRegionUpdateMetadataCallback { + /** + * Receives the newly update offline region metadata. + * + * @param metadata the offline metadata to u[date + */ + void onUpdate(byte[] metadata); /** - * When set true, the `OfflineRegionObserver` will continue to deliver messages even if - * the region state has been set as STATE_INACTIVE (operations happen asynchronously). If set - * false, the client won't be notified of further messages. + * Receives the error message. * - * @param deliverInactiveMessages true if it should deliver inactive messages + * @param error the error message to be shown */ - public void setDeliverInactiveMessages(boolean deliverInactiveMessages) { - this.deliverInactiveMessages = deliverInactiveMessages; + void onError(String error); + } + + /** + * A region is either inactive (not downloading, but previously-downloaded + * resources are available for use), or active (resources are being downloaded + * or will be downloaded, if necessary, when network access is available). + * <p> + * This state is independent of whether or not the complete set of resources + * is currently available for offline use. To check if that is the case, use + * `OfflineRegionStatus.isComplete()`. + * </p> + */ + + @IntDef( {STATE_INACTIVE, STATE_ACTIVE}) + @Retention(RetentionPolicy.SOURCE) + public @interface DownloadState { + } + + public static final int STATE_INACTIVE = 0; + public static final int STATE_ACTIVE = 1; + + // Keep track of the region state + private int state = STATE_INACTIVE; + + private boolean deliverInactiveMessages = false; + + /** + * Gets whether or not the `OfflineRegionObserver` will continue to deliver messages even if + * the region state has been set as STATE_INACTIVE. + * + * @return true if delivering inactive messages + */ + public boolean isDeliveringInactiveMessages() { + return deliverInactiveMessages; + } + + /** + * When set true, the `OfflineRegionObserver` will continue to deliver messages even if + * the region state has been set as STATE_INACTIVE (operations happen asynchronously). If set + * false, the client won't be notified of further messages. + * + * @param deliverInactiveMessages true if it should deliver inactive messages + */ + public void setDeliverInactiveMessages(boolean deliverInactiveMessages) { + this.deliverInactiveMessages = deliverInactiveMessages; + } + + private boolean deliverMessages() { + if (state == STATE_ACTIVE) { + return true; } - - private boolean deliverMessages() { - if (state == STATE_ACTIVE) return true; - if (isDeliveringInactiveMessages()) return true; - return false; + if (isDeliveringInactiveMessages()) { + return true; } + return false; + } - /* - * Constructor - */ + /* + * Constructor + */ - private OfflineRegion() { - // For JNI use only, to create a new offline region, use - // OfflineManager.createOfflineRegion() instead. - } + private OfflineRegion() { + // For JNI use only, to create a new offline region, use + // OfflineManager.createOfflineRegion() instead. + } - /* - * Getters - */ + /* + * Getters + */ - public long getID() { - return mId; - } - - public OfflineRegionDefinition getDefinition() { - return mDefinition; - } + public long getID() { + return mId; + } - public byte[] getMetadata() { - return mMetadata; - } + public OfflineRegionDefinition getDefinition() { + return mDefinition; + } - private Handler getHandler() { - if (handler == null) { - handler = new Handler(Looper.getMainLooper()); - } + public byte[] getMetadata() { + return mMetadata; + } - return handler; + private Handler getHandler() { + if (handler == null) { + handler = new Handler(Looper.getMainLooper()); } - /** - * Register an observer to be notified when the state of the region changes. - * - * @param observer the observer to be notified - */ - public void setObserver(@NonNull final OfflineRegionObserver observer) { - setOfflineRegionObserver(new OfflineRegionObserver() { + return handler; + } + + /** + * Register an observer to be notified when the state of the region changes. + * + * @param observer the observer to be notified + */ + public void setObserver(@NonNull final OfflineRegionObserver observer) { + setOfflineRegionObserver(new OfflineRegionObserver() { + @Override + public void onStatusChanged(final OfflineRegionStatus status) { + if (deliverMessages()) { + getHandler().post(new Runnable() { @Override - public void onStatusChanged(final OfflineRegionStatus status) { - if (deliverMessages()) { - getHandler().post(new Runnable() { - @Override - public void run() { - observer.onStatusChanged(status); - } - }); - } + public void run() { + observer.onStatusChanged(status); } + }); + } + } + @Override + public void onError(final OfflineRegionError error) { + if (deliverMessages()) { + getHandler().post(new Runnable() { @Override - public void onError(final OfflineRegionError error) { - if (deliverMessages()) { - getHandler().post(new Runnable() { - @Override - public void run() { - observer.onError(error); - } - }); - } + public void run() { + observer.onError(error); } + }); + } + } + @Override + public void mapboxTileCountLimitExceeded(final long limit) { + if (deliverMessages()) { + getHandler().post(new Runnable() { @Override - public void mapboxTileCountLimitExceeded(final long limit) { - if (deliverMessages()) { - getHandler().post(new Runnable() { - @Override - public void run() { - observer.mapboxTileCountLimitExceeded(limit); - } - }); - } + public void run() { + observer.mapboxTileCountLimitExceeded(limit); } + }); + } + } + }); + } + + /** + * Pause or resume downloading of regional resources. + * + * @param state the download state + */ + public void setDownloadState(@DownloadState int state) { + this.state = state; + setOfflineRegionDownloadState(state); + } + + /** + * Retrieve the current status of the region. The query will be executed + * asynchronously and the results passed to the given callback which will be + * executed on the main thread. + * + * @param callback the callback to invoked. + */ + public void getStatus(@NonNull final OfflineRegionStatusCallback callback) { + getOfflineRegionStatus(new OfflineRegionStatusCallback() { + @Override + public void onStatus(final OfflineRegionStatus status) { + getHandler().post(new Runnable() { + @Override + public void run() { + callback.onStatus(status); + } }); - } - - /** - * Pause or resume downloading of regional resources. - * - * @param state the download state - */ - public void setDownloadState(@DownloadState int state) { - this.state = state; - setOfflineRegionDownloadState(state); - } - - /** - * Retrieve the current status of the region. The query will be executed - * asynchronously and the results passed to the given callback which will be - * executed on the main thread. - * - * @param callback the callback to invoked. - */ - public void getStatus(@NonNull final OfflineRegionStatusCallback callback) { - getOfflineRegionStatus(new OfflineRegionStatusCallback() { - @Override - public void onStatus(final OfflineRegionStatus status) { - getHandler().post(new Runnable() { - @Override - public void run() { - callback.onStatus(status); - } - }); - } - - @Override - public void onError(final String error) { - getHandler().post(new Runnable() { - @Override - public void run() { - callback.onError(error); - } - }); - } + } + + @Override + public void onError(final String error) { + getHandler().post(new Runnable() { + @Override + public void run() { + callback.onError(error); + } }); - } - - /** - * Remove an offline region from the database and perform any resources evictions - * necessary as a result. - * <p> - * Eviction works by removing the least-recently requested resources not also required - * by other regions, until the database shrinks below a certain size. - * </p> - * <p> - * When the operation is complete or encounters an error, the given callback will be - * executed on the main thread. - * </p> - * <p> - * After you call this method, you may not call any additional methods on this object. - * </p> - * - * @param callback the callback to be invoked - */ - public void delete(@NonNull final OfflineRegionDeleteCallback callback) { - deleteOfflineRegion(new OfflineRegionDeleteCallback() { - @Override - public void onDelete() { - getHandler().post(new Runnable() { - @Override - public void run() { - callback.onDelete(); - OfflineRegion.this.finalize(); - } - }); - } - - @Override - public void onError(final String error) { - getHandler().post(new Runnable() { - @Override - public void run() { - callback.onError(error); - } - }); - } + } + }); + } + + /** + * Remove an offline region from the database and perform any resources evictions + * necessary as a result. + * <p> + * Eviction works by removing the least-recently requested resources not also required + * by other regions, until the database shrinks below a certain size. + * </p> + * <p> + * When the operation is complete or encounters an error, the given callback will be + * executed on the main thread. + * </p> + * <p> + * After you call this method, you may not call any additional methods on this object. + * </p> + * + * @param callback the callback to be invoked + */ + public void delete(@NonNull final OfflineRegionDeleteCallback callback) { + deleteOfflineRegion(new OfflineRegionDeleteCallback() { + @Override + public void onDelete() { + getHandler().post(new Runnable() { + @Override + public void run() { + callback.onDelete(); + OfflineRegion.this.finalize(); + } }); - } - - /** - * Update an offline region metadata from the database. - * <p> - * When the operation is complete or encounters an error, the given callback will be - * executed on the main thread. - * </p> - * <p> - * After you call this method, you may not call any additional methods on this object. - * </p> - * - * @param callback the callback to be invoked - */ - public void updateMetadata(@NonNull final byte[] bytes, @NonNull final OfflineRegionUpdateMetadataCallback callback) { - updateOfflineRegionMetadata(bytes, new OfflineRegionUpdateMetadataCallback() { - @Override - public void onUpdate(final byte[] metadata) { - getHandler().post(new Runnable() { - @Override - public void run() { - mMetadata = metadata; - callback.onUpdate(metadata); - } - }); - } - - @Override - public void onError(final String error) { - getHandler().post(new Runnable() { - @Override - public void run() { - callback.onError(error); - } - }); - } + } + + @Override + public void onError(final String error) { + getHandler().post(new Runnable() { + @Override + public void run() { + callback.onError(error); + } }); + } + }); + } + + /** + * Update an offline region metadata from the database. + * <p> + * When the operation is complete or encounters an error, the given callback will be + * executed on the main thread. + * </p> + * <p> + * After you call this method, you may not call any additional methods on this object. + * </p> + * + * @param callback the callback to be invoked + */ + public void updateMetadata(@NonNull final byte[] bytes, @NonNull final OfflineRegionUpdateMetadataCallback callback) { + updateOfflineRegionMetadata(bytes, new OfflineRegionUpdateMetadataCallback() { + @Override + public void onUpdate(final byte[] metadata) { + getHandler().post(new Runnable() { + @Override + public void run() { + mMetadata = metadata; + callback.onUpdate(metadata); + } + }); + } + + @Override + public void onError(final String error) { + getHandler().post(new Runnable() { + @Override + public void run() { + callback.onError(error); + } + }); + } + }); + } + + @Override + protected void finalize() { + try { + super.finalize(); + destroyOfflineRegion(); + } catch (Throwable throwable) { + Timber.e("Failed to finalize OfflineRegion: " + throwable.getMessage()); } + } - @Override - protected void finalize() { - try { - super.finalize(); - destroyOfflineRegion(); - } catch (Throwable throwable) { - Timber.e("Failed to finalize OfflineRegion: " + throwable.getMessage()); - } - } - - /* - * Native methods - */ + /* + * Native methods + */ - private native void destroyOfflineRegion(); + private native void destroyOfflineRegion(); - private native void setOfflineRegionObserver( - OfflineRegionObserver observerCallback); + private native void setOfflineRegionObserver( + OfflineRegionObserver observerCallback); - private native void setOfflineRegionDownloadState( - @DownloadState int offlineRegionDownloadState); + private native void setOfflineRegionDownloadState( + @DownloadState int offlineRegionDownloadState); - private native void getOfflineRegionStatus( - OfflineRegionStatusCallback statusCallback); + private native void getOfflineRegionStatus( + OfflineRegionStatusCallback statusCallback); - private native void deleteOfflineRegion( - OfflineRegionDeleteCallback deleteCallback); + private native void deleteOfflineRegion( + OfflineRegionDeleteCallback deleteCallback); - private native void updateOfflineRegionMetadata(byte[] metadata, OfflineRegionUpdateMetadataCallback callback); + private native void updateOfflineRegionMetadata(byte[] metadata, OfflineRegionUpdateMetadataCallback callback); } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionDefinition.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionDefinition.java index 0e7fb38e1c..a21ff0a443 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionDefinition.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionDefinition.java @@ -2,7 +2,7 @@ package com.mapbox.mapboxsdk.offline; /** * This is the interface that all Offline Region definitions have to implement. - * + * <p> * For the present, a tile pyramid is the only type of offline region. */ public interface OfflineRegionDefinition { diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionError.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionError.java index e7a57379c5..60c4a8661c 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionError.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionError.java @@ -10,44 +10,47 @@ import java.lang.annotation.RetentionPolicy; */ public class OfflineRegionError { - /** - * Error code, as a string, self-explanatory. - */ - @StringDef({REASON_SUCCESS, REASON_NOT_FOUND, REASON_SERVER, REASON_CONNECTION, REASON_OTHER}) - @Retention(RetentionPolicy.SOURCE) - public @interface ErrorReason {} - - public static final String REASON_SUCCESS = "REASON_SUCCESS"; - public static final String REASON_NOT_FOUND = "REASON_NOT_FOUND"; - public static final String REASON_SERVER = "REASON_SERVER"; - public static final String REASON_CONNECTION = "REASON_CONNECTION"; - public static final String REASON_OTHER = "REASON_OTHER"; - - private @ErrorReason String reason; - - /** - /* An error message from the request handler, e.g. a server message or a system message - /* informing the user about the reason for the failure. - */ - private String message; - - /* - * Constructors - */ - - private OfflineRegionError() { - // For JNI use only - } - - /* - * Getters - */ - - public @ErrorReason String getReason() { - return reason; - } - - public String getMessage() { - return message; - } + /** + * Error code, as a string, self-explanatory. + */ + @StringDef( {REASON_SUCCESS, REASON_NOT_FOUND, REASON_SERVER, REASON_CONNECTION, REASON_OTHER}) + @Retention(RetentionPolicy.SOURCE) + public @interface ErrorReason { + } + + public static final String REASON_SUCCESS = "REASON_SUCCESS"; + public static final String REASON_NOT_FOUND = "REASON_NOT_FOUND"; + public static final String REASON_SERVER = "REASON_SERVER"; + public static final String REASON_CONNECTION = "REASON_CONNECTION"; + public static final String REASON_OTHER = "REASON_OTHER"; + + @ErrorReason + private String reason; + + /** + * /* An error message from the request handler, e.g. a server message or a system message + * /* informing the user about the reason for the failure. + */ + private String message; + + /* + * Constructors + */ + + private OfflineRegionError() { + // For JNI use only + } + + /* + * Getters + */ + + @ErrorReason + public String getReason() { + return reason; + } + + public String getMessage() { + return message; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionStatus.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionStatus.java index 48609a13bb..11f2da132d 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionStatus.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionStatus.java @@ -4,101 +4,103 @@ package com.mapbox.mapboxsdk.offline; * A region's status includes its active/inactive state as well as counts * of the number of resources that have completed downloading, their total * size in bytes, and the total number of resources that are required. - * + * <p> * Note that the total required size in bytes is not currently available. A * future API release may provide an estimate of this number. */ public class OfflineRegionStatus { - @OfflineRegion.DownloadState private int downloadState = OfflineRegion.STATE_INACTIVE; - - /** - * The number of resources (inclusive of tiles) that have been fully downloaded - * and are ready for offline access. - */ - private long completedResourceCount = 0; - - /** - * The cumulative size, in bytes, of all resources (inclusive of tiles) that have - * been fully downloaded. - */ - private long completedResourceSize = 0; - - /** - * The number of tiles that have been fully downloaded and are ready for - * offline access. - */ - private long completedTileCount = 0; - - /** - * The cumulative size, in bytes, of all tiles that have been fully downloaded. - */ - private long completedTileSize = 0; - - /** - * The number of resources that are known to be required for this region. See the - * documentation for `requiredResourceCountIsPrecise` for an important caveat - * about this number. - */ - private long requiredResourceCount = 0; - - /** - * This property is true when the value of requiredResourceCount is a precise - * count of the number of required resources, and false when it is merely a lower - * bound. - * - * Specifically, it is false during early phases of an offline download. Once - * style and tile sources have been downloaded, it is possible to calculate the - * precise number of required resources, at which point it is set to true. - */ - private boolean requiredResourceCountIsPrecise = true; - - /* - * Use setObserver(OfflineRegionObserver observer) to obtain a OfflineRegionStatus object. - */ - - private OfflineRegionStatus() { - // For JNI use only - } - - /* - * Is the region complete? - */ - - public boolean isComplete() { - return (completedResourceCount == requiredResourceCount); - } - - /* - * Getters - */ - - public @OfflineRegion.DownloadState int getDownloadState() { - return downloadState; - } - - public long getCompletedResourceCount() { - return completedResourceCount; - } - - public long getCompletedResourceSize() { - return completedResourceSize; - } - - public long getCompletedTileCount() { - return completedTileCount; - } - - public long getCompletedTileSize() { - return completedTileSize; - } - - public long getRequiredResourceCount() { - return requiredResourceCount; - } - - public boolean isRequiredResourceCountPrecise() { - return requiredResourceCountIsPrecise; - } + @OfflineRegion.DownloadState + private int downloadState = OfflineRegion.STATE_INACTIVE; + + /** + * The number of resources (inclusive of tiles) that have been fully downloaded + * and are ready for offline access. + */ + private long completedResourceCount = 0; + + /** + * The cumulative size, in bytes, of all resources (inclusive of tiles) that have + * been fully downloaded. + */ + private long completedResourceSize = 0; + + /** + * The number of tiles that have been fully downloaded and are ready for + * offline access. + */ + private long completedTileCount = 0; + + /** + * The cumulative size, in bytes, of all tiles that have been fully downloaded. + */ + private long completedTileSize = 0; + + /** + * The number of resources that are known to be required for this region. See the + * documentation for `requiredResourceCountIsPrecise` for an important caveat + * about this number. + */ + private long requiredResourceCount = 0; + + /** + * This property is true when the value of requiredResourceCount is a precise + * count of the number of required resources, and false when it is merely a lower + * bound. + * <p> + * Specifically, it is false during early phases of an offline download. Once + * style and tile sources have been downloaded, it is possible to calculate the + * precise number of required resources, at which point it is set to true. + */ + private boolean requiredResourceCountIsPrecise = true; + + /* + * Use setObserver(OfflineRegionObserver observer) to obtain a OfflineRegionStatus object. + */ + + private OfflineRegionStatus() { + // For JNI use only + } + + /* + * Is the region complete? + */ + + public boolean isComplete() { + return (completedResourceCount == requiredResourceCount); + } + + /* + * Getters + */ + + @OfflineRegion.DownloadState + public int getDownloadState() { + return downloadState; + } + + public long getCompletedResourceCount() { + return completedResourceCount; + } + + public long getCompletedResourceSize() { + return completedResourceSize; + } + + public long getCompletedTileCount() { + return completedTileCount; + } + + public long getCompletedTileSize() { + return completedTileSize; + } + + public long getRequiredResourceCount() { + return requiredResourceCount; + } + + public boolean isRequiredResourceCountPrecise() { + return requiredResourceCountIsPrecise; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineTilePyramidRegionDefinition.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineTilePyramidRegionDefinition.java index 5a0be6b33f..5fc844afe5 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineTilePyramidRegionDefinition.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineTilePyramidRegionDefinition.java @@ -5,61 +5,61 @@ import com.mapbox.mapboxsdk.geometry.LatLngBounds; /** * An offline region defined by a style URL, geographic bounding box, zoom range, and * device pixel ratio. - * + * <p> * Both minZoom and maxZoom must be ≥ 0, and maxZoom must be ≥ minZoom. - * + * <p> * maxZoom may be ∞, in which case for each tile source, the region will include * tiles from minZoom up to the maximum zoom level provided by that source. - * + * <p> * pixelRatio must be ≥ 0 and should typically be 1.0 or 2.0. */ public class OfflineTilePyramidRegionDefinition implements OfflineRegionDefinition { - private String styleURL; - private LatLngBounds bounds; - private double minZoom; - private double maxZoom; - private float pixelRatio; + private String styleURL; + private LatLngBounds bounds; + private double minZoom; + private double maxZoom; + private float pixelRatio; - /* - * Constructors - */ + /* + * Constructors + */ - private OfflineTilePyramidRegionDefinition() { - // For JNI use only - } + private OfflineTilePyramidRegionDefinition() { + // For JNI use only + } - public OfflineTilePyramidRegionDefinition( - String styleURL, LatLngBounds bounds, double minZoom, double maxZoom, float pixelRatio) { - this.styleURL = styleURL; - this.bounds = bounds; - this.minZoom = minZoom; - this.maxZoom = maxZoom; - this.pixelRatio = pixelRatio; - } + public OfflineTilePyramidRegionDefinition( + String styleURL, LatLngBounds bounds, double minZoom, double maxZoom, float pixelRatio) { + this.styleURL = styleURL; + this.bounds = bounds; + this.minZoom = minZoom; + this.maxZoom = maxZoom; + this.pixelRatio = pixelRatio; + } - /* - * Getters - */ + /* + * Getters + */ - public String getStyleURL() { - return styleURL; - } + public String getStyleURL() { + return styleURL; + } - public LatLngBounds getBounds() { - return bounds; - } + public LatLngBounds getBounds() { + return bounds; + } - public double getMinZoom() { - return minZoom; - } + public double getMinZoom() { + return minZoom; + } - public double getMaxZoom() { - return maxZoom; - } + public double getMaxZoom() { + return maxZoom; + } - public float getPixelRatio() { - return pixelRatio; - } + public float getPixelRatio() { + return pixelRatio; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/BackgroundLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/BackgroundLayer.java index c78887ff15..45523b41ab 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/BackgroundLayer.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/BackgroundLayer.java @@ -1,12 +1,11 @@ -// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. package com.mapbox.mapboxsdk.style.layers; - -import android.support.annotation.UiThread; +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. import android.support.annotation.ColorInt; import android.support.annotation.NonNull; +import android.support.annotation.UiThread; -import static com.mapbox.mapboxsdk.utils.ColorUtils.*; +import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor; /** * The background color or pattern of the map. @@ -16,93 +15,94 @@ import static com.mapbox.mapboxsdk.utils.ColorUtils.*; @UiThread public class BackgroundLayer extends Layer { - /** - * Creates a BackgroundLayer. - * - * @param nativePtr pointer used by core - */ - public BackgroundLayer(long nativePtr) { - super(nativePtr); - } - - /** - * Creates a BackgroundLayer. - * - * @param layerId the id of the layer - */ - public BackgroundLayer(String layerId) { - initialize(layerId); + /** + * Creates a BackgroundLayer. + * + * @param nativePtr pointer used by core + */ + public BackgroundLayer(long nativePtr) { + super(nativePtr); + } + + /** + * Creates a BackgroundLayer. + * + * @param layerId the id of the layer + */ + public BackgroundLayer(String layerId) { + initialize(layerId); + } + + protected native void initialize(String layerId); + + /** + * Set a property or properties. + * + * @param properties the var-args properties + * @return This + */ + public BackgroundLayer withProperties(@NonNull Property<?>... properties) { + setProperties(properties); + return this; + } + + // Property getters + + /** + * Get the BackgroundColor property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getBackgroundColor() { + return (PropertyValue<String>) new PropertyValue(nativeGetBackgroundColor()); + } + + /** + * The color with which the background will be drawn. + * + * @return int representation of a rgba string color + * @throws RuntimeException thrown if property isn't a value + */ + @ColorInt + public int getBackgroundColorAsInt() { + PropertyValue<String> value = getBackgroundColor(); + if (value.isValue()) { + return rgbaToColor(value.getValue()); + } else { + throw new RuntimeException("background-color was set as a Function"); } + } - protected native void initialize(String layerId); - - /** - * Set a property or properties. - * - * @param properties the var-args properties - * @return This - */ - public BackgroundLayer withProperties(@NonNull Property<?>... properties) { - setProperties(properties); - return this; - } - // Property getters + /** + * Get the BackgroundPattern property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getBackgroundPattern() { + return (PropertyValue<String>) new PropertyValue(nativeGetBackgroundPattern()); + } - /** - * Get the BackgroundColor property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getBackgroundColor() { - return (PropertyValue<String>) new PropertyValue(nativeGetBackgroundColor()); - } - /** - * The color with which the background will be drawn. - * - * @return int representation of a rgba string color - * @throws RuntimeException thrown if property isn't a value - */ - @ColorInt - public int getBackgroundColorAsInt() { - PropertyValue<String> value = getBackgroundColor(); - if (value.isValue()) { - return rgbaToColor(value.getValue()); - } else { - throw new RuntimeException("background-color was set as a Function"); - } - } + /** + * Get the BackgroundOpacity property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getBackgroundOpacity() { + return (PropertyValue<Float>) new PropertyValue(nativeGetBackgroundOpacity()); + } - - /** - * Get the BackgroundPattern property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getBackgroundPattern() { - return (PropertyValue<String>) new PropertyValue(nativeGetBackgroundPattern()); - } - - /** - * Get the BackgroundOpacity property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getBackgroundOpacity() { - return (PropertyValue<Float>) new PropertyValue(nativeGetBackgroundOpacity()); - } - - private native Object nativeGetBackgroundColor(); + private native Object nativeGetBackgroundColor(); - private native Object nativeGetBackgroundPattern(); + private native Object nativeGetBackgroundPattern(); - private native Object nativeGetBackgroundOpacity(); + private native Object nativeGetBackgroundOpacity(); - @Override - protected native void finalize() throws Throwable; + @Override + protected native void finalize() throws Throwable; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CannotAddLayerException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CannotAddLayerException.java index 088c82f313..212493032d 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CannotAddLayerException.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CannotAddLayerException.java @@ -5,8 +5,8 @@ package com.mapbox.mapboxsdk.style.layers; */ public class CannotAddLayerException extends RuntimeException { - public CannotAddLayerException(String message) { - super(message); - } + public CannotAddLayerException(String message) { + super(message); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java index d46414a351..f16ab688d6 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java @@ -1,12 +1,11 @@ -// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. package com.mapbox.mapboxsdk.style.layers; - -import android.support.annotation.UiThread; +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. import android.support.annotation.ColorInt; import android.support.annotation.NonNull; +import android.support.annotation.UiThread; -import static com.mapbox.mapboxsdk.utils.ColorUtils.*; +import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor; /** * A filled circle. @@ -16,254 +15,257 @@ import static com.mapbox.mapboxsdk.utils.ColorUtils.*; @UiThread public class CircleLayer extends Layer { - /** - * Creates a CircleLayer. - * - * @param nativePtr pointer used by core - */ - public CircleLayer(long nativePtr) { - super(nativePtr); - } + /** + * Creates a CircleLayer. + * + * @param nativePtr pointer used by core + */ + public CircleLayer(long nativePtr) { + super(nativePtr); + } - /** - * Creates a CircleLayer. - * - * @param layerId the id of the layer - * @param sourceId the id of the source - */ - public CircleLayer(String layerId, String sourceId) { - initialize(layerId, sourceId); - } + /** + * Creates a CircleLayer. + * + * @param layerId the id of the layer + * @param sourceId the id of the source + */ + public CircleLayer(String layerId, String sourceId) { + initialize(layerId, sourceId); + } - protected native void initialize(String layerId, String sourceId); + protected native void initialize(String layerId, String sourceId); - /** - * Set the source layer. - * - * @param sourceLayer the source layer to set - */ - public void setSourceLayer(String sourceLayer) { - nativeSetSourceLayer(sourceLayer); - } + /** + * Set the source layer. + * + * @param sourceLayer the source layer to set + */ + public void setSourceLayer(String sourceLayer) { + nativeSetSourceLayer(sourceLayer); + } - /** - * Set the source Layer. - * - * @param sourceLayer the source layer to set - * @return This - */ - public CircleLayer withSourceLayer(String sourceLayer) { - setSourceLayer(sourceLayer); - return this; - } - /** - * Set a single filter. - * - * @param filter the filter to set - */ - public void setFilter(Filter.Statement filter) { - this.setFilter(filter.toArray()); - } + /** + * Set the source Layer. + * + * @param sourceLayer the source layer to set + * @return This + */ + public CircleLayer withSourceLayer(String sourceLayer) { + setSourceLayer(sourceLayer); + return this; + } - /** - * Set an array of filters. - * - * @param filter the filter array to set - */ - public void setFilter(Object[] filter) { - nativeSetFilter(filter); - } + /** + * Set a single filter. + * + * @param filter the filter to set + */ + public void setFilter(Filter.Statement filter) { + this.setFilter(filter.toArray()); + } - /** - * Set an array of filters. - * - * @param filter tthe filter array to set - * @return This - */ - public CircleLayer withFilter(Object[] filter) { - setFilter(filter); - return this; - } + /** + * Set an array of filters. + * + * @param filter the filter array to set + */ + public void setFilter(Object[] filter) { + nativeSetFilter(filter); + } - /** - * Set a single filter. - * - * @param filter the filter to set - * @return This - */ - public CircleLayer withFilter(Filter.Statement filter) { - setFilter(filter); - return this; - } + /** + * Set an array of filters. + * + * @param filter tthe filter array to set + * @return This + */ + public CircleLayer withFilter(Object[] filter) { + setFilter(filter); + return this; + } + /** + * Set a single filter. + * + * @param filter the filter to set + * @return This + */ + public CircleLayer withFilter(Filter.Statement filter) { + setFilter(filter); + return this; + } - /** - * Set a property or properties. - * - * @param properties the var-args properties - * @return This - */ - public CircleLayer withProperties(@NonNull Property<?>... properties) { - setProperties(properties); - return this; - } - // Property getters + /** + * Set a property or properties. + * + * @param properties the var-args properties + * @return This + */ + public CircleLayer withProperties(@NonNull Property<?>... properties) { + setProperties(properties); + return this; + } - /** - * Get the CircleRadius property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getCircleRadius() { - return (PropertyValue<Float>) new PropertyValue(nativeGetCircleRadius()); - } - - /** - * Get the CircleColor property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getCircleColor() { - return (PropertyValue<String>) new PropertyValue(nativeGetCircleColor()); - } - /** - * The fill color of the circle. - * - * @return int representation of a rgba string color - * @throws RuntimeException thrown if property isn't a value - */ - @ColorInt - public int getCircleColorAsInt() { - PropertyValue<String> value = getCircleColor(); - if (value.isValue()) { - return rgbaToColor(value.getValue()); - } else { - throw new RuntimeException("circle-color was set as a Function"); - } - } + // Property getters - - /** - * Get the CircleBlur property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getCircleBlur() { - return (PropertyValue<Float>) new PropertyValue(nativeGetCircleBlur()); - } - - /** - * Get the CircleOpacity property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getCircleOpacity() { - return (PropertyValue<Float>) new PropertyValue(nativeGetCircleOpacity()); - } - - /** - * Get the CircleTranslate property - * - * @return property wrapper value around Float[] - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float[]> getCircleTranslate() { - return (PropertyValue<Float[]>) new PropertyValue(nativeGetCircleTranslate()); - } - - /** - * Get the CircleTranslateAnchor property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getCircleTranslateAnchor() { - return (PropertyValue<String>) new PropertyValue(nativeGetCircleTranslateAnchor()); - } - - /** - * Get the CirclePitchScale property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getCirclePitchScale() { - return (PropertyValue<String>) new PropertyValue(nativeGetCirclePitchScale()); - } - - /** - * Get the CircleStrokeWidth property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getCircleStrokeWidth() { - return (PropertyValue<Float>) new PropertyValue(nativeGetCircleStrokeWidth()); - } - - /** - * Get the CircleStrokeColor property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getCircleStrokeColor() { - return (PropertyValue<String>) new PropertyValue(nativeGetCircleStrokeColor()); - } - /** - * The stroke color of the circle. - * - * @return int representation of a rgba string color - * @throws RuntimeException thrown if property isn't a value - */ - @ColorInt - public int getCircleStrokeColorAsInt() { - PropertyValue<String> value = getCircleStrokeColor(); - if (value.isValue()) { - return rgbaToColor(value.getValue()); - } else { - throw new RuntimeException("circle-stroke-color was set as a Function"); - } + /** + * Get the CircleRadius property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getCircleRadius() { + return (PropertyValue<Float>) new PropertyValue(nativeGetCircleRadius()); + } + + /** + * Get the CircleColor property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getCircleColor() { + return (PropertyValue<String>) new PropertyValue(nativeGetCircleColor()); + } + + /** + * The fill color of the circle. + * + * @return int representation of a rgba string color + * @throws RuntimeException thrown if property isn't a value + */ + @ColorInt + public int getCircleColorAsInt() { + PropertyValue<String> value = getCircleColor(); + if (value.isValue()) { + return rgbaToColor(value.getValue()); + } else { + throw new RuntimeException("circle-color was set as a Function"); } + } + + + /** + * Get the CircleBlur property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getCircleBlur() { + return (PropertyValue<Float>) new PropertyValue(nativeGetCircleBlur()); + } - - /** - * Get the CircleStrokeOpacity property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getCircleStrokeOpacity() { - return (PropertyValue<Float>) new PropertyValue(nativeGetCircleStrokeOpacity()); + /** + * Get the CircleOpacity property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getCircleOpacity() { + return (PropertyValue<Float>) new PropertyValue(nativeGetCircleOpacity()); + } + + /** + * Get the CircleTranslate property + * + * @return property wrapper value around Float[] + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float[]> getCircleTranslate() { + return (PropertyValue<Float[]>) new PropertyValue(nativeGetCircleTranslate()); + } + + /** + * Get the CircleTranslateAnchor property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getCircleTranslateAnchor() { + return (PropertyValue<String>) new PropertyValue(nativeGetCircleTranslateAnchor()); + } + + /** + * Get the CirclePitchScale property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getCirclePitchScale() { + return (PropertyValue<String>) new PropertyValue(nativeGetCirclePitchScale()); + } + + /** + * Get the CircleStrokeWidth property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getCircleStrokeWidth() { + return (PropertyValue<Float>) new PropertyValue(nativeGetCircleStrokeWidth()); + } + + /** + * Get the CircleStrokeColor property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getCircleStrokeColor() { + return (PropertyValue<String>) new PropertyValue(nativeGetCircleStrokeColor()); + } + + /** + * The stroke color of the circle. + * + * @return int representation of a rgba string color + * @throws RuntimeException thrown if property isn't a value + */ + @ColorInt + public int getCircleStrokeColorAsInt() { + PropertyValue<String> value = getCircleStrokeColor(); + if (value.isValue()) { + return rgbaToColor(value.getValue()); + } else { + throw new RuntimeException("circle-stroke-color was set as a Function"); } - - private native Object nativeGetCircleRadius(); + } + + + /** + * Get the CircleStrokeOpacity property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getCircleStrokeOpacity() { + return (PropertyValue<Float>) new PropertyValue(nativeGetCircleStrokeOpacity()); + } + + private native Object nativeGetCircleRadius(); - private native Object nativeGetCircleColor(); + private native Object nativeGetCircleColor(); - private native Object nativeGetCircleBlur(); + private native Object nativeGetCircleBlur(); - private native Object nativeGetCircleOpacity(); + private native Object nativeGetCircleOpacity(); - private native Object nativeGetCircleTranslate(); + private native Object nativeGetCircleTranslate(); - private native Object nativeGetCircleTranslateAnchor(); + private native Object nativeGetCircleTranslateAnchor(); - private native Object nativeGetCirclePitchScale(); + private native Object nativeGetCirclePitchScale(); - private native Object nativeGetCircleStrokeWidth(); + private native Object nativeGetCircleStrokeWidth(); - private native Object nativeGetCircleStrokeColor(); + private native Object nativeGetCircleStrokeColor(); - private native Object nativeGetCircleStrokeOpacity(); + private native Object nativeGetCircleStrokeOpacity(); - @Override - protected native void finalize() throws Throwable; + @Override + protected native void finalize() throws Throwable; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CustomLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CustomLayer.java index 4d578b54f8..7807556b78 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CustomLayer.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CustomLayer.java @@ -8,27 +8,28 @@ package com.mapbox.mapboxsdk.style.layers; */ public class CustomLayer extends Layer { - public CustomLayer(String id, - long context, - long initializeFunction, - long renderFunction, - long deinitializeFunction) { - initialize(id, initializeFunction, renderFunction, deinitializeFunction, context); - } + public CustomLayer(String id, + long context, + long initializeFunction, + long renderFunction, + long deinitializeFunction) { + initialize(id, initializeFunction, renderFunction, deinitializeFunction, context); + } - public CustomLayer(long nativePtr) { - super(nativePtr); - } + public CustomLayer(long nativePtr) { + super(nativePtr); + } - public void update() { - nativeUpdate(); - } + public void update() { + nativeUpdate(); + } - protected native void initialize(String id, long initializeFunction, long renderFunction, long deinitializeFunction, long context); + protected native void initialize(String id, long initializeFunction, long renderFunction, long deinitializeFunction, + long context); - protected native void nativeUpdate(); + protected native void nativeUpdate(); - @Override - protected native void finalize() throws Throwable; + @Override + protected native void finalize() throws Throwable; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillLayer.java index b49b23e732..3f79c9306a 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillLayer.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillLayer.java @@ -1,12 +1,11 @@ -// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. package com.mapbox.mapboxsdk.style.layers; - -import android.support.annotation.UiThread; +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. import android.support.annotation.ColorInt; import android.support.annotation.NonNull; +import android.support.annotation.UiThread; -import static com.mapbox.mapboxsdk.utils.ColorUtils.*; +import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor; /** * A filled polygon with an optional stroked border. @@ -16,218 +15,222 @@ import static com.mapbox.mapboxsdk.utils.ColorUtils.*; @UiThread public class FillLayer extends Layer { - /** - * Creates a FillLayer. - * - * @param nativePtr pointer used by core - */ - public FillLayer(long nativePtr) { - super(nativePtr); - } - - /** - * Creates a FillLayer. - * - * @param layerId the id of the layer - * @param sourceId the id of the source - */ - public FillLayer(String layerId, String sourceId) { - initialize(layerId, sourceId); - } - - protected native void initialize(String layerId, String sourceId); - - /** - * Set the source layer. - * - * @param sourceLayer the source layer to set - */ - public void setSourceLayer(String sourceLayer) { - nativeSetSourceLayer(sourceLayer); - } - - /** - * Set the source Layer. - * - * @param sourceLayer the source layer to set - * @return This - */ - public FillLayer withSourceLayer(String sourceLayer) { - setSourceLayer(sourceLayer); - return this; - } - /** - * Set a single filter. - * - * @param filter the filter to set - */ - public void setFilter(Filter.Statement filter) { - this.setFilter(filter.toArray()); - } - - /** - * Set an array of filters. - * - * @param filter the filter array to set - */ - public void setFilter(Object[] filter) { - nativeSetFilter(filter); - } - - /** - * Set an array of filters. - * - * @param filter tthe filter array to set - * @return This - */ - public FillLayer withFilter(Object[] filter) { - setFilter(filter); - return this; - } - - /** - * Set a single filter. - * - * @param filter the filter to set - * @return This - */ - public FillLayer withFilter(Filter.Statement filter) { - setFilter(filter); - return this; - } - - - /** - * Set a property or properties. - * - * @param properties the var-args properties - * @return This - */ - public FillLayer withProperties(@NonNull Property<?>... properties) { - setProperties(properties); - return this; - } - - // Property getters - - /** - * Get the FillAntialias property - * - * @return property wrapper value around Boolean - */ - @SuppressWarnings("unchecked") - public PropertyValue<Boolean> getFillAntialias() { - return (PropertyValue<Boolean>) new PropertyValue(nativeGetFillAntialias()); - } - - /** - * Get the FillOpacity property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getFillOpacity() { - return (PropertyValue<Float>) new PropertyValue(nativeGetFillOpacity()); - } - - /** - * Get the FillColor property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getFillColor() { - return (PropertyValue<String>) new PropertyValue(nativeGetFillColor()); - } - /** - * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the color's opacity will not affect the opacity of the 1px stroke, if it is used. - * - * @return int representation of a rgba string color - * @throws RuntimeException thrown if property isn't a value - */ - @ColorInt - public int getFillColorAsInt() { - PropertyValue<String> value = getFillColor(); - if (value.isValue()) { - return rgbaToColor(value.getValue()); - } else { - throw new RuntimeException("fill-color was set as a Function"); - } - } - - - /** - * Get the FillOutlineColor property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getFillOutlineColor() { - return (PropertyValue<String>) new PropertyValue(nativeGetFillOutlineColor()); - } - /** - * The outline color of the fill. Matches the value of `fill-color` if unspecified. - * - * @return int representation of a rgba string color - * @throws RuntimeException thrown if property isn't a value - */ - @ColorInt - public int getFillOutlineColorAsInt() { - PropertyValue<String> value = getFillOutlineColor(); - if (value.isValue()) { - return rgbaToColor(value.getValue()); - } else { - throw new RuntimeException("fill-outline-color was set as a Function"); - } - } - - - /** - * Get the FillTranslate property - * - * @return property wrapper value around Float[] - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float[]> getFillTranslate() { - return (PropertyValue<Float[]>) new PropertyValue(nativeGetFillTranslate()); - } - - /** - * Get the FillTranslateAnchor property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getFillTranslateAnchor() { - return (PropertyValue<String>) new PropertyValue(nativeGetFillTranslateAnchor()); - } - - /** - * Get the FillPattern property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getFillPattern() { - return (PropertyValue<String>) new PropertyValue(nativeGetFillPattern()); - } - - private native Object nativeGetFillAntialias(); - - private native Object nativeGetFillOpacity(); - - private native Object nativeGetFillColor(); - - private native Object nativeGetFillOutlineColor(); - - private native Object nativeGetFillTranslate(); - - private native Object nativeGetFillTranslateAnchor(); - - private native Object nativeGetFillPattern(); - - - @Override - protected native void finalize() throws Throwable; + /** + * Creates a FillLayer. + * + * @param nativePtr pointer used by core + */ + public FillLayer(long nativePtr) { + super(nativePtr); + } + + /** + * Creates a FillLayer. + * + * @param layerId the id of the layer + * @param sourceId the id of the source + */ + public FillLayer(String layerId, String sourceId) { + initialize(layerId, sourceId); + } + + protected native void initialize(String layerId, String sourceId); + + /** + * Set the source layer. + * + * @param sourceLayer the source layer to set + */ + public void setSourceLayer(String sourceLayer) { + nativeSetSourceLayer(sourceLayer); + } + + /** + * Set the source Layer. + * + * @param sourceLayer the source layer to set + * @return This + */ + public FillLayer withSourceLayer(String sourceLayer) { + setSourceLayer(sourceLayer); + return this; + } + + /** + * Set a single filter. + * + * @param filter the filter to set + */ + public void setFilter(Filter.Statement filter) { + this.setFilter(filter.toArray()); + } + + /** + * Set an array of filters. + * + * @param filter the filter array to set + */ + public void setFilter(Object[] filter) { + nativeSetFilter(filter); + } + + /** + * Set an array of filters. + * + * @param filter tthe filter array to set + * @return This + */ + public FillLayer withFilter(Object[] filter) { + setFilter(filter); + return this; + } + + /** + * Set a single filter. + * + * @param filter the filter to set + * @return This + */ + public FillLayer withFilter(Filter.Statement filter) { + setFilter(filter); + return this; + } + + + /** + * Set a property or properties. + * + * @param properties the var-args properties + * @return This + */ + public FillLayer withProperties(@NonNull Property<?>... properties) { + setProperties(properties); + return this; + } + + // Property getters + + /** + * Get the FillAntialias property + * + * @return property wrapper value around Boolean + */ + @SuppressWarnings("unchecked") + public PropertyValue<Boolean> getFillAntialias() { + return (PropertyValue<Boolean>) new PropertyValue(nativeGetFillAntialias()); + } + + /** + * Get the FillOpacity property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getFillOpacity() { + return (PropertyValue<Float>) new PropertyValue(nativeGetFillOpacity()); + } + + /** + * Get the FillColor property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getFillColor() { + return (PropertyValue<String>) new PropertyValue(nativeGetFillColor()); + } + + /** + * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the + * color's opacity will not affect the opacity of the 1px stroke, if it is used. + * + * @return int representation of a rgba string color + * @throws RuntimeException thrown if property isn't a value + */ + @ColorInt + public int getFillColorAsInt() { + PropertyValue<String> value = getFillColor(); + if (value.isValue()) { + return rgbaToColor(value.getValue()); + } else { + throw new RuntimeException("fill-color was set as a Function"); + } + } + + + /** + * Get the FillOutlineColor property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getFillOutlineColor() { + return (PropertyValue<String>) new PropertyValue(nativeGetFillOutlineColor()); + } + + /** + * The outline color of the fill. Matches the value of `fill-color` if unspecified. + * + * @return int representation of a rgba string color + * @throws RuntimeException thrown if property isn't a value + */ + @ColorInt + public int getFillOutlineColorAsInt() { + PropertyValue<String> value = getFillOutlineColor(); + if (value.isValue()) { + return rgbaToColor(value.getValue()); + } else { + throw new RuntimeException("fill-outline-color was set as a Function"); + } + } + + + /** + * Get the FillTranslate property + * + * @return property wrapper value around Float[] + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float[]> getFillTranslate() { + return (PropertyValue<Float[]>) new PropertyValue(nativeGetFillTranslate()); + } + + /** + * Get the FillTranslateAnchor property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getFillTranslateAnchor() { + return (PropertyValue<String>) new PropertyValue(nativeGetFillTranslateAnchor()); + } + + /** + * Get the FillPattern property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getFillPattern() { + return (PropertyValue<String>) new PropertyValue(nativeGetFillPattern()); + } + + private native Object nativeGetFillAntialias(); + + private native Object nativeGetFillOpacity(); + + private native Object nativeGetFillColor(); + + private native Object nativeGetFillOutlineColor(); + + private native Object nativeGetFillTranslate(); + + private native Object nativeGetFillTranslateAnchor(); + + private native Object nativeGetFillPattern(); + + + @Override + protected native void finalize() throws Throwable; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Filter.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Filter.java index 6f881e4960..643a126388 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Filter.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Filter.java @@ -10,221 +10,221 @@ import java.util.Collections; */ public class Filter { - /** - * Base {@link Filter} statement. Subclassed to provide concrete statements. - */ - public abstract static class Statement { - protected final String operator; - - public Statement(String operator) { - this.operator = operator; - } - - /** - * Generate a raw array representation of the filter - * - * @return the filter represented as an array - */ - public abstract Object[] toArray(); - } - - /** - * Represents a {@link Filter} statement. Can be unary (eg `has()`, etc) or take any number of values. - */ - private static class SimpleStatement extends Statement { - private final String key; - private final Object[] values; - - /** - * @param operator the operator (eg `=`, etc) - * @param key the property key - * @param values the values to operate on, if any - */ - SimpleStatement(String operator, String key, Object... values) { - super(operator); - this.key = key; - this.values = values; - } - - - /** - * {@inheritDoc} - */ - @Override - public Object[] toArray() { - ArrayList<Object> array = new ArrayList<>(2 + values.length); - array.add(operator); - array.add(key); - Collections.addAll(array, values); - return array.toArray(); - } - } - - /** - * Represents a collection of {@link Statement}s with an operator that describes their relationship - */ - private static class CompoundStatement extends Statement { - private final Statement[] statements; - - /** - * @param operator the relationship operator - * @param statements the statements to compound - */ - CompoundStatement(String operator, Statement... statements) { - super(operator); - this.statements = statements; - } - - /** - * {@inheritDoc} - */ - @Override - public Object[] toArray() { - ArrayList<Object> array = new ArrayList<>(1 + statements.length); - array.add(operator); - for (Statement statement : statements) { - array.add(statement.toArray()); - } - return array.toArray(); - } - } - - /** - * Groups a collection of statements in an 'all' relationship - * - * @param statements the collection of statements - * @return the statements compounded - */ - public static Statement all(Statement... statements) { - return new CompoundStatement("all", statements); - } - - /** - * Groups a collection of statements in an 'any' relationship - * - * @param statements the collection of statements - * @return the statements compounded - */ - public static Statement any(Statement... statements) { - return new CompoundStatement("any", statements); - } - - /** - * Groups a collection of statements in an 'none' relationship - * - * @param statements the collection of statements - * @return the statements compounded - */ - public static Statement none(Statement... statements) { - return new CompoundStatement("none", statements); - } - - /** - * Check the property's existence - * - * @param key the property key - * @return the statement - */ - public static Statement has(String key) { - return new SimpleStatement("has", key); - } + /** + * Base {@link Filter} statement. Subclassed to provide concrete statements. + */ + public abstract static class Statement { + protected final String operator; - /** - * Check the property's existence, negated - * - * @param key the property key - * @return the statement - */ - public static Statement notHas(String key) { - return new SimpleStatement("!has", key); + public Statement(String operator) { + this.operator = operator; } /** - * Check the property equals the given value + * Generate a raw array representation of the filter * - * @param key the property key - * @param value the value to check against - * @return the statement - */ - public static Statement eq(String key, Object value) { - return new SimpleStatement("==", key, value); - } - - /** - * Check the property does not equals the given value - * - * @param key the property key - * @param value the value to check against - * @return the statement - */ - public static Statement neq(String key, Object value) { - return new SimpleStatement("!=", key, value); - } - - /** - * Check the property exceeds the given value - * - * @param key the property key - * @param value the value to check against - * @return the statement - */ - public static Statement gt(String key, Object value) { - return new SimpleStatement(">", key, value); - } - - /** - * Check the property exceeds or equals the given value - * - * @param key the property key - * @param value the value to check against - * @return the statement - */ - public static Statement gte(String key, Object value) { - return new SimpleStatement(">=", key, value); - } - - /** - * Check the property does not exceeds the given value - * - * @param key the property key - * @param value the value to check against - * @return the statement - */ - public static Statement lt(String key, Object value) { - return new SimpleStatement("<", key, value); - } - - /** - * Check the property equals or does not exceeds the given value - * - * @param key the property key - * @param value the value to check against - * @return the statement - */ - public static Statement lte(String key, Object value) { - return new SimpleStatement("<=", key, value); - } - - /** - * Check the property is within the given set - * - * @param key the property key - * @param values the set of values to check against - * @return the statement - */ - public static Statement in(String key, Object... values) { - return new SimpleStatement("in", key, values); - } - - /** - * Check the property is not within the given set - * - * @param key the property key - * @param values the set of values to check against - * @return the statement - */ - public static Statement notIn(String key, Object... values) { - return new SimpleStatement("!in", key, values); - } + * @return the filter represented as an array + */ + public abstract Object[] toArray(); + } + + /** + * Represents a {@link Filter} statement. Can be unary (eg `has()`, etc) or take any number of values. + */ + private static class SimpleStatement extends Statement { + private final String key; + private final Object[] values; + + /** + * @param operator the operator (eg `=`, etc) + * @param key the property key + * @param values the values to operate on, if any + */ + SimpleStatement(String operator, String key, Object... values) { + super(operator); + this.key = key; + this.values = values; + } + + + /** + * {@inheritDoc} + */ + @Override + public Object[] toArray() { + ArrayList<Object> array = new ArrayList<>(2 + values.length); + array.add(operator); + array.add(key); + Collections.addAll(array, values); + return array.toArray(); + } + } + + /** + * Represents a collection of {@link Statement}s with an operator that describes their relationship + */ + private static class CompoundStatement extends Statement { + private final Statement[] statements; + + /** + * @param operator the relationship operator + * @param statements the statements to compound + */ + CompoundStatement(String operator, Statement... statements) { + super(operator); + this.statements = statements; + } + + /** + * {@inheritDoc} + */ + @Override + public Object[] toArray() { + ArrayList<Object> array = new ArrayList<>(1 + statements.length); + array.add(operator); + for (Statement statement : statements) { + array.add(statement.toArray()); + } + return array.toArray(); + } + } + + /** + * Groups a collection of statements in an 'all' relationship + * + * @param statements the collection of statements + * @return the statements compounded + */ + public static Statement all(Statement... statements) { + return new CompoundStatement("all", statements); + } + + /** + * Groups a collection of statements in an 'any' relationship + * + * @param statements the collection of statements + * @return the statements compounded + */ + public static Statement any(Statement... statements) { + return new CompoundStatement("any", statements); + } + + /** + * Groups a collection of statements in an 'none' relationship + * + * @param statements the collection of statements + * @return the statements compounded + */ + public static Statement none(Statement... statements) { + return new CompoundStatement("none", statements); + } + + /** + * Check the property's existence + * + * @param key the property key + * @return the statement + */ + public static Statement has(String key) { + return new SimpleStatement("has", key); + } + + /** + * Check the property's existence, negated + * + * @param key the property key + * @return the statement + */ + public static Statement notHas(String key) { + return new SimpleStatement("!has", key); + } + + /** + * Check the property equals the given value + * + * @param key the property key + * @param value the value to check against + * @return the statement + */ + public static Statement eq(String key, Object value) { + return new SimpleStatement("==", key, value); + } + + /** + * Check the property does not equals the given value + * + * @param key the property key + * @param value the value to check against + * @return the statement + */ + public static Statement neq(String key, Object value) { + return new SimpleStatement("!=", key, value); + } + + /** + * Check the property exceeds the given value + * + * @param key the property key + * @param value the value to check against + * @return the statement + */ + public static Statement gt(String key, Object value) { + return new SimpleStatement(">", key, value); + } + + /** + * Check the property exceeds or equals the given value + * + * @param key the property key + * @param value the value to check against + * @return the statement + */ + public static Statement gte(String key, Object value) { + return new SimpleStatement(">=", key, value); + } + + /** + * Check the property does not exceeds the given value + * + * @param key the property key + * @param value the value to check against + * @return the statement + */ + public static Statement lt(String key, Object value) { + return new SimpleStatement("<", key, value); + } + + /** + * Check the property equals or does not exceeds the given value + * + * @param key the property key + * @param value the value to check against + * @return the statement + */ + public static Statement lte(String key, Object value) { + return new SimpleStatement("<=", key, value); + } + + /** + * Check the property is within the given set + * + * @param key the property key + * @param values the set of values to check against + * @return the statement + */ + public static Statement in(String key, Object... values) { + return new SimpleStatement("in", key, values); + } + + /** + * Check the property is not within the given set + * + * @param key the property key + * @param values the set of values to check against + * @return the statement + */ + public static Statement notIn(String key, Object... values) { + return new SimpleStatement("!in", key, values); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Function.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Function.java index e147b5204f..900fe10476 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Function.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Function.java @@ -19,119 +19,119 @@ import java.util.Map; */ public class Function<T> { - /** - * A stop represents a certain point in the range of this function - * - * @param <I> input - * @param <O> output - */ - public static class Stop<I, O> { - public final I in; - public final O out; - - Stop(I in, O out) { - this.in = in; - this.out = out; - } - - /** - * @return an array representation of the Stop - */ - Object[] toValueObject() { - return new Object[]{in, out}; - } - - @Override - public String toString() { - return String.format("[%s, %s]", in, out); - } - } - - /** - * Zoom functions allow the appearance of a map feature to change with map’s zoom. - * Zoom functions can be used to create the illusion of depth and control data density. - * Each stop is an array with two elements, the first is a zoom and the second is a function output value. - * - * @param stops the stops that define the function - * @param <T> the property type - * @return the {@link Function} - */ - @SafeVarargs - public static <T> Function<T> zoom(@NonNull @Size(min = 1) Stop<Float, T>... stops) { - return new Function<T>(stops); + /** + * A stop represents a certain point in the range of this function + * + * @param <I> input + * @param <O> output + */ + public static class Stop<I, O> { + public final I in; + public final O out; + + Stop(I in, O out) { + this.in = in; + this.out = out; } - /** - * Zoom functions allow the appearance of a map feature to change with map’s zoom. - * Zoom functions can be used to create the illusion of depth and control data density. - * Each stop is an array with two elements, the first is a zoom and the second is a function output value. - * - * @param stops the stops that define the function - * @param base the exponential base of the interpolation curve - Default 1 - * @param <T> the property type - * @return the {@link Function} + * @return an array representation of the Stop */ - @SafeVarargs - public static <T> Function<T> zoom( - @FloatRange(from = 0, to = 1, fromInclusive = false, toInclusive = false) float base, - @NonNull @Size(min = 1) Stop<Float, T>... stops) { - return new Function<T>(stops) - .withBase(base); + Object[] toValueObject() { + return new Object[] {in, out}; } - /** - * Creates a stop to use in a {@link Function} - * - * @param in the input for the stop - * @param output the output for the stop - * @param <T> the output property type - * @return the {@link Stop} - */ - public static <T> Stop<Float, T> stop(float in, Property<T> output) { - return new Stop<>(in, output.value); + @Override + public String toString() { + return String.format("[%s, %s]", in, out); } - - private final Stop<Float, T>[] stops; - private Float base; - - Function(@NonNull @Size(min = 1) Stop<Float, T>[] stops) { - this.stops = stops; + } + + /** + * Zoom functions allow the appearance of a map feature to change with map’s zoom. + * Zoom functions can be used to create the illusion of depth and control data density. + * Each stop is an array with two elements, the first is a zoom and the second is a function output value. + * + * @param stops the stops that define the function + * @param <T> the property type + * @return the {@link Function} + */ + @SafeVarargs + public static <T> Function<T> zoom(@NonNull @Size(min = 1) Stop<Float, T>... stops) { + return new Function<T>(stops); + } + + + /** + * Zoom functions allow the appearance of a map feature to change with map’s zoom. + * Zoom functions can be used to create the illusion of depth and control data density. + * Each stop is an array with two elements, the first is a zoom and the second is a function output value. + * + * @param stops the stops that define the function + * @param base the exponential base of the interpolation curve - Default 1 + * @param <T> the property type + * @return the {@link Function} + */ + @SafeVarargs + public static <T> Function<T> zoom( + @FloatRange(from = 0, to = 1, fromInclusive = false, toInclusive = false) float base, + @NonNull @Size(min = 1) Stop<Float, T>... stops) { + return new Function<T>(stops) + .withBase(base); + } + + /** + * Creates a stop to use in a {@link Function} + * + * @param in the input for the stop + * @param output the output for the stop + * @param <T> the output property type + * @return the {@link Stop} + */ + public static <T> Stop<Float, T> stop(float in, Property<T> output) { + return new Stop<>(in, output.value); + } + + private final Stop<Float, T>[] stops; + private Float base; + + Function(@NonNull @Size(min = 1) Stop<Float, T>[] stops) { + this.stops = stops; + } + + Function<T> withBase(float base) { + this.base = base; + return this; + } + + /** + * @return the base + */ + @Nullable + public Float getBase() { + return base; + } + + /** + * @return the stops in this function + */ + public Stop<Float, T>[] getStops() { + return stops; + } + + Map<String, Object> toValueObject() { + Object[] stopsValue = new Object[stops.length]; + + for (int i = 0; i < stopsValue.length; i++) { + Stop stop = stops[i]; + stopsValue[i] = stop.toValueObject(); } - Function<T> withBase(float base) { - this.base = base; - return this; - } - - /** - * @return the base - */ - @Nullable - public Float getBase() { - return base; - } - - /** - * @return the stops in this function - */ - public Stop<Float, T>[] getStops() { - return stops; - } - - Map<String, Object> toValueObject() { - Object[] stopsValue = new Object[stops.length]; - - for (int i = 0; i < stopsValue.length; i++) { - Stop stop = stops[i]; - stopsValue[i] = stop.toValueObject(); - } - - Map<String, Object> value = new HashMap<>(); - if (base != null) { - value.put("base", base); - } - value.put("stops", stopsValue); - return value; + Map<String, Object> value = new HashMap<>(); + if (base != null) { + value.put("base", base); } + value.put("stops", stopsValue); + return value; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java index 9b39d9726f..2878d76430 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java @@ -7,83 +7,83 @@ import android.support.annotation.NonNull; */ public abstract class Layer { - private long nativePtr; - private boolean invalidated; + private long nativePtr; + private boolean invalidated; - public Layer(long nativePtr) { - this.nativePtr = nativePtr; - } + public Layer(long nativePtr) { + this.nativePtr = nativePtr; + } - public Layer() { - } + public Layer() { + } - public void setProperties(@NonNull Property<?>... properties) { - if (properties.length == 0) { - return; - } - - for (Property<?> property : properties) { - Object converted = convertValue(property.value); - if (property instanceof PaintProperty) { - nativeSetPaintProperty(property.name, converted); - } else { - nativeSetLayoutProperty(property.name, converted); - } - } + public void setProperties(@NonNull Property<?>... properties) { + if (properties.length == 0) { + return; } - public String getId() { - return nativeGetId(); + for (Property<?> property : properties) { + Object converted = convertValue(property.value); + if (property instanceof PaintProperty) { + nativeSetPaintProperty(property.name, converted); + } else { + nativeSetLayoutProperty(property.name, converted); + } } + } - public PropertyValue<String> getVisibility() { - return new PropertyValue<>(nativeGetVisibility()); - } + public String getId() { + return nativeGetId(); + } - public float getMinZoom() { - return nativeGetMinZoom(); - } + public PropertyValue<String> getVisibility() { + return new PropertyValue<>(nativeGetVisibility()); + } - public float getMaxZoom() { - return nativeGetMaxZoom(); - } + public float getMinZoom() { + return nativeGetMinZoom(); + } - public void setMinZoom(float zoom) { - nativeSetMinZoom(zoom); - } + public float getMaxZoom() { + return nativeGetMaxZoom(); + } - public void setMaxZoom(float zoom) { - nativeSetMaxZoom(zoom); - } + public void setMinZoom(float zoom) { + nativeSetMinZoom(zoom); + } - @Override - protected native void finalize() throws Throwable; + public void setMaxZoom(float zoom) { + nativeSetMaxZoom(zoom); + } - protected native String nativeGetId(); + @Override + protected native void finalize() throws Throwable; - protected native Object nativeGetVisibility(); + protected native String nativeGetId(); - protected native void nativeSetLayoutProperty(String name, Object value); + protected native Object nativeGetVisibility(); - protected native void nativeSetPaintProperty(String name, Object value); + protected native void nativeSetLayoutProperty(String name, Object value); - protected native void nativeSetFilter(Object[] filter); + protected native void nativeSetPaintProperty(String name, Object value); - protected native void nativeSetSourceLayer(String sourceLayer); + protected native void nativeSetFilter(Object[] filter); - protected native float nativeGetMinZoom(); + protected native void nativeSetSourceLayer(String sourceLayer); - protected native float nativeGetMaxZoom(); + protected native float nativeGetMinZoom(); - protected native void nativeSetMinZoom(float zoom); + protected native float nativeGetMaxZoom(); - protected native void nativeSetMaxZoom(float zoom); + protected native void nativeSetMinZoom(float zoom); - public long getNativePtr() { - return nativePtr; - } + protected native void nativeSetMaxZoom(float zoom); - private Object convertValue(Object value) { - return value != null && value instanceof Function ? ((Function) value).toValueObject() : value; - } + public long getNativePtr() { + return nativePtr; + } + + private Object convertValue(Object value) { + return value != null && value instanceof Function ? ((Function) value).toValueObject() : value; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LayoutProperty.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LayoutProperty.java index 553554270e..4c0b52be55 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LayoutProperty.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LayoutProperty.java @@ -2,8 +2,8 @@ package com.mapbox.mapboxsdk.style.layers; class LayoutProperty<T> extends Property<T> { - LayoutProperty(String name, T value) { - super(name, value); - } + LayoutProperty(String name, T value) { + super(name, value); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LineLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LineLayer.java index fb647870f1..4c52a40b05 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LineLayer.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LineLayer.java @@ -1,12 +1,11 @@ -// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. package com.mapbox.mapboxsdk.style.layers; - -import android.support.annotation.UiThread; +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. import android.support.annotation.ColorInt; import android.support.annotation.NonNull; +import android.support.annotation.UiThread; -import static com.mapbox.mapboxsdk.utils.ColorUtils.*; +import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor; /** * A stroked line. @@ -16,286 +15,288 @@ import static com.mapbox.mapboxsdk.utils.ColorUtils.*; @UiThread public class LineLayer extends Layer { - /** - * Creates a LineLayer. - * - * @param nativePtr pointer used by core - */ - public LineLayer(long nativePtr) { - super(nativePtr); - } - - /** - * Creates a LineLayer. - * - * @param layerId the id of the layer - * @param sourceId the id of the source - */ - public LineLayer(String layerId, String sourceId) { - initialize(layerId, sourceId); - } - - protected native void initialize(String layerId, String sourceId); - - /** - * Set the source layer. - * - * @param sourceLayer the source layer to set - */ - public void setSourceLayer(String sourceLayer) { - nativeSetSourceLayer(sourceLayer); - } - - /** - * Set the source Layer. - * - * @param sourceLayer the source layer to set - * @return This - */ - public LineLayer withSourceLayer(String sourceLayer) { - setSourceLayer(sourceLayer); - return this; - } - /** - * Set a single filter. - * - * @param filter the filter to set - */ - public void setFilter(Filter.Statement filter) { - this.setFilter(filter.toArray()); - } - - /** - * Set an array of filters. - * - * @param filter the filter array to set - */ - public void setFilter(Object[] filter) { - nativeSetFilter(filter); - } - - /** - * Set an array of filters. - * - * @param filter tthe filter array to set - * @return This - */ - public LineLayer withFilter(Object[] filter) { - setFilter(filter); - return this; - } - - /** - * Set a single filter. - * - * @param filter the filter to set - * @return This - */ - public LineLayer withFilter(Filter.Statement filter) { - setFilter(filter); - return this; - } - - - /** - * Set a property or properties. - * - * @param properties the var-args properties - * @return This - */ - public LineLayer withProperties(@NonNull Property<?>... properties) { - setProperties(properties); - return this; - } - - // Property getters - - /** - * Get the LineCap property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getLineCap() { - return (PropertyValue<String>) new PropertyValue(nativeGetLineCap()); - } - - /** - * Get the LineJoin property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getLineJoin() { - return (PropertyValue<String>) new PropertyValue(nativeGetLineJoin()); - } - - /** - * Get the LineMiterLimit property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getLineMiterLimit() { - return (PropertyValue<Float>) new PropertyValue(nativeGetLineMiterLimit()); - } - - /** - * Get the LineRoundLimit property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getLineRoundLimit() { - return (PropertyValue<Float>) new PropertyValue(nativeGetLineRoundLimit()); + /** + * Creates a LineLayer. + * + * @param nativePtr pointer used by core + */ + public LineLayer(long nativePtr) { + super(nativePtr); + } + + /** + * Creates a LineLayer. + * + * @param layerId the id of the layer + * @param sourceId the id of the source + */ + public LineLayer(String layerId, String sourceId) { + initialize(layerId, sourceId); + } + + protected native void initialize(String layerId, String sourceId); + + /** + * Set the source layer. + * + * @param sourceLayer the source layer to set + */ + public void setSourceLayer(String sourceLayer) { + nativeSetSourceLayer(sourceLayer); + } + + /** + * Set the source Layer. + * + * @param sourceLayer the source layer to set + * @return This + */ + public LineLayer withSourceLayer(String sourceLayer) { + setSourceLayer(sourceLayer); + return this; + } + + /** + * Set a single filter. + * + * @param filter the filter to set + */ + public void setFilter(Filter.Statement filter) { + this.setFilter(filter.toArray()); + } + + /** + * Set an array of filters. + * + * @param filter the filter array to set + */ + public void setFilter(Object[] filter) { + nativeSetFilter(filter); + } + + /** + * Set an array of filters. + * + * @param filter tthe filter array to set + * @return This + */ + public LineLayer withFilter(Object[] filter) { + setFilter(filter); + return this; + } + + /** + * Set a single filter. + * + * @param filter the filter to set + * @return This + */ + public LineLayer withFilter(Filter.Statement filter) { + setFilter(filter); + return this; + } + + + /** + * Set a property or properties. + * + * @param properties the var-args properties + * @return This + */ + public LineLayer withProperties(@NonNull Property<?>... properties) { + setProperties(properties); + return this; + } + + // Property getters + + /** + * Get the LineCap property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getLineCap() { + return (PropertyValue<String>) new PropertyValue(nativeGetLineCap()); + } + + /** + * Get the LineJoin property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getLineJoin() { + return (PropertyValue<String>) new PropertyValue(nativeGetLineJoin()); + } + + /** + * Get the LineMiterLimit property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getLineMiterLimit() { + return (PropertyValue<Float>) new PropertyValue(nativeGetLineMiterLimit()); + } + + /** + * Get the LineRoundLimit property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getLineRoundLimit() { + return (PropertyValue<Float>) new PropertyValue(nativeGetLineRoundLimit()); + } + + /** + * Get the LineOpacity property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getLineOpacity() { + return (PropertyValue<Float>) new PropertyValue(nativeGetLineOpacity()); + } + + /** + * Get the LineColor property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getLineColor() { + return (PropertyValue<String>) new PropertyValue(nativeGetLineColor()); + } + + /** + * The color with which the line will be drawn. + * + * @return int representation of a rgba string color + * @throws RuntimeException thrown if property isn't a value + */ + @ColorInt + public int getLineColorAsInt() { + PropertyValue<String> value = getLineColor(); + if (value.isValue()) { + return rgbaToColor(value.getValue()); + } else { + throw new RuntimeException("line-color was set as a Function"); } - - /** - * Get the LineOpacity property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getLineOpacity() { - return (PropertyValue<Float>) new PropertyValue(nativeGetLineOpacity()); - } - - /** - * Get the LineColor property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getLineColor() { - return (PropertyValue<String>) new PropertyValue(nativeGetLineColor()); - } - /** - * The color with which the line will be drawn. - * - * @return int representation of a rgba string color - * @throws RuntimeException thrown if property isn't a value - */ - @ColorInt - public int getLineColorAsInt() { - PropertyValue<String> value = getLineColor(); - if (value.isValue()) { - return rgbaToColor(value.getValue()); - } else { - throw new RuntimeException("line-color was set as a Function"); - } - } - - - /** - * Get the LineTranslate property - * - * @return property wrapper value around Float[] - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float[]> getLineTranslate() { - return (PropertyValue<Float[]>) new PropertyValue(nativeGetLineTranslate()); - } - - /** - * Get the LineTranslateAnchor property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getLineTranslateAnchor() { - return (PropertyValue<String>) new PropertyValue(nativeGetLineTranslateAnchor()); - } - - /** - * Get the LineWidth property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getLineWidth() { - return (PropertyValue<Float>) new PropertyValue(nativeGetLineWidth()); - } - - /** - * Get the LineGapWidth property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getLineGapWidth() { - return (PropertyValue<Float>) new PropertyValue(nativeGetLineGapWidth()); - } - - /** - * Get the LineOffset property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getLineOffset() { - return (PropertyValue<Float>) new PropertyValue(nativeGetLineOffset()); - } - - /** - * Get the LineBlur property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getLineBlur() { - return (PropertyValue<Float>) new PropertyValue(nativeGetLineBlur()); - } - - /** - * Get the LineDasharray property - * - * @return property wrapper value around Float[] - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float[]> getLineDasharray() { - return (PropertyValue<Float[]>) new PropertyValue(nativeGetLineDasharray()); - } - - /** - * Get the LinePattern property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getLinePattern() { - return (PropertyValue<String>) new PropertyValue(nativeGetLinePattern()); - } - - private native Object nativeGetLineCap(); - - private native Object nativeGetLineJoin(); - - private native Object nativeGetLineMiterLimit(); - - private native Object nativeGetLineRoundLimit(); - - private native Object nativeGetLineOpacity(); - - private native Object nativeGetLineColor(); - - private native Object nativeGetLineTranslate(); - - private native Object nativeGetLineTranslateAnchor(); - - private native Object nativeGetLineWidth(); - - private native Object nativeGetLineGapWidth(); - - private native Object nativeGetLineOffset(); - - private native Object nativeGetLineBlur(); - - private native Object nativeGetLineDasharray(); - - private native Object nativeGetLinePattern(); - - - @Override - protected native void finalize() throws Throwable; + } + + + /** + * Get the LineTranslate property + * + * @return property wrapper value around Float[] + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float[]> getLineTranslate() { + return (PropertyValue<Float[]>) new PropertyValue(nativeGetLineTranslate()); + } + + /** + * Get the LineTranslateAnchor property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getLineTranslateAnchor() { + return (PropertyValue<String>) new PropertyValue(nativeGetLineTranslateAnchor()); + } + + /** + * Get the LineWidth property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getLineWidth() { + return (PropertyValue<Float>) new PropertyValue(nativeGetLineWidth()); + } + + /** + * Get the LineGapWidth property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getLineGapWidth() { + return (PropertyValue<Float>) new PropertyValue(nativeGetLineGapWidth()); + } + + /** + * Get the LineOffset property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getLineOffset() { + return (PropertyValue<Float>) new PropertyValue(nativeGetLineOffset()); + } + + /** + * Get the LineBlur property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getLineBlur() { + return (PropertyValue<Float>) new PropertyValue(nativeGetLineBlur()); + } + + /** + * Get the LineDasharray property + * + * @return property wrapper value around Float[] + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float[]> getLineDasharray() { + return (PropertyValue<Float[]>) new PropertyValue(nativeGetLineDasharray()); + } + + /** + * Get the LinePattern property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getLinePattern() { + return (PropertyValue<String>) new PropertyValue(nativeGetLinePattern()); + } + + private native Object nativeGetLineCap(); + + private native Object nativeGetLineJoin(); + + private native Object nativeGetLineMiterLimit(); + + private native Object nativeGetLineRoundLimit(); + + private native Object nativeGetLineOpacity(); + + private native Object nativeGetLineColor(); + + private native Object nativeGetLineTranslate(); + + private native Object nativeGetLineTranslateAnchor(); + + private native Object nativeGetLineWidth(); + + private native Object nativeGetLineGapWidth(); + + private native Object nativeGetLineOffset(); + + private native Object nativeGetLineBlur(); + + private native Object nativeGetLineDasharray(); + + private native Object nativeGetLinePattern(); + + + @Override + protected native void finalize() throws Throwable; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/NoSuchLayerException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/NoSuchLayerException.java index d6ef4f8824..3b8777080d 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/NoSuchLayerException.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/NoSuchLayerException.java @@ -5,7 +5,7 @@ package com.mapbox.mapboxsdk.style.layers; */ public class NoSuchLayerException extends Exception { - public NoSuchLayerException(String message) { - super(message); - } + public NoSuchLayerException(String message) { + super(message); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PaintProperty.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PaintProperty.java index 6f1a9a0a16..69405177d9 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PaintProperty.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PaintProperty.java @@ -2,8 +2,8 @@ package com.mapbox.mapboxsdk.style.layers; class PaintProperty<T> extends Property<T> { - PaintProperty(String name, T value) { - super(name, value); - } + PaintProperty(String name, T value) { + super(name, value); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java index c19ded4d8e..bb060ddf15 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java @@ -1,5 +1,5 @@ -// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. package com.mapbox.mapboxsdk.style.layers; +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. import android.support.annotation.StringDef; @@ -11,448 +11,477 @@ import java.lang.annotation.RetentionPolicy; */ public abstract class Property<T> { - //VISIBILITY: Whether this layer is displayed. - - /** - * The layer is shown. - */ - public static final String VISIBLE = "visible"; - /** - * The layer is hidden. - */ - public static final String NONE = "none"; - - @StringDef({ - VISIBLE, - NONE - }) - @Retention(RetentionPolicy.SOURCE) - public @interface VISIBILITY {} - - //LINE_CAP: The display of line endings. - - /** - * A cap with a squared-off end which is drawn to the exact endpoint of the line. - */ - public static final String LINE_CAP_BUTT = "butt"; - /** - * A cap with a rounded end which is drawn beyond the endpoint of the line at a radius of one-half of the line's width and centered on the endpoint of the line. - */ - public static final String LINE_CAP_ROUND = "round"; - /** - * A cap with a squared-off end which is drawn beyond the endpoint of the line at a distance of one-half of the line's width. - */ - public static final String LINE_CAP_SQUARE = "square"; - - /** - * The display of line endings. - */ - @StringDef({ - LINE_CAP_BUTT, - LINE_CAP_ROUND, - LINE_CAP_SQUARE, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface LINE_CAP {} - - //LINE_JOIN: The display of lines when joining. - - /** - * A join with a squared-off end which is drawn beyond the endpoint of the line at a distance of one-half of the line's width. - */ - public static final String LINE_JOIN_BEVEL = "bevel"; - /** - * A join with a rounded end which is drawn beyond the endpoint of the line at a radius of one-half of the line's width and centered on the endpoint of the line. - */ - public static final String LINE_JOIN_ROUND = "round"; - /** - * A join with a sharp, angled corner which is drawn with the outer sides beyond the endpoint of the path until they meet. - */ - public static final String LINE_JOIN_MITER = "miter"; - - /** - * The display of lines when joining. - */ - @StringDef({ - LINE_JOIN_BEVEL, - LINE_JOIN_ROUND, - LINE_JOIN_MITER, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface LINE_JOIN {} - - //SYMBOL_PLACEMENT: Label placement relative to its geometry. - - /** - * The label is placed at the point where the geometry is located. - */ - public static final String SYMBOL_PLACEMENT_POINT = "point"; - /** - * The label is placed along the line of the geometry. Can only be used on LineString and Polygon geometries. - */ - public static final String SYMBOL_PLACEMENT_LINE = "line"; - - /** - * Label placement relative to its geometry. - */ - @StringDef({ - SYMBOL_PLACEMENT_POINT, - SYMBOL_PLACEMENT_LINE, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface SYMBOL_PLACEMENT {} - - //ICON_ROTATION_ALIGNMENT: In combination with `symbol-placement`, determines the rotation behavior of icons. - - /** - * When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_POINT}, aligns icons east-west. When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_LINE}, aligns icon x-axes with the line. - */ - public static final String ICON_ROTATION_ALIGNMENT_MAP = "map"; - /** - * Produces icons whose x-axes are aligned with the x-axis of the viewport, regardless of the value of {@link SYMBOL_PLACEMENT}. - */ - public static final String ICON_ROTATION_ALIGNMENT_VIEWPORT = "viewport"; - /** - * When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_POINT}, this is equivalent to {@link Property#ICON_ROTATION_ALIGNMENT_VIEWPORT}. When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_LINE}, this is equivalent to {@link Property#ICON_ROTATION_ALIGNMENT_MAP}. - */ - public static final String ICON_ROTATION_ALIGNMENT_AUTO = "auto"; - - /** - * In combination with `symbol-placement`, determines the rotation behavior of icons. - */ - @StringDef({ - ICON_ROTATION_ALIGNMENT_MAP, - ICON_ROTATION_ALIGNMENT_VIEWPORT, - ICON_ROTATION_ALIGNMENT_AUTO, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface ICON_ROTATION_ALIGNMENT {} - - //ICON_TEXT_FIT: Scales the icon to fit around the associated text. - - /** - * The icon is displayed at its intrinsic aspect ratio. - */ - public static final String ICON_TEXT_FIT_NONE = "none"; - /** - * The icon is scaled in the x-dimension to fit the width of the text. - */ - public static final String ICON_TEXT_FIT_WIDTH = "width"; - /** - * The icon is scaled in the y-dimension to fit the height of the text. - */ - public static final String ICON_TEXT_FIT_HEIGHT = "height"; - /** - * The icon is scaled in both x- and y-dimensions. - */ - public static final String ICON_TEXT_FIT_BOTH = "both"; - - /** - * Scales the icon to fit around the associated text. - */ - @StringDef({ - ICON_TEXT_FIT_NONE, - ICON_TEXT_FIT_WIDTH, - ICON_TEXT_FIT_HEIGHT, - ICON_TEXT_FIT_BOTH, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface ICON_TEXT_FIT {} - - //TEXT_PITCH_ALIGNMENT: Orientation of text when map is pitched. - - /** - * The text is aligned to the plane of the map. - */ - public static final String TEXT_PITCH_ALIGNMENT_MAP = "map"; - /** - * The text is aligned to the plane of the viewport. - */ - public static final String TEXT_PITCH_ALIGNMENT_VIEWPORT = "viewport"; - /** - * Automatically matches the value of {@link TEXT_ROTATION_ALIGNMENT}. - */ - public static final String TEXT_PITCH_ALIGNMENT_AUTO = "auto"; - - /** - * Orientation of text when map is pitched. - */ - @StringDef({ - TEXT_PITCH_ALIGNMENT_MAP, - TEXT_PITCH_ALIGNMENT_VIEWPORT, - TEXT_PITCH_ALIGNMENT_AUTO, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface TEXT_PITCH_ALIGNMENT {} - - //TEXT_ROTATION_ALIGNMENT: In combination with `symbol-placement`, determines the rotation behavior of the individual glyphs forming the text. - - /** - * When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_POINT}, aligns text east-west. When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_LINE}, aligns text x-axes with the line. - */ - public static final String TEXT_ROTATION_ALIGNMENT_MAP = "map"; - /** - * Produces glyphs whose x-axes are aligned with the x-axis of the viewport, regardless of the value of {@link SYMBOL_PLACEMENT}. - */ - public static final String TEXT_ROTATION_ALIGNMENT_VIEWPORT = "viewport"; - /** - * When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_POINT}, this is equivalent to {@link Property#TEXT_ROTATION_ALIGNMENT_VIEWPORT}. When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_LINE}, this is equivalent to {@link Property#TEXT_ROTATION_ALIGNMENT_MAP}. - */ - public static final String TEXT_ROTATION_ALIGNMENT_AUTO = "auto"; - - /** - * In combination with `symbol-placement`, determines the rotation behavior of the individual glyphs forming the text. - */ - @StringDef({ - TEXT_ROTATION_ALIGNMENT_MAP, - TEXT_ROTATION_ALIGNMENT_VIEWPORT, - TEXT_ROTATION_ALIGNMENT_AUTO, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface TEXT_ROTATION_ALIGNMENT {} - - //TEXT_JUSTIFY: Text justification options. - - /** - * The text is aligned to the left. - */ - public static final String TEXT_JUSTIFY_LEFT = "left"; - /** - * The text is centered. - */ - public static final String TEXT_JUSTIFY_CENTER = "center"; - /** - * The text is aligned to the right. - */ - public static final String TEXT_JUSTIFY_RIGHT = "right"; - - /** - * Text justification options. - */ - @StringDef({ - TEXT_JUSTIFY_LEFT, - TEXT_JUSTIFY_CENTER, - TEXT_JUSTIFY_RIGHT, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface TEXT_JUSTIFY {} - - //TEXT_ANCHOR: Part of the text placed closest to the anchor. - - /** - * The center of the text is placed closest to the anchor. - */ - public static final String TEXT_ANCHOR_CENTER = "center"; - /** - * The left side of the text is placed closest to the anchor. - */ - public static final String TEXT_ANCHOR_LEFT = "left"; - /** - * The right side of the text is placed closest to the anchor. - */ - public static final String TEXT_ANCHOR_RIGHT = "right"; - /** - * The top of the text is placed closest to the anchor. - */ - public static final String TEXT_ANCHOR_TOP = "top"; - /** - * The bottom of the text is placed closest to the anchor. - */ - public static final String TEXT_ANCHOR_BOTTOM = "bottom"; - /** - * The top left corner of the text is placed closest to the anchor. - */ - public static final String TEXT_ANCHOR_TOP_LEFT = "top-left"; - /** - * The top right corner of the text is placed closest to the anchor. - */ - public static final String TEXT_ANCHOR_TOP_RIGHT = "top-right"; - /** - * The bottom left corner of the text is placed closest to the anchor. - */ - public static final String TEXT_ANCHOR_BOTTOM_LEFT = "bottom-left"; - /** - * The bottom right corner of the text is placed closest to the anchor. - */ - public static final String TEXT_ANCHOR_BOTTOM_RIGHT = "bottom-right"; - - /** - * Part of the text placed closest to the anchor. - */ - @StringDef({ - TEXT_ANCHOR_CENTER, - TEXT_ANCHOR_LEFT, - TEXT_ANCHOR_RIGHT, - TEXT_ANCHOR_TOP, - TEXT_ANCHOR_BOTTOM, - TEXT_ANCHOR_TOP_LEFT, - TEXT_ANCHOR_TOP_RIGHT, - TEXT_ANCHOR_BOTTOM_LEFT, - TEXT_ANCHOR_BOTTOM_RIGHT, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface TEXT_ANCHOR {} - - //TEXT_TRANSFORM: Specifies how to capitalize text, similar to the CSS `text-transform` property. - - /** - * The text is not altered. - */ - public static final String TEXT_TRANSFORM_NONE = "none"; - /** - * Forces all letters to be displayed in uppercase. - */ - public static final String TEXT_TRANSFORM_UPPERCASE = "uppercase"; - /** - * Forces all letters to be displayed in lowercase. - */ - public static final String TEXT_TRANSFORM_LOWERCASE = "lowercase"; - - /** - * Specifies how to capitalize text, similar to the CSS `text-transform` property. - */ - @StringDef({ - TEXT_TRANSFORM_NONE, - TEXT_TRANSFORM_UPPERCASE, - TEXT_TRANSFORM_LOWERCASE, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface TEXT_TRANSFORM {} - - //FILL_TRANSLATE_ANCHOR: Controls the translation reference point. - - /** - * The fill is translated relative to the map. - */ - public static final String FILL_TRANSLATE_ANCHOR_MAP = "map"; - /** - * The fill is translated relative to the viewport. - */ - public static final String FILL_TRANSLATE_ANCHOR_VIEWPORT = "viewport"; - - /** - * Controls the translation reference point. - */ - @StringDef({ - FILL_TRANSLATE_ANCHOR_MAP, - FILL_TRANSLATE_ANCHOR_VIEWPORT, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface FILL_TRANSLATE_ANCHOR {} - - //LINE_TRANSLATE_ANCHOR: Controls the translation reference point. - - /** - * The line is translated relative to the map. - */ - public static final String LINE_TRANSLATE_ANCHOR_MAP = "map"; - /** - * The line is translated relative to the viewport. - */ - public static final String LINE_TRANSLATE_ANCHOR_VIEWPORT = "viewport"; - - /** - * Controls the translation reference point. - */ - @StringDef({ - LINE_TRANSLATE_ANCHOR_MAP, - LINE_TRANSLATE_ANCHOR_VIEWPORT, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface LINE_TRANSLATE_ANCHOR {} - - //ICON_TRANSLATE_ANCHOR: Controls the translation reference point. - - /** - * Icons are translated relative to the map. - */ - public static final String ICON_TRANSLATE_ANCHOR_MAP = "map"; - /** - * Icons are translated relative to the viewport. - */ - public static final String ICON_TRANSLATE_ANCHOR_VIEWPORT = "viewport"; - - /** - * Controls the translation reference point. - */ - @StringDef({ - ICON_TRANSLATE_ANCHOR_MAP, - ICON_TRANSLATE_ANCHOR_VIEWPORT, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface ICON_TRANSLATE_ANCHOR {} - - //TEXT_TRANSLATE_ANCHOR: Controls the translation reference point. - - /** - * The text is translated relative to the map. - */ - public static final String TEXT_TRANSLATE_ANCHOR_MAP = "map"; - /** - * The text is translated relative to the viewport. - */ - public static final String TEXT_TRANSLATE_ANCHOR_VIEWPORT = "viewport"; - - /** - * Controls the translation reference point. - */ - @StringDef({ - TEXT_TRANSLATE_ANCHOR_MAP, - TEXT_TRANSLATE_ANCHOR_VIEWPORT, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface TEXT_TRANSLATE_ANCHOR {} - - //CIRCLE_TRANSLATE_ANCHOR: Controls the translation reference point. - - /** - * The circle is translated relative to the map. - */ - public static final String CIRCLE_TRANSLATE_ANCHOR_MAP = "map"; - /** - * The circle is translated relative to the viewport. - */ - public static final String CIRCLE_TRANSLATE_ANCHOR_VIEWPORT = "viewport"; - - /** - * Controls the translation reference point. - */ - @StringDef({ - CIRCLE_TRANSLATE_ANCHOR_MAP, - CIRCLE_TRANSLATE_ANCHOR_VIEWPORT, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface CIRCLE_TRANSLATE_ANCHOR {} - - //CIRCLE_PITCH_SCALE: Controls the scaling behavior of the circle when the map is pitched. - - /** - * Circles are scaled according to their apparent distance to the camera. - */ - public static final String CIRCLE_PITCH_SCALE_MAP = "map"; - /** - * Circles are not scaled. - */ - public static final String CIRCLE_PITCH_SCALE_VIEWPORT = "viewport"; - - /** - * Controls the scaling behavior of the circle when the map is pitched. - */ - @StringDef({ - CIRCLE_PITCH_SCALE_MAP, - CIRCLE_PITCH_SCALE_VIEWPORT, - }) - @Retention(RetentionPolicy.SOURCE) - public @interface CIRCLE_PITCH_SCALE {} - - - //Class definition - public final String name; - public final T value; - - /* package */ Property(String name, T value) { - this.name = name; - this.value = value; - } - + //VISIBILITY: Whether this layer is displayed. + + /** + * The layer is shown. + */ + public static final String VISIBLE = "visible"; + /** + * The layer is hidden. + */ + public static final String NONE = "none"; + + @StringDef( { + VISIBLE, + NONE + }) + @Retention(RetentionPolicy.SOURCE) + public @interface VISIBILITY { + } + + //LINE_CAP: The display of line endings. + + /** + * A cap with a squared-off end which is drawn to the exact endpoint of the line. + */ + public static final String LINE_CAP_BUTT = "butt"; + /** + * A cap with a rounded end which is drawn beyond the endpoint of the line at a radius of one-half of the line's + * width and centered on the endpoint of the line. + */ + public static final String LINE_CAP_ROUND = "round"; + /** + * A cap with a squared-off end which is drawn beyond the endpoint of the line at a distance of one-half of the + * line's width. + */ + public static final String LINE_CAP_SQUARE = "square"; + + /** + * The display of line endings. + */ + @StringDef( { + LINE_CAP_BUTT, + LINE_CAP_ROUND, + LINE_CAP_SQUARE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface LINE_CAP { + } + + //LINE_JOIN: The display of lines when joining. + + /** + * A join with a squared-off end which is drawn beyond the endpoint of the line at a distance of one-half of the + * line's width. + */ + public static final String LINE_JOIN_BEVEL = "bevel"; + /** + * A join with a rounded end which is drawn beyond the endpoint of the line at a radius of one-half of the line's + * width and centered on the endpoint of the line. + */ + public static final String LINE_JOIN_ROUND = "round"; + /** + * A join with a sharp, angled corner which is drawn with the outer sides beyond the endpoint of the path until + * they meet. + */ + public static final String LINE_JOIN_MITER = "miter"; + + /** + * The display of lines when joining. + */ + @StringDef( { + LINE_JOIN_BEVEL, + LINE_JOIN_ROUND, + LINE_JOIN_MITER, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface LINE_JOIN { + } + + //SYMBOL_PLACEMENT: Label placement relative to its geometry. + + /** + * The label is placed at the point where the geometry is located. + */ + public static final String SYMBOL_PLACEMENT_POINT = "point"; + /** + * The label is placed along the line of the geometry. Can only be used on LineString and Polygon geometries. + */ + public static final String SYMBOL_PLACEMENT_LINE = "line"; + + /** + * Label placement relative to its geometry. + */ + @StringDef( { + SYMBOL_PLACEMENT_POINT, + SYMBOL_PLACEMENT_LINE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SYMBOL_PLACEMENT { + } + + //ICON_ROTATION_ALIGNMENT: In combination with `symbol-placement`, determines the rotation behavior of icons. + + /** + * When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_POINT}, aligns icons east-west. When + * {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_LINE}, aligns icon x-axes with the line. + */ + public static final String ICON_ROTATION_ALIGNMENT_MAP = "map"; + /** + * Produces icons whose x-axes are aligned with the x-axis of the viewport, regardless of the value of + * {@link SYMBOL_PLACEMENT}. + */ + public static final String ICON_ROTATION_ALIGNMENT_VIEWPORT = "viewport"; + /** + * When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_POINT}, this is equivalent to + * {@link Property#ICON_ROTATION_ALIGNMENT_VIEWPORT}. When {@link SYMBOL_PLACEMENT} is set to + * {@link Property#SYMBOL_PLACEMENT_LINE}, this is equivalent to {@link Property#ICON_ROTATION_ALIGNMENT_MAP}. + */ + public static final String ICON_ROTATION_ALIGNMENT_AUTO = "auto"; + + /** + * In combination with `symbol-placement`, determines the rotation behavior of icons. + */ + @StringDef( { + ICON_ROTATION_ALIGNMENT_MAP, + ICON_ROTATION_ALIGNMENT_VIEWPORT, + ICON_ROTATION_ALIGNMENT_AUTO, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ICON_ROTATION_ALIGNMENT { + } + + //ICON_TEXT_FIT: Scales the icon to fit around the associated text. + + /** + * The icon is displayed at its intrinsic aspect ratio. + */ + public static final String ICON_TEXT_FIT_NONE = "none"; + /** + * The icon is scaled in the x-dimension to fit the width of the text. + */ + public static final String ICON_TEXT_FIT_WIDTH = "width"; + /** + * The icon is scaled in the y-dimension to fit the height of the text. + */ + public static final String ICON_TEXT_FIT_HEIGHT = "height"; + /** + * The icon is scaled in both x- and y-dimensions. + */ + public static final String ICON_TEXT_FIT_BOTH = "both"; + + /** + * Scales the icon to fit around the associated text. + */ + @StringDef( { + ICON_TEXT_FIT_NONE, + ICON_TEXT_FIT_WIDTH, + ICON_TEXT_FIT_HEIGHT, + ICON_TEXT_FIT_BOTH, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ICON_TEXT_FIT { + } + + //TEXT_PITCH_ALIGNMENT: Orientation of text when map is pitched. + + /** + * The text is aligned to the plane of the map. + */ + public static final String TEXT_PITCH_ALIGNMENT_MAP = "map"; + /** + * The text is aligned to the plane of the viewport. + */ + public static final String TEXT_PITCH_ALIGNMENT_VIEWPORT = "viewport"; + /** + * Automatically matches the value of {@link TEXT_ROTATION_ALIGNMENT}. + */ + public static final String TEXT_PITCH_ALIGNMENT_AUTO = "auto"; + + /** + * Orientation of text when map is pitched. + */ + @StringDef( { + TEXT_PITCH_ALIGNMENT_MAP, + TEXT_PITCH_ALIGNMENT_VIEWPORT, + TEXT_PITCH_ALIGNMENT_AUTO, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface TEXT_PITCH_ALIGNMENT { + } + + //TEXT_ROTATION_ALIGNMENT: In combination with `symbol-placement`, determines the rotation behavior of the individual + // glyphs forming the text. + + /** + * When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_POINT}, aligns text east-west. When + * {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_LINE}, aligns text x-axes with the line. + */ + public static final String TEXT_ROTATION_ALIGNMENT_MAP = "map"; + /** + * Produces glyphs whose x-axes are aligned with the x-axis of the viewport, regardless of the value of + * {@link SYMBOL_PLACEMENT}. + */ + public static final String TEXT_ROTATION_ALIGNMENT_VIEWPORT = "viewport"; + /** + * When {@link SYMBOL_PLACEMENT} is set to {@link Property#SYMBOL_PLACEMENT_POINT}, this is equivalent to + * {@link Property#TEXT_ROTATION_ALIGNMENT_VIEWPORT}. When {@link SYMBOL_PLACEMENT} is set to + * {@link Property#SYMBOL_PLACEMENT_LINE}, this is equivalent to {@link Property#TEXT_ROTATION_ALIGNMENT_MAP}. + */ + public static final String TEXT_ROTATION_ALIGNMENT_AUTO = "auto"; + + /** + * In combination with `symbol-placement`, determines the rotation behavior of the individual glyphs forming the text. + */ + @StringDef( { + TEXT_ROTATION_ALIGNMENT_MAP, + TEXT_ROTATION_ALIGNMENT_VIEWPORT, + TEXT_ROTATION_ALIGNMENT_AUTO, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface TEXT_ROTATION_ALIGNMENT { + } + + //TEXT_JUSTIFY: Text justification options. + + /** + * The text is aligned to the left. + */ + public static final String TEXT_JUSTIFY_LEFT = "left"; + /** + * The text is centered. + */ + public static final String TEXT_JUSTIFY_CENTER = "center"; + /** + * The text is aligned to the right. + */ + public static final String TEXT_JUSTIFY_RIGHT = "right"; + + /** + * Text justification options. + */ + @StringDef( { + TEXT_JUSTIFY_LEFT, + TEXT_JUSTIFY_CENTER, + TEXT_JUSTIFY_RIGHT, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface TEXT_JUSTIFY { + } + + //TEXT_ANCHOR: Part of the text placed closest to the anchor. + + /** + * The center of the text is placed closest to the anchor. + */ + public static final String TEXT_ANCHOR_CENTER = "center"; + /** + * The left side of the text is placed closest to the anchor. + */ + public static final String TEXT_ANCHOR_LEFT = "left"; + /** + * The right side of the text is placed closest to the anchor. + */ + public static final String TEXT_ANCHOR_RIGHT = "right"; + /** + * The top of the text is placed closest to the anchor. + */ + public static final String TEXT_ANCHOR_TOP = "top"; + /** + * The bottom of the text is placed closest to the anchor. + */ + public static final String TEXT_ANCHOR_BOTTOM = "bottom"; + /** + * The top left corner of the text is placed closest to the anchor. + */ + public static final String TEXT_ANCHOR_TOP_LEFT = "top-left"; + /** + * The top right corner of the text is placed closest to the anchor. + */ + public static final String TEXT_ANCHOR_TOP_RIGHT = "top-right"; + /** + * The bottom left corner of the text is placed closest to the anchor. + */ + public static final String TEXT_ANCHOR_BOTTOM_LEFT = "bottom-left"; + /** + * The bottom right corner of the text is placed closest to the anchor. + */ + public static final String TEXT_ANCHOR_BOTTOM_RIGHT = "bottom-right"; + + /** + * Part of the text placed closest to the anchor. + */ + @StringDef( { + TEXT_ANCHOR_CENTER, + TEXT_ANCHOR_LEFT, + TEXT_ANCHOR_RIGHT, + TEXT_ANCHOR_TOP, + TEXT_ANCHOR_BOTTOM, + TEXT_ANCHOR_TOP_LEFT, + TEXT_ANCHOR_TOP_RIGHT, + TEXT_ANCHOR_BOTTOM_LEFT, + TEXT_ANCHOR_BOTTOM_RIGHT, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface TEXT_ANCHOR { + } + + //TEXT_TRANSFORM: Specifies how to capitalize text, similar to the CSS `text-transform` property. + + /** + * The text is not altered. + */ + public static final String TEXT_TRANSFORM_NONE = "none"; + /** + * Forces all letters to be displayed in uppercase. + */ + public static final String TEXT_TRANSFORM_UPPERCASE = "uppercase"; + /** + * Forces all letters to be displayed in lowercase. + */ + public static final String TEXT_TRANSFORM_LOWERCASE = "lowercase"; + + /** + * Specifies how to capitalize text, similar to the CSS `text-transform` property. + */ + @StringDef( { + TEXT_TRANSFORM_NONE, + TEXT_TRANSFORM_UPPERCASE, + TEXT_TRANSFORM_LOWERCASE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface TEXT_TRANSFORM { + } + + //FILL_TRANSLATE_ANCHOR: Controls the translation reference point. + + /** + * The fill is translated relative to the map. + */ + public static final String FILL_TRANSLATE_ANCHOR_MAP = "map"; + /** + * The fill is translated relative to the viewport. + */ + public static final String FILL_TRANSLATE_ANCHOR_VIEWPORT = "viewport"; + + /** + * Controls the translation reference point. + */ + @StringDef( { + FILL_TRANSLATE_ANCHOR_MAP, + FILL_TRANSLATE_ANCHOR_VIEWPORT, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface FILL_TRANSLATE_ANCHOR { + } + + //LINE_TRANSLATE_ANCHOR: Controls the translation reference point. + + /** + * The line is translated relative to the map. + */ + public static final String LINE_TRANSLATE_ANCHOR_MAP = "map"; + /** + * The line is translated relative to the viewport. + */ + public static final String LINE_TRANSLATE_ANCHOR_VIEWPORT = "viewport"; + + /** + * Controls the translation reference point. + */ + @StringDef( { + LINE_TRANSLATE_ANCHOR_MAP, + LINE_TRANSLATE_ANCHOR_VIEWPORT, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface LINE_TRANSLATE_ANCHOR { + } + + //ICON_TRANSLATE_ANCHOR: Controls the translation reference point. + + /** + * Icons are translated relative to the map. + */ + public static final String ICON_TRANSLATE_ANCHOR_MAP = "map"; + /** + * Icons are translated relative to the viewport. + */ + public static final String ICON_TRANSLATE_ANCHOR_VIEWPORT = "viewport"; + + /** + * Controls the translation reference point. + */ + @StringDef( { + ICON_TRANSLATE_ANCHOR_MAP, + ICON_TRANSLATE_ANCHOR_VIEWPORT, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ICON_TRANSLATE_ANCHOR { + } + + //TEXT_TRANSLATE_ANCHOR: Controls the translation reference point. + + /** + * The text is translated relative to the map. + */ + public static final String TEXT_TRANSLATE_ANCHOR_MAP = "map"; + /** + * The text is translated relative to the viewport. + */ + public static final String TEXT_TRANSLATE_ANCHOR_VIEWPORT = "viewport"; + + /** + * Controls the translation reference point. + */ + @StringDef( { + TEXT_TRANSLATE_ANCHOR_MAP, + TEXT_TRANSLATE_ANCHOR_VIEWPORT, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface TEXT_TRANSLATE_ANCHOR { + } + + //CIRCLE_TRANSLATE_ANCHOR: Controls the translation reference point. + + /** + * The circle is translated relative to the map. + */ + public static final String CIRCLE_TRANSLATE_ANCHOR_MAP = "map"; + /** + * The circle is translated relative to the viewport. + */ + public static final String CIRCLE_TRANSLATE_ANCHOR_VIEWPORT = "viewport"; + + /** + * Controls the translation reference point. + */ + @StringDef( { + CIRCLE_TRANSLATE_ANCHOR_MAP, + CIRCLE_TRANSLATE_ANCHOR_VIEWPORT, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface CIRCLE_TRANSLATE_ANCHOR { + } + + //CIRCLE_PITCH_SCALE: Controls the scaling behavior of the circle when the map is pitched. + + /** + * Circles are scaled according to their apparent distance to the camera. + */ + public static final String CIRCLE_PITCH_SCALE_MAP = "map"; + /** + * Circles are not scaled. + */ + public static final String CIRCLE_PITCH_SCALE_VIEWPORT = "viewport"; + + /** + * Controls the scaling behavior of the circle when the map is pitched. + */ + @StringDef( { + CIRCLE_PITCH_SCALE_MAP, + CIRCLE_PITCH_SCALE_VIEWPORT, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface CIRCLE_PITCH_SCALE { + } + + //Class definition + public final String name; + public final T value; + + /* package */ Property(String name, T value) { + this.name = name; + this.value = value; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java index d24dd541d0..8e7d516a39 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java @@ -1,5 +1,5 @@ -// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. package com.mapbox.mapboxsdk.style.layers; +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. import android.annotation.SuppressLint; import android.support.annotation.ColorInt; @@ -11,1909 +11,1947 @@ import android.support.annotation.ColorInt; */ public class PropertyFactory { - /** - * Set the property visibility. - * - * @param value the visibility value - * @return property wrapper around visibility - */ - public static Property<String> visibility(@Property.VISIBILITY String value) { - return new LayoutProperty<>("visibility", value); - } - - /** - * Set the property visibility. - * - * @param function the visibility function - * @return property wrapper around a String function - */ - public static Property<Function<String>> visibility(Function<String> function) { - return new LayoutProperty<>("visibility", function); - } - - /** - * Whether or not the fill should be antialiased. - * - * @param value a Boolean value - * @return property wrapper around Boolean - */ - public static Property<Boolean> fillAntialias(Boolean value) { - return new PaintProperty<>("fill-antialias", value); - } - - /** - * Whether or not the fill should be antialiased. - * - * @param function a wrapper function for Boolean - * @return property wrapper around a Boolean function - */ - public static Property<Function<Boolean>> fillAntialias(Function<Boolean> function) { - return new PaintProperty<>("fill-antialias", function); - } - - /** - * The opacity of the entire fill layer. In contrast to the {@link PropertyFactory#fillColor}, this value will also affect the 1px stroke around the fill, if the stroke is used. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> fillOpacity(Float value) { - return new PaintProperty<>("fill-opacity", value); - } - - /** - * The opacity of the entire fill layer. In contrast to the {@link PropertyFactory#fillColor}, this value will also affect the 1px stroke around the fill, if the stroke is used. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> fillOpacity(Function<Float> function) { - return new PaintProperty<>("fill-opacity", function); - } - - /** - * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the color's opacity will not affect the opacity of the 1px stroke, if it is used. - * - * @param value a int color value - * @return property wrapper around String color - */ - public static Property<String> fillColor(@ColorInt int value) { - return new PaintProperty<>("fill-color", colorToRgbaString(value)); - } - - /** - * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the color's opacity will not affect the opacity of the 1px stroke, if it is used. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> fillColor(String value) { - return new PaintProperty<>("fill-color", value); - } - - /** - * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the color's opacity will not affect the opacity of the 1px stroke, if it is used. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> fillColor(Function<String> function) { - return new PaintProperty<>("fill-color", function); - } - - /** - * The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified. - * - * @param value a int color value - * @return property wrapper around String color - */ - public static Property<String> fillOutlineColor(@ColorInt int value) { - return new PaintProperty<>("fill-outline-color", colorToRgbaString(value)); - } - - /** - * The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> fillOutlineColor(String value) { - return new PaintProperty<>("fill-outline-color", value); - } - - /** - * The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> fillOutlineColor(Function<String> function) { - return new PaintProperty<>("fill-outline-color", function); - } - - /** - * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively. - * - * @param value a Float[] value - * @return property wrapper around Float[] - */ - public static Property<Float[]> fillTranslate(Float[] value) { - return new PaintProperty<>("fill-translate", value); - } - - /** - * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively. - * - * @param function a wrapper function for Float[] - * @return property wrapper around a Float[] function - */ - public static Property<Function<Float[]>> fillTranslate(Function<Float[]> function) { - return new PaintProperty<>("fill-translate", function); - } - - /** - * Controls the translation reference point. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> fillTranslateAnchor(@Property.FILL_TRANSLATE_ANCHOR String value) { - return new PaintProperty<>("fill-translate-anchor", value); - } - - /** - * Controls the translation reference point. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> fillTranslateAnchor(Function<String> function) { - return new PaintProperty<>("fill-translate-anchor", function); - } - - /** - * Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512). - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> fillPattern(String value) { - return new PaintProperty<>("fill-pattern", value); - } - - /** - * Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512). - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> fillPattern(Function<String> function) { - return new PaintProperty<>("fill-pattern", function); - } - - /** - * The opacity at which the line will be drawn. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> lineOpacity(Float value) { - return new PaintProperty<>("line-opacity", value); - } - - /** - * The opacity at which the line will be drawn. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> lineOpacity(Function<Float> function) { - return new PaintProperty<>("line-opacity", function); - } - - /** - * The color with which the line will be drawn. - * - * @param value a int color value - * @return property wrapper around String color - */ - public static Property<String> lineColor(@ColorInt int value) { - return new PaintProperty<>("line-color", colorToRgbaString(value)); - } - - /** - * The color with which the line will be drawn. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> lineColor(String value) { - return new PaintProperty<>("line-color", value); - } - - /** - * The color with which the line will be drawn. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> lineColor(Function<String> function) { - return new PaintProperty<>("line-color", function); - } - - /** - * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively. - * - * @param value a Float[] value - * @return property wrapper around Float[] - */ - public static Property<Float[]> lineTranslate(Float[] value) { - return new PaintProperty<>("line-translate", value); - } - - /** - * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively. - * - * @param function a wrapper function for Float[] - * @return property wrapper around a Float[] function - */ - public static Property<Function<Float[]>> lineTranslate(Function<Float[]> function) { - return new PaintProperty<>("line-translate", function); - } - - /** - * Controls the translation reference point. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> lineTranslateAnchor(@Property.LINE_TRANSLATE_ANCHOR String value) { - return new PaintProperty<>("line-translate-anchor", value); - } - - /** - * Controls the translation reference point. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> lineTranslateAnchor(Function<String> function) { - return new PaintProperty<>("line-translate-anchor", function); - } - - /** - * Stroke thickness. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> lineWidth(Float value) { - return new PaintProperty<>("line-width", value); - } - - /** - * Stroke thickness. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> lineWidth(Function<Float> function) { - return new PaintProperty<>("line-width", function); - } - - /** - * Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> lineGapWidth(Float value) { - return new PaintProperty<>("line-gap-width", value); - } - - /** - * Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> lineGapWidth(Function<Float> function) { - return new PaintProperty<>("line-gap-width", function); - } - - /** - * The line's offset. For linear features, a positive value offsets the line to the right, relative to the direction of the line, and a negative value to the left. For polygon features, a positive value results in an inset, and a negative value results in an outset. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> lineOffset(Float value) { - return new PaintProperty<>("line-offset", value); - } - - /** - * The line's offset. For linear features, a positive value offsets the line to the right, relative to the direction of the line, and a negative value to the left. For polygon features, a positive value results in an inset, and a negative value results in an outset. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> lineOffset(Function<Float> function) { - return new PaintProperty<>("line-offset", function); - } - - /** - * Blur applied to the line, in pixels. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> lineBlur(Float value) { - return new PaintProperty<>("line-blur", value); - } - - /** - * Blur applied to the line, in pixels. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> lineBlur(Function<Float> function) { - return new PaintProperty<>("line-blur", function); - } - - /** - * Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to pixels, multiply the length by the current line width. - * - * @param value a Float[] value - * @return property wrapper around Float[] - */ - public static Property<Float[]> lineDasharray(Float[] value) { - return new PaintProperty<>("line-dasharray", value); - } - - /** - * Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to pixels, multiply the length by the current line width. - * - * @param function a wrapper function for Float[] - * @return property wrapper around a Float[] function - */ - public static Property<Function<Float[]>> lineDasharray(Function<Float[]> function) { - return new PaintProperty<>("line-dasharray", function); - } - - /** - * Name of image in sprite to use for drawing image lines. For seamless patterns, image width must be a factor of two (2, 4, 8, ..., 512). - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> linePattern(String value) { - return new PaintProperty<>("line-pattern", value); - } - - /** - * Name of image in sprite to use for drawing image lines. For seamless patterns, image width must be a factor of two (2, 4, 8, ..., 512). - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> linePattern(Function<String> function) { - return new PaintProperty<>("line-pattern", function); - } - - /** - * The opacity at which the icon will be drawn. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> iconOpacity(Float value) { - return new PaintProperty<>("icon-opacity", value); - } - - /** - * The opacity at which the icon will be drawn. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> iconOpacity(Function<Float> function) { - return new PaintProperty<>("icon-opacity", function); - } - - /** - * The color of the icon. This can only be used with sdf icons. - * - * @param value a int color value - * @return property wrapper around String color - */ - public static Property<String> iconColor(@ColorInt int value) { - return new PaintProperty<>("icon-color", colorToRgbaString(value)); - } - - /** - * The color of the icon. This can only be used with sdf icons. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> iconColor(String value) { - return new PaintProperty<>("icon-color", value); - } - - /** - * The color of the icon. This can only be used with sdf icons. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> iconColor(Function<String> function) { - return new PaintProperty<>("icon-color", function); - } - - /** - * The color of the icon's halo. Icon halos can only be used with SDF icons. - * - * @param value a int color value - * @return property wrapper around String color - */ - public static Property<String> iconHaloColor(@ColorInt int value) { - return new PaintProperty<>("icon-halo-color", colorToRgbaString(value)); - } - - /** - * The color of the icon's halo. Icon halos can only be used with SDF icons. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> iconHaloColor(String value) { - return new PaintProperty<>("icon-halo-color", value); - } - - /** - * The color of the icon's halo. Icon halos can only be used with SDF icons. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> iconHaloColor(Function<String> function) { - return new PaintProperty<>("icon-halo-color", function); - } - - /** - * Distance of halo to the icon outline. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> iconHaloWidth(Float value) { - return new PaintProperty<>("icon-halo-width", value); - } - - /** - * Distance of halo to the icon outline. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> iconHaloWidth(Function<Float> function) { - return new PaintProperty<>("icon-halo-width", function); - } - - /** - * Fade out the halo towards the outside. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> iconHaloBlur(Float value) { - return new PaintProperty<>("icon-halo-blur", value); - } - - /** - * Fade out the halo towards the outside. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> iconHaloBlur(Function<Float> function) { - return new PaintProperty<>("icon-halo-blur", function); - } - - /** - * Distance that the icon's anchor is moved from its original placement. Positive values indicate right and down, while negative values indicate left and up. - * - * @param value a Float[] value - * @return property wrapper around Float[] - */ - public static Property<Float[]> iconTranslate(Float[] value) { - return new PaintProperty<>("icon-translate", value); - } - - /** - * Distance that the icon's anchor is moved from its original placement. Positive values indicate right and down, while negative values indicate left and up. - * - * @param function a wrapper function for Float[] - * @return property wrapper around a Float[] function - */ - public static Property<Function<Float[]>> iconTranslate(Function<Float[]> function) { - return new PaintProperty<>("icon-translate", function); - } - - /** - * Controls the translation reference point. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> iconTranslateAnchor(@Property.ICON_TRANSLATE_ANCHOR String value) { - return new PaintProperty<>("icon-translate-anchor", value); - } - - /** - * Controls the translation reference point. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> iconTranslateAnchor(Function<String> function) { - return new PaintProperty<>("icon-translate-anchor", function); - } - - /** - * The opacity at which the text will be drawn. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> textOpacity(Float value) { - return new PaintProperty<>("text-opacity", value); - } - - /** - * The opacity at which the text will be drawn. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> textOpacity(Function<Float> function) { - return new PaintProperty<>("text-opacity", function); - } - - /** - * The color with which the text will be drawn. - * - * @param value a int color value - * @return property wrapper around String color - */ - public static Property<String> textColor(@ColorInt int value) { - return new PaintProperty<>("text-color", colorToRgbaString(value)); - } - - /** - * The color with which the text will be drawn. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> textColor(String value) { - return new PaintProperty<>("text-color", value); - } - - /** - * The color with which the text will be drawn. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> textColor(Function<String> function) { - return new PaintProperty<>("text-color", function); - } - - /** - * The color of the text's halo, which helps it stand out from backgrounds. - * - * @param value a int color value - * @return property wrapper around String color - */ - public static Property<String> textHaloColor(@ColorInt int value) { - return new PaintProperty<>("text-halo-color", colorToRgbaString(value)); - } - - /** - * The color of the text's halo, which helps it stand out from backgrounds. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> textHaloColor(String value) { - return new PaintProperty<>("text-halo-color", value); - } - - /** - * The color of the text's halo, which helps it stand out from backgrounds. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> textHaloColor(Function<String> function) { - return new PaintProperty<>("text-halo-color", function); - } - - /** - * Distance of halo to the font outline. Max text halo width is 1/4 of the font-size. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> textHaloWidth(Float value) { - return new PaintProperty<>("text-halo-width", value); - } - - /** - * Distance of halo to the font outline. Max text halo width is 1/4 of the font-size. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> textHaloWidth(Function<Float> function) { - return new PaintProperty<>("text-halo-width", function); - } - - /** - * The halo's fadeout distance towards the outside. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> textHaloBlur(Float value) { - return new PaintProperty<>("text-halo-blur", value); - } - - /** - * The halo's fadeout distance towards the outside. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> textHaloBlur(Function<Float> function) { - return new PaintProperty<>("text-halo-blur", function); - } - - /** - * Distance that the text's anchor is moved from its original placement. Positive values indicate right and down, while negative values indicate left and up. - * - * @param value a Float[] value - * @return property wrapper around Float[] - */ - public static Property<Float[]> textTranslate(Float[] value) { - return new PaintProperty<>("text-translate", value); - } - - /** - * Distance that the text's anchor is moved from its original placement. Positive values indicate right and down, while negative values indicate left and up. - * - * @param function a wrapper function for Float[] - * @return property wrapper around a Float[] function - */ - public static Property<Function<Float[]>> textTranslate(Function<Float[]> function) { - return new PaintProperty<>("text-translate", function); - } - - /** - * Controls the translation reference point. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> textTranslateAnchor(@Property.TEXT_TRANSLATE_ANCHOR String value) { - return new PaintProperty<>("text-translate-anchor", value); - } - - /** - * Controls the translation reference point. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> textTranslateAnchor(Function<String> function) { - return new PaintProperty<>("text-translate-anchor", function); - } - - /** - * Circle radius. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> circleRadius(Float value) { - return new PaintProperty<>("circle-radius", value); - } - - /** - * Circle radius. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> circleRadius(Function<Float> function) { - return new PaintProperty<>("circle-radius", function); - } - - /** - * The fill color of the circle. - * - * @param value a int color value - * @return property wrapper around String color - */ - public static Property<String> circleColor(@ColorInt int value) { - return new PaintProperty<>("circle-color", colorToRgbaString(value)); - } - - /** - * The fill color of the circle. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> circleColor(String value) { - return new PaintProperty<>("circle-color", value); - } - - /** - * The fill color of the circle. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> circleColor(Function<String> function) { - return new PaintProperty<>("circle-color", function); - } - - /** - * Amount to blur the circle. 1 blurs the circle such that only the centerpoint is full opacity. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> circleBlur(Float value) { - return new PaintProperty<>("circle-blur", value); - } - - /** - * Amount to blur the circle. 1 blurs the circle such that only the centerpoint is full opacity. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> circleBlur(Function<Float> function) { - return new PaintProperty<>("circle-blur", function); - } - - /** - * The opacity at which the circle will be drawn. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> circleOpacity(Float value) { - return new PaintProperty<>("circle-opacity", value); - } - - /** - * The opacity at which the circle will be drawn. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> circleOpacity(Function<Float> function) { - return new PaintProperty<>("circle-opacity", function); - } - - /** - * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively. - * - * @param value a Float[] value - * @return property wrapper around Float[] - */ - public static Property<Float[]> circleTranslate(Float[] value) { - return new PaintProperty<>("circle-translate", value); - } - - /** - * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively. - * - * @param function a wrapper function for Float[] - * @return property wrapper around a Float[] function - */ - public static Property<Function<Float[]>> circleTranslate(Function<Float[]> function) { - return new PaintProperty<>("circle-translate", function); - } - - /** - * Controls the translation reference point. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> circleTranslateAnchor(@Property.CIRCLE_TRANSLATE_ANCHOR String value) { - return new PaintProperty<>("circle-translate-anchor", value); - } - - /** - * Controls the translation reference point. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> circleTranslateAnchor(Function<String> function) { - return new PaintProperty<>("circle-translate-anchor", function); - } - - /** - * Controls the scaling behavior of the circle when the map is pitched. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> circlePitchScale(@Property.CIRCLE_PITCH_SCALE String value) { - return new PaintProperty<>("circle-pitch-scale", value); - } - - /** - * Controls the scaling behavior of the circle when the map is pitched. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> circlePitchScale(Function<String> function) { - return new PaintProperty<>("circle-pitch-scale", function); - } - - /** - * The width of the circle's stroke. Strokes are placed outside of the "circle-radius". - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> circleStrokeWidth(Float value) { - return new PaintProperty<>("circle-stroke-width", value); - } - - /** - * The width of the circle's stroke. Strokes are placed outside of the "circle-radius". - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> circleStrokeWidth(Function<Float> function) { - return new PaintProperty<>("circle-stroke-width", function); - } - - /** - * The stroke color of the circle. - * - * @param value a int color value - * @return property wrapper around String color - */ - public static Property<String> circleStrokeColor(@ColorInt int value) { - return new PaintProperty<>("circle-stroke-color", colorToRgbaString(value)); - } - - /** - * The stroke color of the circle. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> circleStrokeColor(String value) { - return new PaintProperty<>("circle-stroke-color", value); - } - - /** - * The stroke color of the circle. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> circleStrokeColor(Function<String> function) { - return new PaintProperty<>("circle-stroke-color", function); - } - - /** - * The opacity of the circle's stroke. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> circleStrokeOpacity(Float value) { - return new PaintProperty<>("circle-stroke-opacity", value); - } - - /** - * The opacity of the circle's stroke. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> circleStrokeOpacity(Function<Float> function) { - return new PaintProperty<>("circle-stroke-opacity", function); - } - - /** - * The opacity at which the image will be drawn. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> rasterOpacity(Float value) { - return new PaintProperty<>("raster-opacity", value); - } - - /** - * The opacity at which the image will be drawn. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> rasterOpacity(Function<Float> function) { - return new PaintProperty<>("raster-opacity", function); - } - - /** - * Rotates hues around the color wheel. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> rasterHueRotate(Float value) { - return new PaintProperty<>("raster-hue-rotate", value); - } - - /** - * Rotates hues around the color wheel. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> rasterHueRotate(Function<Float> function) { - return new PaintProperty<>("raster-hue-rotate", function); - } - - /** - * Increase or reduce the brightness of the image. The value is the minimum brightness. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> rasterBrightnessMin(Float value) { - return new PaintProperty<>("raster-brightness-min", value); - } - - /** - * Increase or reduce the brightness of the image. The value is the minimum brightness. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> rasterBrightnessMin(Function<Float> function) { - return new PaintProperty<>("raster-brightness-min", function); - } - - /** - * Increase or reduce the brightness of the image. The value is the maximum brightness. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> rasterBrightnessMax(Float value) { - return new PaintProperty<>("raster-brightness-max", value); - } - - /** - * Increase or reduce the brightness of the image. The value is the maximum brightness. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> rasterBrightnessMax(Function<Float> function) { - return new PaintProperty<>("raster-brightness-max", function); - } - - /** - * Increase or reduce the saturation of the image. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> rasterSaturation(Float value) { - return new PaintProperty<>("raster-saturation", value); - } - - /** - * Increase or reduce the saturation of the image. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> rasterSaturation(Function<Float> function) { - return new PaintProperty<>("raster-saturation", function); - } - - /** - * Increase or reduce the contrast of the image. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> rasterContrast(Float value) { - return new PaintProperty<>("raster-contrast", value); - } - - /** - * Increase or reduce the contrast of the image. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> rasterContrast(Function<Float> function) { - return new PaintProperty<>("raster-contrast", function); - } - - /** - * Fade duration when a new tile is added. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> rasterFadeDuration(Float value) { - return new PaintProperty<>("raster-fade-duration", value); - } - - /** - * Fade duration when a new tile is added. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> rasterFadeDuration(Function<Float> function) { - return new PaintProperty<>("raster-fade-duration", function); - } - - /** - * The color with which the background will be drawn. - * - * @param value a int color value - * @return property wrapper around String color - */ - public static Property<String> backgroundColor(@ColorInt int value) { - return new PaintProperty<>("background-color", colorToRgbaString(value)); - } - - /** - * The color with which the background will be drawn. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> backgroundColor(String value) { - return new PaintProperty<>("background-color", value); - } - - /** - * The color with which the background will be drawn. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> backgroundColor(Function<String> function) { - return new PaintProperty<>("background-color", function); - } - - /** - * Name of image in sprite to use for drawing an image background. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512). - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> backgroundPattern(String value) { - return new PaintProperty<>("background-pattern", value); - } - - /** - * Name of image in sprite to use for drawing an image background. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512). - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> backgroundPattern(Function<String> function) { - return new PaintProperty<>("background-pattern", function); - } - - /** - * The opacity at which the background will be drawn. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> backgroundOpacity(Float value) { - return new PaintProperty<>("background-opacity", value); - } - - /** - * The opacity at which the background will be drawn. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> backgroundOpacity(Function<Float> function) { - return new PaintProperty<>("background-opacity", function); - } - - /** - * The display of line endings. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> lineCap(@Property.LINE_CAP String value) { - return new LayoutProperty<>("line-cap", value); - } - - /** - * The display of line endings. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> lineCap(Function<String> function) { - return new LayoutProperty<>("line-cap", function); - } - - /** - * The display of lines when joining. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> lineJoin(@Property.LINE_JOIN String value) { - return new LayoutProperty<>("line-join", value); - } - - /** - * The display of lines when joining. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> lineJoin(Function<String> function) { - return new LayoutProperty<>("line-join", function); - } - - /** - * Used to automatically convert miter joins to bevel joins for sharp angles. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> lineMiterLimit(Float value) { - return new LayoutProperty<>("line-miter-limit", value); - } - - /** - * Used to automatically convert miter joins to bevel joins for sharp angles. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> lineMiterLimit(Function<Float> function) { - return new LayoutProperty<>("line-miter-limit", function); - } - - /** - * Used to automatically convert round joins to miter joins for shallow angles. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> lineRoundLimit(Float value) { - return new LayoutProperty<>("line-round-limit", value); - } - - /** - * Used to automatically convert round joins to miter joins for shallow angles. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> lineRoundLimit(Function<Float> function) { - return new LayoutProperty<>("line-round-limit", function); - } - - /** - * Label placement relative to its geometry. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> symbolPlacement(@Property.SYMBOL_PLACEMENT String value) { - return new LayoutProperty<>("symbol-placement", value); - } - - /** - * Label placement relative to its geometry. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> symbolPlacement(Function<String> function) { - return new LayoutProperty<>("symbol-placement", function); - } - - /** - * Distance between two symbol anchors. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> symbolSpacing(Float value) { - return new LayoutProperty<>("symbol-spacing", value); - } - - /** - * Distance between two symbol anchors. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> symbolSpacing(Function<Float> function) { - return new LayoutProperty<>("symbol-spacing", function); - } - - /** - * If true, the symbols will not cross tile edges to avoid mutual collisions. Recommended in layers that don't have enough padding in the vector tile to prevent collisions, or if it is a point symbol layer placed after a line symbol layer. - * - * @param value a Boolean value - * @return property wrapper around Boolean - */ - public static Property<Boolean> symbolAvoidEdges(Boolean value) { - return new LayoutProperty<>("symbol-avoid-edges", value); - } - - /** - * If true, the symbols will not cross tile edges to avoid mutual collisions. Recommended in layers that don't have enough padding in the vector tile to prevent collisions, or if it is a point symbol layer placed after a line symbol layer. - * - * @param function a wrapper function for Boolean - * @return property wrapper around a Boolean function - */ - public static Property<Function<Boolean>> symbolAvoidEdges(Function<Boolean> function) { - return new LayoutProperty<>("symbol-avoid-edges", function); - } - - /** - * If true, the icon will be visible even if it collides with other previously drawn symbols. - * - * @param value a Boolean value - * @return property wrapper around Boolean - */ - public static Property<Boolean> iconAllowOverlap(Boolean value) { - return new LayoutProperty<>("icon-allow-overlap", value); - } - - /** - * If true, the icon will be visible even if it collides with other previously drawn symbols. - * - * @param function a wrapper function for Boolean - * @return property wrapper around a Boolean function - */ - public static Property<Function<Boolean>> iconAllowOverlap(Function<Boolean> function) { - return new LayoutProperty<>("icon-allow-overlap", function); - } - - /** - * If true, other symbols can be visible even if they collide with the icon. - * - * @param value a Boolean value - * @return property wrapper around Boolean - */ - public static Property<Boolean> iconIgnorePlacement(Boolean value) { - return new LayoutProperty<>("icon-ignore-placement", value); - } - - /** - * If true, other symbols can be visible even if they collide with the icon. - * - * @param function a wrapper function for Boolean - * @return property wrapper around a Boolean function - */ - public static Property<Function<Boolean>> iconIgnorePlacement(Function<Boolean> function) { - return new LayoutProperty<>("icon-ignore-placement", function); - } - - /** - * If true, text will display without their corresponding icons when the icon collides with other symbols and the text does not. - * - * @param value a Boolean value - * @return property wrapper around Boolean - */ - public static Property<Boolean> iconOptional(Boolean value) { - return new LayoutProperty<>("icon-optional", value); - } - - /** - * If true, text will display without their corresponding icons when the icon collides with other symbols and the text does not. - * - * @param function a wrapper function for Boolean - * @return property wrapper around a Boolean function - */ - public static Property<Function<Boolean>> iconOptional(Function<Boolean> function) { - return new LayoutProperty<>("icon-optional", function); - } - - /** - * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of icons. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> iconRotationAlignment(@Property.ICON_ROTATION_ALIGNMENT String value) { - return new LayoutProperty<>("icon-rotation-alignment", value); - } - - /** - * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of icons. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> iconRotationAlignment(Function<String> function) { - return new LayoutProperty<>("icon-rotation-alignment", function); - } - - /** - * Scale factor for icon. 1 is original size, 3 triples the size. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> iconSize(Float value) { - return new LayoutProperty<>("icon-size", value); - } - - /** - * Scale factor for icon. 1 is original size, 3 triples the size. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> iconSize(Function<Float> function) { - return new LayoutProperty<>("icon-size", function); - } - - /** - * Scales the icon to fit around the associated text. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> iconTextFit(@Property.ICON_TEXT_FIT String value) { - return new LayoutProperty<>("icon-text-fit", value); - } - - /** - * Scales the icon to fit around the associated text. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> iconTextFit(Function<String> function) { - return new LayoutProperty<>("icon-text-fit", function); - } - - /** - * Size of the additional area added to dimensions determined by {@link Property.ICON_TEXT_FIT}, in clockwise order: top, right, bottom, left. - * - * @param value a Float[] value - * @return property wrapper around Float[] - */ - public static Property<Float[]> iconTextFitPadding(Float[] value) { - return new LayoutProperty<>("icon-text-fit-padding", value); - } - - /** - * Size of the additional area added to dimensions determined by {@link Property.ICON_TEXT_FIT}, in clockwise order: top, right, bottom, left. - * - * @param function a wrapper function for Float[] - * @return property wrapper around a Float[] function - */ - public static Property<Function<Float[]>> iconTextFitPadding(Function<Float[]> function) { - return new LayoutProperty<>("icon-text-fit-padding", function); - } - - /** - * A string with {tokens} replaced, referencing the data property to pull from. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> iconImage(String value) { - return new LayoutProperty<>("icon-image", value); - } - - /** - * A string with {tokens} replaced, referencing the data property to pull from. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> iconImage(Function<String> function) { - return new LayoutProperty<>("icon-image", function); - } - - /** - * Rotates the icon clockwise. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> iconRotate(Float value) { - return new LayoutProperty<>("icon-rotate", value); - } - - /** - * Rotates the icon clockwise. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> iconRotate(Function<Float> function) { - return new LayoutProperty<>("icon-rotate", function); - } - - /** - * Size of the additional area around the icon bounding box used for detecting symbol collisions. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> iconPadding(Float value) { - return new LayoutProperty<>("icon-padding", value); - } - - /** - * Size of the additional area around the icon bounding box used for detecting symbol collisions. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> iconPadding(Function<Float> function) { - return new LayoutProperty<>("icon-padding", function); - } - - /** - * If true, the icon may be flipped to prevent it from being rendered upside-down. - * - * @param value a Boolean value - * @return property wrapper around Boolean - */ - public static Property<Boolean> iconKeepUpright(Boolean value) { - return new LayoutProperty<>("icon-keep-upright", value); - } - - /** - * If true, the icon may be flipped to prevent it from being rendered upside-down. - * - * @param function a wrapper function for Boolean - * @return property wrapper around a Boolean function - */ - public static Property<Function<Boolean>> iconKeepUpright(Function<Boolean> function) { - return new LayoutProperty<>("icon-keep-upright", function); - } - - /** - * Offset distance of icon from its anchor. Positive values indicate right and down, while negative values indicate left and up. - * - * @param value a Float[] value - * @return property wrapper around Float[] - */ - public static Property<Float[]> iconOffset(Float[] value) { - return new LayoutProperty<>("icon-offset", value); - } - - /** - * Offset distance of icon from its anchor. Positive values indicate right and down, while negative values indicate left and up. - * - * @param function a wrapper function for Float[] - * @return property wrapper around a Float[] function - */ - public static Property<Function<Float[]>> iconOffset(Function<Float[]> function) { - return new LayoutProperty<>("icon-offset", function); - } - - /** - * Orientation of text when map is pitched. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> textPitchAlignment(@Property.TEXT_PITCH_ALIGNMENT String value) { - return new LayoutProperty<>("text-pitch-alignment", value); - } - - /** - * Orientation of text when map is pitched. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> textPitchAlignment(Function<String> function) { - return new LayoutProperty<>("text-pitch-alignment", function); - } - - /** - * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of the individual glyphs forming the text. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> textRotationAlignment(@Property.TEXT_ROTATION_ALIGNMENT String value) { - return new LayoutProperty<>("text-rotation-alignment", value); - } - - /** - * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of the individual glyphs forming the text. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> textRotationAlignment(Function<String> function) { - return new LayoutProperty<>("text-rotation-alignment", function); - } - - /** - * Value to use for a text label. Feature properties are specified using tokens like {field_name}. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> textField(String value) { - return new LayoutProperty<>("text-field", value); - } - - /** - * Value to use for a text label. Feature properties are specified using tokens like {field_name}. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> textField(Function<String> function) { - return new LayoutProperty<>("text-field", function); - } - - /** - * Font stack to use for displaying text. - * - * @param value a String[] value - * @return property wrapper around String[] - */ - public static Property<String[]> textFont(String[] value) { - return new LayoutProperty<>("text-font", value); - } - - /** - * Font stack to use for displaying text. - * - * @param function a wrapper function for String[] - * @return property wrapper around a String[] function - */ - public static Property<Function<String[]>> textFont(Function<String[]> function) { - return new LayoutProperty<>("text-font", function); - } - - /** - * Font size. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> textSize(Float value) { - return new LayoutProperty<>("text-size", value); - } - - /** - * Font size. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> textSize(Function<Float> function) { - return new LayoutProperty<>("text-size", function); - } - - /** - * The maximum line width for text wrapping. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> textMaxWidth(Float value) { - return new LayoutProperty<>("text-max-width", value); - } - - /** - * The maximum line width for text wrapping. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> textMaxWidth(Function<Float> function) { - return new LayoutProperty<>("text-max-width", function); - } - - /** - * Text leading value for multi-line text. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> textLineHeight(Float value) { - return new LayoutProperty<>("text-line-height", value); - } - - /** - * Text leading value for multi-line text. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> textLineHeight(Function<Float> function) { - return new LayoutProperty<>("text-line-height", function); - } - - /** - * Text tracking amount. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> textLetterSpacing(Float value) { - return new LayoutProperty<>("text-letter-spacing", value); - } - - /** - * Text tracking amount. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> textLetterSpacing(Function<Float> function) { - return new LayoutProperty<>("text-letter-spacing", function); - } - - /** - * Text justification options. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> textJustify(@Property.TEXT_JUSTIFY String value) { - return new LayoutProperty<>("text-justify", value); - } - - /** - * Text justification options. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> textJustify(Function<String> function) { - return new LayoutProperty<>("text-justify", function); - } - - /** - * Part of the text placed closest to the anchor. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> textAnchor(@Property.TEXT_ANCHOR String value) { - return new LayoutProperty<>("text-anchor", value); - } - - /** - * Part of the text placed closest to the anchor. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> textAnchor(Function<String> function) { - return new LayoutProperty<>("text-anchor", function); - } - - /** - * Maximum angle change between adjacent characters. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> textMaxAngle(Float value) { - return new LayoutProperty<>("text-max-angle", value); - } - - /** - * Maximum angle change between adjacent characters. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> textMaxAngle(Function<Float> function) { - return new LayoutProperty<>("text-max-angle", function); - } - - /** - * Rotates the text clockwise. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> textRotate(Float value) { - return new LayoutProperty<>("text-rotate", value); - } - - /** - * Rotates the text clockwise. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> textRotate(Function<Float> function) { - return new LayoutProperty<>("text-rotate", function); - } - - /** - * Size of the additional area around the text bounding box used for detecting symbol collisions. - * - * @param value a Float value - * @return property wrapper around Float - */ - public static Property<Float> textPadding(Float value) { - return new LayoutProperty<>("text-padding", value); - } - - /** - * Size of the additional area around the text bounding box used for detecting symbol collisions. - * - * @param function a wrapper function for Float - * @return property wrapper around a Float function - */ - public static Property<Function<Float>> textPadding(Function<Float> function) { - return new LayoutProperty<>("text-padding", function); - } - - /** - * If true, the text may be flipped vertically to prevent it from being rendered upside-down. - * - * @param value a Boolean value - * @return property wrapper around Boolean - */ - public static Property<Boolean> textKeepUpright(Boolean value) { - return new LayoutProperty<>("text-keep-upright", value); - } - - /** - * If true, the text may be flipped vertically to prevent it from being rendered upside-down. - * - * @param function a wrapper function for Boolean - * @return property wrapper around a Boolean function - */ - public static Property<Function<Boolean>> textKeepUpright(Function<Boolean> function) { - return new LayoutProperty<>("text-keep-upright", function); - } - - /** - * Specifies how to capitalize text, similar to the CSS {@link PropertyFactory#textTransform} property. - * - * @param value a String value - * @return property wrapper around String - */ - public static Property<String> textTransform(@Property.TEXT_TRANSFORM String value) { - return new LayoutProperty<>("text-transform", value); - } - - /** - * Specifies how to capitalize text, similar to the CSS {@link PropertyFactory#textTransform} property. - * - * @param function a wrapper function for String - * @return property wrapper around a String function - */ - public static Property<Function<String>> textTransform(Function<String> function) { - return new LayoutProperty<>("text-transform", function); - } - - /** - * Offset distance of text from its anchor. Positive values indicate right and down, while negative values indicate left and up. - * - * @param value a Float[] value - * @return property wrapper around Float[] - */ - public static Property<Float[]> textOffset(Float[] value) { - return new LayoutProperty<>("text-offset", value); - } - - /** - * Offset distance of text from its anchor. Positive values indicate right and down, while negative values indicate left and up. - * - * @param function a wrapper function for Float[] - * @return property wrapper around a Float[] function - */ - public static Property<Function<Float[]>> textOffset(Function<Float[]> function) { - return new LayoutProperty<>("text-offset", function); - } - - /** - * If true, the text will be visible even if it collides with other previously drawn symbols. - * - * @param value a Boolean value - * @return property wrapper around Boolean - */ - public static Property<Boolean> textAllowOverlap(Boolean value) { - return new LayoutProperty<>("text-allow-overlap", value); - } - - /** - * If true, the text will be visible even if it collides with other previously drawn symbols. - * - * @param function a wrapper function for Boolean - * @return property wrapper around a Boolean function - */ - public static Property<Function<Boolean>> textAllowOverlap(Function<Boolean> function) { - return new LayoutProperty<>("text-allow-overlap", function); - } - - /** - * If true, other symbols can be visible even if they collide with the text. - * - * @param value a Boolean value - * @return property wrapper around Boolean - */ - public static Property<Boolean> textIgnorePlacement(Boolean value) { - return new LayoutProperty<>("text-ignore-placement", value); - } - - /** - * If true, other symbols can be visible even if they collide with the text. - * - * @param function a wrapper function for Boolean - * @return property wrapper around a Boolean function - */ - public static Property<Function<Boolean>> textIgnorePlacement(Function<Boolean> function) { - return new LayoutProperty<>("text-ignore-placement", function); - } - - /** - * If true, icons will display without their corresponding text when the text collides with other symbols and the icon does not. - * - * @param value a Boolean value - * @return property wrapper around Boolean - */ - public static Property<Boolean> textOptional(Boolean value) { - return new LayoutProperty<>("text-optional", value); - } - - /** - * If true, icons will display without their corresponding text when the text collides with other symbols and the icon does not. - * - * @param function a wrapper function for Boolean - * @return property wrapper around a Boolean function - */ - public static Property<Function<Boolean>> textOptional(Function<Boolean> function) { - return new LayoutProperty<>("text-optional", function); - } - - @SuppressLint("DefaultLocale") - static String colorToRgbaString(@ColorInt int value) { - return String.format("rgba(%d, %d, %d, %d)", (value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF, (value >> 24) & 0xFF); - } + /** + * Set the property visibility. + * + * @param value the visibility value + * @return property wrapper around visibility + */ + public static Property<String> visibility(@Property.VISIBILITY String value) { + return new LayoutProperty<>("visibility", value); + } + + /** + * Set the property visibility. + * + * @param function the visibility function + * @return property wrapper around a String function + */ + public static Property<Function<String>> visibility(Function<String> function) { + return new LayoutProperty<>("visibility", function); + } + + /** + * Whether or not the fill should be antialiased. + * + * @param value a Boolean value + * @return property wrapper around Boolean + */ + public static Property<Boolean> fillAntialias(Boolean value) { + return new PaintProperty<>("fill-antialias", value); + } + + /** + * Whether or not the fill should be antialiased. + * + * @param function a wrapper function for Boolean + * @return property wrapper around a Boolean function + */ + public static Property<Function<Boolean>> fillAntialias(Function<Boolean> function) { + return new PaintProperty<>("fill-antialias", function); + } + + /** + * The opacity of the entire fill layer. In contrast to the {@link PropertyFactory#fillColor}, this value will also + * affect the 1px stroke around the fill, if the stroke is used. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> fillOpacity(Float value) { + return new PaintProperty<>("fill-opacity", value); + } + + /** + * The opacity of the entire fill layer. In contrast to the {@link PropertyFactory#fillColor}, this value will also + * affect the 1px stroke around the fill, if the stroke is used. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> fillOpacity(Function<Float> function) { + return new PaintProperty<>("fill-opacity", function); + } + + /** + * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the + * color's opacity will not affect the opacity of the 1px stroke, if it is used. + * + * @param value a int color value + * @return property wrapper around String color + */ + public static Property<String> fillColor(@ColorInt int value) { + return new PaintProperty<>("fill-color", colorToRgbaString(value)); + } + + /** + * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the + * color's opacity will not affect the opacity of the 1px stroke, if it is used. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> fillColor(String value) { + return new PaintProperty<>("fill-color", value); + } + + /** + * The color of the filled part of this layer. This color can be specified as `rgba` with an alpha component and the + * color's opacity will not affect the opacity of the 1px stroke, if it is used. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> fillColor(Function<String> function) { + return new PaintProperty<>("fill-color", function); + } + + /** + * The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified. + * + * @param value a int color value + * @return property wrapper around String color + */ + public static Property<String> fillOutlineColor(@ColorInt int value) { + return new PaintProperty<>("fill-outline-color", colorToRgbaString(value)); + } + + /** + * The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> fillOutlineColor(String value) { + return new PaintProperty<>("fill-outline-color", value); + } + + /** + * The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> fillOutlineColor(Function<String> function) { + return new PaintProperty<>("fill-outline-color", function); + } + + /** + * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively. + * + * @param value a Float[] value + * @return property wrapper around Float[] + */ + public static Property<Float[]> fillTranslate(Float[] value) { + return new PaintProperty<>("fill-translate", value); + } + + /** + * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively. + * + * @param function a wrapper function for Float[] + * @return property wrapper around a Float[] function + */ + public static Property<Function<Float[]>> fillTranslate(Function<Float[]> function) { + return new PaintProperty<>("fill-translate", function); + } + + /** + * Controls the translation reference point. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> fillTranslateAnchor(@Property.FILL_TRANSLATE_ANCHOR String value) { + return new PaintProperty<>("fill-translate-anchor", value); + } + + /** + * Controls the translation reference point. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> fillTranslateAnchor(Function<String> function) { + return new PaintProperty<>("fill-translate-anchor", function); + } + + /** + * Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a + * factor of two (2, 4, 8, ..., 512). + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> fillPattern(String value) { + return new PaintProperty<>("fill-pattern", value); + } + + /** + * Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a + * factor of two (2, 4, 8, ..., 512). + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> fillPattern(Function<String> function) { + return new PaintProperty<>("fill-pattern", function); + } + + /** + * The opacity at which the line will be drawn. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> lineOpacity(Float value) { + return new PaintProperty<>("line-opacity", value); + } + + /** + * The opacity at which the line will be drawn. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> lineOpacity(Function<Float> function) { + return new PaintProperty<>("line-opacity", function); + } + + /** + * The color with which the line will be drawn. + * + * @param value a int color value + * @return property wrapper around String color + */ + public static Property<String> lineColor(@ColorInt int value) { + return new PaintProperty<>("line-color", colorToRgbaString(value)); + } + + /** + * The color with which the line will be drawn. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> lineColor(String value) { + return new PaintProperty<>("line-color", value); + } + + /** + * The color with which the line will be drawn. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> lineColor(Function<String> function) { + return new PaintProperty<>("line-color", function); + } + + /** + * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively. + * + * @param value a Float[] value + * @return property wrapper around Float[] + */ + public static Property<Float[]> lineTranslate(Float[] value) { + return new PaintProperty<>("line-translate", value); + } + + /** + * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively. + * + * @param function a wrapper function for Float[] + * @return property wrapper around a Float[] function + */ + public static Property<Function<Float[]>> lineTranslate(Function<Float[]> function) { + return new PaintProperty<>("line-translate", function); + } + + /** + * Controls the translation reference point. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> lineTranslateAnchor(@Property.LINE_TRANSLATE_ANCHOR String value) { + return new PaintProperty<>("line-translate-anchor", value); + } + + /** + * Controls the translation reference point. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> lineTranslateAnchor(Function<String> function) { + return new PaintProperty<>("line-translate-anchor", function); + } + + /** + * Stroke thickness. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> lineWidth(Float value) { + return new PaintProperty<>("line-width", value); + } + + /** + * Stroke thickness. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> lineWidth(Function<Float> function) { + return new PaintProperty<>("line-width", function); + } + + /** + * Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> lineGapWidth(Float value) { + return new PaintProperty<>("line-gap-width", value); + } + + /** + * Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> lineGapWidth(Function<Float> function) { + return new PaintProperty<>("line-gap-width", function); + } + + /** + * The line's offset. For linear features, a positive value offsets the line to the right, relative to the direction + * of the line, and a negative value to the left. For polygon features, a positive value results in an inset, and a + * negative value results in an outset. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> lineOffset(Float value) { + return new PaintProperty<>("line-offset", value); + } + + /** + * The line's offset. For linear features, a positive value offsets the line to the right, relative to the direction + * of the line, and a negative value to the left. For polygon features, a positive value results in an inset, and a + * negative value results in an outset. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> lineOffset(Function<Float> function) { + return new PaintProperty<>("line-offset", function); + } + + /** + * Blur applied to the line, in pixels. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> lineBlur(Float value) { + return new PaintProperty<>("line-blur", value); + } + + /** + * Blur applied to the line, in pixels. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> lineBlur(Function<Float> function) { + return new PaintProperty<>("line-blur", function); + } + + /** + * Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled + * by the line width. To convert a dash length to pixels, multiply the length by the current line width. + * + * @param value a Float[] value + * @return property wrapper around Float[] + */ + public static Property<Float[]> lineDasharray(Float[] value) { + return new PaintProperty<>("line-dasharray", value); + } + + /** + * Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled + * by the line width. To convert a dash length to pixels, multiply the length by the current line width. + * + * @param function a wrapper function for Float[] + * @return property wrapper around a Float[] function + */ + public static Property<Function<Float[]>> lineDasharray(Function<Float[]> function) { + return new PaintProperty<>("line-dasharray", function); + } + + /** + * Name of image in sprite to use for drawing image lines. For seamless patterns, image width must be a factor of two + * (2, 4, 8, ..., 512). + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> linePattern(String value) { + return new PaintProperty<>("line-pattern", value); + } + + /** + * Name of image in sprite to use for drawing image lines. For seamless patterns, image width must be a factor of two + * (2, 4, 8, ..., 512). + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> linePattern(Function<String> function) { + return new PaintProperty<>("line-pattern", function); + } + + /** + * The opacity at which the icon will be drawn. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> iconOpacity(Float value) { + return new PaintProperty<>("icon-opacity", value); + } + + /** + * The opacity at which the icon will be drawn. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> iconOpacity(Function<Float> function) { + return new PaintProperty<>("icon-opacity", function); + } + + /** + * The color of the icon. This can only be used with sdf icons. + * + * @param value a int color value + * @return property wrapper around String color + */ + public static Property<String> iconColor(@ColorInt int value) { + return new PaintProperty<>("icon-color", colorToRgbaString(value)); + } + + /** + * The color of the icon. This can only be used with sdf icons. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> iconColor(String value) { + return new PaintProperty<>("icon-color", value); + } + + /** + * The color of the icon. This can only be used with sdf icons. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> iconColor(Function<String> function) { + return new PaintProperty<>("icon-color", function); + } + + /** + * The color of the icon's halo. Icon halos can only be used with SDF icons. + * + * @param value a int color value + * @return property wrapper around String color + */ + public static Property<String> iconHaloColor(@ColorInt int value) { + return new PaintProperty<>("icon-halo-color", colorToRgbaString(value)); + } + + /** + * The color of the icon's halo. Icon halos can only be used with SDF icons. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> iconHaloColor(String value) { + return new PaintProperty<>("icon-halo-color", value); + } + + /** + * The color of the icon's halo. Icon halos can only be used with SDF icons. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> iconHaloColor(Function<String> function) { + return new PaintProperty<>("icon-halo-color", function); + } + + /** + * Distance of halo to the icon outline. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> iconHaloWidth(Float value) { + return new PaintProperty<>("icon-halo-width", value); + } + + /** + * Distance of halo to the icon outline. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> iconHaloWidth(Function<Float> function) { + return new PaintProperty<>("icon-halo-width", function); + } + + /** + * Fade out the halo towards the outside. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> iconHaloBlur(Float value) { + return new PaintProperty<>("icon-halo-blur", value); + } + + /** + * Fade out the halo towards the outside. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> iconHaloBlur(Function<Float> function) { + return new PaintProperty<>("icon-halo-blur", function); + } + + /** + * Distance that the icon's anchor is moved from its original placement. Positive values indicate right and down, + * while negative values indicate left and up. + * + * @param value a Float[] value + * @return property wrapper around Float[] + */ + public static Property<Float[]> iconTranslate(Float[] value) { + return new PaintProperty<>("icon-translate", value); + } + + /** + * Distance that the icon's anchor is moved from its original placement. Positive values indicate right and down, + * while negative values indicate left and up. + * + * @param function a wrapper function for Float[] + * @return property wrapper around a Float[] function + */ + public static Property<Function<Float[]>> iconTranslate(Function<Float[]> function) { + return new PaintProperty<>("icon-translate", function); + } + + /** + * Controls the translation reference point. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> iconTranslateAnchor(@Property.ICON_TRANSLATE_ANCHOR String value) { + return new PaintProperty<>("icon-translate-anchor", value); + } + + /** + * Controls the translation reference point. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> iconTranslateAnchor(Function<String> function) { + return new PaintProperty<>("icon-translate-anchor", function); + } + + /** + * The opacity at which the text will be drawn. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> textOpacity(Float value) { + return new PaintProperty<>("text-opacity", value); + } + + /** + * The opacity at which the text will be drawn. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> textOpacity(Function<Float> function) { + return new PaintProperty<>("text-opacity", function); + } + + /** + * The color with which the text will be drawn. + * + * @param value a int color value + * @return property wrapper around String color + */ + public static Property<String> textColor(@ColorInt int value) { + return new PaintProperty<>("text-color", colorToRgbaString(value)); + } + + /** + * The color with which the text will be drawn. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> textColor(String value) { + return new PaintProperty<>("text-color", value); + } + + /** + * The color with which the text will be drawn. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> textColor(Function<String> function) { + return new PaintProperty<>("text-color", function); + } + + /** + * The color of the text's halo, which helps it stand out from backgrounds. + * + * @param value a int color value + * @return property wrapper around String color + */ + public static Property<String> textHaloColor(@ColorInt int value) { + return new PaintProperty<>("text-halo-color", colorToRgbaString(value)); + } + + /** + * The color of the text's halo, which helps it stand out from backgrounds. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> textHaloColor(String value) { + return new PaintProperty<>("text-halo-color", value); + } + + /** + * The color of the text's halo, which helps it stand out from backgrounds. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> textHaloColor(Function<String> function) { + return new PaintProperty<>("text-halo-color", function); + } + + /** + * Distance of halo to the font outline. Max text halo width is 1/4 of the font-size. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> textHaloWidth(Float value) { + return new PaintProperty<>("text-halo-width", value); + } + + /** + * Distance of halo to the font outline. Max text halo width is 1/4 of the font-size. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> textHaloWidth(Function<Float> function) { + return new PaintProperty<>("text-halo-width", function); + } + + /** + * The halo's fadeout distance towards the outside. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> textHaloBlur(Float value) { + return new PaintProperty<>("text-halo-blur", value); + } + + /** + * The halo's fadeout distance towards the outside. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> textHaloBlur(Function<Float> function) { + return new PaintProperty<>("text-halo-blur", function); + } + + /** + * Distance that the text's anchor is moved from its original placement. Positive values indicate right and down, + * while negative values indicate left and up. + * + * @param value a Float[] value + * @return property wrapper around Float[] + */ + public static Property<Float[]> textTranslate(Float[] value) { + return new PaintProperty<>("text-translate", value); + } + + /** + * Distance that the text's anchor is moved from its original placement. Positive values indicate right and down, + * while negative values indicate left and up. + * + * @param function a wrapper function for Float[] + * @return property wrapper around a Float[] function + */ + public static Property<Function<Float[]>> textTranslate(Function<Float[]> function) { + return new PaintProperty<>("text-translate", function); + } + + /** + * Controls the translation reference point. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> textTranslateAnchor(@Property.TEXT_TRANSLATE_ANCHOR String value) { + return new PaintProperty<>("text-translate-anchor", value); + } + + /** + * Controls the translation reference point. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> textTranslateAnchor(Function<String> function) { + return new PaintProperty<>("text-translate-anchor", function); + } + + /** + * Circle radius. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> circleRadius(Float value) { + return new PaintProperty<>("circle-radius", value); + } + + /** + * Circle radius. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> circleRadius(Function<Float> function) { + return new PaintProperty<>("circle-radius", function); + } + + /** + * The fill color of the circle. + * + * @param value a int color value + * @return property wrapper around String color + */ + public static Property<String> circleColor(@ColorInt int value) { + return new PaintProperty<>("circle-color", colorToRgbaString(value)); + } + + /** + * The fill color of the circle. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> circleColor(String value) { + return new PaintProperty<>("circle-color", value); + } + + /** + * The fill color of the circle. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> circleColor(Function<String> function) { + return new PaintProperty<>("circle-color", function); + } + + /** + * Amount to blur the circle. 1 blurs the circle such that only the centerpoint is full opacity. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> circleBlur(Float value) { + return new PaintProperty<>("circle-blur", value); + } + + /** + * Amount to blur the circle. 1 blurs the circle such that only the centerpoint is full opacity. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> circleBlur(Function<Float> function) { + return new PaintProperty<>("circle-blur", function); + } + + /** + * The opacity at which the circle will be drawn. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> circleOpacity(Float value) { + return new PaintProperty<>("circle-opacity", value); + } + + /** + * The opacity at which the circle will be drawn. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> circleOpacity(Function<Float> function) { + return new PaintProperty<>("circle-opacity", function); + } + + /** + * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively. + * + * @param value a Float[] value + * @return property wrapper around Float[] + */ + public static Property<Float[]> circleTranslate(Float[] value) { + return new PaintProperty<>("circle-translate", value); + } + + /** + * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively. + * + * @param function a wrapper function for Float[] + * @return property wrapper around a Float[] function + */ + public static Property<Function<Float[]>> circleTranslate(Function<Float[]> function) { + return new PaintProperty<>("circle-translate", function); + } + + /** + * Controls the translation reference point. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> circleTranslateAnchor(@Property.CIRCLE_TRANSLATE_ANCHOR String value) { + return new PaintProperty<>("circle-translate-anchor", value); + } + + /** + * Controls the translation reference point. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> circleTranslateAnchor(Function<String> function) { + return new PaintProperty<>("circle-translate-anchor", function); + } + + /** + * Controls the scaling behavior of the circle when the map is pitched. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> circlePitchScale(@Property.CIRCLE_PITCH_SCALE String value) { + return new PaintProperty<>("circle-pitch-scale", value); + } + + /** + * Controls the scaling behavior of the circle when the map is pitched. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> circlePitchScale(Function<String> function) { + return new PaintProperty<>("circle-pitch-scale", function); + } + + /** + * The width of the circle's stroke. Strokes are placed outside of the "circle-radius". + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> circleStrokeWidth(Float value) { + return new PaintProperty<>("circle-stroke-width", value); + } + + /** + * The width of the circle's stroke. Strokes are placed outside of the "circle-radius". + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> circleStrokeWidth(Function<Float> function) { + return new PaintProperty<>("circle-stroke-width", function); + } + + /** + * The stroke color of the circle. + * + * @param value a int color value + * @return property wrapper around String color + */ + public static Property<String> circleStrokeColor(@ColorInt int value) { + return new PaintProperty<>("circle-stroke-color", colorToRgbaString(value)); + } + + /** + * The stroke color of the circle. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> circleStrokeColor(String value) { + return new PaintProperty<>("circle-stroke-color", value); + } + + /** + * The stroke color of the circle. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> circleStrokeColor(Function<String> function) { + return new PaintProperty<>("circle-stroke-color", function); + } + + /** + * The opacity of the circle's stroke. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> circleStrokeOpacity(Float value) { + return new PaintProperty<>("circle-stroke-opacity", value); + } + + /** + * The opacity of the circle's stroke. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> circleStrokeOpacity(Function<Float> function) { + return new PaintProperty<>("circle-stroke-opacity", function); + } + + /** + * The opacity at which the image will be drawn. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> rasterOpacity(Float value) { + return new PaintProperty<>("raster-opacity", value); + } + + /** + * The opacity at which the image will be drawn. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> rasterOpacity(Function<Float> function) { + return new PaintProperty<>("raster-opacity", function); + } + + /** + * Rotates hues around the color wheel. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> rasterHueRotate(Float value) { + return new PaintProperty<>("raster-hue-rotate", value); + } + + /** + * Rotates hues around the color wheel. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> rasterHueRotate(Function<Float> function) { + return new PaintProperty<>("raster-hue-rotate", function); + } + + /** + * Increase or reduce the brightness of the image. The value is the minimum brightness. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> rasterBrightnessMin(Float value) { + return new PaintProperty<>("raster-brightness-min", value); + } + + /** + * Increase or reduce the brightness of the image. The value is the minimum brightness. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> rasterBrightnessMin(Function<Float> function) { + return new PaintProperty<>("raster-brightness-min", function); + } + + /** + * Increase or reduce the brightness of the image. The value is the maximum brightness. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> rasterBrightnessMax(Float value) { + return new PaintProperty<>("raster-brightness-max", value); + } + + /** + * Increase or reduce the brightness of the image. The value is the maximum brightness. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> rasterBrightnessMax(Function<Float> function) { + return new PaintProperty<>("raster-brightness-max", function); + } + + /** + * Increase or reduce the saturation of the image. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> rasterSaturation(Float value) { + return new PaintProperty<>("raster-saturation", value); + } + + /** + * Increase or reduce the saturation of the image. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> rasterSaturation(Function<Float> function) { + return new PaintProperty<>("raster-saturation", function); + } + + /** + * Increase or reduce the contrast of the image. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> rasterContrast(Float value) { + return new PaintProperty<>("raster-contrast", value); + } + + /** + * Increase or reduce the contrast of the image. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> rasterContrast(Function<Float> function) { + return new PaintProperty<>("raster-contrast", function); + } + + /** + * Fade duration when a new tile is added. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> rasterFadeDuration(Float value) { + return new PaintProperty<>("raster-fade-duration", value); + } + + /** + * Fade duration when a new tile is added. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> rasterFadeDuration(Function<Float> function) { + return new PaintProperty<>("raster-fade-duration", function); + } + + /** + * The color with which the background will be drawn. + * + * @param value a int color value + * @return property wrapper around String color + */ + public static Property<String> backgroundColor(@ColorInt int value) { + return new PaintProperty<>("background-color", colorToRgbaString(value)); + } + + /** + * The color with which the background will be drawn. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> backgroundColor(String value) { + return new PaintProperty<>("background-color", value); + } + + /** + * The color with which the background will be drawn. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> backgroundColor(Function<String> function) { + return new PaintProperty<>("background-color", function); + } + + /** + * Name of image in sprite to use for drawing an image background. For seamless patterns, image width and height must + * be a factor of two (2, 4, 8, ..., 512). + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> backgroundPattern(String value) { + return new PaintProperty<>("background-pattern", value); + } + + /** + * Name of image in sprite to use for drawing an image background. For seamless patterns, image width and height must + * be a factor of two (2, 4, 8, ..., 512). + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> backgroundPattern(Function<String> function) { + return new PaintProperty<>("background-pattern", function); + } + + /** + * The opacity at which the background will be drawn. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> backgroundOpacity(Float value) { + return new PaintProperty<>("background-opacity", value); + } + + /** + * The opacity at which the background will be drawn. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> backgroundOpacity(Function<Float> function) { + return new PaintProperty<>("background-opacity", function); + } + + /** + * The display of line endings. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> lineCap(@Property.LINE_CAP String value) { + return new LayoutProperty<>("line-cap", value); + } + + /** + * The display of line endings. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> lineCap(Function<String> function) { + return new LayoutProperty<>("line-cap", function); + } + + /** + * The display of lines when joining. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> lineJoin(@Property.LINE_JOIN String value) { + return new LayoutProperty<>("line-join", value); + } + + /** + * The display of lines when joining. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> lineJoin(Function<String> function) { + return new LayoutProperty<>("line-join", function); + } + + /** + * Used to automatically convert miter joins to bevel joins for sharp angles. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> lineMiterLimit(Float value) { + return new LayoutProperty<>("line-miter-limit", value); + } + + /** + * Used to automatically convert miter joins to bevel joins for sharp angles. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> lineMiterLimit(Function<Float> function) { + return new LayoutProperty<>("line-miter-limit", function); + } + + /** + * Used to automatically convert round joins to miter joins for shallow angles. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> lineRoundLimit(Float value) { + return new LayoutProperty<>("line-round-limit", value); + } + + /** + * Used to automatically convert round joins to miter joins for shallow angles. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> lineRoundLimit(Function<Float> function) { + return new LayoutProperty<>("line-round-limit", function); + } + + /** + * Label placement relative to its geometry. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> symbolPlacement(@Property.SYMBOL_PLACEMENT String value) { + return new LayoutProperty<>("symbol-placement", value); + } + + /** + * Label placement relative to its geometry. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> symbolPlacement(Function<String> function) { + return new LayoutProperty<>("symbol-placement", function); + } + + /** + * Distance between two symbol anchors. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> symbolSpacing(Float value) { + return new LayoutProperty<>("symbol-spacing", value); + } + + /** + * Distance between two symbol anchors. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> symbolSpacing(Function<Float> function) { + return new LayoutProperty<>("symbol-spacing", function); + } + + /** + * If true, the symbols will not cross tile edges to avoid mutual collisions. Recommended in layers that don't have + * enough padding in the vector tile to prevent collisions, or if it is a point symbol layer placed after a line + * symbol layer. + * + * @param value a Boolean value + * @return property wrapper around Boolean + */ + public static Property<Boolean> symbolAvoidEdges(Boolean value) { + return new LayoutProperty<>("symbol-avoid-edges", value); + } + + /** + * If true, the symbols will not cross tile edges to avoid mutual collisions. Recommended in layers that don't have + * enough padding in the vector tile to prevent collisions, or if it is a point symbol layer placed after a line + * symbol layer. + * + * @param function a wrapper function for Boolean + * @return property wrapper around a Boolean function + */ + public static Property<Function<Boolean>> symbolAvoidEdges(Function<Boolean> function) { + return new LayoutProperty<>("symbol-avoid-edges", function); + } + + /** + * If true, the icon will be visible even if it collides with other previously drawn symbols. + * + * @param value a Boolean value + * @return property wrapper around Boolean + */ + public static Property<Boolean> iconAllowOverlap(Boolean value) { + return new LayoutProperty<>("icon-allow-overlap", value); + } + + /** + * If true, the icon will be visible even if it collides with other previously drawn symbols. + * + * @param function a wrapper function for Boolean + * @return property wrapper around a Boolean function + */ + public static Property<Function<Boolean>> iconAllowOverlap(Function<Boolean> function) { + return new LayoutProperty<>("icon-allow-overlap", function); + } + + /** + * If true, other symbols can be visible even if they collide with the icon. + * + * @param value a Boolean value + * @return property wrapper around Boolean + */ + public static Property<Boolean> iconIgnorePlacement(Boolean value) { + return new LayoutProperty<>("icon-ignore-placement", value); + } + + /** + * If true, other symbols can be visible even if they collide with the icon. + * + * @param function a wrapper function for Boolean + * @return property wrapper around a Boolean function + */ + public static Property<Function<Boolean>> iconIgnorePlacement(Function<Boolean> function) { + return new LayoutProperty<>("icon-ignore-placement", function); + } + + /** + * If true, text will display without their corresponding icons when the icon collides with other symbols and the + * text does not. + * + * @param value a Boolean value + * @return property wrapper around Boolean + */ + public static Property<Boolean> iconOptional(Boolean value) { + return new LayoutProperty<>("icon-optional", value); + } + + /** + * If true, text will display without their corresponding icons when the icon collides with other symbols and the + * text does not. + * + * @param function a wrapper function for Boolean + * @return property wrapper around a Boolean function + */ + public static Property<Function<Boolean>> iconOptional(Function<Boolean> function) { + return new LayoutProperty<>("icon-optional", function); + } + + /** + * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of icons. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> iconRotationAlignment(@Property.ICON_ROTATION_ALIGNMENT String value) { + return new LayoutProperty<>("icon-rotation-alignment", value); + } + + /** + * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of icons. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> iconRotationAlignment(Function<String> function) { + return new LayoutProperty<>("icon-rotation-alignment", function); + } + + /** + * Scale factor for icon. 1 is original size, 3 triples the size. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> iconSize(Float value) { + return new LayoutProperty<>("icon-size", value); + } + + /** + * Scale factor for icon. 1 is original size, 3 triples the size. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> iconSize(Function<Float> function) { + return new LayoutProperty<>("icon-size", function); + } + + /** + * Scales the icon to fit around the associated text. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> iconTextFit(@Property.ICON_TEXT_FIT String value) { + return new LayoutProperty<>("icon-text-fit", value); + } + + /** + * Scales the icon to fit around the associated text. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> iconTextFit(Function<String> function) { + return new LayoutProperty<>("icon-text-fit", function); + } + + /** + * Size of the additional area added to dimensions determined by {@link Property.ICON_TEXT_FIT}, in clockwise order: + * top, right, bottom, left. + * + * @param value a Float[] value + * @return property wrapper around Float[] + */ + public static Property<Float[]> iconTextFitPadding(Float[] value) { + return new LayoutProperty<>("icon-text-fit-padding", value); + } + + /** + * Size of the additional area added to dimensions determined by {@link Property.ICON_TEXT_FIT}, in clockwise order: + * top, right, bottom, left. + * + * @param function a wrapper function for Float[] + * @return property wrapper around a Float[] function + */ + public static Property<Function<Float[]>> iconTextFitPadding(Function<Float[]> function) { + return new LayoutProperty<>("icon-text-fit-padding", function); + } + + /** + * A string with {tokens} replaced, referencing the data property to pull from. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> iconImage(String value) { + return new LayoutProperty<>("icon-image", value); + } + + /** + * A string with {tokens} replaced, referencing the data property to pull from. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> iconImage(Function<String> function) { + return new LayoutProperty<>("icon-image", function); + } + + /** + * Rotates the icon clockwise. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> iconRotate(Float value) { + return new LayoutProperty<>("icon-rotate", value); + } + + /** + * Rotates the icon clockwise. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> iconRotate(Function<Float> function) { + return new LayoutProperty<>("icon-rotate", function); + } + + /** + * Size of the additional area around the icon bounding box used for detecting symbol collisions. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> iconPadding(Float value) { + return new LayoutProperty<>("icon-padding", value); + } + + /** + * Size of the additional area around the icon bounding box used for detecting symbol collisions. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> iconPadding(Function<Float> function) { + return new LayoutProperty<>("icon-padding", function); + } + + /** + * If true, the icon may be flipped to prevent it from being rendered upside-down. + * + * @param value a Boolean value + * @return property wrapper around Boolean + */ + public static Property<Boolean> iconKeepUpright(Boolean value) { + return new LayoutProperty<>("icon-keep-upright", value); + } + + /** + * If true, the icon may be flipped to prevent it from being rendered upside-down. + * + * @param function a wrapper function for Boolean + * @return property wrapper around a Boolean function + */ + public static Property<Function<Boolean>> iconKeepUpright(Function<Boolean> function) { + return new LayoutProperty<>("icon-keep-upright", function); + } + + /** + * Offset distance of icon from its anchor. Positive values indicate right and down, while negative values indicate + * left and up. + * + * @param value a Float[] value + * @return property wrapper around Float[] + */ + public static Property<Float[]> iconOffset(Float[] value) { + return new LayoutProperty<>("icon-offset", value); + } + + /** + * Offset distance of icon from its anchor. Positive values indicate right and down, while negative values indicate + * left and up. + * + * @param function a wrapper function for Float[] + * @return property wrapper around a Float[] function + */ + public static Property<Function<Float[]>> iconOffset(Function<Float[]> function) { + return new LayoutProperty<>("icon-offset", function); + } + + /** + * Orientation of text when map is pitched. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> textPitchAlignment(@Property.TEXT_PITCH_ALIGNMENT String value) { + return new LayoutProperty<>("text-pitch-alignment", value); + } + + /** + * Orientation of text when map is pitched. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> textPitchAlignment(Function<String> function) { + return new LayoutProperty<>("text-pitch-alignment", function); + } + + /** + * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of the individual glyphs + * forming the text. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> textRotationAlignment(@Property.TEXT_ROTATION_ALIGNMENT String value) { + return new LayoutProperty<>("text-rotation-alignment", value); + } + + /** + * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of the individual glyphs + * forming the text. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> textRotationAlignment(Function<String> function) { + return new LayoutProperty<>("text-rotation-alignment", function); + } + + /** + * Value to use for a text label. Feature properties are specified using tokens like {field_name}. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> textField(String value) { + return new LayoutProperty<>("text-field", value); + } + + /** + * Value to use for a text label. Feature properties are specified using tokens like {field_name}. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> textField(Function<String> function) { + return new LayoutProperty<>("text-field", function); + } + + /** + * Font stack to use for displaying text. + * + * @param value a String[] value + * @return property wrapper around String[] + */ + public static Property<String[]> textFont(String[] value) { + return new LayoutProperty<>("text-font", value); + } + + /** + * Font stack to use for displaying text. + * + * @param function a wrapper function for String[] + * @return property wrapper around a String[] function + */ + public static Property<Function<String[]>> textFont(Function<String[]> function) { + return new LayoutProperty<>("text-font", function); + } + + /** + * Font size. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> textSize(Float value) { + return new LayoutProperty<>("text-size", value); + } + + /** + * Font size. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> textSize(Function<Float> function) { + return new LayoutProperty<>("text-size", function); + } + + /** + * The maximum line width for text wrapping. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> textMaxWidth(Float value) { + return new LayoutProperty<>("text-max-width", value); + } + + /** + * The maximum line width for text wrapping. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> textMaxWidth(Function<Float> function) { + return new LayoutProperty<>("text-max-width", function); + } + + /** + * Text leading value for multi-line text. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> textLineHeight(Float value) { + return new LayoutProperty<>("text-line-height", value); + } + + /** + * Text leading value for multi-line text. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> textLineHeight(Function<Float> function) { + return new LayoutProperty<>("text-line-height", function); + } + + /** + * Text tracking amount. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> textLetterSpacing(Float value) { + return new LayoutProperty<>("text-letter-spacing", value); + } + + /** + * Text tracking amount. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> textLetterSpacing(Function<Float> function) { + return new LayoutProperty<>("text-letter-spacing", function); + } + + /** + * Text justification options. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> textJustify(@Property.TEXT_JUSTIFY String value) { + return new LayoutProperty<>("text-justify", value); + } + + /** + * Text justification options. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> textJustify(Function<String> function) { + return new LayoutProperty<>("text-justify", function); + } + + /** + * Part of the text placed closest to the anchor. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> textAnchor(@Property.TEXT_ANCHOR String value) { + return new LayoutProperty<>("text-anchor", value); + } + + /** + * Part of the text placed closest to the anchor. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> textAnchor(Function<String> function) { + return new LayoutProperty<>("text-anchor", function); + } + + /** + * Maximum angle change between adjacent characters. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> textMaxAngle(Float value) { + return new LayoutProperty<>("text-max-angle", value); + } + + /** + * Maximum angle change between adjacent characters. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> textMaxAngle(Function<Float> function) { + return new LayoutProperty<>("text-max-angle", function); + } + + /** + * Rotates the text clockwise. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> textRotate(Float value) { + return new LayoutProperty<>("text-rotate", value); + } + + /** + * Rotates the text clockwise. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> textRotate(Function<Float> function) { + return new LayoutProperty<>("text-rotate", function); + } + + /** + * Size of the additional area around the text bounding box used for detecting symbol collisions. + * + * @param value a Float value + * @return property wrapper around Float + */ + public static Property<Float> textPadding(Float value) { + return new LayoutProperty<>("text-padding", value); + } + + /** + * Size of the additional area around the text bounding box used for detecting symbol collisions. + * + * @param function a wrapper function for Float + * @return property wrapper around a Float function + */ + public static Property<Function<Float>> textPadding(Function<Float> function) { + return new LayoutProperty<>("text-padding", function); + } + + /** + * If true, the text may be flipped vertically to prevent it from being rendered upside-down. + * + * @param value a Boolean value + * @return property wrapper around Boolean + */ + public static Property<Boolean> textKeepUpright(Boolean value) { + return new LayoutProperty<>("text-keep-upright", value); + } + + /** + * If true, the text may be flipped vertically to prevent it from being rendered upside-down. + * + * @param function a wrapper function for Boolean + * @return property wrapper around a Boolean function + */ + public static Property<Function<Boolean>> textKeepUpright(Function<Boolean> function) { + return new LayoutProperty<>("text-keep-upright", function); + } + + /** + * Specifies how to capitalize text, similar to the CSS {@link PropertyFactory#textTransform} property. + * + * @param value a String value + * @return property wrapper around String + */ + public static Property<String> textTransform(@Property.TEXT_TRANSFORM String value) { + return new LayoutProperty<>("text-transform", value); + } + + /** + * Specifies how to capitalize text, similar to the CSS {@link PropertyFactory#textTransform} property. + * + * @param function a wrapper function for String + * @return property wrapper around a String function + */ + public static Property<Function<String>> textTransform(Function<String> function) { + return new LayoutProperty<>("text-transform", function); + } + + /** + * Offset distance of text from its anchor. Positive values indicate right and down, while negative values indicate + * left and up. + * + * @param value a Float[] value + * @return property wrapper around Float[] + */ + public static Property<Float[]> textOffset(Float[] value) { + return new LayoutProperty<>("text-offset", value); + } + + /** + * Offset distance of text from its anchor. Positive values indicate right and down, while negative values indicate + * left and up. + * + * @param function a wrapper function for Float[] + * @return property wrapper around a Float[] function + */ + public static Property<Function<Float[]>> textOffset(Function<Float[]> function) { + return new LayoutProperty<>("text-offset", function); + } + + /** + * If true, the text will be visible even if it collides with other previously drawn symbols. + * + * @param value a Boolean value + * @return property wrapper around Boolean + */ + public static Property<Boolean> textAllowOverlap(Boolean value) { + return new LayoutProperty<>("text-allow-overlap", value); + } + + /** + * If true, the text will be visible even if it collides with other previously drawn symbols. + * + * @param function a wrapper function for Boolean + * @return property wrapper around a Boolean function + */ + public static Property<Function<Boolean>> textAllowOverlap(Function<Boolean> function) { + return new LayoutProperty<>("text-allow-overlap", function); + } + + /** + * If true, other symbols can be visible even if they collide with the text. + * + * @param value a Boolean value + * @return property wrapper around Boolean + */ + public static Property<Boolean> textIgnorePlacement(Boolean value) { + return new LayoutProperty<>("text-ignore-placement", value); + } + + /** + * If true, other symbols can be visible even if they collide with the text. + * + * @param function a wrapper function for Boolean + * @return property wrapper around a Boolean function + */ + public static Property<Function<Boolean>> textIgnorePlacement(Function<Boolean> function) { + return new LayoutProperty<>("text-ignore-placement", function); + } + + /** + * If true, icons will display without their corresponding text when the text collides with other symbols and the + * icon does not. + * + * @param value a Boolean value + * @return property wrapper around Boolean + */ + public static Property<Boolean> textOptional(Boolean value) { + return new LayoutProperty<>("text-optional", value); + } + + /** + * If true, icons will display without their corresponding text when the text collides with other symbols and the + * icon does not. + * + * @param function a wrapper function for Boolean + * @return property wrapper around a Boolean function + */ + public static Property<Function<Boolean>> textOptional(Function<Boolean> function) { + return new LayoutProperty<>("text-optional", function); + } + + @SuppressLint("DefaultLocale") + static String colorToRgbaString(@ColorInt int value) { + return String.format("rgba(%d, %d, %d, %d)", (value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF, + (value >> 24) & 0xFF); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java index 542ec46e1f..c404f07c76 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java @@ -1,6 +1,7 @@ package com.mapbox.mapboxsdk.style.layers; import android.support.annotation.Nullable; + import timber.log.Timber; /** @@ -8,48 +9,49 @@ import timber.log.Timber; */ public class PropertyValue<T> { - private final Object value; + private final Object value; - /* package */ PropertyValue(Object value) { - this.value = value; - } + /* package */ PropertyValue(Object value) { + this.value = value; + } - public boolean isNull() { - return value == null; - } + public boolean isNull() { + return value == null; + } - public boolean isFunction() { - return !isNull() && value instanceof Function; - } + public boolean isFunction() { + return !isNull() && value instanceof Function; + } - public boolean isValue() { - return !isNull() && !isFunction(); - } + public boolean isValue() { + return !isNull() && !isFunction(); + } - @Nullable - public Function<T> getFunction() { - if (isFunction()) { - //noinspection unchecked - return (Function<T>) value; - } else { - Timber.w("not a function, try value"); - return null; - } + @Nullable + public Function<T> getFunction() { + if (isFunction()) { + //noinspection unchecked + return (Function<T>) value; + } else { + Timber.w("not a function, try value"); + return null; } - - @Nullable - public T getValue() { - if (isValue()) { - //noinspection unchecked - return (T) value; - } else { - Timber.w("not a value, try function"); - return null; - } + } + + @Nullable + public T getValue() { + if (isValue()) { + //noinspection unchecked + return (T) value; + } else { + Timber.w("not a value, try function"); + return null; } + } - @Override - public String toString() { - return String.format("%s (%s)", getClass().getSimpleName(), value != null ? value.getClass().getSimpleName() : null); - } + @Override + public String toString() { + return String.format("%s (%s)", getClass().getSimpleName(), value != null + ? value.getClass().getSimpleName() : null); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/RasterLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/RasterLayer.java index 115bab26ef..785106c394 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/RasterLayer.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/RasterLayer.java @@ -1,12 +1,8 @@ -// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. package com.mapbox.mapboxsdk.style.layers; +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. -import android.support.annotation.UiThread; - -import android.support.annotation.ColorInt; import android.support.annotation.NonNull; - -import static com.mapbox.mapboxsdk.utils.ColorUtils.*; +import android.support.annotation.UiThread; /** * Raster map textures such as satellite imagery. @@ -16,146 +12,146 @@ import static com.mapbox.mapboxsdk.utils.ColorUtils.*; @UiThread public class RasterLayer extends Layer { - /** - * Creates a RasterLayer. - * - * @param nativePtr pointer used by core - */ - public RasterLayer(long nativePtr) { - super(nativePtr); - } - - /** - * Creates a RasterLayer. - * - * @param layerId the id of the layer - * @param sourceId the id of the source - */ - public RasterLayer(String layerId, String sourceId) { - initialize(layerId, sourceId); - } - - protected native void initialize(String layerId, String sourceId); - - /** - * Set the source layer. - * - * @param sourceLayer the source layer to set - */ - public void setSourceLayer(String sourceLayer) { - nativeSetSourceLayer(sourceLayer); - } - - /** - * Set the source Layer. - * - * @param sourceLayer the source layer to set - * @return This - */ - public RasterLayer withSourceLayer(String sourceLayer) { - setSourceLayer(sourceLayer); - return this; - } - - /** - * Set a property or properties. - * - * @param properties the var-args properties - * @return This - */ - public RasterLayer withProperties(@NonNull Property<?>... properties) { - setProperties(properties); - return this; - } - - // Property getters - - /** - * Get the RasterOpacity property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getRasterOpacity() { - return (PropertyValue<Float>) new PropertyValue(nativeGetRasterOpacity()); - } - - /** - * Get the RasterHueRotate property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getRasterHueRotate() { - return (PropertyValue<Float>) new PropertyValue(nativeGetRasterHueRotate()); - } - - /** - * Get the RasterBrightnessMin property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getRasterBrightnessMin() { - return (PropertyValue<Float>) new PropertyValue(nativeGetRasterBrightnessMin()); - } - - /** - * Get the RasterBrightnessMax property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getRasterBrightnessMax() { - return (PropertyValue<Float>) new PropertyValue(nativeGetRasterBrightnessMax()); - } - - /** - * Get the RasterSaturation property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getRasterSaturation() { - return (PropertyValue<Float>) new PropertyValue(nativeGetRasterSaturation()); - } - - /** - * Get the RasterContrast property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getRasterContrast() { - return (PropertyValue<Float>) new PropertyValue(nativeGetRasterContrast()); - } - - /** - * Get the RasterFadeDuration property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getRasterFadeDuration() { - return (PropertyValue<Float>) new PropertyValue(nativeGetRasterFadeDuration()); - } - - private native Object nativeGetRasterOpacity(); - - private native Object nativeGetRasterHueRotate(); - - private native Object nativeGetRasterBrightnessMin(); - - private native Object nativeGetRasterBrightnessMax(); - - private native Object nativeGetRasterSaturation(); - - private native Object nativeGetRasterContrast(); - - private native Object nativeGetRasterFadeDuration(); - - - @Override - protected native void finalize() throws Throwable; + /** + * Creates a RasterLayer. + * + * @param nativePtr pointer used by core + */ + public RasterLayer(long nativePtr) { + super(nativePtr); + } + + /** + * Creates a RasterLayer. + * + * @param layerId the id of the layer + * @param sourceId the id of the source + */ + public RasterLayer(String layerId, String sourceId) { + initialize(layerId, sourceId); + } + + protected native void initialize(String layerId, String sourceId); + + /** + * Set the source layer. + * + * @param sourceLayer the source layer to set + */ + public void setSourceLayer(String sourceLayer) { + nativeSetSourceLayer(sourceLayer); + } + + /** + * Set the source Layer. + * + * @param sourceLayer the source layer to set + * @return This + */ + public RasterLayer withSourceLayer(String sourceLayer) { + setSourceLayer(sourceLayer); + return this; + } + + /** + * Set a property or properties. + * + * @param properties the var-args properties + * @return This + */ + public RasterLayer withProperties(@NonNull Property<?>... properties) { + setProperties(properties); + return this; + } + + // Property getters + + /** + * Get the RasterOpacity property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getRasterOpacity() { + return (PropertyValue<Float>) new PropertyValue(nativeGetRasterOpacity()); + } + + /** + * Get the RasterHueRotate property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getRasterHueRotate() { + return (PropertyValue<Float>) new PropertyValue(nativeGetRasterHueRotate()); + } + + /** + * Get the RasterBrightnessMin property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getRasterBrightnessMin() { + return (PropertyValue<Float>) new PropertyValue(nativeGetRasterBrightnessMin()); + } + + /** + * Get the RasterBrightnessMax property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getRasterBrightnessMax() { + return (PropertyValue<Float>) new PropertyValue(nativeGetRasterBrightnessMax()); + } + + /** + * Get the RasterSaturation property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getRasterSaturation() { + return (PropertyValue<Float>) new PropertyValue(nativeGetRasterSaturation()); + } + + /** + * Get the RasterContrast property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getRasterContrast() { + return (PropertyValue<Float>) new PropertyValue(nativeGetRasterContrast()); + } + + /** + * Get the RasterFadeDuration property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getRasterFadeDuration() { + return (PropertyValue<Float>) new PropertyValue(nativeGetRasterFadeDuration()); + } + + private native Object nativeGetRasterOpacity(); + + private native Object nativeGetRasterHueRotate(); + + private native Object nativeGetRasterBrightnessMin(); + + private native Object nativeGetRasterBrightnessMax(); + + private native Object nativeGetRasterSaturation(); + + private native Object nativeGetRasterContrast(); + + private native Object nativeGetRasterFadeDuration(); + + + @Override + protected native void finalize() throws Throwable; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java index 7ed8d5e69a..abc516d6d0 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java @@ -1,12 +1,11 @@ -// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. package com.mapbox.mapboxsdk.style.layers; - -import android.support.annotation.UiThread; +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`. import android.support.annotation.ColorInt; import android.support.annotation.NonNull; +import android.support.annotation.UiThread; -import static com.mapbox.mapboxsdk.utils.ColorUtils.*; +import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor; /** * An icon or a text label. @@ -16,742 +15,747 @@ import static com.mapbox.mapboxsdk.utils.ColorUtils.*; @UiThread public class SymbolLayer extends Layer { - /** - * Creates a SymbolLayer. - * - * @param nativePtr pointer used by core - */ - public SymbolLayer(long nativePtr) { - super(nativePtr); - } - - /** - * Creates a SymbolLayer. - * - * @param layerId the id of the layer - * @param sourceId the id of the source - */ - public SymbolLayer(String layerId, String sourceId) { - initialize(layerId, sourceId); - } - - protected native void initialize(String layerId, String sourceId); - - /** - * Set the source layer. - * - * @param sourceLayer the source layer to set - */ - public void setSourceLayer(String sourceLayer) { - nativeSetSourceLayer(sourceLayer); - } - - /** - * Set the source Layer. - * - * @param sourceLayer the source layer to set - * @return This - */ - public SymbolLayer withSourceLayer(String sourceLayer) { - setSourceLayer(sourceLayer); - return this; - } - /** - * Set a single filter. - * - * @param filter the filter to set - */ - public void setFilter(Filter.Statement filter) { - this.setFilter(filter.toArray()); - } - - /** - * Set an array of filters. - * - * @param filter the filter array to set - */ - public void setFilter(Object[] filter) { - nativeSetFilter(filter); - } + /** + * Creates a SymbolLayer. + * + * @param nativePtr pointer used by core + */ + public SymbolLayer(long nativePtr) { + super(nativePtr); + } + + /** + * Creates a SymbolLayer. + * + * @param layerId the id of the layer + * @param sourceId the id of the source + */ + public SymbolLayer(String layerId, String sourceId) { + initialize(layerId, sourceId); + } + + protected native void initialize(String layerId, String sourceId); + + /** + * Set the source layer. + * + * @param sourceLayer the source layer to set + */ + public void setSourceLayer(String sourceLayer) { + nativeSetSourceLayer(sourceLayer); + } + + /** + * Set the source Layer. + * + * @param sourceLayer the source layer to set + * @return This + */ + public SymbolLayer withSourceLayer(String sourceLayer) { + setSourceLayer(sourceLayer); + return this; + } + + /** + * Set a single filter. + * + * @param filter the filter to set + */ + public void setFilter(Filter.Statement filter) { + this.setFilter(filter.toArray()); + } + + /** + * Set an array of filters. + * + * @param filter the filter array to set + */ + public void setFilter(Object[] filter) { + nativeSetFilter(filter); + } + + /** + * Set an array of filters. + * + * @param filter tthe filter array to set + * @return This + */ + public SymbolLayer withFilter(Object[] filter) { + setFilter(filter); + return this; + } + + /** + * Set a single filter. + * + * @param filter the filter to set + * @return This + */ + public SymbolLayer withFilter(Filter.Statement filter) { + setFilter(filter); + return this; + } + + + /** + * Set a property or properties. + * + * @param properties the var-args properties + * @return This + */ + public SymbolLayer withProperties(@NonNull Property<?>... properties) { + setProperties(properties); + return this; + } + + // Property getters + + /** + * Get the SymbolPlacement property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getSymbolPlacement() { + return (PropertyValue<String>) new PropertyValue(nativeGetSymbolPlacement()); + } + + /** + * Get the SymbolSpacing property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getSymbolSpacing() { + return (PropertyValue<Float>) new PropertyValue(nativeGetSymbolSpacing()); + } + + /** + * Get the SymbolAvoidEdges property + * + * @return property wrapper value around Boolean + */ + @SuppressWarnings("unchecked") + public PropertyValue<Boolean> getSymbolAvoidEdges() { + return (PropertyValue<Boolean>) new PropertyValue(nativeGetSymbolAvoidEdges()); + } + + /** + * Get the IconAllowOverlap property + * + * @return property wrapper value around Boolean + */ + @SuppressWarnings("unchecked") + public PropertyValue<Boolean> getIconAllowOverlap() { + return (PropertyValue<Boolean>) new PropertyValue(nativeGetIconAllowOverlap()); + } + + /** + * Get the IconIgnorePlacement property + * + * @return property wrapper value around Boolean + */ + @SuppressWarnings("unchecked") + public PropertyValue<Boolean> getIconIgnorePlacement() { + return (PropertyValue<Boolean>) new PropertyValue(nativeGetIconIgnorePlacement()); + } + + /** + * Get the IconOptional property + * + * @return property wrapper value around Boolean + */ + @SuppressWarnings("unchecked") + public PropertyValue<Boolean> getIconOptional() { + return (PropertyValue<Boolean>) new PropertyValue(nativeGetIconOptional()); + } + + /** + * Get the IconRotationAlignment property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getIconRotationAlignment() { + return (PropertyValue<String>) new PropertyValue(nativeGetIconRotationAlignment()); + } + + /** + * Get the IconSize property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getIconSize() { + return (PropertyValue<Float>) new PropertyValue(nativeGetIconSize()); + } + + /** + * Get the IconTextFit property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getIconTextFit() { + return (PropertyValue<String>) new PropertyValue(nativeGetIconTextFit()); + } + + /** + * Get the IconTextFitPadding property + * + * @return property wrapper value around Float[] + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float[]> getIconTextFitPadding() { + return (PropertyValue<Float[]>) new PropertyValue(nativeGetIconTextFitPadding()); + } + + /** + * Get the IconImage property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getIconImage() { + return (PropertyValue<String>) new PropertyValue(nativeGetIconImage()); + } + + /** + * Get the IconRotate property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getIconRotate() { + return (PropertyValue<Float>) new PropertyValue(nativeGetIconRotate()); + } + + /** + * Get the IconPadding property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getIconPadding() { + return (PropertyValue<Float>) new PropertyValue(nativeGetIconPadding()); + } + + /** + * Get the IconKeepUpright property + * + * @return property wrapper value around Boolean + */ + @SuppressWarnings("unchecked") + public PropertyValue<Boolean> getIconKeepUpright() { + return (PropertyValue<Boolean>) new PropertyValue(nativeGetIconKeepUpright()); + } + + /** + * Get the IconOffset property + * + * @return property wrapper value around Float[] + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float[]> getIconOffset() { + return (PropertyValue<Float[]>) new PropertyValue(nativeGetIconOffset()); + } + + /** + * Get the TextPitchAlignment property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getTextPitchAlignment() { + return (PropertyValue<String>) new PropertyValue(nativeGetTextPitchAlignment()); + } + + /** + * Get the TextRotationAlignment property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getTextRotationAlignment() { + return (PropertyValue<String>) new PropertyValue(nativeGetTextRotationAlignment()); + } + + /** + * Get the TextField property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getTextField() { + return (PropertyValue<String>) new PropertyValue(nativeGetTextField()); + } + + /** + * Get the TextFont property + * + * @return property wrapper value around String[] + */ + @SuppressWarnings("unchecked") + public PropertyValue<String[]> getTextFont() { + return (PropertyValue<String[]>) new PropertyValue(nativeGetTextFont()); + } + + /** + * Get the TextSize property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getTextSize() { + return (PropertyValue<Float>) new PropertyValue(nativeGetTextSize()); + } + + /** + * Get the TextMaxWidth property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getTextMaxWidth() { + return (PropertyValue<Float>) new PropertyValue(nativeGetTextMaxWidth()); + } + + /** + * Get the TextLineHeight property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getTextLineHeight() { + return (PropertyValue<Float>) new PropertyValue(nativeGetTextLineHeight()); + } + + /** + * Get the TextLetterSpacing property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getTextLetterSpacing() { + return (PropertyValue<Float>) new PropertyValue(nativeGetTextLetterSpacing()); + } + + /** + * Get the TextJustify property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getTextJustify() { + return (PropertyValue<String>) new PropertyValue(nativeGetTextJustify()); + } + + /** + * Get the TextAnchor property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getTextAnchor() { + return (PropertyValue<String>) new PropertyValue(nativeGetTextAnchor()); + } + + /** + * Get the TextMaxAngle property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getTextMaxAngle() { + return (PropertyValue<Float>) new PropertyValue(nativeGetTextMaxAngle()); + } + + /** + * Get the TextRotate property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getTextRotate() { + return (PropertyValue<Float>) new PropertyValue(nativeGetTextRotate()); + } + + /** + * Get the TextPadding property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getTextPadding() { + return (PropertyValue<Float>) new PropertyValue(nativeGetTextPadding()); + } + + /** + * Get the TextKeepUpright property + * + * @return property wrapper value around Boolean + */ + @SuppressWarnings("unchecked") + public PropertyValue<Boolean> getTextKeepUpright() { + return (PropertyValue<Boolean>) new PropertyValue(nativeGetTextKeepUpright()); + } + + /** + * Get the TextTransform property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getTextTransform() { + return (PropertyValue<String>) new PropertyValue(nativeGetTextTransform()); + } + + /** + * Get the TextOffset property + * + * @return property wrapper value around Float[] + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float[]> getTextOffset() { + return (PropertyValue<Float[]>) new PropertyValue(nativeGetTextOffset()); + } + + /** + * Get the TextAllowOverlap property + * + * @return property wrapper value around Boolean + */ + @SuppressWarnings("unchecked") + public PropertyValue<Boolean> getTextAllowOverlap() { + return (PropertyValue<Boolean>) new PropertyValue(nativeGetTextAllowOverlap()); + } + + /** + * Get the TextIgnorePlacement property + * + * @return property wrapper value around Boolean + */ + @SuppressWarnings("unchecked") + public PropertyValue<Boolean> getTextIgnorePlacement() { + return (PropertyValue<Boolean>) new PropertyValue(nativeGetTextIgnorePlacement()); + } + + /** + * Get the TextOptional property + * + * @return property wrapper value around Boolean + */ + @SuppressWarnings("unchecked") + public PropertyValue<Boolean> getTextOptional() { + return (PropertyValue<Boolean>) new PropertyValue(nativeGetTextOptional()); + } + + /** + * Get the IconOpacity property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getIconOpacity() { + return (PropertyValue<Float>) new PropertyValue(nativeGetIconOpacity()); + } + + /** + * Get the IconColor property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getIconColor() { + return (PropertyValue<String>) new PropertyValue(nativeGetIconColor()); + } + + /** + * The color of the icon. This can only be used with sdf icons. + * + * @return int representation of a rgba string color + * @throws RuntimeException thrown if property isn't a value + */ + @ColorInt + public int getIconColorAsInt() { + PropertyValue<String> value = getIconColor(); + if (value.isValue()) { + return rgbaToColor(value.getValue()); + } else { + throw new RuntimeException("icon-color was set as a Function"); + } + } + + + /** + * Get the IconHaloColor property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getIconHaloColor() { + return (PropertyValue<String>) new PropertyValue(nativeGetIconHaloColor()); + } + + /** + * The color of the icon's halo. Icon halos can only be used with SDF icons. + * + * @return int representation of a rgba string color + * @throws RuntimeException thrown if property isn't a value + */ + @ColorInt + public int getIconHaloColorAsInt() { + PropertyValue<String> value = getIconHaloColor(); + if (value.isValue()) { + return rgbaToColor(value.getValue()); + } else { + throw new RuntimeException("icon-halo-color was set as a Function"); + } + } + + + /** + * Get the IconHaloWidth property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getIconHaloWidth() { + return (PropertyValue<Float>) new PropertyValue(nativeGetIconHaloWidth()); + } + + /** + * Get the IconHaloBlur property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getIconHaloBlur() { + return (PropertyValue<Float>) new PropertyValue(nativeGetIconHaloBlur()); + } + + /** + * Get the IconTranslate property + * + * @return property wrapper value around Float[] + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float[]> getIconTranslate() { + return (PropertyValue<Float[]>) new PropertyValue(nativeGetIconTranslate()); + } + + /** + * Get the IconTranslateAnchor property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getIconTranslateAnchor() { + return (PropertyValue<String>) new PropertyValue(nativeGetIconTranslateAnchor()); + } + + /** + * Get the TextOpacity property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getTextOpacity() { + return (PropertyValue<Float>) new PropertyValue(nativeGetTextOpacity()); + } + + /** + * Get the TextColor property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getTextColor() { + return (PropertyValue<String>) new PropertyValue(nativeGetTextColor()); + } + + /** + * The color with which the text will be drawn. + * + * @return int representation of a rgba string color + * @throws RuntimeException thrown if property isn't a value + */ + @ColorInt + public int getTextColorAsInt() { + PropertyValue<String> value = getTextColor(); + if (value.isValue()) { + return rgbaToColor(value.getValue()); + } else { + throw new RuntimeException("text-color was set as a Function"); + } + } + + + /** + * Get the TextHaloColor property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getTextHaloColor() { + return (PropertyValue<String>) new PropertyValue(nativeGetTextHaloColor()); + } + + /** + * The color of the text's halo, which helps it stand out from backgrounds. + * + * @return int representation of a rgba string color + * @throws RuntimeException thrown if property isn't a value + */ + @ColorInt + public int getTextHaloColorAsInt() { + PropertyValue<String> value = getTextHaloColor(); + if (value.isValue()) { + return rgbaToColor(value.getValue()); + } else { + throw new RuntimeException("text-halo-color was set as a Function"); + } + } + + + /** + * Get the TextHaloWidth property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getTextHaloWidth() { + return (PropertyValue<Float>) new PropertyValue(nativeGetTextHaloWidth()); + } - /** - * Set an array of filters. - * - * @param filter tthe filter array to set - * @return This - */ - public SymbolLayer withFilter(Object[] filter) { - setFilter(filter); - return this; - } + /** + * Get the TextHaloBlur property + * + * @return property wrapper value around Float + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float> getTextHaloBlur() { + return (PropertyValue<Float>) new PropertyValue(nativeGetTextHaloBlur()); + } - /** - * Set a single filter. - * - * @param filter the filter to set - * @return This - */ - public SymbolLayer withFilter(Filter.Statement filter) { - setFilter(filter); - return this; - } + /** + * Get the TextTranslate property + * + * @return property wrapper value around Float[] + */ + @SuppressWarnings("unchecked") + public PropertyValue<Float[]> getTextTranslate() { + return (PropertyValue<Float[]>) new PropertyValue(nativeGetTextTranslate()); + } + /** + * Get the TextTranslateAnchor property + * + * @return property wrapper value around String + */ + @SuppressWarnings("unchecked") + public PropertyValue<String> getTextTranslateAnchor() { + return (PropertyValue<String>) new PropertyValue(nativeGetTextTranslateAnchor()); + } - /** - * Set a property or properties. - * - * @param properties the var-args properties - * @return This - */ - public SymbolLayer withProperties(@NonNull Property<?>... properties) { - setProperties(properties); - return this; - } - - // Property getters - - /** - * Get the SymbolPlacement property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getSymbolPlacement() { - return (PropertyValue<String>) new PropertyValue(nativeGetSymbolPlacement()); - } - - /** - * Get the SymbolSpacing property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getSymbolSpacing() { - return (PropertyValue<Float>) new PropertyValue(nativeGetSymbolSpacing()); - } - - /** - * Get the SymbolAvoidEdges property - * - * @return property wrapper value around Boolean - */ - @SuppressWarnings("unchecked") - public PropertyValue<Boolean> getSymbolAvoidEdges() { - return (PropertyValue<Boolean>) new PropertyValue(nativeGetSymbolAvoidEdges()); - } - - /** - * Get the IconAllowOverlap property - * - * @return property wrapper value around Boolean - */ - @SuppressWarnings("unchecked") - public PropertyValue<Boolean> getIconAllowOverlap() { - return (PropertyValue<Boolean>) new PropertyValue(nativeGetIconAllowOverlap()); - } - - /** - * Get the IconIgnorePlacement property - * - * @return property wrapper value around Boolean - */ - @SuppressWarnings("unchecked") - public PropertyValue<Boolean> getIconIgnorePlacement() { - return (PropertyValue<Boolean>) new PropertyValue(nativeGetIconIgnorePlacement()); - } - - /** - * Get the IconOptional property - * - * @return property wrapper value around Boolean - */ - @SuppressWarnings("unchecked") - public PropertyValue<Boolean> getIconOptional() { - return (PropertyValue<Boolean>) new PropertyValue(nativeGetIconOptional()); - } - - /** - * Get the IconRotationAlignment property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getIconRotationAlignment() { - return (PropertyValue<String>) new PropertyValue(nativeGetIconRotationAlignment()); - } - - /** - * Get the IconSize property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getIconSize() { - return (PropertyValue<Float>) new PropertyValue(nativeGetIconSize()); - } - - /** - * Get the IconTextFit property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getIconTextFit() { - return (PropertyValue<String>) new PropertyValue(nativeGetIconTextFit()); - } - - /** - * Get the IconTextFitPadding property - * - * @return property wrapper value around Float[] - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float[]> getIconTextFitPadding() { - return (PropertyValue<Float[]>) new PropertyValue(nativeGetIconTextFitPadding()); - } - - /** - * Get the IconImage property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getIconImage() { - return (PropertyValue<String>) new PropertyValue(nativeGetIconImage()); - } - - /** - * Get the IconRotate property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getIconRotate() { - return (PropertyValue<Float>) new PropertyValue(nativeGetIconRotate()); - } - - /** - * Get the IconPadding property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getIconPadding() { - return (PropertyValue<Float>) new PropertyValue(nativeGetIconPadding()); - } - - /** - * Get the IconKeepUpright property - * - * @return property wrapper value around Boolean - */ - @SuppressWarnings("unchecked") - public PropertyValue<Boolean> getIconKeepUpright() { - return (PropertyValue<Boolean>) new PropertyValue(nativeGetIconKeepUpright()); - } - - /** - * Get the IconOffset property - * - * @return property wrapper value around Float[] - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float[]> getIconOffset() { - return (PropertyValue<Float[]>) new PropertyValue(nativeGetIconOffset()); - } - - /** - * Get the TextPitchAlignment property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getTextPitchAlignment() { - return (PropertyValue<String>) new PropertyValue(nativeGetTextPitchAlignment()); - } - - /** - * Get the TextRotationAlignment property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getTextRotationAlignment() { - return (PropertyValue<String>) new PropertyValue(nativeGetTextRotationAlignment()); - } - - /** - * Get the TextField property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getTextField() { - return (PropertyValue<String>) new PropertyValue(nativeGetTextField()); - } - - /** - * Get the TextFont property - * - * @return property wrapper value around String[] - */ - @SuppressWarnings("unchecked") - public PropertyValue<String[]> getTextFont() { - return (PropertyValue<String[]>) new PropertyValue(nativeGetTextFont()); - } - - /** - * Get the TextSize property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getTextSize() { - return (PropertyValue<Float>) new PropertyValue(nativeGetTextSize()); - } - - /** - * Get the TextMaxWidth property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getTextMaxWidth() { - return (PropertyValue<Float>) new PropertyValue(nativeGetTextMaxWidth()); - } - - /** - * Get the TextLineHeight property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getTextLineHeight() { - return (PropertyValue<Float>) new PropertyValue(nativeGetTextLineHeight()); - } - - /** - * Get the TextLetterSpacing property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getTextLetterSpacing() { - return (PropertyValue<Float>) new PropertyValue(nativeGetTextLetterSpacing()); - } - - /** - * Get the TextJustify property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getTextJustify() { - return (PropertyValue<String>) new PropertyValue(nativeGetTextJustify()); - } - - /** - * Get the TextAnchor property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getTextAnchor() { - return (PropertyValue<String>) new PropertyValue(nativeGetTextAnchor()); - } - - /** - * Get the TextMaxAngle property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getTextMaxAngle() { - return (PropertyValue<Float>) new PropertyValue(nativeGetTextMaxAngle()); - } - - /** - * Get the TextRotate property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getTextRotate() { - return (PropertyValue<Float>) new PropertyValue(nativeGetTextRotate()); - } - - /** - * Get the TextPadding property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getTextPadding() { - return (PropertyValue<Float>) new PropertyValue(nativeGetTextPadding()); - } - - /** - * Get the TextKeepUpright property - * - * @return property wrapper value around Boolean - */ - @SuppressWarnings("unchecked") - public PropertyValue<Boolean> getTextKeepUpright() { - return (PropertyValue<Boolean>) new PropertyValue(nativeGetTextKeepUpright()); - } - - /** - * Get the TextTransform property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getTextTransform() { - return (PropertyValue<String>) new PropertyValue(nativeGetTextTransform()); - } - - /** - * Get the TextOffset property - * - * @return property wrapper value around Float[] - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float[]> getTextOffset() { - return (PropertyValue<Float[]>) new PropertyValue(nativeGetTextOffset()); - } - - /** - * Get the TextAllowOverlap property - * - * @return property wrapper value around Boolean - */ - @SuppressWarnings("unchecked") - public PropertyValue<Boolean> getTextAllowOverlap() { - return (PropertyValue<Boolean>) new PropertyValue(nativeGetTextAllowOverlap()); - } - - /** - * Get the TextIgnorePlacement property - * - * @return property wrapper value around Boolean - */ - @SuppressWarnings("unchecked") - public PropertyValue<Boolean> getTextIgnorePlacement() { - return (PropertyValue<Boolean>) new PropertyValue(nativeGetTextIgnorePlacement()); - } - - /** - * Get the TextOptional property - * - * @return property wrapper value around Boolean - */ - @SuppressWarnings("unchecked") - public PropertyValue<Boolean> getTextOptional() { - return (PropertyValue<Boolean>) new PropertyValue(nativeGetTextOptional()); - } - - /** - * Get the IconOpacity property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getIconOpacity() { - return (PropertyValue<Float>) new PropertyValue(nativeGetIconOpacity()); - } - - /** - * Get the IconColor property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getIconColor() { - return (PropertyValue<String>) new PropertyValue(nativeGetIconColor()); - } - /** - * The color of the icon. This can only be used with sdf icons. - * - * @return int representation of a rgba string color - * @throws RuntimeException thrown if property isn't a value - */ - @ColorInt - public int getIconColorAsInt() { - PropertyValue<String> value = getIconColor(); - if (value.isValue()) { - return rgbaToColor(value.getValue()); - } else { - throw new RuntimeException("icon-color was set as a Function"); - } - } - - - /** - * Get the IconHaloColor property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getIconHaloColor() { - return (PropertyValue<String>) new PropertyValue(nativeGetIconHaloColor()); - } - /** - * The color of the icon's halo. Icon halos can only be used with SDF icons. - * - * @return int representation of a rgba string color - * @throws RuntimeException thrown if property isn't a value - */ - @ColorInt - public int getIconHaloColorAsInt() { - PropertyValue<String> value = getIconHaloColor(); - if (value.isValue()) { - return rgbaToColor(value.getValue()); - } else { - throw new RuntimeException("icon-halo-color was set as a Function"); - } - } - - - /** - * Get the IconHaloWidth property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getIconHaloWidth() { - return (PropertyValue<Float>) new PropertyValue(nativeGetIconHaloWidth()); - } - - /** - * Get the IconHaloBlur property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getIconHaloBlur() { - return (PropertyValue<Float>) new PropertyValue(nativeGetIconHaloBlur()); - } - - /** - * Get the IconTranslate property - * - * @return property wrapper value around Float[] - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float[]> getIconTranslate() { - return (PropertyValue<Float[]>) new PropertyValue(nativeGetIconTranslate()); - } - - /** - * Get the IconTranslateAnchor property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getIconTranslateAnchor() { - return (PropertyValue<String>) new PropertyValue(nativeGetIconTranslateAnchor()); - } - - /** - * Get the TextOpacity property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getTextOpacity() { - return (PropertyValue<Float>) new PropertyValue(nativeGetTextOpacity()); - } - - /** - * Get the TextColor property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getTextColor() { - return (PropertyValue<String>) new PropertyValue(nativeGetTextColor()); - } - /** - * The color with which the text will be drawn. - * - * @return int representation of a rgba string color - * @throws RuntimeException thrown if property isn't a value - */ - @ColorInt - public int getTextColorAsInt() { - PropertyValue<String> value = getTextColor(); - if (value.isValue()) { - return rgbaToColor(value.getValue()); - } else { - throw new RuntimeException("text-color was set as a Function"); - } - } - - - /** - * Get the TextHaloColor property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getTextHaloColor() { - return (PropertyValue<String>) new PropertyValue(nativeGetTextHaloColor()); - } - /** - * The color of the text's halo, which helps it stand out from backgrounds. - * - * @return int representation of a rgba string color - * @throws RuntimeException thrown if property isn't a value - */ - @ColorInt - public int getTextHaloColorAsInt() { - PropertyValue<String> value = getTextHaloColor(); - if (value.isValue()) { - return rgbaToColor(value.getValue()); - } else { - throw new RuntimeException("text-halo-color was set as a Function"); - } - } - - - /** - * Get the TextHaloWidth property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getTextHaloWidth() { - return (PropertyValue<Float>) new PropertyValue(nativeGetTextHaloWidth()); - } - - /** - * Get the TextHaloBlur property - * - * @return property wrapper value around Float - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float> getTextHaloBlur() { - return (PropertyValue<Float>) new PropertyValue(nativeGetTextHaloBlur()); - } - - /** - * Get the TextTranslate property - * - * @return property wrapper value around Float[] - */ - @SuppressWarnings("unchecked") - public PropertyValue<Float[]> getTextTranslate() { - return (PropertyValue<Float[]>) new PropertyValue(nativeGetTextTranslate()); - } - - /** - * Get the TextTranslateAnchor property - * - * @return property wrapper value around String - */ - @SuppressWarnings("unchecked") - public PropertyValue<String> getTextTranslateAnchor() { - return (PropertyValue<String>) new PropertyValue(nativeGetTextTranslateAnchor()); - } - - private native Object nativeGetSymbolPlacement(); + private native Object nativeGetSymbolPlacement(); - private native Object nativeGetSymbolSpacing(); + private native Object nativeGetSymbolSpacing(); - private native Object nativeGetSymbolAvoidEdges(); + private native Object nativeGetSymbolAvoidEdges(); - private native Object nativeGetIconAllowOverlap(); + private native Object nativeGetIconAllowOverlap(); - private native Object nativeGetIconIgnorePlacement(); + private native Object nativeGetIconIgnorePlacement(); - private native Object nativeGetIconOptional(); + private native Object nativeGetIconOptional(); - private native Object nativeGetIconRotationAlignment(); + private native Object nativeGetIconRotationAlignment(); - private native Object nativeGetIconSize(); + private native Object nativeGetIconSize(); - private native Object nativeGetIconTextFit(); + private native Object nativeGetIconTextFit(); - private native Object nativeGetIconTextFitPadding(); + private native Object nativeGetIconTextFitPadding(); - private native Object nativeGetIconImage(); + private native Object nativeGetIconImage(); - private native Object nativeGetIconRotate(); + private native Object nativeGetIconRotate(); - private native Object nativeGetIconPadding(); + private native Object nativeGetIconPadding(); - private native Object nativeGetIconKeepUpright(); + private native Object nativeGetIconKeepUpright(); - private native Object nativeGetIconOffset(); + private native Object nativeGetIconOffset(); - private native Object nativeGetTextPitchAlignment(); + private native Object nativeGetTextPitchAlignment(); - private native Object nativeGetTextRotationAlignment(); + private native Object nativeGetTextRotationAlignment(); - private native Object nativeGetTextField(); + private native Object nativeGetTextField(); - private native Object nativeGetTextFont(); + private native Object nativeGetTextFont(); - private native Object nativeGetTextSize(); + private native Object nativeGetTextSize(); - private native Object nativeGetTextMaxWidth(); + private native Object nativeGetTextMaxWidth(); - private native Object nativeGetTextLineHeight(); + private native Object nativeGetTextLineHeight(); - private native Object nativeGetTextLetterSpacing(); + private native Object nativeGetTextLetterSpacing(); - private native Object nativeGetTextJustify(); + private native Object nativeGetTextJustify(); - private native Object nativeGetTextAnchor(); + private native Object nativeGetTextAnchor(); - private native Object nativeGetTextMaxAngle(); + private native Object nativeGetTextMaxAngle(); - private native Object nativeGetTextRotate(); + private native Object nativeGetTextRotate(); - private native Object nativeGetTextPadding(); + private native Object nativeGetTextPadding(); - private native Object nativeGetTextKeepUpright(); + private native Object nativeGetTextKeepUpright(); - private native Object nativeGetTextTransform(); + private native Object nativeGetTextTransform(); - private native Object nativeGetTextOffset(); + private native Object nativeGetTextOffset(); - private native Object nativeGetTextAllowOverlap(); + private native Object nativeGetTextAllowOverlap(); - private native Object nativeGetTextIgnorePlacement(); + private native Object nativeGetTextIgnorePlacement(); - private native Object nativeGetTextOptional(); + private native Object nativeGetTextOptional(); - private native Object nativeGetIconOpacity(); + private native Object nativeGetIconOpacity(); - private native Object nativeGetIconColor(); + private native Object nativeGetIconColor(); - private native Object nativeGetIconHaloColor(); + private native Object nativeGetIconHaloColor(); - private native Object nativeGetIconHaloWidth(); + private native Object nativeGetIconHaloWidth(); - private native Object nativeGetIconHaloBlur(); + private native Object nativeGetIconHaloBlur(); - private native Object nativeGetIconTranslate(); + private native Object nativeGetIconTranslate(); - private native Object nativeGetIconTranslateAnchor(); + private native Object nativeGetIconTranslateAnchor(); - private native Object nativeGetTextOpacity(); + private native Object nativeGetTextOpacity(); - private native Object nativeGetTextColor(); + private native Object nativeGetTextColor(); - private native Object nativeGetTextHaloColor(); + private native Object nativeGetTextHaloColor(); - private native Object nativeGetTextHaloWidth(); + private native Object nativeGetTextHaloWidth(); - private native Object nativeGetTextHaloBlur(); + private native Object nativeGetTextHaloBlur(); - private native Object nativeGetTextTranslate(); + private native Object nativeGetTextTranslate(); - private native Object nativeGetTextTranslateAnchor(); + private native Object nativeGetTextTranslateAnchor(); - @Override - protected native void finalize() throws Throwable; + @Override + protected native void finalize() throws Throwable; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CannotAddSourceException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CannotAddSourceException.java index 9d5a837b5a..ddc4c58cf1 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CannotAddSourceException.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CannotAddSourceException.java @@ -5,8 +5,8 @@ package com.mapbox.mapboxsdk.style.sources; */ public class CannotAddSourceException extends RuntimeException { - public CannotAddSourceException(String message) { - super(message); - } + public CannotAddSourceException(String message) { + super(message); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java index 55a9799cb7..27a3d5c898 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonOptions.java @@ -9,70 +9,72 @@ import java.util.HashMap; */ public class GeoJsonOptions extends HashMap<String, Object> { - /** - * Maximum zoom level at which to create vector tiles (higher means greater detail at high zoom levels). - * - * @param maxZoom the maximum zoom - Defaults to 18. - * @return the current instance for chaining - */ - public GeoJsonOptions withMaxZoom(int maxZoom) { - this.put("maxzoom", maxZoom); - return this; - } + /** + * Maximum zoom level at which to create vector tiles (higher means greater detail at high zoom levels). + * + * @param maxZoom the maximum zoom - Defaults to 18. + * @return the current instance for chaining + */ + public GeoJsonOptions withMaxZoom(int maxZoom) { + this.put("maxzoom", maxZoom); + return this; + } - /** - * Tile buffer size on each side (measured in 1/512ths of a tile; higher means fewer rendering artifacts near tile edges but slower performance). - * - * @param buffer the buffer size - Defaults to 128. - * @return the current instance for chaining - */ - public GeoJsonOptions withBuffer(int buffer) { - this.put("buffer", buffer); - return this; - } + /** + * Tile buffer size on each side (measured in 1/512ths of a tile; higher means fewer rendering artifacts near tile + * edges but slower performance). + * + * @param buffer the buffer size - Defaults to 128. + * @return the current instance for chaining + */ + public GeoJsonOptions withBuffer(int buffer) { + this.put("buffer", buffer); + return this; + } - /** - * Douglas-Peucker simplification tolerance (higher means simpler geometries and faster performance). - * - * @param tolerance the tolerance - Defaults to 0.375 - * @return the current instance for chaining - */ - public GeoJsonOptions withTolerance(float tolerance) { - this.put("tolerance", tolerance); - return this; - } + /** + * Douglas-Peucker simplification tolerance (higher means simpler geometries and faster performance). + * + * @param tolerance the tolerance - Defaults to 0.375 + * @return the current instance for chaining + */ + public GeoJsonOptions withTolerance(float tolerance) { + this.put("tolerance", tolerance); + return this; + } - /** - * If the data is a collection of point features, setting this to true clusters the points by radius into groups. - * - * @param cluster cluster? - Defaults to false - * @return the current instance for chaining - */ - public GeoJsonOptions withCluster(boolean cluster) { - this.put("cluster", cluster); - return this; - } + /** + * If the data is a collection of point features, setting this to true clusters the points by radius into groups. + * + * @param cluster cluster? - Defaults to false + * @return the current instance for chaining + */ + public GeoJsonOptions withCluster(boolean cluster) { + this.put("cluster", cluster); + return this; + } - /** - * Max zoom to cluster points on. - * - * @param clusterMaxZoom clusterMaxZoom cluster maximum zoom - Defaults to one zoom less than maxzoom (so that last zoom features are not clustered) - * @return the current instance for chaining - */ - public GeoJsonOptions withClusterMaxZoom(int clusterMaxZoom) { - this.put("clusterMaxZoom", clusterMaxZoom); - return this; - } + /** + * Max zoom to cluster points on. + * + * @param clusterMaxZoom clusterMaxZoom cluster maximum zoom - Defaults to one zoom less than maxzoom (so that last + * zoom features are not clustered) + * @return the current instance for chaining + */ + public GeoJsonOptions withClusterMaxZoom(int clusterMaxZoom) { + this.put("clusterMaxZoom", clusterMaxZoom); + return this; + } - /** - * Radius of each cluster when clustering points, measured in 1/512ths of a tile. - * - * @param clusterRadius cluster radius - Defaults to 50 - * @return the current instance for chaining - */ - public GeoJsonOptions withClusterRadius(int clusterRadius) { - this.put("clusterRadius", clusterRadius); - return this; - } + /** + * Radius of each cluster when clustering points, measured in 1/512ths of a tile. + * + * @param clusterRadius cluster radius - Defaults to 50 + * @return the current instance for chaining + */ + public GeoJsonOptions withClusterRadius(int clusterRadius) { + this.put("clusterRadius", clusterRadius); + return this; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java index 80730d143c..0c2ee42ea0 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java @@ -14,166 +14,166 @@ import java.util.HashMap; */ public class GeoJsonSource extends Source { - /** - * Internal use - * - * @param nativePtr - pointer to native peer - */ - public GeoJsonSource(long nativePtr) { - super(nativePtr); + /** + * Internal use + * + * @param nativePtr - pointer to native peer + */ + public GeoJsonSource(long nativePtr) { + super(nativePtr); + } + + /** + * Create an empty GeoJsonSource + * + * @param id the source id + */ + public GeoJsonSource(String id) { + initialize(id, null); + setGeoJson(FeatureCollection.fromFeatures(new ArrayList<Feature>())); + } + + /** + * Create an empty GeoJsonSource with non-default {@link GeoJsonOptions} + * + * @param id the source id + * @param options options + */ + public GeoJsonSource(String id, GeoJsonOptions options) { + initialize(id, options); + setGeoJson(FeatureCollection.fromFeatures(new ArrayList<Feature>())); + } + + /** + * Create a GeoJsonSource from a raw json string + * + * @param id the source id + * @param geoJson raw Json FeatureCollection + */ + public GeoJsonSource(String id, String geoJson) { + if (geoJson == null || geoJson.startsWith("http")) { + throw new IllegalArgumentException("Expected a raw json body"); } - - /** - * Create an empty GeoJsonSource - * - * @param id the source id - */ - public GeoJsonSource(String id) { - initialize(id, null); - setGeoJson(FeatureCollection.fromFeatures(new ArrayList<Feature>())); - } - - /** - * Create an empty GeoJsonSource with non-default {@link GeoJsonOptions} - * - * @param id the source id - * @param options options - */ - public GeoJsonSource(String id, GeoJsonOptions options) { - initialize(id, options); - setGeoJson(FeatureCollection.fromFeatures(new ArrayList<Feature>())); - } - - /** - * Create a GeoJsonSource from a raw json string - * - * @param id the source id - * @param geoJson raw Json FeatureCollection - */ - public GeoJsonSource(String id, String geoJson) { - if (geoJson == null || geoJson.startsWith("http")) { - throw new IllegalArgumentException("Expected a raw json body"); - } - initialize(id, null); - setGeoJson(geoJson); - } - - /** - * Create a GeoJsonSource from a raw json string and non-default {@link GeoJsonOptions} - * - * @param id the source id - * @param geoJson raw Json body - * @param options options - */ - public GeoJsonSource(String id, String geoJson, GeoJsonOptions options) { - if (geoJson == null || geoJson.startsWith("http")) { - throw new IllegalArgumentException("Expected a raw json body"); - } - initialize(id, options); - setGeoJson(geoJson); - } - - /** - * Create a GeoJsonSource from a remote geo json file - * - * @param id the source id - * @param url remote json file - */ - public GeoJsonSource(String id, URL url) { - initialize(id, null); - nativeSetUrl(url.toExternalForm()); - } - - /** - * Create a GeoJsonSource from a remote geo json file and non-default {@link GeoJsonOptions} - * - * @param id the source id - * @param url remote json file - * @param options options - */ - public GeoJsonSource(String id, URL url, GeoJsonOptions options) { - initialize(id, options); - nativeSetUrl(url.toExternalForm()); - } - - /** - * Create a GeoJsonSource from a {@link FeatureCollection} - * - * @param id the source id - * @param features the features - */ - public GeoJsonSource(String id, FeatureCollection features) { - initialize(id, null); - setGeoJson(features); - } - - /** - * Create a GeoJsonSource from a {@link FeatureCollection} and non-default {@link GeoJsonOptions} - * - * @param id the source id - * @param features the features - * @param options options - */ - public GeoJsonSource(String id, FeatureCollection features, GeoJsonOptions options) { - initialize(id, options); - setGeoJson(features); + initialize(id, null); + setGeoJson(geoJson); + } + + /** + * Create a GeoJsonSource from a raw json string and non-default {@link GeoJsonOptions} + * + * @param id the source id + * @param geoJson raw Json body + * @param options options + */ + public GeoJsonSource(String id, String geoJson, GeoJsonOptions options) { + if (geoJson == null || geoJson.startsWith("http")) { + throw new IllegalArgumentException("Expected a raw json body"); } - - /** - * Updates the GeoJson - * - * @param features the GeoJSON {@link FeatureCollection} - */ - public void setGeoJson(FeatureCollection features) { - checkValidity(); - setGeoJson(features.toJson()); - } - - /** - * Updates the GeoJson - * - * @param json the raw GeoJson FeatureCollection string - */ - public void setGeoJson(String json) { - checkValidity(); - setRawJson(json); - } - - /** - * Updates the url - * - * @param url the GeoJSON FeatureCollection url - */ - public void setUrl(URL url) { - checkValidity(); - setUrl(url.toExternalForm()); - } - - /** - * Updates the url - * - * @param url the GeoJSON FeatureCollection url - */ - public void setUrl(String url) { - checkValidity(); - nativeSetUrl(url); - } - - protected void setRawJson(String geoJson) { - //Wrap the String in a map as an Object is expected by the - //style conversion template - HashMap<String, String> wrapper = new HashMap<>(); - wrapper.put("data", geoJson); - nativeSetGeoJson(wrapper); - } - - protected native void initialize(String layerId, Object options); - - protected native void nativeSetUrl(String url); - - private native void nativeSetGeoJson(Object geoJson); - - @Override - protected native void finalize() throws Throwable; + initialize(id, options); + setGeoJson(geoJson); + } + + /** + * Create a GeoJsonSource from a remote geo json file + * + * @param id the source id + * @param url remote json file + */ + public GeoJsonSource(String id, URL url) { + initialize(id, null); + nativeSetUrl(url.toExternalForm()); + } + + /** + * Create a GeoJsonSource from a remote geo json file and non-default {@link GeoJsonOptions} + * + * @param id the source id + * @param url remote json file + * @param options options + */ + public GeoJsonSource(String id, URL url, GeoJsonOptions options) { + initialize(id, options); + nativeSetUrl(url.toExternalForm()); + } + + /** + * Create a GeoJsonSource from a {@link FeatureCollection} + * + * @param id the source id + * @param features the features + */ + public GeoJsonSource(String id, FeatureCollection features) { + initialize(id, null); + setGeoJson(features); + } + + /** + * Create a GeoJsonSource from a {@link FeatureCollection} and non-default {@link GeoJsonOptions} + * + * @param id the source id + * @param features the features + * @param options options + */ + public GeoJsonSource(String id, FeatureCollection features, GeoJsonOptions options) { + initialize(id, options); + setGeoJson(features); + } + + /** + * Updates the GeoJson + * + * @param features the GeoJSON {@link FeatureCollection} + */ + public void setGeoJson(FeatureCollection features) { + checkValidity(); + setGeoJson(features.toJson()); + } + + /** + * Updates the GeoJson + * + * @param json the raw GeoJson FeatureCollection string + */ + public void setGeoJson(String json) { + checkValidity(); + setRawJson(json); + } + + /** + * Updates the url + * + * @param url the GeoJSON FeatureCollection url + */ + public void setUrl(URL url) { + checkValidity(); + setUrl(url.toExternalForm()); + } + + /** + * Updates the url + * + * @param url the GeoJSON FeatureCollection url + */ + public void setUrl(String url) { + checkValidity(); + nativeSetUrl(url); + } + + protected void setRawJson(String geoJson) { + //Wrap the String in a map as an Object is expected by the + //style conversion template + HashMap<String, String> wrapper = new HashMap<>(); + wrapper.put("data", geoJson); + nativeSetGeoJson(wrapper); + } + + protected native void initialize(String layerId, Object options); + + protected native void nativeSetUrl(String url); + + private native void nativeSetGeoJson(Object geoJson); + + @Override + protected native void finalize() throws Throwable; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/NoSuchSourceException.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/NoSuchSourceException.java index 4622d72445..06d35b598b 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/NoSuchSourceException.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/NoSuchSourceException.java @@ -5,7 +5,7 @@ package com.mapbox.mapboxsdk.style.sources; */ public class NoSuchSourceException extends Exception { - public NoSuchSourceException(String message) { - super(message); - } + public NoSuchSourceException(String message) { + super(message); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.java index 7a7ae49909..eabbdb8395 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/RasterSource.java @@ -8,72 +8,72 @@ import java.net.URL; * @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-raster">The style specification</a> */ public class RasterSource extends Source { - public static final int DEFAULT_TILE_SIZE = 512; + public static final int DEFAULT_TILE_SIZE = 512; - /** - * Internal use - * - * @param nativePtr - pointer to native peer - */ - public RasterSource(long nativePtr) { - super(nativePtr); - } + /** + * Internal use + * + * @param nativePtr - pointer to native peer + */ + public RasterSource(long nativePtr) { + super(nativePtr); + } - /** - * Create the raster source from an URL - * - * @param id the source id - * @param url the source url - */ - public RasterSource(String id, URL url) { - this(id, url.toExternalForm()); - } + /** + * Create the raster source from an URL + * + * @param id the source id + * @param url the source url + */ + public RasterSource(String id, URL url) { + this(id, url.toExternalForm()); + } - /** - * Create the raster source from an URL - * - * @param id the source id - * @param url the source url - */ - public RasterSource(String id, String url) { - initialize(id, url, DEFAULT_TILE_SIZE); - } + /** + * Create the raster source from an URL + * + * @param id the source id + * @param url the source url + */ + public RasterSource(String id, String url) { + initialize(id, url, DEFAULT_TILE_SIZE); + } - /** - * Create the raster source from an URL with a specific tile size - * - * @param id the source id - * @param url the source url - * @param tileSize the tile size - */ - public RasterSource(String id, String url, int tileSize) { - initialize(id, url, tileSize); - } + /** + * Create the raster source from an URL with a specific tile size + * + * @param id the source id + * @param url the source url + * @param tileSize the tile size + */ + public RasterSource(String id, String url, int tileSize) { + initialize(id, url, tileSize); + } - /** - * Create the raster source from a {@link TileSet} - * - * @param id the source id - * @param tileSet the {@link TileSet} - */ - public RasterSource(String id, TileSet tileSet) { - initialize(id, tileSet.toValueObject(), DEFAULT_TILE_SIZE); - } + /** + * Create the raster source from a {@link TileSet} + * + * @param id the source id + * @param tileSet the {@link TileSet} + */ + public RasterSource(String id, TileSet tileSet) { + initialize(id, tileSet.toValueObject(), DEFAULT_TILE_SIZE); + } - /** - * Create the raster source from a {@link TileSet} with a specific tile size - * - * @param id the source id - * @param tileSet the {@link TileSet} - * @param tileSize tje tile size - */ - public RasterSource(String id, TileSet tileSet, int tileSize) { - initialize(id, tileSet.toValueObject(), tileSize); - } + /** + * Create the raster source from a {@link TileSet} with a specific tile size + * + * @param id the source id + * @param tileSet the {@link TileSet} + * @param tileSize tje tile size + */ + public RasterSource(String id, TileSet tileSet, int tileSize) { + initialize(id, tileSet.toValueObject(), tileSize); + } - protected native void initialize(String layerId, Object payload, int tileSize); + protected native void initialize(String layerId, Object payload, int tileSize); - @Override - protected native void finalize() throws Throwable; + @Override + protected native void finalize() throws Throwable; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/Source.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/Source.java index 0856b117dc..6826fed1b5 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/Source.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/Source.java @@ -4,52 +4,52 @@ package com.mapbox.mapboxsdk.style.sources; * Base Peer class for sources. see source.hpp for the other half of the peer. */ public abstract class Source { - private long nativePtr; - private boolean invalidated; - - /** - * Internal use - * - * @param nativePtr - pointer to native peer - */ - public Source(long nativePtr) { - this.nativePtr = nativePtr; - } - - public Source() { - } - - /** - * Retrieve the source id - * - * @return the source id - */ - public String getId() { - checkValidity(); - return nativeGetId(); - } - - /** - * Internal use - * - * @return the native peer pointer - */ - public long getNativePtr() { - return nativePtr; - } - - protected native String nativeGetId(); - - protected void checkValidity() { - if (invalidated) { - throw new RuntimeException("Layer has been invalidated. Request a new reference after adding"); - } - } - - /** - * Internal use - invalidates the source for further use (after adding it to the map) - */ - public final void invalidate() { - this.invalidated = true; + private long nativePtr; + private boolean invalidated; + + /** + * Internal use + * + * @param nativePtr - pointer to native peer + */ + public Source(long nativePtr) { + this.nativePtr = nativePtr; + } + + public Source() { + } + + /** + * Retrieve the source id + * + * @return the source id + */ + public String getId() { + checkValidity(); + return nativeGetId(); + } + + /** + * Internal use + * + * @return the native peer pointer + */ + public long getNativePtr() { + return nativePtr; + } + + protected native String nativeGetId(); + + protected void checkValidity() { + if (invalidated) { + throw new RuntimeException("Layer has been invalidated. Request a new reference after adding"); } + } + + /** + * Internal use - invalidates the source for further use (after adding it to the map) + */ + public final void invalidate() { + this.invalidated = true; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.java index b645020c21..9f403c2fb9 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.java @@ -13,304 +13,307 @@ import java.util.Map; * @see <a href="https://github.com/mapbox/tilejson-spec/tree/master/2.1.0">The tileset specification</a> */ public class TileSet { - private final String tilejson; - private String name; - private String description; - private String version; - private String attribution; - private String template; - private String legend; - private String scheme; - private final String[] tiles; - private String[] grids; - private String[] data; - private Float minZoom; - private Float maxZoom; - private Float[] bounds; - private Float[] center; - - /** - * @param tilejson A semver.org style version number. Describes the version of the TileJSON spec that is implemented by this JSON object. - * @param tiles An array of tile endpoints. {z}, {x} and {y}, if present, are replaced with the corresponding integers. - * If multiple endpoints are specified, clients may use any combination of endpoints. All endpoints MUST return the same - * content for the same URL. The array MUST contain at least one endpoint. - * Example: "http:localhost:8888/admin/1.0.0/world-light,broadband/{z}/{x}/{y}.png" - */ - public TileSet(String tilejson, String... tiles) { - this.tilejson = tilejson; - this.tiles = tiles; + private final String tilejson; + private String name; + private String description; + private String version; + private String attribution; + private String template; + private String legend; + private String scheme; + private final String[] tiles; + private String[] grids; + private String[] data; + private Float minZoom; + private Float maxZoom; + private Float[] bounds; + private Float[] center; + + /** + * @param tilejson A semver.org style version number. Describes the version of the TileJSON spec that is implemented + * by this JSON object. + * @param tiles An array of tile endpoints. {z}, {x} and {y}, if present, are replaced with the corresponding + * integers. + * If multiple endpoints are specified, clients may use any combination of endpoints. All endpoints + * MUST return the same + * content for the same URL. The array MUST contain at least one endpoint. + * Example: "http:localhost:8888/admin/1.0.0/world-light,broadband/{z}/{x}/{y}.png" + */ + public TileSet(String tilejson, String... tiles) { + this.tilejson = tilejson; + this.tiles = tiles; + } + + public String getTilejson() { + return tilejson; + } + + public String getName() { + return name; + } + + /** + * A name describing the tileset. The name can + * contain any legal character. Implementations SHOULD NOT interpret the + * name as HTML. + * "name": "compositing", + * + * @param name the name to be set + */ + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + /** + * A text description of the tileset. The + * description can contain any legal character. + * Implementations SHOULD NOT + * interpret the description as HTML. + * "description": "A simple, light grey world." + * + * @param description the description to set + */ + public void setDescription(String description) { + this.description = description; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getAttribution() { + return attribution; + } + + /** + * Default: null. Contains an attribution to be displayed + * when the map is shown to a user. Implementations MAY decide to treat this + * as HTML or literal text. For security reasons, make absolutely sure that + * this field can't be abused as a vector for XSS or beacon tracking. + * "attribution": "<a href='http:openstreetmap.org'>OSM contributors</a>", + * + * @param attribution the attribution to set + */ + public void setAttribution(String attribution) { + this.attribution = attribution; + } + + public String getTemplate() { + return template; + } + + /** + * Contains a mustache template to be used to + * format data from grids for interaction. + * See https:github.com/mapbox/utfgrid-spec/tree/master/1.2 + * for the interactivity specification. + * "template": "{{#__teaser__}}{{NAME}}{{/__teaser__}}" + * + * @param template the template to set + */ + public void setTemplate(String template) { + this.template = template; + } + + public String getLegend() { + return legend; + } + + /** + * Contains a legend to be displayed with the map. + * Implementations MAY decide to treat this as HTML or literal text. + * For security reasons, make absolutely sure that this field can't be + * abused as a vector for XSS or beacon tracking. + * "legend": "Dangerous zones are red, safe zones are green" + * + * @param legend the legend to set + */ + public void setLegend(String legend) { + this.legend = legend; + } + + public String getScheme() { + return scheme; + } + + /** + * Default: "xyz". Either "xyz" or "tms". Influences the y + * direction of the tile coordinates. + * The global-mercator (aka Spherical Mercator) profile is assumed. + * "scheme": "xyz" + * + * @param scheme the scheme to set + */ + public void setScheme(String scheme) { + this.scheme = scheme; + } + + public String[] getTiles() { + return tiles; + } + + public String[] getGrids() { + return grids; + } + + /** + * An array of interactivity endpoints. {z}, {x} + * and {y}, if present, are replaced with the corresponding integers. If multiple + * endpoints are specified, clients may use any combination of endpoints. + * All endpoints MUST return the same content for the same URL. + * If the array doesn't contain any entries, interactivity is not supported + * for this tileset. See https:github.com/mapbox/utfgrid-spec/tree/master/1.2 + * for the interactivity specification. + * <p> + * Example: "http:localhost:8888/admin/1.0.0/broadband/{z}/{x}/{y}.grid.json" + * </p> + * + * @param grids the grids to set + */ + public void setGrids(String... grids) { + this.grids = grids; + } + + public String[] getData() { + return data; + } + + /** + * An array of data files in GeoJSON format. + * {z}, {x} and {y}, if present, + * are replaced with the corresponding integers. If multiple + * endpoints are specified, clients may use any combination of endpoints. + * All endpoints MUST return the same content for the same URL. + * If the array doesn't contain any entries, then no data is present in + * the map. + * <p> + * "http:localhost:8888/admin/data.geojson" + * </p> + * + * @param data the data array to set + */ + public void setData(String... data) { + this.data = data; + } + + public float getMinZoom() { + return minZoom; + } + + /** + * 0. >= 0, < 22. An integer specifying the minimum zoom level. + * + * @param minZoom the minZoom level to set + */ + public void setMinZoom(float minZoom) { + this.minZoom = minZoom; + } + + public float getMaxZoom() { + return maxZoom; + } + + /** + * 0. >= 0, <= 22. An integer specifying the maximum zoom level. + * + * @param maxZoom the maxZoom level to set + */ + public void setMaxZoom(float maxZoom) { + this.maxZoom = maxZoom; + } + + public Float[] getBounds() { + return bounds; + } + + /** + * Default: [-180, -90, 180, 90]. The maximum extent of available map tiles. Bounds MUST define an area + * covered by all zoom levels. The bounds are represented in WGS:84 + * latitude and longitude values, in the order left, bottom, right, top. + * Values may be integers or floating point numbers. + * + * @param bounds the Float array to set + */ + public void setBounds(@Size(value = 4) Float... bounds) { + this.bounds = bounds; + } + + public Float[] getCenter() { + return center; + } + + /** + * The first value is the longitude, the second is latitude (both in + * WGS:84 values), the third value is the zoom level as an integer. + * Longitude and latitude MUST be within the specified bounds. + * The zoom level MUST be between minzoom and maxzoom. + * Implementations can use this value to set the default location. If the + * value is null, implementations may use their own algorithm for + * determining a default location. + * + * @param center the Float array to set + */ + public void setCenter(@Size(value = 2) Float... center) { + this.center = center; + } + + public void setCenter(LatLng center) { + this.center = new Float[] {(float) center.getLongitude(), (float) center.getLatitude()}; + } + + Map<String, Object> toValueObject() { + Map<String, Object> result = new HashMap<>(); + result.put("tilejson", tilejson); + result.put("tiles", tiles); + + if (name != null) { + result.put("name", name); } - - public String getTilejson() { - return tilejson; - } - - public String getName() { - return name; - } - - /** - * A name describing the tileset. The name can - * contain any legal character. Implementations SHOULD NOT interpret the - * name as HTML. - * "name": "compositing", - * - * @param name the name to be set - */ - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - /** - * A text description of the tileset. The - * description can contain any legal character. - * Implementations SHOULD NOT - * interpret the description as HTML. - * "description": "A simple, light grey world." - * - * @param description the description to set - */ - public void setDescription(String description) { - this.description = description; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; + if (description != null) { + result.put("description", description); } - - public String getAttribution() { - return attribution; + if (version != null) { + result.put("version", version); } - - /** - * Default: null. Contains an attribution to be displayed - * when the map is shown to a user. Implementations MAY decide to treat this - * as HTML or literal text. For security reasons, make absolutely sure that - * this field can't be abused as a vector for XSS or beacon tracking. - * "attribution": "<a href='http:openstreetmap.org'>OSM contributors</a>", - * - * @param attribution the attribution to set - */ - public void setAttribution(String attribution) { - this.attribution = attribution; + if (attribution != null) { + result.put("attribution", attribution); } - - public String getTemplate() { - return template; + if (template != null) { + result.put("template", template); } - - /** - * Contains a mustache template to be used to - * format data from grids for interaction. - * See https:github.com/mapbox/utfgrid-spec/tree/master/1.2 - * for the interactivity specification. - * "template": "{{#__teaser__}}{{NAME}}{{/__teaser__}}" - * - * @param template the template to set - */ - public void setTemplate(String template) { - this.template = template; + if (legend != null) { + result.put("legend", legend); } - - public String getLegend() { - return legend; + if (scheme != null) { + result.put("scheme", scheme); } - - /** - * Contains a legend to be displayed with the map. - * Implementations MAY decide to treat this as HTML or literal text. - * For security reasons, make absolutely sure that this field can't be - * abused as a vector for XSS or beacon tracking. - * "legend": "Dangerous zones are red, safe zones are green" - * - * @param legend the legend to set - */ - public void setLegend(String legend) { - this.legend = legend; + if (grids != null) { + result.put("grids", grids); } - - public String getScheme() { - return scheme; + if (data != null) { + result.put("data", data); } - - /** - * Default: "xyz". Either "xyz" or "tms". Influences the y - * direction of the tile coordinates. - * The global-mercator (aka Spherical Mercator) profile is assumed. - * "scheme": "xyz" - * - * @param scheme the scheme to set - */ - public void setScheme(String scheme) { - this.scheme = scheme; + if (minZoom != null) { + result.put("minzoom", minZoom); } - - public String[] getTiles() { - return tiles; + if (maxZoom != null) { + result.put("maxzoom", maxZoom); } - - public String[] getGrids() { - return grids; + if (bounds != null) { + result.put("bounds", bounds); } - - /** - * An array of interactivity endpoints. {z}, {x} - * and {y}, if present, are replaced with the corresponding integers. If multiple - * endpoints are specified, clients may use any combination of endpoints. - * All endpoints MUST return the same content for the same URL. - * If the array doesn't contain any entries, interactivity is not supported - * for this tileset. See https:github.com/mapbox/utfgrid-spec/tree/master/1.2 - * for the interactivity specification. - * <p> - * Example: "http:localhost:8888/admin/1.0.0/broadband/{z}/{x}/{y}.grid.json" - * </p> - * - * @param grids the grids to set - */ - public void setGrids(String... grids) { - this.grids = grids; + if (center != null) { + result.put("center", center); } - public String[] getData() { - return data; - } - - /** - * An array of data files in GeoJSON format. - * {z}, {x} and {y}, if present, - * are replaced with the corresponding integers. If multiple - * endpoints are specified, clients may use any combination of endpoints. - * All endpoints MUST return the same content for the same URL. - * If the array doesn't contain any entries, then no data is present in - * the map. - * <p> - * "http:localhost:8888/admin/data.geojson" - * </p> - * - * @param data the data array to set - */ - public void setData(String... data) { - this.data = data; - } - - public float getMinZoom() { - return minZoom; - } - - /** - * 0. >= 0, < 22. An integer specifying the minimum zoom level. - * - * @param minZoom the minZoom level to set - */ - public void setMinZoom(float minZoom) { - this.minZoom = minZoom; - } - - public float getMaxZoom() { - return maxZoom; - } - - /** - * 0. >= 0, <= 22. An integer specifying the maximum zoom level. - * - * @param maxZoom the maxZoom level to set - */ - public void setMaxZoom(float maxZoom) { - this.maxZoom = maxZoom; - } - - public Float[] getBounds() { - return bounds; - } - - /** - * Default: [-180, -90, 180, 90]. The maximum extent of available map tiles. Bounds MUST define an area - * covered by all zoom levels. The bounds are represented in WGS:84 - * latitude and longitude values, in the order left, bottom, right, top. - * Values may be integers or floating point numbers. - * - * @param bounds the Float array to set - */ - public void setBounds(@Size(value = 4) Float... bounds) { - this.bounds = bounds; - } - - public Float[] getCenter() { - return center; - } - - /** - * The first value is the longitude, the second is latitude (both in - * WGS:84 values), the third value is the zoom level as an integer. - * Longitude and latitude MUST be within the specified bounds. - * The zoom level MUST be between minzoom and maxzoom. - * Implementations can use this value to set the default location. If the - * value is null, implementations may use their own algorithm for - * determining a default location. - * - * @param center the Float array to set - */ - public void setCenter(@Size(value = 2) Float... center) { - this.center = center; - } - - public void setCenter(LatLng center) { - this.center = new Float[]{(float) center.getLongitude(), (float) center.getLatitude()}; - } - - Map<String, Object> toValueObject() { - Map<String, Object> result = new HashMap<>(); - result.put("tilejson", tilejson); - result.put("tiles", tiles); - - if (name != null) { - result.put("name", name); - } - if (description != null) { - result.put("description", description); - } - if (version != null) { - result.put("version", version); - } - if (attribution != null) { - result.put("attribution", attribution); - } - if (template != null) { - result.put("template", template); - } - if (legend != null) { - result.put("legend", legend); - } - if (scheme != null) { - result.put("scheme", scheme); - } - if (grids != null) { - result.put("grids", grids); - } - if (data != null) { - result.put("data", data); - } - if (minZoom != null) { - result.put("minzoom", minZoom); - } - if (maxZoom != null) { - result.put("maxzoom", maxZoom); - } - if (bounds != null) { - result.put("bounds", bounds); - } - if (center != null) { - result.put("center", center); - } - - return result; - } + return result; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java index 689ea7c6bc..feaca839d3 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java @@ -9,47 +9,47 @@ import java.net.URL; */ public class VectorSource extends Source { - /** - * Internal use - * - * @param nativePtr - pointer to native peer - */ - public VectorSource(long nativePtr) { - super(nativePtr); - } - - /** - * Create a vector source from a remote url - * - * @param id the source id - * @param url the url - */ - public VectorSource(String id, URL url) { - this(id, url.toExternalForm()); - } - - /** - * Create a vector source from a remote url - * - * @param id the source id - * @param url the url - */ - public VectorSource(String id, String url) { - initialize(id, url); - } - - /** - * Create a vector source from a tilset - * - * @param id the source id - * @param tileSet the tileset - */ - public VectorSource(String id, TileSet tileSet) { - initialize(id, tileSet.toValueObject()); - } - - protected native void initialize(String layerId, Object payload); - - @Override - protected native void finalize() throws Throwable; + /** + * Internal use + * + * @param nativePtr - pointer to native peer + */ + public VectorSource(long nativePtr) { + super(nativePtr); + } + + /** + * Create a vector source from a remote url + * + * @param id the source id + * @param url the url + */ + public VectorSource(String id, URL url) { + this(id, url.toExternalForm()); + } + + /** + * Create a vector source from a remote url + * + * @param id the source id + * @param url the url + */ + public VectorSource(String id, String url) { + initialize(id, url); + } + + /** + * Create a vector source from a tilset + * + * @param id the source id + * @param tileSet the tileset + */ + public VectorSource(String id, TileSet tileSet) { + initialize(id, tileSet.toValueObject()); + } + + protected native void initialize(String layerId, Object payload); + + @Override + protected native void finalize() throws Throwable; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/GzipRequestInterceptor.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/GzipRequestInterceptor.java index bc7d8fff87..8457d24ff2 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/GzipRequestInterceptor.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/GzipRequestInterceptor.java @@ -1,7 +1,9 @@ package com.mapbox.mapboxsdk.telemetry; import timber.log.Timber; + import java.io.IOException; + import okhttp3.Interceptor; import okhttp3.MediaType; import okhttp3.Request; @@ -17,36 +19,40 @@ import okio.Okio; */ public final class GzipRequestInterceptor implements Interceptor { - @Override public Response intercept(Interceptor.Chain chain) throws IOException { - Request originalRequest = chain.request(); - if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) { - Timber.d("Not compressing"); - return chain.proceed(originalRequest); - } - - Timber.d("Compressing"); - Request compressedRequest = originalRequest.newBuilder() - .header("Content-Encoding", "gzip") - .method(originalRequest.method(), gzip(originalRequest.body())) - .build(); - return chain.proceed(compressedRequest); + @Override + public Response intercept(Interceptor.Chain chain) throws IOException { + Request originalRequest = chain.request(); + if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) { + Timber.d("Not compressing"); + return chain.proceed(originalRequest); } - private RequestBody gzip(final RequestBody body) { - return new RequestBody() { - @Override public MediaType contentType() { - return body.contentType(); - } - - @Override public long contentLength() { - return -1; // We don't know the compressed length in advance! - } - - @Override public void writeTo(BufferedSink sink) throws IOException { - BufferedSink gzipSink = Okio.buffer(new GzipSink(sink)); - body.writeTo(gzipSink); - gzipSink.close(); - } - }; - } + Timber.d("Compressing"); + Request compressedRequest = originalRequest.newBuilder() + .header("Content-Encoding", "gzip") + .method(originalRequest.method(), gzip(originalRequest.body())) + .build(); + return chain.proceed(compressedRequest); + } + + private RequestBody gzip(final RequestBody body) { + return new RequestBody() { + @Override + public MediaType contentType() { + return body.contentType(); + } + + @Override + public long contentLength() { + return -1; // We don't know the compressed length in advance! + } + + @Override + public void writeTo(BufferedSink sink) throws IOException { + BufferedSink gzipSink = Okio.buffer(new GzipSink(sink)); + body.writeTo(gzipSink); + gzipSink.close(); + } + }; + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java index a3545df565..b125b35cf3 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java @@ -4,7 +4,6 @@ import android.graphics.PointF; import android.support.annotation.NonNull; import com.mapbox.mapboxsdk.geometry.LatLng; -import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.maps.Projection; import java.io.Serializable; @@ -16,128 +15,133 @@ import timber.log.Timber; * Constants for Telemetry Metadata */ public class MapboxEvent implements Serializable { - public static final int VERSION_NUMBER = 2; - public static final String MAPBOX_EVENTS_BASE_URL = "https://events.mapbox.com"; - public static final String SOURCE_MAPBOX = "mapbox"; - - // Event Types - public static final String TYPE_TURNSTILE = "appUserTurnstile"; - public static final String TYPE_MAP_LOAD = "map.load"; - public static final String TYPE_MAP_CLICK = "map.click"; - public static final String TYPE_MAP_DRAGEND = "map.dragend"; - public static final String TYPE_LOCATION = "location"; - public static final String TYPE_VISIT = "visit"; - - // Event Keys - public static final String KEY_LATITUDE = "lat"; - public static final String KEY_LONGITUDE = "lng"; - public static final String KEY_SPEED = "speed"; - public static final String KEY_COURSE = "course"; - public static final String KEY_ALTITUDE = "altitude"; - public static final String KEY_HORIZONTAL_ACCURACY = "horizontalAccuracy"; - public static final String KEY_ZOOM = "zoom"; - - public static final String KEY_PUSH_ENABLED = "enabled.push"; - public static final String KEY_EMAIL_ENABLED = "enabled.email"; - public static final String KEY_GESTURE_ID = "gesture"; - public static final String KEY_ARRIVAL_DATE = "arrivalDate"; - public static final String KEY_DEPARTURE_DATE = "departureDate"; - - public static final String GESTURE_SINGLETAP = "SingleTap"; - public static final String GESTURE_DOUBLETAP = "DoubleTap"; - public static final String GESTURE_TWO_FINGER_SINGLETAP = "TwoFingerTap"; - public static final String GESTURE_QUICK_ZOOM = "QuickZoom"; - public static final String GESTURE_PAN_START = "Pan"; - public static final String GESTURE_PINCH_START = "Pinch"; - public static final String GESTURE_ROTATION_START = "Rotation"; - public static final String GESTURE_PITCH_START = "Pitch"; - - // Event Attributes - public static final String ATTRIBUTE_EVENT = "event"; - public static final String ATTRIBUTE_USERID = "userId"; - public static final String ATTRIBUTE_SOURCE = "source"; - public static final String ATTRIBUTE_ENABLED_TELEMETRY = "enabled.telemetry"; - public static final String ATTRIBUTE_SESSION_ID = "sessionId"; - public static final String ATTRIBUTE_VERSION = "version"; - public static final String ATTRIBUTE_CREATED = "created"; - public static final String ATTRIBUTE_VENDOR_ID = "vendorId"; - public static final String ATTRIBUTE_APP_BUNDLE_ID = "appBundleId"; - public static final String ATTRIBUTE_MODEL = "model"; - public static final String ATTRIBUTE_OPERATING_SYSTEM = "operatingSystem"; - public static final String ATTRIBUTE_ORIENTATION = "orientation"; - public static final String ATTRIBUTE_BATTERY_LEVEL = "batteryLevel"; - public static final String ATTRIBUTE_PLUGGED_IN = "pluggedIn"; - public static final String ATTRIBUTE_APPLICATION_STATE = "applicationState"; - public static final String ATTRIBUTE_RESOLUTION = "resolution"; - public static final String ATTRIBUTE_ACCESSIBILITY_FONT_SCALE = "accessibilityFontScale"; - public static final String ATTRIBUTE_CARRIER = "carrier"; - public static final String ATTRIBUTE_CELLULAR_NETWORK_TYPE = "cellularNetworkType"; - public static final String ATTRIBUTE_WIFI = "wifi"; - - /** - * Helper method for tracking gesture events - * - * @param projection Projection of the Map object - * @param gestureId Type of Gesture See {@see MapboxEvent#GESTURE_SINGLETAP MapboxEvent#GESTURE_DOUBLETAP MapboxEvent#GESTURE_TWO_FINGER_SINGLETAP MapboxEvent#GESTURE_QUICK_ZOOM MapboxEvent#GESTURE_PAN_START MapboxEvent#GESTURE_PINCH_START MapboxEvent#GESTURE_ROTATION_START MapboxEvent#GESTURE_PITCH_START} - * @param xCoordinate Original x screen coordinate at start of gesture - * @param yCoordinate Original y screen cooridnate at start of gesture - * @param zoom Zoom level to be registered - */ - public static void trackGestureEvent(@NonNull Projection projection, @NonNull String gestureId, float xCoordinate, float yCoordinate, double zoom) { - LatLng tapLatLng = projection.fromScreenLocation(new PointF(xCoordinate, yCoordinate)); - - // NaN and Infinite checks to prevent JSON errors at send to server time - if (Double.isNaN(tapLatLng.getLatitude()) || Double.isNaN(tapLatLng.getLongitude())) { - Timber.d("trackGestureEvent() has a NaN lat or lon. Returning."); - return; - } - - if (Double.isInfinite(tapLatLng.getLatitude()) || Double.isInfinite(tapLatLng.getLongitude())) { - Timber.d("trackGestureEvent() has an Infinite lat or lon. Returning."); - return; - } - - Hashtable<String, Object> evt = new Hashtable<>(); - evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_CLICK); - evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate()); - evt.put(MapboxEvent.KEY_GESTURE_ID, gestureId); - evt.put(MapboxEvent.KEY_LATITUDE, tapLatLng.getLatitude()); - evt.put(MapboxEvent.KEY_LONGITUDE, tapLatLng.getLongitude()); - evt.put(MapboxEvent.KEY_ZOOM, zoom); - - MapboxEventManager.getMapboxEventManager().pushEvent(evt); + public static final int VERSION_NUMBER = 2; + public static final String MAPBOX_EVENTS_BASE_URL = "https://events.mapbox.com"; + public static final String SOURCE_MAPBOX = "mapbox"; + + // Event Types + public static final String TYPE_TURNSTILE = "appUserTurnstile"; + public static final String TYPE_MAP_LOAD = "map.load"; + public static final String TYPE_MAP_CLICK = "map.click"; + public static final String TYPE_MAP_DRAGEND = "map.dragend"; + public static final String TYPE_LOCATION = "location"; + public static final String TYPE_VISIT = "visit"; + + // Event Keys + public static final String KEY_LATITUDE = "lat"; + public static final String KEY_LONGITUDE = "lng"; + public static final String KEY_SPEED = "speed"; + public static final String KEY_COURSE = "course"; + public static final String KEY_ALTITUDE = "altitude"; + public static final String KEY_HORIZONTAL_ACCURACY = "horizontalAccuracy"; + public static final String KEY_ZOOM = "zoom"; + + public static final String KEY_PUSH_ENABLED = "enabled.push"; + public static final String KEY_EMAIL_ENABLED = "enabled.email"; + public static final String KEY_GESTURE_ID = "gesture"; + public static final String KEY_ARRIVAL_DATE = "arrivalDate"; + public static final String KEY_DEPARTURE_DATE = "departureDate"; + + public static final String GESTURE_SINGLETAP = "SingleTap"; + public static final String GESTURE_DOUBLETAP = "DoubleTap"; + public static final String GESTURE_TWO_FINGER_SINGLETAP = "TwoFingerTap"; + public static final String GESTURE_QUICK_ZOOM = "QuickZoom"; + public static final String GESTURE_PAN_START = "Pan"; + public static final String GESTURE_PINCH_START = "Pinch"; + public static final String GESTURE_ROTATION_START = "Rotation"; + public static final String GESTURE_PITCH_START = "Pitch"; + + // Event Attributes + public static final String ATTRIBUTE_EVENT = "event"; + public static final String ATTRIBUTE_USERID = "userId"; + public static final String ATTRIBUTE_SOURCE = "source"; + public static final String ATTRIBUTE_ENABLED_TELEMETRY = "enabled.telemetry"; + public static final String ATTRIBUTE_SESSION_ID = "sessionId"; + public static final String ATTRIBUTE_VERSION = "version"; + public static final String ATTRIBUTE_CREATED = "created"; + public static final String ATTRIBUTE_VENDOR_ID = "vendorId"; + public static final String ATTRIBUTE_APP_BUNDLE_ID = "appBundleId"; + public static final String ATTRIBUTE_MODEL = "model"; + public static final String ATTRIBUTE_OPERATING_SYSTEM = "operatingSystem"; + public static final String ATTRIBUTE_ORIENTATION = "orientation"; + public static final String ATTRIBUTE_BATTERY_LEVEL = "batteryLevel"; + public static final String ATTRIBUTE_PLUGGED_IN = "pluggedIn"; + public static final String ATTRIBUTE_APPLICATION_STATE = "applicationState"; + public static final String ATTRIBUTE_RESOLUTION = "resolution"; + public static final String ATTRIBUTE_ACCESSIBILITY_FONT_SCALE = "accessibilityFontScale"; + public static final String ATTRIBUTE_CARRIER = "carrier"; + public static final String ATTRIBUTE_CELLULAR_NETWORK_TYPE = "cellularNetworkType"; + public static final String ATTRIBUTE_WIFI = "wifi"; + + /** + * Helper method for tracking gesture events + * + * @param projection Projection of the Map object + * @param gestureId Type of Gesture See {@see MapboxEvent#GESTURE_SINGLETAP MapboxEvent#GESTURE_DOUBLETAP + * MapboxEvent#GESTURE_TWO_FINGER_SINGLETAP MapboxEvent#GESTURE_QUICK_ZOOM + * MapboxEvent#GESTURE_PAN_START MapboxEvent#GESTURE_PINCH_START + * MapboxEvent#GESTURE_ROTATION_START MapboxEvent#GESTURE_PITCH_START} + * @param xCoordinate Original x screen coordinate at start of gesture + * @param yCoordinate Original y screen cooridnate at start of gesture + * @param zoom Zoom level to be registered + */ + public static void trackGestureEvent(@NonNull Projection projection, @NonNull String gestureId, + float xCoordinate, float yCoordinate, double zoom) { + LatLng tapLatLng = projection.fromScreenLocation(new PointF(xCoordinate, yCoordinate)); + + // NaN and Infinite checks to prevent JSON errors at send to server time + if (Double.isNaN(tapLatLng.getLatitude()) || Double.isNaN(tapLatLng.getLongitude())) { + Timber.d("trackGestureEvent() has a NaN lat or lon. Returning."); + return; } - /** - * Helper method for tracking DragEnd gesture event - * See {@see MapboxEvent#TYPE_MAP_DRAGEND} - * - * @param projection projection of the Map object. - * @param xCoordinate Original x screen coordinate at end of drag - * @param yCoordinate Orginal y screen coordinate at end of drag - * @param zoom Zoom level to be registered - */ - public static void trackGestureDragEndEvent(@NonNull Projection projection, float xCoordinate, float yCoordinate, double zoom) { - LatLng tapLatLng = projection.fromScreenLocation(new PointF(xCoordinate, yCoordinate)); - - // NaN and Infinite checks to prevent JSON errors at send to server time - if (Double.isNaN(tapLatLng.getLatitude()) || Double.isNaN(tapLatLng.getLongitude())) { - Timber.d("trackGestureDragEndEvent() has a NaN lat or lon. Returning."); - return; - } - - if (Double.isInfinite(tapLatLng.getLatitude()) || Double.isInfinite(tapLatLng.getLongitude())) { - Timber.d("trackGestureDragEndEvent() has an Infinite lat or lon. Returning."); - return; - } - - Hashtable<String, Object> evt = new Hashtable<>(); - evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_DRAGEND); - evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate()); - evt.put(MapboxEvent.KEY_LATITUDE, tapLatLng.getLatitude()); - evt.put(MapboxEvent.KEY_LONGITUDE, tapLatLng.getLongitude()); - evt.put(MapboxEvent.KEY_ZOOM, zoom); - - MapboxEventManager.getMapboxEventManager().pushEvent(evt); + if (Double.isInfinite(tapLatLng.getLatitude()) || Double.isInfinite(tapLatLng.getLongitude())) { + Timber.d("trackGestureEvent() has an Infinite lat or lon. Returning."); + return; } + + Hashtable<String, Object> evt = new Hashtable<>(); + evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_CLICK); + evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate()); + evt.put(MapboxEvent.KEY_GESTURE_ID, gestureId); + evt.put(MapboxEvent.KEY_LATITUDE, tapLatLng.getLatitude()); + evt.put(MapboxEvent.KEY_LONGITUDE, tapLatLng.getLongitude()); + evt.put(MapboxEvent.KEY_ZOOM, zoom); + + MapboxEventManager.getMapboxEventManager().pushEvent(evt); + } + + /** + * Helper method for tracking DragEnd gesture event + * See {@see MapboxEvent#TYPE_MAP_DRAGEND} + * + * @param projection projection of the Map object. + * @param xCoordinate Original x screen coordinate at end of drag + * @param yCoordinate Orginal y screen coordinate at end of drag + * @param zoom Zoom level to be registered + */ + public static void trackGestureDragEndEvent(@NonNull Projection projection, float xCoordinate, + float yCoordinate, double zoom) { + LatLng tapLatLng = projection.fromScreenLocation(new PointF(xCoordinate, yCoordinate)); + + // NaN and Infinite checks to prevent JSON errors at send to server time + if (Double.isNaN(tapLatLng.getLatitude()) || Double.isNaN(tapLatLng.getLongitude())) { + Timber.d("trackGestureDragEndEvent() has a NaN lat or lon. Returning."); + return; + } + + if (Double.isInfinite(tapLatLng.getLatitude()) || Double.isInfinite(tapLatLng.getLongitude())) { + Timber.d("trackGestureDragEndEvent() has an Infinite lat or lon. Returning."); + return; + } + + Hashtable<String, Object> evt = new Hashtable<>(); + evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_DRAGEND); + evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate()); + evt.put(MapboxEvent.KEY_LATITUDE, tapLatLng.getLatitude()); + evt.put(MapboxEvent.KEY_LONGITUDE, tapLatLng.getLongitude()); + evt.put(MapboxEvent.KEY_ZOOM, zoom); + + MapboxEventManager.getMapboxEventManager().pushEvent(evt); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java index 22624677c5..6deb961584 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java @@ -21,13 +21,11 @@ import android.support.annotation.NonNull; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.DisplayMetrics; -import timber.log.Timber; import android.view.WindowManager; import com.mapbox.mapboxsdk.BuildConfig; import com.mapbox.mapboxsdk.MapboxAccountManager; import com.mapbox.mapboxsdk.constants.GeoConstants; -import com.mapbox.mapboxsdk.constants.MapboxConstants; import com.mapbox.mapboxsdk.exceptions.TelemetryServiceNotConfiguredException; import com.mapbox.mapboxsdk.location.LocationServices; import com.mapbox.mapboxsdk.utils.MathUtils; @@ -53,6 +51,46 @@ import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import okhttp3.internal.Util; +import timber.log.Timber; + +import static com.mapbox.mapboxsdk.constants.MapboxConstants.KEY_META_DATA_STAGING_ACCESS_TOKEN; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.KEY_META_DATA_STAGING_SERVER; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.MAPBOX_LOCALE; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.MAPBOX_SHARED_PREFERENCES_FILE; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_ENABLED; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_ACCESS_TOKEN; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_URL; +import static com.mapbox.mapboxsdk.constants.MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_VENDORID; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.ATTRIBUTE_ACCESSIBILITY_FONT_SCALE; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.ATTRIBUTE_APPLICATION_STATE; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.ATTRIBUTE_BATTERY_LEVEL; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.ATTRIBUTE_CARRIER; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.ATTRIBUTE_CREATED; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.ATTRIBUTE_ENABLED_TELEMETRY; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.ATTRIBUTE_EVENT; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.ATTRIBUTE_MODEL; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.ATTRIBUTE_ORIENTATION; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.ATTRIBUTE_PLUGGED_IN; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.ATTRIBUTE_RESOLUTION; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.ATTRIBUTE_SESSION_ID; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.ATTRIBUTE_SOURCE; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.ATTRIBUTE_USERID; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.ATTRIBUTE_WIFI; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.KEY_ALTITUDE; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.KEY_GESTURE_ID; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.KEY_HORIZONTAL_ACCURACY; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.KEY_LATITUDE; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.KEY_LONGITUDE; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.KEY_ZOOM; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.MAPBOX_EVENTS_BASE_URL; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.SOURCE_MAPBOX; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.TYPE_LOCATION; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.TYPE_MAP_CLICK; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.TYPE_MAP_DRAGEND; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.TYPE_MAP_LOAD; +import static com.mapbox.mapboxsdk.telemetry.MapboxEvent.TYPE_TURNSTILE; /** * Singleton control center for managing Telemetry Data. @@ -60,733 +98,749 @@ import okhttp3.internal.Util; */ public class MapboxEventManager { - private static MapboxEventManager mapboxEventManager = null; + private static MapboxEventManager mapboxEventManager = null; - private boolean initialized = false; - private boolean stagingEnv; - private boolean telemetryEnabled; + private boolean initialized = false; + private boolean stagingEnv; + private boolean telemetryEnabled; - private final Vector<Hashtable<String, Object>> events = new Vector<>(); - private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); - private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", MapboxConstants.MAPBOX_LOCALE); + private final Vector<Hashtable<String, Object>> events = new Vector<>(); + private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); + private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", MAPBOX_LOCALE); - private Context context = null; - private String accessToken = null; - private String eventsURL = MapboxEvent.MAPBOX_EVENTS_BASE_URL; + private Context context = null; + private String accessToken = null; + private String eventsURL = MAPBOX_EVENTS_BASE_URL; - private String userAgent = BuildConfig.MAPBOX_EVENTS_USER_AGENT_BASE; + private String userAgent = BuildConfig.MAPBOX_EVENTS_USER_AGENT_BASE; - private Intent batteryStatus = null; - private final String operatingSystem = "Android - " + Build.VERSION.RELEASE; + private Intent batteryStatus = null; + private final String operatingSystem = "Android - " + Build.VERSION.RELEASE; - private DisplayMetrics displayMetrics = null; + private DisplayMetrics displayMetrics = null; - private String mapboxVendorId = null; + private String mapboxVendorId = null; - private String mapboxSessionId = null; - private long mapboxSessionIdLastSet = 0; - private static long hourInMillis = 1000 * 60 * 60; - private static long flushDelayInitialInMillis = 1000 * 10; // 10 Seconds - private static long flushDelayInMillis = 1000 * 60 * 3; // 3 Minutes - private static final int SESSION_ID_ROTATION_HOURS = 24; + private String mapboxSessionId = null; + private long mapboxSessionIdLastSet = 0; + private static long hourInMillis = 1000 * 60 * 60; + private static long flushDelayInitialInMillis = 1000 * 10; // 10 Seconds + private static long flushDelayInMillis = 1000 * 60 * 3; // 3 Minutes + private static final int SESSION_ID_ROTATION_HOURS = 24; - private static final int FLUSH_EVENTS_CAP = 1000; + private static final int FLUSH_EVENTS_CAP = 1000; - private static MessageDigest messageDigest = null; + private static MessageDigest messageDigest = null; - private static final double locationEventAccuracy = 10000000; + private static final double locationEventAccuracy = 10000000; - private Timer timer = null; + private Timer timer = null; - /** - * Private Constructor for configuring the single instance per app. - */ - private MapboxEventManager() { - super(); - } - - /** - * Internal setup of MapboxEventsManager. It needs to be called once before @link MapboxEventManager#getMapboxEventManager - * - * This allows for a cleaner getMapboxEventManager() that doesn't require context and accessToken - * - * @param context The context associated with MapView - * @param accessToken The accessToken to load MapView - */ - public void initialize(@NonNull Context context, @NonNull String accessToken) { + /** + * Private Constructor for configuring the single instance per app. + */ + private MapboxEventManager() { + super(); + } - Timber.i("Telemetry initialize() called..."); - - if (initialized) { - Timber.i("Mapbox Telemetry has already been initialized."); - return; - } - - this.context = context.getApplicationContext(); - this.accessToken = accessToken; - - validateTelemetryServiceConfigured(); - - // Setup Message Digest - try { - messageDigest = MessageDigest.getInstance("SHA-1"); - } catch (NoSuchAlgorithmException e) { - Timber.w("Error getting Encryption Algorithm: " + e); - } + /** + * Internal setup of MapboxEventsManager. It needs to be called once before + * {@link MapboxEventManager#getMapboxEventManager} + * <p> + * This allows for a cleaner getMapboxEventManager() that doesn't require context and accessToken + * + * @param context The context associated with MapView + * @param accessToken The accessToken to load MapView + */ + public void initialize(@NonNull Context context, @NonNull String accessToken) { - // Create Initial Session Id - rotateSessionId(); + Timber.i("Telemetry initialize() called..."); - SharedPreferences prefs = context.getSharedPreferences(MapboxConstants.MAPBOX_SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE); + if (initialized) { + Timber.i("Mapbox Telemetry has already been initialized."); + return; + } - // Determine if Telemetry Should Be Enabled - Timber.i("Right before Telemetry set enabled in initialized()"); - setTelemetryEnabled(prefs.getBoolean(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_ENABLED, true)); + this.context = context.getApplicationContext(); + this.accessToken = accessToken; - // Load / Create Vendor Id - if (prefs.contains(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_VENDORID)) { - mapboxVendorId = prefs.getString(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_VENDORID, ""); - } - if (TextUtils.isEmpty(mapboxVendorId)) { - String vendorId = UUID.randomUUID().toString(); - mapboxVendorId = encodeString(vendorId); - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_VENDORID, mapboxVendorId); - editor.apply(); - editor.commit(); - } + validateTelemetryServiceConfigured(); - // Get DisplayMetrics Setup - displayMetrics = new DisplayMetrics(); - ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(displayMetrics); + // Setup Message Digest + try { + messageDigest = MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException noSuchAlgorithmException) { + Timber.w("Error getting Encryption Algorithm: " + noSuchAlgorithmException); + } - // Check for Staging Server Information - try { - ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA); - String stagingURL = appInfo.metaData.getString(MapboxConstants.KEY_META_DATA_STAGING_SERVER); - String stagingAccessToken = appInfo.metaData.getString(MapboxConstants.KEY_META_DATA_STAGING_ACCESS_TOKEN); + // Create Initial Session Id + rotateSessionId(); - if (TextUtils.isEmpty(stagingURL) || TextUtils.isEmpty(stagingAccessToken)) { - Timber.d("Looking in SharedPreferences for Staging Credentials"); - stagingURL = prefs.getString(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_URL, null); - stagingAccessToken = prefs.getString(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_ACCESS_TOKEN, null); - } + SharedPreferences prefs = context.getSharedPreferences(MAPBOX_SHARED_PREFERENCES_FILE, + Context.MODE_PRIVATE); - if (!TextUtils.isEmpty(stagingURL) && !TextUtils.isEmpty(stagingAccessToken)) { - eventsURL = stagingURL; - this.accessToken = accessToken; - stagingEnv = true; - } + // Determine if Telemetry Should Be Enabled + Timber.i("Right before Telemetry set enabled in initialized()"); + setTelemetryEnabled(prefs.getBoolean(MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_ENABLED, true)); - // Build User Agent - String appIdentifier = getApplicationIdentifier(); - if (TextUtils.equals(userAgent, BuildConfig.MAPBOX_EVENTS_USER_AGENT_BASE) && !TextUtils.isEmpty(appIdentifier)) { - userAgent = Util.toHumanReadableAscii(String.format(MapboxConstants.MAPBOX_LOCALE, "%s %s", appIdentifier, userAgent)); - } + // Load / Create Vendor Id + if (prefs.contains(MAPBOX_SHARED_PREFERENCE_KEY_VENDORID)) { + mapboxVendorId = prefs.getString(MAPBOX_SHARED_PREFERENCE_KEY_VENDORID, ""); + } + if (TextUtils.isEmpty(mapboxVendorId)) { + String vendorId = UUID.randomUUID().toString(); + mapboxVendorId = encodeString(vendorId); + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(MAPBOX_SHARED_PREFERENCE_KEY_VENDORID, mapboxVendorId); + editor.apply(); + editor.commit(); + } - } catch (Exception e) { - Timber.e("Error Trying to load Staging Credentials: " + e.toString()); - } + // Get DisplayMetrics Setup + displayMetrics = new DisplayMetrics(); + ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(displayMetrics); + + // Check for Staging Server Information + try { + ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), + PackageManager.GET_META_DATA); + String stagingURL = appInfo.metaData.getString(KEY_META_DATA_STAGING_SERVER); + String stagingAccessToken = appInfo.metaData.getString(KEY_META_DATA_STAGING_ACCESS_TOKEN); + + if (TextUtils.isEmpty(stagingURL) || TextUtils.isEmpty(stagingAccessToken)) { + Timber.d("Looking in SharedPreferences for Staging Credentials"); + stagingURL = prefs.getString(MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_URL, null); + stagingAccessToken = prefs.getString(MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_STAGING_ACCESS_TOKEN, null); + } + + if (!TextUtils.isEmpty(stagingURL) && !TextUtils.isEmpty(stagingAccessToken)) { + eventsURL = stagingURL; + this.accessToken = accessToken; + stagingEnv = true; + } - // Register for battery updates - IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); - batteryStatus = context.registerReceiver(null, iFilter); + // Build User Agent + String appIdentifier = getApplicationIdentifier(); + if (TextUtils.equals(userAgent, BuildConfig.MAPBOX_EVENTS_USER_AGENT_BASE) && !TextUtils.isEmpty(appIdentifier)) { + userAgent = Util.toHumanReadableAscii(String.format(MAPBOX_LOCALE, "%s %s", appIdentifier, userAgent)); + } - initialized = true; + } catch (Exception exception) { + Timber.e("Error Trying to load Staging Credentials: " + exception.toString()); } - /** - * Primary Access method using Singleton pattern - * - * @return MapboxEventManager - */ - public static MapboxEventManager getMapboxEventManager() { - if (mapboxEventManager == null) { - mapboxEventManager = new MapboxEventManager(); - } - return mapboxEventManager; + // Register for battery updates + IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); + batteryStatus = context.registerReceiver(null, iFilter); + + initialized = true; + } + + /** + * Primary Access method using Singleton pattern + * + * @return MapboxEventManager + */ + public static MapboxEventManager getMapboxEventManager() { + if (mapboxEventManager == null) { + mapboxEventManager = new MapboxEventManager(); } - - // Checks that TelemetryService has been configured by developer - private void validateTelemetryServiceConfigured() { - try { - // Check Implementing app's AndroidManifest.xml - PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SERVICES); - if (packageInfo.services != null) { - for (ServiceInfo service : packageInfo.services) { - if (TextUtils.equals("com.mapbox.mapboxsdk.telemetry.TelemetryService", service.name)) { - return; - } - } - } - } catch (Exception e) { - Timber.w("Error checking for Telemetry Service Config: " + e); + return mapboxEventManager; + } + + // Checks that TelemetryService has been configured by developer + private void validateTelemetryServiceConfigured() { + try { + // Check Implementing app's AndroidManifest.xml + PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), + PackageManager.GET_SERVICES); + if (packageInfo.services != null) { + for (ServiceInfo service : packageInfo.services) { + if (TextUtils.equals("com.mapbox.mapboxsdk.telemetry.TelemetryService", service.name)) { + return; + } } - throw new TelemetryServiceNotConfiguredException(); + } + } catch (Exception exception) { + Timber.w("Error checking for Telemetry Service Config: " + exception); } - - public static String generateCreateDate() { - return dateFormat.format(new Date()); + throw new TelemetryServiceNotConfiguredException(); + } + + public static String generateCreateDate() { + return dateFormat.format(new Date()); + } + + public boolean isTelemetryEnabled() { + return telemetryEnabled; + } + + /** + * Enables / Disables Telemetry + * + * @param telemetryEnabled True to start telemetry, false to stop it + */ + public void setTelemetryEnabled(boolean telemetryEnabled) { + Timber.i("setTelemetryEnabled(); this.telemetryEnabled = " + this.telemetryEnabled + "; telemetryEnabled = " + + telemetryEnabled); + if (this.telemetryEnabled == telemetryEnabled) { + Timber.d("No need to start / stop telemetry as it's already in that state."); + return; } - public boolean isTelemetryEnabled() { - return telemetryEnabled; - } + if (telemetryEnabled) { + Timber.d("Starting Telemetry Up!"); + // Start It Up + context.startService(new Intent(context, TelemetryService.class)); - /** - * Enables / Disables Telemetry - * @param telemetryEnabled True to start telemetry, false to stop it - */ - public void setTelemetryEnabled(boolean telemetryEnabled) { - Timber.i("setTelemetryEnabled(); this.telemetryEnabled = " + this.telemetryEnabled + "; telemetryEnabled = " + telemetryEnabled); - if (this.telemetryEnabled == telemetryEnabled) { - Timber.d("No need to start / stop telemetry as it's already in that state."); - return; + // Make sure Ambient Mode is started at a minimum + if (LocationServices.getLocationServices(context).areLocationPermissionsGranted()) { + Timber.i("Permissions are good, see if GPS is enabled and if not then setup Ambient."); + if (LocationServices.getLocationServices(context).isGpsEnabled()) { + LocationServices.getLocationServices(context).toggleGPS(false); } - - if (telemetryEnabled) { - Timber.d("Starting Telemetry Up!"); - // Start It Up - context.startService(new Intent(context, TelemetryService.class)); - - // Make sure Ambient Mode is started at a minimum + } else { + // Start timer that checks for Permissions + Timber.i("Permissions are not good. Need to do some looping to check on stuff."); + + final Handler permsHandler = new Handler(); + Runnable runnable = new Runnable() { + @Override + public void run() { if (LocationServices.getLocationServices(context).areLocationPermissionsGranted()) { - Timber.i("Permissions are good, see if GPS is enabled and if not then setup Ambient."); - if (LocationServices.getLocationServices(context).isGPSEnabled()) { - LocationServices.getLocationServices(context).toggleGPS(false); - } + Timber.i("Permissions finally granted, so starting Ambient if GPS isn't already enabled"); + // Start Ambient + if (LocationServices.getLocationServices(context).isGpsEnabled()) { + LocationServices.getLocationServices(context).toggleGPS(false); + } } else { - // Start timer that checks for Permissions - Timber.i("Permissions are not good. Need to do some looping to check on stuff."); - - final Handler permsHandler = new Handler(); - Runnable runnable = new Runnable() { - @Override - public void run() { - if (LocationServices.getLocationServices(context).areLocationPermissionsGranted()) { - Timber.i("Permissions finally granted, so starting Ambient if GPS isn't already enabled"); - // Start Ambient - if (LocationServices.getLocationServices(context).isGPSEnabled()) { - LocationServices.getLocationServices(context).toggleGPS(false); - } - } else { - // Restart Handler - Timber.i("Permissions not granted yet... let's try again in 30 seconds"); - permsHandler.postDelayed(this, 1000 * 30); - } - } - }; - permsHandler.postDelayed(runnable, 1000 * 10); + // Restart Handler + Timber.i("Permissions not granted yet... let's try again in 30 seconds"); + permsHandler.postDelayed(this, 1000 * 30); } - - // Manage Timer Flush - timer = new Timer(); - timer.schedule(new FlushEventsTimerTask(), flushDelayInitialInMillis, flushDelayInMillis); - } else { - Timber.d("Shutting Telemetry Down"); - // Shut It Down - events.removeAllElements(); - context.stopService(new Intent(context, TelemetryService.class)); - - if (timer != null) { - timer.cancel(); - timer = null; - } - } - - // Persist - this.telemetryEnabled = telemetryEnabled; - SharedPreferences prefs = context.getSharedPreferences(MapboxConstants.MAPBOX_SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE); - SharedPreferences.Editor editor = prefs.edit(); - editor.putBoolean(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_ENABLED, telemetryEnabled); - editor.apply(); - editor.commit(); + } + }; + permsHandler.postDelayed(runnable, 1000 * 10); + } + + // Manage Timer Flush + timer = new Timer(); + timer.schedule(new FlushEventsTimerTask(), flushDelayInitialInMillis, flushDelayInMillis); + } else { + Timber.d("Shutting Telemetry Down"); + // Shut It Down + events.removeAllElements(); + context.stopService(new Intent(context, TelemetryService.class)); + + if (timer != null) { + timer.cancel(); + timer = null; + } } - /** - * Immediately attempt to send all events data in the queue to the server. - * - * NOTE: Permission set to package private to enable only telemetry code to use this. - */ - void flushEventsQueueImmediately() { - Timber.i("flushEventsQueueImmediately() called..."); - new FlushTheEventsTask().execute(); + // Persist + this.telemetryEnabled = telemetryEnabled; + SharedPreferences prefs = context.getSharedPreferences(MAPBOX_SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean(MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_ENABLED, telemetryEnabled); + editor.apply(); + editor.commit(); + } + + /** + * Immediately attempt to send all events data in the queue to the server. + * <p> + * NOTE: Permission set to package private to enable only telemetry code to use this. + */ + void flushEventsQueueImmediately() { + Timber.i("flushEventsQueueImmediately() called..."); + new FlushTheEventsTask().execute(); + } + + /** + * Centralized method for adding populated event to the queue allowing for cap size checking + * + * @param event Event to add to the Events Queue + */ + private void putEventOnQueue(@NonNull Hashtable<String, Object> event) { + if (event == null) { + return; } - - /** - * Centralized method for adding populated event to the queue allowing for cap size checking - * @param event Event to add to the Events Queue - */ - private void putEventOnQueue(@NonNull Hashtable<String, Object> event) { - if (event == null) { - return; - } - events.add(event); - if (events.size() == FLUSH_EVENTS_CAP) { - Timber.d("eventsSize == flushCap so send data."); - flushEventsQueueImmediately(); - } + events.add(event); + if (events.size() == FLUSH_EVENTS_CAP) { + Timber.d("eventsSize == flushCap so send data."); + flushEventsQueueImmediately(); } - - /** - * Adds a Location Event to the system for processing - * - * @param location Location event - */ - public void addLocationEvent(Location location) { - - // NaN and Infinite checks to prevent JSON errors at send to server time - if (Double.isNaN(location.getLatitude()) || Double.isNaN(location.getLongitude()) || Double.isNaN(location.getAltitude()) || Float.isNaN(location.getAccuracy())) { - return; - } - - if (Double.isInfinite(location.getLatitude()) || Double.isInfinite(location.getLongitude()) || Double.isInfinite(location.getAltitude()) || Float.isInfinite(location.getAccuracy())) { - return; - } - - // Add Location even to queue - Hashtable<String, Object> event = new Hashtable<>(); - event.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_LOCATION); - event.put(MapboxEvent.ATTRIBUTE_CREATED, generateCreateDate()); - event.put(MapboxEvent.ATTRIBUTE_SOURCE, MapboxEvent.SOURCE_MAPBOX); - event.put(MapboxEvent.ATTRIBUTE_SESSION_ID, encodeString(mapboxSessionId)); - event.put(MapboxEvent.KEY_LATITUDE, Math.floor(location.getLatitude() * locationEventAccuracy) / locationEventAccuracy); - event.put(MapboxEvent.KEY_LONGITUDE, Math.floor(location.getLongitude() * locationEventAccuracy) / locationEventAccuracy); - event.put(MapboxEvent.KEY_ALTITUDE, location.getAltitude()); - event.put(MapboxEvent.KEY_HORIZONTAL_ACCURACY, Math.round(location.getAccuracy())); - event.put(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM, operatingSystem); - event.put(MapboxEvent.ATTRIBUTE_APPLICATION_STATE, getApplicationState()); - - putEventOnQueue(event); - - rotateSessionId(); + } + + /** + * Adds a Location Event to the system for processing + * + * @param location Location event + */ + public void addLocationEvent(Location location) { + + // NaN and Infinite checks to prevent JSON errors at send to server time + if (Double.isNaN(location.getLatitude()) || Double.isNaN(location.getLongitude()) + || Double.isNaN(location.getAltitude()) || Float.isNaN(location.getAccuracy())) { + return; } - /** - * Push Interactive Events to the system for processing - * - * @param eventWithAttributes Event with attributes - */ - public void pushEvent(Hashtable<String, Object> eventWithAttributes) { - if (context == null || accessToken == null) { - return; - } - - if (eventWithAttributes == null) { - return; - } - - String eventType = (String) eventWithAttributes.get(MapboxEvent.ATTRIBUTE_EVENT); - if (TextUtils.isEmpty(eventType)) { - return; - } - - if (eventType.equalsIgnoreCase(MapboxEvent.TYPE_MAP_LOAD)) { - // Map Load Data Model - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_USERID, mapboxVendorId); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_MODEL, Build.MODEL); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM, operatingSystem); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_RESOLUTION, displayMetrics.density); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_ACCESSIBILITY_FONT_SCALE, getAccesibilityFontScaleSize()); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_ORIENTATION, getOrientation()); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL, getBatteryLevel()); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_PLUGGED_IN, isPluggedIn()); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CARRIER, getCellularCarrier()); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, getCellularNetworkType()); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_WIFI, getConnectedToWifi()); - - // Put Map Load on events before Turnstile clears it - putEventOnQueue(eventWithAttributes); - - // Turnstile - pushTurnstileEvent(); - - // Return immediately to avoid double adding of event - return; - - } else if (eventType.equalsIgnoreCase(MapboxEvent.TYPE_MAP_CLICK)) { - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_ORIENTATION, getOrientation()); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL, getBatteryLevel()); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_PLUGGED_IN, isPluggedIn()); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CARRIER, getCellularCarrier()); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, getCellularNetworkType()); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_WIFI, getConnectedToWifi()); - } else if (eventType.equalsIgnoreCase(MapboxEvent.TYPE_MAP_DRAGEND)) { - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_ORIENTATION, getOrientation()); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL, getBatteryLevel()); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_PLUGGED_IN, isPluggedIn()); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CARRIER, getCellularCarrier()); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, getCellularNetworkType()); - eventWithAttributes.put(MapboxEvent.ATTRIBUTE_WIFI, getConnectedToWifi()); - } else { - Timber.w("This is not an event type in the Events Data Model."); - return; - } - - putEventOnQueue(eventWithAttributes); + if (Double.isInfinite(location.getLatitude()) || Double.isInfinite(location.getLongitude()) + || Double.isInfinite(location.getAltitude()) || Float.isInfinite(location.getAccuracy())) { + return; } - /** - * Pushes turnstile event for internal billing purposes - */ - private void pushTurnstileEvent() { - - Hashtable<String, Object> event = new Hashtable<>(); - event.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_TURNSTILE); - event.put(MapboxEvent.ATTRIBUTE_CREATED, generateCreateDate()); - event.put(MapboxEvent.ATTRIBUTE_USERID, mapboxVendorId); - event.put(MapboxEvent.ATTRIBUTE_ENABLED_TELEMETRY, telemetryEnabled); - - events.add(event); - - // Send to Server Immediately - flushEventsQueueImmediately(); - Timber.d("turnstile event pushed."); + // Add Location even to queue + Hashtable<String, Object> event = new Hashtable<>(); + event.put(ATTRIBUTE_EVENT, TYPE_LOCATION); + event.put(ATTRIBUTE_CREATED, generateCreateDate()); + event.put(ATTRIBUTE_SOURCE, SOURCE_MAPBOX); + event.put(ATTRIBUTE_SESSION_ID, encodeString(mapboxSessionId)); + event.put(KEY_LATITUDE, Math.floor(location.getLatitude() * locationEventAccuracy) + / locationEventAccuracy); + event.put(KEY_LONGITUDE, Math.floor(location.getLongitude() * locationEventAccuracy) + / locationEventAccuracy); + event.put(KEY_ALTITUDE, location.getAltitude()); + event.put(KEY_HORIZONTAL_ACCURACY, Math.round(location.getAccuracy())); + event.put(ATTRIBUTE_OPERATING_SYSTEM, operatingSystem); + event.put(ATTRIBUTE_APPLICATION_STATE, getApplicationState()); + + putEventOnQueue(event); + + rotateSessionId(); + } + + /** + * Push Interactive Events to the system for processing + * + * @param eventWithAttributes Event with attributes + */ + public void pushEvent(Hashtable<String, Object> eventWithAttributes) { + if (context == null || accessToken == null) { + return; } - /** - * SHA-1 Encoding for strings - * @param string String to encode - * @return String encoded if no error, original string if error - */ - private String encodeString(String string) { - try { - if (messageDigest != null) { - messageDigest.reset(); - messageDigest.update(string.getBytes("UTF-8")); - byte[] bytes = messageDigest.digest(); - - // Get the Hex version of the digest - StringBuilder sb = new StringBuilder(); - for (byte b : bytes) { - sb.append( String.format("%02X", b) ); - } - String hex = sb.toString(); - - return hex; - } - } catch (Exception e) { - Timber.w("Error encoding string, will return in original form." + e); - } - return string; + if (eventWithAttributes == null) { + return; } - /** - * Changes Session Id based on time boundary - */ - private void rotateSessionId() { - long now = System.currentTimeMillis(); - if ((TextUtils.isEmpty(mapboxSessionId)) || (now - mapboxSessionIdLastSet > (SESSION_ID_ROTATION_HOURS * hourInMillis))) { - mapboxSessionId = UUID.randomUUID().toString(); - mapboxSessionIdLastSet = System.currentTimeMillis(); - } + String eventType = (String) eventWithAttributes.get(ATTRIBUTE_EVENT); + if (TextUtils.isEmpty(eventType)) { + return; } - private String getOrientation() { - switch (context.getResources().getConfiguration().orientation) { - case Configuration.ORIENTATION_LANDSCAPE: - return "Landscape"; - case Configuration.ORIENTATION_PORTRAIT: - return "Portrait"; - default: - return ""; - } + if (eventType.equalsIgnoreCase(TYPE_MAP_LOAD)) { + // Map Load Data Model + eventWithAttributes.put(ATTRIBUTE_USERID, mapboxVendorId); + eventWithAttributes.put(ATTRIBUTE_MODEL, Build.MODEL); + eventWithAttributes.put(ATTRIBUTE_OPERATING_SYSTEM, operatingSystem); + eventWithAttributes.put(ATTRIBUTE_RESOLUTION, displayMetrics.density); + eventWithAttributes.put(ATTRIBUTE_ACCESSIBILITY_FONT_SCALE, getAccesibilityFontScaleSize()); + eventWithAttributes.put(ATTRIBUTE_ORIENTATION, getOrientation()); + eventWithAttributes.put(ATTRIBUTE_BATTERY_LEVEL, getBatteryLevel()); + eventWithAttributes.put(ATTRIBUTE_PLUGGED_IN, isPluggedIn()); + eventWithAttributes.put(ATTRIBUTE_CARRIER, getCellularCarrier()); + eventWithAttributes.put(ATTRIBUTE_CELLULAR_NETWORK_TYPE, getCellularNetworkType()); + eventWithAttributes.put(ATTRIBUTE_WIFI, getConnectedToWifi()); + + // Put Map Load on events before Turnstile clears it + putEventOnQueue(eventWithAttributes); + + // Turnstile + pushTurnstileEvent(); + + // Return immediately to avoid double adding of event + return; + + } else if (eventType.equalsIgnoreCase(TYPE_MAP_CLICK)) { + eventWithAttributes.put(ATTRIBUTE_ORIENTATION, getOrientation()); + eventWithAttributes.put(ATTRIBUTE_BATTERY_LEVEL, getBatteryLevel()); + eventWithAttributes.put(ATTRIBUTE_PLUGGED_IN, isPluggedIn()); + eventWithAttributes.put(ATTRIBUTE_CARRIER, getCellularCarrier()); + eventWithAttributes.put(ATTRIBUTE_CELLULAR_NETWORK_TYPE, getCellularNetworkType()); + eventWithAttributes.put(ATTRIBUTE_WIFI, getConnectedToWifi()); + } else if (eventType.equalsIgnoreCase(TYPE_MAP_DRAGEND)) { + eventWithAttributes.put(ATTRIBUTE_ORIENTATION, getOrientation()); + eventWithAttributes.put(ATTRIBUTE_BATTERY_LEVEL, getBatteryLevel()); + eventWithAttributes.put(ATTRIBUTE_PLUGGED_IN, isPluggedIn()); + eventWithAttributes.put(ATTRIBUTE_CARRIER, getCellularCarrier()); + eventWithAttributes.put(ATTRIBUTE_CELLULAR_NETWORK_TYPE, getCellularNetworkType()); + eventWithAttributes.put(ATTRIBUTE_WIFI, getConnectedToWifi()); + } else { + Timber.w("This is not an event type in the Events Data Model."); + return; } - private int getBatteryLevel() { - int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); - int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1); + putEventOnQueue(eventWithAttributes); + } + + /** + * Pushes turnstile event for internal billing purposes + */ + private void pushTurnstileEvent() { + + Hashtable<String, Object> event = new Hashtable<>(); + event.put(ATTRIBUTE_EVENT, TYPE_TURNSTILE); + event.put(ATTRIBUTE_CREATED, generateCreateDate()); + event.put(ATTRIBUTE_USERID, mapboxVendorId); + event.put(ATTRIBUTE_ENABLED_TELEMETRY, telemetryEnabled); + + events.add(event); + + // Send to Server Immediately + flushEventsQueueImmediately(); + Timber.d("turnstile event pushed."); + } + + /** + * SHA-1 Encoding for strings + * + * @param string String to encode + * @return String encoded if no error, original string if error + */ + private String encodeString(String string) { + try { + if (messageDigest != null) { + messageDigest.reset(); + messageDigest.update(string.getBytes("UTF-8")); + byte[] bytes = messageDigest.digest(); + + // Get the Hex version of the digest + StringBuilder sb = new StringBuilder(); + for (byte b : bytes) { + sb.append(String.format("%02X", b)); + } + String hex = sb.toString(); - return Math.round((level / (float)scale) * 100); + return hex; + } + } catch (Exception exception) { + Timber.w("Error encoding string, will return in original form." + exception); + } + return string; + } + + /** + * Changes Session Id based on time boundary + */ + private void rotateSessionId() { + long now = System.currentTimeMillis(); + if ((TextUtils.isEmpty(mapboxSessionId)) || (now - mapboxSessionIdLastSet + > (SESSION_ID_ROTATION_HOURS * hourInMillis))) { + mapboxSessionId = UUID.randomUUID().toString(); + mapboxSessionIdLastSet = System.currentTimeMillis(); + } + } + + private String getOrientation() { + switch (context.getResources().getConfiguration().orientation) { + case Configuration.ORIENTATION_LANDSCAPE: + return "Landscape"; + case Configuration.ORIENTATION_PORTRAIT: + return "Portrait"; + default: + return ""; + } + } + + private int getBatteryLevel() { + int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); + int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1); + + return Math.round((level / (float) scale) * 100); + } + + /** + * Determine if device is plugged in to power via USB or AC or not. + * <p> + * http://developer.android.com/reference/android/os/BatteryManager.html#EXTRA_PLUGGED + * + * @return true if plugged in, false if not + */ + private boolean isPluggedIn() { + + int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); + if (chargePlug == BatteryManager.BATTERY_PLUGGED_USB || chargePlug == BatteryManager.BATTERY_PLUGGED_AC) { + return true; } - /** - * Determine if device is plugged in to power via USB or AC or not. - * - * http://developer.android.com/reference/android/os/BatteryManager.html#EXTRA_PLUGGED - * @return true if plugged in, false if not - */ - private boolean isPluggedIn() { + return false; + } - int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); - if (chargePlug == BatteryManager.BATTERY_PLUGGED_USB || chargePlug == BatteryManager.BATTERY_PLUGGED_AC) { - return true; - } + private String getApplicationState() { - return false; + ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses(); + if (appProcesses == null) { + return ""; } - - private String getApplicationState() { - - ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); - List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses(); - if (appProcesses == null) { - return ""; - } - final String packageName = context.getPackageName(); - for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) { - if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) { - return "Foreground"; - } - } - return "Background"; + final String packageName = context.getPackageName(); + for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) { + if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND + && appProcess.processName.equals(packageName)) { + return "Foreground"; + } } - - private float getAccesibilityFontScaleSize() { - // Values - // Small = 0.85 - // Normal = 1.0 - // Large = 1.15 - // Huge = 1.3 - - return context.getResources().getConfiguration().fontScale; + return "Background"; + } + + private float getAccesibilityFontScaleSize() { + // Values + // Small = 0.85 + // Normal = 1.0 + // Large = 1.15 + // Huge = 1.3 + + return context.getResources().getConfiguration().fontScale; + } + + private String getCellularCarrier() { + TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + String carrierName = manager.getNetworkOperatorName(); + if (TextUtils.isEmpty(carrierName)) { + carrierName = ""; } - - private String getCellularCarrier() { - TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); - String carrierName = manager.getNetworkOperatorName(); - if (TextUtils.isEmpty(carrierName)) { - carrierName = ""; - } - return carrierName; + return carrierName; + } + + private String getCellularNetworkType() { + TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + switch (manager.getNetworkType()) { + case TelephonyManager.NETWORK_TYPE_1xRTT: + return "1xRTT"; + case TelephonyManager.NETWORK_TYPE_CDMA: + return "CDMA"; + case TelephonyManager.NETWORK_TYPE_EDGE: + return "EDGE"; + case TelephonyManager.NETWORK_TYPE_EHRPD: + return "EHRPD"; + case TelephonyManager.NETWORK_TYPE_EVDO_0: + return "EVDO_0"; + case TelephonyManager.NETWORK_TYPE_EVDO_A: + return "EVDO_A"; + case TelephonyManager.NETWORK_TYPE_EVDO_B: + return "EVDO_B"; + case TelephonyManager.NETWORK_TYPE_GPRS: + return "GPRS"; + case TelephonyManager.NETWORK_TYPE_HSDPA: + return "HSDPA"; + case TelephonyManager.NETWORK_TYPE_HSPA: + return "HSPA"; + case TelephonyManager.NETWORK_TYPE_HSPAP: + return "HSPAP"; + case TelephonyManager.NETWORK_TYPE_HSUPA: + return "HSUPA"; + case TelephonyManager.NETWORK_TYPE_IDEN: + return "IDEN"; + case TelephonyManager.NETWORK_TYPE_LTE: + return "LTE"; + case TelephonyManager.NETWORK_TYPE_UMTS: + return "UMTS"; + case TelephonyManager.NETWORK_TYPE_UNKNOWN: + return "Unknown"; + default: + return ""; } + } - private String getCellularNetworkType () { - TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); - switch (manager.getNetworkType()) { - case TelephonyManager.NETWORK_TYPE_1xRTT: - return "1xRTT"; - case TelephonyManager.NETWORK_TYPE_CDMA: - return "CDMA"; - case TelephonyManager.NETWORK_TYPE_EDGE: - return "EDGE"; - case TelephonyManager.NETWORK_TYPE_EHRPD: - return "EHRPD"; - case TelephonyManager.NETWORK_TYPE_EVDO_0: - return "EVDO_0"; - case TelephonyManager.NETWORK_TYPE_EVDO_A: - return "EVDO_A"; - case TelephonyManager.NETWORK_TYPE_EVDO_B: - return "EVDO_B"; - case TelephonyManager.NETWORK_TYPE_GPRS: - return "GPRS"; - case TelephonyManager.NETWORK_TYPE_HSDPA: - return "HSDPA"; - case TelephonyManager.NETWORK_TYPE_HSPA: - return "HSPA"; - case TelephonyManager.NETWORK_TYPE_HSPAP: - return "HSPAP"; - case TelephonyManager.NETWORK_TYPE_HSUPA: - return "HSUPA"; - case TelephonyManager.NETWORK_TYPE_IDEN: - return "IDEN"; - case TelephonyManager.NETWORK_TYPE_LTE: - return "LTE"; - case TelephonyManager.NETWORK_TYPE_UMTS: - return "UMTS"; - case TelephonyManager.NETWORK_TYPE_UNKNOWN: - return "Unknown"; - default: - return ""; - } - } + public Boolean getConnectedToWifi() { - public Boolean getConnectedToWifi() { - - Boolean status = false; - WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); - if (wifiMgr.isWifiEnabled()) { - try { - WifiInfo wifiInfo = wifiMgr.getConnectionInfo(); - if (wifiInfo.getNetworkId() != -1){ - status = true; - } - } catch (Exception e) { - Timber.w("Error getting Wifi Connection Status: " + e); - status = false; - } + Boolean status = false; + WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); + if (wifiMgr.isWifiEnabled()) { + try { + WifiInfo wifiInfo = wifiMgr.getConnectionInfo(); + if (wifiInfo.getNetworkId() != -1) { + status = true; } - - return status; + } catch (Exception exception) { + Timber.w("Error getting Wifi Connection Status: " + exception); + status = false; + } } - - /** - * Task responsible for converting stored events and sending them to the server - */ - private class FlushTheEventsTask extends AsyncTask<Void, Void, Void> { - - @Override - protected Void doInBackground(Void... voids) { - - if (events.isEmpty()) { - Timber.d("No events in the queue to send so returning."); - return null; + return status; + } + + + /** + * Task responsible for converting stored events and sending them to the server + */ + private class FlushTheEventsTask extends AsyncTask<Void, Void, Void> { + + @Override + protected Void doInBackground(Void... voids) { + + if (events.isEmpty()) { + Timber.d("No events in the queue to send so returning."); + return null; + } + + // Check for NetworkConnectivity + if (!MapboxAccountManager.getInstance().isConnected()) { + Timber.w("Not connected to network, so empty events cache and return without attempting to send events"); + // Make sure that events don't pile up when Offline + // and thus impact available memory over time. + events.removeAllElements(); + return null; + } + + Response response = null; + + try { + // Send data + // ========= + JSONArray jsonArray = new JSONArray(); + + Vector<Hashtable<String, Object>> eventsClone = (Vector<Hashtable<String, Object>>) events.clone(); + + for (Hashtable<String, Object> evt : eventsClone) { + JSONObject jsonObject = new JSONObject(); + + // Build the JSON but only if there's a value for it in the evt + jsonObject.putOpt(ATTRIBUTE_EVENT, evt.get(ATTRIBUTE_EVENT)); + jsonObject.putOpt(ATTRIBUTE_CREATED, evt.get(ATTRIBUTE_CREATED)); + jsonObject.putOpt(ATTRIBUTE_USERID, evt.get(ATTRIBUTE_USERID)); + jsonObject.putOpt(ATTRIBUTE_ENABLED_TELEMETRY, evt.get(ATTRIBUTE_ENABLED_TELEMETRY)); + jsonObject.putOpt(ATTRIBUTE_SOURCE, evt.get(ATTRIBUTE_SOURCE)); + jsonObject.putOpt(ATTRIBUTE_SESSION_ID, evt.get(ATTRIBUTE_SESSION_ID)); + jsonObject.putOpt(KEY_LATITUDE, evt.get(KEY_LATITUDE)); + + // Make sure Longitude Is Wrapped + if (evt.containsKey(KEY_LONGITUDE)) { + double lon = (double) evt.get(KEY_LONGITUDE); + if ((lon < GeoConstants.MIN_LONGITUDE) || (lon > GeoConstants.MAX_LONGITUDE)) { + lon = MathUtils.wrap(lon, GeoConstants.MIN_LONGITUDE, GeoConstants.MAX_LONGITUDE); } - - // Check for NetworkConnectivity - if (!MapboxAccountManager.getInstance().isConnected()) { - Timber.w("Not connected to network, so empty events cache and return without attempting to send events"); - // Make sure that events don't pile up when Offline - // and thus impact available memory over time. - events.removeAllElements(); - return null; + jsonObject.put(KEY_LONGITUDE, lon); + } + + jsonObject.putOpt(KEY_ALTITUDE, evt.get(KEY_ALTITUDE)); + jsonObject.putOpt(KEY_ZOOM, evt.get(KEY_ZOOM)); + jsonObject.putOpt(ATTRIBUTE_OPERATING_SYSTEM, evt.get(ATTRIBUTE_OPERATING_SYSTEM)); + jsonObject.putOpt(ATTRIBUTE_USERID, evt.get(ATTRIBUTE_USERID)); + jsonObject.putOpt(ATTRIBUTE_MODEL, evt.get(ATTRIBUTE_MODEL)); + jsonObject.putOpt(ATTRIBUTE_RESOLUTION, evt.get(ATTRIBUTE_RESOLUTION)); + jsonObject.putOpt(ATTRIBUTE_ACCESSIBILITY_FONT_SCALE, evt.get(ATTRIBUTE_ACCESSIBILITY_FONT_SCALE)); + jsonObject.putOpt(ATTRIBUTE_BATTERY_LEVEL, evt.get(ATTRIBUTE_BATTERY_LEVEL)); + jsonObject.putOpt(ATTRIBUTE_PLUGGED_IN, evt.get(ATTRIBUTE_PLUGGED_IN)); + jsonObject.putOpt(ATTRIBUTE_WIFI, evt.get(ATTRIBUTE_WIFI)); + + // Special Cases where empty string is denoting null and therefore should not be sent at all + // This arises as thread safe Hashtable does not accept null values (nor keys) + if (evt.containsKey(ATTRIBUTE_ORIENTATION)) { + String orientation = (String) evt.get(ATTRIBUTE_ORIENTATION); + if (!TextUtils.isEmpty(orientation)) { + jsonObject.putOpt(ATTRIBUTE_ORIENTATION, orientation); } - - Response response = null; - - try { - // Send data - // ========= - JSONArray jsonArray = new JSONArray(); - - Vector<Hashtable<String, Object>> eventsClone = (Vector<Hashtable<String, Object>>) events.clone(); - - for (Hashtable<String, Object> evt : eventsClone) { - JSONObject jsonObject = new JSONObject(); - - // Build the JSON but only if there's a value for it in the evt - jsonObject.putOpt(MapboxEvent.ATTRIBUTE_EVENT, evt.get(MapboxEvent.ATTRIBUTE_EVENT)); - jsonObject.putOpt(MapboxEvent.ATTRIBUTE_CREATED, evt.get(MapboxEvent.ATTRIBUTE_CREATED)); - jsonObject.putOpt(MapboxEvent.ATTRIBUTE_USERID, evt.get(MapboxEvent.ATTRIBUTE_USERID)); - jsonObject.putOpt(MapboxEvent.ATTRIBUTE_ENABLED_TELEMETRY, evt.get(MapboxEvent.ATTRIBUTE_ENABLED_TELEMETRY)); - jsonObject.putOpt(MapboxEvent.ATTRIBUTE_SOURCE, evt.get(MapboxEvent.ATTRIBUTE_SOURCE)); - jsonObject.putOpt(MapboxEvent.ATTRIBUTE_SESSION_ID, evt.get(MapboxEvent.ATTRIBUTE_SESSION_ID)); - jsonObject.putOpt(MapboxEvent.KEY_LATITUDE, evt.get(MapboxEvent.KEY_LATITUDE)); - - // Make sure Longitude Is Wrapped - if (evt.containsKey(MapboxEvent.KEY_LONGITUDE)) { - double lon = (double)evt.get(MapboxEvent.KEY_LONGITUDE); - if ((lon < GeoConstants.MIN_LONGITUDE) || (lon > GeoConstants.MAX_LONGITUDE)) { - lon = MathUtils.wrap(lon, GeoConstants.MIN_LONGITUDE, GeoConstants.MAX_LONGITUDE); - } - jsonObject.put(MapboxEvent.KEY_LONGITUDE, lon); - } - - jsonObject.putOpt(MapboxEvent.KEY_ALTITUDE, evt.get(MapboxEvent.KEY_ALTITUDE)); - jsonObject.putOpt(MapboxEvent.KEY_ZOOM, evt.get(MapboxEvent.KEY_ZOOM)); - jsonObject.putOpt(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM, evt.get(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM)); - jsonObject.putOpt(MapboxEvent.ATTRIBUTE_USERID, evt.get(MapboxEvent.ATTRIBUTE_USERID)); - jsonObject.putOpt(MapboxEvent.ATTRIBUTE_MODEL, evt.get(MapboxEvent.ATTRIBUTE_MODEL)); - jsonObject.putOpt(MapboxEvent.ATTRIBUTE_RESOLUTION, evt.get(MapboxEvent.ATTRIBUTE_RESOLUTION)); - jsonObject.putOpt(MapboxEvent.ATTRIBUTE_ACCESSIBILITY_FONT_SCALE, evt.get(MapboxEvent.ATTRIBUTE_ACCESSIBILITY_FONT_SCALE)); - jsonObject.putOpt(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL, evt.get(MapboxEvent.ATTRIBUTE_BATTERY_LEVEL)); - jsonObject.putOpt(MapboxEvent.ATTRIBUTE_PLUGGED_IN, evt.get(MapboxEvent.ATTRIBUTE_PLUGGED_IN)); - jsonObject.putOpt(MapboxEvent.ATTRIBUTE_WIFI, evt.get(MapboxEvent.ATTRIBUTE_WIFI)); - - // Special Cases where empty string is denoting null and therefore should not be sent at all - // This arises as thread safe Hashtable does not accept null values (nor keys) - if (evt.containsKey(MapboxEvent.ATTRIBUTE_ORIENTATION)) { - String orientation = (String)evt.get(MapboxEvent.ATTRIBUTE_ORIENTATION); - if (!TextUtils.isEmpty(orientation)) { - jsonObject.putOpt(MapboxEvent.ATTRIBUTE_ORIENTATION, orientation); - } - } - if (evt.containsKey(MapboxEvent.ATTRIBUTE_CARRIER)) { - String carrier = (String)evt.get(MapboxEvent.ATTRIBUTE_CARRIER); - if (!TextUtils.isEmpty(carrier)) { - jsonObject.putOpt(MapboxEvent.ATTRIBUTE_CARRIER, carrier); - } - } - if (evt.containsKey(MapboxEvent.ATTRIBUTE_APPLICATION_STATE)) { - String appState = (String)evt.get(MapboxEvent.ATTRIBUTE_APPLICATION_STATE); - if (!TextUtils.isEmpty(appState)) { - jsonObject.putOpt(MapboxEvent.ATTRIBUTE_APPLICATION_STATE, evt.get(MapboxEvent.ATTRIBUTE_APPLICATION_STATE)); - } - } - - // Special Cases where null has to be passed if no value exists - // Requires using put() instead of putOpt() - String eventType = (String)evt.get(MapboxEvent.ATTRIBUTE_EVENT); - if (!TextUtils.isEmpty(eventType) && eventType.equalsIgnoreCase(MapboxEvent.TYPE_MAP_CLICK)) { - jsonObject.put(MapboxEvent.KEY_GESTURE_ID, evt.get(MapboxEvent.KEY_GESTURE_ID)); - } - if (evt.containsKey(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE)) { - String cellularNetworkType = (String)evt.get(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE); - if (TextUtils.isEmpty(cellularNetworkType)) { - jsonObject.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, null); - } else { - jsonObject.put(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE, evt.get(MapboxEvent.ATTRIBUTE_CELLULAR_NETWORK_TYPE)); - } - } - - jsonArray.put(jsonObject); - } - - // Based on http://square.github.io/okhttp/3.x/okhttp/okhttp3/CertificatePinner.html - CertificatePinner.Builder certificatePinnerBuilder = new CertificatePinner.Builder(); - if(stagingEnv){ - // Staging - Geotrust - certificatePinnerBuilder - .add("cloudfront-staging.tilestream.net", "sha256/3euxrJOrEZI15R4104UsiAkDqe007EPyZ6eTL/XxdAY=") - .add("cloudfront-staging.tilestream.net", "sha256/5kJvNEMw0KjrCAu7eXY5HZdvyCS13BbA0VJG1RSP91w=") - .add("cloudfront-staging.tilestream.net", "sha256/r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E="); - }else{ - certificatePinnerBuilder - // Prod - Geotrust - .add("events.mapbox.com", "sha256/BhynraKizavqoC5U26qgYuxLZst6pCu9J5stfL6RSYY=") - .add("events.mapbox.com", "sha256/owrR9U9FWDWtrFF+myoRIu75JwU4sJwzvhCNLZoY37g=") - .add("events.mapbox.com", "sha256/SQVGZiOrQXi+kqxcvWWE96HhfydlLVqFr4lQTqI5qqo=") - // Prod - DigiCert - .add("events.mapbox.com", "sha256/Tb0uHZ/KQjWh8N9+CZFLc4zx36LONQ55l6laDi1qtT4=") - .add("events.mapbox.com", "sha256/RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho=") - .add("events.mapbox.com", "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="); - } - - OkHttpClient client = new OkHttpClient.Builder() - .certificatePinner(certificatePinnerBuilder.build()) - .addInterceptor(new GzipRequestInterceptor()) - .build(); - RequestBody body = RequestBody.create(JSON, jsonArray.toString()); - - String url = eventsURL + "/events/v2?access_token=" + accessToken; - - Request request = new Request.Builder() - .url(url) - .header("User-Agent", userAgent) - .post(body) - .build(); - response = client.newCall(request).execute(); - Timber.d("response code = " + response.code() + " for events " + events.size()); - - } catch (Exception e) { - Timber.e("FlushTheEventsTask borked: " + e); - e.printStackTrace(); - } finally { - if (response != null && response.body() != null) { - response.body().close(); - } - // Reset Events - // ============ - events.removeAllElements(); + } + if (evt.containsKey(ATTRIBUTE_CARRIER)) { + String carrier = (String) evt.get(ATTRIBUTE_CARRIER); + if (!TextUtils.isEmpty(carrier)) { + jsonObject.putOpt(ATTRIBUTE_CARRIER, carrier); } + } + if (evt.containsKey(ATTRIBUTE_APPLICATION_STATE)) { + String appState = (String) evt.get(ATTRIBUTE_APPLICATION_STATE); + if (!TextUtils.isEmpty(appState)) { + jsonObject.putOpt(ATTRIBUTE_APPLICATION_STATE, evt.get(ATTRIBUTE_APPLICATION_STATE)); + } + } + + // Special Cases where null has to be passed if no value exists + // Requires using put() instead of putOpt() + String eventType = (String) evt.get(ATTRIBUTE_EVENT); + if (!TextUtils.isEmpty(eventType) && eventType.equalsIgnoreCase(TYPE_MAP_CLICK)) { + jsonObject.put(KEY_GESTURE_ID, evt.get(KEY_GESTURE_ID)); + } + if (evt.containsKey(ATTRIBUTE_CELLULAR_NETWORK_TYPE)) { + String cellularNetworkType = (String) evt.get(ATTRIBUTE_CELLULAR_NETWORK_TYPE); + if (TextUtils.isEmpty(cellularNetworkType)) { + jsonObject.put(ATTRIBUTE_CELLULAR_NETWORK_TYPE, null); + } else { + jsonObject.put(ATTRIBUTE_CELLULAR_NETWORK_TYPE, evt.get(ATTRIBUTE_CELLULAR_NETWORK_TYPE)); + } + } + + jsonArray.put(jsonObject); + } + + // Based on http://square.github.io/okhttp/3.x/okhttp/okhttp3/CertificatePinner.html + CertificatePinner.Builder certificatePinnerBuilder = new CertificatePinner.Builder(); + if (stagingEnv) { + // Staging - Geotrust + certificatePinnerBuilder + .add("cloudfront-staging.tilestream.net", "sha256/3euxrJOrEZI15R4104UsiAkDqe007EPyZ6eTL/XxdAY=") + .add("cloudfront-staging.tilestream.net", "sha256/5kJvNEMw0KjrCAu7eXY5HZdvyCS13BbA0VJG1RSP91w=") + .add("cloudfront-staging.tilestream.net", "sha256/r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E="); + } else { + certificatePinnerBuilder + // Prod - Geotrust + .add("events.mapbox.com", "sha256/BhynraKizavqoC5U26qgYuxLZst6pCu9J5stfL6RSYY=") + .add("events.mapbox.com", "sha256/owrR9U9FWDWtrFF+myoRIu75JwU4sJwzvhCNLZoY37g=") + .add("events.mapbox.com", "sha256/SQVGZiOrQXi+kqxcvWWE96HhfydlLVqFr4lQTqI5qqo=") + // Prod - DigiCert + .add("events.mapbox.com", "sha256/Tb0uHZ/KQjWh8N9+CZFLc4zx36LONQ55l6laDi1qtT4=") + .add("events.mapbox.com", "sha256/RRM1dGqnDFsCJXBTHky16vi1obOlCgFFn/yOhI/y+ho=") + .add("events.mapbox.com", "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="); + } - return null; + OkHttpClient client = new OkHttpClient.Builder() + .certificatePinner(certificatePinnerBuilder.build()) + .addInterceptor(new GzipRequestInterceptor()) + .build(); + RequestBody body = RequestBody.create(JSON, jsonArray.toString()); + + String url = eventsURL + "/events/v2?access_token=" + accessToken; + + Request request = new Request.Builder() + .url(url) + .header("User-Agent", userAgent) + .post(body) + .build(); + response = client.newCall(request).execute(); + Timber.d("response code = " + response.code() + " for events " + events.size()); + + } catch (Exception exception) { + Timber.e("FlushTheEventsTask borked: " + exception); + exception.printStackTrace(); + } finally { + if (response != null && response.body() != null) { + response.body().close(); } + // Reset Events + // ============ + events.removeAllElements(); + } + return null; } + } + + /** + * TimerTask responsible for sending event data to server + */ + private class FlushEventsTimerTask extends TimerTask { /** - * TimerTask responsible for sending event data to server + * The task to run should be specified in the implementation of the {@code run()} + * method. */ - private class FlushEventsTimerTask extends TimerTask { - /** - * The task to run should be specified in the implementation of the {@code run()} - * method. - */ - @Override - public void run() { - new FlushTheEventsTask().execute(); - } + @Override + public void run() { + new FlushTheEventsTask().execute(); } - - private String getApplicationIdentifier() { - try { - PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); - return String.format(MapboxConstants.MAPBOX_LOCALE, "%s/%s/%s", context.getPackageName(), packageInfo.versionName, packageInfo.versionCode); - } catch (Exception e) { - return ""; - } + } + + private String getApplicationIdentifier() { + try { + PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); + return String.format(MAPBOX_LOCALE, "%s/%s/%s", context.getPackageName(), packageInfo.versionName, + packageInfo.versionCode); + } catch (Exception exception) { + return ""; } + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java index 3e594b530c..2274fb2b82 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java @@ -5,67 +5,66 @@ import android.content.Context; import android.content.Intent; import android.location.Location; import android.location.LocationManager; -import android.os.Handler; /** * Listener for Location updates generated by implementing app. */ public class TelemetryLocationReceiver extends BroadcastReceiver { - public static final String INTENT_STRING = "com.mapbox.mapboxsdk.telemetry.TelemetryLocationReceiver"; + public static final String INTENT_STRING = "com.mapbox.mapboxsdk.telemetry.TelemetryLocationReceiver"; - /** - * Default Constructor - */ - public TelemetryLocationReceiver() { - super(); - } + /** + * Default Constructor + */ + public TelemetryLocationReceiver() { + super(); + } - /** - * This method is called when the BroadcastReceiver is receiving an Intent - * broadcast. During this time you can use the other methods on - * BroadcastReceiver to view/modify the current result values. This method - * is always called within the main thread of its process, unless you - * explicitly asked for it to be scheduled on a different thread using - * {@link Context#registerReceiver(BroadcastReceiver, - * IntentFilter, String, Handler)}. When it runs on the main - * thread you should - * never perform long-running operations in it (there is a timeout of - * 10 seconds that the system allows before considering the receiver to - * be blocked and a candidate to be killed). You cannot launch a popup dialog - * in your implementation of onReceive(). - * - * <p><b>If this BroadcastReceiver was launched through a <receiver> tag, - * then the object is no longer alive after returning from this - * function.</b> This means you should not perform any operations that - * return a result to you asynchronously -- in particular, for interacting - * with services, you should use - * {@link Context#startService(Intent)} instead of - * {@link Context#bindService(Intent, ServiceConnection, int)}. If you wish - * to interact with a service that is already running, you can use - * {@link #peekService}. - * - * <p>The Intent filters used in {@link Context#registerReceiver} - * and in application manifests are <em>not</em> guaranteed to be exclusive. They - * are hints to the operating system about how to find suitable recipients. It is - * possible for senders to force delivery to specific recipients, bypassing filter - * resolution. For this reason, {@link #onReceive(Context, Intent) onReceive()} - * implementations should respond only to known actions, ignoring any unexpected - * Intents that they may receive. - * - * @param context The Context in which the receiver is running. - * @param intent The Intent being received. - */ - @Override - public void onReceive(Context context, Intent intent) { - if (intent == null || intent.getExtras() == null) { - // see https://github.com/mapbox/mapbox-gl-native/issues/6934 - return; - } + /** + * This method is called when the BroadcastReceiver is receiving an Intent + * broadcast. During this time you can use the other methods on + * BroadcastReceiver to view/modify the current result values. This method + * is always called within the main thread of its process, unless you + * explicitly asked for it to be scheduled on a different thread using + * {@link Context#registerReceiver(BroadcastReceiver, + * android.content.IntentFilter, String, android.os.Handler)}. When it runs on the main + * thread you should + * never perform long-running operations in it (there is a timeout of + * 10 seconds that the system allows before considering the receiver to + * be blocked and a candidate to be killed). You cannot launch a popup dialog + * in your implementation of onReceive(). + * <p> + * <p><b>If this BroadcastReceiver was launched through a <receiver> tag, + * then the object is no longer alive after returning from this + * function.</b> This means you should not perform any operations that + * return a result to you asynchronously -- in particular, for interacting + * with services, you should use + * {@link Context#startService(Intent)} instead of + * {@link Context#bindService(Intent, android.content.ServiceConnection, int)}. If you wish + * to interact with a service that is already running, you can use + * {@link #peekService}. + * <p> + * <p>The Intent filters used in {@link Context#registerReceiver} + * and in application manifests are <em>not</em> guaranteed to be exclusive. They + * are hints to the operating system about how to find suitable recipients. It is + * possible for senders to force delivery to specific recipients, bypassing filter + * resolution. For this reason, {@link #onReceive(Context, Intent) onReceive()} + * implementations should respond only to known actions, ignoring any unexpected + * Intents that they may receive. + * + * @param context The Context in which the receiver is running. + * @param intent The Intent being received. + */ + @Override + public void onReceive(Context context, Intent intent) { + if (intent == null || intent.getExtras() == null) { + // see https://github.com/mapbox/mapbox-gl-native/issues/6934 + return; + } - Location location = (Location) intent.getExtras().get(LocationManager.KEY_LOCATION_CHANGED); - if (location != null) { - MapboxEventManager.getMapboxEventManager().addLocationEvent(location); - } + Location location = (Location) intent.getExtras().get(LocationManager.KEY_LOCATION_CHANGED); + if (location != null) { + MapboxEventManager.getMapboxEventManager().addLocationEvent(location); } + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java index bfa275d5a1..a965591f75 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java @@ -8,6 +8,7 @@ import android.content.pm.ServiceInfo; import android.os.AsyncTask; import android.os.IBinder; import android.support.annotation.Nullable; + import timber.log.Timber; /** @@ -15,139 +16,139 @@ import timber.log.Timber; */ public class TelemetryService extends Service { - private TelemetryLocationReceiver telemetryLocationReceiver = null; - - /** - * Return the communication channel to the service. May return null if - * clients can not bind to the service. The returned - * {@link IBinder} is usually for a complex interface - * that has been <a href="{@docRoot}guide/components/aidl.html">described using - * aidl</a>. - * - * <p><em>Note that unlike other application components, calls on to the - * IBinder interface returned here may not happen on the main thread - * of the process</em>. More information about the main thread can be found in - * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html">Processes and - * Threads</a>.</p> - * - * @param intent The Intent that was used to bind to this service, - * as given to {@link Context#bindService - * Context.bindService}. Note that any extras that were included with - * the Intent at that point will <em>not</em> be seen here. - * @return Return an IBinder through which clients can call on to the - * service. - */ - @Nullable - @Override - public IBinder onBind(Intent intent) { - return null; - } - - - /** - * Called by the system when the service is first created. Do not call this method directly. - */ - @Override - public void onCreate() { - super.onCreate(); - - Timber.i("onCreate() called"); - - // Enable Location Listening for lifecycle of app - IntentFilter filter = new IntentFilter(TelemetryLocationReceiver.INTENT_STRING); - telemetryLocationReceiver = new TelemetryLocationReceiver(); - registerReceiver(telemetryLocationReceiver, filter); - } - - /** - * Called by the system to notify a Service that it is no longer used and is being removed. The - * service should clean up any resources it holds (threads, registered - * receivers, etc) at this point. Upon return, there will be no more calls - * in to this Service object and it is effectively dead. Do not call this method directly. - */ - @Override - public void onDestroy() { - shutdownTelemetry(); - super.onDestroy(); + private TelemetryLocationReceiver telemetryLocationReceiver = null; + + /** + * Return the communication channel to the service. May return null if + * clients can not bind to the service. The returned + * {@link IBinder} is usually for a complex interface + * that has been <a href="{@docRoot}guide/components/aidl.html">described using + * aidl</a>. + * <p> + * <p><em>Note that unlike other application components, calls on to the + * IBinder interface returned here may not happen on the main thread + * of the process</em>. More information about the main thread can be found in + * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html">Processes and + * Threads</a>.</p> + * + * @param intent The Intent that was used to bind to this service, + * as given to {@link Context#bindService + * Context.bindService}. Note that any extras that were included with + * the Intent at that point will <em>not</em> be seen here. + * @return Return an IBinder through which clients can call on to the + * service. + */ + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } + + + /** + * Called by the system when the service is first created. Do not call this method directly. + */ + @Override + public void onCreate() { + super.onCreate(); + + Timber.i("onCreate() called"); + + // Enable Location Listening for lifecycle of app + IntentFilter filter = new IntentFilter(TelemetryLocationReceiver.INTENT_STRING); + telemetryLocationReceiver = new TelemetryLocationReceiver(); + registerReceiver(telemetryLocationReceiver, filter); + } + + /** + * Called by the system to notify a Service that it is no longer used and is being removed. The + * service should clean up any resources it holds (threads, registered + * receivers, etc) at this point. Upon return, there will be no more calls + * in to this Service object and it is effectively dead. Do not call this method directly. + */ + @Override + public void onDestroy() { + shutdownTelemetry(); + super.onDestroy(); + } + + /** + * This is called if the service is currently running and the user has + * removed a task that comes from the service's application. If you have + * set {@link ServiceInfo#FLAG_STOP_WITH_TASK ServiceInfo.FLAG_STOP_WITH_TASK} + * then you will not receive this callback; instead, the service will simply + * be stopped. + * + * @param rootIntent The original root Intent that was used to launch + * the task that is being removed. + */ + @Override + public void onTaskRemoved(Intent rootIntent) { + shutdownTelemetry(); + super.onTaskRemoved(rootIntent); + } + + /** + * Called by the system every time a client explicitly starts the service by calling + * {@link Context#startService}, providing the arguments it supplied and a + * unique integer token representing the start request. Do not call this method directly. + * <p> + * <p>For backwards compatibility, the default implementation calls + * {@link #onStart} and returns either {@link #START_STICKY} + * or {@link #START_STICKY_COMPATIBILITY}. + * </p> + * <p>If you need your application to run on platform versions prior to API + * level 5, you can use the following model to handle the older {@link #onStart} + * callback in that case. The <code>handleCommand</code> method is implemented by + * you as appropriate: + * </p> + * <p> + * <p class="caution">Note that the system calls this on your + * service's main thread. A service's main thread is the same + * thread where UI operations take place for Activities running in the + * same process. You should always avoid stalling the main + * thread's event loop. When doing long-running operations, + * network calls, or heavy disk I/O, you should kick off a new + * thread, or use {@link AsyncTask}.</p> + * + * @param intent The Intent supplied to {@link Context#startService}, + * as given. This may be null if the service is being restarted after + * its process has gone away, and it had previously returned anything + * except {@link #START_STICKY_COMPATIBILITY}. + * @param flags Additional data about this start request. Currently either + * 0, {@link #START_FLAG_REDELIVERY}, or {@link #START_FLAG_RETRY}. + * @param startId A unique integer representing this specific request to + * start. Use with {@link #stopSelfResult(int)}. + * @return The return value indicates what semantics the system should + * use for the service's current started state. It may be one of the + * constants associated with the {@link #START_CONTINUATION_MASK} bits. + * @see #stopSelfResult(int) + */ + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + + Timber.i("onStartCommand() called"); + + return START_NOT_STICKY; + } + + private void shutdownTelemetry() { + + // Send Any Remaining events to the server + MapboxEventManager.getMapboxEventManager().flushEventsQueueImmediately(); + + // Undesired, but needed trick to keep app alive long enough for data to get to server + try { + Thread.sleep(1000); + } catch (Exception exception) { + Timber.e("Error while trying to sleep for 1 second: " + exception); } - /** - * This is called if the service is currently running and the user has - * removed a task that comes from the service's application. If you have - * set {@link ServiceInfo#FLAG_STOP_WITH_TASK ServiceInfo.FLAG_STOP_WITH_TASK} - * then you will not receive this callback; instead, the service will simply - * be stopped. - * - * @param rootIntent The original root Intent that was used to launch - * the task that is being removed. - */ - @Override - public void onTaskRemoved(Intent rootIntent) { - shutdownTelemetry(); - super.onTaskRemoved(rootIntent); + try { + unregisterReceiver(telemetryLocationReceiver); + } catch (IllegalArgumentException illegalArgumentException) { + Timber.e("Error when unregisterReceiver: " + illegalArgumentException); } - /** - * Called by the system every time a client explicitly starts the service by calling - * {@link Context#startService}, providing the arguments it supplied and a - * unique integer token representing the start request. Do not call this method directly. - * - * <p>For backwards compatibility, the default implementation calls - * {@link #onStart} and returns either {@link #START_STICKY} - * or {@link #START_STICKY_COMPATIBILITY}. - * </p> - * <p>If you need your application to run on platform versions prior to API - * level 5, you can use the following model to handle the older {@link #onStart} - * callback in that case. The <code>handleCommand</code> method is implemented by - * you as appropriate: - * </p> - * - * <p class="caution">Note that the system calls this on your - * service's main thread. A service's main thread is the same - * thread where UI operations take place for Activities running in the - * same process. You should always avoid stalling the main - * thread's event loop. When doing long-running operations, - * network calls, or heavy disk I/O, you should kick off a new - * thread, or use {@link AsyncTask}.</p> - * - * @param intent The Intent supplied to {@link Context#startService}, - * as given. This may be null if the service is being restarted after - * its process has gone away, and it had previously returned anything - * except {@link #START_STICKY_COMPATIBILITY}. - * @param flags Additional data about this start request. Currently either - * 0, {@link #START_FLAG_REDELIVERY}, or {@link #START_FLAG_RETRY}. - * @param startId A unique integer representing this specific request to - * start. Use with {@link #stopSelfResult(int)}. - * @return The return value indicates what semantics the system should - * use for the service's current started state. It may be one of the - * constants associated with the {@link #START_CONTINUATION_MASK} bits. - * @see #stopSelfResult(int) - */ - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - - Timber.i("onStartCommand() called"); - - return START_NOT_STICKY; - } - - private void shutdownTelemetry() { - - // Send Any Remaining events to the server - MapboxEventManager.getMapboxEventManager().flushEventsQueueImmediately(); - - // Undesired, but needed trick to keep app alive long enough for data to get to server - try { - Thread.sleep(1000); - } catch (Exception e) { - Timber.e("Error while trying to sleep for 1 second: " + e); - } - - try { - unregisterReceiver(telemetryLocationReceiver); - } catch (IllegalArgumentException e) { - Timber.e("Error when unregisterReceiver: " + e); - } - - } + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java index ab3b841043..7694604d9f 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java @@ -12,94 +12,98 @@ import android.view.View; public class AnimatorUtils { - public static void animate(@NonNull final View view, @AnimatorRes int animatorRes, @Nullable OnAnimationEndListener listener) { - animate(view, animatorRes, -1, listener); + public static void animate(@NonNull final View view, @AnimatorRes int animatorRes, + @Nullable OnAnimationEndListener listener) { + animate(view, animatorRes, -1, listener); + } + + public static void animate(final View view, @AnimatorRes int animatorRes, int duration, + @Nullable final OnAnimationEndListener listener) { + if (view == null) { + return; } - public static void animate(final View view, @AnimatorRes int animatorRes, int duration, @Nullable final OnAnimationEndListener listener) { - if (view == null) { - return; - } + view.setLayerType(View.LAYER_TYPE_HARDWARE, null); + Animator animator = AnimatorInflater.loadAnimator(view.getContext(), animatorRes); + if (duration != -1) { + animator.setDuration(duration); + } - view.setLayerType(View.LAYER_TYPE_HARDWARE, null); - Animator animator = AnimatorInflater.loadAnimator(view.getContext(), animatorRes); - if (duration != -1) { - animator.setDuration(duration); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + view.setLayerType(View.LAYER_TYPE_NONE, null); + if (listener != null) { + listener.onAnimationEnd(); } + } + }); + animator.setTarget(view); + animator.start(); + } - animator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - super.onAnimationEnd(animation); - view.setLayerType(View.LAYER_TYPE_NONE, null); - if (listener != null) { - listener.onAnimationEnd(); - } - } - }); - animator.setTarget(view); - animator.start(); - } + public static void animate(@NonNull final View view, @AnimatorRes int animatorRes) { + animate(view, animatorRes, -1); + } - public static void animate(@NonNull final View view, @AnimatorRes int animatorRes) { - animate(view, animatorRes, -1); - } - - public static void animate(@NonNull final View view, @AnimatorRes int animatorRes, int duration) { - animate(view, animatorRes, duration, null); - } + public static void animate(@NonNull final View view, @AnimatorRes int animatorRes, int duration) { + animate(view, animatorRes, duration, null); + } - public static void rotate(@NonNull final View view, float rotation) { - view.setLayerType(View.LAYER_TYPE_HARDWARE, null); - ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(view, View.ROTATION, view.getRotation(), rotation); - rotateAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - super.onAnimationEnd(animation); - view.setLayerType(View.LAYER_TYPE_NONE, null); - } - }); - rotateAnimator.start(); - } + public static void rotate(@NonNull final View view, float rotation) { + view.setLayerType(View.LAYER_TYPE_HARDWARE, null); + ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(view, View.ROTATION, view.getRotation(), rotation); + rotateAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + view.setLayerType(View.LAYER_TYPE_NONE, null); + } + }); + rotateAnimator.start(); + } - public static void rotateBy(@NonNull final View view, float rotationBy) { - view.setLayerType(View.LAYER_TYPE_HARDWARE, null); - view.animate().rotationBy(rotationBy).setInterpolator(new FastOutSlowInInterpolator()).setListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - super.onAnimationEnd(animation); - view.setLayerType(View.LAYER_TYPE_NONE, null); - } - }); - } + public static void rotateBy(@NonNull final View view, float rotationBy) { + view.setLayerType(View.LAYER_TYPE_HARDWARE, null); + view.animate().rotationBy(rotationBy).setInterpolator(new FastOutSlowInInterpolator()).setListener( + new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + view.setLayerType(View.LAYER_TYPE_NONE, null); + } + }); + } - public static void alpha(@NonNull final View convertView, float alpha, @Nullable final OnAnimationEndListener listener) { - convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null); - ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(convertView, View.ALPHA, convertView.getAlpha(), alpha); - rotateAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - super.onAnimationStart(animation); - convertView.setVisibility(View.VISIBLE); - } + public static void alpha(@NonNull final View convertView, float alpha, + @Nullable final OnAnimationEndListener listener) { + convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(convertView, View.ALPHA, convertView.getAlpha(), alpha); + rotateAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + convertView.setVisibility(View.VISIBLE); + } - @Override - public void onAnimationEnd(Animator animation) { - super.onAnimationEnd(animation); - convertView.setLayerType(View.LAYER_TYPE_NONE, null); - if (listener != null) { - listener.onAnimationEnd(); - } - } - }); - rotateAnimator.start(); - } + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + convertView.setLayerType(View.LAYER_TYPE_NONE, null); + if (listener != null) { + listener.onAnimationEnd(); + } + } + }); + rotateAnimator.start(); + } - public static void alpha(@NonNull final View convertView, float alpha) { - alpha(convertView, alpha, null); - } + public static void alpha(@NonNull final View convertView, float alpha) { + alpha(convertView, alpha, null); + } - public interface OnAnimationEndListener { - void onAnimationEnd(); - } + public interface OnAnimationEndListener { + void onAnimationEnd(); + } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java index 190e0b9b8f..d45d647247 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java @@ -19,101 +19,104 @@ import java.util.regex.Pattern; public class ColorUtils { - /** - * Returns a color integer associated as primary color from a theme based on a {@link Context}. - * - * @param context The context used to style the color attributes. - * @return The primary color value of current theme in the form 0xAARRGGBB. - */ - @ColorInt - public static int getPrimaryColor(@NonNull Context context) { - TypedValue typedValue = new TypedValue(); - Resources.Theme theme = context.getTheme(); - theme.resolveAttribute(R.attr.colorPrimary, typedValue, true); - return typedValue.data; - } + /** + * Returns a color integer associated as primary color from a theme based on a {@link Context}. + * + * @param context The context used to style the color attributes. + * @return The primary color value of current theme in the form 0xAARRGGBB. + */ + @ColorInt + public static int getPrimaryColor(@NonNull Context context) { + TypedValue typedValue = new TypedValue(); + Resources.Theme theme = context.getTheme(); + theme.resolveAttribute(R.attr.colorPrimary, typedValue, true); + return typedValue.data; + } - /** - * Returns a color integer associated as primary dark color from a theme based on a {@link Context}. - * - * @param context The context used to style the color attributes. - * @return The primary dark color value of current theme in the form 0xAARRGGBB. - */ - @ColorInt - public static int getPrimaryDarkColor(@NonNull Context context) { - TypedValue typedValue = new TypedValue(); - Resources.Theme theme = context.getTheme(); - theme.resolveAttribute(R.attr.colorPrimaryDark, typedValue, true); - return typedValue.data; - } + /** + * Returns a color integer associated as primary dark color from a theme based on a {@link Context}. + * + * @param context The context used to style the color attributes. + * @return The primary dark color value of current theme in the form 0xAARRGGBB. + */ + @ColorInt + public static int getPrimaryDarkColor(@NonNull Context context) { + TypedValue typedValue = new TypedValue(); + Resources.Theme theme = context.getTheme(); + theme.resolveAttribute(R.attr.colorPrimaryDark, typedValue, true); + return typedValue.data; + } - /** - * Returns a color integer associated as accent color from a theme based on a {@link Context}. - * - * @param context The context used to style the color attributes. - * @return The accent color value of current theme in the form 0xAARRGGBB. - */ - @ColorInt - public static int getAccentColor(@NonNull Context context) { - TypedValue typedValue = new TypedValue(); - Resources.Theme theme = context.getTheme(); - theme.resolveAttribute(R.attr.colorAccent, typedValue, true); - return typedValue.data; - } + /** + * Returns a color integer associated as accent color from a theme based on a {@link Context}. + * + * @param context The context used to style the color attributes. + * @return The accent color value of current theme in the form 0xAARRGGBB. + */ + @ColorInt + public static int getAccentColor(@NonNull Context context) { + TypedValue typedValue = new TypedValue(); + Resources.Theme theme = context.getTheme(); + theme.resolveAttribute(R.attr.colorAccent, typedValue, true); + return typedValue.data; + } - /** - * Returns a color state list associated with a theme based on a {@link Context} - * - * @param color The color used for tinting. - * @return A ColorStateList object containing the primary color of a theme - */ - @NonNull - public static ColorStateList getSelector(@ColorInt int color) { - return new ColorStateList( - new int[][]{ - new int[]{android.R.attr.state_pressed}, - new int[]{} - }, - new int[]{ - color, - color - } - ); - } + /** + * Returns a color state list associated with a theme based on a {@link Context} + * + * @param color The color used for tinting. + * @return A ColorStateList object containing the primary color of a theme + */ + @NonNull + public static ColorStateList getSelector(@ColorInt int color) { + return new ColorStateList( + new int[][] { + new int[] {android.R.attr.state_pressed}, + new int[] {} + }, + new int[] { + color, + color + } + ); + } - /** - * Set a color tint list to the {@link Drawable} of an {@link ImageView}. - * - * @param imageView The view to set the default tint list. - * @param tintColor The color to tint. - */ - public static void setTintList(@NonNull ImageView imageView, @ColorInt int tintColor) { - Drawable originalDrawable = imageView.getDrawable(); - Drawable wrappedDrawable = DrawableCompat.wrap(originalDrawable); - DrawableCompat.setTintList(wrappedDrawable, getSelector(tintColor)); - } + /** + * Set a color tint list to the {@link Drawable} of an {@link ImageView}. + * + * @param imageView The view to set the default tint list. + * @param tintColor The color to tint. + */ + public static void setTintList(@NonNull ImageView imageView, @ColorInt int tintColor) { + Drawable originalDrawable = imageView.getDrawable(); + Drawable wrappedDrawable = DrawableCompat.wrap(originalDrawable); + DrawableCompat.setTintList(wrappedDrawable, getSelector(tintColor)); + } - static int normalizeColorComponent(String value) { - return (int) (Float.parseFloat(value) * 255); - } + static int normalizeColorComponent(String value) { + return (int) (Float.parseFloat(value) * 255); + } - /** - * Convert an rgba string to a Color int. - * - * @param value the String representation of rgba - * @return the int representation of rgba - * @throws ConversionException on illegal input - */ - @ColorInt - public static int rgbaToColor(String value) { - Pattern c = Pattern.compile("rgba?\\s*\\(\\s*(\\d+\\.?\\d*)\\s*,\\s*(\\d+\\.?\\d*)\\s*,\\s*(\\d+\\.?\\d*)\\s*,?\\s*(\\d+\\.?\\d*)?\\s*\\)"); - Matcher m = c.matcher(value); - if (m.matches() && m.groupCount() == 3) { - return Color.rgb(normalizeColorComponent(m.group(1)), normalizeColorComponent(m.group(2)), normalizeColorComponent(m.group(3))); - } else if (m.matches() && m.groupCount() == 4) { - return Color.argb(normalizeColorComponent(m.group(4)), normalizeColorComponent(m.group(1)), normalizeColorComponent(m.group(2)), normalizeColorComponent(m.group(3))); - } else { - throw new ConversionException("Not a valid rgb/rgba value"); - } + /** + * Convert an rgba string to a Color int. + * + * @param value the String representation of rgba + * @return the int representation of rgba + * @throws ConversionException on illegal input + */ + @ColorInt + public static int rgbaToColor(String value) { + Pattern c = Pattern.compile("rgba?\\s*\\(\\s*(\\d+\\.?\\d*)\\s*,\\s*(\\d+\\.?\\d*)\\s*,\\s*(\\d+\\.?\\d*)\\s*," + + "?\\s*(\\d+\\.?\\d*)?\\s*\\)"); + Matcher m = c.matcher(value); + if (m.matches() && m.groupCount() == 3) { + return Color.rgb(normalizeColorComponent(m.group(1)), normalizeColorComponent(m.group(2)), + normalizeColorComponent(m.group(3))); + } else if (m.matches() && m.groupCount() == 4) { + return Color.argb(normalizeColorComponent(m.group(4)), normalizeColorComponent(m.group(1)), + normalizeColorComponent(m.group(2)), normalizeColorComponent(m.group(3))); + } else { + throw new ConversionException("Not a valid rgb/rgba value"); } + } }
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java index 2c1a1b8e64..30ec214798 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java @@ -2,63 +2,65 @@ package com.mapbox.mapboxsdk.utils; public class MathUtils { - /** - * Test a value in specified range, returning minimum if it's below, and maximum if it's above - * @param value Value to test - * @param min Minimum value of range - * @param max Maximum value of range - * @return value if it's between min and max, min if it's below, max if it's above - */ - public static double clamp(double value, double min, double max) { - return Math.max(min, Math.min(max, value)); - } + /** + * Test a value in specified range, returning minimum if it's below, and maximum if it's above + * + * @param value Value to test + * @param min Minimum value of range + * @param max Maximum value of range + * @return value if it's between min and max, min if it's below, max if it's above + */ + public static double clamp(double value, double min, double max) { + return Math.max(min, Math.min(max, value)); + } - /** - * Test a value in specified range, returning minimum if it's below, and maximum if it's above - * @param value Value to test - * @param min Minimum value of range - * @param max Maximum value of range - * @return value if it's between min and max, min if it's below, max if it's above - */ - public static float clamp(float value, float min, float max) { - return Math.max(min, Math.min(max, value)); - } + /** + * Test a value in specified range, returning minimum if it's below, and maximum if it's above + * + * @param value Value to test + * @param min Minimum value of range + * @param max Maximum value of range + * @return value if it's between min and max, min if it's below, max if it's above + */ + public static float clamp(float value, float min, float max) { + return Math.max(min, Math.min(max, value)); + } - /** - * Constrains value to the given range (including min, excluding max) via modular arithmetic. - * - * Same formula as used in Core GL (wrap.hpp) - * std::fmod((std::fmod((value - min), d) + d), d) + min; - * - * @param value Value to wrap - * @param min Minimum value - * @param max Maximum value - * @return Wrapped value - */ - public static double wrap(double value, double min, double max) { - double delta = max - min; + /** + * Constrains value to the given range (including min, excluding max) via modular arithmetic. + * <p> + * Same formula as used in Core GL (wrap.hpp) + * std::fmod((std::fmod((value - min), d) + d), d) + min; + * + * @param value Value to wrap + * @param min Minimum value + * @param max Maximum value + * @return Wrapped value + */ + public static double wrap(double value, double min, double max) { + double delta = max - min; - double firstMod = (value - min) % delta; - double secondMod = (firstMod + delta) % delta; + double firstMod = (value - min) % delta; + double secondMod = (firstMod + delta) % delta; - return secondMod + min; - } + return secondMod + min; + } - /** - * Convert bearing from core to match Android SDK value. - * - * @param nativeBearing bearing value coming from core - * @return bearing in degrees starting from 0 rotating clockwise - */ - public static double convertNativeBearing(double nativeBearing) { - double direction = -nativeBearing; + /** + * Convert bearing from core to match Android SDK value. + * + * @param nativeBearing bearing value coming from core + * @return bearing in degrees starting from 0 rotating clockwise + */ + public static double convertNativeBearing(double nativeBearing) { + double direction = -nativeBearing; - while (direction > 360) { - direction -= 360; - } - while (direction < 0) { - direction += 360; - } - return direction; + while (direction > 360) { + direction -= 360; + } + while (direction < 0) { + direction += 360; } + return direction; + } } |