immutable_features #24

Merged
altavir merged 7 commits from immutable_features into dev 2024-07-08 11:56:05 +03:00
3 changed files with 33 additions and 18 deletions
Showing only changes of commit 3a4c9133c6 - Show all commits

View File

@ -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<T : Any>(
/**
* Create a canvas with extended functionality (e.g., drawing text)
*/
@OptIn(FlowPreview::class)
@Composable
public fun <T : Any> FeatureCanvas(
state: CanvasState<T>,
featureFlow: StateFlow<Map<String, Feature<T>>>,
modifier: Modifier = Modifier,
sampleDuration: Duration = 20.milliseconds,
draw: FeatureDrawScope<T>.() -> Unit = {},
) {
val textMeasurer = rememberTextMeasurer(0)
val features by featureFlow.collectAsState()
val features by featureFlow.sample(sampleDuration).collectAsState(featureFlow.value)
val painterCache = key(features) {
features.values
val painterCache = features.values
.filterIsInstance<PainterFeature<T>>()
.associateWith { it.getPainter() }
}
Canvas(modifier) {
if (state.canvasSize != size.toDpSize()) {
@ -102,12 +106,13 @@ public fun <T : Any> FeatureCanvas(
val attributesCache = mutableMapOf<List<String>, Attributes>()
fun computeGroupAttributes(path: List<String>): Attributes = attributesCache.getOrPut(path){
fun computeGroupAttributes(path: List<String>): 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)
}
}

View File

@ -46,10 +46,12 @@ public interface FeatureBuilder<T : Any> {
public val space: CoordinateSpace<T>
/**
* 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 <F : Feature<T>> feature(id: String?, feature: F): FeatureRef<T, F>
public fun putFeatures(features: Map<String, Feature<T>?>)
/**
* Update existing feature if it is present and is of type [F]
*/
@ -89,6 +91,18 @@ public class FeatureStore<T : Any>(
return FeatureRef(this, safeId)
}
public override fun putFeatures(features: Map<String, Feature<T>?>) {
_featureFlow.value = _featureFlow.value.toMutableMap().apply {
features.forEach { (key, value) ->
if (value == null) {
remove(key)
} else {
put(key, value)
}
}
}
}
@Suppress("UNCHECKED_CAST")
override fun <F : Feature<T>> updateFeature(id: String, block: (F?) -> F): FeatureRef<T, F> =
feature(id, block(features[id] as? F))
@ -159,10 +173,13 @@ public data class FeatureGroup<T : Any> internal constructor(
override fun withAttributes(modify: Attributes.() -> Attributes): FeatureGroup<T> =
FeatureGroup(store, groupId, modify(attributes))
override fun <F : Feature<T>> feature(id: String?, feature: F): FeatureRef<T, F> =
store.feature("$groupId/${id ?: generateFeatureId(feature)}", feature)
public override fun putFeatures(features: Map<String, Feature<T>?>) {
store.putFeatures(features.mapKeys { "$groupId/${it.key}" })
}
override fun <F : Feature<T>> updateFeature(id: String, block: (F?) -> F): FeatureRef<T, F> =
store.updateFeature("$groupId/$id", block)

View File

@ -98,13 +98,6 @@ public fun <T : Any> FeatureDrawScope<T>.drawFeature(
is FeatureGroup -> {
//ignore groups
// feature.features.values.forEach {
// drawFeature(
// it.withAttributes {
// feature.attributes + this
// }
// )
// }
}
is PathFeature -> {