package de.uniluebeck.mi.projmi6.controller; /** * Created by Johannes on 12.11.15. */ import de.uniluebeck.mi.projmi6.db.DBHandler; import de.uniluebeck.mi.projmi6.model.Patient; import de.uniluebeck.mi.projmi6.model.Station; import de.uniluebeck.mi.projmi6.model.StationsUebersichtsItem; import de.uniluebeck.mi.projmi6.view.SelectKeyComboBoxListener; import javafx.beans.binding.Bindings; import javafx.beans.binding.ObjectBinding; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.collections.transformation.FilteredList; import javafx.concurrent.Task; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.image.Image; import javafx.stage.Modality; import javafx.stage.Stage; import java.io.IOException; import java.time.LocalDate; import java.util.List; /** * Controller class. */ public class PatientTablesController { private final MainController mainController; /** * The placeholder labels in case the TableViews are empty */ @FXML private Label lblTablePatientEmpty, lblTableStationEmpty; @FXML private Button btnPatCreate, btnPatEdit, btnPatRefresh; @FXML private TableView tblPatientOverview; @FXML private TableColumn colPatPatId, colPatGeburtsname, colPatNachname, colPatVorname, colPatStrasse, colPatPlz, colPatOrt, colPatCave; @FXML private TableColumn colPatGebDatum; @FXML private ToggleButton btnEntlassenePatientenZeigen; @FXML private Button btnStatRefresh; @FXML private ComboBox cmbStationenFilter; @FXML private TableView tblStationOverview; @FXML private TableColumn colStatPatId, colStatAlter; @FXML private TableColumn colStatFullName; @FXML private TableColumn colStatGebDatum, colStatAufnahmedatum, colStatEntlassungsdatum; @FXML private TabPane patientOverviewTabPane; @FXML private Tab stationOverviewTab, patientOverviewTab; private final ObservableList stationsUebersicht = FXCollections.observableArrayList(); private final FilteredList stationsUebersichtsItemFilteredList = new FilteredList(stationsUebersicht, item -> item.getStationEntlassung() == null || item.getStationEntlassung().isAfter(LocalDate.now())); private Task loadStationsHistorieTask = null; private Task loadPatientTask = null; private ObjectBinding patientObjectBinding = null; /** * Constructor. * * @param mainController The controller that creates this instance */ public PatientTablesController(MainController mainController) { this.mainController = mainController; } /** * Getter for the TabPane that contains patient and hospital ward overview tabs. */ public TabPane getPatientOverviewTabPane() { return patientOverviewTabPane; } /** * FXMLLoaders initialize()-method. */ @FXML private void initialize() { btnPatEdit.disableProperty().bind(tblPatientOverview.getSelectionModel().selectedItemProperty().isNull()); tblPatientOverview.setRowFactory(tableView -> { TableRow tableRow = new TableRow<>(); tableRow.setOnMouseClicked(event -> { if (event.getClickCount() == 2 && (!tableRow.isEmpty())) { Patient patient = tableRow.getItem(); showEditWindow(patient); } }); return tableRow; }); tblPatientOverview.itemsProperty().bind(mainController.getStammdaten().patientenProperty()); lblTablePatientEmpty.setText("Liste ist leer."); tblStationOverview.disableProperty().bind(cmbStationenFilter.valueProperty().isNull()); cmbStationenFilter.itemsProperty().bind(mainController.getStammdaten().stationenProperty()); new SelectKeyComboBoxListener(cmbStationenFilter); patientObjectBinding = Bindings.createObjectBinding(() -> { if (patientOverviewTabPane.getSelectionModel().getSelectedItem().equals(patientOverviewTab)) { return tblPatientOverview.getSelectionModel().getSelectedItem(); } else if (tblStationOverview.getSelectionModel().getSelectedItem() == null) { return null; } else { int selectedPatId = tblStationOverview.getSelectionModel().getSelectedItem().getPatId(); return tblPatientOverview.getItems().stream().filter(p -> p.getPatID() == selectedPatId).findFirst().orElse(null); } }, tblPatientOverview.getSelectionModel().selectedItemProperty(), tblStationOverview.getSelectionModel().selectedItemProperty(), patientOverviewTabPane.getSelectionModel().selectedItemProperty()); initColumnsPatient(); initColumnsStation(); updatePatientsFromDb(); } /** * Set up cell value factories for the patients table. */ private void initColumnsPatient() { colPatPatId.setCellValueFactory(cellDataFeatures -> cellDataFeatures.getValue().patIDProperty().asString()); colPatGeburtsname.setCellValueFactory(new PropertyValueFactory<>("geburtsname")); colPatNachname.setCellValueFactory(new PropertyValueFactory<>("nachname")); colPatVorname.setCellValueFactory(new PropertyValueFactory<>("vorname")); colPatGebDatum.setCellValueFactory(cellDataFeatures -> cellDataFeatures.getValue().geburtsdatumProperty()); colPatStrasse.setCellValueFactory(cellDataFeatures -> { Patient patient = cellDataFeatures.getValue(); return Bindings.concat(patient.strasseProperty(), " ", patient.hausnummerProperty()); }); colPatPlz.setCellValueFactory(new PropertyValueFactory<>("plz")); colPatOrt.setCellValueFactory(new PropertyValueFactory<>("ort")); colPatCave.setCellValueFactory(new PropertyValueFactory<>("cave")); } /** * Set up cell value factories for the hospital ward overview. */ private void initColumnsStation() { colStatPatId.setCellValueFactory(new PropertyValueFactory("patId")); colStatFullName.setCellValueFactory(cellDataFeatures -> cellDataFeatures.getValue().patNameProperty()); colStatGebDatum.setCellValueFactory(cellDataFeatures -> cellDataFeatures.getValue().patBirthdateProperty()); colStatAlter.setCellValueFactory(new PropertyValueFactory("patAge")); colStatAufnahmedatum.setCellValueFactory(cellDataFeatures -> cellDataFeatures.getValue().stationAufnahmeProperty()); colStatEntlassungsdatum.setCellValueFactory(cellDataFeatures -> cellDataFeatures.getValue().stationEntlassungProperty()); //Reload data if the user selects another ward. cmbStationenFilter.valueProperty().addListener((observableValue, oldValue, newValue) -> { updateStationsHistorieFromDb(); }); //Init filter tblStationOverview.itemsProperty().bind(Bindings.createObjectBinding(() -> { if (btnEntlassenePatientenZeigen.isSelected()) { return stationsUebersicht; } else { return stationsUebersichtsItemFilteredList; } }, btnEntlassenePatientenZeigen.selectedProperty())); } /** * EventHandler for {@link #btnPatCreate} */ @FXML private void clickedCreatePatient() { showEditWindow(null); } /** * EventHandler for {@link #btnPatEdit} */ @FXML private void clickedEditPatient() { showEditWindow(tblPatientOverview.getSelectionModel().getSelectedItem()); } /** * Opens a window for editing the given patient. * * @param patient The patient that should be opened for editing. */ private void showEditWindow(Patient patient) { FXMLLoader fxmlLoader = new FXMLLoader(); fxmlLoader.setLocation(getClass().getClassLoader().getResource("patient_edit.fxml")); PatientEditorController patientEditorController = new PatientEditorController(mainController); fxmlLoader.setControllerFactory(clazz -> patientEditorController); Parent root = null; try { root = fxmlLoader.load(); } catch (IOException e) { e.printStackTrace(); return; } Stage stage = new Stage(); stage.setTitle(patient == null ? "Neuen Patienten erstellen" : "Patient bearbeiten"); stage.setScene(new Scene(root, 600, 600)); stage.getIcons().add(new Image("icon.png")); stage.initModality(Modality.WINDOW_MODAL); stage.initOwner(btnPatEdit.getScene().getWindow()); patientEditorController.setPatient(patient); stage.showAndWait(); } /** * Highlight the given patient in the list, if patient was changed outside the controller. */ public void selectPatient(Patient patient) { patientOverviewTabPane.getSelectionModel().select(0); // Select first tab tblPatientOverview.getSelectionModel().select(patient); } /** * Start the db request for loading every patient in the MySQL database. */ public void updatePatientsFromDb() { if (this.loadPatientTask != null && this.loadPatientTask.isRunning()) { System.out.println("Patienten werden bereits geladen."); return; } btnPatRefresh.setDisable(true); mainController.getStammdaten().setPatienten(null); mainController.increaseParallelTaskCount(); lblTablePatientEmpty.setText("Liste wird geladen..."); Task> loadPatientsTask = new Task>() { @Override protected List call() throws Exception { return FXCollections.observableArrayList(DBHandler.getAllPatients()); } @Override protected void succeeded() { super.succeeded(); btnPatRefresh.setDisable(false); lblTablePatientEmpty.setText("Liste ist leer."); mainController.getStammdaten().setPatienten(FXCollections.observableArrayList(this.getValue())); mainController.decreaseParallelTaskCount(); } @Override protected void failed() { super.failed(); btnPatRefresh.setDisable(false); lblTablePatientEmpty.setText("Laden fehlgeschlagen!"); mainController.decreaseParallelTaskCount(); if (getException() != null) { getException().printStackTrace(); } } }; this.loadPatientTask = loadPatientsTask; Thread thread = new Thread(loadPatientsTask); thread.setDaemon(true); thread.start(); } /** * EventHandler for {@link #btnStatRefresh} */ @FXML private void clickedRefreshStation() { updateStationsHistorieFromDb(); } /** * Updates the hospital ward history for the currently selected hospital ward. */ public void updateStationsHistorieFromDb() { if (this.loadStationsHistorieTask != null) { loadStationsHistorieTask.cancel(); } lblTableStationEmpty.setText("Liste wird geladen..."); btnStatRefresh.setDisable(true); stationsUebersicht.clear(); mainController.increaseParallelTaskCount(); this.loadStationsHistorieTask = new Task>() { @Override protected List call() throws Exception { return FXCollections.observableArrayList( DBHandler.getStationsUebersichtsItems(cmbStationenFilter.getValue().getStation())); } @Override protected void succeeded() { super.succeeded(); if (!isCancelled()) { lblTableStationEmpty.setText("Liste ist leer."); stationsUebersicht.setAll(this.getValue()); btnStatRefresh.setDisable(false); mainController.decreaseParallelTaskCount(); } } @Override protected void cancelled() { super.cancelled(); mainController.decreaseParallelTaskCount(); } @Override protected void failed() { super.failed(); if (!isCancelled()) { lblTableStationEmpty.setText("Laden fehlgeschlagen!"); getException().printStackTrace(); btnStatRefresh.setDisable(false); mainController.decreaseParallelTaskCount(); } } }; Thread thread = new Thread(loadStationsHistorieTask); thread.setDaemon(true); thread.start(); } /** * EventHandler for the {@link #btnPatRefresh} */ @FXML private void clickedRefreshPatient() { updatePatientsFromDb(); } /** * A property for the currently selected patient. Depends on the currently visible tab. */ public ObjectBinding selectedPatientProperty() { return patientObjectBinding; } /** * Getter for the {@link #selectedPatientProperty()} */ public Patient getSelectedPatient() { return selectedPatientProperty().get(); } }