Compare View

switch
from
...
to
 
Commits (7)

Diff

Showing 13 changed files Inline Diff

src/main/kotlin/application/App.kt View file @ 5250f69
@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 @ 5250f69
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<Pair<String, ArrayList<MessageData?>>> = FXCollections.observableArrayList() 23 23 private var dataList: ObservableList<String> = FXCollections.observableArrayList()
private lateinit var timeData: ArrayList<MessageData?> 24 24 private lateinit var timeData: ArrayList<String>
25 25
private val latitude: ArrayList<MessageData?> = arrayListOf() 26 26 private val latitude: ArrayList<Double> = arrayListOf()
private val longitude: ArrayList<MessageData?> = arrayListOf() 27 27 private val longitude: ArrayList<Double> = arrayListOf()
private val speedOverGround: ArrayList<MessageData?> = arrayListOf() 28 28 private val speedOverGround: ArrayList<Double> = arrayListOf()
private val courseOverGround: ArrayList<MessageData?> = arrayListOf() 29 29 private val courseOverGround: ArrayList<Double> = arrayListOf()
private val heading: ArrayList<MessageData?> = arrayListOf() 30 30 private val heading: ArrayList<Double> = arrayListOf()
private val vesselName: ArrayList<MessageData?> = arrayListOf() 31 31 private val vesselName: ArrayList<String> = arrayListOf()
private val imo: ArrayList<MessageData?> = arrayListOf() 32 32 private val imo: ArrayList<String> = arrayListOf()
private val callSign: ArrayList<MessageData?> = arrayListOf() 33 33 private val callSign: ArrayList<String> = arrayListOf()
private val vesselType: ArrayList<MessageData?> = arrayListOf() 34 34 private val vesselType: ArrayList<Double> = arrayListOf()
private val status: ArrayList<MessageData?> = arrayListOf() 35 35 private val status: ArrayList<String> = arrayListOf()
private val length: ArrayList<MessageData?> = arrayListOf() 36 36 private val length: ArrayList<Double> = arrayListOf()
private val width: ArrayList<MessageData?> = arrayListOf() 37 37 private val width: ArrayList<Double> = arrayListOf()
private val draft: ArrayList<MessageData?> = arrayListOf() 38 38 private val draft: ArrayList<Double> = arrayListOf()
private val cargo: ArrayList<MessageData?> = arrayListOf() 39 39 private val cargo: ArrayList<Double> = arrayListOf()
40 40
private var selectedItem: Pair<String, ArrayList<MessageData?>>? = null 41 41 private var selectedItem: String? = null
42 42
@FXML 43 43 @FXML
var dataListView = ListView<Pair<String, ArrayList<MessageData?>>>() 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()
51
override fun initialize(location: URL?, resources: ResourceBundle?) { 52 51 override fun initialize(location: URL?, resources: ResourceBundle?) {
setObservableSelectedVesselListener() 53 52 setObservableSelectedVesselListener()
dataListView.items = dataList 54 53 dataListView.items = dataList
55 54
56 55
57 56
config.showLegend(false) 58 57 config.showLegend(false)
config.setLegendInsidePlot(false) 59 58 config.setLegendInsidePlot(false)
60 59
setObservableCurrentTimeListener() 61 60 setObservableCurrentTimeListener()
62 61
dataListView.setCellFactory { 63 62 dataListView.setCellFactory {
object : ListCell<Pair<String, ArrayList<MessageData?>>?>() { 64 63 object : ListCell<String?>() {
override fun updateItem(item: Pair<String, ArrayList<MessageData?>>?, empty: Boolean) { 65 64 override fun updateItem(item: String?, empty: Boolean) {
super.updateItem(item, empty) 66 65 super.updateItem(item, empty)
text = if (empty) { 67 66 text = if (empty) {
null 68 67 null
} else { 69 68 } else {
item?.first 70 69 item
} 71 70 }
} 72 71 }
} 73 72 }
} 74 73 }
75 74
dataListView.selectionModel.selectedItemProperty().addListener { _, _, newValue -> 76 75 dataListView.selectionModel.selectedItemProperty().addListener { _, _, newValue ->
selectedItem = newValue 77 76 selectedItem = newValue
updateDataList(observableSelectedVessel.value) 78 77 updateDataList(observableSelectedVessel.value)
plot(newValue) 79 78 plot(newValue)
} 80 79 }
81 80
plotData.allTraces.clear() 82 81 plotData.allTraces.clear()
config.setxAxisTitle("") 83 82 config.setxAxisTitle("")
config.setyAxisTitle("") 84 83 config.setyAxisTitle("")
config.plotTitle = "" 85 84 config.plotTitle = ""
dataViewer.updateConfiguration(config) 86 85 dataViewer.updateConfiguration(config)
dataViewer.updatePlot(plotData) 87 86 dataViewer.updatePlot(plotData)
initDataList() 88 87 initDataList()
89 88
90
} 91 89 }
92 90
private fun plot() { 93 91 private fun plot() {
if (selectedItem != null || observableSelectedVessel.value == Vessel(null)) { 94 92 if (selectedItem != null && observableSelectedVessel.value.messages.size != 0) {
GlobalScope.launch { 95 93 GlobalScope.launch {
plot(selectedItem) 96 94 plot(selectedItem)
} 97 95 }
} 98 96 }
} 99 97 }
100 98
private fun plot(data: Pair<String, ArrayList<MessageData?>>?) { 101 99 private fun plot(data: String?) {
if (data == null) { 102 100 if (data == null) {
plotData.allTraces.clear() 103 101 plotData.allTraces.clear()
config.setxAxisTitle("") 104 102 config.setxAxisTitle("")
config.setyAxisTitle("") 105 103 config.setyAxisTitle("")
dataViewer.updateConfiguration(config) 106 104 dataViewer.updateConfiguration(config)
107 105
dataViewer.resetPlot() 108 106 dataViewer.resetPlot()
109 107
return 110 108 return
}else if (data.second.size < timeData.size) return 111
112
val getValueVisitorX = GetValueVisitor() 113
val getValueVisitorY = GetValueVisitor() 114
115
val arrayListStringX = arrayListOf<String>() 116
// val arrayListDoubleX = arrayListOf<Double>() 117
val arrayListStringY = arrayListOf<String>() 118
val arrayListDoubleY = arrayListOf<Double>() 119
120
for (x in 0 until timeData.size) { 121
timeData[x]?.accept(getValueVisitorX) 122
data.second[x]?.accept(getValueVisitorY) 123
124
if (getValueVisitorY.value.toDoubleOrNull() == null) { 125
arrayListStringX.add(getValueVisitorX.value) 126
arrayListStringY.add(getValueVisitorY.value) 127
} else { 128
arrayListStringX.add(getValueVisitorX.value) 129
arrayListDoubleY.add(getValueVisitorY.value.toDouble()) 130
} 131
} 132 109 }
133 110
val scatterTrace = ScatterTrace<Any>() 134 111 val scatterTrace = ScatterTrace<Any>()
scatterTrace.traceColour = TraceColour.RED 135 112 scatterTrace.traceColour = TraceColour.RED
scatterTrace.traceVisibility = TraceVisibility.TRUE 136 113 scatterTrace.traceVisibility = TraceVisibility.TRUE
137 114
val serieStringX: Array<String> = arrayListStringX.toTypedArray() 138 115 val serieStringX: Array<String> = timeData.toTypedArray()
// val serieDoubleX: Array<Double> = arrayListDoubleX.toTypedArray() 139 116 // val serieDoubleX: Array<Double> = arrayListDoubleX.toTypedArray()
val serieStringY: Array<String> = arrayListStringY.toTypedArray() 140 117 var serieStringY: Array<String> = arrayOf()
val serieDoubleY: Array<Double> = arrayListDoubleY.toTypedArray() 141 118 var serieDoubleY: Array<Double> = arrayOf()
119 when (data) {
120 "Latitude" -> {
121 serieDoubleY = latitude.toTypedArray()
122 }
123 "Longitude" -> {
124 serieDoubleY = longitude.toTypedArray()
125 }
126 "Speed Over Ground" -> {
127 serieDoubleY = speedOverGround.toTypedArray()
128 }
129 "Course Over Ground" -> {
130 serieDoubleY = courseOverGround.toTypedArray()
131 }
132 "Heading" -> {
133 serieDoubleY = heading.toTypedArray()
134 }
135 "Vessel Name" -> {
136 serieStringY = vesselName.toTypedArray()
137 }
138 "IMO" -> {
139 serieStringY = imo.toTypedArray()
140 }
141 "Call Sign" -> {
142 serieStringY = callSign.toTypedArray()
143 }
144 "Vessel Type" -> {
145 serieDoubleY = vesselType.toTypedArray()
146 }
147 "Status" -> {
148 serieStringY = status.toTypedArray()
149 }
150 "Length" -> {
151 serieDoubleY = length.toTypedArray()
152 }
153 "Width" -> {
154 serieDoubleY = width.toTypedArray()
155 }
156 "Draft" -> {
157 serieDoubleY = draft.toTypedArray()
158 }
159 "Cargo" -> {
160 serieDoubleY = cargo.toTypedArray()
161 }
162 }
142 163
if (getValueVisitorY.value.toDoubleOrNull() == null) { 143 164 if (serieStringY.isNotEmpty()) {
scatterTrace.setxArray(serieStringX) 144 165 scatterTrace.setxArray(serieStringX)
scatterTrace.setyArray(serieStringY) 145 166 scatterTrace.setyArray(serieStringY)
} else { 146 167 } else {
scatterTrace.setxArray(serieStringX) 147 168 scatterTrace.setxArray(serieStringX)
scatterTrace.setyArray(serieDoubleY) 148 169 scatterTrace.setyArray(serieDoubleY)
} 149 170 }
150 171
config.plotTitle = "" 151 172 config.plotTitle = ""
config.setxAxisTitle("Time (s)") 152 173 config.setxAxisTitle("Time (s)")
config.setyAxisTitle(data.first) 153 174 config.setyAxisTitle(data)
dataViewer.resetPlot() 154 175 dataViewer.resetPlot()
plotData.allTraces.clear() 155 176 plotData.allTraces.clear()
plotData.addTrace(scatterTrace) 156 177 plotData.addTrace(scatterTrace)
dataViewer.updateConfiguration(config) 157 178 dataViewer.updateConfiguration(config)
dataViewer.updatePlot(plotData) 158 179 dataViewer.updatePlot(plotData)
159 180
} 160 181 }
161 182
162
private fun setObservableSelectedVesselListener() { 163 183 private fun setObservableSelectedVesselListener() {
observableSelectedVessel.listeners.add(this) 164 184 observableSelectedVessel.listeners.add(this)
} 165 185 }
166 186
private fun populateTime(vessel: Vessel): ArrayList<MessageData?> { 167 187 private fun populateTime(vessel: Vessel): ArrayList<String> {
return if (observableIsReplayState.value) { 168 188 return if (observableIsReplayState.value) {
vessel.getAllTimeBeforeSelectedTime() 169 189 vessel.getAllTimeBeforeSelectedTime()
} else { 170 190 } else {
vessel.getAllTime() 171 191 vessel.getAllTime()
} 172 192 }
} 173 193 }
174 194
175 195 private fun populateLatitude(vessel: Vessel): ArrayList<Double> {
private fun populateLatitude(vessel: Vessel): ArrayList<MessageData?> { 176
return if (observableIsReplayState.value) { 177 196 return if (observableIsReplayState.value) {
vessel.getAllLatitudeBeforeSelectedTime() 178 197 vessel.getAllLatitudeBeforeSelectedTime()
} else { 179 198 } else {
vessel.getAllLatitude() 180 199 vessel.getAllLatitude()
} 181 200 }
} 182 201 }
183 202
private fun populateLongitude(vessel: Vessel): ArrayList<MessageData?> { 184 203 private fun populateLongitude(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 185 204 return if (observableIsReplayState.value) {
vessel.getAllLongitudeBeforeSelectedTime() 186 205 vessel.getAllLongitudeBeforeSelectedTime()
} else { 187 206 } else {
vessel.getAllLongitude() 188 207 vessel.getAllLongitude()
} 189 208 }
} 190 209 }
191 210
private fun populateSpeedOverGround(vessel: Vessel): ArrayList<MessageData?> { 192 211 private fun populateSpeedOverGround(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 193 212 return if (observableIsReplayState.value) {
vessel.getAllSpeedOverGroundBeforeSelectedTime() 194 213 vessel.getAllSpeedOverGroundBeforeSelectedTime()
} else { 195 214 } else {
vessel.getAllSpeedOverGround() 196 215 vessel.getAllSpeedOverGround()
} 197 216 }
} 198 217 }
199 218
private fun populateCourseOverGround(vessel: Vessel): ArrayList<MessageData?> { 200 219 private fun populateCourseOverGround(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 201 220 return if (observableIsReplayState.value) {
vessel.getAllCourseOverGroundBeforeSelectedTime() 202 221 vessel.getAllCourseOverGroundBeforeSelectedTime()
} else { 203 222 } else {
vessel.getAllCourseOverGround() 204 223 vessel.getAllCourseOverGround()
} 205 224 }
} 206 225 }
207 226
private fun populateHeading(vessel: Vessel): ArrayList<MessageData?> { 208 227 private fun populateHeading(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 209 228 return if (observableIsReplayState.value) {
vessel.getAllHeadingBeforeSelectedTime() 210 229 vessel.getAllHeadingBeforeSelectedTime()
} else { 211 230 } else {
vessel.getAllHeading() 212 231 vessel.getAllHeading()
} 213 232 }
} 214 233 }
215 234
private fun populateVesselName(vessel: Vessel): ArrayList<MessageData?> { 216 235 private fun populateVesselName(vessel: Vessel): ArrayList<String> {
return if (observableIsReplayState.value) { 217 236 return if (observableIsReplayState.value) {
vessel.getAllVesselNameBeforeSelectedTime() 218 237 vessel.getAllVesselNameBeforeSelectedTime()
} else { 219 238 } else {
vessel.getAllVesselName() 220 239 vessel.getAllVesselName()
} 221 240 }
} 222 241 }
223 242
private fun populateIMO(vessel: Vessel): ArrayList<MessageData?> { 224 243 private fun populateIMO(vessel: Vessel): ArrayList<String> {
return if (observableIsReplayState.value) { 225 244 return if (observableIsReplayState.value) {
vessel.getAllIMOBeforeSelectedTime() 226 245 vessel.getAllIMOBeforeSelectedTime()
} else { 227 246 } else {
vessel.getAllIMO() 228 247 vessel.getAllIMO()
} 229 248 }
} 230 249 }
231 250
private fun populateCallSign(vessel: Vessel): ArrayList<MessageData?> { 232 251 private fun populateCallSign(vessel: Vessel): ArrayList<String> {
return if (observableIsReplayState.value) { 233 252 return if (observableIsReplayState.value) {
vessel.getAllCallSignBeforeSelectedTime() 234 253 vessel.getAllCallSignBeforeSelectedTime()
} else { 235 254 } else {
vessel.getAllCallSign() 236 255 vessel.getAllCallSign()
} 237 256 }
} 238 257 }
239 258
private fun populateVesselType(vessel: Vessel): ArrayList<MessageData?> { 240 259 private fun populateVesselType(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 241 260 return if (observableIsReplayState.value) {
vessel.getAllVesselTypeBeforeSelectedTime() 242 261 vessel.getAllVesselTypeBeforeSelectedTime()
} else { 243 262 } else {
vessel.getAllVesselType() 244 263 vessel.getAllVesselType()
} 245 264 }
} 246 265 }
247 266
private fun populateStatus(vessel: Vessel): ArrayList<MessageData?> { 248 267 private fun populateStatus(vessel: Vessel): ArrayList<String> {
return if (observableIsReplayState.value) { 249 268 return if (observableIsReplayState.value) {
vessel.getAllStatusBeforeSelectedTime() 250 269 vessel.getAllStatusBeforeSelectedTime()
} else { 251 270 } else {
vessel.getAllStatus() 252 271 vessel.getAllStatus()
} 253 272 }
} 254 273 }
255 274
private fun populateLength(vessel: Vessel): ArrayList<MessageData?> { 256 275 private fun populateLength(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 257 276 return if (observableIsReplayState.value) {
vessel.getAllLengthBeforeSelectedTime() 258 277 vessel.getAllLengthBeforeSelectedTime()
} else { 259 278 } else {
vessel.getAllLength() 260 279 vessel.getAllLength()
} 261 280 }
} 262 281 }
263 282
private fun populateWidth(vessel: Vessel): ArrayList<MessageData?> { 264 283 private fun populateWidth(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 265 284 return if (observableIsReplayState.value) {
vessel.getAllWidthBeforeSelectedTime() 266 285 vessel.getAllWidthBeforeSelectedTime()
} else { 267 286 } else {
vessel.getAllWidth() 268 287 vessel.getAllWidth()
} 269 288 }
} 270 289 }
271 290
private fun populateDraft(vessel: Vessel): ArrayList<MessageData?> { 272 291 private fun populateDraft(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 273 292 return if (observableIsReplayState.value) {
vessel.getAllDraftBeforeSelectedTime() 274 293 vessel.getAllDraftBeforeSelectedTime()
} else { 275 294 } else {
vessel.getAllDraft() 276 295 vessel.getAllDraft()
} 277 296 }
} 278 297 }
279 298
private fun populateCargo(vessel: Vessel): ArrayList<MessageData?> { 280 299 private fun populateCargo(vessel: Vessel): ArrayList<Double> {
return if (observableIsReplayState.value) { 281 300 return if (observableIsReplayState.value) {
vessel.getAllCargoBeforeSelectedTime() 282 301 vessel.getAllCargoBeforeSelectedTime()
} else { 283 302 } else {
vessel.getAllCargo() 284 303 vessel.getAllCargo()
} 285 304 }
} 286 305 }
287 306
private fun initDataList() { 288 307 private fun initDataList() {
val data = arrayListOf<Pair<String, ArrayList<MessageData?>>>() 289 308 val data = arrayListOf<String>()
290 309
data.add(Pair("Latitude", latitude)) 291 310 data.add("Latitude")
data.add(Pair("Longitude", longitude)) 292 311 data.add("Longitude")
data.add(Pair("Speed Over Ground", speedOverGround)) 293 312 data.add("Speed Over Ground")
data.add(Pair("Course Over Ground", courseOverGround)) 294 313 data.add("Course Over Ground")
data.add(Pair("Heading", heading)) 295 314 data.add("Heading")
data.add(Pair("Vessel Name", vesselName)) 296 315 data.add("Vessel Name")
data.add(Pair("IMO", imo)) 297 316 data.add("IMO")
data.add(Pair("Call Sign", callSign)) 298 317 data.add("Call Sign")
data.add(Pair("Vessel Type", vesselType)) 299 318 data.add("Vessel Type")
data.add(Pair("Status", status)) 300 319 data.add("Status")
data.add(Pair("Length", length)) 301 320 data.add("Length")
data.add(Pair("Width", width)) 302 321 data.add("Width")
data.add(Pair("Draft", draft)) 303 322 data.add("Draft")
data.add(Pair("Cargo", cargo)) 304 323 data.add("Cargo")
305 324
dataList.addAll(data) 306 325 dataList.addAll(data)
} 307 326 }
308 327
private fun updateDataList(vessel: Vessel) { 309 328 private fun updateDataList(vessel: Vessel) {
timeData = populateTime(vessel) 310 329 timeData = populateTime(vessel)
311 330
if(dataListView.selectionModel.selectedItem == null) return 312 331 if (dataListView.selectionModel.selectedItem == null) return
313 332
when (dataListView.selectionModel.selectedItem.first) { 314 333 when (dataListView.selectionModel.selectedItem) {
"Latitude" -> { 315 334 "Latitude" -> {
latitude.clear() 316 335 latitude.clear()
latitude.addAll(populateLatitude(vessel)) 317 336 latitude.addAll(populateLatitude(vessel))
} 318 337 }
"Longitude" -> { 319 338 "Longitude" -> {
longitude.clear() 320 339 longitude.clear()
longitude.addAll(populateLongitude(vessel)) 321 340 longitude.addAll(populateLongitude(vessel))
} 322 341 }
"Speed Over Ground" -> { 323 342 "Speed Over Ground" -> {
speedOverGround.clear() 324 343 speedOverGround.clear()
speedOverGround.addAll(populateSpeedOverGround(vessel)) 325 344 speedOverGround.addAll(populateSpeedOverGround(vessel))
} 326 345 }
"Course Over Ground" -> { 327 346 "Course Over Ground" -> {
courseOverGround.clear() 328 347 courseOverGround.clear()
courseOverGround.addAll(populateCourseOverGround(vessel)) 329 348 courseOverGround.addAll(populateCourseOverGround(vessel))
} 330 349 }
"Heading" -> { 331 350 "Heading" -> {
heading.clear() 332 351 heading.clear()
heading.addAll(populateHeading(vessel)) 333 352 heading.addAll(populateHeading(vessel))
} 334 353 }
"Vessel Name" -> { 335 354 "Vessel Name" -> {
vesselName.clear() 336 355 vesselName.clear()
vesselName.addAll(populateVesselName(vessel)) 337 356 vesselName.addAll(populateVesselName(vessel))
} 338 357 }
"IMO" -> { 339 358 "IMO" -> {
imo.clear() 340 359 imo.clear()
imo.addAll(populateIMO(vessel)) 341 360 imo.addAll(populateIMO(vessel))
} 342 361 }
"Call Sign" -> { 343 362 "Call Sign" -> {
callSign.clear() 344 363 callSign.clear()
callSign.addAll(populateCallSign(vessel)) 345 364 callSign.addAll(populateCallSign(vessel))
} 346 365 }
"Vessel Type" -> { 347 366 "Vessel Type" -> {
vesselType.clear() 348 367 vesselType.clear()
vesselType.addAll(populateVesselType(vessel)) 349 368 vesselType.addAll(populateVesselType(vessel))
} 350 369 }
"Status" -> { 351 370 "Status" -> {
status.clear() 352 371 status.clear()
status.addAll(populateStatus(vessel)) 353 372 status.addAll(populateStatus(vessel))
} 354 373 }
"Length" -> { 355 374 "Length" -> {
length.clear() 356 375 length.clear()
length.addAll(populateLength(vessel)) 357 376 length.addAll(populateLength(vessel))
} 358 377 }
"Width" -> { 359 378 "Width" -> {
width.clear() 360 379 width.clear()
width.addAll(populateWidth(vessel)) 361 380 width.addAll(populateWidth(vessel))
} 362 381 }
"Draft" -> { 363 382 "Draft" -> {
draft.clear() 364 383 draft.clear()
draft.addAll(populateDraft(vessel)) 365 384 draft.addAll(populateDraft(vessel))
} 366 385 }
"Cargo" -> { 367 386 "Cargo" -> {
cargo.clear() 368 387 cargo.clear()
cargo.addAll(populateCargo(vessel)) 369 388 cargo.addAll(populateCargo(vessel))
} 370 389 }
} 371 390 }
} 372 391 }
373 392
private fun setObservableCurrentTimeListener() { 374 393 private fun setObservableCurrentTimeListener() {
observableCurrentTime.listeners.add(object : CurrentTime { 375 394 observableCurrentTime.listeners.add(object : CurrentTime {
override fun onValueChanged(newValue: Int) { 376 395 override fun onValueChanged(newValue: Int) {
updateDataList(observableSelectedVessel.value) 377 396 updateDataList(observableSelectedVessel.value)
plot() 378 397 plot()
} 379 398 }
}) 380 399 })
} 381 400 }
382 401
override fun onValueChanged(newValue: Vessel) { 383 402 override fun onValueChanged(newValue: Vessel) {
updateDataList(newValue) 384 403 updateDataList(newValue)
plot() 385 404 plot()
} 386 405 }
387 406
} 388 407 }
389 408
390 409
391 410
src/main/kotlin/application/controller/MenuBarController.kt View file @ 5250f69
package application.controller 1 1 package application.controller
2 2
import application.model.MapState.* 3 3 import application.model.MapState.*
import application.model.createVesselCollection 4 4 import application.model.createVesselCollection
import application.model.observableIsReplayState 5 5 import application.model.observableIsReplayState
import application.model.observableMapState 6 6 import application.model.observableMapState
import application.model.observableVessel 7 7 import application.model.observableVessel
import javafx.event.EventHandler 8 8 import javafx.event.EventHandler
import javafx.fxml.FXML 9 9 import javafx.fxml.FXML
import javafx.fxml.Initializable 10 10 import javafx.fxml.Initializable
import javafx.scene.control.* 11 11 import javafx.scene.control.*
import javafx.stage.FileChooser 12 12 import javafx.stage.FileChooser
13 import java.io.*
import java.net.URL 13 14 import java.net.URL
import java.util.* 14 15 import java.util.*
15 16
17
class MenuBarController : Initializable { 16 18 class MenuBarController : Initializable {
17 19
@FXML 18 20 @FXML
var menuBar: MenuBar = MenuBar() 19 21 var menuBar: MenuBar = MenuBar()
20 22
@FXML 21 23 @FXML
var import: MenuItem = MenuItem() 22 24 var import: MenuItem = MenuItem()
23 25
@FXML 24 26 @FXML
var allMessages: CheckMenuItem = CheckMenuItem() 25 27 var allMessages: CheckMenuItem = CheckMenuItem()
26 28
@FXML 27 29 @FXML
var clusteredMessage: CheckMenuItem = CheckMenuItem() 28 30 var clusteredMessage: CheckMenuItem = CheckMenuItem()
29 31
@FXML 30 32 @FXML
var heatMap: CheckMenuItem = CheckMenuItem() 31 33 var heatMap: CheckMenuItem = CheckMenuItem()
32 34
@FXML 33 35 @FXML
var activateReplayButton: RadioMenuItem = RadioMenuItem() 34 36 var activateTimeSliderButton: RadioMenuItem = RadioMenuItem()
35 37
override fun initialize(location: URL?, resources: ResourceBundle?) { 36 38 override fun initialize(location: URL?, resources: ResourceBundle?) {
37 39
setOnActionImportButton() 38 40 setOnActionImportButton()
39 41
setOnActionAllMessageButton() 40 42 setOnActionAllMessageButton()
setOnActionClusteredMessageButton() 41 43 setOnActionClusteredMessageButton()
setOnActionHeatMapButton() 42 44 setOnActionHeatMapButton()
setOnActionActivateReplayButton() 43 45 setOnActionActivateReplayButton()
observableMapState.state = CLUSTERED_MESSAGES 44 46 observableMapState.state = CLUSTERED_MESSAGES
allMessages.isSelected = false 45 47 allMessages.isSelected = false
clusteredMessage.isSelected = true 46 48 clusteredMessage.isSelected = true
heatMap.isSelected = false 47 49 heatMap.isSelected = false
48 50
} 49 51 }
50 52
private fun setOnActionActivateReplayButton() { 51 53 private fun setOnActionActivateReplayButton() {
activateReplayButton.onAction = EventHandler { 52 54 activateTimeSliderButton.onAction = EventHandler {
observableIsReplayState.value = activateReplayButton.isSelected 53 55 observableIsReplayState.value = activateTimeSliderButton.isSelected
} 54 56 }
} 55 57 }
56 58
private fun setOnActionImportButton() { 57 59 private fun setOnActionImportButton() {
import.onAction = EventHandler { 58 60 import.onAction = EventHandler {
val fileChooser = FileChooser() 59 61 val fileChooser = FileChooser()
fileChooser.title = "Choose a file to import" 60 62 fileChooser.title = "Choose a file to import"
val window = menuBar.scene.window 61 63 val window = menuBar.scene.window
val file = fileChooser.showOpenDialog(window) 62 64 val file = fileChooser.showOpenDialog(window)
65
try { 63 66 try {
if (file.extension != "csv") { 64 67 if (file.extension != "csv") {
val alert = Alert(Alert.AlertType.WARNING) 65 68 val alert = Alert(Alert.AlertType.WARNING)
alert.title = "Warning Alert" 66 69 alert.title = "Warning Alert"
alert.headerText = "Wrong file format." 67 70 alert.headerText = "Wrong file format."
alert.contentText = "Please choose à .csv file." 68 71 alert.contentText = "Please choose à .csv file."
alert.showAndWait() 69 72 alert.showAndWait()
} 70 73 }
val vessels = createVesselCollection(file) 71
observableVessel.vessels.clear() 72 74 observableVessel.vessels.clear()
observableVessel.vessels = vessels 73 75 if(toMuchVessel(file)){
76 observableVessel.vessels = mutableMapOf()
77 }else {
78 val vessels = createVesselCollection(file)
79 observableVessel.vessels = vessels
80 }
} catch (ignore: IllegalStateException) { 74 81 } catch (ignore: IllegalStateException) {
75 82
} 76 83 }
} 77 84 }
} 78 85 }
79 86
87 private fun toMuchVessel(file: File): Boolean {
88 val nbLine = file.readLines().size
89 if (nbLine > 50000) {
90 val alert = Alert(Alert.AlertType.CONFIRMATION)
91 alert.title = "Warning!!"
92 alert.headerText = "Warning: This file contain a lot of messages."
93 alert.contentText = "Are you sure you want to continue."
94 val buttonTypeYes = ButtonType("Yes")
95 val buttonTypeNo = ButtonType("No ")
96 alert.buttonTypes.setAll(buttonTypeYes, buttonTypeNo)
97 val result = alert.showAndWait()
98
99 return result.get() != buttonTypeYes
100 }
101 return false
102 }
103
private fun setOnActionAllMessageButton() { 80 104 private fun setOnActionAllMessageButton() {
allMessages.onAction = EventHandler { 81 105 allMessages.onAction = EventHandler {
observableMapState.state = ALL_MESSAGES 82 106 observableMapState.state = ALL_MESSAGES
allMessages.isSelected = true 83 107 allMessages.isSelected = true
clusteredMessage.isSelected = false 84 108 clusteredMessage.isSelected = false
heatMap.isSelected = false 85 109 heatMap.isSelected = false
} 86 110 }
} 87 111 }
88 112
private fun setOnActionClusteredMessageButton() { 89 113 private fun setOnActionClusteredMessageButton() {
clusteredMessage.onAction = EventHandler { 90 114 clusteredMessage.onAction = EventHandler {
observableMapState.state = CLUSTERED_MESSAGES 91 115 observableMapState.state = CLUSTERED_MESSAGES
heatMap.isSelected = false 92 116 heatMap.isSelected = false
src/main/kotlin/application/controller/VesselListPanelController.kt View file @ 5250f69
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)
} 44 52 }
45 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 }
63 }
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/kotlin/application/model/Message.kt View file @ 5250f69
package application.model 1 1 package application.model
2 2
import java.time.LocalDateTime 3 3 import java.time.LocalDateTime
4 4
class Message(split: List<String>) { 5 5 class Message(split: List<String>) {
val mmsi = MMSI(if (split[0] == "") null else split[0]) 6 6 val mmsi = MMSI(if (split[0] == "") null else split[0])
val time = Time(LocalDateTime.parse(split[1])) 7 7 val time = Time(LocalDateTime.parse(split[1]))
val latitude = Latitude(split[2].toDoubleOrNull()) 8 8 val latitude = Latitude(split[2].toDoubleOrNull())
val longitude = Longitude(split[3].toDoubleOrNull()) 9 9 val longitude = Longitude(split[3].toDoubleOrNull())
val speedOverGround = SpeedOverGround(split[4].toDoubleOrNull()) 10 10 val speedOverGround = SpeedOverGround(split[4].toDoubleOrNull())
val courseOverGround = CourseOverGround(split[5].toDoubleOrNull()) 11 11 val courseOverGround = CourseOverGround(split[5].toDoubleOrNull())
val heading = Heading(split[6].toDoubleOrNull()) 12 12 val heading = Heading(split[6].toDoubleOrNull())
val vesselName = VesselName(if (split[7] == "") null else split[7]) 13 13 val vesselName = VesselName(if (split[7] == "") null else split[7])
val imo = IMO(if (split[8] == "") null else split[8]) 14 14 val imo = IMO(if (split[8] == "") null else split[8])
val callSign = CallSign(if (split[9] == "") null else split[9]) 15 15 val callSign = CallSign(if (split[9] == "") null else split[9])
val vesselType = VesselType(split[10].toIntOrNull()) 16 16 val vesselType = VesselType(split[10].toDoubleOrNull())
val status = Status(if (split[11] == "") null else split[11]) 17 17 val status = Status(if (split[11] == "") null else split[11])
val length = Length(split[12].toDoubleOrNull()) 18 18 val length = Length(split[12].toDoubleOrNull())
val width = Width(split[13].toDoubleOrNull()) 19 19 val width = Width(split[13].toDoubleOrNull())
val draft = Draft(split[14].toDoubleOrNull()) 20 20 val draft = Draft(split[14].toDoubleOrNull())
val cargo = Cargo(split[15].toIntOrNull()) 21 21 val cargo = Cargo(split[15].toDoubleOrNull())
22 22
fun getHexColorStroke(): String { 23 23 fun getHexColorStroke(): String {
var hex = Integer.toHexString(this.mmsi.value?.toInt()!!) 24 24 var hex = Integer.toHexString(this.mmsi.value?.toInt()!!)
if (hex.length > 6) { 25 25 if (hex.length > 6) {
hex = hex.substring(hex.length - 6) 26 26 hex = hex.substring(hex.length - 6)
} 27 27 }
return hex 28 28 return hex
} 29 29 }
src/main/kotlin/application/model/MessageData.kt View file @ 5250f69
package application.model 1 1 package application.model
2 2
import java.time.LocalDateTime 3 3 import java.time.LocalDateTime
4 4
interface MessageDataVisitor { 5 5 interface MessageDataVisitor {
fun visit(messageData: MMSI) 6 6 fun visit(messageData: MMSI)
fun visit(messageData: Time) 7 7 fun visit(messageData: Time)
fun visit(messageData: Latitude) 8 8 fun visit(messageData: Latitude)
fun visit(messageData: Longitude) 9 9 fun visit(messageData: Longitude)
fun visit(messageData: SpeedOverGround) 10 10 fun visit(messageData: SpeedOverGround)
fun visit(messageData: CourseOverGround) 11 11 fun visit(messageData: CourseOverGround)
fun visit(messageData: Heading) 12 12 fun visit(messageData: Heading)
fun visit(messageData: VesselName) 13 13 fun visit(messageData: VesselName)
fun visit(messageData: IMO) 14 14 fun visit(messageData: IMO)
fun visit(messageData: CallSign) 15 15 fun visit(messageData: CallSign)
fun visit(messageData: VesselType) 16 16 fun visit(messageData: VesselType)
fun visit(messageData: Status) 17 17 fun visit(messageData: Status)
fun visit(messageData: Length) 18 18 fun visit(messageData: Length)
fun visit(messageData: Width) 19 19 fun visit(messageData: Width)
fun visit(messageData: Draft) 20 20 fun visit(messageData: Draft)
fun visit(messageData: Cargo) 21 21 fun visit(messageData: Cargo)
} 22 22 }
23 23
interface MessageData { 24 24 interface MessageData {
25 25
fun accept(visitor: MessageDataVisitor) 26 26 fun accept(visitor: MessageDataVisitor)
27 27
} 28 28 }
29 29
data class MMSI(val value: String?) : MessageData { 30 30 data class MMSI(val value: String?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 31 31 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 32 32 }
33 33
data class Time(val value: LocalDateTime) : MessageData { 34 34 data class Time(val date: LocalDateTime) : MessageData {
35 val value: String?
36
37 init {
38 value = date.toString()
39 }
40
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 35 41 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 36 42 }
37 43
data class Latitude(val value: Double?) : MessageData { 38 44 data class Latitude(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 39 45 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 40 46 }
41 47
data class Longitude(val value: Double?) : MessageData { 42 48 data class Longitude(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 43 49 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 44 50 }
45 51
data class SpeedOverGround(val value: Double?) : MessageData { 46 52 data class SpeedOverGround(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 47 53 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 48 54 }
49 55
data class CourseOverGround(val value: Double?) : MessageData { 50 56 data class CourseOverGround(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 51 57 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 52 58 }
53 59
data class Heading(val value: Double?) : MessageData { 54 60 data class Heading(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 55 61 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 56 62 }
57 63
data class VesselName(val value: String?) : MessageData { 58 64 data class VesselName(val value: String?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 59 65 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 60 66 }
61 67
data class IMO(val value: String?) : MessageData { 62 68 data class IMO(val value: String?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 63 69 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 64 70 }
65 71
data class CallSign(val value: String?) : MessageData { 66 72 data class CallSign(val value: String?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 67 73 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 68 74 }
69 75
data class VesselType(val value: Int?) : MessageData { 70 76 data class VesselType(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 71 77 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 72 78 }
73 79
data class Status(val value: String?) : MessageData { 74 80 data class Status(val value: String?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 75 81 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 76 82 }
77 83
data class Length(val value: Double?) : MessageData { 78 84 data class Length(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 79 85 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 80 86 }
81 87
data class Width(val value: Double?) : MessageData { 82 88 data class Width(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 83 89 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 84 90 }
85 91
data class Draft(val value: Double?) : MessageData { 86 92 data class Draft(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 87 93 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 88 94 }
89 95
data class Cargo(val value: Int?) : MessageData { 90 96 data class Cargo(val value: Double?) : MessageData {
override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this) 91 97 override fun accept(visitor: MessageDataVisitor) = visitor.visit(messageData = this)
} 92 98 }
93 99
class GetValueVisitor() : MessageDataVisitor { 94 100 class GetValueVisitor() : MessageDataVisitor {
var value: String = "" 95 101 var value: String = ""
96 102
override fun visit(messageData: MMSI) { 97 103 override fun visit(messageData: MMSI) {
value = messageData.value.toString() 98 104 value = messageData.value.toString()
} 99 105 }
100 106
override fun visit(messageData: Time) { 101 107 override fun visit(messageData: Time) {
value = messageData.value.toString() 102 108 value = messageData.value.toString()
} 103 109 }
104 110
override fun visit(messageData: Latitude) { 105 111 override fun visit(messageData: Latitude) {
value = messageData.value.toString() 106 112 value = messageData.value.toString()
} 107 113 }
108 114
override fun visit(messageData: Longitude) { 109 115 override fun visit(messageData: Longitude) {
value = messageData.value.toString() 110 116 value = messageData.value.toString()
} 111 117 }
112 118
override fun visit(messageData: SpeedOverGround) { 113 119 override fun visit(messageData: SpeedOverGround) {
value = messageData.value.toString() 114 120 value = messageData.value.toString()
} 115 121 }
116 122
override fun visit(messageData: CourseOverGround) { 117 123 override fun visit(messageData: CourseOverGround) {
value = messageData.value.toString() 118 124 value = messageData.value.toString()
} 119 125 }
120 126
override fun visit(messageData: Heading) { 121 127 override fun visit(messageData: Heading) {
value = messageData.value.toString() 122 128 value = messageData.value.toString()
} 123 129 }
124 130
override fun visit(messageData: VesselName) { 125 131 override fun visit(messageData: VesselName) {
src/main/kotlin/application/model/Vessel.kt View file @ 5250f69
package application.model 1 1 package application.model
2 2
import java.util.* 3 3 import java.util.*
4 4
class Vessel(val mmsi: String?) { 5 5 class Vessel(val mmsi: String?) {
val messages: SortedMap<Long, Message> = sortedMapOf() 6 6 val messages: SortedMap<Long, Message> = sortedMapOf()
private val messageBeforeSelectedTime: Map<Long, Message> 7 7 private val messageBeforeSelectedTime: Map<Long, Message>
get() { 8 8 get() {
return messages.filter { observableCurrentTime.value > it.key } 9 9 return messages.filter { observableCurrentTime.value > it.key }
} 10 10 }
11 11
var messageToDisplay: Message? = null 12 12 var messageToDisplay: Message? = null
get() { 13 13 get() {
field = 14 14 field =
messages.asSequence().map { it }.firstOrNull { observableCurrentTime.value < it.key }.let { it?.value } 15 15 messages.asSequence().map { it }.firstOrNull { observableCurrentTime.value < it.key }.let { it?.value }
return field 16 16 return field
} 17 17 }
18 18
fun getAllTimeBeforeSelectedTime(): ArrayList<MessageData?> { 19 19 fun getAllTimeBeforeSelectedTime(): ArrayList<String> {
val timeList = arrayListOf<MessageData?>() 20 20 val timeList = arrayListOf<String>()
messageBeforeSelectedTime.forEach { 21 21 messageBeforeSelectedTime.forEach {
timeList.add(it.value.time) 22 22 if (it.value.time.value != null)
23 timeList.add(it.value.time.value!!)
} 23 24 }
24 25
return timeList 25 26 return timeList
} 26 27 }
27 28
fun getAllLatitudeBeforeSelectedTime(): ArrayList<MessageData?> { 28 29 fun getAllLatitudeBeforeSelectedTime(): ArrayList<Double> {
val latitudeList = arrayListOf<MessageData?>() 29 30 val latitudeList = arrayListOf<Double>()
messageBeforeSelectedTime.forEach { 30 31 messageBeforeSelectedTime.forEach {
latitudeList.add(it.value.latitude) 31 32 if (it.value.latitude.value != null)
33 latitudeList.add(it.value.latitude.value!!)
} 32 34 }
33 35
return latitudeList 34 36 return latitudeList
} 35 37 }
36 38
fun getAllLongitudeBeforeSelectedTime(): ArrayList<MessageData?> { 37 39 fun getAllLongitudeBeforeSelectedTime(): ArrayList<Double> {
val longitudeList = arrayListOf<MessageData?>() 38 40 val longitudeList = arrayListOf<Double>()
messageBeforeSelectedTime.forEach { 39 41 messageBeforeSelectedTime.forEach {
longitudeList.add(it.value.longitude) 40 42 if (it.value.longitude.value != null)
43 longitudeList.add(it.value.longitude.value!!)
} 41 44 }
42 45
return longitudeList 43 46 return longitudeList
} 44 47 }
45 48
fun getAllSpeedOverGroundBeforeSelectedTime(): ArrayList<MessageData?> { 46 49 fun getAllSpeedOverGroundBeforeSelectedTime(): ArrayList<Double> {
val speedOverGroundList = arrayListOf<MessageData?>() 47 50 val speedOverGroundList = arrayListOf<Double>()
messageBeforeSelectedTime.forEach { 48 51 messageBeforeSelectedTime.forEach {
speedOverGroundList.add(it.value.speedOverGround) 49 52 if (it.value.speedOverGround.value != null)
53 speedOverGroundList.add(it.value.speedOverGround.value!!)
} 50 54 }
51 55
return speedOverGroundList 52 56 return speedOverGroundList
} 53 57 }
54 58
fun getAllCourseOverGroundBeforeSelectedTime(): ArrayList<MessageData?> { 55 59 fun getAllCourseOverGroundBeforeSelectedTime(): ArrayList<Double> {
val res = arrayListOf<MessageData?>() 56 60 val res = arrayListOf<Double>()
messageBeforeSelectedTime.forEach { 57 61 messageBeforeSelectedTime.forEach {
res.add(it.value.courseOverGround) 58 62 if (it.value.courseOverGround.value != null)
63 res.add(it.value.courseOverGround.value!!)
} 59 64 }
60 65
return res 61 66 return res
} 62 67 }
63 68
fun getAllHeadingBeforeSelectedTime(): ArrayList<MessageData?> { 64 69 fun getAllHeadingBeforeSelectedTime(): ArrayList<Double> {
val res = arrayListOf<MessageData?>() 65 70 val res = arrayListOf<Double>()
messageBeforeSelectedTime.forEach { 66 71 messageBeforeSelectedTime.forEach {
res.add(it.value.heading) 67 72 if (it.value.heading.value != null)
73 res.add(it.value.heading.value!!)
} 68 74 }
69 75
return res 70 76 return res
} 71 77 }
72 78
fun getAllVesselNameBeforeSelectedTime(): ArrayList<MessageData?> { 73 79 fun getAllVesselNameBeforeSelectedTime(): ArrayList<String> {
val res = arrayListOf<MessageData?>() 74 80 val res = arrayListOf<String>()
messageBeforeSelectedTime.forEach { 75 81 messageBeforeSelectedTime.forEach {
res.add(it.value.vesselName) 76 82 if (it.value.vesselName.value != null)
83 res.add(it.value.vesselName.value!!)
} 77 84 }
return res 78 85 return res
} 79 86 }
80 87
fun getAllIMOBeforeSelectedTime(): ArrayList<MessageData?> { 81 88 fun getAllIMOBeforeSelectedTime(): ArrayList<String> {
val res = arrayListOf<MessageData?>() 82 89 val res = arrayListOf<String>()
messageBeforeSelectedTime.forEach { 83 90 messageBeforeSelectedTime.forEach {
res.add(it.value.imo) 84 91 if (it.value.imo.value != null)
92 res.add(it.value.imo.value!!)
} 85 93 }
return res 86 94 return res
} 87 95 }
88 96
fun getAllCallSignBeforeSelectedTime(): ArrayList<MessageData?> { 89 97 fun getAllCallSignBeforeSelectedTime(): ArrayList<String> {
val res = arrayListOf<MessageData?>() 90 98 val res = arrayListOf<String>()
messageBeforeSelectedTime.forEach { 91 99 messageBeforeSelectedTime.forEach {
res.add(it.value.callSign) 92 100 if (it.value.callSign.value != null)
101 res.add(it.value.callSign.value!!)
} 93 102 }
return res 94 103 return res
} 95 104 }
96 105
fun getAllVesselTypeBeforeSelectedTime(): ArrayList<MessageData?> { 97 106 fun getAllVesselTypeBeforeSelectedTime(): ArrayList<Double> {
val res = arrayListOf<MessageData?>() 98 107 val res = arrayListOf<Double>()
messageBeforeSelectedTime.forEach { 99 108 messageBeforeSelectedTime.forEach {
res.add(it.value.vesselType) 100 109 if (it.value.vesselType.value != null)
110 res.add(it.value.vesselType.value!!)
} 101 111 }
return res 102 112 return res
} 103 113 }
104 114
fun getAllStatusBeforeSelectedTime(): ArrayList<MessageData?> { 105 115 fun getAllStatusBeforeSelectedTime(): ArrayList<String> {
val res = arrayListOf<MessageData?>() 106 116 val res = arrayListOf<String>()
messageBeforeSelectedTime.forEach { 107 117 messageBeforeSelectedTime.forEach {
res.add(it.value.status) 108 118 if (it.value.status.value != null)
119 res.add(it.value.status.value!!)
} 109 120 }
return res 110 121 return res
} 111 122 }
112 123
fun getAllLengthBeforeSelectedTime(): ArrayList<MessageData?> { 113 124 fun getAllLengthBeforeSelectedTime(): ArrayList<Double> {
val res = arrayListOf<MessageData?>() 114 125 val res = arrayListOf<Double>()
messageBeforeSelectedTime.forEach { 115 126 messageBeforeSelectedTime.forEach {
res.add(it.value.length) 116 127 if (it.value.length.value != null)
128 res.add(it.value.length.value!!)
} 117 129 }
return res 118 130 return res
} 119 131 }
120 132
fun getAllWidthBeforeSelectedTime(): ArrayList<MessageData?> { 121 133 fun getAllWidthBeforeSelectedTime(): ArrayList<Double> {
val res = arrayListOf<MessageData?>() 122 134 val res = arrayListOf<Double>()
messageBeforeSelectedTime.forEach { 123 135 messageBeforeSelectedTime.forEach {
res.add(it.value.width) 124 136 if (it.value.width.value != null)
137 res.add(it.value.width.value!!)
} 125 138 }
return res 126 139 return res
} 127 140 }
128 141
fun getAllDraftBeforeSelectedTime(): ArrayList<MessageData?> { 129 142 fun getAllDraftBeforeSelectedTime(): ArrayList<Double> {
val res = arrayListOf<MessageData?>() 130 143 val res = arrayListOf<Double>()
messageBeforeSelectedTime.forEach { 131 144 messageBeforeSelectedTime.forEach {
res.add(it.value.draft) 132 145 if (it.value.draft.value != null)
146 res.add(it.value.draft.value!!)
} 133 147 }
return res 134 148 return res
} 135 149 }
136 150
fun getAllCargoBeforeSelectedTime(): ArrayList<MessageData?> { 137 151 fun getAllCargoBeforeSelectedTime(): ArrayList<Double> {
val res = arrayListOf<MessageData?>() 138 152 val res = arrayListOf<Double>()
messageBeforeSelectedTime.forEach { 139 153 messageBeforeSelectedTime.forEach {
res.add(it.value.cargo) 140 154 if (it.value.cargo.value != null)
155 res.add(it.value.cargo.value!!)
} 141 156 }
return res 142 157 return res
} 143 158 }
144 159
fun getAllTime(): ArrayList<MessageData?> { 145 160 fun getAllTime(): ArrayList<String> {
val timeList = arrayListOf<MessageData?>() 146 161 val timeList = arrayListOf<String>()
messages.forEach { 147 162 messages.forEach {
timeList.add(it.value.time) 148 163 if (it.value.time.value != null)
164 timeList.add(it.value.time.value!!)
} 149 165 }
150 166
return timeList 151 167 return timeList
} 152 168 }
153 169
fun getAllLatitude(): ArrayList<MessageData?> { 154 170 fun getAllLatitude(): ArrayList<Double> {
val latitudeList = arrayListOf<MessageData?>() 155 171 val latitudeList = arrayListOf<Double>()
messages.forEach { 156 172 messages.forEach {
latitudeList.add(it.value.latitude) 157 173 if (it.value.latitude.value != null)
174 latitudeList.add(it.value.latitude.value!!)
} 158 175 }
159 176
return latitudeList 160 177 return latitudeList
} 161 178 }
162 179
fun getAllLongitude(): ArrayList<MessageData?> { 163 180 fun getAllLongitude(): ArrayList<Double> {
val longitudeList = arrayListOf<MessageData?>() 164 181 val longitudeList = arrayListOf<Double>()
messages.forEach { 165 182 messages.forEach {
longitudeList.add(it.value.longitude) 166 183 if (it.value.longitude.value != null)
184 longitudeList.add(it.value.longitude.value!!)
} 167 185 }
168 186
return longitudeList 169 187 return longitudeList
} 170 188 }
171 189
fun getAllSpeedOverGround(): ArrayList<MessageData?> { 172 190 fun getAllSpeedOverGround(): ArrayList<Double> {
val speedOverGroundList = arrayListOf<MessageData?>() 173 191 val speedOverGroundList = arrayListOf<Double>()
messages.forEach { 174 192 messages.forEach {
speedOverGroundList.add(it.value.speedOverGround) 175 193 if (it.value.speedOverGround.value != null)
194 speedOverGroundList.add(it.value.speedOverGround.value!!)
} 176 195 }
177 196
return speedOverGroundList 178 197 return speedOverGroundList
} 179 198 }
180 199
fun getAllCourseOverGround(): ArrayList<MessageData?> { 181 200 fun getAllCourseOverGround(): ArrayList<Double> {
val res = arrayListOf<MessageData?>() 182 201 val res = arrayListOf<Double>()
messages.forEach { 183 202 messages.forEach {
res.add(it.value.courseOverGround) 184 203 if (it.value.courseOverGround.value != null)
204 res.add(it.value.courseOverGround.value!!)
} 185 205 }
186 206
return res 187 207 return res
} 188 208 }
189 209
fun getAllHeading(): ArrayList<MessageData?> { 190 210 fun getAllHeading(): ArrayList<Double> {
val res = arrayListOf<MessageData?>() 191 211 val res = arrayListOf<Double>()
messages.forEach { 192 212 messages.forEach {
res.add(it.value.heading) 193 213 if (it.value.heading.value != null)
214 res.add(it.value.heading.value!!)
} 194 215 }
195 216
return res 196 217 return res
} 197 218 }
198 219
fun getAllVesselName(): ArrayList<MessageData?> { 199 220 fun getAllVesselName(): ArrayList<String> {
val res = arrayListOf<MessageData?>() 200 221 val res = arrayListOf<String>()
messages.forEach { 201 222 messages.forEach {
res.add(it.value.vesselName) 202 223 if (it.value.vesselName.value != null)
224 res.add(it.value.vesselName.value!!)
} 203 225 }
return res 204 226 return res
} 205 227 }
206 228
fun getAllIMO(): ArrayList<MessageData?> { 207 229 fun getAllIMO(): ArrayList<String> {
val res = arrayListOf<MessageData?>() 208 230 val res = arrayListOf<String>()
messages.forEach { 209 231 messages.forEach {
res.add(it.value.imo) 210 232 if (it.value.imo.value != null)
233 res.add(it.value.imo.value!!)
} 211 234 }
return res 212 235 return res
} 213 236 }
214 237
fun getAllCallSign(): ArrayList<MessageData?> { 215 238 fun getAllCallSign(): ArrayList<String> {
val res = arrayListOf<MessageData?>() 216 239 val res = arrayListOf<String>()
messages.forEach { 217 240 messages.forEach {
res.add(it.value.callSign) 218 241 if (it.value.callSign.value != null)
242 res.add(it.value.callSign.value!!)
} 219 243 }
return res 220 244 return res
} 221 245 }
222 246
fun getAllVesselType(): ArrayList<MessageData?> { 223 247 fun getAllVesselType(): ArrayList<Double> {
val res = arrayListOf<MessageData?>() 224 248 val res = arrayListOf<Double>()
messages.forEach { 225 249 messages.forEach {
res.add(it.value.vesselType) 226 250 if (it.value.vesselType.value != null)
251 res.add(it.value.vesselType.value!!)
} 227 252 }
return res 228 253 return res
} 229 254 }
230 255
fun getAllStatus(): ArrayList<MessageData?> { 231 256 fun getAllStatus(): ArrayList<String> {
val res = arrayListOf<MessageData?>() 232 257 val res = arrayListOf<String>()
messages.forEach { 233 258 messages.forEach {
res.add(it.value.status) 234 259 if (it.value.status.value != null)
260 res.add(it.value.status.value!!)
} 235 261 }
return res 236 262 return res
} 237 263 }
238 264
fun getAllLength(): ArrayList<MessageData?> { 239 265 fun getAllLength(): ArrayList<Double> {
val res = arrayListOf<MessageData?>() 240 266 val res = arrayListOf<Double>()
messages.forEach { 241 267 messages.forEach {
res.add(it.value.length) 242 268 if (it.value.length.value != null)
269 res.add(it.value.length.value!!)
} 243 270 }
return res 244 271 return res
} 245 272 }
246 273
fun getAllWidth(): ArrayList<MessageData?> { 247 274 fun getAllWidth(): ArrayList<Double> {
val res = arrayListOf<MessageData?>() 248 275 val res = arrayListOf<Double>()
messages.forEach { 249 276 messages.forEach {
res.add(it.value.width) 250 277 if (it.value.width.value != null)
278 res.add(it.value.width.value!!)
} 251 279 }
return res 252 280 return res
} 253 281 }
254 282
fun getAllDraft(): ArrayList<MessageData?> { 255 283 fun getAllDraft(): ArrayList<Double> {
val res = arrayListOf<MessageData?>() 256 284 val res = arrayListOf<Double>()
messages.forEach { 257 285 messages.forEach {
res.add(it.value.draft) 258 286 if (it.value.draft.value != null)
287 res.add(it.value.draft.value!!)
} 259 288 }
return res 260 289 return res
} 261 290 }
262 291
fun getAllCargo(): ArrayList<MessageData?> { 263 292 fun getAllCargo(): ArrayList<Double> {
val res = arrayListOf<MessageData?>() 264 293 val res = arrayListOf<Double>()
messages.forEach { 265 294 messages.forEach {
res.add(it.value.cargo) 266 295 if (it.value.cargo.value != null)
296 res.add(it.value.cargo.value!!)
297
} 267 298 }
return res 268 299 return res
} 269 300 }
270 301
companion object { 271 302 companion object {
var maxTime: Long = 0 272 303 var maxTime: Long = 0
var minTime: Long = 0 273 304 var minTime: Long = 0
} 274 305 }
275 306
} 276 307 }
src/main/kotlin/application/model/VesselGenerator.kt View file @ 5250f69
package application.model 1 1 package application.model
2 2
import java.io.File 3 3 import java.io.File
import java.time.ZoneOffset 4 4 import java.time.ZoneOffset
import java.util.* 5 5 import java.util.*
6 6
fun createVesselCollection(file: File): SortedMap<String, Vessel> { 7 7 fun createVesselCollection(file: File): SortedMap<String, Vessel> {
val messages: ArrayList<Message> = arrayListOf() 8 8 val messages: ArrayList<Message> = arrayListOf()
val vessels: SortedMap<String, Vessel> = sortedMapOf() 9 9 val vessels: SortedMap<String, Vessel> = sortedMapOf()
var maxTime: Long = 0 10 10 var maxTime: Long = 0
var minTime: Long = Long.MAX_VALUE 11 11 var minTime: Long = Long.MAX_VALUE
12 12
file.forEachLine { 13 13 file.forEachLine {
val arrayMessage = it.split(",") 14 14 val arrayMessage = it.split(",")
if (arrayMessage[0].toIntOrNull() !== null) { 15 15 if (arrayMessage[0].toIntOrNull() !== null) {
val message = Message(arrayMessage) 16 16 val message = Message(arrayMessage)
messages.add(message) 17 17 messages.add(message)
if (!vessels.containsKey(message.mmsi.value)) { 18 18 if (!vessels.containsKey(message.mmsi.value)) {
vessels[message.mmsi.value] = Vessel(message.mmsi.value!!) 19 19 vessels[message.mmsi.value] = Vessel(message.mmsi.value!!)
} 20 20 }
val time = message.time.value.toEpochSecond(ZoneOffset.UTC) 21 21 val time = message.time.date.toEpochSecond(ZoneOffset.UTC)
vessels[message.mmsi.value]?.messages?.set(time, message) 22 22 vessels[message.mmsi.value]?.messages?.set(time, message)
if (time > maxTime) { 23 23 if (time > maxTime) {
maxTime = time 24 24 maxTime = time
} 25 25 }
if (time < minTime){ 26 26 if (time < minTime){
minTime = time 27 27 minTime = time
} 28 28 }
} 29 29 }
} 30 30 }
31 31
Vessel.maxTime = maxTime 32 32 Vessel.maxTime = maxTime
src/main/resources/gui/mapPanel.fxml View file @ 5250f69
<?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 @ 5250f69
<?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="activateTimeSliderButton" mnemonicParsing="false" text="Time Slider" />
</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>
</MenuBar> 30 30 </MenuBar>
src/main/resources/gui/timePanel.fxml View file @ 5250f69
<?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 @ 5250f69
<?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 @ 5250f69
<?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>