diff --git a/demo/maps/src/jvmMain/kotlin/Main.kt b/demo/maps/src/jvmMain/kotlin/Main.kt index d34bc9b..853c823 100644 --- a/demo/maps/src/jvmMain/kotlin/Main.kt +++ b/demo/maps/src/jvmMain/kotlin/Main.kt @@ -11,6 +11,10 @@ import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Window import androidx.compose.ui.window.application +import center.sciprog.attributes.AlphaAttribute +import center.sciprog.attributes.Attributes +import center.sciprog.attributes.ColorAttribute +import center.sciprog.attributes.ZAttribute import center.sciprog.maps.compose.* import center.sciprog.maps.coordinates.* import center.sciprog.maps.features.* diff --git a/maps-kt-compose/src/commonMain/kotlin/center/sciprog/maps/compose/WebMercatorSpace.kt b/maps-kt-compose/src/commonMain/kotlin/center/sciprog/maps/compose/WebMercatorSpace.kt index 639fc84..b96233f 100644 --- a/maps-kt-compose/src/commonMain/kotlin/center/sciprog/maps/compose/WebMercatorSpace.kt +++ b/maps-kt-compose/src/commonMain/kotlin/center/sciprog/maps/compose/WebMercatorSpace.kt @@ -85,6 +85,7 @@ public object WebMercatorSpace : CoordinateSpace { } override fun Gmc.isInsidePolygon(points: List): Boolean = points.zipWithNext().count { (left, right) -> + //using raytracing algorithm with the ray pointing "up" val longitudeRange = if(right.longitude >= left.longitude) { left.longitude..right.longitude } else { diff --git a/maps-kt-features/src/commonMain/kotlin/center.sciprog.attributes/Attribute.kt b/maps-kt-features/src/commonMain/kotlin/center.sciprog.attributes/Attribute.kt new file mode 100644 index 0000000..23bdd06 --- /dev/null +++ b/maps-kt-features/src/commonMain/kotlin/center.sciprog.attributes/Attribute.kt @@ -0,0 +1,29 @@ +package center.sciprog.attributes + +import androidx.compose.ui.graphics.Color +import center.sciprog.maps.features.DragHandle +import center.sciprog.maps.features.DragListener +import center.sciprog.maps.features.FloatRange +import center.sciprog.maps.features.MouseListener + +public interface Attribute + +public object ZAttribute : Attribute + +public object DraggableAttribute : Attribute> + +public interface SetAttribute : Attribute> + +public object DragListenerAttribute : SetAttribute> + +public object ClickListenerAttribute : SetAttribute> + +public object HoverListenerAttribute : SetAttribute> + +public object VisibleAttribute : Attribute + +public object ColorAttribute : Attribute + +public object ZoomRangeAttribute : Attribute + +public object AlphaAttribute : Attribute diff --git a/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/Attributes.kt b/maps-kt-features/src/commonMain/kotlin/center.sciprog.attributes/Attributes.kt similarity index 50% rename from maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/Attributes.kt rename to maps-kt-features/src/commonMain/kotlin/center.sciprog.attributes/Attributes.kt index 19176e3..8970989 100644 --- a/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/Attributes.kt +++ b/maps-kt-features/src/commonMain/kotlin/center.sciprog.attributes/Attributes.kt @@ -1,6 +1,7 @@ -package center.sciprog.maps.features +package center.sciprog.attributes import androidx.compose.runtime.Stable +import center.sciprog.maps.features.Feature import kotlin.jvm.JvmInline @Stable @@ -9,16 +10,16 @@ public value class Attributes internal constructor(internal val map: Map get(attribute: Attribute): T? = map[attribute] as? T - public operator fun Attribute.invoke(value: T?): Attributes = withAttribute(this, value) +// public operator fun Attribute.invoke(value: T?): Attributes = withAttribute(this, value) - override fun toString(): String = "AttributeMap(value=${map.entries})" + override fun toString(): String = "Attributes(value=${map.entries})" public companion object { public val EMPTY: Attributes = Attributes(emptyMap()) } } -public fun > Attributes.withAttribute( +public fun > Attributes.attribute( attribute: A, attrValue: T?, ): Attributes = Attributes( @@ -29,6 +30,34 @@ public fun > Attributes.withAttribute( } ) +/** + * Add an element to a [SetAttribute] + */ +public fun > Attributes.addValue( + attribute: A, + attrValue: T, +): Attributes { + val currentSet: Set = get(attribute) ?: emptySet() + return Attributes( + map + (attribute to (currentSet + attrValue)) + ) +} + +/** + * Remove an element from [SetAttribute] + */ +public fun > Attributes.removeValue( + attribute: A, + attrValue: T, +): Attributes { + val currentSet: Set = get(attribute) ?: emptySet() + return Attributes( + map + (attribute to (currentSet - attrValue)) + ) +} + + + public fun > Attributes( attribute: A, attrValue: T, diff --git a/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/Attribute.kt b/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/Attribute.kt deleted file mode 100644 index 73f6bdd..0000000 --- a/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/Attribute.kt +++ /dev/null @@ -1,23 +0,0 @@ -package center.sciprog.maps.features - -import androidx.compose.ui.graphics.Color - -public interface Attribute - -public object ZAttribute : Attribute - -public object DraggableAttribute : Attribute> - -public object DragListenerAttribute : Attribute>> - -public object ClickListenerAttribute : Attribute>> - -public object HoverListenerAttribute : Attribute>> - -public object VisibleAttribute : Attribute - -public object ColorAttribute : Attribute - -public object ZoomRangeAttribute : Attribute - -public object AlphaAttribute : Attribute diff --git a/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/Feature.kt b/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/Feature.kt index cc05ef9..7c5c20e 100644 --- a/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/Feature.kt +++ b/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/Feature.kt @@ -14,6 +14,9 @@ import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp +import center.sciprog.attributes.Attributes +import center.sciprog.attributes.ColorAttribute +import center.sciprog.attributes.ZoomRangeAttribute public typealias FloatRange = ClosedFloatingPointRange diff --git a/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/FeatureGroup.kt b/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/FeatureGroup.kt index c6bf469..aaa30cd 100644 --- a/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/FeatureGroup.kt +++ b/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/FeatureGroup.kt @@ -13,6 +13,7 @@ import androidx.compose.ui.input.pointer.PointerEvent import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp +import center.sciprog.attributes.* import kotlin.jvm.JvmInline @JvmInline @@ -64,7 +65,7 @@ public data class FeatureGroup( if (feature is FeatureGroup) { feature.visitUntil(visitor) } else { - if (!visitor(this, key, feature)) return@forEach + if (!visitor(this, key, feature)) return@visitUntil } } } @@ -79,7 +80,15 @@ public data class FeatureGroup( } public fun , V> FeatureId.attribute(key: Attribute, value: V?): FeatureId { - feature(this, get(this).withAttributes { withAttribute(key, value) }) + feature(this, get(this).withAttributes { attribute(key, value) }) + return this + } + + /** + * Add multi-entry [SetAttribute] value + */ + public fun , V> FeatureId.addAttribute(key: SetAttribute, value: V): FeatureId { + feature(this, get(this).withAttributes { addValue(key, value) }) return this } @@ -126,12 +135,9 @@ public data class FeatureGroup( public fun FeatureId>.onDrag( listener: PointerEvent.(from: ViewPoint, to: ViewPoint) -> Unit, ) { - attribute( + addAttribute( DragListenerAttribute, - (getAttribute(this, DragListenerAttribute) ?: emptySet()) + - DragListener { event, from, to -> - event.listener(from as ViewPoint, to as ViewPoint) - } + DragListener { event, from, to -> event.listener(from as ViewPoint, to as ViewPoint) } ) } @@ -139,21 +145,20 @@ public data class FeatureGroup( public fun > FeatureId.onClick( onClick: PointerEvent.(click: ViewPoint) -> Unit, ) { - attribute( + addAttribute( ClickListenerAttribute, - (getAttribute(this, ClickListenerAttribute) ?: emptySet()) + - MouseListener { event, point -> event.onClick(point as ViewPoint) } + MouseListener { event, point -> event.onClick(point as ViewPoint) } ) + } @Suppress("UNCHECKED_CAST") public fun > FeatureId.onHover( onClick: PointerEvent.(move: ViewPoint) -> Unit, ) { - attribute( + addAttribute( HoverListenerAttribute, - (getAttribute(this, HoverListenerAttribute) ?: emptySet()) + - MouseListener { event, point -> event.onClick(point as ViewPoint) } + MouseListener { event, point -> event.onClick(point as ViewPoint) } ) } diff --git a/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/compositeFeatures.kt b/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/compositeFeatures.kt index c39f879..a3143a7 100644 --- a/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/compositeFeatures.kt +++ b/maps-kt-features/src/commonMain/kotlin/center/sciprog/maps/features/compositeFeatures.kt @@ -1,5 +1,9 @@ package center.sciprog.maps.features +import center.sciprog.attributes.Attributes +import center.sciprog.attributes.ZAttribute +import center.sciprog.attributes.attribute + public fun FeatureGroup.draggableLine( aId: FeatureId>, @@ -16,7 +20,7 @@ public fun FeatureGroup.draggableLine( get(bId).center, lineId?.id ?: id ) - if (attributes != null) currentId.modifyAttributes { attributes.withAttribute(ZAttribute, -10f) } + if (attributes != null) currentId.modifyAttributes { attributes.attribute(ZAttribute, -10f) } lineId = currentId return currentId } diff --git a/maps-kt-features/src/jvmMain/kotlin/center/sciprog/maps/compose/mapControls.kt b/maps-kt-features/src/jvmMain/kotlin/center/sciprog/maps/compose/mapControls.kt index 30289c2..3622c22 100644 --- a/maps-kt-features/src/jvmMain/kotlin/center/sciprog/maps/compose/mapControls.kt +++ b/maps-kt-features/src/jvmMain/kotlin/center/sciprog/maps/compose/mapControls.kt @@ -7,6 +7,9 @@ import androidx.compose.ui.input.pointer.* import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.DpRect import androidx.compose.ui.unit.dp +import center.sciprog.attributes.ClickListenerAttribute +import center.sciprog.attributes.DraggableAttribute +import center.sciprog.attributes.HoverListenerAttribute import center.sciprog.maps.features.* import kotlin.math.max import kotlin.math.min @@ -94,9 +97,15 @@ public fun Modifier.mapControls( val dragResult = config.dragHandle?.handle(event, dragStart, dragEnd) if (dragResult?.handleNext == false) return@drag + var continueAfter = true + features.forEachWithAttributeUntil(DraggableAttribute) { _, _, handler -> - handler.handle(event, dragStart, dragEnd).handleNext + handler.handle(event, dragStart, dragEnd).handleNext.also { + if (!it) continueAfter = false + } } + + if (!continueAfter) return@drag } if (event.buttons.isPrimaryPressed) { diff --git a/maps-kt-features/src/jvmMain/kotlin/center/sciprog/maps/features/drawFeature.kt b/maps-kt-features/src/jvmMain/kotlin/center/sciprog/maps/features/drawFeature.kt index 8c4aad8..a1c65ab 100644 --- a/maps-kt-features/src/jvmMain/kotlin/center/sciprog/maps/features/drawFeature.kt +++ b/maps-kt-features/src/jvmMain/kotlin/center/sciprog/maps/features/drawFeature.kt @@ -11,6 +11,8 @@ import androidx.compose.ui.graphics.drawscope.translate import androidx.compose.ui.graphics.nativeCanvas import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.toArgb +import center.sciprog.attributes.AlphaAttribute +import center.sciprog.attributes.plus import org.jetbrains.skia.Font import org.jetbrains.skia.Paint import kotlin.math.PI diff --git a/maps-kt-scheme/src/commonMain/kotlin/center/sciprog/maps/scheme/schemeFeatures.kt b/maps-kt-scheme/src/commonMain/kotlin/center/sciprog/maps/scheme/schemeFeatures.kt index 5f6ae37..33acdf0 100644 --- a/maps-kt-scheme/src/commonMain/kotlin/center/sciprog/maps/scheme/schemeFeatures.kt +++ b/maps-kt-scheme/src/commonMain/kotlin/center/sciprog/maps/scheme/schemeFeatures.kt @@ -8,6 +8,8 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp +import center.sciprog.attributes.Attributes +import center.sciprog.attributes.ZAttribute import center.sciprog.maps.features.* internal fun Pair.toCoordinates(): XY = XY(first.toFloat(), second.toFloat())