diff --git a/pom.xml b/pom.xml index b0e06c3..b170004 100644 --- a/pom.xml +++ b/pom.xml @@ -34,21 +34,33 @@ org.junit.jupiter junit-jupiter-api - 5.7.1 + 5.8.1 test org.junit.jupiter junit-jupiter-engine - 5.7.1 + 5.8.1 test + + org.jetbrains + annotations + 22.0.0 + + package src src/test/ + + + resources + + + org.apache.maven.plugins @@ -73,6 +85,11 @@ + + org.apache.maven.plugins + maven-resources-plugin + 3.1.0 + \ No newline at end of file diff --git a/resources/connect_gui.fxml b/resources/connect_gui.fxml new file mode 100644 index 0000000..b574c85 --- /dev/null +++ b/resources/connect_gui.fxml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + diff --git a/src/fr/univ/lyon1/gui/ClientPanel.java b/src/fr/univ/lyon1/gui/ClientPanel.java index e47bd98..045545c 100644 --- a/src/fr/univ/lyon1/gui/ClientPanel.java +++ b/src/fr/univ/lyon1/gui/ClientPanel.java @@ -12,15 +12,13 @@ import javafx.scene.text.Text; import javafx.scene.text.TextFlow; public class ClientPanel extends Parent { - private TextArea textToSend = new TextArea(); - private ScrollPane scrollReceivedText = new ScrollPane(); - private TextFlow receivedText = new TextFlow(); - private Button sendBtn = new Button(); - private Button clearBtn = new Button(); + private final TextArea textToSend = new TextArea(); + private final TextFlow receivedText = new TextFlow(); private final MainGui gui; ClientPanel(MainGui gui) { this.gui = gui; + ScrollPane scrollReceivedText = new ScrollPane(); scrollReceivedText.setLayoutX(20); scrollReceivedText.setLayoutY(20); scrollReceivedText.setPrefWidth(400); @@ -29,13 +27,14 @@ public class ClientPanel extends Parent { scrollReceivedText.vvalueProperty().bind(receivedText.heightProperty()); this.getChildren().add(scrollReceivedText); + Button sendBtn = new Button(); sendBtn.setPrefWidth(80); int btnMargin = 20; textToSend.setLayoutX(scrollReceivedText.getLayoutX()); textToSend.setLayoutY(scrollReceivedText.getLayoutY() + scrollReceivedText.getPrefHeight() + 20); - textToSend.setPrefWidth(400-sendBtn.getPrefWidth()-btnMargin); + textToSend.setPrefWidth(400- sendBtn.getPrefWidth()-btnMargin); textToSend.setPrefHeight(100); this.getChildren().add(textToSend); textToSend.setOnKeyPressed(this::textToSendKeyPressed); @@ -49,6 +48,7 @@ public class ClientPanel extends Parent { this.getChildren().add(sendBtn); sendBtn.setOnAction(this::sendBtnAction); + Button clearBtn = new Button(); clearBtn.setText("Clear"); clearBtn.setLayoutX(sendBtn.getLayoutX()); clearBtn.setPrefWidth(sendBtn.getPrefWidth()); diff --git a/src/fr/univ/lyon1/gui/MainGui.java b/src/fr/univ/lyon1/gui/MainGui.java index 2b1c691..d9e931f 100644 --- a/src/fr/univ/lyon1/gui/MainGui.java +++ b/src/fr/univ/lyon1/gui/MainGui.java @@ -1,22 +1,47 @@ package fr.univ.lyon1.gui; import javafx.application.Application; +import javafx.fxml.FXMLLoader; import javafx.scene.Group; import javafx.scene.Scene; import javafx.stage.Stage; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; public class MainGui extends Application { private ClientPanel clientPanel; + @Nullable private ClientGUI client; @Override - public void start(Stage stage) throws Exception { - List parameters = this.getParameters().getUnnamed(); - client = new ClientGUI(this, parameters.get(0), Integer.parseInt(parameters.get(1))); - //ToDo: error management especially for bad server IP/port - //ToDo: Server IP/port enter by user on the GUI + public void start(Stage stage) { + try { + @NotNull + final List parameters = this.getParameters().getUnnamed(); + + if (parameters.size() != 2) { + // TODO: Error + System.out.println("Error"); + + FXMLLoader fxmlLoader = new FXMLLoader(ClassLoader.getSystemClassLoader().getResource("connect_gui.fxml")); + Scene scene = new Scene(fxmlLoader.load(), 320, 240); + // stage.getIcons().add(new Image(Objects.requireNonNull(HelloApplication.class.getResourceAsStream("icon.jpg")))); + stage.setTitle("Hello!"); + stage.setScene(scene); + stage.show(); + return; + } else { + client = new ClientGUI(this, parameters.get(0), Integer.parseInt(parameters.get(1))); + //ToDo: error management especially for bad server IP/port + //ToDo: Server IP/port enter by user on the GUI + } + } catch (Exception exception) { + System.out.println(exception.getMessage()); + exception.printStackTrace(); + return; + } stage.setTitle("Chat client"); stage.setWidth(440); @@ -28,7 +53,10 @@ public class MainGui extends Application { stage.setScene(scene); stage.show(); - client.run(); + + if (client != null) { + client.run(); + } } public static void main(String[] args) { @@ -36,7 +64,9 @@ public class MainGui extends Application { } public void sendMessage(String msg) { - client.sendMessage(msg); + if (client != null) { + client.sendMessage(msg); + } } public void receiveMessage(String msg) { diff --git a/src/fr/univ/lyon1/gui/controller/ConnectGuiController.java b/src/fr/univ/lyon1/gui/controller/ConnectGuiController.java new file mode 100644 index 0000000..79d0241 --- /dev/null +++ b/src/fr/univ/lyon1/gui/controller/ConnectGuiController.java @@ -0,0 +1,82 @@ +package fr.univ.lyon1.gui.controller; + +import javafx.event.ActionEvent; +import javafx.scene.control.Alert; +import javafx.scene.control.Button; +import javafx.scene.control.TextField; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.net.Socket; + +public class ConnectGuiController { + public TextField addressTextField; + public TextField portTextField; + public Button connectButton; + + /** + * Called by submit button in resources/connect_gui.fxml + * @param actionEvent Action Event + */ + public void connect(ActionEvent actionEvent) { + this.connectButton.setDisable(true); + + @NotNull + final String address = this.addressTextField.getText(); + @NotNull + final String port = this.portTextField.getText(); + + System.out.println("Checking if port is valid..."); + // Check if the port is a number and if it's an available port + if (this.isNumber(port) && this.isAvailablePort(Integer.parseInt(port))) { + final int iPort = Integer.parseInt(port); + System.out.println("Port valid, next step..."); + System.out.println("Checking if connection is available..."); + + // Check if the connection is available + if (this.isAccessible(address, iPort)) { + + } else { + System.out.println("Connection not available"); + this.showDialog("Erreur de connexion", "Impossible de se connecter au serveur, veuillez vérifier les informations saisies"); + this.connectButton.setDisable(false); + } + } else { + this.showDialog("Erreur", "Veuillez saisir un numéro de port valide"); + this.connectButton.setDisable(false); + } + } + + private void showDialog(String title, String description) { + @NotNull + final Alert alert = new Alert(Alert.AlertType.WARNING); + alert.setTitle(title); + alert.setContentText(description); + alert.show(); + } + + private boolean isNumber(String text) { + try { + Integer.parseInt(text); + return true; + } catch (NumberFormatException ignored) { + return false; + } + } + + private boolean isAvailablePort(int port) { + return !(port < 0 || port > 0xFFFF); + } + + private boolean isAccessible(String address, int port) { + try { + @NotNull + final Socket socket = new Socket(address, port); + socket.setSoTimeout(5 * 1000); + + return true; + } catch (IOException exception) { + return false; + } + } +} diff --git a/src/module-info.java b/src/module-info.java index 39f3612..1e2cdcd 100644 --- a/src/module-info.java +++ b/src/module-info.java @@ -1,9 +1,13 @@ -module fr.univ.lyon1.gui { +module fr.univ.lyon { requires javafx.controls; requires javafx.fxml; requires org.kordamp.bootstrapfx.core; + requires org.jetbrains.annotations; opens fr.univ.lyon1.gui to javafx.fxml; + + exports fr.univ.lyon1.common; exports fr.univ.lyon1.gui; + exports fr.univ.lyon1.gui.controller; } \ No newline at end of file