From b520d2f93a907172d4eecf8f8d01b570ac422ef2 Mon Sep 17 00:00:00 2001 From: "a.kalmakhanov" Date: Sat, 16 Jul 2022 14:58:56 +0600 Subject: [PATCH] Added function to draw custom markers with Kotlin DSL Canvas API. FeatureId can be extended to hold info about a feature??? I added unused onFeatureClick, which can be latter implemented with pointer input, where it will check coordinates with offset? Features need to hold info about their coordinates? --- .../sciprog/maps/compose/FeatureBuilder.kt | 20 ++++++++++++++++++- .../centre/sciprog/maps/compose/MapFeature.kt | 11 +++++++++- .../centre/sciprog/maps/compose/MapView.kt | 7 +++++-- src/jvmMain/kotlin/Main.kt | 17 +++++++++++++--- .../centre/sciprog/maps/compose/MapViewJvm.kt | 6 +++++- 5 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/commonMain/kotlin/centre/sciprog/maps/compose/FeatureBuilder.kt b/src/commonMain/kotlin/centre/sciprog/maps/compose/FeatureBuilder.kt index 040a110..9a7e38f 100644 --- a/src/commonMain/kotlin/centre/sciprog/maps/compose/FeatureBuilder.kt +++ b/src/commonMain/kotlin/centre/sciprog/maps/compose/FeatureBuilder.kt @@ -3,9 +3,12 @@ package centre.sciprog.maps.compose import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateMapOf import androidx.compose.runtime.snapshots.SnapshotStateMap +import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.vector.ImageVector +import centre.sciprog.maps.GmcBox typealias FeatureId = String @@ -15,7 +18,7 @@ interface FeatureBuilder { fun build(): SnapshotStateMap } -internal class MapFeatureBuilder(initialFeatures: Map) : FeatureBuilder { +internal class MapFeatureBuilder(initialFeatures: Map) : FeatureBuilder { private val content: SnapshotStateMap = mutableStateMapOf().apply { putAll(initialFeatures) @@ -41,6 +44,21 @@ fun FeatureBuilder.circle( id, MapCircleFeature(centerCoordinates.toCoordinates(), zoomRange, size, color) ) +fun FeatureBuilder.custom( + position: Pair, + id: FeatureId? = null, + customFeatureBuilder: DrawScope.(Offset) -> Unit, +) = addFeature(id, object : MapCustomFeature(position = position.toCoordinates()) { + override fun drawFeature(drawScope: DrawScope, offset: Offset) { + customFeatureBuilder(drawScope, offset) + } + + override fun getBoundingBox(zoom: Int): GmcBox { + return GmcBox(position.toCoordinates(), position.toCoordinates()) + } + +}) + fun FeatureBuilder.line( aCoordinates: Pair, bCoordinates: Pair, diff --git a/src/commonMain/kotlin/centre/sciprog/maps/compose/MapFeature.kt b/src/commonMain/kotlin/centre/sciprog/maps/compose/MapFeature.kt index 700e7aa..8b7defb 100644 --- a/src/commonMain/kotlin/centre/sciprog/maps/compose/MapFeature.kt +++ b/src/commonMain/kotlin/centre/sciprog/maps/compose/MapFeature.kt @@ -1,9 +1,11 @@ package centre.sciprog.maps.compose import androidx.compose.runtime.Composable +import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.rememberVectorPainter @@ -31,6 +33,13 @@ class MapFeatureSelector(val selector: (zoom: Int) -> MapFeature) : MapFeature(d } +abstract class MapCustomFeature( + zoomRange: IntRange = defaultZoomRange, + val position: GeodeticMapCoordinates +) : MapFeature(zoomRange) { + abstract fun drawFeature(drawScope: DrawScope, offset: Offset) +} + class MapCircleFeature( val center: GeodeticMapCoordinates, zoomRange: IntRange = defaultZoomRange, @@ -68,7 +77,7 @@ class MapBitmapImageFeature( } -class MapVectorImageFeature ( +class MapVectorImageFeature( val position: GeodeticMapCoordinates, val painter: Painter, val size: Size, diff --git a/src/commonMain/kotlin/centre/sciprog/maps/compose/MapView.kt b/src/commonMain/kotlin/centre/sciprog/maps/compose/MapView.kt index ebd8483..8cc99ce 100644 --- a/src/commonMain/kotlin/centre/sciprog/maps/compose/MapView.kt +++ b/src/commonMain/kotlin/centre/sciprog/maps/compose/MapView.kt @@ -21,6 +21,7 @@ expect fun MapView( computeViewPoint: (canvasSize: DpSize) -> MapViewPoint, features: Map, onClick: MapViewPoint.() -> Unit = {}, + onFeatureClick: (FeatureId) -> Unit = {}, //TODO consider replacing by modifier config: MapViewConfig = MapViewConfig(), modifier: Modifier = Modifier.fillMaxSize(), @@ -32,13 +33,14 @@ fun MapView( initialViewPoint: MapViewPoint, features: Map = emptyMap(), onClick: MapViewPoint.() -> Unit = {}, + onFeatureClick: (FeatureId) -> Unit = {}, config: MapViewConfig = MapViewConfig(), modifier: Modifier = Modifier.fillMaxSize(), buildFeatures: @Composable (FeatureBuilder.() -> Unit) = {}, ) { val featuresBuilder = MapFeatureBuilder(features) featuresBuilder.buildFeatures() - MapView(mapTileProvider, { initialViewPoint }, featuresBuilder.build(), onClick, config, modifier) + MapView(mapTileProvider, { initialViewPoint }, featuresBuilder.build(), onClick, onFeatureClick, config, modifier) } @Composable @@ -47,6 +49,7 @@ fun MapView( box: GmcBox, features: Map = emptyMap(), onClick: MapViewPoint.() -> Unit = {}, + onFeatureClick: (FeatureId) -> Unit = {}, config: MapViewConfig = MapViewConfig(), modifier: Modifier = Modifier.fillMaxSize(), buildFeatures: @Composable (FeatureBuilder.() -> Unit) = {}, @@ -62,5 +65,5 @@ fun MapView( ) MapViewPoint(box.center, zoom) } - MapView(mapTileProvider, computeViewPoint, featuresBuilder.build(), onClick, config, modifier) + MapView(mapTileProvider, computeViewPoint, featuresBuilder.build(), onClick, onFeatureClick, config, modifier) } \ No newline at end of file diff --git a/src/jvmMain/kotlin/Main.kt b/src/jvmMain/kotlin/Main.kt index 7112b15..37efda6 100644 --- a/src/jvmMain/kotlin/Main.kt +++ b/src/jvmMain/kotlin/Main.kt @@ -6,14 +6,15 @@ import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Home import androidx.compose.runtime.* +import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color import androidx.compose.ui.window.Window import androidx.compose.ui.window.application import centre.sciprog.maps.GeodeticMapCoordinates import centre.sciprog.maps.MapViewPoint import centre.sciprog.maps.compose.* -import io.ktor.client.HttpClient -import io.ktor.client.engine.cio.CIO +import io.ktor.client.* +import io.ktor.client.engine.cio.* import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import kotlinx.coroutines.launch @@ -44,15 +45,25 @@ fun App() { mapTileProvider, viewPoint, onClick = { coordinates = focus }, + onFeatureClick = { + + }, config = MapViewConfig(inferViewBoxFromFeatures = true) ) { val pointOne = 55.568548 to 37.568604 val pointTwo = 55.929444 to 37.518434 + val pointThree = 60.929444 to 37.518434 image(pointOne, Icons.Filled.Home) //remember feature Id - val circleId: FeatureId = circle(pointTwo) + val circleId: FeatureId = custom(position = pointThree) { + drawRect( + color = Color.Red, + topLeft = it, + size = Size(20f, 20f) + ) + } line(pointOne, pointTwo) text(pointOne, "Home") diff --git a/src/jvmMain/kotlin/centre/sciprog/maps/compose/MapViewJvm.kt b/src/jvmMain/kotlin/centre/sciprog/maps/compose/MapViewJvm.kt index 910fd44..b3efd11 100644 --- a/src/jvmMain/kotlin/centre/sciprog/maps/compose/MapViewJvm.kt +++ b/src/jvmMain/kotlin/centre/sciprog/maps/compose/MapViewJvm.kt @@ -41,6 +41,7 @@ actual fun MapView( computeViewPoint: (canvasSize: DpSize) -> MapViewPoint, features: Map, onClick: MapViewPoint.() -> Unit, + onFeatureClick: (FeatureId) -> Unit, config: MapViewConfig, modifier: Modifier, ) { @@ -219,7 +220,10 @@ actual fun MapView( feature.color.toPaint() ) } - + is MapCustomFeature -> drawIntoCanvas { canvas -> + val offset = feature.position.toOffset() + feature.drawFeature(this, offset) + } } }