diff --git a/src/main/java/de/uniluebeck/mi/projmi6/Main.java b/src/main/java/de/uniluebeck/mi/projmi6/Main.java index 479ab65..85c6d54 100644 --- a/src/main/java/de/uniluebeck/mi/projmi6/Main.java +++ b/src/main/java/de/uniluebeck/mi/projmi6/Main.java @@ -7,6 +7,7 @@ import de.uniluebeck.mi.projmi6.db.DBHandler; import de.uniluebeck.mi.projmi6.hapi.HL7Receiver; import de.uniluebeck.mi.projmi6.hapi.HL7Server; import javafx.application.Application; +import javafx.application.Platform; import javafx.beans.property.ReadOnlyStringProperty; import javafx.collections.FXCollections; import javafx.concurrent.Task; @@ -27,17 +28,29 @@ import javafx.scene.text.Text; import javafx.stage.Stage; import javafx.stage.StageStyle; - +/** + * The JavaFX application class that starts our application. + * + * @author Johannes + */ public class Main extends Application { + /** + * The ip adress of the OPS system we wan't to communicate with. + * Can be set in the settings tab. + */ public static String OPS_IP = "127.0.0.1"; - public static int OPS_PORT = 1112; + /** + * OPS system's port number. + * Can be changed from the settings tab. + */ + public static int OPS_PORT = 1112; - private HL7Server server; /** - * Cuz building the GUI from FXML is a bit costly, + * Because building the GUI from FXML is a bit costly + * and loading the master data takes some time, * it's done from its own thread. */ private Task loadMainWindowTask = new Task() { @@ -101,8 +114,18 @@ public class Main extends Application { launch(args); } + + /** + * Server instance that is currently running + */ + private HL7Server server; + + /** + * In the application lifecycle, this method will be called when closing. + */ @Override public void stop() throws Exception { + //Stop the server if (server != null) { server.stop(); server.shutdown(); @@ -112,9 +135,6 @@ public class Main extends Application { @Override public void start(Stage primaryStage) { - // TODO: Jojo kann das weg? - // System.out.println(getClass().getClassLoader().getResource("").toExternalForm()); - primaryStage.getIcons().add(icon); Stage loadingMessage = createLoadWindow(loadMainWindowTask.messageProperty()); @@ -122,6 +142,7 @@ public class Main extends Application { loadMainWindowTask.setOnFailed(event -> { loadMainWindowTask.getException().printStackTrace(); loadingMessage.close(); + Platform.exit(); }); loadMainWindowTask.setOnSucceeded(event -> { Parent root = loadMainWindowTask.getValue(); @@ -162,6 +183,7 @@ public class Main extends Application { Scene scene = new Scene(root, 400, 500); Stage stage = new Stage(StageStyle.UNDECORATED); + stage.setTitle("KIS wird geladen...."); stage.getIcons().add(icon); root.setBackground(new Background(new BackgroundFill(Paint.valueOf("#0093D1"), CornerRadii.EMPTY, Insets.EMPTY))); stage.setScene(scene); diff --git a/src/main/java/de/uniluebeck/mi/projmi6/controller/DiagnoseController.java b/src/main/java/de/uniluebeck/mi/projmi6/controller/DiagnoseController.java index c7e4732..7d6a9a6 100644 --- a/src/main/java/de/uniluebeck/mi/projmi6/controller/DiagnoseController.java +++ b/src/main/java/de/uniluebeck/mi/projmi6/controller/DiagnoseController.java @@ -115,20 +115,19 @@ public class DiagnoseController { */ @FXML private void initialize() { + initButtons(); + //Init diagnosis list view diagDiagnose.itemsProperty().bind(mainController.getStammdaten().icd10CodesProperty()); - new SelectKeyComboBoxListener(diagDiagnose); + //init fields on the right diagDiagnoseArt.setItems(FXCollections.observableArrayList(DiagArt.values())); diagDiagnoseArzt.itemsProperty().bind(mainController.getStammdaten().mitarbeiterProperty()); - diagnoseList.itemsProperty().bind(diagnosen); - - initButtons(); - fields.disableProperty().bind(state.isEqualTo(State.VIEW)); + //Init the list view on the left. diagnoseList.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); diagnoseList.disableProperty().bind(state.isNotEqualTo(State.VIEW)); diagnoseList.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { @@ -139,6 +138,7 @@ public class DiagnoseController { } }); + //React on state changes. state.addListener((observable, oldValue, newValue) -> { if(newValue == State.VIEW){ mainController.unlockFromEdit(); @@ -168,9 +168,10 @@ public class DiagnoseController { btnDiagEdit.disableProperty().bind(diagnoseList.getSelectionModel().selectedItemProperty().isNull()); - btnDiagEdit.managedProperty().bind(state.isEqualTo(State.VIEW)); - btnDiagEdit.visibleProperty().bind(btnDiagEdit.managedProperty()); - + //btnDiagEdit.managedProperty().bind(state.isEqualTo(State.VIEW)); + //btnDiagEdit.visibleProperty().bind(btnDiagEdit.managedProperty()); + btnDiagEdit.setManaged(false); + btnDiagEdit.setVisible(false); btnDiagSave.managedProperty().bind(state.isNotEqualTo(State.VIEW)); btnDiagSave.visibleProperty().bind(btnDiagSave.managedProperty()); diff --git a/src/main/java/de/uniluebeck/mi/projmi6/controller/FallController.java b/src/main/java/de/uniluebeck/mi/projmi6/controller/FallController.java index d16032c..f081193 100644 --- a/src/main/java/de/uniluebeck/mi/projmi6/controller/FallController.java +++ b/src/main/java/de/uniluebeck/mi/projmi6/controller/FallController.java @@ -1,8 +1,5 @@ package de.uniluebeck.mi.projmi6.controller; -/** - * Created by 631806 on 12.11.15. - */ import ca.uhn.hl7v2.HL7Exception; import de.uniluebeck.mi.projmi6.db.DBHandler; @@ -132,6 +129,9 @@ public class FallController { @FXML private void initialize() { fallEinweisenderArzt.disableProperty().bind(fallSelbsteinweisung.selectedProperty()); + fallEinweisenderArzt.managedProperty().bind(fallSelbsteinweisung.selectedProperty().not()); + fallEinweisenderArzt.visibleProperty().bind(fallEinweisenderArzt.managedProperty()); + fallFallart.setItems(FXCollections.observableArrayList(FallArt.values())); fallKasse.setItems(mainController.getStammdaten().getKassen()); @@ -194,8 +194,6 @@ public class FallController { */ @FXML private void clickedSendHl7() { - /* Natascha */ - //TODO send funny message Patient patient = mainController.getPatientTablesController().getSelectedPatient(); Fall fall = fallProperty.get(); fall.setPatient(patient); @@ -208,6 +206,41 @@ public class FallController { } /** + * Opens a dialog to inform the user about invalid data. + */ + private void showMessage(String title, String message) { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Ung\u00fcltige Falldaten eingegeben!"); + alert.setHeaderText(title); + alert.setContentText(message); + + alert.showAndWait(); + } + + + /** + * Validate the data entered by the user. + */ + private boolean validateData(Fall fall){ + if(fall.getAufnahmeDatum()!= null && fall.getEntlassungsDatum() != null + && fall.getAufnahmeDatum().isAfter(fall.getEntlassungsDatum())){ + showMessage("Aufnahmedatum lieght hinter Entlassungsdatum", "Der Patient muss aufgenommen worden sein, ehe " + + "er wieder entlassen worden sein kann."); + return false; + } + if(fall.getKasse()==null || fall.getVersichertenNummer().isEmpty()){ + showMessage("Fall hat keine Kasse/Versicherungsnummer", "An den Fall m\u00fcssen Abrechnungsinfos angeh\u00e4ngt werden!"); + return false; + } + if(fall.getFallArt()==null){ + showMessage("Es ist keine Fallart ausgew\u00e4hlt!", "Bitte eine Fallart ausw\u00e4hlen!"); + return false; + } + return true; + } + + + /** * Toggle controller state to edit */ public void editFall() { @@ -255,30 +288,35 @@ public class FallController { if (this.state.get() == State.CREATE) { Fall fall = new Fall(); copyFieldDataIntoFall(fall); + if(!validateData(fall)){ + return; + } try { int newfallid = DBHandler.setFall(fall, mainController.getCurrentMitarbeiter().getMitarbID()); fall.setFallID(newfallid); - } catch (SQLException e) { e.printStackTrace(); + return; } try { HL7Sender.createMessageADT_A01(fall); } catch (IOException | HL7Exception | SQLException e) { e.printStackTrace(); } - } else { + mainController.refreshCasesFromDb(mainController.getPatientTablesController().getSelectedPatient()); + } else { //Update / edit copyFieldDataIntoFall(fallProperty.get()); + if(!validateData(fallProperty.get())){ + return; + } try { DBHandler.setFall(fallProperty.get(), mainController.getCurrentMitarbeiter().getMitarbID(), true); - } catch (SQLException e) { e.printStackTrace(); } } this.state.set(State.VIEW); - mainController.refreshCasesFromDb(mainController.getPatientTablesController().getSelectedPatient()); } /** diff --git a/src/main/java/de/uniluebeck/mi/projmi6/controller/LogController.java b/src/main/java/de/uniluebeck/mi/projmi6/controller/LogController.java index e22aa24..1b863f3 100644 --- a/src/main/java/de/uniluebeck/mi/projmi6/controller/LogController.java +++ b/src/main/java/de/uniluebeck/mi/projmi6/controller/LogController.java @@ -25,7 +25,7 @@ public class LogController { /** * The superior controller */ - final MainController mainController; + private final MainController mainController; @FXML private TableView tblLog; @@ -60,7 +60,6 @@ public class LogController { initColumns(); refreshLogFromDb(); } - /** * Init cell value factories for the table columns */ diff --git a/src/main/java/de/uniluebeck/mi/projmi6/controller/MainController.java b/src/main/java/de/uniluebeck/mi/projmi6/controller/MainController.java index 593d712..147e3f2 100644 --- a/src/main/java/de/uniluebeck/mi/projmi6/controller/MainController.java +++ b/src/main/java/de/uniluebeck/mi/projmi6/controller/MainController.java @@ -110,6 +110,9 @@ public class MainController { private int fallIdToShow = -1; + /** + * Public constructor + */ public MainController() { fallController = new FallController(this); diagnoseController = new DiagnoseController(this); @@ -307,9 +310,11 @@ public class MainController { */ @FXML private void initialize() { + initCaseListView(); + //Init user data. cmbUserChoose.itemsProperty().bind(this.getStammdaten().mitarbeiterProperty()); - cmbUserChoose.getSelectionModel().select(0); // TODO: Bessere Loesung finden. + cmbUserChoose.getSelectionModel().select(0); //Disable the right side if no case is selected. @@ -322,6 +327,19 @@ public class MainController { }); + + tabPaneFall.setDisable(false); + tabFallDiagnose.setDisable(true); + tabFallStationsHistorie.setDisable(true); + tabFallUntersuchungen.setDisable(true); + + + } + + /** + * Setup the list view of the patient's cases. + */ + private void initCaseListView(){ lvFall.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); fallController.fallProperty().bind(lvFall.getSelectionModel().selectedItemProperty()); @@ -383,14 +401,9 @@ public class MainController { stationsHistorieController.setStationsHistorie(null); diagnoseController.setDiagnosen(null); untersuchungenController.setUntersuchungen(null); - //fallController.c return; } - if (fall == null) { // If no patient is selected - lvFallPlaceholder.setText("Kein Patient ausgew\u00e4hlt!"); - return; - } loadCaseData = new Task() { diff --git a/src/main/java/de/uniluebeck/mi/projmi6/controller/MessageController.java b/src/main/java/de/uniluebeck/mi/projmi6/controller/MessageController.java index d9f925f..b1f1955 100644 --- a/src/main/java/de/uniluebeck/mi/projmi6/controller/MessageController.java +++ b/src/main/java/de/uniluebeck/mi/projmi6/controller/MessageController.java @@ -16,7 +16,7 @@ import java.io.IOException; /** * This controller controlls the small message icon at the bottom of the application's main window. - * Created by Johannes on 21/11/2015. + * @author Johannes */ public class MessageController { /** @@ -27,7 +27,7 @@ public class MessageController { /** * The list of unread messages */ - private final SimpleListProperty messages = new SimpleListProperty(FXCollections.observableArrayList()); + private final SimpleListProperty messages = new SimpleListProperty<>(FXCollections.observableArrayList()); /** * The view that is mantained by this controller @@ -64,8 +64,11 @@ public class MessageController { * @see de.uniluebeck.mi.projmi6.controller.MessageListController */ private void showMessageList() { + //Load the window content from FXML FXMLLoader fxmlLoader = new FXMLLoader(); fxmlLoader.setLocation(getClass().getClassLoader().getResource("message_list.fxml")); + + //Non-empty constructor of the controller class MessageListController messageListController = new MessageListController(messages, mainController); fxmlLoader.setControllerFactory(clazz -> messageListController); @@ -77,6 +80,7 @@ public class MessageController { return; } + //Create stage and open window. Stage stage = new Stage(); stage.setTitle("Neue HL7-Nachrichten"); diff --git a/src/main/java/de/uniluebeck/mi/projmi6/controller/MessageListController.java b/src/main/java/de/uniluebeck/mi/projmi6/controller/MessageListController.java index c989ce6..5be2020 100644 --- a/src/main/java/de/uniluebeck/mi/projmi6/controller/MessageListController.java +++ b/src/main/java/de/uniluebeck/mi/projmi6/controller/MessageListController.java @@ -17,7 +17,6 @@ import javafx.stage.Stage; * @author Johannes */ public class MessageListController { - private final SimpleListProperty messages; private final MainController mainController; @FXML diff --git a/src/main/java/de/uniluebeck/mi/projmi6/controller/PatientTablesController.java b/src/main/java/de/uniluebeck/mi/projmi6/controller/PatientTablesController.java index 135d59c..da4b8e8 100644 --- a/src/main/java/de/uniluebeck/mi/projmi6/controller/PatientTablesController.java +++ b/src/main/java/de/uniluebeck/mi/projmi6/controller/PatientTablesController.java @@ -76,6 +76,7 @@ public class PatientTablesController { private ObservableList stationsUebersicht = FXCollections.observableArrayList(); private 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; @@ -88,6 +89,9 @@ public class PatientTablesController { this.mainController = mainController; } + /** + * Getter for the TabPane that contains patient and hospital ward overview tabs. + */ public TabPane getPatientOverviewTabPane() { return patientOverviewTabPane; } @@ -288,11 +292,17 @@ public class PatientTablesController { 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(); @@ -348,15 +358,25 @@ public class PatientTablesController { 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(); } diff --git a/src/main/java/de/uniluebeck/mi/projmi6/controller/package-info.java b/src/main/java/de/uniluebeck/mi/projmi6/controller/package-info.java index 849297c..7488ddc 100644 --- a/src/main/java/de/uniluebeck/mi/projmi6/controller/package-info.java +++ b/src/main/java/de/uniluebeck/mi/projmi6/controller/package-info.java @@ -1,4 +1,24 @@ /** - * Controller Klassen + * This package contains the FXML Controller classes. + * + * There is the {@link de.uniluebeck.mi.projmi6.controller.MainController}, that creates instances of these nested controller classes: + *
    + *
  • {@link de.uniluebeck.mi.projmi6.controller.DiagnoseController}
  • + *
  • {@link de.uniluebeck.mi.projmi6.controller.FallController}
  • + *
  • {@link de.uniluebeck.mi.projmi6.controller.LogController}
  • + *
  • {@link de.uniluebeck.mi.projmi6.controller.PatientTablesController}
  • + *
  • {@link de.uniluebeck.mi.projmi6.controller.MessageController}
  • + *
  • {@link de.uniluebeck.mi.projmi6.controller.SettingsController}
  • + *
  • {@link de.uniluebeck.mi.projmi6.controller.StationsHistorieController}
  • + *
  • {@link de.uniluebeck.mi.projmi6.controller.UntersuchungenController}
  • + *
+ * The main controller has an {@link de.uniluebeck.mi.projmi6.controller.MainController#getControllerFactory()} for + * the FXMLLoader. + * + * There are also two other controller classes, that aren't directly maintained by the FXMLLoader + *
    + *
  • {@link de.uniluebeck.mi.projmi6.controller.PatientEditorController} for the edit/create patient window
  • + *
  • {@link de.uniluebeck.mi.projmi6.controller.MessageListController} for the window of unseen HL7 messages
  • + *
*/ package de.uniluebeck.mi.projmi6.controller; \ No newline at end of file diff --git a/src/main/java/de/uniluebeck/mi/projmi6/model/package-info.java b/src/main/java/de/uniluebeck/mi/projmi6/model/package-info.java index ec8a0c6..13e430e 100644 --- a/src/main/java/de/uniluebeck/mi/projmi6/model/package-info.java +++ b/src/main/java/de/uniluebeck/mi/projmi6/model/package-info.java @@ -1,4 +1,5 @@ /** - * Model Klassen. + * Model classes. + * In this project we use a relative flat object structure, that correlate directly with the db table columns. */ package de.uniluebeck.mi.projmi6.model; \ No newline at end of file diff --git a/src/main/java/de/uniluebeck/mi/projmi6/view/DateTimePicker.java b/src/main/java/de/uniluebeck/mi/projmi6/view/DateTimePicker.java index 3f46822..d52d706 100644 --- a/src/main/java/de/uniluebeck/mi/projmi6/view/DateTimePicker.java +++ b/src/main/java/de/uniluebeck/mi/projmi6/view/DateTimePicker.java @@ -37,6 +37,31 @@ public class DateTimePicker extends HBox { */ public DateTimePicker() { this.setAlignment(Pos.CENTER_LEFT); + + HBox timePicker = initTimePicker(); + + //Set Now-Button action + btnNow.setOnAction(event -> setToCurrentDateTime()); + //Make it large enough to read the text + btnNow.setMinWidth(50); + btnNow.getStyleClass().add("now-button"); + + //Jetzt-Button nimmt keine Platz ein wenn View deaktiviert: + btnNow.managedProperty().bind(this.disabledProperty().not()); + + + //Add the subcomponents to the view. + this.getChildren().addAll(datePicker, timePicker, btnNow); + + + this.setSpacing(5); + } + + + /** + * Inits the timepicker, which is composed from an HBox and two textfields + */ + private HBox initTimePicker(){ hourText.setOnKeyReleased(event -> { if (hourText.getCaretPosition() >= 2) { int hour = Integer.parseInt(hourText.getText()); @@ -48,11 +73,13 @@ public class DateTimePicker extends HBox { hourText.setAlignment(Pos.CENTER_RIGHT); hourText.setBackground(null); hourText.setPadding(Insets.EMPTY); - hourText.setPromptText("HH"); + hourText.promptTextProperty().bind(Bindings.createStringBinding( + ()->this.isDisabled()?"":"HH", this.disabledProperty())); HBox.setHgrow(hourText, Priority.ALWAYS); minuteText.setBackground(null); minuteText.setPadding(Insets.EMPTY); - minuteText.setPromptText("MM"); + minuteText.promptTextProperty().bind(Bindings.createStringBinding( + ()->this.isDisabled()?"":"MM", this.disabledProperty())); HBox.setHgrow(minuteText, Priority.ALWAYS); hourText.effectProperty().bind(Bindings.createObjectBinding(() -> { @@ -81,7 +108,12 @@ public class DateTimePicker extends HBox { return invalidValue; }, minuteText.textProperty())); Label colon = new Label(":"); - + colon.visibleProperty().bind(Bindings.createBooleanBinding(()->{ + if(this.isDisabled() && (minuteText.getText()==null || minuteText.getText().isEmpty())){ + return false; + } + return true; + },this.disabledProperty(), minuteText.textProperty())); HBox timePicker = new HBox(hourText, colon, minuteText); timePicker.maxHeightProperty().bind(datePicker.heightProperty()); timePicker.getStyleClass().add("time-picker"); @@ -89,20 +121,7 @@ public class DateTimePicker extends HBox { timePicker.setMaxWidth(80); timePicker.getStyleClass().add("button"); - //Set Now-Button action - btnNow.setOnAction(event -> setToCurrentDateTime()); - //Make it large enough to read the text - btnNow.setMinWidth(50); - btnNow.getStyleClass().add("now-button"); - - btnNow.managedProperty().bind(this.disabledProperty().not()); - - - //Add the subcomponents to the view. - this.getChildren().addAll(datePicker, timePicker, btnNow); - - - this.setSpacing(5); + return timePicker; } /** diff --git a/src/main/java/de/uniluebeck/mi/projmi6/view/package-info.java b/src/main/java/de/uniluebeck/mi/projmi6/view/package-info.java index 7c7efbd..4213237 100644 --- a/src/main/java/de/uniluebeck/mi/projmi6/view/package-info.java +++ b/src/main/java/de/uniluebeck/mi/projmi6/view/package-info.java @@ -1,4 +1,4 @@ /** - * View Klassen. + * The custom view classes. */ package de.uniluebeck.mi.projmi6.view; \ No newline at end of file diff --git a/src/main/resources/style.css b/src/main/resources/style.css index f229b45..3ec7759 100644 --- a/src/main/resources/style.css +++ b/src/main/resources/style.css @@ -61,3 +61,9 @@ DateTimePicker .text-field { visibility: hidden; } +.fields:disabled .check-box { + -fx-opacity: 0; +} +.fiels:disabled .check-box:selected{ + -fx-opacity: 1; +}