Commit a6a8df6ff5be1e08eddb715734fc61cd03bce8b0

Authored by lsagona
1 parent df68a9fdcc
Exists in master and in 1 other branch dev

add the possibility to search an MMSI

Showing 8 changed files with 31 additions and 27 deletions Inline Diff

src/main/kotlin/application/App.kt View file @ a6a8df6
@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
16
class App : Application() { 16 17 class App : Application() {
var style: Style = Style.LIGHT 17 18 var style: Style = Style.LIGHT
18 19
override fun start(primaryStage: Stage?) { 19 20 override fun start(primaryStage: Stage?) {
20 21
val fxmlLoader = FXMLLoader(App::class.java.getResource("/gui/windows.fxml")) 21 22 val fxmlLoader = FXMLLoader(App::class.java.getResource("/gui/windows.fxml"))
val parent: Parent = fxmlLoader.load() 22 23 val parent: Parent = fxmlLoader.load()
val scene = Scene(parent) 23 24 val scene = Scene(parent)
JMetro(scene, style) 24 25 JMetro(scene, style)
primaryStage!!.scene = scene 25 26 primaryStage!!.scene = scene
primaryStage.title = "Maritime Visualisation" 26 27 primaryStage.title = "Maritime Visualisation"
primaryStage.onCloseRequest = EventHandler { closeApplication() } 27 28 primaryStage.onCloseRequest = EventHandler { closeApplication() }
primaryStage.show() 28 29 primaryStage.show()
} 29 30 }
30 31
private fun closeApplication() { 31 32 private fun closeApplication() {
32
Platform.exit() 33 33 Platform.exit()
exitProcess(0) 34 34 exitProcess(0)
} 35 35 }
src/main/kotlin/application/controller/DataPanelController.kt View file @ a6a8df6
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
import kotlinx.coroutines.GlobalScope 10 10 import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch 11 11 import kotlinx.coroutines.launch
import org.charts.dataviewer.api.config.DataViewerConfiguration 12 12 import org.charts.dataviewer.api.config.DataViewerConfiguration
import org.charts.dataviewer.api.data.PlotData 13 13 import org.charts.dataviewer.api.data.PlotData
import org.charts.dataviewer.api.trace.ScatterTrace 14 14 import org.charts.dataviewer.api.trace.ScatterTrace
import org.charts.dataviewer.javafx.JavaFxDataViewer 15 15 import org.charts.dataviewer.javafx.JavaFxDataViewer
import org.charts.dataviewer.utils.TraceColour 16 16 import org.charts.dataviewer.utils.TraceColour
import org.charts.dataviewer.utils.TraceVisibility 17 17 import org.charts.dataviewer.utils.TraceVisibility
import java.net.URL 18 18 import java.net.URL
import java.util.* 19 19 import java.util.*
20 20
21 21
class DataPanelController : Initializable, SelectedVesselListener { 22 22 class DataPanelController : Initializable, SelectedVesselListener {
private var dataList: ObservableList<String> = FXCollections.observableArrayList() 23 23 private var dataList: ObservableList<String> = FXCollections.observableArrayList()
private lateinit var timeData: ArrayList<String> 24 24 private lateinit var timeData: ArrayList<String>
25 25
private val latitude: ArrayList<Double> = arrayListOf() 26 26 private val latitude: ArrayList<Double> = arrayListOf()
private val longitude: ArrayList<Double> = arrayListOf() 27 27 private val longitude: ArrayList<Double> = arrayListOf()
private val speedOverGround: ArrayList<Double> = arrayListOf() 28 28 private val speedOverGround: ArrayList<Double> = arrayListOf()
private val courseOverGround: ArrayList<Double> = arrayListOf() 29 29 private val courseOverGround: ArrayList<Double> = arrayListOf()
private val heading: ArrayList<Double> = arrayListOf() 30 30 private val heading: ArrayList<Double> = arrayListOf()
private val vesselName: ArrayList<String> = arrayListOf() 31 31 private val vesselName: ArrayList<String> = arrayListOf()
private val imo: ArrayList<String> = arrayListOf() 32 32 private val imo: ArrayList<String> = arrayListOf()
private val callSign: ArrayList<String> = arrayListOf() 33 33 private val callSign: ArrayList<String> = arrayListOf()
private val vesselType: ArrayList<Double> = arrayListOf() 34 34 private val vesselType: ArrayList<Double> = arrayListOf()
private val status: ArrayList<String> = arrayListOf() 35 35 private val status: ArrayList<String> = arrayListOf()
private val length: ArrayList<Double> = arrayListOf() 36 36 private val length: ArrayList<Double> = arrayListOf()
private val width: ArrayList<Double> = arrayListOf() 37 37 private val width: ArrayList<Double> = arrayListOf()
private val draft: ArrayList<Double> = arrayListOf() 38 38 private val draft: ArrayList<Double> = arrayListOf()
private val cargo: ArrayList<Double> = arrayListOf() 39 39 private val cargo: ArrayList<Double> = arrayListOf()
40 40
private var selectedItem: String? = null 41 41 private var selectedItem: String? = null
42 42
@FXML 43 43 @FXML
var dataListView = ListView<String>() 44 44 var dataListView = ListView<String>()
45 45
@FXML 46 46 @FXML
var dataViewer = JavaFxDataViewer() 47 47 var dataViewer = JavaFxDataViewer()
48 48
private val plotData = PlotData() 49 49 private val plotData = PlotData()
private val config = DataViewerConfiguration() 50 50 private val config = DataViewerConfiguration()
override fun initialize(location: URL?, resources: ResourceBundle?) { 51 51 override fun initialize(location: URL?, resources: ResourceBundle?) {
setObservableSelectedVesselListener() 52 52 setObservableSelectedVesselListener()
dataListView.items = dataList 53 53 dataListView.items = dataList
54 54
55 55
56 56
config.showLegend(false) 57 57 config.showLegend(false)
config.setLegendInsidePlot(false) 58 58 config.setLegendInsidePlot(false)
59 59
setObservableCurrentTimeListener() 60 60 setObservableCurrentTimeListener()
61 61
dataListView.setCellFactory { 62 62 dataListView.setCellFactory {
object : ListCell<String?>() { 63 63 object : ListCell<String?>() {
override fun updateItem(item: String?, empty: Boolean) { 64 64 override fun updateItem(item: String?, empty: Boolean) {
super.updateItem(item, empty) 65 65 super.updateItem(item, empty)
text = if (empty) { 66 66 text = if (empty) {
null 67 67 null
} else { 68 68 } else {
item 69 69 item
} 70 70 }
} 71 71 }
} 72 72 }
} 73 73 }
74 74
dataListView.selectionModel.selectedItemProperty().addListener { _, _, newValue -> 75 75 dataListView.selectionModel.selectedItemProperty().addListener { _, _, newValue ->
selectedItem = newValue 76 76 selectedItem = newValue
updateDataList(observableSelectedVessel.value) 77 77 updateDataList(observableSelectedVessel.value)
plot(newValue) 78 78 plot(newValue)
} 79 79 }
80 80
plotData.allTraces.clear() 81 81 plotData.allTraces.clear()
config.setxAxisTitle("") 82 82 config.setxAxisTitle("")
config.setyAxisTitle("") 83 83 config.setyAxisTitle("")
config.plotTitle = "" 84 84 config.plotTitle = ""
dataViewer.updateConfiguration(config) 85 85 dataViewer.updateConfiguration(config)
dataViewer.updatePlot(plotData) 86 86 dataViewer.updatePlot(plotData)
initDataList() 87 87 initDataList()
88 88
89
} 90 89 }
91 90
private fun plot() { 92 91 private fun plot() {
if (selectedItem != null && observableSelectedVessel.value.messages.size != 0) { 93 92 if (selectedItem != null && observableSelectedVessel.value.messages.size != 0) {
GlobalScope.launch { 94 93 GlobalScope.launch {
plot(selectedItem) 95 94 plot(selectedItem)
} 96 95 }
} 97 96 }
} 98 97 }
99 98
100
101
private fun plot(data: String?) { 102 99 private fun plot(data: String?) {
if (data == null) { 103 100 if (data == null) {
plotData.allTraces.clear() 104 101 plotData.allTraces.clear()
config.setxAxisTitle("") 105 102 config.setxAxisTitle("")
config.setyAxisTitle("") 106 103 config.setyAxisTitle("")
dataViewer.updateConfiguration(config) 107 104 dataViewer.updateConfiguration(config)
108 105
dataViewer.resetPlot() 109 106 dataViewer.resetPlot()
110 107
return 111 108 return
} 112 109 }
113 110
val scatterTrace = ScatterTrace<Any>() 114 111 val scatterTrace = ScatterTrace<Any>()
scatterTrace.traceColour = TraceColour.RED 115 112 scatterTrace.traceColour = TraceColour.RED
scatterTrace.traceVisibility = TraceVisibility.TRUE 116 113 scatterTrace.traceVisibility = TraceVisibility.TRUE
117 114
val serieStringX: Array<String> = timeData.toTypedArray() 118 115 val serieStringX: Array<String> = timeData.toTypedArray()
// val serieDoubleX: Array<Double> = arrayListDoubleX.toTypedArray() 119 116 // val serieDoubleX: Array<Double> = arrayListDoubleX.toTypedArray()
var serieStringY: Array<String> = arrayOf() 120 117 var serieStringY: Array<String> = arrayOf()
var serieDoubleY: Array<Double> = arrayOf() 121 118 var serieDoubleY: Array<Double> = arrayOf()
when (data) { 122 119 when (data) {
"Latitude" -> { 123 120 "Latitude" -> {
serieDoubleY = latitude.toTypedArray() 124 121 serieDoubleY = latitude.toTypedArray()
} 125 122 }
"Longitude" -> { 126 123 "Longitude" -> {
serieDoubleY = longitude.toTypedArray() 127 124 serieDoubleY = longitude.toTypedArray()
} 128 125 }
"Speed Over Ground" -> { 129 126 "Speed Over Ground" -> {
serieDoubleY = speedOverGround.toTypedArray() 130 127 serieDoubleY = speedOverGround.toTypedArray()
} 131 128 }
"Course Over Ground" -> { 132 129 "Course Over Ground" -> {
serieDoubleY = courseOverGround.toTypedArray() 133 130 serieDoubleY = courseOverGround.toTypedArray()
} 134 131 }
"Heading" -> { 135 132 "Heading" -> {
serieDoubleY = heading.toTypedArray() 136 133 serieDoubleY = heading.toTypedArray()
} 137 134 }
"Vessel Name" -> { 138 135 "Vessel Name" -> {
serieStringY = vesselName.toTypedArray() 139 136 serieStringY = vesselName.toTypedArray()
} 140 137 }
"IMO" -> { 141 138 "IMO" -> {
serieStringY = imo.toTypedArray() 142 139 serieStringY = imo.toTypedArray()
} 143 140 }
"Call Sign" -> { 144 141 "Call Sign" -> {
serieStringY = callSign.toTypedArray() 145 142 serieStringY = callSign.toTypedArray()
} 146 143 }
"Vessel Type" -> { 147 144 "Vessel Type" -> {
serieDoubleY = vesselType.toTypedArray() 148 145 serieDoubleY = vesselType.toTypedArray()
} 149 146 }
"Status" -> { 150 147 "Status" -> {
serieStringY = status.toTypedArray() 151 148 serieStringY = status.toTypedArray()
} 152 149 }
"Length" -> { 153 150 "Length" -> {
serieDoubleY = length.toTypedArray() 154 151 serieDoubleY = length.toTypedArray()
} 155 152 }
"Width" -> { 156 153 "Width" -> {
serieDoubleY = width.toTypedArray() 157 154 serieDoubleY = width.toTypedArray()
} 158 155 }
"Draft" -> { 159 156 "Draft" -> {
serieDoubleY = draft.toTypedArray() 160 157 serieDoubleY = draft.toTypedArray()
} 161 158 }
"Cargo" -> { 162 159 "Cargo" -> {
serieDoubleY = cargo.toTypedArray() 163 160 serieDoubleY = cargo.toTypedArray()
} 164 161 }
} 165 162 }
166 163
if (serieStringY.isNotEmpty()) { 167 164 if (serieStringY.isNotEmpty()) {
scatterTrace.setxArray(serieStringX) 168 165 scatterTrace.setxArray(serieStringX)
scatterTrace.setyArray(serieStringY) 169 166 scatterTrace.setyArray(serieStringY)
} else { 170 167 } else {
scatterTrace.setxArray(serieStringX) 171 168 scatterTrace.setxArray(serieStringX)
scatterTrace.setyArray(serieDoubleY) 172 169 scatterTrace.setyArray(serieDoubleY)
} 173 170 }
174 171
config.plotTitle = "" 175 172 config.plotTitle = ""
config.setxAxisTitle("Time (s)") 176 173 config.setxAxisTitle("Time (s)")
config.setyAxisTitle(data) 177 174 config.setyAxisTitle(data)
dataViewer.resetPlot() 178 175 dataViewer.resetPlot()
plotData.allTraces.clear() 179 176 plotData.allTraces.clear()
plotData.addTrace(scatterTrace) 180 177 plotData.addTrace(scatterTrace)
dataViewer.updateConfiguration(config) 181 178 dataViewer.updateConfiguration(config)
dataViewer.updatePlot(plotData) 182 179 dataViewer.updatePlot(plotData)
183 180
} 184 181 }
185 182
private fun setObservableSelectedVesselListener() { 186 183 private fun setObservableSelectedVesselListener() {
observableSelectedVessel.listeners.add(this) 187 184 observableSelectedVessel.listeners.add(this)
} 188 185 }
189 186
private fun populateTime(vessel: Vessel): ArrayList<String> { 190 187 private fun populateTime(vessel: Vessel): ArrayList<String> {
return if (observableIsReplayState.value) { 191 188 return if (observableIsReplayState.value) {
vessel.getAllTimeBeforeSelectedTime() 192 189 vessel.getAllTimeBeforeSelectedTime()
} else { 193 190 } else {
vessel.getAllTime() 194 191 vessel.getAllTime()
} 195 192 }
} 196 193 }
197 194
private fun populateLatitude(vessel: Vessel): ArrayList<Double> { 198 195 private fun populateLatitude(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 199 196 return if (observableIsReplayState.value) {
vessel.getAllLatitudeBeforeSelectedTime() 200 197 vessel.getAllLatitudeBeforeSelectedTime()
} else { 201 198 } else {
vessel.getAllLatitude() 202 199 vessel.getAllLatitude()
} 203 200 }
} 204 201 }
205 202
private fun populateLongitude(vessel: Vessel): ArrayList<Double> { 206 203 private fun populateLongitude(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 207 204 return if (observableIsReplayState.value) {
vessel.getAllLongitudeBeforeSelectedTime() 208 205 vessel.getAllLongitudeBeforeSelectedTime()
} else { 209 206 } else {
vessel.getAllLongitude() 210 207 vessel.getAllLongitude()
} 211 208 }
} 212 209 }
213 210
private fun populateSpeedOverGround(vessel: Vessel): ArrayList<Double> { 214 211 private fun populateSpeedOverGround(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 215 212 return if (observableIsReplayState.value) {
vessel.getAllSpeedOverGroundBeforeSelectedTime() 216 213 vessel.getAllSpeedOverGroundBeforeSelectedTime()
} else { 217 214 } else {
vessel.getAllSpeedOverGround() 218 215 vessel.getAllSpeedOverGround()
} 219 216 }
} 220 217 }
221 218
private fun populateCourseOverGround(vessel: Vessel): ArrayList<Double> { 222 219 private fun populateCourseOverGround(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 223 220 return if (observableIsReplayState.value) {
vessel.getAllCourseOverGroundBeforeSelectedTime() 224 221 vessel.getAllCourseOverGroundBeforeSelectedTime()
} else { 225 222 } else {
vessel.getAllCourseOverGround() 226 223 vessel.getAllCourseOverGround()
} 227 224 }
} 228 225 }
229 226
private fun populateHeading(vessel: Vessel): ArrayList<Double> { 230 227 private fun populateHeading(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 231 228 return if (observableIsReplayState.value) {
vessel.getAllHeadingBeforeSelectedTime() 232 229 vessel.getAllHeadingBeforeSelectedTime()
} else { 233 230 } else {
vessel.getAllHeading() 234 231 vessel.getAllHeading()
} 235 232 }
} 236 233 }
237 234
private fun populateVesselName(vessel: Vessel): ArrayList<String> { 238 235 private fun populateVesselName(vessel: Vessel): ArrayList<String> {
return if (observableIsReplayState.value) { 239 236 return if (observableIsReplayState.value) {
vessel.getAllVesselNameBeforeSelectedTime() 240 237 vessel.getAllVesselNameBeforeSelectedTime()
} else { 241 238 } else {
vessel.getAllVesselName() 242 239 vessel.getAllVesselName()
} 243 240 }
} 244 241 }
245 242
private fun populateIMO(vessel: Vessel): ArrayList<String> { 246 243 private fun populateIMO(vessel: Vessel): ArrayList<String> {
return if (observableIsReplayState.value) { 247 244 return if (observableIsReplayState.value) {
vessel.getAllIMOBeforeSelectedTime() 248 245 vessel.getAllIMOBeforeSelectedTime()
} else { 249 246 } else {
vessel.getAllIMO() 250 247 vessel.getAllIMO()
} 251 248 }
} 252 249 }
253 250
private fun populateCallSign(vessel: Vessel): ArrayList<String> { 254 251 private fun populateCallSign(vessel: Vessel): ArrayList<String> {
return if (observableIsReplayState.value) { 255 252 return if (observableIsReplayState.value) {
vessel.getAllCallSignBeforeSelectedTime() 256 253 vessel.getAllCallSignBeforeSelectedTime()
} else { 257 254 } else {
vessel.getAllCallSign() 258 255 vessel.getAllCallSign()
} 259 256 }
} 260 257 }
261 258
private fun populateVesselType(vessel: Vessel): ArrayList<Double> { 262 259 private fun populateVesselType(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 263 260 return if (observableIsReplayState.value) {
vessel.getAllVesselTypeBeforeSelectedTime() 264 261 vessel.getAllVesselTypeBeforeSelectedTime()
} else { 265 262 } else {
vessel.getAllVesselType() 266 263 vessel.getAllVesselType()
} 267 264 }
} 268 265 }
269 266
private fun populateStatus(vessel: Vessel): ArrayList<String> { 270 267 private fun populateStatus(vessel: Vessel): ArrayList<String> {
return if (observableIsReplayState.value) { 271 268 return if (observableIsReplayState.value) {
vessel.getAllStatusBeforeSelectedTime() 272 269 vessel.getAllStatusBeforeSelectedTime()
} else { 273 270 } else {
vessel.getAllStatus() 274 271 vessel.getAllStatus()
} 275 272 }
} 276 273 }
277 274
private fun populateLength(vessel: Vessel): ArrayList<Double> { 278 275 private fun populateLength(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 279 276 return if (observableIsReplayState.value) {
vessel.getAllLengthBeforeSelectedTime() 280 277 vessel.getAllLengthBeforeSelectedTime()
} else { 281 278 } else {
vessel.getAllLength() 282 279 vessel.getAllLength()
} 283 280 }
} 284 281 }
285 282
private fun populateWidth(vessel: Vessel): ArrayList<Double> { 286 283 private fun populateWidth(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 287 284 return if (observableIsReplayState.value) {
vessel.getAllWidthBeforeSelectedTime() 288 285 vessel.getAllWidthBeforeSelectedTime()
} else { 289 286 } else {
vessel.getAllWidth() 290 287 vessel.getAllWidth()
} 291 288 }
} 292 289 }
293 290
private fun populateDraft(vessel: Vessel): ArrayList<Double> { 294 291 private fun populateDraft(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 295 292 return if (observableIsReplayState.value) {
vessel.getAllDraftBeforeSelectedTime() 296 293 vessel.getAllDraftBeforeSelectedTime()
} else { 297 294 } else {
vessel.getAllDraft() 298 295 vessel.getAllDraft()
} 299 296 }
} 300 297 }
301 298
private fun populateCargo(vessel: Vessel): ArrayList<Double> { 302 299 private fun populateCargo(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 303 300 return if (observableIsReplayState.value) {
vessel.getAllCargoBeforeSelectedTime() 304 301 vessel.getAllCargoBeforeSelectedTime()
} else { 305 302 } else {
vessel.getAllCargo() 306 303 vessel.getAllCargo()
} 307 304 }
} 308 305 }
309 306
private fun initDataList() { 310 307 private fun initDataList() {
val data = arrayListOf<String>() 311 308 val data = arrayListOf<String>()
312 309
data.add("Latitude") 313 310 data.add("Latitude")
data.add("Longitude") 314 311 data.add("Longitude")
data.add("Speed Over Ground") 315 312 data.add("Speed Over Ground")
data.add("Course Over Ground") 316 313 data.add("Course Over Ground")
data.add("Heading") 317 314 data.add("Heading")
data.add("Vessel Name") 318 315 data.add("Vessel Name")
data.add("IMO") 319 316 data.add("IMO")
data.add("Call Sign") 320 317 data.add("Call Sign")
data.add("Vessel Type") 321 318 data.add("Vessel Type")
data.add("Status") 322 319 data.add("Status")
data.add("Length") 323 320 data.add("Length")
data.add("Width") 324 321 data.add("Width")
data.add("Draft") 325 322 data.add("Draft")
data.add("Cargo") 326 323 data.add("Cargo")
327 324
dataList.addAll(data) 328 325 dataList.addAll(data)
} 329 326 }
330 327
private fun updateDataList(vessel: Vessel) { 331 328 private fun updateDataList(vessel: Vessel) {
timeData = populateTime(vessel) 332 329 timeData = populateTime(vessel)
333 330
if (dataListView.selectionModel.selectedItem == null) return 334 331 if (dataListView.selectionModel.selectedItem == null) return
//NOTE: Ajouter les nouvelles donnรฉe ร  la fin 335 332
when (dataListView.selectionModel.selectedItem) { 336 333 when (dataListView.selectionModel.selectedItem) {
"Latitude" -> { 337 334 "Latitude" -> {
latitude.clear() 338 335 latitude.clear()
latitude.addAll(populateLatitude(vessel)) 339 336 latitude.addAll(populateLatitude(vessel))
} 340 337 }
"Longitude" -> { 341 338 "Longitude" -> {
longitude.clear() 342 339 longitude.clear()
longitude.addAll(populateLongitude(vessel)) 343 340 longitude.addAll(populateLongitude(vessel))
} 344 341 }
"Speed Over Ground" -> { 345 342 "Speed Over Ground" -> {
speedOverGround.clear() 346 343 speedOverGround.clear()
speedOverGround.addAll(populateSpeedOverGround(vessel)) 347 344 speedOverGround.addAll(populateSpeedOverGround(vessel))
} 348 345 }
"Course Over Ground" -> { 349 346 "Course Over Ground" -> {
courseOverGround.clear() 350 347 courseOverGround.clear()
courseOverGround.addAll(populateCourseOverGround(vessel)) 351 348 courseOverGround.addAll(populateCourseOverGround(vessel))
} 352 349 }
"Heading" -> { 353 350 "Heading" -> {
heading.clear() 354 351 heading.clear()
heading.addAll(populateHeading(vessel)) 355 352 heading.addAll(populateHeading(vessel))
} 356 353 }
"Vessel Name" -> { 357 354 "Vessel Name" -> {
vesselName.clear() 358 355 vesselName.clear()
vesselName.addAll(populateVesselName(vessel)) 359 356 vesselName.addAll(populateVesselName(vessel))
src/main/kotlin/application/controller/VesselListPanelController.kt View file @ a6a8df6
package application.controller 1 1 package application.controller
2 2
import application.model.MessageListener 3 3 import application.model.MessageListener
import application.model.Vessel 4 4 import application.model.Vessel
import application.model.observableSelectedVessel 5 5 import application.model.observableSelectedVessel
import application.model.observableVessel 6 6 import application.model.observableVessel
import javafx.collections.FXCollections 7 7 import javafx.collections.FXCollections
import javafx.collections.ObservableList 8 8 import javafx.collections.ObservableList
9 import javafx.collections.transformation.FilteredList
import javafx.fxml.FXML 9 10 import javafx.fxml.FXML
import javafx.fxml.Initializable 10 11 import javafx.fxml.Initializable
import javafx.scene.control.ListCell 11 12 import javafx.scene.control.*
import javafx.scene.control.ListView 12
import javafx.scene.control.MultipleSelectionModel 13
import javafx.scene.control.SelectionMode 14
import javafx.scene.input.MouseEvent 15 13 import javafx.scene.input.MouseEvent
import java.net.URL 16 14 import java.net.URL
import java.util.* 17 15 import java.util.*
18 16
19 17
class VesselListPanelController : Initializable, MessageListener { 20 18 class VesselListPanelController : Initializable, MessageListener {
19
@FXML 21 20 @FXML
var shipListView: ListView<String?> = ListView() 22 21 var shipListView: ListView<String?> = ListView()
23 22
23 @FXML
24 var filterInput: TextField = TextField()
25
private var shipList: ObservableList<String?> = FXCollections.observableArrayList() 24 26 private var shipList: ObservableList<String?> = FXCollections.observableArrayList()
25 27
28 private val filterMMSI = FilteredList(shipList)
29
override fun initialize(location: URL?, resources: ResourceBundle?) { 26 30 override fun initialize(location: URL?, resources: ResourceBundle?) {
27 31
28 32
shipListView.items = shipList 29 33 shipListView.items = filterMMSI
34
observableVessel.listeners.add(this) 30 35 observableVessel.listeners.add(this)
shipListView.selectionModel.selectedItemProperty().addListener { _, _, newValue -> 31 36 shipListView.selectionModel.selectedItemProperty().addListener { _, _, newValue ->
if (newValue == null) { 32 37 if (newValue == null) {
observableSelectedVessel.value = Vessel(null) 33 38 observableSelectedVessel.value = Vessel(null)
} else { 34 39 } else {
observableSelectedVessel.value = observableVessel.vessels[newValue]!! 35 40 observableSelectedVessel.value = observableVessel.vessels[newValue]!!
} 36 41 }
} 37 42 }
43
44
setCellFactory() 38 45 setCellFactory()
46 setFilterTextListener()
} 39 47 }
40 48
override fun onValueChanged(newValue: MutableMap<String?, Vessel>) { 41 49 override fun onValueChanged(newValue: MutableMap<String?, Vessel>) {
shipList.clear() 42 50 shipList.clear()
shipList.addAll(newValue.keys) 43 51 shipList.addAll(newValue.keys)
52 }
53
54 private fun setFilterTextListener() {
55 filterInput.textProperty().addListener { _ ->
56 val filter: String = filterInput.text
57 if (filter.isEmpty()) {
58 filterMMSI.setPredicate { true }
59 } else {
60 filterMMSI.setPredicate { s: String? -> s!!.contains(filter) }
61 }
62 }
} 44 63 }
45 64
private fun setCellFactory() { 46 65 private fun setCellFactory() {
val selectionModel: MultipleSelectionModel<String?>? = shipListView.selectionModel 47 66 val selectionModel: MultipleSelectionModel<String?>? = shipListView.selectionModel
selectionModel?.selectionMode = SelectionMode.SINGLE 48 67 selectionModel?.selectionMode = SelectionMode.SINGLE
shipListView.setCellFactory { 49 68 shipListView.setCellFactory {
val cell = ListCell<String?>() 50 69 val cell = ListCell<String?>()
cell.textProperty().bind(cell.itemProperty()) 51 70 cell.textProperty().bind(cell.itemProperty())
cell.addEventFilter(MouseEvent.MOUSE_PRESSED) { event: MouseEvent -> 52 71 cell.addEventFilter(MouseEvent.MOUSE_PRESSED) { event: MouseEvent ->
shipListView.requestFocus() 53 72 shipListView.requestFocus()
if (!cell.isEmpty) { 54 73 if (!cell.isEmpty) {
val index = cell.index 55 74 val index = cell.index
if (selectionModel!!.selectedIndices.contains(index)) { 56 75 if (selectionModel!!.selectedIndices.contains(index)) {
selectionModel.clearSelection() 57 76 selectionModel.clearSelection()
} else { 58 77 } else {
selectionModel.select(index) 59 78 selectionModel.select(index)
} 60 79 }
src/main/resources/gui/mapPanel.fxml View file @ a6a8df6
<?xml version="1.0" encoding="UTF-8"?> 1 1 <?xml version="1.0" encoding="UTF-8"?>
2 2
<?import javafx.scene.layout.*?> 3 3 <?import javafx.scene.layout.*?>
4 4
<VBox prefHeight="150.0" prefWidth="371.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller.MapPanelController"> 5 5 <VBox prefHeight="150.0" prefWidth="371.0" xmlns="http://javafx.com/javafx/8.0.241" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller.MapPanelController">
<StackPane fx:id="map" /> 6 6 <StackPane fx:id="map" />
<fx:include source="timePanel.fxml" /> 7 7 <fx:include source="timePanel.fxml" />
src/main/resources/gui/menuBar.fxml View file @ a6a8df6
<?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.*?>
4 4
<MenuBar fx:id="menuBar" prefHeight="25.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller.MenuBarController"> 5 5 <MenuBar fx:id="menuBar" prefHeight="25.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.241" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller.MenuBarController">
<menus> 6 6 <menus>
<Menu mnemonicParsing="false" text="File"> 7 7 <Menu mnemonicParsing="false" text="File">
<items> 8 8 <items>
<MenuItem fx:id="import" mnemonicParsing="false" text="Import" /> 9 9 <MenuItem fx:id="import" mnemonicParsing="false" text="Import" />
</items> 10 10 </items>
</Menu> 11 11 </Menu>
<Menu mnemonicParsing="false" text="Settings"> 12 12 <Menu mnemonicParsing="false" text="Settings">
<items> 13 13 <items>
<Menu mnemonicParsing="false" text="Map selected"> 14 14 <Menu mnemonicParsing="false" text="Map selected">
<items> 15 15 <items>
<CheckMenuItem fx:id="allMessages" mnemonicParsing="false" text="All messages" /> 16 16 <CheckMenuItem fx:id="allMessages" mnemonicParsing="false" text="All messages" />
<CheckMenuItem fx:id="clusteredMessage" mnemonicParsing="false" text="Clustered messages" /> 17 17 <CheckMenuItem fx:id="clusteredMessage" mnemonicParsing="false" text="Clustered messages" />
<CheckMenuItem fx:id="heatMap" mnemonicParsing="false" text="Heat map" /> 18 18 <CheckMenuItem fx:id="heatMap" mnemonicParsing="false" text="Heat map" />
</items> 19 19 </items>
</Menu> 20 20 </Menu>
<RadioMenuItem fx:id="activateReplayButton" mnemonicParsing="false" text="Unspecified Action" /> 21 21 <RadioMenuItem fx:id="activateReplayButton" mnemonicParsing="false" text="Unspecified Action" />
</items> 22 22 </items>
</Menu> 23 23 </Menu>
<Menu mnemonicParsing="false" text="Help"> 24 24 <Menu mnemonicParsing="false" text="Help">
<items> 25 25 <items>
<MenuItem mnemonicParsing="false" text="About" /> 26 26 <MenuItem mnemonicParsing="false" text="About" />
</items> 27 27 </items>
</Menu> 28 28 </Menu>
</menus> 29 29 </menus>
src/main/resources/gui/timePanel.fxml View file @ a6a8df6
<?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/8.0.241" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller.TimePanel">
<children> 8 8 <children>
<Slider fx:id="timeSlider" prefHeight="14.0" prefWidth="538.0"> 9 9 <Slider fx:id="timeSlider" prefHeight="14.0" prefWidth="538.0">
<HBox.margin> 10 10 <HBox.margin>
<Insets left="5.0" right="5.0" /> 11 11 <Insets left="5.0" right="5.0" />
</HBox.margin></Slider> 12 12 </HBox.margin></Slider>
</children> 13 13 </children>
src/main/resources/gui/vesselListPanel.fxml View file @ a6a8df6
<?xml version="1.0" encoding="UTF-8"?> 1 1 <?xml version="1.0" encoding="UTF-8"?>
2 2
<?import javafx.geometry.*?> 3
<?import javafx.scene.control.*?> 4 3 <?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?> 5 4 <?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?> 6
7 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/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller.VesselListPanelController"> 8 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/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.controller.VesselListPanelController">
<center> 9 7 <center>
<ListView fx:id="shipListView" prefHeight="50.0" prefWidth="200.0" /> 10 8 <ListView fx:id="shipListView" prefHeight="50.0" prefWidth="200.0" />
</center> 11 9 </center>
<top> 12 10 <top>
<TextFlow prefHeight="28.0" prefWidth="200.0" style="-fx-font-weight: bold;" textAlignment="CENTER" BorderPane.alignment="CENTER"> 13 11 <TextField fx:id="filterInput" promptText="MMSI" BorderPane.alignment="CENTER" />
<children> 14
<Text scaleX="1.5" scaleY="1.5" strokeType="OUTSIDE" strokeWidth="0.0" text="MMSI" textAlignment="CENTER" /> 15
</children> 16
<BorderPane.margin> 17
<Insets /> 18
</BorderPane.margin> 19
<padding> 20
<Insets top="5.0" /> 21
</padding> 22
</TextFlow> 23
</top> 24 12 </top>
src/main/resources/gui/windows.fxml View file @ a6a8df6
<?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/11.0.1" 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/8.0.241" 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.13772954924874792" 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.13772954924874792" 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="vesselListPanel.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" />
<fx:include source="dataPanel.fxml" /> 22 22 <fx:include source="dataPanel.fxml" />
</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="3000.0" layoutX="101.0" layoutY="35.0" startX="-100.0" AnchorPane.leftAnchor="-3.0" AnchorPane.rightAnchor="0.0" /> 29 29 <Line endX="3000.0" layoutX="101.0" layoutY="35.0" startX="-100.0" AnchorPane.leftAnchor="-3.0" AnchorPane.rightAnchor="0.0" />
</children> 30 30 </children>