diff --git a/README b/README deleted file mode 100644 index e69de29..0000000 diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/main/kotlin/application/App.kt b/src/main/kotlin/application/App.kt index c38bd1c..47397f1 100644 --- a/src/main/kotlin/application/App.kt +++ b/src/main/kotlin/application/App.kt @@ -1,3 +1,5 @@ +@file:JvmName("App") + package application import javafx.application.Application @@ -7,13 +9,12 @@ import javafx.fxml.FXMLLoader import javafx.scene.Parent import javafx.scene.Scene import javafx.stage.Stage -import javafx.stage.WindowEvent import jfxtras.styles.jmetro.JMetro import jfxtras.styles.jmetro.Style import kotlin.system.exitProcess class App : Application() { - var style : Style = Style.LIGHT + var style: Style = Style.LIGHT override fun start(primaryStage: Stage?) { diff --git a/src/main/kotlin/application/Logger.kt b/src/main/kotlin/application/Logger.kt deleted file mode 100644 index b71dfec..0000000 --- a/src/main/kotlin/application/Logger.kt +++ /dev/null @@ -1,6 +0,0 @@ -package application - -import org.slf4j.Logger -import org.slf4j.LoggerFactory - -fun getLogger(): Logger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME) \ No newline at end of file diff --git a/src/main/kotlin/application/VisualisationChart.kt b/src/main/kotlin/application/VisualisationChart.kt deleted file mode 100644 index 9184890..0000000 --- a/src/main/kotlin/application/VisualisationChart.kt +++ /dev/null @@ -1,10 +0,0 @@ -package application - -import javafx.scene.chart.Axis -import javafx.scene.chart.ScatterChart - -class VisualisationChart(xAxis: Axis?, yAxis: Axis?) : ScatterChart(xAxis, yAxis) { - - - -} \ No newline at end of file diff --git a/src/main/kotlin/application/controller/DataPanelController.kt b/src/main/kotlin/application/controller/DataPanelController.kt index c844171..d68433d 100644 --- a/src/main/kotlin/application/controller/DataPanelController.kt +++ b/src/main/kotlin/application/controller/DataPanelController.kt @@ -7,14 +7,11 @@ import javafx.fxml.FXML import javafx.fxml.Initializable import javafx.scene.control.ListCell import javafx.scene.control.ListView -import javafx.scene.layout.StackPane import org.charts.dataviewer.api.config.DataViewerConfiguration import org.charts.dataviewer.api.data.PlotData -import org.charts.dataviewer.api.trace.LineTrace import org.charts.dataviewer.api.trace.ScatterTrace import org.charts.dataviewer.javafx.JavaFxDataViewer import org.charts.dataviewer.utils.TraceColour -import org.charts.dataviewer.utils.TraceMode import org.charts.dataviewer.utils.TraceVisibility import java.net.URL import java.util.* @@ -28,41 +25,16 @@ class DataPanelController : Initializable, SelectedVesselListener { @FXML var dataListView = ListView>>() -// @FXML -// var stackPanePlot = StackPane() - @FXML var dataViewer = JavaFxDataViewer() -// @FXML -// var xaxisNumber: CategoryAxis = CategoryAxis() -// -// @FXML -// var yaxisNumber: NumberAxis = NumberAxis() -// -// @FXML -// lateinit var scatterChartNumber: ScatterChart -// -// @FXML -// var xaxisCategory: CategoryAxis = CategoryAxis() -// -// @FXML -// var yaxisCategory: CategoryAxis = CategoryAxis() -// -// @FXML -// lateinit var scatterChartCategory: ScatterChart override fun initialize(location: URL?, resources: ResourceBundle?) { -// xaxisNumber.animated = false -// yaxisNumber.animated = false -// xaxisCategory.animated = false -// yaxisCategory.animated = false setObservableSelectedVesselListener() dataListView.items = dataList val plotData = PlotData() - plotData.addTrace(createScatterTrace()) val config = DataViewerConfiguration() config.showLegend(true) config.setLegendInsidePlot(false) @@ -85,6 +57,8 @@ class DataPanelController : Initializable, SelectedVesselListener { plotData.allTraces.clear() config.setxAxisTitle("") config.setyAxisTitle("") + dataViewer.updateConfiguration(config) + dataViewer.resetPlot() return@addListener @@ -139,46 +113,13 @@ class DataPanelController : Initializable, SelectedVesselListener { } plotData.allTraces.clear() -// plotData.addTrace(createScatterTrace()) config.setxAxisTitle("") config.setyAxisTitle("") - config.plotTitle = "No data selected" dataViewer.updateConfiguration(config) dataViewer.updatePlot(plotData) -// stackPanePlot.children.add(dataViewer) - - } - - private fun createScatterTrace(): ScatterTrace<*>? { - val scatterTrace = ScatterTrace() - scatterTrace.setxArray(arrayOf("asdf", "fdsa", "asdfffe", "asdfe", "asfee3")) - scatterTrace.setyArray(arrayOf("pppp", "koojoi", "pp", "ii", "rty", "ert")) - scatterTrace.traceName = "MyScatterTrace" - scatterTrace.traceColour = TraceColour.PURPLE - scatterTrace.traceMode = TraceMode.MARKERS - return scatterTrace - } - - fun createLineTrace(): LineTrace<*>? { - val lineTrace = LineTrace() - lineTrace.setxArray(arrayOf("asdf", "fdsa", "asdfffe", "asdfe", "asfee3")) - lineTrace.setyArray(arrayOf(0.0, 1.0, 2.0, 3.0, 4.0, 5.0)) - lineTrace.traceName = "MyLineTrace" - lineTrace.traceColour = TraceColour.PURPLE - return lineTrace } -// private fun setChartCategoryVisible() { -// scatterChartCategory.isVisible = true -// scatterChartNumber.isVisible = false -// } -// -// private fun setChartNumberVisible() { -// scatterChartCategory.isVisible = false -// scatterChartNumber.isVisible = true -// } - private fun setObservableSelectedVesselListener() { observableSelectedVessel.listeners.add(this) } diff --git a/src/main/kotlin/application/controller/MapPanelController.kt b/src/main/kotlin/application/controller/MapPanelController.kt index 001cc88..54fcd50 100644 --- a/src/main/kotlin/application/controller/MapPanelController.kt +++ b/src/main/kotlin/application/controller/MapPanelController.kt @@ -52,7 +52,7 @@ class MapPanelController : Initializable { } } - private fun updateMap(selectedMMSI: Int) { + private fun updateMap(selectedMMSI: String) { when (observableState.state) { ALL_MESSAGES -> displayAllMessageOnMap(mapView, selectedMMSI) CLUSTERED_MESSAGES -> displayClusterMessageOnMap(mapView, selectedMMSI) @@ -62,7 +62,7 @@ class MapPanelController : Initializable { private fun setObservableVesselListener() { observableVessel.listeners.add(object : MessageListener { - override fun onValueChanged(newValue: MutableMap) { + override fun onValueChanged(newValue: MutableMap) { updateMap() } }) @@ -73,6 +73,8 @@ class MapPanelController : Initializable { override fun onValueChanged(newValue: Vessel) { if (newValue.mmsi != null){ updateMap(newValue.mmsi) + }else { + updateMap() } } }) diff --git a/src/main/kotlin/application/controller/VesselListPanelController.kt b/src/main/kotlin/application/controller/VesselListPanelController.kt index 51726bd..056ad86 100644 --- a/src/main/kotlin/application/controller/VesselListPanelController.kt +++ b/src/main/kotlin/application/controller/VesselListPanelController.kt @@ -2,34 +2,65 @@ package application.controller import application.model.MessageListener import application.model.Vessel -import application.model.observableVessel import application.model.observableSelectedVessel +import application.model.observableVessel import javafx.collections.FXCollections import javafx.collections.ObservableList +import javafx.event.EventHandler import javafx.fxml.FXML import javafx.fxml.Initializable -import javafx.scene.control.ListView +import javafx.scene.control.* +import javafx.scene.input.MouseEvent import java.net.URL import java.util.* + class VesselListPanelController : Initializable, MessageListener { @FXML - var shipListView: ListView = ListView() + var shipListView: ListView = ListView() - - private var shipList: ObservableList = FXCollections.observableArrayList() + private var shipList: ObservableList = FXCollections.observableArrayList() override fun initialize(location: URL?, resources: ResourceBundle?) { + + shipListView.items = shipList observableVessel.listeners.add(this) shipListView.selectionModel.selectedItemProperty().addListener { _, _, newValue -> - observableSelectedVessel.vessel = observableVessel.vessels[newValue]!! + if (newValue == null) { + observableSelectedVessel.vessel = Vessel(null) + } else { + observableSelectedVessel.vessel = observableVessel.vessels[newValue]!! + } } + setCellFactory() } - override fun onValueChanged(newValue: MutableMap) { + override fun onValueChanged(newValue: MutableMap) { shipList.clear() shipList.addAll(newValue.keys) } -} \ No newline at end of file + private fun setCellFactory() { + val selectionModel: MultipleSelectionModel? = shipListView.selectionModel + selectionModel?.selectionMode = SelectionMode.SINGLE + shipListView.setCellFactory { + val cell = ListCell() + cell.textProperty().bind(cell.itemProperty()) + cell.addEventFilter(MouseEvent.MOUSE_PRESSED) { event: MouseEvent -> + shipListView.requestFocus() + if (!cell.isEmpty) { + val index = cell.index + if (selectionModel!!.selectedIndices.contains(index)) { + selectionModel.clearSelection() + } else { + selectionModel.select(index) + } + event.consume() + } + } + cell + } + } +} + diff --git a/src/main/kotlin/application/model/Message.kt b/src/main/kotlin/application/model/Message.kt index d3ce810..68d7726 100644 --- a/src/main/kotlin/application/model/Message.kt +++ b/src/main/kotlin/application/model/Message.kt @@ -3,7 +3,7 @@ package application.model import java.time.LocalDateTime class Message(split: List) { - val mmsi = MMSI(split[0].toIntOrNull()) + val mmsi = MMSI(if (split[0] == "") null else split[0]) val time = Time(LocalDateTime.parse(split[1])) val latitude = Latitude(split[2].toDoubleOrNull()) val longitude = Longitude(split[3].toDoubleOrNull()) @@ -20,9 +20,8 @@ class Message(split: List) { val draft = Draft(split[14].toDoubleOrNull()) val cargo = Cargo(split[15].toIntOrNull()) - fun getHexColorStroke(): String { - var hex = Integer.toHexString(this.mmsi.value!!) + var hex = Integer.toHexString(this.mmsi.value?.toInt()!!) if (hex.length > 6) { hex = hex.substring(hex.length - 6) } diff --git a/src/main/kotlin/application/model/MessageData.kt b/src/main/kotlin/application/model/MessageData.kt index e221950..2596b99 100644 --- a/src/main/kotlin/application/model/MessageData.kt +++ b/src/main/kotlin/application/model/MessageData.kt @@ -27,7 +27,7 @@ interface MessageData { } -data class MMSI(val value: Int?) : MessageData { +data class MMSI(val value: String?) : MessageData { override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) } diff --git a/src/main/kotlin/application/model/MessageListener.kt b/src/main/kotlin/application/model/MessageListener.kt index 6e05c27..b681a34 100644 --- a/src/main/kotlin/application/model/MessageListener.kt +++ b/src/main/kotlin/application/model/MessageListener.kt @@ -1,5 +1,5 @@ package application.model interface MessageListener { - fun onValueChanged(newValue: MutableMap) + fun onValueChanged(newValue: MutableMap) } \ No newline at end of file diff --git a/src/main/kotlin/application/model/ObservableVessel.kt b/src/main/kotlin/application/model/ObservableVessel.kt index ebce912..40c173d 100644 --- a/src/main/kotlin/application/model/ObservableVessel.kt +++ b/src/main/kotlin/application/model/ObservableVessel.kt @@ -5,7 +5,7 @@ import kotlin.properties.Delegates class ObservableVessel { val listeners: MutableList = mutableListOf() - var vessels: MutableMap by Delegates.observable( + var vessels: MutableMap by Delegates.observable( initialValue = mutableMapOf(), onChange = { _, _, new -> run { diff --git a/src/main/kotlin/application/model/Vessel.kt b/src/main/kotlin/application/model/Vessel.kt index 8e13b3f..0d3945b 100644 --- a/src/main/kotlin/application/model/Vessel.kt +++ b/src/main/kotlin/application/model/Vessel.kt @@ -5,19 +5,9 @@ import java.time.ZoneOffset import java.util.* -class Vessel(val mmsi: Int?) { +class Vessel(val mmsi: String?) { val messages: SortedMap = sortedMapOf() - fun getAllTimeInMilliSeconde(): ArrayList { - val timeList = arrayListOf() - var timeInMilliSeconde: Long - messages.forEach { - timeInMilliSeconde = it.value.time.value.toEpochSecond(ZoneOffset.UTC).toInt().toLong() - timeList.add(timeInMilliSeconde) - } - return timeList - } - fun getAllTime(): ArrayList { val timeList = arrayListOf() messages.forEach { diff --git a/src/main/kotlin/application/model/VesselGenerator.kt b/src/main/kotlin/application/model/VesselGenerator.kt index a8a1dcb..cfd09f6 100644 --- a/src/main/kotlin/application/model/VesselGenerator.kt +++ b/src/main/kotlin/application/model/VesselGenerator.kt @@ -4,9 +4,9 @@ import java.io.File import java.util.* import kotlin.collections.ArrayList -fun createVesselCollection(file: File) : SortedMap { +fun createVesselCollection(file: File) : SortedMap { val messages : ArrayList = arrayListOf() - val vessels: SortedMap = sortedMapOf() + val vessels: SortedMap = sortedMapOf() file.forEachLine { val arrayMessage = it.split(",") diff --git a/src/main/kotlin/map/MapDisplayer.kt b/src/main/kotlin/map/MapDisplayer.kt index cda3bb7..bcb5429 100644 --- a/src/main/kotlin/map/MapDisplayer.kt +++ b/src/main/kotlin/map/MapDisplayer.kt @@ -44,7 +44,7 @@ fun displayAllMessageOnMap(map: LeafletMapView) { } } -fun displayAllMessageOnMap(map: LeafletMapView, selectedMMSI: Int) { +fun displayAllMessageOnMap(map: LeafletMapView, selectedMMSI: String) { clearMap(map) observableVessel.vessels.forEach { (_, value) -> value.messages.forEach { (_, message) -> @@ -67,7 +67,7 @@ fun displayClusterMessageOnMap(map: LeafletMapView) { map.execScript("myMap.addLayer(markerClusters);") } -fun displayClusterMessageOnMap(map: LeafletMapView, selectedMMSI: Int) { +fun displayClusterMessageOnMap(map: LeafletMapView, selectedMMSI: String) { clearMap(map) observableVessel.vessels.forEach { (_, value) -> value.messages.forEach { (_, message) -> @@ -90,7 +90,7 @@ fun displayHeatMapOnMap(map: LeafletMapView) { } } -fun displayHeatMapOnMap(map: LeafletMapView, selectedMMSI: Int) { +fun displayHeatMapOnMap(map: LeafletMapView, selectedMMSI: String) { clearMap(map) observableVessel.vessels.forEach { (_, value) -> value.messages.forEach { (_, message) -> diff --git a/src/main/resources/gui/vesselListPanel.fxml b/src/main/resources/gui/vesselListPanel.fxml index f928dfc..e2f9cdb 100644 --- a/src/main/resources/gui/vesselListPanel.fxml +++ b/src/main/resources/gui/vesselListPanel.fxml @@ -1,17 +1,25 @@ + + - - - - - -