Im Rahmen der Veranstaltung "CS3330 - Projektpraktikum MedizinischeInformatik" an der Universität zu Lübeck entstandenes Krankenhausinformationssystem (KIS).
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

388 lines
14 KiB

  1. package de.uniluebeck.mi.projmi6.controller;
  2. /**
  3. * Created by Johannes on 12.11.15.
  4. */
  5. import de.uniluebeck.mi.projmi6.db.DBHandler;
  6. import de.uniluebeck.mi.projmi6.model.Patient;
  7. import de.uniluebeck.mi.projmi6.model.Station;
  8. import de.uniluebeck.mi.projmi6.model.StationsUebersichtsItem;
  9. import de.uniluebeck.mi.projmi6.view.SelectKeyComboBoxListener;
  10. import javafx.beans.binding.Bindings;
  11. import javafx.beans.binding.ObjectBinding;
  12. import javafx.collections.FXCollections;
  13. import javafx.collections.ObservableList;
  14. import javafx.collections.transformation.FilteredList;
  15. import javafx.concurrent.Task;
  16. import javafx.fxml.FXML;
  17. import javafx.fxml.FXMLLoader;
  18. import javafx.scene.Parent;
  19. import javafx.scene.Scene;
  20. import javafx.scene.control.*;
  21. import javafx.scene.control.cell.PropertyValueFactory;
  22. import javafx.scene.image.Image;
  23. import javafx.stage.Modality;
  24. import javafx.stage.Stage;
  25. import java.io.IOException;
  26. import java.time.LocalDate;
  27. import java.util.List;
  28. /**
  29. * Controller class.
  30. */
  31. public class PatientTablesController {
  32. private final MainController mainController;
  33. /**
  34. * The placeholder labels in case the TableViews are empty
  35. */
  36. @FXML
  37. private Label lblTablePatientEmpty, lblTableStationEmpty;
  38. @FXML
  39. private Button btnPatCreate, btnPatEdit, btnPatRefresh;
  40. @FXML
  41. private TableView<Patient> tblPatientOverview;
  42. @FXML
  43. private TableColumn<Patient, String> colPatPatId, colPatGeburtsname, colPatNachname, colPatVorname, colPatStrasse,
  44. colPatPlz, colPatOrt, colPatCave;
  45. @FXML
  46. private TableColumn<Patient, LocalDate> colPatGebDatum;
  47. @FXML
  48. private ToggleButton btnEntlassenePatientenZeigen;
  49. @FXML
  50. private Button btnStatRefresh;
  51. @FXML
  52. private ComboBox<Station> cmbStationenFilter;
  53. @FXML
  54. private TableView<StationsUebersichtsItem> tblStationOverview;
  55. @FXML
  56. private TableColumn<StationsUebersichtsItem, Integer> colStatPatId, colStatAlter;
  57. @FXML
  58. private TableColumn<StationsUebersichtsItem, String> colStatFullName;
  59. @FXML
  60. private TableColumn<StationsUebersichtsItem, LocalDate> colStatGebDatum, colStatAufnahmedatum, colStatEntlassungsdatum;
  61. @FXML
  62. private TabPane patientOverviewTabPane;
  63. @FXML
  64. private Tab stationOverviewTab, patientOverviewTab;
  65. private final ObservableList<StationsUebersichtsItem> stationsUebersicht = FXCollections.observableArrayList();
  66. private final FilteredList<StationsUebersichtsItem> stationsUebersichtsItemFilteredList = new FilteredList<StationsUebersichtsItem>(stationsUebersicht,
  67. item -> item.getStationEntlassung() == null || item.getStationEntlassung().isAfter(LocalDate.now()));
  68. private Task loadStationsHistorieTask = null;
  69. private Task loadPatientTask = null;
  70. private ObjectBinding<Patient> patientObjectBinding = null;
  71. /**
  72. * Constructor.
  73. *
  74. * @param mainController The controller that creates this instance
  75. */
  76. public PatientTablesController(MainController mainController) {
  77. this.mainController = mainController;
  78. }
  79. /**
  80. * Getter for the TabPane that contains patient and hospital ward overview tabs.
  81. */
  82. public TabPane getPatientOverviewTabPane() {
  83. return patientOverviewTabPane;
  84. }
  85. /**
  86. * FXMLLoaders initialize()-method.
  87. */
  88. @FXML
  89. private void initialize() {
  90. btnPatEdit.disableProperty().bind(tblPatientOverview.getSelectionModel().selectedItemProperty().isNull());
  91. tblPatientOverview.setRowFactory(tableView -> {
  92. TableRow<Patient> tableRow = new TableRow<>();
  93. tableRow.setOnMouseClicked(event -> {
  94. if (event.getClickCount() == 2 && (!tableRow.isEmpty())) {
  95. Patient patient = tableRow.getItem();
  96. showEditWindow(patient);
  97. }
  98. });
  99. return tableRow;
  100. });
  101. tblPatientOverview.itemsProperty().bind(mainController.getStammdaten().patientenProperty());
  102. lblTablePatientEmpty.setText("Liste ist leer.");
  103. tblStationOverview.disableProperty().bind(cmbStationenFilter.valueProperty().isNull());
  104. cmbStationenFilter.itemsProperty().bind(mainController.getStammdaten().stationenProperty());
  105. new SelectKeyComboBoxListener(cmbStationenFilter);
  106. patientObjectBinding = Bindings.<Patient>createObjectBinding(() -> {
  107. if (patientOverviewTabPane.getSelectionModel().getSelectedItem().equals(patientOverviewTab)) {
  108. return tblPatientOverview.getSelectionModel().getSelectedItem();
  109. } else if (tblStationOverview.getSelectionModel().getSelectedItem() == null) {
  110. return null;
  111. } else {
  112. int selectedPatId = tblStationOverview.getSelectionModel().getSelectedItem().getPatId();
  113. return tblPatientOverview.getItems().stream().filter(p -> p.getPatID() == selectedPatId).findFirst().orElse(null);
  114. }
  115. }, tblPatientOverview.getSelectionModel().selectedItemProperty(),
  116. tblStationOverview.getSelectionModel().selectedItemProperty(),
  117. patientOverviewTabPane.getSelectionModel().selectedItemProperty());
  118. initColumnsPatient();
  119. initColumnsStation();
  120. updatePatientsFromDb();
  121. }
  122. /**
  123. * Set up cell value factories for the patients table.
  124. */
  125. private void initColumnsPatient() {
  126. colPatPatId.setCellValueFactory(cellDataFeatures -> cellDataFeatures.getValue().patIDProperty().asString());
  127. colPatGeburtsname.setCellValueFactory(new PropertyValueFactory<>("geburtsname"));
  128. colPatNachname.setCellValueFactory(new PropertyValueFactory<>("nachname"));
  129. colPatVorname.setCellValueFactory(new PropertyValueFactory<>("vorname"));
  130. colPatGebDatum.setCellValueFactory(cellDataFeatures -> cellDataFeatures.getValue().geburtsdatumProperty());
  131. colPatStrasse.setCellValueFactory(cellDataFeatures -> {
  132. Patient patient = cellDataFeatures.getValue();
  133. return Bindings.concat(patient.strasseProperty(), " ", patient.hausnummerProperty());
  134. });
  135. colPatPlz.setCellValueFactory(new PropertyValueFactory<>("plz"));
  136. colPatOrt.setCellValueFactory(new PropertyValueFactory<>("ort"));
  137. colPatCave.setCellValueFactory(new PropertyValueFactory<>("cave"));
  138. }
  139. /**
  140. * Set up cell value factories for the hospital ward overview.
  141. */
  142. private void initColumnsStation() {
  143. colStatPatId.setCellValueFactory(new PropertyValueFactory<StationsUebersichtsItem, Integer>("patId"));
  144. colStatFullName.setCellValueFactory(cellDataFeatures -> cellDataFeatures.getValue().patNameProperty());
  145. colStatGebDatum.setCellValueFactory(cellDataFeatures -> cellDataFeatures.getValue().patBirthdateProperty());
  146. colStatAlter.setCellValueFactory(new PropertyValueFactory<StationsUebersichtsItem, Integer>("patAge"));
  147. colStatAufnahmedatum.setCellValueFactory(cellDataFeatures -> cellDataFeatures.getValue().stationAufnahmeProperty());
  148. colStatEntlassungsdatum.setCellValueFactory(cellDataFeatures -> cellDataFeatures.getValue().stationEntlassungProperty());
  149. //Reload data if the user selects another ward.
  150. cmbStationenFilter.valueProperty().addListener((observableValue, oldValue, newValue) -> {
  151. updateStationsHistorieFromDb();
  152. });
  153. //Init filter
  154. tblStationOverview.itemsProperty().bind(Bindings.createObjectBinding(() -> {
  155. if (btnEntlassenePatientenZeigen.isSelected()) {
  156. return stationsUebersicht;
  157. } else {
  158. return stationsUebersichtsItemFilteredList;
  159. }
  160. }, btnEntlassenePatientenZeigen.selectedProperty()));
  161. }
  162. /**
  163. * EventHandler for {@link #btnPatCreate}
  164. */
  165. @FXML
  166. private void clickedCreatePatient() {
  167. showEditWindow(null);
  168. }
  169. /**
  170. * EventHandler for {@link #btnPatEdit}
  171. */
  172. @FXML
  173. private void clickedEditPatient() {
  174. showEditWindow(tblPatientOverview.getSelectionModel().getSelectedItem());
  175. }
  176. /**
  177. * Opens a window for editing the given patient.
  178. *
  179. * @param patient The patient that should be opened for editing.
  180. */
  181. private void showEditWindow(Patient patient) {
  182. FXMLLoader fxmlLoader = new FXMLLoader();
  183. fxmlLoader.setLocation(getClass().getClassLoader().getResource("patient_edit.fxml"));
  184. PatientEditorController patientEditorController = new PatientEditorController(mainController);
  185. fxmlLoader.setControllerFactory(clazz -> patientEditorController);
  186. Parent root = null;
  187. try {
  188. root = fxmlLoader.load();
  189. } catch (IOException e) {
  190. e.printStackTrace();
  191. return;
  192. }
  193. Stage stage = new Stage();
  194. stage.setTitle(patient == null ? "Neuen Patienten erstellen" : "Patient bearbeiten");
  195. stage.setScene(new Scene(root, 600, 600));
  196. stage.getIcons().add(new Image("icon.png"));
  197. stage.initModality(Modality.WINDOW_MODAL);
  198. stage.initOwner(btnPatEdit.getScene().getWindow());
  199. patientEditorController.setPatient(patient);
  200. stage.showAndWait();
  201. }
  202. /**
  203. * Highlight the given patient in the list, if patient was changed outside the controller.
  204. */
  205. public void selectPatient(Patient patient) {
  206. patientOverviewTabPane.getSelectionModel().select(0); // Select first tab
  207. tblPatientOverview.getSelectionModel().select(patient);
  208. }
  209. /**
  210. * Start the db request for loading every patient in the MySQL database.
  211. */
  212. public void updatePatientsFromDb() {
  213. if (this.loadPatientTask != null && this.loadPatientTask.isRunning()) {
  214. System.out.println("Patienten werden bereits geladen.");
  215. return;
  216. }
  217. btnPatRefresh.setDisable(true);
  218. mainController.getStammdaten().setPatienten(null);
  219. mainController.increaseParallelTaskCount();
  220. lblTablePatientEmpty.setText("Liste wird geladen...");
  221. Task<List<Patient>> loadPatientsTask = new Task<List<Patient>>() {
  222. @Override
  223. protected List<Patient> call() throws Exception {
  224. return FXCollections.observableArrayList(DBHandler.getAllPatients());
  225. }
  226. @Override
  227. protected void succeeded() {
  228. super.succeeded();
  229. btnPatRefresh.setDisable(false);
  230. lblTablePatientEmpty.setText("Liste ist leer.");
  231. mainController.getStammdaten().setPatienten(FXCollections.observableArrayList(this.getValue()));
  232. mainController.decreaseParallelTaskCount();
  233. }
  234. @Override
  235. protected void failed() {
  236. super.failed();
  237. btnPatRefresh.setDisable(false);
  238. lblTablePatientEmpty.setText("Laden fehlgeschlagen!");
  239. mainController.decreaseParallelTaskCount();
  240. if (getException() != null) {
  241. getException().printStackTrace();
  242. }
  243. }
  244. };
  245. this.loadPatientTask = loadPatientsTask;
  246. Thread thread = new Thread(loadPatientsTask);
  247. thread.setDaemon(true);
  248. thread.start();
  249. }
  250. /**
  251. * EventHandler for {@link #btnStatRefresh}
  252. */
  253. @FXML
  254. private void clickedRefreshStation() {
  255. updateStationsHistorieFromDb();
  256. }
  257. /**
  258. * Updates the hospital ward history for the currently selected hospital ward.
  259. */
  260. public void updateStationsHistorieFromDb() {
  261. if (this.loadStationsHistorieTask != null) {
  262. loadStationsHistorieTask.cancel();
  263. }
  264. lblTableStationEmpty.setText("Liste wird geladen...");
  265. btnStatRefresh.setDisable(true);
  266. stationsUebersicht.clear();
  267. mainController.increaseParallelTaskCount();
  268. this.loadStationsHistorieTask = new Task<List<StationsUebersichtsItem>>() {
  269. @Override
  270. protected List<StationsUebersichtsItem> call() throws Exception {
  271. return FXCollections.observableArrayList(
  272. DBHandler.getStationsUebersichtsItems(cmbStationenFilter.getValue().getStation()));
  273. }
  274. @Override
  275. protected void succeeded() {
  276. super.succeeded();
  277. if (!isCancelled()) {
  278. lblTableStationEmpty.setText("Liste ist leer.");
  279. stationsUebersicht.setAll(this.getValue());
  280. btnStatRefresh.setDisable(false);
  281. mainController.decreaseParallelTaskCount();
  282. }
  283. }
  284. @Override
  285. protected void cancelled() {
  286. super.cancelled();
  287. mainController.decreaseParallelTaskCount();
  288. }
  289. @Override
  290. protected void failed() {
  291. super.failed();
  292. if (!isCancelled()) {
  293. lblTableStationEmpty.setText("Laden fehlgeschlagen!");
  294. getException().printStackTrace();
  295. btnStatRefresh.setDisable(false);
  296. mainController.decreaseParallelTaskCount();
  297. }
  298. }
  299. };
  300. Thread thread = new Thread(loadStationsHistorieTask);
  301. thread.setDaemon(true);
  302. thread.start();
  303. }
  304. /**
  305. * EventHandler for the {@link #btnPatRefresh}
  306. */
  307. @FXML
  308. private void clickedRefreshPatient() {
  309. updatePatientsFromDb();
  310. }
  311. /**
  312. * A property for the currently selected patient. Depends on the currently visible tab.
  313. */
  314. public ObjectBinding<Patient> selectedPatientProperty() {
  315. return patientObjectBinding;
  316. }
  317. /**
  318. * Getter for the {@link #selectedPatientProperty()}
  319. */
  320. public Patient getSelectedPatient() {
  321. return selectedPatientProperty().get();
  322. }
  323. }