Polygon editor demo
This commit is contained in:
parent
5a3a4b059e
commit
6278235b51
38
demo/polygon-editor/build.gradle.kts
Normal file
38
demo/polygon-editor/build.gradle.kts
Normal file
@ -0,0 +1,38 @@
|
||||
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
|
||||
|
||||
plugins {
|
||||
kotlin("multiplatform")
|
||||
id("org.jetbrains.compose")
|
||||
}
|
||||
|
||||
val ktorVersion: String by rootProject.extra
|
||||
|
||||
kotlin {
|
||||
jvm {
|
||||
compilations.all {
|
||||
kotlinOptions.jvmTarget = "11"
|
||||
}
|
||||
withJava()
|
||||
}
|
||||
sourceSets {
|
||||
val jvmMain by getting {
|
||||
dependencies {
|
||||
implementation(projects.mapsKtScheme)
|
||||
implementation(compose.desktop.currentOs)
|
||||
implementation("ch.qos.logback:logback-classic:1.2.11")
|
||||
}
|
||||
}
|
||||
val jvmTest by getting
|
||||
}
|
||||
}
|
||||
|
||||
compose.desktop {
|
||||
application {
|
||||
mainClass = "MainKt"
|
||||
nativeDistributions {
|
||||
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
|
||||
packageName = "polygon-editor-demo"
|
||||
packageVersion = "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
86
demo/polygon-editor/src/jvmMain/kotlin/Main.kt
Normal file
86
demo/polygon-editor/src/jvmMain/kotlin/Main.kt
Normal file
@ -0,0 +1,86 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
import androidx.compose.desktop.ui.tooling.preview.Preview
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.CursorDropdownMenu
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.snapshots.SnapshotStateList
|
||||
import androidx.compose.ui.graphics.PointMode
|
||||
import androidx.compose.ui.input.pointer.isSecondaryPressed
|
||||
import androidx.compose.ui.window.Window
|
||||
import androidx.compose.ui.window.application
|
||||
import center.sciprog.maps.features.*
|
||||
import center.sciprog.maps.scheme.SchemeView
|
||||
import center.sciprog.maps.scheme.XY
|
||||
import center.sciprog.maps.scheme.XYCoordinateSpace
|
||||
import center.sciprog.maps.scheme.XYViewScope
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun App() {
|
||||
MaterialTheme {
|
||||
|
||||
var clickPoint by remember { mutableStateOf<XY?>(null) }
|
||||
|
||||
val myPolygon: SnapshotStateList<XY> = remember { mutableStateListOf<XY>() }
|
||||
|
||||
val featureState: FeatureGroup<XY> = FeatureGroup.remember(XYCoordinateSpace) {
|
||||
points(
|
||||
listOf(XY(0f, 0f), XY(0f, 1f), XY(1f, 1f), XY(1f, 0f), XY(0f, 0f)),
|
||||
pointMode = PointMode.Polygon,
|
||||
id = "frame"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
if(myPolygon.isNotEmpty()) {
|
||||
featureState.group("polygon") {
|
||||
points(
|
||||
myPolygon + myPolygon.first(),
|
||||
pointMode = PointMode.Polygon,
|
||||
)
|
||||
myPolygon.forEachIndexed { index, xy ->
|
||||
circle(xy, id = "point[$index]").draggable { _, to ->
|
||||
myPolygon[index] = to.focus
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val mapState: XYViewScope = XYViewScope.remember(
|
||||
config = ViewConfig<XY>(
|
||||
onClick = { event, point ->
|
||||
if (event.buttons.isSecondaryPressed) {
|
||||
clickPoint = point.focus
|
||||
}
|
||||
}
|
||||
),
|
||||
initialRectangle = featureState.getBoundingBox(1f),
|
||||
)
|
||||
|
||||
CursorDropdownMenu(clickPoint != null, { clickPoint = null }) {
|
||||
clickPoint?.let { point ->
|
||||
Button({
|
||||
myPolygon.add(point)
|
||||
clickPoint = null
|
||||
}) {
|
||||
Text("Create node")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SchemeView(
|
||||
mapState,
|
||||
featureState,
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun main() = application {
|
||||
Window(title = "Polygon editor demo", onCloseRequest = ::exitApplication) {
|
||||
App()
|
||||
}
|
||||
}
|
@ -11,7 +11,6 @@ import androidx.compose.ui.window.application
|
||||
import center.sciprog.maps.features.FeatureGroup
|
||||
import center.sciprog.maps.features.ViewConfig
|
||||
import center.sciprog.maps.features.ViewPoint
|
||||
import center.sciprog.maps.features.computeBoundingBox
|
||||
import center.sciprog.maps.scheme.*
|
||||
import center.sciprog.maps.svg.FeatureStateSnapshot
|
||||
import center.sciprog.maps.svg.exportToSvg
|
||||
@ -29,7 +28,7 @@ fun App() {
|
||||
MaterialTheme {
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
val schemeFeaturesState = FeatureGroup.remember(XYCoordinateSpace) {
|
||||
val schemeFeaturesState: FeatureGroup<XY> = FeatureGroup.remember(XYCoordinateSpace) {
|
||||
background(1600f, 1200f) { painterResource("middle-earth.jpg") }
|
||||
circle(410.52737 to 868.7676).color(Color.Blue)
|
||||
text(410.52737 to 868.7676, "Shire").color(Color.Blue)
|
||||
@ -53,8 +52,7 @@ fun App() {
|
||||
}
|
||||
|
||||
val initialViewPoint: ViewPoint<XY> = remember {
|
||||
schemeFeaturesState.features.computeBoundingBox(XYCoordinateSpace, 1f)?.computeViewPoint()
|
||||
?: XYViewPoint(XY(0f, 0f))
|
||||
schemeFeaturesState.getBoundingBox(1f)?.computeViewPoint() ?: XYViewPoint(XY(0f, 0f))
|
||||
}
|
||||
|
||||
var viewPoint: ViewPoint<XY> by remember { mutableStateOf(initialViewPoint) }
|
||||
|
Before Width: | Height: | Size: 469 KiB After Width: | Height: | Size: 469 KiB |
@ -47,7 +47,7 @@ class XYViewScope(
|
||||
companion object{
|
||||
@Composable
|
||||
public fun remember(
|
||||
config: ViewConfig<XY>,
|
||||
config: ViewConfig<XY> = ViewConfig(),
|
||||
initialViewPoint: ViewPoint<XY>? = null,
|
||||
initialRectangle: Rectangle<XY>? = null,
|
||||
): XYViewScope = remember {
|
||||
|
@ -24,12 +24,12 @@ private val logger = KotlinLogging.logger("SchemeView")
|
||||
public fun SchemeView(
|
||||
state: XYViewScope,
|
||||
featuresState: FeatureGroup<XY>,
|
||||
modifier: Modifier = Modifier.fillMaxSize(),
|
||||
) {
|
||||
modifier: Modifier = Modifier,
|
||||
) = key(state, featuresState) {
|
||||
with(state) {
|
||||
val painterCache: Map<PainterFeature<XY>, Painter> = key(featuresState) {
|
||||
//Can't do that inside canvas
|
||||
val painterCache: Map<PainterFeature<XY>, Painter> =
|
||||
featuresState.features.filterIsInstance<PainterFeature<XY>>().associateWith { it.getPainter() }
|
||||
}
|
||||
|
||||
Canvas(modifier = modifier.mapControls(state, featuresState).fillMaxSize()) {
|
||||
|
||||
@ -41,10 +41,11 @@ public fun SchemeView(
|
||||
clipRect {
|
||||
featuresState.featureMap.values.sortedBy { it.z }
|
||||
.filter { viewPoint.zoom in it.zoomRange }
|
||||
.forEach { background ->
|
||||
drawFeature(state, painterCache, background)
|
||||
.forEach { feature ->
|
||||
drawFeature(state, painterCache, feature)
|
||||
}
|
||||
}
|
||||
|
||||
selectRect?.let { dpRect ->
|
||||
val rect = dpRect.toRect()
|
||||
drawRect(
|
||||
@ -96,7 +97,10 @@ public fun SchemeView(
|
||||
val state = XYViewScope.remember(
|
||||
config,
|
||||
initialViewPoint = initialViewPoint,
|
||||
initialRectangle = initialRectangle ?: featureState.features.computeBoundingBox(XYCoordinateSpace, Float.MAX_VALUE),
|
||||
initialRectangle = initialRectangle ?: featureState.features.computeBoundingBox(
|
||||
XYCoordinateSpace,
|
||||
Float.MAX_VALUE
|
||||
),
|
||||
)
|
||||
|
||||
SchemeView(state, featureState, modifier)
|
||||
@ -121,7 +125,10 @@ public fun SchemeView(
|
||||
val mapState: XYViewScope = XYViewScope.remember(
|
||||
config,
|
||||
initialViewPoint = initialViewPoint,
|
||||
initialRectangle = initialRectangle ?: featureState.features.computeBoundingBox(XYCoordinateSpace, Float.MAX_VALUE),
|
||||
initialRectangle = initialRectangle ?: featureState.features.computeBoundingBox(
|
||||
XYCoordinateSpace,
|
||||
Float.MAX_VALUE
|
||||
),
|
||||
)
|
||||
|
||||
SchemeView(mapState, featureState, modifier)
|
||||
|
@ -49,8 +49,9 @@ include(
|
||||
":maps-kt-geojson",
|
||||
":maps-kt-features",
|
||||
":maps-kt-compose",
|
||||
":demo:maps",
|
||||
":maps-kt-scheme",
|
||||
":demo:scheme"
|
||||
":demo:maps",
|
||||
":demo:scheme",
|
||||
":demo:polygon-editor"
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user