From 53f01ecc3407a1e8b0a5bc7ec5947988e380f5e2 Mon Sep 17 00:00:00 2001 From: lsagona Date: Fri, 17 Jul 2020 16:14:49 +0200 Subject: [PATCH] display message on map --- .../application/controller/MapPanelController.kt | 42 +++++++ .../application/controller/MenuBarController.kt | 3 - .../kotlin/application/model/ObservableVessel.kt | 1 + src/main/kotlin/application/model/Vessel.kt | 5 +- .../kotlin/application/model/VesselGenerator.kt | 6 +- src/main/kotlin/map/Circle.kt | 2 +- src/main/kotlin/map/CircleMarkerGenerator.kt | 15 +++ src/main/kotlin/map/ColorMarker.kt | 2 +- src/main/kotlin/map/ControlPosition.kt | 2 +- src/main/kotlin/map/LatLong.kt | 2 +- src/main/kotlin/map/LeafletMapView.kt | 132 +++++++++++--------- src/main/kotlin/map/MapConfig.kt | 2 +- src/main/kotlin/map/MapLayer.kt | 2 +- src/main/kotlin/map/Marker.kt | 29 +++-- src/main/kotlin/map/ScaleControlConfig.kt | 9 +- src/main/kotlin/map/Zone.kt | 5 +- src/main/kotlin/map/ZoomControlConfig.kt | 7 +- src/main/kotlin/map/events/MapClickEvent.kt | 4 +- src/main/kotlin/map/events/MapMoveEvent.kt | 4 +- src/main/kotlin/map/events/MarkerClickEvent.kt | 2 +- src/main/resources/gui/mapPanel.fxml | 8 ++ src/main/resources/gui/windows.fxml | 7 +- 22 files changed, 191 insertions(+), 100 deletions(-) create mode 100644 src/main/kotlin/application/controller/MapPanelController.kt create mode 100644 src/main/kotlin/map/CircleMarkerGenerator.kt create mode 100644 src/main/resources/gui/mapPanel.fxml diff --git a/src/main/kotlin/application/controller/MapPanelController.kt b/src/main/kotlin/application/controller/MapPanelController.kt new file mode 100644 index 0000000..742802a --- /dev/null +++ b/src/main/kotlin/application/controller/MapPanelController.kt @@ -0,0 +1,42 @@ +package application.controller + +import application.model.MessageListener +import application.model.Vessel +import application.model.observableMessages +import javafx.concurrent.Worker +import javafx.fxml.FXML +import javafx.fxml.Initializable +import javafx.scene.layout.StackPane +import map.LeafletMapView +import map.MapConfig +import map.displayMessageOnMap +import java.net.URL +import java.util.* +import java.util.concurrent.CompletableFuture + +class MapPanelController : Initializable, MessageListener { + + @FXML + private lateinit var map: StackPane + + private val mapView = LeafletMapView() + + + override fun initialize(location: URL?, resources: ResourceBundle?) { + val completeFutureMap: CompletableFuture = mapView.displayMap(MapConfig()) + observableMessages.listeners.add(this) + + /*completeFutureMap.whenComplete{ + workerState, _ -> + if (workerState == Worker.State.SUCCEEDED) { + } + }*/ + map.children.add(mapView) + } + + override fun onValueChanged(newValue: MutableMap) { + displayMessageOnMap(mapView) + } + + +} \ No newline at end of file diff --git a/src/main/kotlin/application/controller/MenuBarController.kt b/src/main/kotlin/application/controller/MenuBarController.kt index 9ac032e..6c0d69f 100644 --- a/src/main/kotlin/application/controller/MenuBarController.kt +++ b/src/main/kotlin/application/controller/MenuBarController.kt @@ -1,13 +1,10 @@ package application.controller -import application.App import application.model.createVesselCollection import application.model.observableMessages import javafx.event.EventHandler import javafx.fxml.FXML -import javafx.fxml.FXMLLoader import javafx.fxml.Initializable -import javafx.scene.Parent import javafx.scene.control.MenuBar import javafx.scene.control.MenuItem import javafx.stage.FileChooser diff --git a/src/main/kotlin/application/model/ObservableVessel.kt b/src/main/kotlin/application/model/ObservableVessel.kt index 6116dad..41881a3 100644 --- a/src/main/kotlin/application/model/ObservableVessel.kt +++ b/src/main/kotlin/application/model/ObservableVessel.kt @@ -1,5 +1,6 @@ package application.model +import java.util.* import kotlin.properties.Delegates class ObservableVessel { diff --git a/src/main/kotlin/application/model/Vessel.kt b/src/main/kotlin/application/model/Vessel.kt index 319c3d9..bdd5764 100644 --- a/src/main/kotlin/application/model/Vessel.kt +++ b/src/main/kotlin/application/model/Vessel.kt @@ -1,8 +1,9 @@ package application.model import java.time.LocalDateTime +import java.util.* -class Vessel() { - val messages: MutableMap = mutableMapOf() +class Vessel { + val messages: SortedMap = sortedMapOf() } \ No newline at end of file diff --git a/src/main/kotlin/application/model/VesselGenerator.kt b/src/main/kotlin/application/model/VesselGenerator.kt index fe986bd..9b40dbf 100644 --- a/src/main/kotlin/application/model/VesselGenerator.kt +++ b/src/main/kotlin/application/model/VesselGenerator.kt @@ -1,10 +1,12 @@ package application.model import java.io.File +import java.util.* +import kotlin.collections.ArrayList -fun createVesselCollection(file: File) : MutableMap { +fun createVesselCollection(file: File) : SortedMap { val messages : ArrayList = arrayListOf() - val vessels: MutableMap = mutableMapOf() + val vessels: SortedMap = sortedMapOf() file.forEachLine { val arrayMessage = it.split(",") diff --git a/src/main/kotlin/map/Circle.kt b/src/main/kotlin/map/Circle.kt index cceb0d7..95ffad6 100644 --- a/src/main/kotlin/map/Circle.kt +++ b/src/main/kotlin/map/Circle.kt @@ -1,4 +1,4 @@ -package fdit.leafletmap +package map import javafx.scene.paint.Color diff --git a/src/main/kotlin/map/CircleMarkerGenerator.kt b/src/main/kotlin/map/CircleMarkerGenerator.kt new file mode 100644 index 0000000..c08da33 --- /dev/null +++ b/src/main/kotlin/map/CircleMarkerGenerator.kt @@ -0,0 +1,15 @@ +package map + +import application.model.observableMessages + +fun clearMap(map: LeafletMapView) { + map.clearAllLayer() +} + +fun displayMessageOnMap(map: LeafletMapView) { + observableMessages.vessels.forEach { (_, value) -> + value.messages.forEach { (_, message) -> + map.execScript("L.circleMarker([${message.latitude}, ${message.longitude}], {renderer: myRenderer, radius: 0.01}).addTo(myMap)") + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/map/ColorMarker.kt b/src/main/kotlin/map/ColorMarker.kt index e80cec8..6d32a4a 100644 --- a/src/main/kotlin/map/ColorMarker.kt +++ b/src/main/kotlin/map/ColorMarker.kt @@ -1,4 +1,4 @@ -package fdit.leafletmap +package map /** * Enumeration for all marker colors of the leaflet-color-markers JavaScript library. diff --git a/src/main/kotlin/map/ControlPosition.kt b/src/main/kotlin/map/ControlPosition.kt index f87c6d3..acc3f04 100644 --- a/src/main/kotlin/map/ControlPosition.kt +++ b/src/main/kotlin/map/ControlPosition.kt @@ -1,4 +1,4 @@ -package fdit.leafletmap +package map /** * Enumeration for all possible map control positions. diff --git a/src/main/kotlin/map/LatLong.kt b/src/main/kotlin/map/LatLong.kt index 3c6b42b..a445109 100644 --- a/src/main/kotlin/map/LatLong.kt +++ b/src/main/kotlin/map/LatLong.kt @@ -1,4 +1,4 @@ -package fdit.leafletmap +package map /** * Immutable value class for defining a geo position. diff --git a/src/main/kotlin/map/LeafletMapView.kt b/src/main/kotlin/map/LeafletMapView.kt index 8197c42..1228dc0 100644 --- a/src/main/kotlin/map/LeafletMapView.kt +++ b/src/main/kotlin/map/LeafletMapView.kt @@ -1,16 +1,12 @@ -package fdit.leafletmap +package map -import fdit.leafletmap.events.* -import fdit.leafletmap.events.MapClickEventMaker -import fdit.leafletmap.events.MapMoveEventMaker -import fdit.leafletmap.events.MarkerClickEventMaker import javafx.concurrent.Worker import javafx.scene.layout.StackPane import javafx.scene.paint.Color import javafx.scene.shape.Polygon import javafx.scene.web.WebEngine import javafx.scene.web.WebView -import fdit.leafletmap.events.* +import map.events.* import netscape.javascript.JSObject import java.io.ByteArrayOutputStream import java.io.File @@ -83,50 +79,51 @@ class LeafletMapView : StackPane() { } val jsLayers = mapConfig.layers - .mapIndexed { i, layer -> "'${layer.displayName}': layer${i + 1}" } - .joinToString(", ") + .mapIndexed { i, layer -> "'${layer.displayName}': layer${i + 1}" } + .joinToString(", ") execScript("var baseMaps = { $jsLayers };") // execute script for map view creation (Leaflet attribution must not be a clickable link) - execScript(""" + execScript( + """ |var myMap = L.map('map', { | center: new L.LatLng(${mapConfig.initialCenter.latitude}, ${mapConfig.initialCenter.longitude}), | zoom: 5, | zoomControl: false, | layers: [layer1] |}); - | - |var markersGroup = L.featureGroup(); - |myMap.addLayer(markersGroup); - |var trackGroup = L.featureGroup(); - |myMap.addLayer(trackGroup); - | - |myMap.addEventListener("contextmenu", function(e){}); - |var attribution = myMap.attributionControl; - |attribution.setPrefix('Leaflet');""".trimMargin()) - - eventZoomChangeIcon() + |L.control.scale().addTo(mymap); + |var myRenderer = L.canvas({ padding: 0.5 });""".trimMargin() + ) + +// eventZoomChangeIcon() // execute script for layer control definition if there are multiple layers if (mapConfig.layers.size > 1) { - execScript(""" + execScript( + """ |var overlayMaps = {}; - |L.control.layers(baseMaps, overlayMaps).addTo(myMap);""".trimMargin()) + |L.control.layers(baseMaps, overlayMaps).addTo(myMap);""".trimMargin() + ) } // execute script for scale control definition if (mapConfig.scaleControlConfig.show) { - execScript("L.control.scale({position: '${mapConfig.scaleControlConfig.position.positionName}', " + - "metric: ${mapConfig.scaleControlConfig.metric}, " + - "imperial: ${!mapConfig.scaleControlConfig.metric}})" + - ".addTo(myMap);") + execScript( + "L.control.scale({position: '${mapConfig.scaleControlConfig.position.positionName}', " + + "metric: ${mapConfig.scaleControlConfig.metric}, " + + "imperial: ${!mapConfig.scaleControlConfig.metric}})" + + ".addTo(myMap);" + ) } // execute script for zoom control definition if (mapConfig.zoomControlConfig.show) { - execScript("L.control.zoom({position: '${mapConfig.zoomControlConfig.position.positionName}'})" + - ".addTo(myMap);") + execScript( + "L.control.zoom({position: '${mapConfig.zoomControlConfig.position.positionName}'})" + + ".addTo(myMap);" + ) } } @@ -137,7 +134,7 @@ class LeafletMapView : StackPane() { * @param zoomLevel zoom level (0 - 19 for OpenStreetMap) */ fun setView(position: LatLong, zoomLevel: Int) = - execScript("myMap.setView([${position.latitude}, ${position.longitude}], $zoomLevel);") + execScript("myMap.setView([${position.latitude}, ${position.longitude}], $zoomLevel);") /** * Pans the map to the specified geographical center position. @@ -145,7 +142,7 @@ class LeafletMapView : StackPane() { * @param position map center position */ fun panTo(position: LatLong) = - execScript("myMap.panTo([${position.latitude}, ${position.longitude}]);") + execScript("myMap.panTo([${position.latitude}, ${position.longitude}]);") /** * Sets the zoom of the map to the specified level. @@ -153,7 +150,7 @@ class LeafletMapView : StackPane() { * @param zoomLevel zoom level (0 - 19 for OpenStreetMap) */ fun setZoom(zoomLevel: Int) = - execScript("myMap.setZoom([$zoomLevel]);") + execScript("myMap.setZoom([$zoomLevel]);") /** * Adds a Marker Object to a map @@ -201,11 +198,12 @@ class LeafletMapView : StackPane() { } fun setEventMousePosition() { - execScript("var lat=0.0, lng=0.0;\n" + - "myMap.addEventListener('mousemove', function(ev) {\n" + - " lat = ev.latlng.lat;\n" + - " lng = ev.latlng.lng;\n" + - "});" + execScript( + "var lat=0.0, lng=0.0;\n" + + "myMap.addEventListener('mousemove', function(ev) {\n" + + " lat = ev.latlng.lat;\n" + + " lng = ev.latlng.lng;\n" + + "});" ) } @@ -222,11 +220,13 @@ class LeafletMapView : StackPane() { * @param iconUrl the url if the marker icon */ fun addCustomMarker(markerName: String, iconUrl: String): String { - execScript("var $markerName = L.icon({\n" + - "iconUrl: '${createImage(iconUrl, "png")}',\n" + - "iconSize: [24, 24],\n" + - "iconAnchor: [12, 12],\n" + - "});") + execScript( + "var $markerName = L.icon({\n" + + "iconUrl: '${createImage(iconUrl, "png")}',\n" + + "iconSize: [24, 24],\n" + + "iconAnchor: [12, 12],\n" + + "});" + ) return markerName } @@ -315,29 +315,42 @@ class LeafletMapView : StackPane() { fun addTrack(positions: List) { val jsPositions = positions - .map { " [${it.latitude}, ${it.longitude}]" } - .joinToString(", \n") + .map { " [${it.latitude}, ${it.longitude}]" } + .joinToString(", \n") - execScript(""" + execScript( + """ |var latLngs = [ |$jsPositions |]; - |var polyline = L.polyline(latLngs, {color: 'red', weight: 2}).addTo(myMap);""".trimMargin()) + |var polyline = L.polyline(latLngs, {color: 'red', weight: 2}).addTo(myMap);""".trimMargin() + ) + } + + fun clearAllLayer() { + execScript(""" + myMap.eachLayer(function (layer) { + map.removeLayer(layer); + }); + """.trimIndent()) } fun addTrack(positions: List, id: String, color: Color, tooltip: String) { val jsPositions = positions - .map { " [${it.latitude}, ${it.longitude}]" } - .joinToString(", \n") + .map { " [${it.latitude}, ${it.longitude}]" } + .joinToString(", \n") val cleanTooltip = tooltip.replace("'", "'") - execScript(""" + execScript( + """ |var latLngs = [ |$jsPositions |]; - |var color = "rgb(${Math.floor(color.getRed() * 255).toInt()} ,${Math.floor(color.getGreen() * 255).toInt()},${Math.floor(color.getBlue() * 255).toInt()})"; - |var polyline$id = L.polyline(latLngs, {color: color, weight: 2, zIndexOffset: 200}).bindTooltip('$cleanTooltip', {sticky: true}).addTo(trackGroup)""".trimMargin()) + |var color = "rgb(${Math.floor(color.getRed() * 255).toInt()} ,${Math.floor(color.getGreen() * 255) + .toInt()},${Math.floor(color.getBlue() * 255).toInt()})"; + |var polyline$id = L.polyline(latLngs, {color: color, weight: 2, zIndexOffset: 200}).bindTooltip('$cleanTooltip', {sticky: true}).addTo(trackGroup)""".trimMargin() + ) } fun makeVesselTrackTransparent(id: String) { @@ -353,7 +366,8 @@ class LeafletMapView : StackPane() { } fun eventZoomChangeIcon() { - execScript(""" + execScript( + """ |myMap.on('zoomend', function() { |var currentZoom = myMap.getZoom(); |if (currentZoom < $zoomLimitSmallMarker) { @@ -366,7 +380,8 @@ class LeafletMapView : StackPane() { |}); |} |}); - """.trimMargin()) + """.trimMargin() + ) } fun removeTrack(id: String) { @@ -393,15 +408,18 @@ class LeafletMapView : StackPane() { } val jsPositions = latLongs - .map { " [${it.latitude}, ${it.longitude}]" } - .joinToString(", \n") + .map { " [${it.latitude}, ${it.longitude}]" } + .joinToString(", \n") val idSanitized = id.replace("-", "") - execScript(""" + execScript( + """ |var latLngs = [ |$jsPositions |]; - |var color = "rgb(${Math.floor(color.getRed() * 255).toInt()} ,${Math.floor(color.getGreen() * 255).toInt()},${Math.floor(color.getBlue() * 255).toInt()})"; - |var polygon$idSanitized = L.polygon(latLngs, {color: color}).addTo(myMap);""".trimMargin()) + |var color = "rgb(${Math.floor(color.getRed() * 255).toInt()} ,${Math.floor(color.getGreen() * 255) + .toInt()},${Math.floor(color.getBlue() * 255).toInt()})"; + |var polygon$idSanitized = L.polygon(latLngs, {color: color}).addTo(myMap);""".trimMargin() + ) } diff --git a/src/main/kotlin/map/MapConfig.kt b/src/main/kotlin/map/MapConfig.kt index b8f7f99..53f056c 100644 --- a/src/main/kotlin/map/MapConfig.kt +++ b/src/main/kotlin/map/MapConfig.kt @@ -1,4 +1,4 @@ -package fdit.leafletmap +package map /** * Class for defining the layers and controls in the map to be shown. diff --git a/src/main/kotlin/map/MapLayer.kt b/src/main/kotlin/map/MapLayer.kt index ed3e412..62ec3e8 100644 --- a/src/main/kotlin/map/MapLayer.kt +++ b/src/main/kotlin/map/MapLayer.kt @@ -1,4 +1,4 @@ -package fdit.leafletmap +package map /** * Enumeration for all supported map layers. diff --git a/src/main/kotlin/map/Marker.kt b/src/main/kotlin/map/Marker.kt index b2ce16a..cc3b8c6 100644 --- a/src/main/kotlin/map/Marker.kt +++ b/src/main/kotlin/map/Marker.kt @@ -1,8 +1,7 @@ -package fdit.leafletmap +package map + +import application.model.Vessel -import fdit.gui.graphicalScenarioEditor.GraphicalScenarioEditorContext -import fdit.gui.utils.tooltip.VesselTooltipUtils.formatVesselSnapshotTooltip -import fdit.metamodel.vessel.Vessel /** * Creates a marker at the specified geographical position. @@ -24,13 +23,17 @@ class Marker private constructor(private var position: LatLong, private var zInd private var tooltip = "" private var rotation = 0 private lateinit var aircraft: Vessel - private lateinit var context: GraphicalScenarioEditorContext private var relativeDate: Double = 0.0 - constructor(position: LatLong, aircraft: Vessel, relativeDate: Double, context: GraphicalScenarioEditorContext, aircraftIcon: String, zIndexOffset: Int) : this(position, zIndexOffset){ + constructor( + position: LatLong, + aircraft: Vessel, + relativeDate: Double, + aircraftIcon: String, + zIndexOffset: Int + ) : this(position, zIndexOffset) { this.aircraft = aircraft - this.context = context this.relativeDate = relativeDate this.marker = aircraftIcon } @@ -45,7 +48,8 @@ class Marker private constructor(private var position: LatLong, private var zInd this.name = nextMarkerName this.map = map this.attached = true - map.execScript(""" + map.execScript( + """ |var currentZoom = myMap.getZoom(); |var $name; |if (currentZoom < ${map.zoomLimitSmallMarker}) { @@ -53,17 +57,16 @@ class Marker private constructor(private var position: LatLong, private var zInd |} else { |$name = L.marker([${position.latitude}, ${position.longitude}], {title: '', icon: $marker, zIndexOffset: $zIndexOffset}).addTo(markersGroup); |} - """.trimMargin()) - setTooltip() + """.trimMargin() + ) +// setTooltip() if (clickable) { setClickable() } } fun setTooltip() { - this.tooltip = formatVesselSnapshotTooltip(aircraft, - context.getGraphicalScenario().getRecording(), - relativeDate) + this.tooltip = "TODO" this.tooltip = tooltip.replace("\n", "
") this.tooltip = tooltip.replace("'", "'") map.execScript("$name.bindTooltip('
${this.tooltip}
');") diff --git a/src/main/kotlin/map/ScaleControlConfig.kt b/src/main/kotlin/map/ScaleControlConfig.kt index 0d6eb64..1a13e6b 100644 --- a/src/main/kotlin/map/ScaleControlConfig.kt +++ b/src/main/kotlin/map/ScaleControlConfig.kt @@ -1,4 +1,4 @@ -package fdit.leafletmap +package map /** * Class for defining the scale control of the map. The scale can show either metric or imperial units. @@ -6,6 +6,7 @@ package fdit.leafletmap * @author Stefan Saring */ class ScaleControlConfig @JvmOverloads constructor( - val show: Boolean = false, - val position: ControlPosition = ControlPosition.BOTTOM_LEFT, - val metric: Boolean = true) \ No newline at end of file + val show: Boolean = false, + val position: ControlPosition = ControlPosition.BOTTOM_LEFT, + val metric: Boolean = true +) \ No newline at end of file diff --git a/src/main/kotlin/map/Zone.kt b/src/main/kotlin/map/Zone.kt index 869ceb2..33d5cdb 100644 --- a/src/main/kotlin/map/Zone.kt +++ b/src/main/kotlin/map/Zone.kt @@ -1,4 +1,7 @@ -package fdit.leafletmap +package map + +import map.LatLong +import map.LeafletMapView class Zone constructor(private var title: String) { private lateinit var map: LeafletMapView diff --git a/src/main/kotlin/map/ZoomControlConfig.kt b/src/main/kotlin/map/ZoomControlConfig.kt index 3441826..14e9ef0 100644 --- a/src/main/kotlin/map/ZoomControlConfig.kt +++ b/src/main/kotlin/map/ZoomControlConfig.kt @@ -1,4 +1,4 @@ -package fdit.leafletmap +package map /** * Class for defining the zoom control of the map. @@ -6,5 +6,6 @@ package fdit.leafletmap * @author Stefan Saring */ class ZoomControlConfig @JvmOverloads constructor( - val show: Boolean = true, - val position: ControlPosition = ControlPosition.TOP_LEFT) \ No newline at end of file + val show: Boolean = true, + val position: ControlPosition = ControlPosition.TOP_LEFT +) \ No newline at end of file diff --git a/src/main/kotlin/map/events/MapClickEvent.kt b/src/main/kotlin/map/events/MapClickEvent.kt index 360da13..c05891d 100644 --- a/src/main/kotlin/map/events/MapClickEvent.kt +++ b/src/main/kotlin/map/events/MapClickEvent.kt @@ -1,6 +1,6 @@ -package fdit.leafletmap.events +package map.events -import fdit.leafletmap.LatLong +import map.LatLong import java.util.* /** diff --git a/src/main/kotlin/map/events/MapMoveEvent.kt b/src/main/kotlin/map/events/MapMoveEvent.kt index f0b4a66..4cde9a7 100644 --- a/src/main/kotlin/map/events/MapMoveEvent.kt +++ b/src/main/kotlin/map/events/MapMoveEvent.kt @@ -1,6 +1,6 @@ -package fdit.leafletmap.events +package map.events -import fdit.leafletmap.LatLong +import map.LatLong import java.util.* /** diff --git a/src/main/kotlin/map/events/MarkerClickEvent.kt b/src/main/kotlin/map/events/MarkerClickEvent.kt index e5bf43b..44ff59f 100644 --- a/src/main/kotlin/map/events/MarkerClickEvent.kt +++ b/src/main/kotlin/map/events/MarkerClickEvent.kt @@ -1,4 +1,4 @@ -package fdit.leafletmap.events +package map.events import java.util.* diff --git a/src/main/resources/gui/mapPanel.fxml b/src/main/resources/gui/mapPanel.fxml new file mode 100644 index 0000000..1414910 --- /dev/null +++ b/src/main/resources/gui/mapPanel.fxml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/gui/windows.fxml b/src/main/resources/gui/windows.fxml index 91b144f..6848204 100644 --- a/src/main/resources/gui/windows.fxml +++ b/src/main/resources/gui/windows.fxml @@ -1,10 +1,9 @@ - + prefWidth="1200.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1"> @@ -20,11 +19,11 @@ - - + -- 1.7.10.4