package at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller; import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showServiceExceptionAlertAndWait; import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showSuccessAlertAndWait; import static at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.controller.Helper.showValidationErrorAlertAndWait; import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidOperationException; import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidRegistrationException; import at.ac.tuwien.sepm.assignment.groupphase.exception.InvalidVehicleException; import at.ac.tuwien.sepm.assignment.groupphase.exception.ServiceException; import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation; import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Operation.Status; import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Registration; import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.dto.Vehicle; import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service.OperationService; import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service.RegistrationService; import at.ac.tuwien.sepm.assignment.groupphase.missioncontrol.service.VehicleService; import java.io.IOException; import java.util.EnumSet; import java.util.LinkedList; import java.util.Set; import javafx.collections.FXCollections; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.ContextMenu; import javafx.scene.control.Label; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.scene.control.MenuItem; import javafx.scene.control.TextField; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; import javafx.scene.input.MouseButton; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.FlowPane; import javafx.scene.layout.GridPane; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; @Controller public class CreateOperationController { private static final Logger LOG = LoggerFactory.getLogger(CreateOperationController.class); public AnchorPane apCreateOperation; @FXML private GridPane grdWindowContainer; @FXML private TextField txtCode; @FXML private TextField txtAddress; @FXML private TextField txtNote; @FXML private Button btnCreateOperation; @FXML private ListView lvVehicles; @FXML private ListView lvActiveOperations; @FXML private Label lblChosenVehicles; @FXML private AnchorPane apInvisible; @FXML private OperationDetailsController operationDetailsController; @FXML private ManageEmployeesController manageEmployeesController; @FXML private CreateCarController createCarController; @FXML private RegistrationWindowController registrationWindowController; @FXML private ArchiveOperationController archiveOperationController; @FXML private FlowPane fpVehicles; private LinkedList chosenVehicles = new LinkedList<>(); private final OperationService operationService; private final VehicleService vehicleService; private final RegistrationService registrationService; public CreateOperationController( OperationService operationService, VehicleService vehicleService, RegistrationService registrationService) { this.operationService = operationService; this.vehicleService = vehicleService; this.registrationService = registrationService; } @FXML private void initialize() { lblChosenVehicles.setText("keine ausgewählt"); lvActiveOperations.setCellFactory(param -> generateOpCodeListItem()); lvActiveOperations.setOnMouseClicked( event -> { if (event.getClickCount() == 2) { if (lvActiveOperations.getSelectionModel().getSelectedItem() == null) { return; } openDetailsWindow(lvActiveOperations.getSelectionModel().getSelectedItem()); } }); setVisible(true); createCarController.setVisible(false); registrationWindowController.setVisible(false); updateList(); } public void updateList() { try { fpVehicles.getChildren().clear(); // TODO: this should probably be handled differently Set vehicles; if (txtCode.getText().isEmpty()) { vehicles = vehicleService.list( EnumSet.complementOf(EnumSet.of(Vehicle.Status.ABGEMELDET))); } else { vehicles = operationService.rankVehicles(txtCode.getText()); } for (Vehicle vehicle : vehicles) { VehiclePaneController controller = VehiclePaneController.createVehiclePane(); controller.setData(vehicle, true, false); controller .getRootElement() .setOnMouseClicked( event -> { if (event.getButton().equals(MouseButton.SECONDARY)) { createContextMenu( vehicle, vehicleService, registrationService) .show( controller.getRootElement(), event.getScreenX(), event.getScreenY()); } else { if (chosenVehicles.contains(vehicle)) { chosenVehicles.remove(vehicle); controller.setSelected(false); } else { chosenVehicles.add(vehicle); controller.setSelected(true); } StringBuilder result = new StringBuilder(); for (int i = 0; i < chosenVehicles.size(); i++) { if (i == chosenVehicles.size() - 1) { result.append(chosenVehicles.get(i).name()); } else { result.append(chosenVehicles.get(i).name()) .append(", "); } } if (result.toString().equals("")) { lblChosenVehicles.setText("keine ausgewählt"); } else { lblChosenVehicles.setText(result.toString()); } } }); if (chosenVehicles.stream().anyMatch(v -> v.id() == vehicle.id())) controller.setSelected(true); fpVehicles.getChildren().add(controller.getRootElement()); } } catch (ServiceException | IOException e) { LOG.error("Exception in updateList(). ", e); showServiceExceptionAlertAndWait( "Beim Erstellen des Ranking ist ein Fehler aufgetreten."); } catch (InvalidOperationException e) { LOG.debug("Validation error in updateList(). ", e); showValidationErrorAlertAndWait(e.getMessage()); } try { lvActiveOperations.setItems( FXCollections.observableArrayList( operationService.list(EnumSet.of(Status.ACTIVE)))); } catch (ServiceException e) { LOG.error("ServiceException in updateList(). ", e); showServiceExceptionAlertAndWait( "Beim Holen der aktiven Einsätze ist ein Fehler aufgetreten"); } } private ContextMenu createContextMenu( Vehicle data, VehicleService vehicleService, RegistrationService registrationService) { ContextMenu menu = new ContextMenu(); for (Vehicle.Status status : Vehicle.Status.values()) { if (status == Vehicle.Status.ABGEMELDET) continue; MenuItem mi = new MenuItem(status.name()); if (status == Vehicle.Status.FREI_FUNK || status == Vehicle.Status.FREI_WACHE) { mi.getStyleClass().add("mi-free"); } else { mi.getStyleClass().add("mi-other"); } mi.setOnAction( event -> { try { vehicleService.update(data.toBuilder().status(status).build()); this.updateList(); } catch (InvalidVehicleException e) { LOG.debug( "Validation error in createContextMenu(). (mi.setOnAction) ", e); showValidationErrorAlertAndWait(e.getMessage()); } catch (ServiceException e) { LOG.error("Exception in createContextMenu(). (mi.setOnAction) ", e); showServiceExceptionAlertAndWait( "Beim Aktualisieren der Fahrzeuge ist ein Fehler aufgetreten."); } }); menu.getItems().add(mi); } MenuItem abmelden = new MenuItem("abmelden"); abmelden.setOnAction( event -> { try { if (data.registrations() == null) return; for (Registration registration : data.registrations()) registrationService.remove(registration.id()); vehicleService.update( data.toBuilder().status(Vehicle.Status.ABGEMELDET).build()); this.updateList(); } catch (InvalidVehicleException | InvalidRegistrationException e) { LOG.debug( "Validation error in createContextMenu(). (abmelden.setOnAction) ", e); showValidationErrorAlertAndWait(e.getMessage()); } catch (ServiceException e) { LOG.error("Exception in createContextMenu(). (abmelden.setOnAction) ", e); showServiceExceptionAlertAndWait( "Beim Aktualisieren der Fahrzeuge ist ein Fehler aufgetreten."); } }); menu.getItems().add(abmelden); return menu; } @FXML protected void createOperationClicked() { LOG.debug("Button \"Erstellen\" clicked."); Vehicle[] vehicles = new Vehicle[chosenVehicles.size()]; for (int i = 0; i < chosenVehicles.size(); i++) { vehicles[i] = chosenVehicles.get(i); } Operation operation = Operation.builder() .additionalInfo(txtNote.getText()) .destination(txtAddress.getText()) .opCode(txtCode.getText()) .status(Status.ACTIVE) .vehicles(Set.of(vehicles)) .build(); try { operationService.add(operation); } catch (ServiceException e) { LOG.error("Exception in createOperationClicked(). ", e); showServiceExceptionAlertAndWait( "Beim Erstellen des Einsatzes ist ein Fehler aufgetreten."); return; } catch (InvalidOperationException e) { LOG.debug("Validation error in createOperationClicked(). ", e); showValidationErrorAlertAndWait(e.getMessage()); return; } showSuccessAlertAndWait("Der Einsatz wurde erfolgreich gespeichert."); updateList(); lblChosenVehicles.setText("keine ausgewählt"); txtAddress.setText(""); txtCode.setText(""); txtNote.setText(""); chosenVehicles = new LinkedList<>(); } @FXML private void onRegistrationLinkClicked() { LOG.debug("Hyperlink \"Anmeldungen\" clicked."); openRegistrationWindow(); } @FXML private void onEmployeeLinkClicked() { LOG.debug("Hyperlink \"Personen\" clicked."); openCreateNewEmployeeWindow(); } @FXML private void onVehicleLinkClicked() { LOG.debug("Hyperlink \"Fahrzeuge\" clicked."); openCreateCarWindow(); } @FXML private void onArchivLinkClicked() { LOG.debug("Hyperlink \"Archiv\" clicked."); archiveOperationController.update(); openArchivWindow(); } private void openArchivWindow() { archiveOperationController.setVisible(true); this.setVisible(false); } void setVisible(boolean b) { apInvisible.setVisible(!b); grdWindowContainer.setVisible(!b); // if (b) updateList(); } private void openDetailsWindow(Operation operation) { operationDetailsController.initOperation(operation); this.setVisible(false); } private void openCreateNewEmployeeWindow() { this.setVisible(false); manageEmployeesController.setVisible(true); } private void openCreateCarWindow() { this.setVisible(false); createCarController.setVisible(true); createCarController.updateVehiclePane(); } private void openRegistrationWindow() { this.setVisible(false); registrationWindowController.setVisible(true); } @FXML private void onOperationCodeChanged(KeyEvent keyEvent) { if (keyEvent.getCode() == KeyCode.ENTER) { updateList(); } } static ListCell generateOpCodeListItem() { return new ListCell<>() { @Override protected void updateItem(Operation item, boolean empty) { super.updateItem(item, empty); if (empty || item == null || item.opCode() == null) { setText(null); } else { setText(item.opCode()); } } }; } }