Typed features for Map
This commit is contained in:
parent
5448929d31
commit
edeb422335
@ -15,8 +15,6 @@ import center.sciprog.maps.coordinates.*
|
|||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.engine.cio.CIO
|
import io.ktor.client.engine.cio.CIO
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.isActive
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
@ -45,6 +43,8 @@ fun App() {
|
|||||||
val pointTwo = 55.929444 to 37.518434
|
val pointTwo = 55.929444 to 37.518434
|
||||||
val pointThree = 60.929444 to 37.518434
|
val pointThree = 60.929444 to 37.518434
|
||||||
|
|
||||||
|
val dragPoint = 55.744 to 37.614
|
||||||
|
|
||||||
MapView(
|
MapView(
|
||||||
mapTileProvider = mapTileProvider,
|
mapTileProvider = mapTileProvider,
|
||||||
// initialViewPoint = MapViewPoint(
|
// initialViewPoint = MapViewPoint(
|
||||||
@ -67,8 +67,12 @@ fun App() {
|
|||||||
|
|
||||||
var drag2 = Gmc.ofDegrees(55.8, 37.5)
|
var drag2 = Gmc.ofDegrees(55.8, 37.5)
|
||||||
|
|
||||||
|
var drag3 = Gmc.ofDegrees(56.0, 37.5)
|
||||||
|
|
||||||
fun updateLine() {
|
fun updateLine() {
|
||||||
line(drag1, drag2, id = "connection", color = Color.Magenta)
|
line(drag1, drag2, id = "connection1", color = Color.Magenta)
|
||||||
|
line(drag2, drag3, id = "connection2", color = Color.Magenta)
|
||||||
|
line(drag3, drag1, id = "connection3", color = Color.Magenta)
|
||||||
}
|
}
|
||||||
|
|
||||||
rectangle(drag1, size = DpSize(10.dp, 10.dp)).draggable { _, _, end ->
|
rectangle(drag1, size = DpSize(10.dp, 10.dp)).draggable { _, _, end ->
|
||||||
@ -83,6 +87,13 @@ fun App() {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rectangle(drag3, size = DpSize(10.dp, 10.dp)).draggable { _, _, end ->
|
||||||
|
drag3 = end.focus
|
||||||
|
updateLine()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
updateLine()
|
updateLine()
|
||||||
|
|
||||||
points(
|
points(
|
||||||
@ -98,9 +109,13 @@ fun App() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
//remember feature ID
|
//remember feature ID
|
||||||
val circleId: FeatureId = circle(
|
circle(
|
||||||
centerCoordinates = pointTwo,
|
centerCoordinates = pointTwo,
|
||||||
)
|
).updates(scope) {
|
||||||
|
delay(200)
|
||||||
|
//Overwrite a feature with new color
|
||||||
|
it.copy(color = Color(Random.nextFloat(), Random.nextFloat(), Random.nextFloat()))
|
||||||
|
}
|
||||||
|
|
||||||
draw(position = pointThree) {
|
draw(position = pointThree) {
|
||||||
drawLine(start = Offset(-10f, -10f), end = Offset(10f, 10f), color = Color.Red)
|
drawLine(start = Offset(-10f, -10f), end = Offset(10f, 10f), color = Color.Red)
|
||||||
@ -118,18 +133,6 @@ fun App() {
|
|||||||
text(position = it, it.toShortString(), id = "text", color = Color.Blue)
|
text(position = it, it.toShortString(), id = "text", color = Color.Blue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.launch {
|
|
||||||
while (isActive) {
|
|
||||||
delay(200)
|
|
||||||
//Overwrite a feature with new color
|
|
||||||
circle(
|
|
||||||
pointTwo,
|
|
||||||
id = circleId,
|
|
||||||
color = Color(Random.nextFloat(), Random.nextFloat(), Random.nextFloat())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ public interface DraggableMapFeature : SelectableMapFeature {
|
|||||||
public fun Iterable<MapFeature>.computeBoundingBox(zoom: Double): GmcRectangle? =
|
public fun Iterable<MapFeature>.computeBoundingBox(zoom: Double): GmcRectangle? =
|
||||||
mapNotNull { it.getBoundingBox(zoom) }.wrapAll()
|
mapNotNull { it.getBoundingBox(zoom) }.wrapAll()
|
||||||
|
|
||||||
internal fun Pair<Number, Number>.toCoordinates() =
|
public fun Pair<Number, Number>.toCoordinates() =
|
||||||
GeodeticMapCoordinates.ofDegrees(first.toDouble(), second.toDouble())
|
GeodeticMapCoordinates.ofDegrees(first.toDouble(), second.toDouble())
|
||||||
|
|
||||||
internal val defaultZoomRange = 1..18
|
internal val defaultZoomRange = 1..18
|
||||||
@ -88,7 +88,7 @@ public class MapPointsFeature(
|
|||||||
override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(points.first(), points.last())
|
override fun getBoundingBox(zoom: Double): GmcRectangle = GmcRectangle(points.first(), points.last())
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MapCircleFeature(
|
public data class MapCircleFeature(
|
||||||
public val center: GeodeticMapCoordinates,
|
public val center: GeodeticMapCoordinates,
|
||||||
override val zoomRange: IntRange = defaultZoomRange,
|
override val zoomRange: IntRange = defaultZoomRange,
|
||||||
public val size: Float = 5f,
|
public val size: Float = 5f,
|
||||||
@ -179,7 +179,7 @@ public class MapVectorImageFeature(
|
|||||||
* A group of other features
|
* A group of other features
|
||||||
*/
|
*/
|
||||||
public class MapFeatureGroup(
|
public class MapFeatureGroup(
|
||||||
public val children: Map<FeatureId, MapFeature>,
|
public val children: Map<FeatureId<*>, MapFeature>,
|
||||||
override val zoomRange: IntRange = defaultZoomRange,
|
override val zoomRange: IntRange = defaultZoomRange,
|
||||||
) : MapFeature {
|
) : MapFeature {
|
||||||
override fun getBoundingBox(zoom: Double): GmcRectangle? =
|
override fun getBoundingBox(zoom: Double): GmcRectangle? =
|
||||||
|
@ -11,27 +11,33 @@ import androidx.compose.ui.graphics.vector.ImageVector
|
|||||||
import androidx.compose.ui.unit.DpSize
|
import androidx.compose.ui.unit.DpSize
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import center.sciprog.maps.coordinates.*
|
import center.sciprog.maps.coordinates.*
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.isActive
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
public typealias FeatureId = String
|
@JvmInline
|
||||||
|
public value class FeatureId<out MapFeature>(public val id: String)
|
||||||
|
|
||||||
public object DraggableAttribute : MapFeaturesState.Attribute<DragHandle>
|
public object DraggableAttribute : MapFeaturesState.Attribute<DragHandle>
|
||||||
|
public object SelectableAttribute : MapFeaturesState.Attribute<(FeatureId<*>, SelectableMapFeature) -> Unit>
|
||||||
|
|
||||||
public class MapFeaturesState internal constructor(
|
public class MapFeaturesState internal constructor(
|
||||||
private val features: MutableMap<FeatureId, MapFeature>,
|
private val featureMap: MutableMap<String, MapFeature>,
|
||||||
@PublishedApi internal val attributes: MutableMap<FeatureId, SnapshotStateMap<Attribute<out Any?>, in Any?>>,
|
@PublishedApi internal val attributeMap: MutableMap<String, SnapshotStateMap<Attribute<out Any?>, in Any?>>,
|
||||||
) {
|
) {
|
||||||
public interface Attribute<T>
|
public interface Attribute<T>
|
||||||
|
|
||||||
//TODO use context receiver for that
|
//TODO use context receiver for that
|
||||||
public fun FeatureId.draggable(
|
public fun FeatureId<DraggableMapFeature>.draggable(
|
||||||
//TODO add constraints
|
//TODO add constraints
|
||||||
callback: DragHandle = DragHandle.BYPASS,
|
callback: DragHandle = DragHandle.BYPASS,
|
||||||
) {
|
) {
|
||||||
val handle = DragHandle.withPrimaryButton { event, start, end ->
|
val handle = DragHandle.withPrimaryButton { event, start, end ->
|
||||||
val feature = features[this] as? DraggableMapFeature ?: return@withPrimaryButton true
|
val feature = featureMap[id] as? DraggableMapFeature ?: return@withPrimaryButton true
|
||||||
val boundingBox = feature.getBoundingBox(start.zoom) ?: return@withPrimaryButton true
|
val boundingBox = feature.getBoundingBox(start.zoom) ?: return@withPrimaryButton true
|
||||||
if (start.focus in boundingBox) {
|
if (start.focus in boundingBox) {
|
||||||
addFeature(this, feature.withCoordinates(end.focus))
|
feature(id, feature.withCoordinates(end.focus))
|
||||||
callback.handle(event, start, end)
|
callback.handle(event, start, end)
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@ -41,29 +47,53 @@ public class MapFeaturesState internal constructor(
|
|||||||
setAttribute(this, DraggableAttribute, handle)
|
setAttribute(this, DraggableAttribute, handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
public fun features(): Map<FeatureId, MapFeature> = features
|
* Cyclic update of a feature. Called infinitely until canceled.
|
||||||
|
*/
|
||||||
|
public fun <T : MapFeature> FeatureId<T>.updates(
|
||||||
private fun generateID(feature: MapFeature): FeatureId = "@feature[${feature.hashCode().toUInt()}]"
|
scope: CoroutineScope,
|
||||||
|
update: suspend (T) -> T,
|
||||||
public fun addFeature(id: FeatureId?, feature: MapFeature): FeatureId {
|
): Job = scope.launch {
|
||||||
val safeId = id ?: generateID(feature)
|
while (isActive) {
|
||||||
features[id ?: generateID(feature)] = feature
|
feature(this@updates, update(getFeature(this@updates)))
|
||||||
return safeId
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public fun <T> setAttribute(id: FeatureId, key: Attribute<T>, value: T) {
|
|
||||||
attributes.getOrPut(id) { mutableStateMapOf() }[key] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun removeAttribute(id: FeatureId, key: Attribute<*>) {
|
|
||||||
attributes[id]?.remove(key)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
public fun <T> getAttribute(id: FeatureId, key: Attribute<T>): T? =
|
public fun <T : SelectableMapFeature> FeatureId<T>.selectable(
|
||||||
attributes[id]?.get(key)?.let { it as T }
|
onSelect: (FeatureId<T>, T) -> Unit,
|
||||||
|
) {
|
||||||
|
setAttribute(this, SelectableAttribute) { id, feature -> onSelect(id as FeatureId<T>, feature as T) }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public fun features(): Map<FeatureId<*>, MapFeature> = featureMap.mapKeys { FeatureId<MapFeature>(it.key) }
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
public fun <T : MapFeature> getFeature(id: FeatureId<T>): T = featureMap[id.id] as T
|
||||||
|
|
||||||
|
|
||||||
|
private fun generateID(feature: MapFeature): String = "@feature[${feature.hashCode().toUInt()}]"
|
||||||
|
|
||||||
|
public fun <T : MapFeature> feature(id: String?, feature: T): FeatureId<T> {
|
||||||
|
val safeId = id ?: generateID(feature)
|
||||||
|
featureMap[safeId] = feature
|
||||||
|
return FeatureId(safeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun <T : MapFeature> feature(id: FeatureId<T>?, feature: T): FeatureId<T> = feature(id?.id, feature)
|
||||||
|
|
||||||
|
public fun <T> setAttribute(id: FeatureId<*>, key: Attribute<T>, value: T) {
|
||||||
|
attributeMap.getOrPut(id.id) { mutableStateMapOf() }[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun removeAttribute(id: FeatureId<*>, key: Attribute<*>) {
|
||||||
|
attributeMap[id.id]?.remove(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
public fun <T> getAttribute(id: FeatureId<*>, key: Attribute<T>): T? =
|
||||||
|
attributeMap[id.id]?.get(key)?.let { it as T }
|
||||||
|
|
||||||
// @Suppress("UNCHECKED_CAST")
|
// @Suppress("UNCHECKED_CAST")
|
||||||
// public fun <T> findAllWithAttribute(key: Attribute<T>, condition: (T) -> Boolean): Set<FeatureId> {
|
// public fun <T> findAllWithAttribute(key: Attribute<T>, condition: (T) -> Boolean): Set<FeatureId> {
|
||||||
@ -72,11 +102,14 @@ public class MapFeaturesState internal constructor(
|
|||||||
// }.keys
|
// }.keys
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public inline fun <T> forEachWithAttribute(key: Attribute<T>, block: (id: FeatureId, attributeValue: T) -> Unit) {
|
public inline fun <T> forEachWithAttribute(
|
||||||
attributes.forEach { (id, attributeMap) ->
|
key: Attribute<T>,
|
||||||
|
block: (id: FeatureId<*>, attributeValue: T) -> Unit,
|
||||||
|
) {
|
||||||
|
attributeMap.forEach { (id, attributeMap) ->
|
||||||
attributeMap[key]?.let {
|
attributeMap[key]?.let {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
block(id, it as T)
|
block(FeatureId<MapFeature>(id), it as T)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,8 +144,8 @@ public fun MapFeaturesState.circle(
|
|||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
size: Float = 5f,
|
size: Float = 5f,
|
||||||
color: Color = Color.Red,
|
color: Color = Color.Red,
|
||||||
id: FeatureId? = null,
|
id: String? = null,
|
||||||
): FeatureId = addFeature(
|
): FeatureId<MapCircleFeature> = feature(
|
||||||
id, MapCircleFeature(center, zoomRange, size, color)
|
id, MapCircleFeature(center, zoomRange, size, color)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -121,8 +154,8 @@ public fun MapFeaturesState.circle(
|
|||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
size: Float = 5f,
|
size: Float = 5f,
|
||||||
color: Color = Color.Red,
|
color: Color = Color.Red,
|
||||||
id: FeatureId? = null,
|
id: String? = null,
|
||||||
): FeatureId = addFeature(
|
): FeatureId<MapCircleFeature> = feature(
|
||||||
id, MapCircleFeature(centerCoordinates.toCoordinates(), zoomRange, size, color)
|
id, MapCircleFeature(centerCoordinates.toCoordinates(), zoomRange, size, color)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -131,8 +164,8 @@ public fun MapFeaturesState.rectangle(
|
|||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
size: DpSize = DpSize(5.dp, 5.dp),
|
size: DpSize = DpSize(5.dp, 5.dp),
|
||||||
color: Color = Color.Red,
|
color: Color = Color.Red,
|
||||||
id: FeatureId? = null,
|
id: String? = null,
|
||||||
): FeatureId = addFeature(
|
): FeatureId<MapRectangleFeature> = feature(
|
||||||
id, MapRectangleFeature(centerCoordinates, zoomRange, size, color)
|
id, MapRectangleFeature(centerCoordinates, zoomRange, size, color)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -141,25 +174,25 @@ public fun MapFeaturesState.rectangle(
|
|||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
size: DpSize = DpSize(5.dp, 5.dp),
|
size: DpSize = DpSize(5.dp, 5.dp),
|
||||||
color: Color = Color.Red,
|
color: Color = Color.Red,
|
||||||
id: FeatureId? = null,
|
id: String? = null,
|
||||||
): FeatureId = addFeature(
|
): FeatureId<MapRectangleFeature> = feature(
|
||||||
id, MapRectangleFeature(centerCoordinates.toCoordinates(), zoomRange, size, color)
|
id, MapRectangleFeature(centerCoordinates.toCoordinates(), zoomRange, size, color)
|
||||||
)
|
)
|
||||||
|
|
||||||
public fun MapFeaturesState.draw(
|
public fun MapFeaturesState.draw(
|
||||||
position: Pair<Double, Double>,
|
position: Pair<Double, Double>,
|
||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
id: FeatureId? = null,
|
id: String? = null,
|
||||||
drawFeature: DrawScope.() -> Unit,
|
drawFeature: DrawScope.() -> Unit,
|
||||||
): FeatureId = addFeature(id, MapDrawFeature(position.toCoordinates(), zoomRange, drawFeature))
|
): FeatureId<MapDrawFeature> = feature(id, MapDrawFeature(position.toCoordinates(), zoomRange, drawFeature))
|
||||||
|
|
||||||
public fun MapFeaturesState.line(
|
public fun MapFeaturesState.line(
|
||||||
aCoordinates: Gmc,
|
aCoordinates: Gmc,
|
||||||
bCoordinates: Gmc,
|
bCoordinates: Gmc,
|
||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
color: Color = Color.Red,
|
color: Color = Color.Red,
|
||||||
id: FeatureId? = null,
|
id: String? = null,
|
||||||
): FeatureId = addFeature(
|
): FeatureId<MapLineFeature> = feature(
|
||||||
id,
|
id,
|
||||||
MapLineFeature(aCoordinates, bCoordinates, zoomRange, color)
|
MapLineFeature(aCoordinates, bCoordinates, zoomRange, color)
|
||||||
)
|
)
|
||||||
@ -168,8 +201,8 @@ public fun MapFeaturesState.line(
|
|||||||
curve: GmcCurve,
|
curve: GmcCurve,
|
||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
color: Color = Color.Red,
|
color: Color = Color.Red,
|
||||||
id: FeatureId? = null,
|
id: String? = null,
|
||||||
): FeatureId = addFeature(
|
): FeatureId<MapLineFeature> = feature(
|
||||||
id,
|
id,
|
||||||
MapLineFeature(curve.forward.coordinates, curve.backward.coordinates, zoomRange, color)
|
MapLineFeature(curve.forward.coordinates, curve.backward.coordinates, zoomRange, color)
|
||||||
)
|
)
|
||||||
@ -179,8 +212,8 @@ public fun MapFeaturesState.line(
|
|||||||
bCoordinates: Pair<Double, Double>,
|
bCoordinates: Pair<Double, Double>,
|
||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
color: Color = Color.Red,
|
color: Color = Color.Red,
|
||||||
id: FeatureId? = null,
|
id: String? = null,
|
||||||
): FeatureId = addFeature(
|
): FeatureId<MapLineFeature> = feature(
|
||||||
id,
|
id,
|
||||||
MapLineFeature(aCoordinates.toCoordinates(), bCoordinates.toCoordinates(), zoomRange, color)
|
MapLineFeature(aCoordinates.toCoordinates(), bCoordinates.toCoordinates(), zoomRange, color)
|
||||||
)
|
)
|
||||||
@ -191,8 +224,8 @@ public fun MapFeaturesState.arc(
|
|||||||
arcLength: Angle,
|
arcLength: Angle,
|
||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
color: Color = Color.Red,
|
color: Color = Color.Red,
|
||||||
id: FeatureId? = null,
|
id: String? = null,
|
||||||
): FeatureId = addFeature(
|
): FeatureId<MapArcFeature> = feature(
|
||||||
id,
|
id,
|
||||||
MapArcFeature(oval, startAngle, arcLength, zoomRange, color)
|
MapArcFeature(oval, startAngle, arcLength, zoomRange, color)
|
||||||
)
|
)
|
||||||
@ -204,8 +237,8 @@ public fun MapFeaturesState.arc(
|
|||||||
arcLength: Angle,
|
arcLength: Angle,
|
||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
color: Color = Color.Red,
|
color: Color = Color.Red,
|
||||||
id: FeatureId? = null,
|
id: String? = null,
|
||||||
): FeatureId = addFeature(
|
): FeatureId<MapArcFeature> = feature(
|
||||||
id,
|
id,
|
||||||
MapArcFeature(
|
MapArcFeature(
|
||||||
oval = GmcRectangle.square(center.toCoordinates(), radius, radius),
|
oval = GmcRectangle.square(center.toCoordinates(), radius, radius),
|
||||||
@ -222,8 +255,8 @@ public fun MapFeaturesState.points(
|
|||||||
stroke: Float = 2f,
|
stroke: Float = 2f,
|
||||||
color: Color = Color.Red,
|
color: Color = Color.Red,
|
||||||
pointMode: PointMode = PointMode.Points,
|
pointMode: PointMode = PointMode.Points,
|
||||||
id: FeatureId? = null,
|
id: String? = null,
|
||||||
): FeatureId = addFeature(id, MapPointsFeature(points, zoomRange, stroke, color, pointMode))
|
): FeatureId<MapPointsFeature> = feature(id, MapPointsFeature(points, zoomRange, stroke, color, pointMode))
|
||||||
|
|
||||||
@JvmName("pointsFromPairs")
|
@JvmName("pointsFromPairs")
|
||||||
public fun MapFeaturesState.points(
|
public fun MapFeaturesState.points(
|
||||||
@ -232,28 +265,30 @@ public fun MapFeaturesState.points(
|
|||||||
stroke: Float = 2f,
|
stroke: Float = 2f,
|
||||||
color: Color = Color.Red,
|
color: Color = Color.Red,
|
||||||
pointMode: PointMode = PointMode.Points,
|
pointMode: PointMode = PointMode.Points,
|
||||||
id: FeatureId? = null,
|
id: String? = null,
|
||||||
): FeatureId = addFeature(id, MapPointsFeature(points.map { it.toCoordinates() }, zoomRange, stroke, color, pointMode))
|
): FeatureId<MapPointsFeature> =
|
||||||
|
feature(id, MapPointsFeature(points.map { it.toCoordinates() }, zoomRange, stroke, color, pointMode))
|
||||||
|
|
||||||
public fun MapFeaturesState.image(
|
public fun MapFeaturesState.image(
|
||||||
position: Pair<Double, Double>,
|
position: Pair<Double, Double>,
|
||||||
image: ImageVector,
|
image: ImageVector,
|
||||||
size: DpSize = DpSize(20.dp, 20.dp),
|
size: DpSize = DpSize(20.dp, 20.dp),
|
||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
id: FeatureId? = null,
|
id: String? = null,
|
||||||
): FeatureId = addFeature(id, MapVectorImageFeature(position.toCoordinates(), image, size, zoomRange))
|
): FeatureId<MapVectorImageFeature> =
|
||||||
|
feature(id, MapVectorImageFeature(position.toCoordinates(), image, size, zoomRange))
|
||||||
|
|
||||||
public fun MapFeaturesState.group(
|
public fun MapFeaturesState.group(
|
||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
id: FeatureId? = null,
|
id: String? = null,
|
||||||
builder: MapFeaturesState.() -> Unit,
|
builder: MapFeaturesState.() -> Unit,
|
||||||
): FeatureId {
|
): FeatureId<MapFeatureGroup> {
|
||||||
val map = MapFeaturesState(
|
val map = MapFeaturesState(
|
||||||
mutableStateMapOf(),
|
mutableStateMapOf(),
|
||||||
mutableStateMapOf()
|
mutableStateMapOf()
|
||||||
).apply(builder).features()
|
).apply(builder).features()
|
||||||
val feature = MapFeatureGroup(map, zoomRange)
|
val feature = MapFeatureGroup(map, zoomRange)
|
||||||
return addFeature(id, feature)
|
return feature(id, feature)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun MapFeaturesState.text(
|
public fun MapFeaturesState.text(
|
||||||
@ -262,8 +297,8 @@ public fun MapFeaturesState.text(
|
|||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
color: Color = Color.Red,
|
color: Color = Color.Red,
|
||||||
font: MapTextFeatureFont.() -> Unit = { size = 16f },
|
font: MapTextFeatureFont.() -> Unit = { size = 16f },
|
||||||
id: FeatureId? = null,
|
id: String? = null,
|
||||||
): FeatureId = addFeature(id, MapTextFeature(position, text, zoomRange, color, font))
|
): FeatureId<MapTextFeature> = feature(id, MapTextFeature(position, text, zoomRange, color, font))
|
||||||
|
|
||||||
public fun MapFeaturesState.text(
|
public fun MapFeaturesState.text(
|
||||||
position: Pair<Double, Double>,
|
position: Pair<Double, Double>,
|
||||||
@ -271,5 +306,5 @@ public fun MapFeaturesState.text(
|
|||||||
zoomRange: IntRange = defaultZoomRange,
|
zoomRange: IntRange = defaultZoomRange,
|
||||||
color: Color = Color.Red,
|
color: Color = Color.Red,
|
||||||
font: MapTextFeatureFont.() -> Unit = { size = 16f },
|
font: MapTextFeatureFont.() -> Unit = { size = 16f },
|
||||||
id: FeatureId? = null,
|
id: String? = null,
|
||||||
): FeatureId = addFeature(id, MapTextFeature(position.toCoordinates(), text, zoomRange, color, font))
|
): FeatureId<MapTextFeature> = feature(id, MapTextFeature(position.toCoordinates(), text, zoomRange, color, font))
|
||||||
|
@ -98,13 +98,13 @@ public fun MapView(
|
|||||||
mapTileProvider: MapTileProvider,
|
mapTileProvider: MapTileProvider,
|
||||||
initialViewPoint: MapViewPoint? = null,
|
initialViewPoint: MapViewPoint? = null,
|
||||||
initialRectangle: GmcRectangle? = null,
|
initialRectangle: GmcRectangle? = null,
|
||||||
featureMap: Map<FeatureId, MapFeature>,
|
featureMap: Map<FeatureId<*>, MapFeature>,
|
||||||
config: MapViewConfig = MapViewConfig(),
|
config: MapViewConfig = MapViewConfig(),
|
||||||
modifier: Modifier = Modifier.fillMaxSize(),
|
modifier: Modifier = Modifier.fillMaxSize(),
|
||||||
) {
|
) {
|
||||||
val featuresState = key(featureMap) {
|
val featuresState = key(featureMap) {
|
||||||
MapFeaturesState.build {
|
MapFeaturesState.build {
|
||||||
featureMap.forEach(::addFeature)
|
featureMap.forEach { feature(it.key.id, it.value) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ public fun MapView(
|
|||||||
|
|
||||||
val featureDrag: DragHandle = DragHandle.withPrimaryButton { event, start, end ->
|
val featureDrag: DragHandle = DragHandle.withPrimaryButton { event, start, end ->
|
||||||
featureState.forEachWithAttribute(DraggableAttribute) { _, handle ->
|
featureState.forEachWithAttribute(DraggableAttribute) { _, handle ->
|
||||||
if(!handle.handle(event, start, end)) return@withPrimaryButton false
|
if (!handle.handle(event, start, end)) return@withPrimaryButton false
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user