package application.controller import application.model.* import javafx.collections.FXCollections import javafx.collections.ObservableList import javafx.fxml.FXML import javafx.fxml.Initializable import javafx.scene.control.ListCell import javafx.scene.control.ListView import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import org.charts.dataviewer.api.config.DataViewerConfiguration import org.charts.dataviewer.api.data.PlotData import org.charts.dataviewer.api.trace.ScatterTrace import org.charts.dataviewer.javafx.JavaFxDataViewer import org.charts.dataviewer.utils.TraceColour import org.charts.dataviewer.utils.TraceVisibility import java.net.URL import java.util.* class DataPanelController : Initializable, SelectedVesselListener { private var dataList: ObservableList = FXCollections.observableArrayList() private lateinit var timeData: ArrayList private val latitude: ArrayList = arrayListOf() private val longitude: ArrayList = arrayListOf() private val speedOverGround: ArrayList = arrayListOf() private val courseOverGround: ArrayList = arrayListOf() private val heading: ArrayList = arrayListOf() private val vesselName: ArrayList = arrayListOf() private val imo: ArrayList = arrayListOf() private val callSign: ArrayList = arrayListOf() private val vesselType: ArrayList = arrayListOf() private val status: ArrayList = arrayListOf() private val length: ArrayList = arrayListOf() private val width: ArrayList = arrayListOf() private val draft: ArrayList = arrayListOf() private val cargo: ArrayList = arrayListOf() private var selectedItem: String? = null @FXML var dataListView = ListView() @FXML var dataViewer = JavaFxDataViewer() private val plotData = PlotData() private val config = DataViewerConfiguration() override fun initialize(location: URL?, resources: ResourceBundle?) { setObservableSelectedVesselListener() dataListView.items = dataList config.showLegend(false) config.setLegendInsidePlot(false) setObservableCurrentTimeListener() dataListView.setCellFactory { object : ListCell() { override fun updateItem(item: String?, empty: Boolean) { super.updateItem(item, empty) text = if (empty) { null } else { item } } } } dataListView.selectionModel.selectedItemProperty().addListener { _, _, newValue -> selectedItem = newValue updateDataList(observableSelectedVessel.value) plot(newValue) } plotData.allTraces.clear() config.setxAxisTitle("") config.setyAxisTitle("") config.plotTitle = "" dataViewer.updateConfiguration(config) dataViewer.updatePlot(plotData) initDataList() } private fun plot() { if (selectedItem != null && observableSelectedVessel.value.messages.size != 0) { GlobalScope.launch { plot(selectedItem) } } } private fun plot(data: String?) { if (data == null) { plotData.allTraces.clear() config.setxAxisTitle("") config.setyAxisTitle("") dataViewer.updateConfiguration(config) dataViewer.resetPlot() return } val scatterTrace = ScatterTrace() scatterTrace.traceColour = TraceColour.RED scatterTrace.traceVisibility = TraceVisibility.TRUE val serieStringX: Array = timeData.toTypedArray() // val serieDoubleX: Array = arrayListDoubleX.toTypedArray() var serieStringY: Array = arrayOf() var serieDoubleY: Array = arrayOf() when (data) { "Latitude" -> { serieDoubleY = latitude.toTypedArray() } "Longitude" -> { serieDoubleY = longitude.toTypedArray() } "Speed Over Ground" -> { serieDoubleY = speedOverGround.toTypedArray() } "Course Over Ground" -> { serieDoubleY = courseOverGround.toTypedArray() } "Heading" -> { serieDoubleY = heading.toTypedArray() } "Vessel Name" -> { serieStringY = vesselName.toTypedArray() } "IMO" -> { serieStringY = imo.toTypedArray() } "Call Sign" -> { serieStringY = callSign.toTypedArray() } "Vessel Type" -> { serieDoubleY = vesselType.toTypedArray() } "Status" -> { serieStringY = status.toTypedArray() } "Length" -> { serieDoubleY = length.toTypedArray() } "Width" -> { serieDoubleY = width.toTypedArray() } "Draft" -> { serieDoubleY = draft.toTypedArray() } "Cargo" -> { serieDoubleY = cargo.toTypedArray() } } if (serieStringY.isNotEmpty()) { scatterTrace.setxArray(serieStringX) scatterTrace.setyArray(serieStringY) } else { scatterTrace.setxArray(serieStringX) scatterTrace.setyArray(serieDoubleY) } config.plotTitle = "" config.setxAxisTitle("Time (s)") config.setyAxisTitle(data) dataViewer.resetPlot() plotData.allTraces.clear() plotData.addTrace(scatterTrace) dataViewer.updateConfiguration(config) dataViewer.updatePlot(plotData) } private fun setObservableSelectedVesselListener() { observableSelectedVessel.listeners.add(this) } private fun populateTime(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllTimeBeforeSelectedTime() } else { vessel.getAllTime() } } private fun populateLatitude(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllLatitudeBeforeSelectedTime() } else { vessel.getAllLatitude() } } private fun populateLongitude(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllLongitudeBeforeSelectedTime() } else { vessel.getAllLongitude() } } private fun populateSpeedOverGround(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllSpeedOverGroundBeforeSelectedTime() } else { vessel.getAllSpeedOverGround() } } private fun populateCourseOverGround(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllCourseOverGroundBeforeSelectedTime() } else { vessel.getAllCourseOverGround() } } private fun populateHeading(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllHeadingBeforeSelectedTime() } else { vessel.getAllHeading() } } private fun populateVesselName(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllVesselNameBeforeSelectedTime() } else { vessel.getAllVesselName() } } private fun populateIMO(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllIMOBeforeSelectedTime() } else { vessel.getAllIMO() } } private fun populateCallSign(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllCallSignBeforeSelectedTime() } else { vessel.getAllCallSign() } } private fun populateVesselType(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllVesselTypeBeforeSelectedTime() } else { vessel.getAllVesselType() } } private fun populateStatus(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllStatusBeforeSelectedTime() } else { vessel.getAllStatus() } } private fun populateLength(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllLengthBeforeSelectedTime() } else { vessel.getAllLength() } } private fun populateWidth(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllWidthBeforeSelectedTime() } else { vessel.getAllWidth() } } private fun populateDraft(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllDraftBeforeSelectedTime() } else { vessel.getAllDraft() } } private fun populateCargo(vessel: Vessel): ArrayList { return if (observableIsReplayState.value) { vessel.getAllCargoBeforeSelectedTime() } else { vessel.getAllCargo() } } private fun initDataList() { val data = arrayListOf() data.add("Latitude") data.add("Longitude") data.add("Speed Over Ground") data.add("Course Over Ground") data.add("Heading") data.add("Vessel Name") data.add("IMO") data.add("Call Sign") data.add("Vessel Type") data.add("Status") data.add("Length") data.add("Width") data.add("Draft") data.add("Cargo") dataList.addAll(data) } private fun updateDataList(vessel: Vessel) { timeData = populateTime(vessel) if (dataListView.selectionModel.selectedItem == null) return when (dataListView.selectionModel.selectedItem) { "Latitude" -> { latitude.clear() latitude.addAll(populateLatitude(vessel)) } "Longitude" -> { longitude.clear() longitude.addAll(populateLongitude(vessel)) } "Speed Over Ground" -> { speedOverGround.clear() speedOverGround.addAll(populateSpeedOverGround(vessel)) } "Course Over Ground" -> { courseOverGround.clear() courseOverGround.addAll(populateCourseOverGround(vessel)) } "Heading" -> { heading.clear() heading.addAll(populateHeading(vessel)) } "Vessel Name" -> { vesselName.clear() vesselName.addAll(populateVesselName(vessel)) } "IMO" -> { imo.clear() imo.addAll(populateIMO(vessel)) } "Call Sign" -> { callSign.clear() callSign.addAll(populateCallSign(vessel)) } "Vessel Type" -> { vesselType.clear() vesselType.addAll(populateVesselType(vessel)) } "Status" -> { status.clear() status.addAll(populateStatus(vessel)) } "Length" -> { length.clear() length.addAll(populateLength(vessel)) } "Width" -> { width.clear() width.addAll(populateWidth(vessel)) } "Draft" -> { draft.clear() draft.addAll(populateDraft(vessel)) } "Cargo" -> { cargo.clear() cargo.addAll(populateCargo(vessel)) } } } private fun setObservableCurrentTimeListener() { observableCurrentTime.listeners.add(object : CurrentTime { override fun onValueChanged(newValue: Int) { updateDataList(observableSelectedVessel.value) plot() } }) } override fun onValueChanged(newValue: Vessel) { updateDataList(newValue) plot() } }