0.3.0 #23
@ -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 = features.values
|
||||
.filterIsInstance<PainterFeature<T>>()
|
||||
.associateWith { it.getPainter() }
|
||||
|
||||
val painterCache = key(features) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 -> {
|
||||
|
Loading…
Reference in New Issue
Block a user