Optimize attributes working

This commit is contained in:
Alexander Nozik 2023-01-05 12:15:52 +03:00
parent ea8c5571bb
commit cb160110e7
11 changed files with 107 additions and 42 deletions

View File

@ -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.*

View File

@ -85,6 +85,7 @@ public object WebMercatorSpace : CoordinateSpace<Gmc> {
}
override fun Gmc.isInsidePolygon(points: List<Gmc>): 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 {

View File

@ -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<T>
public object ZAttribute : Attribute<Float>
public object DraggableAttribute : Attribute<DragHandle<Any>>
public interface SetAttribute<V> : Attribute<Set<V>>
public object DragListenerAttribute : SetAttribute<DragListener<Any>>
public object ClickListenerAttribute : SetAttribute<MouseListener<Any>>
public object HoverListenerAttribute : SetAttribute<MouseListener<Any>>
public object VisibleAttribute : Attribute<Boolean>
public object ColorAttribute : Attribute<Color>
public object ZoomRangeAttribute : Attribute<FloatRange>
public object AlphaAttribute : Attribute<Float>

View File

@ -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<Attribu
@Suppress("UNCHECKED_CAST")
public operator fun <T> get(attribute: Attribute<T>): T? = map[attribute] as? T
public operator fun <T> Attribute<T>.invoke(value: T?): Attributes = withAttribute(this, value)
// public operator fun <T> Attribute<T>.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 <T, A : Attribute<T>> Attributes.withAttribute(
public fun <T, A : Attribute<T>> Attributes.attribute(
attribute: A,
attrValue: T?,
): Attributes = Attributes(
@ -29,6 +30,34 @@ public fun <T, A : Attribute<T>> Attributes.withAttribute(
}
)
/**
* Add an element to a [SetAttribute]
*/
public fun <T, A : SetAttribute<T>> Attributes.addValue(
attribute: A,
attrValue: T,
): Attributes {
val currentSet: Set<T> = get(attribute) ?: emptySet()
return Attributes(
map + (attribute to (currentSet + attrValue))
)
}
/**
* Remove an element from [SetAttribute]
*/
public fun <T, A : SetAttribute<T>> Attributes.removeValue(
attribute: A,
attrValue: T,
): Attributes {
val currentSet: Set<T> = get(attribute) ?: emptySet()
return Attributes(
map + (attribute to (currentSet - attrValue))
)
}
public fun <T : Any, A : Attribute<T>> Attributes(
attribute: A,
attrValue: T,

View File

@ -1,23 +0,0 @@
package center.sciprog.maps.features
import androidx.compose.ui.graphics.Color
public interface Attribute<T>
public object ZAttribute : Attribute<Float>
public object DraggableAttribute : Attribute<DragHandle<Any>>
public object DragListenerAttribute : Attribute<Set<DragListener<Any>>>
public object ClickListenerAttribute : Attribute<Set<MouseListener<Any>>>
public object HoverListenerAttribute : Attribute<Set<MouseListener<Any>>>
public object VisibleAttribute : Attribute<Boolean>
public object ColorAttribute : Attribute<Color>
public object ZoomRangeAttribute : Attribute<FloatRange>
public object AlphaAttribute : Attribute<Float>

View File

@ -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<Float>

View File

@ -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<T : Any>(
if (feature is FeatureGroup<T>) {
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<T : Any>(
}
public fun <F : Feature<T>, V> FeatureId<F>.attribute(key: Attribute<V>, value: V?): FeatureId<F> {
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 <F : Feature<T>, V> FeatureId<F>.addAttribute(key: SetAttribute<V>, value: V): FeatureId<F> {
feature(this, get(this).withAttributes { addValue(key, value) })
return this
}
@ -126,12 +135,9 @@ public data class FeatureGroup<T : Any>(
public fun FeatureId<DraggableFeature<T>>.onDrag(
listener: PointerEvent.(from: ViewPoint<T>, to: ViewPoint<T>) -> Unit,
) {
attribute(
addAttribute(
DragListenerAttribute,
(getAttribute(this, DragListenerAttribute) ?: emptySet()) +
DragListener { event, from, to ->
event.listener(from as ViewPoint<T>, to as ViewPoint<T>)
}
DragListener { event, from, to -> event.listener(from as ViewPoint<T>, to as ViewPoint<T>) }
)
}
@ -139,21 +145,20 @@ public data class FeatureGroup<T : Any>(
public fun <F : DomainFeature<T>> FeatureId<F>.onClick(
onClick: PointerEvent.(click: ViewPoint<T>) -> Unit,
) {
attribute(
addAttribute(
ClickListenerAttribute,
(getAttribute(this, ClickListenerAttribute) ?: emptySet()) +
MouseListener { event, point -> event.onClick(point as ViewPoint<T>) }
MouseListener { event, point -> event.onClick(point as ViewPoint<T>) }
)
}
@Suppress("UNCHECKED_CAST")
public fun <F : DomainFeature<T>> FeatureId<F>.onHover(
onClick: PointerEvent.(move: ViewPoint<T>) -> Unit,
) {
attribute(
addAttribute(
HoverListenerAttribute,
(getAttribute(this, HoverListenerAttribute) ?: emptySet()) +
MouseListener { event, point -> event.onClick(point as ViewPoint<T>) }
MouseListener { event, point -> event.onClick(point as ViewPoint<T>) }
)
}

View File

@ -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 <T : Any> FeatureGroup<T>.draggableLine(
aId: FeatureId<MarkerFeature<T>>,
@ -16,7 +20,7 @@ public fun <T : Any> FeatureGroup<T>.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
}

View File

@ -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 <T : Any> 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) {

View File

@ -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

View File

@ -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<Number, Number>.toCoordinates(): XY = XY(first.toFloat(), second.toFloat())