Various improvements and fixes for MapBox maps implementation

This commit is contained in:
Marvin W 2019-10-15 14:59:34 +02:00
parent 3c5e68404b
commit fc3e24c0ea
No known key found for this signature in database
GPG Key ID: 072E9235DB996F2A
17 changed files with 350 additions and 149 deletions

View File

@ -65,9 +65,9 @@ public class CreatorImpl extends ICreator.Stub {
@Override
public void initV2(IObjectWrapper resources, int flags) {
BitmapDescriptorFactoryImpl.INSTANCE.initialize(ObjectWrapper.unwrapTyped(resources, Resources.class));
BitmapDescriptorFactoryImpl.INSTANCE.initialize(ObjectWrapper.unwrapTyped(resources, Resources.class), null);
//ResourcesContainer.set((Resources) ObjectWrapper.unwrap(resources));
Log.d(TAG, "initV2");
Log.d(TAG, "initV2 " + flags);
}
@Override

View File

@ -16,6 +16,7 @@
package org.microg.gms.maps.mapbox
import android.util.Log
import com.mapbox.mapboxsdk.camera.CameraPosition
import com.mapbox.mapboxsdk.camera.CameraUpdate
import com.mapbox.mapboxsdk.geometry.LatLngBounds
@ -28,12 +29,13 @@ internal class CameraBoundsWithSizeUpdate(val bounds: LatLngBounds, val width: I
override fun getCameraPosition(map: MapboxMap): CameraPosition? {
val padding = this.padding.clone()
val widthPad = (map.padding[0] + map.padding[2])/2
val heightPad = (map.padding[1] + map.padding[3])/2
val widthPad = ((map.width + map.padding[0] + map.padding[2] - width) / 2).toInt()
val heightPad = ((map.height + map.padding[1] + map.padding[3] - height) / 2).toInt()
padding[0] += widthPad
padding[1] += heightPad
padding[2] += widthPad
padding[3] += heightPad
Log.d(TAG, "map ${map.width} ${map.height}, set $width $height -> ${padding.map { it.toString() }.reduce { a, b -> "$a,$b"}}")
return map.getCameraForLatLngBounds(bounds, padding)
}
@ -78,6 +80,6 @@ internal class CameraBoundsWithSizeUpdate(val bounds: LatLngBounds, val width: I
}
companion object {
val TAG = "GmsCameraBounds"
const val TAG = "GmsMapCameraBounds"
}
}

View File

@ -61,11 +61,8 @@ class CameraUpdateFactoryImpl : ICameraUpdateFactoryDelegate.Stub() {
return ObjectWrapper.wrap(NoCameraUpdate())
}
override fun newLatLngBoundsWithSize(bounds: LatLngBounds, width: Int, height: Int, padding: Int): IObjectWrapper {
Log.d(TAG, "unimplemented Method: newLatLngBoundsWithSize")
return ObjectWrapper.wrap(CameraBoundsWithSizeUpdate(bounds.toMapbox(), width, height, padding))
}
override fun newLatLngBoundsWithSize(bounds: LatLngBounds, width: Int, height: Int, padding: Int): IObjectWrapper =
ObjectWrapper.wrap(CameraBoundsWithSizeUpdate(bounds.toMapbox(), width, height, padding))
override fun onTransact(code: Int, data: Parcel?, reply: Parcel?, flags: Int): Boolean =
if (super.onTransact(code, data, reply, flags)) {

View File

@ -20,6 +20,7 @@ import android.annotation.SuppressLint
import android.content.Context
import android.location.Location
import android.os.Bundle
import android.os.IBinder
import android.os.Parcel
import android.support.annotation.IdRes
import android.support.annotation.Keep
@ -66,12 +67,14 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
val dpiFactor: Float
get() = context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT
private var mapView: MapView?
private var mapView: MapView? = null
private var created = false
private var initialized = false
private val initializedCallbackList = mutableListOf<IOnMapReadyCallback>()
private var loaded = false
private val mapLock = Object()
private val initializedCallbackList = mutableListOf<IOnMapReadyCallback>()
private var loadedCallback : IOnMapLoadedCallback? = null
private var cameraChangeListener: IOnCameraChangeListener? = null
private var cameraMoveListener: IOnCameraMoveListener? = null
private var cameraMoveCanceledListener: IOnCameraMoveCanceledListener? = null
@ -83,7 +86,12 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
private var markerDragListener: IOnMarkerDragListener? = null
var lineManager: LineManager? = null
val pendingLines = mutableSetOf<PolylineImpl>()
var lineId = 0L
var fillManager: FillManager? = null
val pendingFills = mutableSetOf<PolygonImpl>()
var fillId = 0L
var circleManager: CircleManager? = null
val pendingCircles = mutableSetOf<CircleImpl>()
@ -99,6 +107,7 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
init {
val mapContext = MapContext(context)
BitmapDescriptorFactoryImpl.initialize(mapContext.resources, context.resources)
LibraryLoader.setLibraryLoader(MultiArchLoader(mapContext, context))
Mapbox.getInstance(mapContext, BuildConfig.MAPBOX_KEY)
@ -137,8 +146,6 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
return null
}
}
this.mapView = MapView(mapContext)
this.view.addView(this.mapView)
}
override fun getCameraPosition(): CameraPosition? = map?.cameraPosition?.toGms()
@ -147,43 +154,57 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
override fun moveCamera(cameraUpdate: IObjectWrapper?) {
val update = cameraUpdate.unwrap<CameraUpdate>() ?: return
val map = this.map
if (map != null) {
map.moveCamera(update)
} else {
waitingCameraUpdates.add(update)
synchronized(mapLock) {
if (initialized) {
this.map?.moveCamera(update)
} else {
waitingCameraUpdates.add(update)
}
}
}
override fun animateCamera(cameraUpdate: IObjectWrapper?) {
val update = cameraUpdate.unwrap<CameraUpdate>() ?: return
val map = this.map
if (map != null) {
map.animateCamera(update)
} else {
waitingCameraUpdates.add(update)
synchronized(mapLock) {
if (initialized) {
this.map?.animateCamera(update)
} else {
waitingCameraUpdates.add(update)
}
}
}
fun afterInitialized(runnable: () -> Unit) {
initializedCallbackList.add(object : IOnMapReadyCallback {
override fun onMapReady(map: IGoogleMapDelegate?) {
runnable()
}
override fun asBinder(): IBinder? = null
})
}
override fun animateCameraWithCallback(cameraUpdate: IObjectWrapper?, callback: ICancelableCallback?) {
val update = cameraUpdate.unwrap<CameraUpdate>() ?: return
val map = this.map
if (map != null) {
map.animateCamera(update, callback?.toMapbox())
} else {
waitingCameraUpdates.add(update)
callback?.onFinish()
synchronized(mapLock) {
if (initialized) {
this.map?.animateCamera(update, callback?.toMapbox())
} else {
waitingCameraUpdates.add(update)
afterInitialized { callback?.onFinish() }
}
}
}
override fun animateCameraWithDurationAndCallback(cameraUpdate: IObjectWrapper?, duration: Int, callback: ICancelableCallback?) {
val update = cameraUpdate.unwrap<CameraUpdate>() ?: return
val map = this.map
if (map != null) {
map.animateCamera(update, duration, callback?.toMapbox())
} else {
waitingCameraUpdates.add(update)
callback?.onFinish()
synchronized(mapLock) {
if (initialized) {
this.map?.animateCamera(update, duration, callback?.toMapbox())
} else {
waitingCameraUpdates.add(update)
afterInitialized { callback?.onFinish() }
}
}
}
@ -207,21 +228,30 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
}
override fun addPolyline(options: PolylineOptions): IPolylineDelegate? {
val lineOptions = LineOptions()
.withLatLngs(options.points.map { it.toMapbox() })
.withLineWidth(options.width / dpiFactor)
.withLineColor(ColorUtils.colorToRgbaString(options.color))
.withLineOpacity(if (options.isVisible) 1f else 0f)
return lineManager?.let { PolylineImpl(this, it.create(lineOptions)) }
val line = PolylineImpl(this, "l${lineId++}", options)
synchronized(this) {
val lineManager = lineManager
if (lineManager == null) {
pendingLines.add(line)
} else {
line.update(lineManager)
}
}
return line
}
override fun addPolygon(options: PolygonOptions): IPolygonDelegate? {
val fillOptions = FillOptions()
.withLatLngs(listOf(options.points.map { it.toMapbox() }))
.withFillColor(ColorUtils.colorToRgbaString(options.fillColor))
.withFillOpacity(if (options.isVisible) 1f else 0f)
return fillManager?.let { PolygonImpl(this, it.create(fillOptions)) }
val fill = PolygonImpl(this, "p${fillId++}", options)
synchronized(this) {
val fillManager = fillManager
if (fillManager == null) {
pendingFills.add(fill)
} else {
fill.update(fillManager)
}
}
return fill
}
override fun addMarker(options: MarkerOptions): IMarkerDelegate? {
@ -412,7 +442,7 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
}
override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {
Log.d(TAG, "padding: $left, $top, $right, $bottom")
Log.d(TAG, "setPadding: $left $top $right $bottom")
map?.setPadding(left, top, right, bottom)
val fourDp = mapView?.context?.resources?.getDimension(R.dimen.mapbox_four_dp)?.toInt() ?: 0
val ninetyTwoDp = mapView?.context?.resources?.getDimension(R.dimen.mapbox_ninety_two_dp)?.toInt()
@ -433,8 +463,23 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
}
override fun setOnMapLoadedCallback(callback: IOnMapLoadedCallback?) {
Log.d(TAG, "unimplemented Method: setOnMapLoadedCallback")
if (callback != null) {
synchronized(mapLock) {
if (loaded) {
Log.d(TAG, "Invoking callback instantly, as map is loaded")
try {
callback.onMapLoaded()
} catch (e: Exception) {
Log.w(TAG, e)
}
} else {
Log.d(TAG, "Delay callback invocation, as map is not yet loaded")
loadedCallback = callback
}
}
} else {
loadedCallback = null
}
}
override fun setCameraMoveStartedListener(listener: IOnCameraMoveStartedListener?) {
@ -455,8 +500,12 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
override fun onCreate(savedInstanceState: Bundle?) {
if (!created) {
mapView?.onCreate(savedInstanceState?.toMapbox())
mapView?.getMapAsync(this::initMap)
Log.d(TAG, "create");
val mapView = MapView(MapContext(context))
this.mapView = mapView
view.addView(mapView)
mapView.onCreate(savedInstanceState?.toMapbox())
mapView.getMapAsync(this::initMap)
created = true
}
}
@ -533,9 +582,11 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
options.scrollGesturesEnabled?.let { map.uiSettings.isScrollGesturesEnabled = it }
options.tiltGesturesEnabled?.let { map.uiSettings.isTiltGesturesEnabled = it }
options.camera?.let { map.cameraPosition = it.toMapbox() }
waitingCameraUpdates.forEach { map.moveCamera(it) }
synchronized(mapLock) {
initialized = true
waitingCameraUpdates.forEach { map.moveCamera(it) }
val initializedCallbackList = ArrayList(initializedCallbackList)
Log.d(TAG, "Invoking ${initializedCallbackList.size} callbacks delayed, as map is initialized")
for (callback in initializedCallbackList) {
try {
@ -544,30 +595,37 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
Log.w(TAG, e)
}
}
initialized = true
}
map.getStyle {
mapView?.let { view ->
circleManager = CircleManager(view, map, it)
lineManager = LineManager(view, map, it)
fillManager = FillManager(view, map, it)
lineManager?.lineCap = LINE_CAP_ROUND
synchronized(this) {
val symbolManager = SymbolManager(view, map, it)
pendingMarkers.forEach { it.update(symbolManager) }
pendingMarkers.clear()
if (loaded) return@let
val symbolManager: SymbolManager
val lineManager: LineManager
val circleManager: CircleManager
val fillManager: FillManager
synchronized(mapLock) {
circleManager = CircleManager(view, map, it)
fillManager = FillManager(view, map, it)
symbolManager = SymbolManager(view, map, it)
lineManager = LineManager(view, map, it)
lineManager.lineCap = LINE_CAP_ROUND
this.symbolManager = symbolManager
this.lineManager = lineManager
this.circleManager = circleManager
this.fillManager = fillManager
}
symbolManager?.iconAllowOverlap = true
symbolManager?.addClickListener {
symbolManager.iconAllowOverlap = true
symbolManager.addClickListener {
try {
markers[it.id]?.let { markerClickListener?.onMarkerClick(it) }
} catch (e: Exception) {
Log.w(TAG, e)
}
}
symbolManager?.addDragListener(object : OnSymbolDragListener {
symbolManager.addDragListener(object : OnSymbolDragListener {
override fun onAnnotationDragStarted(annotation: Symbol?) {
try {
markers[annotation?.id]?.let { markerDragListener?.onMarkerDragStart(it) }
@ -591,9 +649,23 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
Log.w(TAG, e)
}
}
})
pendingCircles.forEach { it.update(circleManager) }
pendingCircles.clear()
pendingFills.forEach { it.update(fillManager) }
pendingFills.clear()
pendingLines.forEach { it.update(lineManager) }
pendingLines.clear()
pendingMarkers.forEach { it.update(symbolManager) }
pendingMarkers.clear()
synchronized(mapLock) {
loaded = true
if (loadedCallback != null) {
Log.d(TAG, "Invoking callback delayed, as map is loaded")
loadedCallback?.onMapLoaded()
}
}
}
}
}
@ -606,6 +678,7 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
override fun onResume() = mapView?.onResume() ?: Unit
override fun onPause() = mapView?.onPause() ?: Unit
override fun onDestroy() {
Log.d(TAG, "destroy");
circleManager?.onDestroy()
circleManager = null
lineManager?.onDestroy()
@ -621,14 +694,18 @@ class GoogleMapImpl(private val context: Context, var options: GoogleMapOptions)
// TODO can crash?
mapView?.onDestroy()
mapView = null
map = null
created = false
initialized = false
loaded = false
}
override fun onStart() {
Log.d(TAG, "unimplemented Method: onStart")
mapView?.onStart()
}
override fun onStop() {
Log.d(TAG, "unimplemented Method: onStop")
mapView?.onStop()
}
override fun onEnterAmbient(bundle: Bundle?) {

View File

@ -78,7 +78,6 @@ class MapFragmentImpl(private val activity: Activity) : IMapFragmentDelegate.Stu
override fun onDestroyView() {
map?.onDestroy()
map = null
}
override fun onDestroy() {

View File

@ -17,23 +17,26 @@
package org.microg.gms.maps.mapbox.model
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.*
import android.os.Parcel
import android.util.Log
import com.google.android.gms.dynamic.IObjectWrapper
import com.google.android.gms.dynamic.ObjectWrapper
import com.google.android.gms.maps.model.internal.IBitmapDescriptorFactoryDelegate
import com.mapbox.mapboxsdk.maps.MapboxMap
import org.microg.gms.maps.mapbox.R
object BitmapDescriptorFactoryImpl : IBitmapDescriptorFactoryDelegate.Stub() {
private val TAG = "GmsMapBitmap"
private var resources: Resources? = null
private var mapResources: Resources? = null
private val maps = hashSetOf<MapboxMap>()
private val bitmaps = hashMapOf<String, Bitmap>()
fun initialize(resources: Resources) {
BitmapDescriptorFactoryImpl.resources = resources
fun initialize(mapResources: Resources?, resources: Resources?) {
BitmapDescriptorFactoryImpl.mapResources = mapResources ?: resources
BitmapDescriptorFactoryImpl.resources = resources ?: mapResources
}
fun registerMap(map: MapboxMap) {
@ -56,9 +59,13 @@ object BitmapDescriptorFactoryImpl : IBitmapDescriptorFactoryDelegate.Stub() {
?: floatArrayOf(0f, 0f)
private fun registerBitmap(id: String, bitmapCreator: () -> Bitmap?) {
val bitmap = synchronized(bitmaps) {
val bitmap: Bitmap = synchronized(bitmaps) {
if (bitmaps.contains(id)) return
val bitmap = bitmapCreator() ?: return
val bitmap = bitmapCreator()
if (bitmap == null) {
Log.w(TAG, "Failed to register bitmap $id, creator returned null")
return
}
bitmaps[id] = bitmap
bitmap
}
@ -69,7 +76,17 @@ object BitmapDescriptorFactoryImpl : IBitmapDescriptorFactoryDelegate.Stub() {
override fun fromResource(resourceId: Int): IObjectWrapper? {
val id = "resource-$resourceId"
registerBitmap(id) { BitmapFactory.decodeResource(resources, resourceId) }
registerBitmap(id) {
val bitmap = BitmapFactory.decodeResource(resources, resourceId)
if (bitmap == null) {
try {
Log.d(TAG, "Resource $resourceId not found in $resources (${resources?.getResourceName(resourceId)})")
} catch (e: Resources.NotFoundException) {
Log.d(TAG, "Resource $resourceId not found in $resources")
}
}
bitmap
}
return ObjectWrapper.wrap(BitmapDescriptorImpl(id, bitmapSize(id)))
}
@ -86,15 +103,45 @@ object BitmapDescriptorFactoryImpl : IBitmapDescriptorFactoryDelegate.Stub() {
}
override fun defaultMarker(): IObjectWrapper? {
Log.d(TAG, "unimplemented Method: defaultMarker")
val id = "marker"
return ObjectWrapper.wrap(BitmapDescriptorImpl("marker", bitmapSize(id)))
registerBitmap(id) { BitmapFactory.decodeResource(mapResources, R.drawable.maps_default_marker) }
return ObjectWrapper.wrap(BitmapDescriptorImpl(id, bitmapSize(id)))
}
private fun adjustHue(cm: ColorMatrix, value: Float) {
var value = value
value = cleanValue(value, 180f) / 180f * Math.PI.toFloat()
if (value == 0f) {
return
}
val cosVal = Math.cos(value.toDouble()).toFloat()
val sinVal = Math.sin(value.toDouble()).toFloat()
val lumR = 0.213f
val lumG = 0.715f
val lumB = 0.072f
val mat = floatArrayOf(lumR + cosVal * (1 - lumR) + sinVal * -lumR, lumG + cosVal * -lumG + sinVal * -lumG, lumB + cosVal * -lumB + sinVal * (1 - lumB), 0f, 0f, lumR + cosVal * -lumR + sinVal * 0.143f, lumG + cosVal * (1 - lumG) + sinVal * 0.140f, lumB + cosVal * -lumB + sinVal * -0.283f, 0f, 0f, lumR + cosVal * -lumR + sinVal * -(1 - lumR), lumG + cosVal * -lumG + sinVal * lumG, lumB + cosVal * (1 - lumB) + sinVal * lumB, 0f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 0f, 1f)
cm.postConcat(ColorMatrix(mat))
}
private fun cleanValue(p_val: Float, p_limit: Float): Float {
return Math.min(p_limit, Math.max(-p_limit, p_val))
}
override fun defaultMarkerWithHue(hue: Float): IObjectWrapper? {
val id = "marker"
Log.d(TAG, "unimplemented Method: defaultMarkerWithHue")
return ObjectWrapper.wrap(ColorBitmapDescriptorImpl("marker", bitmapSize(id), hue))
val id = "marker-${hue.toInt()}"
registerBitmap(id) {
val bitmap = BitmapFactory.decodeResource(mapResources, R.drawable.maps_default_marker).copy(Bitmap.Config.ARGB_8888, true)
val paint = Paint()
val matrix = ColorMatrix()
val huex = hue % 360f
adjustHue(matrix, if (huex > 180f) huex - 360f else huex)
paint.setColorFilter(ColorMatrixColorFilter(matrix))
val canvas = Canvas(bitmap)
canvas.drawBitmap(bitmap, 0f, 0f, paint)
bitmap
}
return ObjectWrapper.wrap(ColorBitmapDescriptorImpl(id, bitmapSize(id), hue))
}
override fun fromBitmap(bitmap: Bitmap): IObjectWrapper? {

View File

@ -116,6 +116,14 @@ class CircleImpl(private val map: GoogleMapImpl, private val id: String, options
override fun hashCodeRemote(): Int = hashCode()
override fun hashCode(): Int {
return id.hashCode()
}
override fun toString(): String {
return id
}
override fun equals(other: Any?): Boolean {
if (other is CircleImpl) {
return other.id == id

View File

@ -16,6 +16,7 @@
package org.microg.gms.maps.mapbox.model
import android.util.Log
import com.mapbox.mapboxsdk.plugins.annotation.Annotation
import com.mapbox.mapboxsdk.plugins.annotation.AnnotationManager
import com.mapbox.mapboxsdk.plugins.annotation.Options
@ -37,4 +38,8 @@ interface Markup<T : Annotation<*>, S : Options<T>> {
}
}
}
companion object {
private val TAG = "GmsMapMarkup"
}
}

View File

@ -19,57 +19,93 @@ package org.microg.gms.maps.mapbox.model
import android.os.Parcel
import android.util.Log
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.PolygonOptions
import com.google.android.gms.maps.model.PolylineOptions
import com.google.android.gms.maps.model.internal.IPolygonDelegate
import com.mapbox.mapboxsdk.plugins.annotation.AnnotationManager
import com.mapbox.mapboxsdk.plugins.annotation.Fill
import com.mapbox.mapboxsdk.plugins.annotation.FillOptions
import com.mapbox.mapboxsdk.utils.ColorUtils
import org.microg.gms.maps.mapbox.GoogleMapImpl
import org.microg.gms.maps.mapbox.utils.toGms
import org.microg.gms.maps.mapbox.utils.toMapbox
class PolygonImpl(private val map: GoogleMapImpl, private val fill: Fill) : IPolygonDelegate.Stub() {
class PolygonImpl(private val map: GoogleMapImpl, private val id: String, options: PolygonOptions) : IPolygonDelegate.Stub(), Markup<Fill, FillOptions> {
private var points = ArrayList(options.points)
private var holes: List<List<LatLng>> = ArrayList(options.holes.map { ArrayList(it) })
private var fillColor = options.fillColor
private var strokeColor = options.strokeColor
private var strokeWidth = options.strokeWidth
private var visible: Boolean = options.isVisible
private var strokes = (listOf(PolylineImpl(map, "$id-stroke-main", PolylineOptions().color(strokeColor).width(strokeWidth).addAll(points)))
+ holes.mapIndexed { idx, it -> PolylineImpl(map, "$id-stroke-hole-$idx", PolylineOptions().color(strokeColor).width(strokeWidth).addAll(it)) }).toMutableList()
override var annotation: Fill? = null
override var removed: Boolean = false
override val annotationOptions: FillOptions
get() = FillOptions()
.withLatLngs(mutableListOf(points.map { it.toMapbox() }).plus(holes.map { it.map { it.toMapbox() } }))
.withFillColor(ColorUtils.colorToRgbaString(fillColor))
.withFillOpacity(if (visible) 1f else 0f)
override fun remove() {
map.fillManager?.delete(fill)
removed = true
map.fillManager?.let { update(it) }
strokes.forEach { it.remove() }
}
override fun getId(): String = "p" + fill.id.toString()
override fun update(manager: AnnotationManager<*, Fill, FillOptions, *, *, *>) {
super.update(manager)
map.lineManager?.let { lineManager -> strokes.forEach { it.update(lineManager) } }
}
override fun getId(): String = id
override fun setPoints(points: List<LatLng>) {
fill.latLngs = listOf(points.map { it.toMapbox() })
map.fillManager?.update(fill)
this.points = ArrayList(points)
annotation?.latLngs = mutableListOf(points.map { it.toMapbox() }).plus(holes.map { it.map { it.toMapbox() } })
map.fillManager?.let { update(it) }
strokes[0].points = points
}
override fun getPoints(): List<LatLng> = fill.latLngs[0]?.map { it.toGms() } ?: emptyList()
override fun getPoints(): List<LatLng> = points
override fun setHoles(holes: List<Any?>?) {
Log.d(TAG, "unimplemented Method: setHoles")
this.holes = if (holes == null) emptyList() else ArrayList(holes.mapNotNull { if (it is List<*>) it.mapNotNull { if (it is LatLng) it else null }.let { if (it.isNotEmpty()) it else null } else null })
annotation?.latLngs = mutableListOf(points.map { it.toMapbox() }).plus(this.holes.map { it.map { it.toMapbox() } })
while (this.holes.size < strokes.size) {
val last = strokes.last()
last.remove()
strokes.remove(last)
}
strokes.forEachIndexed { idx, it -> it.points = this.holes[idx] }
strokes.addAll(this.holes.subList(strokes.size, this.holes.lastIndex).mapIndexed { idx, it -> PolylineImpl(map, "$id-stroke-hole-${strokes.size + idx}", PolylineOptions().color(strokeColor).width(strokeWidth).addAll(it)) })
map.fillManager?.let { update(it) }
}
override fun getHoles(): List<Any?> {
Log.d(TAG, "unimplemented Method: getHoles")
return emptyList()
}
override fun getHoles(): List<Any?> = holes
override fun setStrokeWidth(width: Float) {
Log.d(TAG, "unimplemented Method: setStrokeWidth")
this.strokeWidth = width
strokes.forEach { it.width = width }
}
override fun getStrokeWidth(): Float {
Log.d(TAG, "unimplemented Method: getStrokeWidth")
return 0f
}
override fun getStrokeWidth(): Float = strokeWidth
override fun setStrokeColor(color: Int) {
fill.setFillOutlineColor(color)
map.fillManager?.update(fill)
this.strokeColor = color
strokes.forEach { it.color = color }
}
override fun getStrokeColor(): Int = fill.fillOutlineColorAsInt
override fun getStrokeColor(): Int = strokeColor
override fun setFillColor(color: Int) {
fill.setFillColor(color)
map.fillManager?.update(fill)
this.fillColor = color
annotation?.setFillColor(color)
map.fillManager?.let { update(it) }
}
override fun getFillColor(): Int = fill.fillColorAsInt
override fun getFillColor(): Int = fillColor
override fun setZIndex(zIndex: Float) {
Log.d(TAG, "unimplemented Method: setZIndex")
@ -81,11 +117,12 @@ class PolygonImpl(private val map: GoogleMapImpl, private val fill: Fill) : IPol
}
override fun setVisible(visible: Boolean) {
fill.fillOpacity = if (visible) 1f else 0f
map.fillManager?.update(fill)
this.visible = visible
annotation?.fillOpacity = if (visible) 1f else 0f
map.fillManager?.let { update(it) }
}
override fun isVisible(): Boolean = fill.fillOpacity != 0f
override fun isVisible(): Boolean = visible
override fun setGeodesic(geod: Boolean) {
Log.d(TAG, "unimplemented Method: setGeodesic")
@ -100,9 +137,17 @@ class PolygonImpl(private val map: GoogleMapImpl, private val fill: Fill) : IPol
override fun hashCodeRemote(): Int = hashCode()
override fun hashCode(): Int {
return id.hashCode()
}
override fun toString(): String {
return id
}
override fun equals(other: Any?): Boolean {
if (other is PolygonImpl) {
return other.fill == fill
return other.id == id
}
return false
}

View File

@ -21,37 +21,57 @@ import android.util.Log
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.internal.IPolylineDelegate
import com.mapbox.mapboxsdk.plugins.annotation.Line
import com.mapbox.mapboxsdk.plugins.annotation.LineOptions
import com.mapbox.mapboxsdk.utils.ColorUtils
import org.microg.gms.maps.mapbox.GoogleMapImpl
import org.microg.gms.maps.mapbox.utils.toGms
import org.microg.gms.maps.mapbox.utils.toMapbox
import com.google.android.gms.maps.model.PolylineOptions as GmsLineOptions
class PolylineImpl(private val map: GoogleMapImpl, private val id: String, options: GmsLineOptions) : IPolylineDelegate.Stub(), Markup<Line, LineOptions> {
private var points = ArrayList(options.points)
private var width = options.width
private var color = options.color
private var visible: Boolean = options.isVisible
override var annotation: Line? = null
override var removed: Boolean = false
override val annotationOptions: LineOptions
get() = LineOptions()
.withLatLngs(points.map { it.toMapbox() })
.withLineWidth(width / map.dpiFactor)
.withLineColor(ColorUtils.colorToRgbaString(color))
.withLineOpacity(if (visible) 1f else 0f)
class PolylineImpl(private val map: GoogleMapImpl, private val line: Line) : IPolylineDelegate.Stub() {
override fun remove() {
map.lineManager?.delete(line)
removed = true
map.lineManager?.let { update(it) }
}
override fun getId(): String = "l" + line.id.toString()
override fun getId(): String = id
override fun setPoints(points: List<LatLng>) {
line.latLngs = points.map { it.toMapbox() }
map.lineManager?.update(line)
this.points = ArrayList(points)
annotation?.latLngs = points.map { it.toMapbox() }
map.lineManager?.let { update(it) }
}
override fun getPoints(): List<LatLng> = line.latLngs.map { it.toGms() }
override fun getPoints(): List<LatLng> = points
override fun setWidth(width: Float) {
line.lineWidth = width / map.dpiFactor
map.lineManager?.update(line)
this.width = width
annotation?.lineWidth = width / map.dpiFactor
map.lineManager?.let { update(it) }
}
override fun getWidth(): Float = line.lineWidth * map.dpiFactor
override fun getWidth(): Float = width
override fun setColor(color: Int) {
line.setLineColor(color)
map.lineManager?.update(line)
this.color = color
annotation?.setLineColor(color)
map.lineManager?.let { update(it) }
}
override fun getColor(): Int = line.lineColorAsInt
override fun getColor(): Int = color
override fun setZIndex(zIndex: Float) {
Log.d(TAG, "unimplemented Method: setZIndex")
@ -63,11 +83,12 @@ class PolylineImpl(private val map: GoogleMapImpl, private val line: Line) : IPo
}
override fun setVisible(visible: Boolean) {
line.lineOpacity = if (visible) 1f else 0f
map.lineManager?.update(line)
this.visible = visible
annotation?.lineOpacity = if (visible) 1f else 0f
map.lineManager?.let { update(it) }
}
override fun isVisible(): Boolean = line.lineOpacity != 0f
override fun isVisible(): Boolean = visible
override fun setGeodesic(geod: Boolean) {
Log.d(TAG, "unimplemented Method: setGeodesic")
@ -82,9 +103,17 @@ class PolylineImpl(private val map: GoogleMapImpl, private val line: Line) : IPo
override fun hashCodeRemote(): Int = hashCode()
override fun hashCode(): Int {
return id.hashCode()
}
override fun toString(): String {
return id
}
override fun equals(other: Any?): Boolean {
if (other is PolylineImpl) {
return other.line == line
return other.id == id
}
return false
}

View File

@ -17,30 +17,24 @@
package org.microg.gms.maps.mapbox.utils
import android.os.Bundle
import android.util.Log
import com.google.android.gms.maps.internal.ICancelableCallback
import com.google.android.gms.maps.model.CircleOptions
import com.google.android.gms.maps.model.MarkerOptions
import com.google.android.gms.maps.model.PolylineOptions
import com.mapbox.mapboxsdk.camera.CameraPosition
import com.mapbox.mapboxsdk.geometry.LatLng
import com.mapbox.mapboxsdk.geometry.LatLngBounds
import com.mapbox.mapboxsdk.geometry.VisibleRegion
import com.mapbox.mapboxsdk.maps.MapboxMap
import com.mapbox.mapboxsdk.plugins.annotation.LineOptions
import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions
import com.mapbox.mapboxsdk.style.layers.Property.ICON_ANCHOR_TOP_LEFT
import com.mapbox.mapboxsdk.utils.ColorUtils
import org.microg.gms.kotlin.unwrap
import org.microg.gms.maps.mapbox.model.BitmapDescriptorImpl
import com.google.android.gms.maps.model.CameraPosition as GmsCameraPosition
import com.google.android.gms.maps.model.LatLng as GmsLatLng
import com.google.android.gms.maps.model.LatLngBounds as GmsLatLngBounds
import com.google.android.gms.maps.model.VisibleRegion as GmsVisibleRegion
fun com.google.android.gms.maps.model.LatLng.toMapbox(): LatLng =
fun GmsLatLng.toMapbox(): LatLng =
LatLng(latitude, longitude)
fun com.google.android.gms.maps.model.LatLngBounds.toMapbox(): LatLngBounds =
fun GmsLatLngBounds.toMapbox(): LatLngBounds =
LatLngBounds.from(this.northeast.latitude, this.northeast.longitude, this.southwest.latitude, this.southwest.longitude)
fun com.google.android.gms.maps.model.CameraPosition.toMapbox(): CameraPosition =
fun GmsCameraPosition.toMapbox(): CameraPosition =
CameraPosition.Builder()
.target(target.toMapbox())
.zoom(zoom.toDouble() - 1.0)
@ -60,23 +54,21 @@ fun Bundle.toMapbox(): Bundle {
for (key in newBundle.keySet()) {
val value = newBundle.get(key)
when (value) {
is com.google.android.gms.maps.model.CameraPosition -> newBundle.putParcelable(key, value.toMapbox())
is com.google.android.gms.maps.model.LatLng -> newBundle.putParcelable(key, value.toMapbox())
is com.google.android.gms.maps.model.LatLngBounds -> newBundle.putParcelable(key, value.toMapbox())
is GmsCameraPosition -> newBundle.putParcelable(key, value.toMapbox())
is GmsLatLng -> newBundle.putParcelable(key, value.toMapbox())
is GmsLatLngBounds -> newBundle.putParcelable(key, value.toMapbox())
is Bundle -> newBundle.putBundle(key, value.toMapbox())
}
}
return newBundle
}
fun LatLng.toGms(): com.google.android.gms.maps.model.LatLng =
com.google.android.gms.maps.model.LatLng(latitude, longitude)
fun LatLng.toGms(): GmsLatLng = GmsLatLng(latitude, longitude)
fun LatLngBounds.toGms(): com.google.android.gms.maps.model.LatLngBounds =
com.google.android.gms.maps.model.LatLngBounds(southWest.toGms(), northEast.toGms())
fun LatLngBounds.toGms(): GmsLatLngBounds = GmsLatLngBounds(southWest.toGms(), northEast.toGms())
fun CameraPosition.toGms(): com.google.android.gms.maps.model.CameraPosition =
com.google.android.gms.maps.model.CameraPosition(target.toGms(), zoom.toFloat() + 1.0f, tilt.toFloat(), bearing.toFloat())
fun CameraPosition.toGms(): GmsCameraPosition =
GmsCameraPosition(target.toGms(), zoom.toFloat() + 1.0f, tilt.toFloat(), bearing.toFloat())
fun Bundle.toGms(): Bundle {
val newBundle = Bundle(this)
@ -92,5 +84,5 @@ fun Bundle.toGms(): Bundle {
return newBundle
}
fun VisibleRegion.toGms(): com.google.android.gms.maps.model.VisibleRegion =
com.google.android.gms.maps.model.VisibleRegion(nearLeft.toGms(), nearRight.toGms(), farLeft.toGms(), farRight.toGms(), latLngBounds.toGms())
fun VisibleRegion.toGms(): GmsVisibleRegion =
GmsVisibleRegion(nearLeft.toGms(), nearRight.toGms(), farLeft.toGms(), farRight.toGms(), latLngBounds.toGms())

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 946 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB