Coverage Summary for Class: LoginFXMLController (it.polimi.ingsw.gc14.View.GUI)
| Class |
Class, %
|
Method, %
|
Branch, %
|
Line, %
|
| LoginFXMLController |
0%
(0/1)
|
0%
(0/14)
|
0%
(0/14)
|
0%
(0/63)
|
package it.polimi.ingsw.gc14.View.GUI;
import it.polimi.ingsw.gc14.Controller.ClientController;
import it.polimi.ingsw.gc14.ErrorType;
import it.polimi.ingsw.gc14.Network.IClient;
import it.polimi.ingsw.gc14.Network.NetworkConfig;
import it.polimi.ingsw.gc14.Network.InterfaceResolver;
import it.polimi.ingsw.gc14.Network.RMI.Client.RMIClient;
import it.polimi.ingsw.gc14.Network.TCP.Client.TCPClient;
import javafx.animation.*;
import javafx.application.Platform;
import javafx.css.PseudoClass;
import javafx.fxml.FXML;
import javafx.geometry.Rectangle2D;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.Screen;
import javafx.util.Duration;
import java.util.Objects;
/**
* FXML controller for the login scene.
*
* <p>Handles username/IP/player-count input, protocol selection (TCP/RMI),
* and initiates the connection to the server.
*/
public class LoginFXMLController {
/** Background image displayed behind the login form. */
@FXML private ImageView backgroundImage;
/** Text field for the player's username. */
@FXML private TextField campoNome;
/** Text field for the desired number of players. */
@FXML private TextField campoNumPlayers;
/** Text field for the server IP address. */
@FXML private TextField campoIP;
/** Button that submits the login form. */
@FXML private Button btnAccedi;
/** Label used to show error or success messages. */
@FXML private Label labelErrore;
/** VBox containing the login form controls. */
@FXML private VBox formPanel;
/** Toggle container for switching between RMI and TCP. */
@FXML private StackPane protocolToggle;
/** Sliding thumb inside the protocol toggle. */
@FXML private Region toggleThumb;
/** Label for the RMI side of the protocol toggle. */
@FXML private Label labelRMI;
/** Label for the TCP side of the protocol toggle. */
@FXML private Label labelTCP;
/** {@code true} when RMI is selected; {@code false} for TCP. */
private boolean isRMI = true;
/** Client controller used to initiate the connection. */
private ClientController controller;
/** CSS pseudo-class applied to the active protocol label. */
private final PseudoClass activeProtocolPseudo = PseudoClass.getPseudoClass("active-protocol");
/**
* Injects the client controller into this FXML controller.
*
* @param controller the client controller to use.
*/
public void setController(ClientController controller) {
this.controller = controller;
}
/** Initializes the scene: loads background, sets up animations, and binds input listeners. */
@FXML
public void initialize() {
// Background setup
Image img = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/GUIImages/BackgroundLogin.png")));
backgroundImage.setImage(img);
Rectangle2D screenBounds = Screen.getPrimary().getBounds();
backgroundImage.setFitWidth(screenBounds.getWidth());
backgroundImage.setFitHeight(screenBounds.getHeight());
// Protocol toggle configuration
protocolToggle.setOnMouseClicked(e -> switchProtocol());
protocolToggle.setStyle(protocolToggle.getStyle() + " -fx-cursor: hand;");
labelRMI.pseudoClassStateChanged(activeProtocolPseudo, true);
labelTCP.pseudoClassStateChanged(activeProtocolPseudo, false);
// Login Action
btnAccedi.setOnAction(e -> onAccediClick());
}
/** Toggles the selected protocol between RMI and TCP, animating the toggle thumb and updating label styles. */
private void switchProtocol() {
isRMI = !isRMI;
TranslateTransition tt = new TranslateTransition(Duration.millis(200), toggleThumb);
tt.setToX(isRMI ? 0 : 110);
tt.play();
labelRMI.pseudoClassStateChanged(activeProtocolPseudo, isRMI);
labelTCP.pseudoClassStateChanged(activeProtocolPseudo, !isRMI);
}
/** Validates form input and starts a background thread to connect to the server. */
@FXML
private void onAccediClick() {
String name = campoNome.getText().trim();
String ip = campoIP.getText().trim();
if (name.isEmpty()) {
showError("Please select a name.");
return;
}
int numPlayers;
try {
numPlayers = Integer.parseInt(campoNumPlayers.getText().trim());
} catch (NumberFormatException e) {
showError("Invalid number of players.");
return;
}
updateLoginButton(false);
controller.setMyUsername(name);
new Thread(() -> {
try {
String localInterface = InterfaceResolver.resolveLocalInterface(ip);
System.setProperty("java.rmi.server.hostname", localInterface);
connect(name, ip, numPlayers, localInterface);
} catch (Exception ex) {
Platform.runLater(() -> {
showError("Network error: " + ex.getMessage());
updateLoginButton(true);
});
}
}).start();
}
/**
* Enables or disables the login button and updates its visual style.
*
* @param enabled {@code true} to enable the button, {@code false} to disable it.
*/
public void updateLoginButton(boolean enabled) {
btnAccedi.setDisable(!enabled);
btnAccedi.setStyle(
"-fx-font-family: 'Cinzel'; -fx-font-size: 12; -fx-font-weight: bold;" +
"-fx-letter-spacing: 4; -fx-text-fill: #0c0601;" +
"-fx-background-color: linear-gradient(to right, #f4c05a, #c8791a, #f4c05a);" +
"-fx-padding: 13 48 13 48; -fx-background-radius: 2;" +
"-fx-opacity: " + (enabled ? "1.0" : "0.3") + ";" +
"-fx-cursor: " + (enabled ? "hand" : "default") + ";"
);
}
/** Connects to the server using the selected protocol and transitions to the waiting state on success. */
private void connect(String nome, String ip, int numPlayers, String localInterface) {
IClient client;
if (isRMI) {
client = new RMIClient(controller, ip, NetworkConfig.RMI_PORT, localInterface);
ErrorType serverResponse = client.connect(nome, numPlayers);
if (serverResponse == null) {
controller.setClient(client);
Platform.runLater(() -> showSuccess("Connected! Waiting for other players…"));
} else {
Platform.runLater(() -> {
showError(serverResponse);
updateLoginButton(true);
});
}
} else {
client = new TCPClient(controller, ip, NetworkConfig.TCP_PORT, NetworkConfig.HEARTBEAT_PORT);
ErrorType serverResponse = client.connect(nome, numPlayers);
if (serverResponse == null) {
controller.setClient(client);
Platform.runLater(() -> showSuccess("Connected! Waiting for other players…"));
} else {
Platform.runLater(() -> {
showError(serverResponse);
updateLoginButton(true);
});
}
}
}
/**
* Displays an error from an {@link ErrorType} constant in the login form label.
*
* @param errorType the error to display.
*/
public void showError(ErrorType errorType) {
labelErrore.setTextFill(Color.web("#e05050"));
labelErrore.setText(errorType.toString());
}
/**
* Displays an arbitrary error message in the login form label.
*
* @param msg the error message to display.
*/
public void showError(String msg) {
labelErrore.setTextFill(Color.web("#e05050"));
labelErrore.setText(msg);
}
/** Displays a success message in green in the login form label. */
private void showSuccess(String msg) {
labelErrore.setTextFill(Color.web("#6fcf8a"));
labelErrore.setText(msg);
}
}