Compare View
Commits (7)
Diff
Showing 13 changed files Inline Diff
- src/main/kotlin/application/App.kt
- src/main/kotlin/application/controller/DataPanelController.kt
- src/main/kotlin/application/controller/MenuBarController.kt
- src/main/kotlin/application/controller/VesselListPanelController.kt
- src/main/kotlin/application/model/Message.kt
- src/main/kotlin/application/model/MessageData.kt
- src/main/kotlin/application/model/Vessel.kt
- src/main/kotlin/application/model/VesselGenerator.kt
- src/main/resources/gui/mapPanel.fxml
- src/main/resources/gui/menuBar.fxml
- src/main/resources/gui/timePanel.fxml
- src/main/resources/gui/vesselListPanel.fxml
- src/main/resources/gui/windows.fxml
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> |