Commit e220e082b538d95eae8e1c1c23879c90ff0bcde6
1 parent
dd1ce7fe83
Exists in
master
and in
1 other branch
graph binded to slider
removed useless start and stop button
Showing 8 changed files with 385 additions and 161 deletions Inline Diff
- build.gradle
 - src/main/kotlin/application/App.kt
 - src/main/kotlin/application/controller/DataPanelController.kt
 - src/main/kotlin/application/controller/MapPanelController.kt
 - src/main/kotlin/application/controller/TimePanel.kt
 - src/main/kotlin/application/model/ObservableCurrentTime.kt
 - src/main/kotlin/application/model/Vessel.kt
 - src/main/resources/gui/timePanel.fxml
 
build.gradle
View file @
e220e08
| plugins { | 1 | 1 | plugins { | |
| id 'java' | 2 | 2 | id 'java' | |
| id 'org.jetbrains.kotlin.jvm' version '1.3.72' | 3 | 3 | id 'org.jetbrains.kotlin.jvm' version '1.3.72' | |
| } | 4 | 4 | } | |
| 5 | 5 | |||
| group 'marivisu' | 6 | 6 | group 'marivisu' | |
| version '1.0-SNAPSHOT' | 7 | 7 | version '1.0-SNAPSHOT' | |
| 8 | 8 | |||
| repositories { | 9 | 9 | repositories { | |
| mavenCentral() | 10 | 10 | mavenCentral() | |
| maven { | 11 | 11 | maven { | |
| url "https://jitpack.io" | 12 | 12 | url "https://jitpack.io" | |
| } | 13 | 13 | } | |
| } | 14 | 14 | } | |
| 15 | 15 | |||
| dependencies { | 16 | 16 | dependencies { | |
| implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" | 17 | 17 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" | |
| implementation 'org.jfxtras:jmetro:8.6.9' | 18 | 18 | implementation 'org.jfxtras:jmetro:8.6.9' | |
| implementation 'org.slf4j:slf4j-api:1.7.30' | 19 | 19 | implementation 'org.slf4j:slf4j-api:1.7.30' | |
| 20 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9" | |||
| testCompile group: 'junit', name: 'junit', version: '4.12' | 20 | 21 | testCompile group: 'junit', name: 'junit', version: '4.12' | |
| testCompile group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3' | 21 | 22 | testCompile group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3' | |
| compile group: 'ch.qos.logback', name: 'logback-core', version: '1.2.3' | 22 | 23 | compile group: 'ch.qos.logback', name: 'logback-core', version: '1.2.3' | |
| compile 'com.github.jasrodis:javafx-dataviewer-wrapper:-SNAPSHOT' | 23 | 24 | compile 'com.github.jasrodis:javafx-dataviewer-wrapper:-SNAPSHOT' | |
| } | 24 | 25 | } | |
| 25 | 26 | |||
| task run(type: JavaExec) { | 26 | 27 | task run(type: JavaExec) { | |
| main = 'application.App' | 27 | 28 | main = 'application.App' | |
| classpath = sourceSets.main.runtimeClasspath | 28 | 29 | classpath = sourceSets.main.runtimeClasspath | |
| } | 29 | 30 | } | |
| 30 | 31 | |||
| compileKotlin { | 31 | 32 | compileKotlin { | 
src/main/kotlin/application/App.kt
View file @
e220e08
| @file:JvmName("App") | 1 | 1 | @file:JvmName("App") | |
| 2 | 2 | |||
| package application | 3 | 3 | package application | |
| 4 | 4 | |||
| import javafx.application.Application | 5 | 5 | import javafx.application.Application | |
| import javafx.application.Platform | 6 | 6 | import javafx.application.Platform | |
| import javafx.event.EventHandler | 7 | 7 | import javafx.event.EventHandler | |
| import javafx.fxml.FXMLLoader | 8 | 8 | import javafx.fxml.FXMLLoader | |
| import javafx.scene.Parent | 9 | 9 | import javafx.scene.Parent | |
| import javafx.scene.Scene | 10 | 10 | import javafx.scene.Scene | |
| import javafx.stage.Stage | 11 | 11 | import javafx.stage.Stage | |
| import jfxtras.styles.jmetro.JMetro | 12 | 12 | import jfxtras.styles.jmetro.JMetro | |
| import jfxtras.styles.jmetro.Style | 13 | 13 | import jfxtras.styles.jmetro.Style | |
| import kotlin.system.exitProcess | 14 | 14 | import kotlin.system.exitProcess | |
| 15 | 15 | |||
| class App : Application() { | 16 | 16 | class App : Application() { | |
| var style: Style = Style.LIGHT | 17 | 17 | var style: Style = Style.LIGHT | |
| 18 | 18 | |||
| override fun start(primaryStage: Stage?) { | 19 | 19 | override fun start(primaryStage: Stage?) { | |
| 20 | 20 | |||
| val fxmlLoader = FXMLLoader(App::class.java.getResource("/gui/windows.fxml")) | 21 | 21 | val fxmlLoader = FXMLLoader(App::class.java.getResource("/gui/windows.fxml")) | |
| val parent: Parent = fxmlLoader.load() | 22 | 22 | val parent: Parent = fxmlLoader.load() | |
| val scene = Scene(parent) | 23 | 23 | val scene = Scene(parent) | |
| JMetro(scene, style) | 24 | 24 | JMetro(scene, style) | |
| primaryStage!!.scene = scene | 25 | 25 | primaryStage!!.scene = scene | |
| primaryStage.title = "Maritime Visualisation" | 26 | 26 | primaryStage.title = "Maritime Visualisation" | |
| primaryStage.onCloseRequest = EventHandler { closeApplication() } | 27 | 27 | primaryStage.onCloseRequest = EventHandler { closeApplication() } | |
| primaryStage.show() | 28 | 28 | primaryStage.show() | |
| } | 29 | 29 | } | |
| 30 | 30 | |||
| private fun closeApplication() { | 31 | 31 | private fun closeApplication() { | |
| 32 | ||||
| Platform.exit() | 32 | 33 | Platform.exit() | |
| exitProcess(0) | 33 | 34 | exitProcess(0) | |
| } | 34 | 35 | } | |
| 35 | 36 | 
src/main/kotlin/application/controller/DataPanelController.kt
View file @
e220e08
| package application.controller | 1 | 1 | package application.controller | |
| 2 | 2 | |||
| import application.model.* | 3 | 3 | import application.model.* | |
| import javafx.collections.FXCollections | 4 | 4 | import javafx.collections.FXCollections | |
| import javafx.collections.ObservableList | 5 | 5 | import javafx.collections.ObservableList | |
| import javafx.fxml.FXML | 6 | 6 | import javafx.fxml.FXML | |
| import javafx.fxml.Initializable | 7 | 7 | import javafx.fxml.Initializable | |
| import javafx.scene.control.ListCell | 8 | 8 | import javafx.scene.control.ListCell | |
| import javafx.scene.control.ListView | 9 | 9 | import javafx.scene.control.ListView | |
| 10 | import kotlinx.coroutines.GlobalScope | |||
| 11 | import kotlinx.coroutines.launch | |||
| import org.charts.dataviewer.api.config.DataViewerConfiguration | 10 | 12 | import org.charts.dataviewer.api.config.DataViewerConfiguration | |
| import org.charts.dataviewer.api.data.PlotData | 11 | 13 | import org.charts.dataviewer.api.data.PlotData | |
| import org.charts.dataviewer.api.trace.ScatterTrace | 12 | 14 | import org.charts.dataviewer.api.trace.ScatterTrace | |
| import org.charts.dataviewer.javafx.JavaFxDataViewer | 13 | 15 | import org.charts.dataviewer.javafx.JavaFxDataViewer | |
| import org.charts.dataviewer.utils.TraceColour | 14 | 16 | import org.charts.dataviewer.utils.TraceColour | |
| import org.charts.dataviewer.utils.TraceVisibility | 15 | 17 | import org.charts.dataviewer.utils.TraceVisibility | |
| import java.net.URL | 16 | 18 | import java.net.URL | |
| import java.util.* | 17 | 19 | import java.util.* | |
| 18 | 20 | |||
| 19 | 21 | |||
| class DataPanelController : Initializable, SelectedVesselListener { | 20 | 22 | class DataPanelController : Initializable, SelectedVesselListener { | |
| private var dataList: ObservableList<Pair<String, ArrayList<MessageData?>>> = FXCollections.observableArrayList() | 21 | 23 | private var dataList: ObservableList<Pair<String, ArrayList<MessageData?>>> = FXCollections.observableArrayList() | |
| private lateinit var timeData: ArrayList<MessageData?> | 22 | 24 | private lateinit var timeData: ArrayList<MessageData?> | |
| 23 | 25 | |||
| 26 | private val latitude: ArrayList<MessageData?> = arrayListOf() | |||
| 27 | private val longitude: ArrayList<MessageData?> = arrayListOf() | |||
| 28 | private val speedOverGround: ArrayList<MessageData?> = arrayListOf() | |||
| 29 | private val courseOverGround: ArrayList<MessageData?> = arrayListOf() | |||
| 30 | private val heading: ArrayList<MessageData?> = arrayListOf() | |||
| 31 | private val vesselName: ArrayList<MessageData?> = arrayListOf() | |||
| 32 | private val imo: ArrayList<MessageData?> = arrayListOf() | |||
| 33 | private val callSign: ArrayList<MessageData?> = arrayListOf() | |||
| 34 | private val vesselType: ArrayList<MessageData?> = arrayListOf() | |||
| 35 | private val status: ArrayList<MessageData?> = arrayListOf() | |||
| 36 | private val length: ArrayList<MessageData?> = arrayListOf() | |||
| 37 | private val width: ArrayList<MessageData?> = arrayListOf() | |||
| 38 | private val draft: ArrayList<MessageData?> = arrayListOf() | |||
| 39 | private val cargo: ArrayList<MessageData?> = arrayListOf() | |||
| 24 | 40 | |||
| 41 | private var selectedItem: Pair<String, ArrayList<MessageData?>>? = null | |||
| 42 | ||||
| @FXML | 25 | 43 | @FXML | |
| var dataListView = ListView<Pair<String, ArrayList<MessageData?>>>() | 26 | 44 | var dataListView = ListView<Pair<String, ArrayList<MessageData?>>>() | |
| 27 | 45 | |||
| @FXML | 28 | 46 | @FXML | |
| var dataViewer = JavaFxDataViewer() | 29 | 47 | var dataViewer = JavaFxDataViewer() | |
| 30 | 48 | |||
| 49 | private val plotData = PlotData() | |||
| 50 | private val config = DataViewerConfiguration() | |||
| 31 | 51 | |||
| override fun initialize(location: URL?, resources: ResourceBundle?) { | 32 | 52 | override fun initialize(location: URL?, resources: ResourceBundle?) { | |
| setObservableSelectedVesselListener() | 33 | 53 | setObservableSelectedVesselListener() | |
| dataListView.items = dataList | 34 | 54 | dataListView.items = dataList | |
| 35 | 55 | |||
| 36 | 56 | |||
| val plotData = PlotData() | 37 | 57 | ||
| val config = DataViewerConfiguration() | 38 | |||
| config.showLegend(true) | 39 | 58 | config.showLegend(true) | |
| config.setLegendInsidePlot(false) | 40 | 59 | config.setLegendInsidePlot(false) | |
| 41 | 60 | |||
| 61 | setObservableCurrentTimeListener() | |||
| 62 | ||||
| dataListView.setCellFactory { | 42 | 63 | dataListView.setCellFactory { | |
| object : ListCell<Pair<String, ArrayList<MessageData?>>?>() { | 43 | 64 | object : ListCell<Pair<String, ArrayList<MessageData?>>?>() { | |
| override fun updateItem(item: Pair<String, ArrayList<MessageData?>>?, empty: Boolean) { | 44 | 65 | override fun updateItem(item: Pair<String, ArrayList<MessageData?>>?, empty: Boolean) { | |
| super.updateItem(item, empty) | 45 | 66 | super.updateItem(item, empty) | |
| text = if (empty) { | 46 | 67 | text = if (empty) { | |
| null | 47 | 68 | null | |
| } else { | 48 | 69 | } else { | |
| item?.first | 49 | 70 | item?.first | |
| } | 50 | 71 | } | |
| } | 51 | 72 | } | |
| } | 52 | 73 | } | |
| } | 53 | 74 | } | |
| 54 | 75 | |||
| dataListView.selectionModel.selectedItemProperty().addListener { _, _, newValue -> | 55 | 76 | dataListView.selectionModel.selectedItemProperty().addListener { _, _, newValue -> | |
| if (newValue == null) { | 56 | 77 | selectedItem = newValue | |
| plotData.allTraces.clear() | 57 | 78 | plot(newValue) | |
| config.setxAxisTitle("") | 58 | 79 | } | |
| config.setyAxisTitle("") | 59 | |||
| dataViewer.updateConfiguration(config) | 60 | |||
| 61 | 80 | |||
| dataViewer.resetPlot() | 62 | 81 | plotData.allTraces.clear() | |
| 82 | config.setxAxisTitle("") | |||
| 83 | config.setyAxisTitle("") | |||
| 84 | config.plotTitle = "" | |||
| 85 | dataViewer.updateConfiguration(config) | |||
| 86 | dataViewer.updatePlot(plotData) | |||
| 87 | initDataList() | |||
| 63 | 88 | |||
| return@addListener | 64 | 89 | ||
| 90 | } | |||
| 91 | ||||
| 92 | private fun plot() { | |||
| 93 | if (selectedItem != null) { | |||
| 94 | GlobalScope.launch { | |||
| 95 | plot(selectedItem) | |||
| } | 65 | 96 | } | |
| 97 | } | |||
| 98 | } | |||
| 66 | 99 | |||
| val getValueVisitorX = GetValueVisitor() | 67 | 100 | private fun plot(data: Pair<String, ArrayList<MessageData?>>?) { | |
| val getValueVisitorY = GetValueVisitor() | 68 | 101 | if (data == null) { | |
| 102 | plotData.allTraces.clear() | |||
| 103 | config.setxAxisTitle("") | |||
| 104 | config.setyAxisTitle("") | |||
| 105 | dataViewer.updateConfiguration(config) | |||
| 69 | 106 | |||
| val arrayListStringX = arrayListOf<String>() | 70 | 107 | dataViewer.resetPlot() | |
| val arrayListDoubleX = arrayListOf<Double>() | 71 | |||
| val arrayListStringY = arrayListOf<String>() | 72 | |||
| val arrayListDoubleY = arrayListOf<Double>() | 73 | |||
| 74 | 108 | |||
| for (x in 0 until newValue.second.size) { | 75 | 109 | return | |
| timeData[x]?.accept(getValueVisitorX) | 76 | 110 | } | |
| newValue.second[x]?.accept(getValueVisitorY) | 77 | |||
| 78 | 111 | |||
| if (getValueVisitorY.value.toDoubleOrNull() == null) { | 79 | 112 | val getValueVisitorX = GetValueVisitor() | |
| arrayListStringX.add(getValueVisitorX.value) | 80 | 113 | val getValueVisitorY = GetValueVisitor() | |
| arrayListStringY.add(getValueVisitorY.value) | 81 | |||
| } else { | 82 | |||
| arrayListStringX.add(getValueVisitorX.value) | 83 | |||
| arrayListDoubleY.add(getValueVisitorY.value.toDouble()) | 84 | |||
| } | 85 | |||
| } | 86 | |||
| 87 | 114 | |||
| val scatterTrace = ScatterTrace<Any>() | 88 | 115 | val arrayListStringX = arrayListOf<String>() | |
| scatterTrace.traceColour = TraceColour.RED | 89 | 116 | // val arrayListDoubleX = arrayListOf<Double>() | |
| scatterTrace.traceVisibility = TraceVisibility.TRUE | 90 | 117 | val arrayListStringY = arrayListOf<String>() | |
| 118 | val arrayListDoubleY = arrayListOf<Double>() | |||
| 91 | 119 | |||
| val serieStringX: Array<String> = arrayListStringX.toTypedArray() | 92 | 120 | for (x in 0 until timeData.size) { | |
| // val serieDoubleX: Array<Double> = arrayListDoubleX.toTypedArray() | 93 | 121 | timeData[x]?.accept(getValueVisitorX) | |
| val serieStringY: Array<String> = arrayListStringY.toTypedArray() | 94 | 122 | data.second[x]?.accept(getValueVisitorY) | |
| val serieDoubleY: Array<Double> = arrayListDoubleY.toTypedArray() | 95 | |||
| 96 | 123 | |||
| if (getValueVisitorY.value.toDoubleOrNull() == null) { | 97 | 124 | if (getValueVisitorY.value.toDoubleOrNull() == null) { | |
| scatterTrace.setxArray(serieStringX) | 98 | 125 | arrayListStringX.add(getValueVisitorX.value) | |
| scatterTrace.setyArray(serieStringY) | 99 | 126 | arrayListStringY.add(getValueVisitorY.value) | |
| } else { | 100 | 127 | } else { | |
| scatterTrace.setxArray(serieStringX) | 101 | 128 | arrayListStringX.add(getValueVisitorX.value) | |
| scatterTrace.setyArray(serieDoubleY) | 102 | 129 | arrayListDoubleY.add(getValueVisitorY.value.toDouble()) | |
| } | 103 | 130 | } | |
| 131 | } | |||
| 104 | 132 | |||
| config.plotTitle = "" | 105 | 133 | val scatterTrace = ScatterTrace<Any>() | |
| config.setxAxisTitle("Time (s)") | 106 | 134 | scatterTrace.traceColour = TraceColour.RED | |
| config.setyAxisTitle(newValue.first) | 107 | 135 | scatterTrace.traceVisibility = TraceVisibility.TRUE | |
| dataViewer.resetPlot() | 108 | |||
| plotData.allTraces.clear() | 109 | |||
| plotData.addTrace(scatterTrace) | 110 | |||
| dataViewer.updateConfiguration(config) | 111 | |||
| dataViewer.updatePlot(plotData) | 112 | |||
| 113 | 136 | |||
| 137 | val serieStringX: Array<String> = arrayListStringX.toTypedArray() | |||
| 138 | // val serieDoubleX: Array<Double> = arrayListDoubleX.toTypedArray() | |||
| 139 | val serieStringY: Array<String> = arrayListStringY.toTypedArray() | |||
| 140 | val serieDoubleY: Array<Double> = arrayListDoubleY.toTypedArray() | |||
| 141 | ||||
| 142 | if (getValueVisitorY.value.toDoubleOrNull() == null) { | |||
| 143 | scatterTrace.setxArray(serieStringX) | |||
| 144 | scatterTrace.setyArray(serieStringY) | |||
| 145 | } else { | |||
| 146 | scatterTrace.setxArray(serieStringX) | |||
| 147 | scatterTrace.setyArray(serieDoubleY) | |||
| } | 114 | 148 | } | |
| 115 | 149 | |||
| plotData.allTraces.clear() | 116 | |||
| config.setxAxisTitle("") | 117 | |||
| config.setyAxisTitle("") | 118 | |||
| config.plotTitle = "" | 119 | 150 | config.plotTitle = "" | |
| 151 | config.setxAxisTitle("Time (s)") | |||
| 152 | config.setyAxisTitle(data.first) | |||
| 153 | dataViewer.resetPlot() | |||
| 154 | plotData.allTraces.clear() | |||
| 155 | plotData.addTrace(scatterTrace) | |||
| dataViewer.updateConfiguration(config) | 120 | 156 | dataViewer.updateConfiguration(config) | |
| dataViewer.updatePlot(plotData) | 121 | 157 | dataViewer.updatePlot(plotData) | |
| 122 | 158 | |||
| } | 123 | 159 | } | |
| 124 | 160 | |||
| 161 | ||||
| private fun setObservableSelectedVesselListener() { | 125 | 162 | private fun setObservableSelectedVesselListener() { | |
| observableSelectedVessel.listeners.add(this) | 126 | 163 | observableSelectedVessel.listeners.add(this) | |
| } | 127 | 164 | } | |
| 128 | 165 | |||
| private fun populateTime(vessel: Vessel): ArrayList<MessageData?> { | 129 | 166 | private fun populateTime(vessel: Vessel): ArrayList<MessageData?> { | |
| val allTime: ArrayList<MessageData?> = vessel.getAllTime() | 130 | 167 | return if (observableIsReplayState.value) { | |
| allTime.sortBy { (it as Time).value } | 131 | 168 | vessel.getAllTimeBeforeSelectedTime() | |
| 132 | 169 | } else { | ||
| return allTime | 133 | 170 | vessel.getAllTime() | |
| 171 | } | |||
| } | 134 | 172 | } | |
| 135 | 173 | |||
| private fun populateLatitude(vessel: Vessel): ArrayList<MessageData?> { | 136 | |||
| val allLatitude: ArrayList<MessageData?> = vessel.getAllLatitude() | 137 | |||
| allLatitude.sortBy { (it as Latitude).value } | 138 | |||
| 139 | 174 | |||
| return allLatitude | 140 | 175 | private fun populateLatitude(vessel: Vessel): ArrayList<MessageData?> { | |
| 176 | return if (observableIsReplayState.value) { | |||
| 177 | vessel.getAllLatitudeBeforeSelectedTime() | |||
| 178 | } else { | |||
| 179 | vessel.getAllLatitude() | |||
| 180 | } | |||
| } | 141 | 181 | } | |
| 142 | 182 | |||
| private fun populateLongitude(vessel: Vessel): ArrayList<MessageData?> { | 143 | 183 | private fun populateLongitude(vessel: Vessel): ArrayList<MessageData?> { | |
| val allLongitude: ArrayList<MessageData?> = vessel.getAllLongitude() | 144 | 184 | return if (observableIsReplayState.value) { | |
| allLongitude.sortBy { (it as Longitude).value } | 145 | 185 | vessel.getAllLongitudeBeforeSelectedTime() | |
| 146 | 186 | } else { | ||
| return allLongitude | 147 | 187 | vessel.getAllLongitude() | |
| 188 | } | |||
| } | 148 | 189 | } | |
| 149 | 190 | |||
| private fun populateSpeedOverGround(vessel: Vessel): ArrayList<MessageData?> { | 150 | 191 | private fun populateSpeedOverGround(vessel: Vessel): ArrayList<MessageData?> { | |
| val allSpeedOverGround: ArrayList<MessageData?> = vessel.getAllSpeedOverGround() | 151 | 192 | return if (observableIsReplayState.value) { | |
| allSpeedOverGround.sortBy { (it as SpeedOverGround).value } | 152 | 193 | vessel.getAllSpeedOverGroundBeforeSelectedTime() | |
| 153 | 194 | } else { | ||
| return allSpeedOverGround | 154 | 195 | vessel.getAllSpeedOverGround() | |
| 196 | } | |||
| } | 155 | 197 | } | |
| 156 | 198 | |||
| private fun populateCourseOverGround(vessel: Vessel): ArrayList<MessageData?> { | 157 | 199 | private fun populateCourseOverGround(vessel: Vessel): ArrayList<MessageData?> { | |
| val allCourseOverGround: ArrayList<MessageData?> = vessel.getAllCourseOverGround() | 158 | 200 | return if (observableIsReplayState.value) { | |
| allCourseOverGround.sortBy { (it as CourseOverGround).value } | 159 | 201 | vessel.getAllCourseOverGroundBeforeSelectedTime() | |
| 160 | 202 | } else { | ||
| return allCourseOverGround | 161 | 203 | vessel.getAllCourseOverGround() | |
| 204 | } | |||
| } | 162 | 205 | } | |
| 163 | 206 | |||
| private fun populateHeading(vessel: Vessel): ArrayList<MessageData?> { | 164 | 207 | private fun populateHeading(vessel: Vessel): ArrayList<MessageData?> { | |
| val allHeading: ArrayList<MessageData?> = vessel.getAllHeading() | 165 | 208 | return if (observableIsReplayState.value) { | |
| allHeading.sortBy { (it as Heading).value } | 166 | 209 | vessel.getAllHeadingBeforeSelectedTime() | |
| 167 | 210 | } else { | ||
| return allHeading | 168 | 211 | vessel.getAllHeading() | |
| 212 | } | |||
| } | 169 | 213 | } | |
| 170 | 214 | |||
| private fun populateVesselName(vessel: Vessel): ArrayList<MessageData?> { | 171 | 215 | private fun populateVesselName(vessel: Vessel): ArrayList<MessageData?> { | |
| val allVesselName: ArrayList<MessageData?> = vessel.getAllVesselName() | 172 | 216 | return if (observableIsReplayState.value) { | |
| allVesselName.sortBy { (it as VesselName).value } | 173 | 217 | vessel.getAllVesselNameBeforeSelectedTime() | |
| 174 | 218 | } else { | ||
| return allVesselName | 175 | 219 | vessel.getAllVesselName() | |
| 220 | } | |||
| } | 176 | 221 | } | |
| 177 | 222 | |||
| private fun populateIMO(vessel: Vessel): ArrayList<MessageData?> { | 178 | 223 | private fun populateIMO(vessel: Vessel): ArrayList<MessageData?> { | |
| val allIMO: ArrayList<MessageData?> = vessel.getAllIMO() | 179 | 224 | return if (observableIsReplayState.value) { | |
| allIMO.sortBy { (it as IMO).value } | 180 | 225 | vessel.getAllIMOBeforeSelectedTime() | |
| 181 | 226 | } else { | ||
| return allIMO | 182 | 227 | vessel.getAllIMO() | |
| 228 | } | |||
| } | 183 | 229 | } | |
| 184 | 230 | |||
| private fun populateCallSign(vessel: Vessel): ArrayList<MessageData?> { | 185 | 231 | private fun populateCallSign(vessel: Vessel): ArrayList<MessageData?> { | |
| val allCallSign: ArrayList<MessageData?> = vessel.getAllCallSign() | 186 | 232 | return if (observableIsReplayState.value) { | |
| allCallSign.sortBy { (it as CallSign).value } | 187 | 233 | vessel.getAllCallSignBeforeSelectedTime() | |
| 188 | 234 | } else { | ||
| return allCallSign | 189 | 235 | vessel.getAllCallSign() | |
| 236 | } | |||
| } | 190 | 237 | } | |
| 191 | 238 | |||
| private fun populateVesselType(vessel: Vessel): ArrayList<MessageData?> { | 192 | 239 | private fun populateVesselType(vessel: Vessel): ArrayList<MessageData?> { | |
| val allVesselType: ArrayList<MessageData?> = vessel.getAllVesselType() | 193 | 240 | return if (observableIsReplayState.value) { | |
| allVesselType.sortBy { (it as VesselType).value } | 194 | 241 | vessel.getAllVesselTypeBeforeSelectedTime() | |
| 195 | 242 | } else { | ||
| return allVesselType | 196 | 243 | vessel.getAllVesselType() | |
| 244 | } | |||
| } | 197 | 245 | } | |
| 198 | 246 | |||
| private fun populateStatus(vessel: Vessel): ArrayList<MessageData?> { | 199 | 247 | private fun populateStatus(vessel: Vessel): ArrayList<MessageData?> { | |
| val allStatus: ArrayList<MessageData?> = vessel.getAllStatus() | 200 | 248 | return if (observableIsReplayState.value) { | |
| allStatus.sortBy { (it as Status).value } | 201 | 249 | vessel.getAllStatusBeforeSelectedTime() | |
| 202 | 250 | } else { | ||
| return allStatus | 203 | 251 | vessel.getAllStatus() | |
| 252 | } | |||
| } | 204 | 253 | } | |
| 205 | 254 | |||
| private fun populateLength(vessel: Vessel): ArrayList<MessageData?> { | 206 | 255 | private fun populateLength(vessel: Vessel): ArrayList<MessageData?> { | |
| val allLength: ArrayList<MessageData?> = vessel.getAllLength() | 207 | 256 | return if (observableIsReplayState.value) { | |
| allLength.sortBy { (it as Length).value } | 208 | 257 | vessel.getAllLengthBeforeSelectedTime() | |
| 209 | 258 | } else { | ||
| return allLength | 210 | 259 | vessel.getAllLength() | |
| 260 | } | |||
| } | 211 | 261 | } | |
| 212 | 262 | |||
| private fun populateWidth(vessel: Vessel): ArrayList<MessageData?> { | 213 | 263 | private fun populateWidth(vessel: Vessel): ArrayList<MessageData?> { | |
| val allWidth: ArrayList<MessageData?> = vessel.getAllWidth() | 214 | 264 | return if (observableIsReplayState.value) { | |
| allWidth.sortBy { (it as Width).value } | 215 | 265 | vessel.getAllWidthBeforeSelectedTime() | |
| 216 | 266 | } else { | ||
| return allWidth | 217 | 267 | vessel.getAllWidth() | |
| 268 | } | |||
| } | 218 | 269 | } | |
| 219 | 270 | |||
| private fun populateDraft(vessel: Vessel): ArrayList<MessageData?> { | 220 | 271 | private fun populateDraft(vessel: Vessel): ArrayList<MessageData?> { | |
| val allDraft: ArrayList<MessageData?> = vessel.getAllDraft() | 221 | 272 | return if (observableIsReplayState.value) { | |
| allDraft.sortBy { (it as Draft).value } | 222 | 273 | vessel.getAllDraftBeforeSelectedTime() | |
| 223 | 274 | } else { | ||
| return allDraft | 224 | 275 | vessel.getAllDraft() | |
| 276 | } | |||
| } | 225 | 277 | } | |
| 226 | 278 | |||
| private fun populateCargo(vessel: Vessel): ArrayList<MessageData?> { | 227 | 279 | private fun populateCargo(vessel: Vessel): ArrayList<MessageData?> { | |
| val allCargo: ArrayList<MessageData?> = vessel.getAllCargo() | 228 | 280 | return if (observableIsReplayState.value) { | |
| allCargo.sortBy { (it as Cargo).value } | 229 | 281 | vessel.getAllCargoBeforeSelectedTime() | |
| 230 | 282 | } else { | ||
| return allCargo | 231 | 283 | vessel.getAllCargo() | |
| 284 | } | |||
| } | 232 | 285 | } | |
| 233 | 286 | |||
| private fun populateDataList(vessel: Vessel) { | 234 | 287 | private fun initDataList() { | |
| val data = arrayListOf<Pair<String, ArrayList<MessageData?>>>() | 235 | 288 | val data = arrayListOf<Pair<String, ArrayList<MessageData?>>>() | |
| 236 | 289 | |||
| 290 | data.add(Pair("Latitude", latitude)) | |||
| 291 | data.add(Pair("Longitude", longitude)) | |||
| 292 | data.add(Pair("Speed Over Ground", speedOverGround)) | |||
| 293 | data.add(Pair("Course Over Ground", courseOverGround)) | |||
| 294 | data.add(Pair("Heading", heading)) | |||
| 295 | data.add(Pair("Vessel Name", vesselName)) | |||
| 296 | data.add(Pair("IMO", imo)) | |||
| 297 | data.add(Pair("Call Sign", callSign)) | |||
| 298 | data.add(Pair("Vessel Type", vesselType)) | |||
| 299 | data.add(Pair("Status", status)) | |||
| 300 | data.add(Pair("Length", length)) | |||
| 301 | data.add(Pair("Width", width)) | |||
| 302 | data.add(Pair("Draft", draft)) | |||
| 303 | data.add(Pair("Cargo", cargo)) | |||
| 304 | ||||
| 305 | dataList.addAll(data) | |||
| 306 | } | |||
| 307 | ||||
| 308 | private fun updateDataList(vessel: Vessel) { | |||
| timeData = populateTime(vessel) | 237 | 309 | timeData = populateTime(vessel) | |
| 238 | 310 | |||
| data.add(Pair("Latitude", populateLatitude(vessel))) | 239 | 311 | latitude.clear() | |
| 312 | latitude.addAll(populateLatitude(vessel)) | |||
| 240 | 313 | |||
| data.add(Pair("Longitude", populateLongitude(vessel))) | 241 | 314 | longitude.clear() | |
| 315 | longitude.addAll(populateLongitude(vessel)) | |||
| 242 | 316 | |||
| data.add(Pair("Speed Over Ground", populateSpeedOverGround(vessel))) | 243 | 317 | speedOverGround.clear() | |
| 318 | speedOverGround.addAll(populateSpeedOverGround(vessel)) | |||
| 244 | 319 | |||
| data.add(Pair("Course Over Ground", populateCourseOverGround(vessel))) | 245 | 320 | courseOverGround.clear() | |
| 321 | courseOverGround.addAll(populateCourseOverGround(vessel)) | |||
| 246 | 322 | |||
| data.add(Pair("Heading", populateHeading(vessel))) | 247 | 323 | heading.clear() | |
| 324 | heading.addAll(populateHeading(vessel)) | |||
| 248 | 325 | |||
| data.add(Pair("Vessel Name", populateVesselName(vessel))) | 249 | 326 | vesselName.clear() | |
| 327 | vesselName.addAll(populateVesselName(vessel)) | |||
| 250 | 328 | |||
| data.add(Pair("IMO", populateIMO(vessel))) | 251 | 329 | imo.clear() | |
| 330 | imo.addAll(populateIMO(vessel)) | |||
| 252 | 331 | |||
| data.add(Pair("Call Sign", populateCallSign(vessel))) | 253 | 332 | callSign.clear() | |
| 333 | callSign.addAll(populateCallSign(vessel)) | |||
| 254 | 334 | |||
| data.add(Pair("Vessel Type", populateVesselType(vessel))) | 255 | 335 | vesselType.clear() | |
| 336 | vesselType.addAll(populateVesselType(vessel)) | |||
| 256 | 337 | |||
| data.add(Pair("Status", populateStatus(vessel))) | 257 | 338 | status.clear() | |
| 339 | status.addAll(populateStatus(vessel)) | |||
| 258 | 340 | |||
| data.add(Pair("Length", populateLength(vessel))) | 259 | 341 | length.clear() | |
| 342 | length.addAll(populateLength(vessel)) | |||
| 260 | 343 | |||
| data.add(Pair("Width", populateWidth(vessel))) | 261 | 344 | width.clear() | |
| 345 | width.addAll(populateWidth(vessel)) | |||
| 262 | 346 | |||
| data.add(Pair("Draft", populateDraft(vessel))) | 263 | 347 | draft.clear() | |
| 348 | draft.addAll(populateDraft(vessel)) | |||
| 264 | 349 | |||
| data.add(Pair("Cargo", populateCargo(vessel))) | 265 | 350 | cargo.clear() | |
| 351 | cargo.addAll(populateCargo(vessel)) | |||
| 266 | 352 | |||
| dataList.addAll(data) | 267 | |||
| } | 268 | 353 | } | |
| 269 | 354 | |||
| override fun onValueChanged(newValue: Vessel) { | 270 | 355 | private fun setObservableCurrentTimeListener() { | |
| dataList.clear() | 271 | 356 | observableCurrentTime.listeners.add(object : CurrentTime { | |
| populateDataList(newValue) | 272 | 357 | override fun onValueChanged(newValue: Int) { | |
| 358 | updateDataList(observableSelectedVessel.value) | |||
| 359 | plot() | |||
| 360 | } | |||
| 361 | }) | |||
| 362 | } | |||
| 273 | 363 | |||
| 364 | override fun onValueChanged(newValue: Vessel) { | |||
| 365 | updateDataList(newValue) | |||
| 366 | plot() | |||
| } | 274 | 367 | } | |
| 275 | 368 | |||
| } | 276 | 369 | } | |
| 277 | 370 | |||
| 278 | 371 | |||
| 279 | 372 | |||
src/main/kotlin/application/controller/MapPanelController.kt
View file @
e220e08
| package application.controller | 1 | 1 | package application.controller | |
| 2 | 2 | |||
| import application.model.* | 3 | 3 | import application.model.* | |
| import application.model.MapState.* | 4 | 4 | import application.model.MapState.* | |
| 5 | import javafx.application.Platform | |||
| import javafx.fxml.FXML | 5 | 6 | import javafx.fxml.FXML | |
| import javafx.fxml.Initializable | 6 | 7 | import javafx.fxml.Initializable | |
| import javafx.scene.layout.StackPane | 7 | 8 | import javafx.scene.layout.StackPane | |
| import map.* | 8 | 9 | import map.* | |
| import java.net.URL | 9 | 10 | import java.net.URL | |
| import java.util.* | 10 | 11 | import java.util.* | |
| 11 | 12 | |||
| class MapPanelController : Initializable { | 12 | 13 | class MapPanelController : Initializable { | |
| 13 | 14 | |||
| @FXML | 14 | 15 | @FXML | |
| private lateinit var map: StackPane | 15 | 16 | private lateinit var map: StackPane | |
| 16 | 17 | |||
| private val mapView = LeafletMapView() | 17 | 18 | private val mapView = LeafletMapView() | |
| 18 | 19 | |||
| override fun initialize(location: URL?, resources: ResourceBundle?) { | 19 | 20 | override fun initialize(location: URL?, resources: ResourceBundle?) { | |
| mapView.displayMap(MapConfig()) | 20 | 21 | mapView.displayMap(MapConfig()) | |
| setObservableVesselListener() | 21 | 22 | setObservableVesselListener() | |
| setObservableSelectedVesselListener() | 22 | 23 | setObservableSelectedVesselListener() | |
| setStateListener() | 23 | 24 | setStateListener() | |
| setObservableIsReplayState() | 24 | 25 | setObservableIsReplayState() | |
| observableCurrentTime() | 25 | 26 | observableCurrentTime() | |
| 26 | 27 | |||
| map.children.add(mapView) | 27 | 28 | map.children.add(mapView) | |
| map.children | 28 | 29 | map.children | |
| } | 29 | 30 | } | |
| 30 | 31 | |||
| private fun setStateListener() { | 31 | 32 | private fun setStateListener() { | |
| observableMapState.listeners.add(object : StateListener { | 32 | 33 | observableMapState.listeners.add(object : StateListener { | |
| override fun onValueChanged(newValue: MapState) { | 33 | 34 | override fun onValueChanged(newValue: MapState) { | |
| if (observableSelectedVessel.value.mmsi != null) { | 34 | 35 | if (observableSelectedVessel.value.mmsi != null) { | |
| updateMap(observableSelectedVessel.value.mmsi!!) | 35 | 36 | updateMap(observableSelectedVessel.value.mmsi!!) | |
| } else { | 36 | 37 | } else { | |
| updateMap() | 37 | 38 | updateMap() | |
| } | 38 | 39 | } | |
| } | 39 | 40 | } | |
| }) | 40 | 41 | }) | |
| } | 41 | 42 | } | |
| 42 | 43 | |||
| private fun observableCurrentTime() { | 43 | 44 | private fun observableCurrentTime() { | |
| observableCurrentTime.listeners.add(object : CurrentTime { | 44 | 45 | observableCurrentTime.listeners.add(object : CurrentTime { | |
| override fun onValueChanged(newValue: Int) { | 45 | 46 | override fun onValueChanged(newValue: Int) { | |
| if (observableSelectedVessel.value.mmsi != null) { | 46 | 47 | if (observableSelectedVessel.value.mmsi != null) { | |
| updateMap(observableSelectedVessel.value.mmsi!!) | 47 | 48 | updateMap(observableSelectedVessel.value.mmsi!!) | |
| } else { | 48 | 49 | } else { | |
| updateMap() | 49 | 50 | updateMap() | |
| } | 50 | 51 | } | |
| } | 51 | 52 | } | |
| }) | 52 | 53 | }) | |
| } | 53 | 54 | } | |
| 54 | 55 | |||
| private fun updateMap() { | 55 | 56 | private fun updateMap() { | |
| if (observableIsReplayState.value) { | 56 | 57 | Platform.runLater { | |
| when (observableMapState.state) { | 57 | 58 | if (observableIsReplayState.value) { | |
| ALL_MESSAGES -> displayTimedAllMessageOnMap(mapView) | 58 | 59 | when (observableMapState.state) { | |
| CLUSTERED_MESSAGES -> displayTimedClusterMessageOnMap(mapView) | 59 | 60 | ALL_MESSAGES -> displayTimedAllMessageOnMap(mapView) | |
| HEAT_MAP -> displayTimedHeatMapOnMap(mapView) | 60 | 61 | CLUSTERED_MESSAGES -> displayTimedClusterMessageOnMap(mapView) | |
| 62 | HEAT_MAP -> displayTimedHeatMapOnMap(mapView) | |||
| 63 | } | |||
| 64 | } else { | |||
| 65 | when (observableMapState.state) { | |||
| 66 | ALL_MESSAGES -> displayAllMessageOnMap(mapView) | |||
| 67 | CLUSTERED_MESSAGES -> displayClusterMessageOnMap(mapView) | |||
| 68 | HEAT_MAP -> displayHeatMapOnMap(mapView) | |||
| 69 | } | |||
| } | 61 | 70 | } | |
| } else { | 62 | |||
| when (observableMapState.state) { | 63 | |||
| ALL_MESSAGES -> displayAllMessageOnMap(mapView) | 64 | |||
| CLUSTERED_MESSAGES -> displayClusterMessageOnMap(mapView) | 65 | |||
| HEAT_MAP -> displayHeatMapOnMap(mapView) | 66 | |||
| } | 67 | |||
| } | 68 | 71 | } | |
| } | 69 | 72 | } | |
| 70 | 73 | |||
| private fun updateMap(selectedMMSI: String) { | 71 | 74 | private fun updateMap(selectedMMSI: String) { | |
| if (observableIsReplayState.value) { | 72 | 75 | Platform.runLater { | |
| when (observableMapState.state) { | 73 | 76 | if (observableIsReplayState.value) { | |
| ALL_MESSAGES -> displayTimedAllMessageOnMap(mapView, selectedMMSI) | 74 | 77 | when (observableMapState.state) { | |
| CLUSTERED_MESSAGES -> displayTimedClusterMessageOnMap(mapView, selectedMMSI) | 75 | 78 | ALL_MESSAGES -> displayTimedAllMessageOnMap(mapView, selectedMMSI) | |
| HEAT_MAP -> displayTimedHeatMapOnMap(mapView, selectedMMSI) | 76 | 79 | CLUSTERED_MESSAGES -> displayTimedClusterMessageOnMap(mapView, selectedMMSI) | |
| 80 | HEAT_MAP -> displayTimedHeatMapOnMap(mapView, selectedMMSI) | |||
| 81 | } | |||
| 82 | } else { | |||
| 83 | when (observableMapState.state) { | |||
| 84 | ALL_MESSAGES -> displayAllMessageOnMap(mapView, selectedMMSI) | |||
| 85 | CLUSTERED_MESSAGES -> displayClusterMessageOnMap(mapView, selectedMMSI) | |||
| 86 | HEAT_MAP -> displayHeatMapOnMap(mapView, selectedMMSI) | |||
| 87 | } | |||
| } | 77 | 88 | } | |
| } else { | 78 | |||
| when (observableMapState.state) { | 79 | |||
| ALL_MESSAGES -> displayAllMessageOnMap(mapView, selectedMMSI) | 80 | |||
| CLUSTERED_MESSAGES -> displayClusterMessageOnMap(mapView, selectedMMSI) | 81 | |||
| HEAT_MAP -> displayHeatMapOnMap(mapView, selectedMMSI) | 82 | |||
| } | 83 | |||
| } | 84 | 89 | } | |
| } | 85 | 90 | } | |
| 86 | 91 | |||
| private fun setObservableVesselListener() { | 87 | 92 | private fun setObservableVesselListener() { | |
| observableVessel.listeners.add(object : MessageListener { | 88 | 93 | observableVessel.listeners.add(object : MessageListener { | |
| override fun onValueChanged(newValue: MutableMap<String?, Vessel>) { | 89 | 94 | override fun onValueChanged(newValue: MutableMap<String?, Vessel>) { | |
| updateMap() | 90 | 95 | updateMap() | |
| } | 91 | 96 | } | |
| }) | 92 | 97 | }) | |
| } | 93 | 98 | } | |
| 94 | 99 | |||
| private fun setObservableIsReplayState() { | 95 | 100 | private fun setObservableIsReplayState() { | |
| observableIsReplayState.listeners.add(object: ReplayState { | 96 | 101 | observableIsReplayState.listeners.add(object : ReplayState { | |
| override fun onValueChanged(newValue: Boolean) { | 97 | 102 | override fun onValueChanged(newValue: Boolean) { | |
| if (observableSelectedVessel.value.mmsi != null) { | 98 | 103 | if (observableSelectedVessel.value.mmsi != null) { | |
| updateMap(observableSelectedVessel.value.mmsi!!) | 99 | 104 | updateMap(observableSelectedVessel.value.mmsi!!) | |
| } else { | 100 | 105 | } else { | |
| updateMap() | 101 | 106 | updateMap() | |
| } | 102 | 107 | } | |
| } | 103 | 108 | } | |
| }) | 104 | 109 | }) | |
| } | 105 | 110 | } | |
| 106 | 111 | |||
| private fun setObservableSelectedVesselListener() { | 107 | 112 | private fun setObservableSelectedVesselListener() { | |
| observableSelectedVessel.listeners.add(object : SelectedVesselListener { | 108 | 113 | observableSelectedVessel.listeners.add(object : SelectedVesselListener { | |
| override fun onValueChanged(newValue: Vessel) { | 109 | 114 | override fun onValueChanged(newValue: Vessel) { | |
| if (newValue.mmsi != null) { | 110 | 115 | if (newValue.mmsi != null) { | |
| updateMap(newValue.mmsi) | 111 | 116 | updateMap(newValue.mmsi) | |
| } else { | 112 | 117 | } else { | |
| updateMap() | 113 | 118 | updateMap() | |
| } | 114 | 119 | } | |
| } | 115 | 120 | } | |
| }) | 116 | 121 | }) | 
src/main/kotlin/application/controller/TimePanel.kt
View file @
e220e08
| package application.controller | 1 | 1 | package application.controller | |
| 2 | 2 | |||
| import application.model.* | 3 | 3 | import application.model.* | |
| import javafx.fxml.FXML | 4 | 4 | import javafx.fxml.FXML | |
| import javafx.fxml.Initializable | 5 | 5 | import javafx.fxml.Initializable | |
| import javafx.scene.control.Button | 6 | 6 | import javafx.scene.control.Button | |
| import javafx.scene.control.Slider | 7 | 7 | import javafx.scene.control.Slider | |
| import java.net.URL | 8 | 8 | import java.net.URL | |
| import java.util.* | 9 | 9 | import java.util.* | |
| 10 | 10 | |||
| 11 | 11 | |||
| class TimePanel : Initializable { | 12 | 12 | class TimePanel : Initializable { | |
| 13 | 13 | |||
| @FXML | 14 | 14 | @FXML | |
| var timeSlider = Slider() | 15 | 15 | var timeSlider = Slider() | |
| 16 | 16 | |||
| @FXML | 17 | 17 | @FXML | |
| var timeStop = Button() | 18 | 18 | var timeStop = Button() | |
| 19 | 19 | |||
| @FXML | 20 | 20 | @FXML | |
| var timePlay = Button() | 21 | 21 | var timePlay = Button() | |
| 22 | 22 | |||
| 23 | 23 | |||
| override fun initialize(location: URL?, resources: ResourceBundle?) { | 24 | 24 | override fun initialize(location: URL?, resources: ResourceBundle?) { | |
| setSliderMinMax() | 25 | 25 | setSliderMinMax() | |
| setSliderListener() | 26 | 26 | setSliderListener() | |
| disableAllButton() | 27 | 27 | disableAllButton() | |
| setDisable() | 28 | 28 | setDisable() | |
| } | 29 | 29 | } | |
| 30 | 30 | |||
| private fun setSliderMinMax() { | 31 | 31 | private fun setSliderMinMax() { | |
| timeSlider.min = 0.0 | 32 | 32 | timeSlider.min = 0.0 | |
| timeSlider.max = 0.0 | 33 | 33 | timeSlider.max = 0.0 | |
| observableVessel.listeners.add(object : MessageListener { | 34 | 34 | observableVessel.listeners.add(object : MessageListener { | |
| override fun onValueChanged(newValue: MutableMap<String?, Vessel>) { | 35 | 35 | override fun onValueChanged(newValue: MutableMap<String?, Vessel>) { | |
| timeSlider.max = Vessel.maxTime.toDouble() | 36 | 36 | timeSlider.max = Vessel.maxTime.toDouble() | |
| timeSlider.min = Vessel.minTime.toDouble() | 37 | 37 | timeSlider.min = Vessel.minTime.toDouble() | |
| } | 38 | 38 | } | |
| }) | 39 | 39 | }) | |
| } | 40 | 40 | } | |
| 41 | 41 | |||
| private fun setSliderListener() { | 42 | 42 | private fun setSliderListener() { | |
| timeSlider.valueProperty().addListener { _, _, newValue -> | 43 | 43 | timeSlider.valueProperty().addListener { _, _, newValue -> | |
| observableCurrentTime.value = newValue.toInt() | 44 | 44 | observableCurrentTime.value = newValue.toInt() | |
| } | 45 | 45 | } | |
| } | 46 | 46 | } | |
| 47 | 47 | |||
| private fun disableAllButton() { | 48 | 48 | private fun disableAllButton() { | |
| timeStop.isDisable = true | 49 | 49 | timeStop.isDisable = true | |
| timeSlider.isDisable = true | 50 | 50 | timeSlider.isDisable = true | |
| timePlay.isDisable = true | 51 | 51 | timePlay.isDisable = true | |
| } | 52 | 52 | } | |
| 53 | 53 | |||
| private fun unableAllButton() { | 54 | 54 | private fun unableAllButton() { | |
| timeStop.isDisable = false | 55 | 55 | timeStop.isDisable = false | |
| timeSlider.isDisable = false | 56 | 56 | timeSlider.isDisable = false | |
| timePlay.isDisable = false | 57 | 57 | timePlay.isDisable = false | |
| } | 58 | 58 | } | |
| 59 | 59 | |||
| private fun setDisable() { | 60 | 60 | private fun setDisable() { | 
src/main/kotlin/application/model/ObservableCurrentTime.kt
View file @
e220e08
| package application.model | 1 | 1 | package application.model | |
| 2 | 2 | |||
| import kotlin.properties.Delegates | 3 | 3 | import kotlin.properties.Delegates | |
| 4 | 4 | |||
| class ObservableCurrentTime { | 5 | 5 | class ObservableCurrentTime { | |
| 6 | 6 | |||
| val listeners: MutableList<CurrentTime> = mutableListOf() | 7 | 7 | val listeners: MutableList<CurrentTime> = mutableListOf() | |
| 8 | 8 | |||
| var value: Int by Delegates.observable( | 9 | 9 | var value: Int by Delegates.observable( | |
| initialValue = 0, | 10 | 10 | initialValue = Int.MAX_VALUE, | |
| onChange = { _, _, new -> | 11 | 11 | onChange = { _, _, new -> | |
| run { | 12 | 12 | run { | |
| listeners.forEach { | 13 | 13 | listeners.forEach { | |
| it.onValueChanged(new) | 14 | 14 | it.onValueChanged(new) | |
| } | 15 | 15 | } | |
| } | 16 | 16 | } | 
src/main/kotlin/application/model/Vessel.kt
View file @
e220e08
| package application.model | 1 | 1 | package application.model | |
| 2 | 2 | |||
| import java.util.* | 3 | 3 | import java.util.* | |
| 4 | 4 | |||
| 5 | ||||
| class Vessel(val mmsi: String?) { | 6 | 5 | class Vessel(val mmsi: String?) { | |
| val messages: SortedMap<Long, Message> = sortedMapOf() | 7 | 6 | val messages: SortedMap<Long, Message> = sortedMapOf() | |
| 7 | private val messageBeforeSelectedTime: Map<Long, Message> | |||
| 8 | get() { | |||
| 9 | return messages.filter { observableCurrentTime.value > it.key } | |||
| 10 | } | |||
| 11 | ||||
| var messageToDisplay: Message? = null | 8 | 12 | var messageToDisplay: Message? = null | |
| get() { | 9 | 13 | get() { | |
| field = | 10 | 14 | field = | |
| messages.asSequence().map { it }.firstOrNull { observableCurrentTime.value < it.key }.let { it?.value } | 11 | 15 | messages.asSequence().map { it }.firstOrNull { observableCurrentTime.value < it.key }.let { it?.value } | |
| return field | 12 | 16 | return field | |
| } | 13 | 17 | } | |
| 18 | ||||
| 19 | fun getAllTimeBeforeSelectedTime(): ArrayList<MessageData?> { | |||
| 20 | val timeList = arrayListOf<MessageData?>() | |||
| 21 | messageBeforeSelectedTime.forEach { | |||
| 22 | timeList.add(it.value.time) | |||
| 23 | } | |||
| 24 | ||||
| 25 | return timeList | |||
| 26 | } | |||
| 27 | ||||
| 28 | fun getAllLatitudeBeforeSelectedTime(): ArrayList<MessageData?> { | |||
| 29 | val latitudeList = arrayListOf<MessageData?>() | |||
| 30 | messageBeforeSelectedTime.forEach { | |||
| 31 | latitudeList.add(it.value.latitude) | |||
| 32 | } | |||
| 33 | ||||
| 34 | return latitudeList | |||
| 35 | } | |||
| 36 | ||||
| 37 | fun getAllLongitudeBeforeSelectedTime(): ArrayList<MessageData?> { | |||
| 38 | val longitudeList = arrayListOf<MessageData?>() | |||
| 39 | messageBeforeSelectedTime.forEach { | |||
| 40 | longitudeList.add(it.value.longitude) | |||
| 41 | } | |||
| 42 | ||||
| 43 | return longitudeList | |||
| 44 | } | |||
| 45 | ||||
| 46 | fun getAllSpeedOverGroundBeforeSelectedTime(): ArrayList<MessageData?> { | |||
| 47 | val speedOverGroundList = arrayListOf<MessageData?>() | |||
| 48 | messageBeforeSelectedTime.forEach { | |||
| 49 | speedOverGroundList.add(it.value.speedOverGround) | |||
| 50 | } | |||
| 51 | ||||
| 52 | return speedOverGroundList | |||
| 53 | } | |||
| 54 | ||||
| 55 | fun getAllCourseOverGroundBeforeSelectedTime(): ArrayList<MessageData?> { | |||
| 56 | val res = arrayListOf<MessageData?>() | |||
| 57 | messageBeforeSelectedTime.forEach { | |||
| 58 | res.add(it.value.courseOverGround) | |||
| 59 | } | |||
| 60 | ||||
| 61 | return res | |||
| 62 | } | |||
| 63 | ||||
| 64 | fun getAllHeadingBeforeSelectedTime(): ArrayList<MessageData?> { | |||
| 65 | val res = arrayListOf<MessageData?>() | |||
| 66 | messageBeforeSelectedTime.forEach { | |||
| 67 | res.add(it.value.heading) | |||
| 68 | } | |||
| 69 | ||||
| 70 | return res | |||
| 71 | } | |||
| 72 | ||||
| 73 | fun getAllVesselNameBeforeSelectedTime(): ArrayList<MessageData?> { | |||
| 74 | val res = arrayListOf<MessageData?>() | |||
| 75 | messageBeforeSelectedTime.forEach { | |||
| 76 | res.add(it.value.vesselName) | |||
| 77 | } | |||
| 78 | return res | |||
| 79 | } | |||
| 80 | ||||
| 81 | fun getAllIMOBeforeSelectedTime(): ArrayList<MessageData?> { | |||
| 82 | val res = arrayListOf<MessageData?>() | |||
| 83 | messageBeforeSelectedTime.forEach { | |||
| 84 | res.add(it.value.imo) | |||
| 85 | } | |||
| 86 | return res | |||
| 87 | } | |||
| 88 | ||||
| 89 | fun getAllCallSignBeforeSelectedTime(): ArrayList<MessageData?> { | |||
| 90 | val res = arrayListOf<MessageData?>() | |||
| 91 | messageBeforeSelectedTime.forEach { | |||
| 92 | res.add(it.value.callSign) | |||
| 93 | } | |||
| 94 | return res | |||
| 95 | } | |||
| 96 | ||||
| 97 | fun getAllVesselTypeBeforeSelectedTime(): ArrayList<MessageData?> { | |||
| 98 | val res = arrayListOf<MessageData?>() | |||
| 99 | messageBeforeSelectedTime.forEach { | |||
| 100 | res.add(it.value.vesselType) | |||
| 101 | } | |||
| 102 | return res | |||
| 103 | } | |||
| 104 | ||||
| 105 | fun getAllStatusBeforeSelectedTime(): ArrayList<MessageData?> { | |||
| 106 | val res = arrayListOf<MessageData?>() | |||
| 107 | messageBeforeSelectedTime.forEach { | |||
| 108 | res.add(it.value.status) | |||
| 109 | } | |||
| 110 | return res | |||
| 111 | } | |||
| 112 | ||||
| 113 | fun getAllLengthBeforeSelectedTime(): ArrayList<MessageData?> { | |||
| 114 | val res = arrayListOf<MessageData?>() | |||
| 115 | messageBeforeSelectedTime.forEach { | |||
| 116 | res.add(it.value.length) | |||
| 117 | } | |||
| 118 | return res | |||
| 119 | } | |||
| 120 | ||||
| 121 | fun getAllWidthBeforeSelectedTime(): ArrayList<MessageData?> { | |||
| 122 | val res = arrayListOf<MessageData?>() | |||
| 123 | messageBeforeSelectedTime.forEach { | |||
| 124 | res.add(it.value.width) | |||
| 125 | } | |||
| 126 | return res | |||
| 127 | } | |||
| 128 | ||||
| 129 | fun getAllDraftBeforeSelectedTime(): ArrayList<MessageData?> { | |||
| 130 | val res = arrayListOf<MessageData?>() | |||
| 131 | messageBeforeSelectedTime.forEach { | |||
| 132 | res.add(it.value.draft) | |||
| 133 | } | |||
| 134 | return res | |||
| 135 | } | |||
| 136 | ||||
| 137 | fun getAllCargoBeforeSelectedTime(): ArrayList<MessageData?> { | |||
| 138 | val res = arrayListOf<MessageData?>() | |||
| 139 | messageBeforeSelectedTime.forEach { | |||
| 140 | res.add(it.value.cargo) | |||
| 141 | } | |||
| 142 | return res | |||
| 143 | } | |||
| 14 | 144 | |||
| fun getAllTime(): ArrayList<MessageData?> { | 15 | 145 | fun getAllTime(): ArrayList<MessageData?> { | |
| val timeList = arrayListOf<MessageData?>() | 16 | 146 | val timeList = arrayListOf<MessageData?>() | |
| messages.forEach { | 17 | 147 | messages.forEach { | |
| timeList.add(it.value.time) | 18 | 148 | timeList.add(it.value.time) | |
| } | 19 | 149 | } | |
| 20 | 150 | |||
| return timeList | 21 | 151 | return timeList | |
| } | 22 | 152 | } | |
| 23 | 153 | |||
| fun getAllLatitude(): ArrayList<MessageData?> { | 24 | 154 | fun getAllLatitude(): ArrayList<MessageData?> { | |
| val latitudeList = arrayListOf<MessageData?>() | 25 | 155 | val latitudeList = arrayListOf<MessageData?>() | |
| messages.forEach { | 26 | 156 | messages.forEach { | |
| latitudeList.add(it.value.latitude) | 27 | 157 | latitudeList.add(it.value.latitude) | |
| } | 28 | 158 | } | |
| 29 | 159 | |||
| return latitudeList | 30 | 160 | return latitudeList | |
| } | 31 | 161 | } | |
| 32 | 162 | |||
| fun getAllLongitude(): ArrayList<MessageData?> { | 33 | 163 | fun getAllLongitude(): ArrayList<MessageData?> { | |
| val longitudeList = arrayListOf<MessageData?>() | 34 | 164 | val longitudeList = arrayListOf<MessageData?>() | |
| messages.forEach { | 35 | 165 | messages.forEach { | |
| longitudeList.add(it.value.longitude) | 36 | 166 | longitudeList.add(it.value.longitude) | |
| } | 37 | 167 | } | |
| 38 | 168 | |||
| return longitudeList | 39 | 169 | return longitudeList | |
| } | 40 | 170 | } | |
| 41 | 171 | |||
| fun getAllSpeedOverGround(): ArrayList<MessageData?> { | 42 | 172 | fun getAllSpeedOverGround(): ArrayList<MessageData?> { | |
| val speedOverGroundList = arrayListOf<MessageData?>() | 43 | 173 | val speedOverGroundList = arrayListOf<MessageData?>() | |
| messages.forEach { | 44 | 174 | messages.forEach { | |
| speedOverGroundList.add(it.value.speedOverGround) | 45 | 175 | speedOverGroundList.add(it.value.speedOverGround) | |
| } | 46 | 176 | } | |
| 47 | 177 | |||
| return speedOverGroundList | 48 | 178 | return speedOverGroundList | |
| } | 49 | 179 | } | |
| 50 | 180 | |||
| fun getAllCourseOverGround(): ArrayList<MessageData?> { | 51 | 181 | fun getAllCourseOverGround(): ArrayList<MessageData?> { | |
| val res = arrayListOf<MessageData?>() | 52 | 182 | val res = arrayListOf<MessageData?>() | |
| messages.forEach { | 53 | 183 | messages.forEach { | |
| res.add(it.value.courseOverGround) | 54 | 184 | res.add(it.value.courseOverGround) | |
| } | 55 | 185 | } | |
| 56 | 186 | |||
| return res | 57 | 187 | return res | |
| } | 58 | 188 | } | |
| 59 | 189 | |||
| fun getAllHeading(): ArrayList<MessageData?> { | 60 | 190 | fun getAllHeading(): ArrayList<MessageData?> { | |
| val res = arrayListOf<MessageData?>() | 61 | 191 | val res = arrayListOf<MessageData?>() | |
| messages.forEach { | 62 | 192 | messages.forEach { | |
| res.add(it.value.heading) | 63 | 193 | res.add(it.value.heading) | |
| } | 64 | 194 | } | |
| 65 | 195 | |||
| return res | 66 | 196 | return res | |
| } | 67 | 197 | } | |
| 68 | 198 | |||
| fun getAllVesselName(): ArrayList<MessageData?> { | 69 | 199 | fun getAllVesselName(): ArrayList<MessageData?> { | |
| val res = arrayListOf<MessageData?>() | 70 | 200 | val res = arrayListOf<MessageData?>() | |
| messages.forEach { | 71 | 201 | messages.forEach { | |
| res.add(it.value.vesselName) | 72 | 202 | res.add(it.value.vesselName) | |
| } | 73 | 203 | } | |
| return res | 74 | 204 | return res | |
| } | 75 | 205 | } | |
| 76 | 206 | |||
| fun getAllIMO(): ArrayList<MessageData?> { | 77 | 207 | fun getAllIMO(): ArrayList<MessageData?> { | |
| val res = arrayListOf<MessageData?>() | 78 | 208 | val res = arrayListOf<MessageData?>() | |
| messages.forEach { | 79 | 209 | messages.forEach { | |
| res.add(it.value.imo) | 80 | 210 | res.add(it.value.imo) | |
| } | 81 | 211 | } | |
| return res | 82 | 212 | return res | |
| } | 83 | 213 | } | |
| 84 | 214 | |||
| fun getAllCallSign(): ArrayList<MessageData?> { | 85 | 215 | fun getAllCallSign(): ArrayList<MessageData?> { | |
| val res = arrayListOf<MessageData?>() | 86 | 216 | val res = arrayListOf<MessageData?>() | |
| messages.forEach { | 87 | 217 | messages.forEach { | |
| res.add(it.value.callSign) | 88 | 218 | res.add(it.value.callSign) | |
| } | 89 | 219 | } | |
| return res | 90 | 220 | return res | |
| } | 91 | 221 | } | |
| 92 | 222 | |||
| fun getAllVesselType(): ArrayList<MessageData?> { | 93 | 223 | fun getAllVesselType(): ArrayList<MessageData?> { | |
| val res = arrayListOf<MessageData?>() | 94 | 224 | val res = arrayListOf<MessageData?>() | |
| messages.forEach { | 95 | 225 | messages.forEach { | |
| res.add(it.value.vesselType) | 96 | 226 | res.add(it.value.vesselType) | |
| } | 97 | 227 | } | |
| return res | 98 | 228 | return res | |
| } | 99 | 229 | } | |
| 100 | 230 | |||
| fun getAllStatus(): ArrayList<MessageData?> { | 101 | 231 | fun getAllStatus(): ArrayList<MessageData?> { | |
| val res = arrayListOf<MessageData?>() | 102 | 232 | val res = arrayListOf<MessageData?>() | |
| messages.forEach { | 103 | 233 | messages.forEach { | |
| res.add(it.value.status) | 104 | 234 | res.add(it.value.status) | |
| } | 105 | 235 | } | |
| return res | 106 | 236 | return res | |
| } | 107 | 237 | } | |
| 108 | 238 | |||
| fun getAllLength(): ArrayList<MessageData?> { | 109 | 239 | fun getAllLength(): ArrayList<MessageData?> { | |
| val res = arrayListOf<MessageData?>() | 110 | 240 | val res = arrayListOf<MessageData?>() | |
| messages.forEach { | 111 | 241 | messages.forEach { | |
| res.add(it.value.length) | 112 | 242 | res.add(it.value.length) | |
| } | 113 | 243 | } | |
| return res | 114 | 244 | return res | |
| } | 115 | 245 | } | |
| 116 | 246 | |||
| fun getAllWidth(): ArrayList<MessageData?> { | 117 | 247 | fun getAllWidth(): ArrayList<MessageData?> { | |
| val res = arrayListOf<MessageData?>() | 118 | 248 | val res = arrayListOf<MessageData?>() | |
| messages.forEach { | 119 | 249 | messages.forEach { | |
| res.add(it.value.width) | 120 | 250 | res.add(it.value.width) | 
src/main/resources/gui/timePanel.fxml
View file @
e220e08
| <?xml version="1.0" encoding="UTF-8"?> | 1 | 1 | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | 2 | |||
| <?import javafx.geometry.*?> | 3 | 3 | <?import javafx.geometry.*?> | |
| <?import javafx.scene.control.*?> | 4 | 4 | <?import javafx.scene.control.*?> | |
| <?import javafx.scene.layout.*?> | 5 | 5 | <?import javafx.scene.layout.*?> | |
| 6 | 6 | |||
| <HBox alignment="CENTER" prefHeight="65.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller.TimePanel"> | 7 | 7 | <HBox alignment="CENTER" prefHeight="65.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller.TimePanel"> | |
| <children> | 8 | 8 | <children> | |
| <Button fx:id="timePlay" alignment="CENTER" mnemonicParsing="false" text="Play"> | 9 | 9 | <Slider fx:id="timeSlider" prefHeight="14.0" prefWidth="538.0"> | |
| <HBox.margin> | 10 | |||
| <Insets left="5.0" right="5.0" /> | 11 | |||
| </HBox.margin></Button> | 12 | |||
| <Button fx:id="timeStop" mnemonicParsing="false" text="Stop"> | 13 | |||
| <HBox.margin> | 14 | |||
| <Insets left="5.0" right="5.0" /> | 15 | |||
| </HBox.margin></Button> | 16 | |||
| <Slider fx:id="timeSlider" prefHeight="14.0" prefWidth="475.0"> | 17 | |||
| <HBox.margin> | 18 | 10 | <HBox.margin> | |
| <Insets left="5.0" right="5.0" /> | 19 | 11 | <Insets left="5.0" right="5.0" /> | |
| </HBox.margin></Slider> | 20 | 12 | </HBox.margin></Slider> | |
| </children> | 21 | 13 | </children> |