164 lines
5.2 KiB
Kotlin
Raw Normal View History

2022-07-23 11:24:37 +03:00
package center.sciprog.maps.scheme
2022-07-23 10:27:58 +03:00
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.snapshots.SnapshotStateMap
import androidx.compose.ui.graphics.Color
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.unit.DpSize
import androidx.compose.ui.unit.dp
2022-07-23 11:24:37 +03:00
import center.sciprog.maps.scheme.SchemeFeature.Companion.defaultScaleRange
2022-07-23 10:27:58 +03:00
typealias FeatureId = String
2022-09-17 10:32:28 +03:00
public class SchemeFeaturesState internal constructor(
private val features: MutableMap<FeatureId, SchemeFeature>,
private val attributes: MutableMap<FeatureId, SnapshotStateMap<Attribute<out Any?>, in Any?>>,
) {
public interface Attribute<T>
2022-07-23 10:27:58 +03:00
2022-09-17 10:32:28 +03:00
public fun features(): Map<FeatureId, SchemeFeature> = features
2022-07-23 10:27:58 +03:00
private fun generateID(feature: SchemeFeature): FeatureId = "@feature[${feature.hashCode().toUInt()}]"
2022-09-17 10:32:28 +03:00
public fun addFeature(id: FeatureId?, feature: SchemeFeature): FeatureId {
2022-07-23 10:27:58 +03:00
val safeId = id ?: generateID(feature)
2022-09-17 10:32:28 +03:00
features[id ?: generateID(feature)] = feature
2022-07-23 10:27:58 +03:00
return safeId
}
2022-09-17 10:32:28 +03:00
public fun <T> setAttribute(id: FeatureId, key: Attribute<T>, value: T) {
attributes.getOrPut(id) { mutableStateMapOf() }[key] = value
}
@Suppress("UNCHECKED_CAST")
public fun <T> getAttribute(id: FeatureId, key: Attribute<T>): T? =
attributes[id]?.get(key)?.let { it as T }
@Suppress("UNCHECKED_CAST")
public fun <T> findAllWithAttribute(key: Attribute<T>, condition: (T) -> Boolean): Set<FeatureId> {
return attributes.filterValues {
condition(it[key] as T)
}.keys
}
public companion object {
/**
* Build, but do not remember map feature state
*/
public fun build(
builder: SchemeFeaturesState.() -> Unit = {},
): SchemeFeaturesState = SchemeFeaturesState(
mutableStateMapOf(),
mutableStateMapOf()
).apply(builder)
/**
* Build and remember map feature state
*/
@Composable
public fun remember(
builder: SchemeFeaturesState.() -> Unit = {},
): SchemeFeaturesState = androidx.compose.runtime.remember(builder) {
build(builder)
}
}
2022-07-23 10:27:58 +03:00
}
2022-09-17 10:32:28 +03:00
fun SchemeFeaturesState.background(
box: SchemeRectangle,
2022-07-23 10:27:58 +03:00
id: FeatureId? = null,
2022-09-17 10:32:28 +03:00
painter: @Composable () -> Painter,
2022-07-23 10:27:58 +03:00
): FeatureId = addFeature(
id,
2022-09-17 10:32:28 +03:00
SchemeBackgroundFeature(box, painter = painter)
2022-07-23 10:27:58 +03:00
)
2022-09-17 10:32:28 +03:00
fun SchemeFeaturesState.background(
width: Float,
height: Float,
2022-07-23 10:27:58 +03:00
offset: SchemeCoordinates = SchemeCoordinates(0f, 0f),
id: FeatureId? = null,
2022-09-17 10:32:28 +03:00
painter: @Composable () -> Painter,
2022-07-23 10:27:58 +03:00
): FeatureId {
2022-09-17 10:32:28 +03:00
val box = SchemeRectangle(
2022-07-23 10:27:58 +03:00
offset,
2022-09-17 10:32:28 +03:00
SchemeCoordinates(width + offset.x, height + offset.y)
2022-07-23 10:27:58 +03:00
)
2022-09-17 10:32:28 +03:00
return background(box, id, painter = painter)
2022-07-23 10:27:58 +03:00
}
2022-09-17 10:32:28 +03:00
fun SchemeFeaturesState.circle(
2022-07-23 10:27:58 +03:00
center: SchemeCoordinates,
scaleRange: FloatRange = defaultScaleRange,
size: Float = 5f,
color: Color = Color.Red,
id: FeatureId? = null,
) = addFeature(
id, SchemeCircleFeature(center, scaleRange, size, color)
)
2022-09-17 10:32:28 +03:00
fun SchemeFeaturesState.circle(
2022-07-23 10:27:58 +03:00
centerCoordinates: Pair<Number, Number>,
scaleRange: FloatRange = defaultScaleRange,
size: Float = 5f,
color: Color = Color.Red,
id: FeatureId? = null,
) = addFeature(
id, SchemeCircleFeature(centerCoordinates.toCoordinates(), scaleRange, size, color)
)
2022-09-17 10:32:28 +03:00
fun SchemeFeaturesState.draw(
2022-07-23 10:27:58 +03:00
position: Pair<Number, Number>,
scaleRange: FloatRange = defaultScaleRange,
id: FeatureId? = null,
drawFeature: DrawScope.() -> Unit,
) = addFeature(id, SchemeDrawFeature(position.toCoordinates(), scaleRange, drawFeature))
2022-09-17 10:32:28 +03:00
fun SchemeFeaturesState.line(
2022-07-23 10:27:58 +03:00
aCoordinates: Pair<Number, Number>,
bCoordinates: Pair<Number, Number>,
scaleRange: FloatRange = defaultScaleRange,
color: Color = Color.Red,
id: FeatureId? = null,
) = addFeature(id, SchemeLineFeature(aCoordinates.toCoordinates(), bCoordinates.toCoordinates(), scaleRange, color))
2022-09-17 10:32:28 +03:00
fun SchemeFeaturesState.text(
2022-07-23 10:27:58 +03:00
position: SchemeCoordinates,
text: String,
scaleRange: FloatRange = defaultScaleRange,
color: Color = Color.Red,
id: FeatureId? = null,
) = addFeature(id, SchemeTextFeature(position, text, scaleRange, color))
2022-09-17 10:32:28 +03:00
fun SchemeFeaturesState.text(
2022-07-23 10:27:58 +03:00
position: Pair<Number, Number>,
text: String,
scaleRange: FloatRange = defaultScaleRange,
color: Color = Color.Red,
id: FeatureId? = null,
) = addFeature(id, SchemeTextFeature(position.toCoordinates(), text, scaleRange, color))
2022-09-17 10:32:28 +03:00
fun SchemeFeaturesState.image(
2022-07-23 10:27:58 +03:00
position: Pair<Number, Number>,
image: ImageVector,
size: DpSize = DpSize(20.dp, 20.dp),
scaleRange: FloatRange = defaultScaleRange,
id: FeatureId? = null,
2022-09-17 10:32:28 +03:00
) = addFeature(id, SchemeImageFeature(position.toCoordinates(), image, size, scaleRange))
2022-07-23 10:27:58 +03:00
2022-09-17 10:32:28 +03:00
fun SchemeFeaturesState.group(
2022-07-23 10:27:58 +03:00
scaleRange: FloatRange = defaultScaleRange,
id: FeatureId? = null,
2022-09-17 10:32:28 +03:00
builder: SchemeFeaturesState.() -> Unit,
2022-07-23 10:27:58 +03:00
): FeatureId {
2022-09-17 10:32:28 +03:00
val groupBuilder = SchemeFeaturesState.build(builder)
val feature = SchemeFeatureGroup(groupBuilder.features(), scaleRange)
2022-07-23 10:27:58 +03:00
return addFeature(id, feature)
}