diff --git a/src/fr/univ/lyon1/gui/ClientGUI.java b/src/fr/univ/lyon1/gui/ClientGUI.java deleted file mode 100644 index 1f43b9d..0000000 --- a/src/fr/univ/lyon1/gui/ClientGUI.java +++ /dev/null @@ -1,38 +0,0 @@ -package fr.univ.lyon1.gui; - -import fr.univ.lyon1.client.Client; -import fr.univ.lyon1.client.ClientReceive; -import fr.univ.lyon1.common.command.Command; -import fr.univ.lyon1.common.command.CommandType; -import fr.univ.lyon1.gui.handlers.MainHandler; - -import java.io.IOException; -import java.util.List; - -public class ClientGUI extends Client { - private final MainHandler gui; - - public ClientGUI(MainHandler handler, String address, int port, String pseudo, String password) throws IOException { - super(address, port, pseudo, password); - this.gui = handler; - } - - @Override - protected void commandMessage(Command cmd) { - gui.receiveMessage(cmd.getArgs().get(0).toString()); - } - - @Override - public void run() throws IOException { - if (started) - return; - - Thread clientReceiveThread = new Thread(new ClientReceive(this)); - clientReceiveThread.start(); - - out.writeObject(new Command(CommandType.login, List.of(this.username, this.password))); // ToDo: Setup login - out.flush(); - - started = true; - } -} diff --git a/src/fr/univ/lyon1/gui/ClientPanel.java b/src/fr/univ/lyon1/gui/ClientPanel.java deleted file mode 100644 index 701de6b..0000000 --- a/src/fr/univ/lyon1/gui/ClientPanel.java +++ /dev/null @@ -1,86 +0,0 @@ -package fr.univ.lyon1.gui; - -import fr.univ.lyon1.gui.handlers.MainHandler; -import javafx.application.Platform; -import javafx.event.ActionEvent; -import javafx.scene.Parent; -import javafx.scene.control.Button; -import javafx.scene.control.ScrollPane; -import javafx.scene.control.TextArea; -import javafx.scene.input.KeyCode; -import javafx.scene.input.KeyEvent; -import javafx.scene.text.Text; -import javafx.scene.text.TextFlow; - -public class ClientPanel extends Parent { - private final TextArea textToSend = new TextArea(); - private final TextFlow receivedText = new TextFlow(); - private final MainHandler gui; - - public ClientPanel(MainHandler gui) { - this.gui = gui; - ScrollPane scrollReceivedText = new ScrollPane(); - scrollReceivedText.setLayoutX(20); - scrollReceivedText.setLayoutY(20); - scrollReceivedText.setPrefWidth(400); - scrollReceivedText.setPrefHeight(350); - scrollReceivedText.setContent(receivedText); - 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.setPrefHeight(100); - this.getChildren().add(textToSend); - textToSend.setOnKeyPressed(this::textToSendKeyPressed); - - sendBtn.setText("Send"); - sendBtn.setLayoutX(textToSend.getLayoutX() + textToSend.getPrefWidth() + btnMargin); - sendBtn.setLayoutY(textToSend.getLayoutY()); - sendBtn.setPrefWidth(80); - sendBtn.setPrefHeight(40); - sendBtn.setVisible(true); - this.getChildren().add(sendBtn); - sendBtn.setOnAction(this::sendBtnAction); - - Button clearBtn = new Button(); - clearBtn.setText("Clear"); - clearBtn.setLayoutX(sendBtn.getLayoutX()); - clearBtn.setPrefWidth(sendBtn.getPrefWidth()); - clearBtn.setPrefHeight(sendBtn.getPrefHeight()); - clearBtn.setLayoutY(textToSend.getLayoutY() + textToSend.getPrefHeight() - clearBtn.getPrefHeight()); - clearBtn.setVisible(true); - this.getChildren().add(clearBtn); - clearBtn.setOnAction(this::clearBtnAction); - } - - private void send() { - String msg = textToSend.getText(); - gui.sendMessage(msg); - textToSend.clear(); - addMessage(msg); - } - - private void sendBtnAction(ActionEvent e) { - send(); - } - - private void textToSendKeyPressed(KeyEvent e) { - if (e.getCode() == KeyCode.ENTER) - send(); - } - - private void clearBtnAction(ActionEvent e) { - textToSend.clear(); - } - - public void addMessage(String message) { - Platform.runLater(() -> receivedText.getChildren().add(new Text(message+"\n"))); - } -} diff --git a/src/fr/univ/lyon1/gui/controller/Dialog.java b/src/fr/univ/lyon1/gui/Dialog.java similarity index 63% rename from src/fr/univ/lyon1/gui/controller/Dialog.java rename to src/fr/univ/lyon1/gui/Dialog.java index b148506..b0b0613 100644 --- a/src/fr/univ/lyon1/gui/controller/Dialog.java +++ b/src/fr/univ/lyon1/gui/Dialog.java @@ -1,15 +1,25 @@ -package fr.univ.lyon1.gui.controller; +package fr.univ.lyon1.gui; import javafx.scene.control.Alert; import org.jetbrains.annotations.NotNull; public class Dialog { + /** + * Show an error alert dialog for user interface + * @param title Title of the alert + * @param description Description of the alert + */ public static void showErrorDialog(String title, String description) { @NotNull final Alert alert = new Alert(Alert.AlertType.WARNING); extracted(title, description, alert); } + /** + * Show a success alert dialog for user interface + * @param title Title of the alert + * @param description Description of the alert + */ public static void showSuccessDialog(String title, String description) { System.out.println("Create success dialog..."); @NotNull @@ -18,6 +28,12 @@ public class Dialog { extracted(title, description, alert); } + /** + * Method used to avoid duplication code + * @param title Title of the alert + * @param description Description of the alert + * @param alert Alert interface + */ private static void extracted(String title, String description, @NotNull Alert alert) { System.out.println("Set title"); alert.setTitle(title); diff --git a/src/fr/univ/lyon1/gui/controller/ApplicationController.java b/src/fr/univ/lyon1/gui/controller/ApplicationController.java index 337f1e9..58f61c9 100644 --- a/src/fr/univ/lyon1/gui/controller/ApplicationController.java +++ b/src/fr/univ/lyon1/gui/controller/ApplicationController.java @@ -36,6 +36,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +/** + * Controller used by interface resources/message_gui.fxml + */ public class ApplicationController { @NotNull private final List channels = new ArrayList<>(); @@ -62,11 +65,13 @@ public class ApplicationController { @NotNull final ServerConfiguration serverConfiguration = ServerConfiguration.load(); + // Init secure socket System.out.println("Init socket..."); this.socket = this.initSSLSocket(serverConfiguration.getAddress(), serverConfiguration.getPort()); - this.objectOutputStream = new ObjectOutputStream(socket.getOutputStream()); - this.objectInputStream = new ObjectInputStream(socket.getInputStream()); + this.objectOutputStream = new ObjectOutputStream(this.socket.getOutputStream()); + this.objectInputStream = new ObjectInputStream(this.socket.getInputStream()); + // Main thread when server send object @NotNull final Thread receiveObjectThread = new Thread(() -> { while (this.isRunning) { @@ -75,8 +80,8 @@ public class ApplicationController { final Object object = this.objectInputStream.readObject(); if (object != null) { - if (object instanceof Command) { - switch (((Command) object).getType()) { + if (object instanceof Command command) { + switch (command.getType()) { // If client receive login type message case login -> { // Request all list of users @@ -89,7 +94,7 @@ public class ApplicationController { // If client receive a message type case message -> { @NotNull - final Message message = (Message) ((Command) object).getArgs().get(0); + final Message message = (Message) command.getArgs().get(0); System.out.println("Message received : " + message.toString()); // If same channel @@ -99,14 +104,12 @@ public class ApplicationController { } // If client receive all users - case list -> { - System.out.println("Connected users : " + Arrays.toString(((Command) object).getArgs().toArray())); - } + case list -> System.out.println("Connected users : " + Arrays.toString(command.getArgs().toArray())); // If client receive a join type message case join -> { @NotNull - final Channel channel = (Channel) ((Command) object).getArgs().get(0); + final Channel channel = (Channel) command.getArgs().get(0); boolean ifChannelExists = this.channels.stream().anyMatch(fChannel -> fChannel.getName().equalsIgnoreCase(channel.getName())); System.out.println("Channel exists : " + ifChannelExists); this.currentChannel = channel; @@ -133,13 +136,12 @@ public class ApplicationController { this.vboxChannelsList.getChildren().stream().filter(node -> node instanceof Text).forEach(txt -> ((Text) txt).setFill(Color.BLACK)); @NotNull - final Text text = (Text) this.vboxChannelsList.getChildren().stream().filter(node -> node instanceof Text && ((Text) node).getText().equalsIgnoreCase("- #" + channel.getName())).toList().get(0); + final Text text = (Text) this.vboxChannelsList.getChildren().stream().filter(node -> node instanceof Text txt && txt.getText().equalsIgnoreCase("- #" + channel.getName())).toList().get(0); text.setFill(Color.RED); } } } } else if (object instanceof LoginInvalid) { - // TODO: Invalid login Platform.runLater(() -> { try { this.closeSocket(); @@ -151,9 +153,9 @@ public class ApplicationController { e.printStackTrace(); } }); - } else if (object instanceof ChatException) { + } else if (object instanceof ChatException chatException) { System.out.println("?"); - ((ChatException) object).printStackTrace(); + chatException.printStackTrace(); } else { this.sendObject(new UnknownCommand()); } @@ -177,13 +179,16 @@ public class ApplicationController { } } }); - receiveObjectThread.start(); + // Login the user with the server configuration System.out.println("Login..."); this.sendObject(new Command(CommandType.login, List.of(serverConfiguration.getPseudo(), serverConfiguration.getPassword()))); } + /** + * Close properly the socket + */ private void closeSocket() throws IOException { this.isRunning = false; this.objectOutputStream.close(); @@ -191,6 +196,12 @@ public class ApplicationController { this.socket.close(); } + /** + * Init the secure socket with SSL + * @param address Address of the server + * @param port Port of the server + * @return Secure socket + */ @NotNull private Socket initSSLSocket(@NotNull String address, int port) throws IOException { SSLContext ctx = ChatSSL.getSSLContext(); @@ -203,26 +214,41 @@ public class ApplicationController { return connection; } + /** + * Send object to the server + * @param object Object to send + */ private void sendObject(@NotNull Object object) throws IOException { this.objectOutputStream.writeObject(object); this.objectOutputStream.flush(); } + /** + * Event when a key is pressed on the text area message + * @param keyEvent Key event + */ public void keyPressedOnTextSendArea(KeyEvent keyEvent) { - if (keyEvent.getCode() == KeyCode.ENTER) { + // If the key pressed is enter, send the current message + if (keyEvent.getCode() == KeyCode.ENTER) this.send(); - } } + /** + * Send the current message to server + */ public void send() { + // Get current message @NotNull final String textToSend = this.textSendArea.getText(); + // Clear the textarea content this.clear(); + // Add the message to the current client System.out.print(">> Send : " + textToSend); Platform.runLater(() -> this.textReceiveArea.getChildren().add(new Text("*>> " + textToSend))); if (this.currentChannel != null) { try { + // Send the message to the server this.sendObject(new Command(CommandType.message, List.of(new Message(textToSend, this.currentChannel)))); } catch (IOException e) { System.out.println("Can not send message to server : " + e.getMessage()); @@ -231,6 +257,9 @@ public class ApplicationController { } } + /** + * Clear the current textarea message + */ public void clear() { this.textSendArea.setText(""); } diff --git a/src/fr/univ/lyon1/gui/controller/ConnectGuiController.java b/src/fr/univ/lyon1/gui/controller/ConnectGuiController.java index 59d836b..c5d6824 100644 --- a/src/fr/univ/lyon1/gui/controller/ConnectGuiController.java +++ b/src/fr/univ/lyon1/gui/controller/ConnectGuiController.java @@ -1,6 +1,7 @@ package fr.univ.lyon1.gui.controller; import fr.univ.lyon1.common.ServerConfiguration; +import fr.univ.lyon1.gui.Dialog; import fr.univ.lyon1.gui.handlers.ApplicationHandler; import javafx.fxml.FXML; import javafx.scene.control.Button; @@ -11,6 +12,9 @@ import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.net.Socket; +/** + * Controller used by interface resources/connect_gui.fxml + */ public class ConnectGuiController { @FXML public TextField addressTextField; @@ -24,7 +28,7 @@ public class ConnectGuiController { public Button connectButton; /** - * Called by submit button in resources/connect_gui.fxml + * Called by connect button */ public void connect() { this.connectButton.setDisable(true); @@ -39,6 +43,7 @@ public class ConnectGuiController { final String password = this.passwordTextField.getText(); System.out.println("Checking if all text fields is not empty"); + // If all fields is not empty if (!address.isEmpty() && !port.isEmpty() && !pseudo.isEmpty() && !password.isEmpty()) { System.out.println("Checking if port is valid..."); // Check if the port is a number and if it's an available port @@ -57,10 +62,7 @@ public class ConnectGuiController { Dialog.showSuccessDialog("Connecté", "Vous êtes bien connecté au serveur"); System.out.println("File saved, next step..."); - System.out.println("Get scene..."); - - // Change scene - + // Change scene for the main application @NotNull final Stage stage = (Stage) this.connectButton.getScene().getWindow(); new ApplicationHandler().launch(stage); @@ -86,6 +88,11 @@ public class ConnectGuiController { } } + /** + * Check if a string is a number + * @param text String to check + * @return Is number + */ private boolean isNumber(String text) { try { Integer.parseInt(text); @@ -95,10 +102,21 @@ public class ConnectGuiController { } } + /** + * Check if a port is in correct range of ports + * @param port Port to check + * @return If port is available + */ private boolean isAvailablePort(int port) { return !(port < 0 || port > 0xFFFF); } + /** + * Check if an address with port is available through a socket + * @param address Address of the server + * @param port Port used by the server + * @return If socket has successfully connected to the server + */ private boolean isAccessible(String address, int port) { try { @NotNull diff --git a/src/fr/univ/lyon1/gui/handlers/MainHandler.java b/src/fr/univ/lyon1/gui/handlers/MainHandler.java deleted file mode 100644 index 636e7df..0000000 --- a/src/fr/univ/lyon1/gui/handlers/MainHandler.java +++ /dev/null @@ -1,56 +0,0 @@ -package fr.univ.lyon1.gui.handlers; - -import fr.univ.lyon1.common.ServerConfiguration; -import fr.univ.lyon1.gui.ClientGUI; -import fr.univ.lyon1.gui.ClientPanel; -import javafx.scene.Group; -import javafx.scene.Scene; -import javafx.stage.Stage; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; - -public class MainHandler implements Handler { - private ClientPanel clientPanel; - @Nullable - private ClientGUI client; - - @Override - public void launch(Stage stage) throws IOException { - System.out.println("New..."); - @NotNull - final ServerConfiguration serverConfiguration = ServerConfiguration.load(); - System.out.println("Launch Client GUI..."); - this.client = new ClientGUI(this, serverConfiguration.getAddress(), serverConfiguration.getPort(), serverConfiguration.getPseudo(), serverConfiguration.getPassword()); - - System.out.println("Set..."); - stage.setTitle("Chat client"); - stage.setWidth(440); - - System.out.println("Set panel..."); - this.clientPanel = new ClientPanel(this); - Group root = new Group(); - root.getChildren().add(this.clientPanel); - Scene scene = new Scene(root, 600, 500); - - System.out.println("Set scene..."); - stage.setScene(scene); - stage.show(); - - if (this.client != null) { - System.out.println("Run..."); - this.client.run(); - } - } - - public void sendMessage(String msg) { - if (client != null) { - client.sendMessage(msg); - } - } - - public void receiveMessage(String msg) { - clientPanel.addMessage(msg); - } -}