package com.dronecontrol.intelcontrol.ui; import com.google.common.collect.Sets; import com.dronecontrol.droneapi.data.NavData; import com.dronecontrol.droneapi.listeners.NavDataListener; import com.dronecontrol.droneapi.listeners.VideoDataListener; import com.dronecontrol.intelcontrol.helpers.RaceTimer; import com.dronecontrol.intelcontrol.ui.data.UIAction; import com.dronecontrol.intelcontrol.ui.listeners.UIActionListener; import com.dronecontrol.perceptual.data.body.Hands; import com.dronecontrol.perceptual.data.events.DetectionData; import com.dronecontrol.perceptual.data.events.HandsDetectionData; import com.dronecontrol.perceptual.helpers.CoordinateListener; import com.dronecontrol.perceptual.listeners.DetectionListener; import javafx.application.Platform; import javafx.embed.swing.SwingFXUtils; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.CheckBox; import javafx.scene.control.Label; import javafx.scene.control.Slider; import javafx.scene.image.ImageView; import javafx.scene.image.WritableImage; import javafx.scene.layout.GridPane; import javafx.scene.layout.VBox; import javafx.scene.paint.Paint; import java.awt.image.BufferedImage; import java.util.Set; @SuppressWarnings({"UnusedParameters", "UnusedDeclaration"}) public class FxController implements VideoDataListener, NavDataListener, EventHandler<ActionEvent>, DetectionListener<Hands>, CoordinateListener { private final Set<UIActionListener> uiActionListeners; private boolean bothHandsVisible = false; @FXML private Button takeOffButton; @FXML private ImageView imageView; @FXML private VBox vbox; @FXML private GridPane imageContainer; @FXML private Label labelBattery; @FXML private Label labelTimer; @FXML private Slider slideRoll; @FXML private Slider slidePitch; @FXML private Slider slideYaw; private WritableImage image; private RaceTimer raceTimer; public FxController() { uiActionListeners = Sets.newHashSet(); } public void init() { } public void addUIActionListener(UIActionListener uiActionlistener) { if (!uiActionListeners.contains(uiActionlistener)) { uiActionListeners.add(uiActionlistener); } } @SuppressWarnings("UnusedDeclaration") public void removeUIActionListener(UIActionListener uiActionlistener) { if (uiActionListeners.contains(uiActionlistener)) { uiActionListeners.remove(uiActionlistener); } } public void onApplicationClose() { emitUIAction(UIAction.CLOSE_APPLICATION); } @FXML protected void onButtonTakeOffAction(ActionEvent event) { emitUIAction(UIAction.TAKE_OFF); } @FXML public void onButtonLandAction(ActionEvent actionEvent) { emitUIAction(UIAction.LAND); } @FXML public void onButtonFlatTrimAction(ActionEvent actionEvent) { emitUIAction(UIAction.FLAT_TRIM); } @FXML public void onButtonEmergencyAction(ActionEvent actionEvent) { emitUIAction(UIAction.EMERGENCY); } @FXML public void onButtonSwitchCameraAction(ActionEvent actionEvent) { emitUIAction(UIAction.SWITCH_CAMERA); } @FXML public void onButtonLedAnimationAction(ActionEvent actionEvent) { emitUIAction(UIAction.PLAY_LED_ANIMATION); } @FXML public void onButtonFlightAnimationAction(ActionEvent actionEvent) { emitUIAction(UIAction.PLAY_FLIGHT_ANIMATION); } @FXML public void onCheckBoxExpertModeAction(ActionEvent actionEvent) { CheckBox checkBox = (CheckBox) actionEvent.getSource(); emitUIAction(checkBox.isSelected() ? UIAction.ENABLE_EXPERT_MODE : UIAction.DISABLE_EXPERT_MODE); } public void emitUIAction(UIAction action) { for (UIActionListener listener : uiActionListeners) { listener.onAction(action); } } private void runOnFxThread(Runnable runnable) { Platform.runLater(runnable); } @Override public void onNavData(final NavData navData) { runOnFxThread(new Runnable() { @Override public void run() { setBatteryLabel(navData); } }); } public void setBatteryLabel(NavData navData) { String batteryLevelText = "Battery: " + navData.getBatteryLevel() + "%"; labelBattery.setText(batteryLevelText); if (navData.getState().isBatteryTooLow()) { labelBattery.setTextFill(Paint.valueOf("red")); } else { labelBattery.setTextFill(Paint.valueOf("white")); } } @Override public void onVideoData(final BufferedImage droneImage) { runOnFxThread(new Runnable() { @Override public void run() { imageView.setFitWidth(vbox.getWidth() - 40); imageView.setFitHeight(vbox.getHeight() - 220); image = SwingFXUtils.toFXImage(droneImage, image); if (imageView.getImage() != image) { imageView.setImage(image); } } }); } // Timer event @Override public void handle(ActionEvent actionEvent) { if (raceTimer != null) { long totalMillis = raceTimer.getElapsedTime(); long seconds = totalMillis / 1000; long millis = totalMillis % 1000; labelTimer.setText(String.format("Time: %d,%03d", seconds, millis)); } } public void setRaceTimer(RaceTimer raceTimer) { this.raceTimer = raceTimer; } public void setHandsDetected(HandsDetectionData data) { bothHandsVisible = data.getLeftHand().isActive() && data.getRightHand().isActive(); takeOffButton.setDisable(!bothHandsVisible); String borderColor = bothHandsVisible ? "green" : "red"; imageContainer.setStyle(String.format("-fx-border-color: %s;", borderColor)); } @Override public void onCoordinate(final float roll, final float pitch, final float yaw, float heightDelta) { //Slider einstellen runOnFxThread(new Runnable() { @Override public void run() { slideRoll.setValue(roll); slidePitch.setValue(pitch); slideYaw.setValue(yaw); } }); } @Override public void onDetection(DetectionData<Hands> data) { final HandsDetectionData handsDetectionData = (HandsDetectionData) data; runOnFxThread(new Runnable() { @Override public void run() { setHandsDetected(handsDetectionData); } }); } }