diff --git a/maps-kt-features/src/commonMain/kotlin/space/kscience/maps/features/FeatureDrawScope.kt b/maps-kt-features/src/commonMain/kotlin/space/kscience/maps/features/FeatureDrawScope.kt index a71d0fa..028fd9f 100644 --- a/maps-kt-features/src/commonMain/kotlin/space/kscience/maps/features/FeatureDrawScope.kt +++ b/maps-kt-features/src/commonMain/kotlin/space/kscience/maps/features/FeatureDrawScope.kt @@ -4,7 +4,6 @@ import androidx.compose.foundation.Canvas import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.key import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color @@ -19,9 +18,13 @@ import androidx.compose.ui.text.drawText import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.unit.DpRect import io.github.oshai.kotlinlogging.KotlinLogging +import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.sample import space.kscience.attributes.Attributes import space.kscience.attributes.plus +import kotlin.time.Duration +import kotlin.time.Duration.Companion.milliseconds /** * An extension of [DrawScope] to include map-specific features @@ -76,22 +79,23 @@ public class ComposeFeatureDrawScope( /** * Create a canvas with extended functionality (e.g., drawing text) */ +@OptIn(FlowPreview::class) @Composable public fun FeatureCanvas( state: CanvasState, featureFlow: StateFlow>>, modifier: Modifier = Modifier, + sampleDuration: Duration = 20.milliseconds, draw: FeatureDrawScope.() -> Unit = {}, ) { val textMeasurer = rememberTextMeasurer(0) - val features by featureFlow.collectAsState() + val features by featureFlow.sample(sampleDuration).collectAsState(featureFlow.value) + + val painterCache = features.values + .filterIsInstance>() + .associateWith { it.getPainter() } - val painterCache = key(features) { - features.values - .filterIsInstance>() - .associateWith { it.getPainter() } - } Canvas(modifier) { if (state.canvasSize != size.toDpSize()) { @@ -102,12 +106,13 @@ public fun FeatureCanvas( val attributesCache = mutableMapOf, Attributes>() - fun computeGroupAttributes(path: List): Attributes = attributesCache.getOrPut(path){ + fun computeGroupAttributes(path: List): Attributes = attributesCache.getOrPut(path) { if (path.isEmpty()) return Attributes.EMPTY else if (path.size == 1) { features[path.first()]?.attributes ?: Attributes.EMPTY } else { - computeGroupAttributes(path.dropLast(1)) + (features[path.first()]?.attributes ?: Attributes.EMPTY) + computeGroupAttributes(path.dropLast(1)) + (features[path.first()]?.attributes + ?: Attributes.EMPTY) } } diff --git a/maps-kt-features/src/commonMain/kotlin/space/kscience/maps/features/FeatureStore.kt b/maps-kt-features/src/commonMain/kotlin/space/kscience/maps/features/FeatureStore.kt index 71aaf4e..b8f4e89 100644 --- a/maps-kt-features/src/commonMain/kotlin/space/kscience/maps/features/FeatureStore.kt +++ b/maps-kt-features/src/commonMain/kotlin/space/kscience/maps/features/FeatureStore.kt @@ -46,10 +46,12 @@ public interface FeatureBuilder { public val space: CoordinateSpace /** - * Add or replace feature. If [id] is null, then a unique id is genertated + * Add or replace feature. If [id] is null, then a unique id is generated */ public fun > feature(id: String?, feature: F): FeatureRef + public fun putFeatures(features: Map?>) + /** * Update existing feature if it is present and is of type [F] */ @@ -89,6 +91,18 @@ public class FeatureStore( return FeatureRef(this, safeId) } + public override fun putFeatures(features: Map?>) { + _featureFlow.value = _featureFlow.value.toMutableMap().apply { + features.forEach { (key, value) -> + if (value == null) { + remove(key) + } else { + put(key, value) + } + } + } + } + @Suppress("UNCHECKED_CAST") override fun > updateFeature(id: String, block: (F?) -> F): FeatureRef = feature(id, block(features[id] as? F)) @@ -159,10 +173,13 @@ public data class FeatureGroup internal constructor( override fun withAttributes(modify: Attributes.() -> Attributes): FeatureGroup = FeatureGroup(store, groupId, modify(attributes)) - override fun > feature(id: String?, feature: F): FeatureRef = store.feature("$groupId/${id ?: generateFeatureId(feature)}", feature) + public override fun putFeatures(features: Map?>) { + store.putFeatures(features.mapKeys { "$groupId/${it.key}" }) + } + override fun > updateFeature(id: String, block: (F?) -> F): FeatureRef = store.updateFeature("$groupId/$id", block) diff --git a/maps-kt-features/src/commonMain/kotlin/space/kscience/maps/features/drawFeature.kt b/maps-kt-features/src/commonMain/kotlin/space/kscience/maps/features/drawFeature.kt index 5b1de31..1c58f01 100644 --- a/maps-kt-features/src/commonMain/kotlin/space/kscience/maps/features/drawFeature.kt +++ b/maps-kt-features/src/commonMain/kotlin/space/kscience/maps/features/drawFeature.kt @@ -98,13 +98,6 @@ public fun FeatureDrawScope.drawFeature( is FeatureGroup -> { //ignore groups -// feature.features.values.forEach { -// drawFeature( -// it.withAttributes { -// feature.attributes + this -// } -// ) -// } } is PathFeature -> {