Commit 2bbe36a1be826b47c824114b471c6a1e5de02983
1 parent
52321443a8
Exists in
master
and in
1 other branch
addd the possibility to select a ship
Showing 13 changed files with 112 additions and 68 deletions Inline Diff
- src/main/kotlin/application/controller/ControlPanelController.kt
- src/main/kotlin/application/controller/MapPanelController.kt
- src/main/kotlin/application/controller/MenuBarController.kt
- src/main/kotlin/application/controller/VesselListPanelController.kt
- src/main/kotlin/application/model/Context.kt
- src/main/kotlin/application/model/ObservableSelectedVessel.kt
- src/main/kotlin/application/model/SelectedVesselListener.kt
- src/main/kotlin/application/model/Vessel.kt
- src/main/kotlin/application/model/VesselGenerator.kt
- src/main/kotlin/map/CircleMarkerGenerator.kt
- src/main/resources/gui/controlPanel.fxml
- src/main/resources/gui/vesselListPanel.fxml
- src/main/resources/gui/windows.fxml
src/main/kotlin/application/controller/ControlPanelController.kt
View file @
2bbe36a
| package application.controller | 1 | File was deleted | ||
| 2 | ||||
| import application.model.MessageListener | 3 | |||
| import application.model.Vessel | 4 | |||
| import application.model.observableMessages | 5 | |||
| import javafx.collections.FXCollections | 6 | |||
| import javafx.collections.ObservableList | 7 | |||
| import javafx.event.EventHandler | 8 | |||
| import javafx.fxml.FXML | 9 | |||
| import javafx.fxml.Initializable | 10 | |||
| import javafx.scene.control.Button | 11 | |||
| import javafx.scene.control.ListView | 12 | |||
| import java.net.URL | 13 | |||
| import java.util.* | 14 | |||
| 15 | ||||
| class ControlPanelController : Initializable, MessageListener { | 16 | |||
| @FXML | 17 | |||
| var shipListView: ListView<Int> = ListView() | 18 | |||
| 19 | ||||
| 20 | ||||
| var shipList: ObservableList<Int> = FXCollections.observableArrayList() | 21 | |||
| 22 | ||||
| override fun initialize(location: URL?, resources: ResourceBundle?) { | 23 | |||
| shipListView.items = shipList | 24 | |||
| observableMessages.listeners.add(this) | 25 | |||
| } | 26 |
src/main/kotlin/application/controller/MapPanelController.kt
View file @
2bbe36a
| package application.controller | 1 | 1 | package application.controller | |
| 2 | 2 | |||
| import application.model.MessageListener | 3 | 3 | import application.model.* | |
| import application.model.Vessel | 4 | |||
| import application.model.observableMessages | 5 | |||
| import javafx.concurrent.Worker | 6 | 4 | import javafx.concurrent.Worker | |
| import javafx.fxml.FXML | 7 | 5 | import javafx.fxml.FXML | |
| import javafx.fxml.Initializable | 8 | 6 | import javafx.fxml.Initializable | |
| import javafx.scene.layout.StackPane | 9 | 7 | import javafx.scene.layout.StackPane | |
| import map.LeafletMapView | 10 | 8 | import map.LeafletMapView | |
| import map.MapConfig | 11 | 9 | import map.MapConfig | |
| import map.displayMessageOnMap | 12 | 10 | import map.displayMessageOnMap | |
| import java.net.URL | 13 | 11 | import java.net.URL | |
| import java.util.* | 14 | 12 | import java.util.* | |
| import java.util.concurrent.CompletableFuture | 15 | 13 | import java.util.concurrent.CompletableFuture | |
| 16 | 14 | |||
| class MapPanelController : Initializable, MessageListener { | 17 | 15 | class MapPanelController : Initializable { | |
| 18 | 16 | |||
| @FXML | 19 | 17 | @FXML | |
| private lateinit var map: StackPane | 20 | 18 | private lateinit var map: StackPane | |
| 21 | 19 | |||
| private val mapView = LeafletMapView() | 22 | 20 | private val mapView = LeafletMapView() | |
| 23 | 21 | |||
| 24 | 22 | |||
| override fun initialize(location: URL?, resources: ResourceBundle?) { | 25 | 23 | override fun initialize(location: URL?, resources: ResourceBundle?) { | |
| val completeFutureMap: CompletableFuture<Worker.State> = mapView.displayMap(MapConfig()) | 26 | 24 | val completeFutureMap: CompletableFuture<Worker.State> = mapView.displayMap(MapConfig()) | |
| observableMessages.listeners.add(this) | 27 | 25 | observableVessel.listeners.add(object : MessageListener { | |
| 26 | override fun onValueChanged(newValue: MutableMap<Int?, Vessel>) { | |||
| 27 | displayMessageOnMap(mapView) | |||
| 28 | } | |||
| 29 | }) | |||
| 28 | 30 | |||
| 31 | observableSelectedVessel.listeners.add(object : SelectedVesselListener { | |||
| 32 | override fun onValueChanged(newValue: Vessel) { | |||
| 33 | displayMessageOnMap(mapView, newValue.mmsi!!) | |||
| 34 | } | |||
| 35 | }) | |||
| 36 | ||||
| /*completeFutureMap.whenComplete{ | 29 | 37 | /*completeFutureMap.whenComplete{ | |
| workerState, _ -> | 30 | 38 | workerState, _ -> | |
| if (workerState == Worker.State.SUCCEEDED) { | 31 | 39 | if (workerState == Worker.State.SUCCEEDED) { | |
| } | 32 | 40 | } | |
| }*/ | 33 | 41 | }*/ | |
| map.children.add(mapView) | 34 | 42 | map.children.add(mapView) | |
| } | 35 |
src/main/kotlin/application/controller/MenuBarController.kt
View file @
2bbe36a
| package application.controller | 1 | 1 | package application.controller | |
| 2 | 2 | |||
| import application.model.createVesselCollection | 3 | 3 | import application.model.createVesselCollection | |
| import application.model.observableMessages | 4 | 4 | import application.model.observableVessel | |
| import javafx.event.EventHandler | 5 | 5 | import javafx.event.EventHandler | |
| import javafx.fxml.FXML | 6 | 6 | import javafx.fxml.FXML | |
| import javafx.fxml.Initializable | 7 | 7 | import javafx.fxml.Initializable | |
| import javafx.scene.control.MenuBar | 8 | 8 | import javafx.scene.control.MenuBar | |
| import javafx.scene.control.MenuItem | 9 | 9 | import javafx.scene.control.MenuItem | |
| import javafx.stage.FileChooser | 10 | 10 | import javafx.stage.FileChooser | |
| import java.net.URL | 11 | 11 | import java.net.URL | |
| import java.util.* | 12 | 12 | import java.util.* | |
| 13 | 13 | |||
| class MenuBarController : Initializable { | 14 | 14 | class MenuBarController : Initializable { | |
| 15 | 15 | |||
| @FXML | 16 | 16 | @FXML | |
| var menuBar: MenuBar = MenuBar() | 17 | 17 | var menuBar: MenuBar = MenuBar() | |
| 18 | 18 | |||
| @FXML | 19 | 19 | @FXML | |
| var import: MenuItem = MenuItem() | 20 | 20 | var import: MenuItem = MenuItem() | |
| 21 | 21 | |||
| override fun initialize(location: URL?, resources: ResourceBundle?) { | 22 | 22 | override fun initialize(location: URL?, resources: ResourceBundle?) { | |
| 23 | 23 | |||
| import.onAction = EventHandler { | 24 | 24 | import.onAction = EventHandler { | |
| val fileChooser = FileChooser() | 25 | 25 | val fileChooser = FileChooser() | |
| fileChooser.title = "Choose a file to import" | 26 | 26 | fileChooser.title = "Choose a file to import" | |
| val window = menuBar.scene.window | 27 | 27 | val window = menuBar.scene.window | |
| val file = fileChooser.showOpenDialog(window) | 28 | 28 | val file = fileChooser.showOpenDialog(window) | |
| val vessels = createVesselCollection(file) | 29 | 29 | val vessels = createVesselCollection(file) | |
| observableMessages.vessels.clear() | 30 | 30 | observableVessel.vessels.clear() | |
| observableMessages.vessels = vessels | 31 | 31 | observableVessel.vessels = vessels |
src/main/kotlin/application/controller/VesselListPanelController.kt
View file @
2bbe36a
| File was created | 1 | package application.controller | ||
| 2 | ||||
| 3 | import application.model.MessageListener | |||
| 4 | import application.model.Vessel | |||
| 5 | import application.model.observableVessel | |||
| 6 | import application.model.observableSelectedVessel | |||
| 7 | import javafx.collections.FXCollections | |||
| 8 | import javafx.collections.ObservableList | |||
| 9 | import javafx.fxml.FXML | |||
| 10 | import javafx.fxml.Initializable | |||
| 11 | import javafx.scene.control.ListView | |||
| 12 | import java.net.URL | |||
| 13 | import java.util.* | |||
| 14 | ||||
| 15 | class VesselListPanelController : Initializable, MessageListener { | |||
| 16 | @FXML | |||
| 17 | var shipListView: ListView<Int> = ListView() | |||
| 18 | ||||
| 19 | ||||
| 20 | var shipList: ObservableList<Int> = FXCollections.observableArrayList() | |||
| 21 | ||||
| 22 | override fun initialize(location: URL?, resources: ResourceBundle?) { | |||
| 23 | shipListView.items = shipList | |||
| 24 | observableVessel.listeners.add(this) | |||
| 25 | shipListView.selectionModel.selectedItemProperty().addListener { _, _, newValue -> | |||
| 26 | observableSelectedVessel.vessel = observableVessel.vessels[newValue]!! | |||
| 27 | } | |||
| 28 | } |
src/main/kotlin/application/model/Context.kt
View file @
2bbe36a
| package application.model | 1 | 1 | package application.model | |
| 2 | 2 | |||
| val observableMessages : ObservableVessel = ObservableVessel() | 3 | 3 | val observableVessel: ObservableVessel = ObservableVessel() | |
| 4 | ||||
| 5 | val observableSelectedVessel: ObservableSelectedVessel = ObservableSelectedVessel() |
src/main/kotlin/application/model/ObservableSelectedVessel.kt
View file @
2bbe36a
| File was created | 1 | package application.model | ||
| 2 | ||||
| 3 | import kotlin.properties.Delegates | |||
| 4 | ||||
| 5 | class ObservableSelectedVessel { | |||
| 6 | val listeners: MutableList<SelectedVesselListener> = mutableListOf() | |||
| 7 | ||||
| 8 | var vessel: Vessel by Delegates.observable( | |||
| 9 | initialValue = Vessel(null), | |||
| 10 | onChange = { _, _, new -> | |||
| 11 | run { | |||
| 12 | listeners.forEach { | |||
| 13 | it.onValueChanged(new) | |||
| 14 | } | |||
| 15 | } |
src/main/kotlin/application/model/SelectedVesselListener.kt
View file @
2bbe36a
| File was created | 1 | package application.model | ||
| 2 | ||||
| 3 | interface SelectedVesselListener { | |||
| 4 | fun onValueChanged(newValue: Vessel) |
src/main/kotlin/application/model/Vessel.kt
View file @
2bbe36a
| package application.model | 1 | 1 | package application.model | |
| 2 | 2 | |||
| import java.time.LocalDateTime | 3 | 3 | import java.time.LocalDateTime | |
| import java.util.* | 4 | 4 | import java.util.* | |
| 5 | 5 | |||
| 6 | 6 | |||
| class Vessel { | 7 | 7 | class Vessel(val mmsi : Int?) { |
src/main/kotlin/application/model/VesselGenerator.kt
View file @
2bbe36a
| package application.model | 1 | 1 | package application.model | |
| 2 | 2 | |||
| import java.io.File | 3 | 3 | import java.io.File | |
| import java.util.* | 4 | 4 | import java.util.* | |
| import kotlin.collections.ArrayList | 5 | 5 | import kotlin.collections.ArrayList | |
| 6 | 6 | |||
| fun createVesselCollection(file: File) : SortedMap<Int, Vessel> { | 7 | 7 | fun createVesselCollection(file: File) : SortedMap<Int, Vessel> { | |
| val messages : ArrayList<Message> = arrayListOf() | 8 | 8 | val messages : ArrayList<Message> = arrayListOf() | |
| val vessels: SortedMap<Int, Vessel> = sortedMapOf() | 9 | 9 | val vessels: SortedMap<Int, Vessel> = sortedMapOf() | |
| 10 | 10 | |||
| file.forEachLine { | 11 | 11 | file.forEachLine { | |
| val arrayMessage = it.split(",") | 12 | 12 | val arrayMessage = it.split(",") | |
| if (arrayMessage[0].toIntOrNull() !== null) { | 13 | 13 | if (arrayMessage[0].toIntOrNull() !== null) { | |
| val message = Message(arrayMessage) | 14 | 14 | val message = Message(arrayMessage) | |
| messages.add(message) | 15 | 15 | messages.add(message) | |
| if (!vessels.containsKey(message.mmsi)){ | 16 | 16 | if (!vessels.containsKey(message.mmsi)){ | |
| vessels[message.mmsi] = Vessel() | 17 | 17 | vessels[message.mmsi] = Vessel(message.mmsi!!) | |
| } | 18 | 18 | } | |
| vessels[message.mmsi]?.messages?.set(message.time, message) | 19 | 19 | vessels[message.mmsi]?.messages?.set(message.time, message) | |
| } | 20 | 20 | } | |
| 21 | 21 |
src/main/kotlin/map/CircleMarkerGenerator.kt
View file @
2bbe36a
| package map | 1 | 1 | package map | |
| 2 | 2 | |||
| import application.model.observableMessages | 3 | 3 | import application.model.observableVessel | |
| 4 | 4 | |||
| fun clearMapCanvas(map: LeafletMapView) { | 5 | 5 | fun clearMapCanvas(map: LeafletMapView) { | |
| map.execScript(""" | 6 | 6 | map.execScript(""" | |
| |myRenderer.removeFrom(myMap) | 7 | 7 | |myRenderer.removeFrom(myMap) | |
| |var myRenderer = L.canvas({ padding: 0.5 }); | 8 | 8 | |var myRenderer = L.canvas({ padding: 0.5 }); | |
| """.trimMargin()) | 9 | 9 | """.trimMargin()) | |
| } | 10 | 10 | } | |
| 11 | 11 | |||
| fun displayMessageOnMap(map: LeafletMapView) { | 12 | 12 | fun displayMessageOnMap(map: LeafletMapView) { | |
| clearMapCanvas(map) | 13 | 13 | clearMapCanvas(map) | |
| observableMessages.vessels.forEach { (_, value) -> | 14 | 14 | observableVessel.vessels.forEach { (_, value) -> | |
| value.messages.forEach { (_, message) -> | 15 | 15 | value.messages.forEach { (_, message) -> | |
| map.execScript("L.circleMarker([${message.latitude}, ${message.longitude}], {renderer: myRenderer, radius: 0.01, color: '#${message.getHexColor()}'}).addTo(myMap)") | 16 | 16 | map.execScript("L.circleMarker([${message.latitude}, ${message.longitude}], {renderer: myRenderer, radius: 0.01, color: '#${message.getHexColor()}'}).addTo(myMap)") | |
| 17 | } | |||
| 18 | } | |||
| 19 | } | |||
| 20 | ||||
| 21 | fun displayMessageOnMap(map: LeafletMapView, selectedMMSI: Int) { | |||
| 22 | clearMapCanvas(map) | |||
| 23 | observableVessel.vessels.forEach { (_, value) -> | |||
| 24 | value.messages.forEach { (_, message) -> | |||
| 25 | if(selectedMMSI == message.mmsi){ | |||
| 26 | map.execScript("L.circleMarker([${message.latitude}, ${message.longitude}], {renderer: myRenderer, radius: 4, color: '#ff001e'}).addTo(myMap)") | |||
| 27 | }else{ | |||
| 28 | map.execScript("L.circleMarker([${message.latitude}, ${message.longitude}], {renderer: myRenderer, radius: 0.01, color: '#${message.getHexColor()}'}).addTo(myMap)") | |||
| 29 | } | |||
| } | 17 | 30 | } | |
| } | 18 | 31 | } |
src/main/resources/gui/controlPanel.fxml
View file @
2bbe36a
| <?xml version="1.0" encoding="UTF-8"?> | 1 | File was deleted | ||
| 2 | ||||
| <?import javafx.scene.control.*?> | 3 | |||
| <?import javafx.scene.layout.*?> | 4 | |||
| 5 | ||||
| <BorderPane prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller.ControlPanelController"> | 6 | |||
| 7 | ||||
| <top> | 8 | |||
| <AnchorPane prefHeight="33.0" prefWidth="200.0" BorderPane.alignment="CENTER"> | 9 | |||
| <children> | 10 | |||
| <Button layoutX="74.0" layoutY="2.0" mnemonicParsing="false" text="Button" fx:id="buton" /> | 11 | |||
| </children></AnchorPane> | 12 | |||
| </top> | 13 | |||
| <center> | 14 |
src/main/resources/gui/vesselListPanel.fxml
View file @
2bbe36a
| File was created | 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | ||||
| 3 | <?import javafx.scene.control.*?> | |||
| 4 | <?import javafx.scene.layout.*?> | |||
| 5 | ||||
| 6 | <BorderPane prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller.VesselListPanelController"> | |||
| 7 | ||||
| 8 | <top> | |||
| 9 | <AnchorPane prefHeight="33.0" prefWidth="200.0" BorderPane.alignment="CENTER"> | |||
| 10 | <children> | |||
| 11 | <Button layoutX="74.0" layoutY="2.0" mnemonicParsing="false" text="Button" fx:id="buton" /> | |||
| 12 | </children></AnchorPane> | |||
| 13 | </top> | |||
| 14 | <center> |
src/main/resources/gui/windows.fxml
View file @
2bbe36a
| <?xml version="1.0" encoding="UTF-8"?> | 1 | 1 | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | 2 | |||
| <?import javafx.scene.control.*?> | 3 | 3 | <?import javafx.scene.control.*?> | |
| <?import javafx.scene.layout.*?> | 4 | 4 | <?import javafx.scene.layout.*?> | |
| <?import javafx.scene.shape.*?> | 5 | 5 | <?import javafx.scene.shape.*?> | |
| 6 | 6 | |||
| <AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="900.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1"> | 7 | 7 | <AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="900.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1"> | |
| <children> | 8 | 8 | <children> | |
| <fx:include source="menuBar.fxml" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" /> | 9 | 9 | <fx:include source="menuBar.fxml" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" /> | |
| <SplitPane dividerPositions="0.29797979797979796" layoutY="39.0" prefHeight="865.0" prefWidth="1194.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="35.0"> | 10 | 10 | <SplitPane dividerPositions="0.29797979797979796" layoutY="39.0" prefHeight="865.0" prefWidth="1194.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="35.0"> | |
| <items> | 11 | 11 | <items> | |
| <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0"> | 12 | 12 | <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0"> | |
| <children> | 13 | 13 | <children> | |
| <fx:include source="controlPanel.fxml" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" /> | 14 | 14 | <fx:include source="vesselListPanel.fxml" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" /> | |
| </children> | 15 | 15 | </children> | |
| </AnchorPane> | 16 | 16 | </AnchorPane> | |
| <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0"> | 17 | 17 | <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0"> | |
| <children> | 18 | 18 | <children> | |
| <SplitPane dividerPositions="0.536" layoutX="127.0" layoutY="74.0" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> | 19 | 19 | <SplitPane dividerPositions="0.536" layoutX="127.0" layoutY="74.0" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> | |
| <items> | 20 | 20 | <items> | |
| <fx:include source="mapPanel.fxml" /> | 21 | 21 | <fx:include source="mapPanel.fxml" /> | |
| <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0" /> | 22 | 22 | <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0" /> | |
| </items> | 23 | 23 | </items> | |
| </SplitPane> | 24 | 24 | </SplitPane> | |
| </children> | 25 | 25 | </children> | |
| </AnchorPane> | 26 | 26 | </AnchorPane> | |
| </items> | 27 | 27 | </items> | |
| </SplitPane> | 28 | 28 | </SplitPane> | |
| <Line endX="1101.0" endY="1.1444091796875E-5" layoutX="101.0" layoutY="35.0" startX="-100.0" /> | 29 | 29 | <Line endX="1101.0" endY="1.1444091796875E-5" layoutX="101.0" layoutY="35.0" startX="-100.0" /> | |
| </children> | 30 | 30 | </children> |