Select Git revision
MainWindowController.java
MainWindowController.java 14.18 KiB
package ch.hepia.ui;
import ch.hepia.Main;
import ch.hepia.api.transport.Connection;
import ch.hepia.api.transport.Journey;
import ch.hepia.api.transport.LinkAPI;
import ch.hepia.api.transport.Location;
import ch.hepia.api.transport.Section;
import ch.hepia.config.AppConfig;
import ch.hepia.config.AppContext;
import ch.hepia.events.ChatMessage;
import ch.hepia.models.User;
import javafx.animation.TranslateTransition;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
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.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Stop;
import javafx.util.Duration;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javafx.scene.layout.Pane;
public class MainWindowController implements Initializable {
@FXML
private Label currentJourneyLabel;
@FXML
private Label startStopLabel;
@FXML
private ComboBox<String> originComboBox;
@FXML
private ComboBox<String> destinationComboBox;
@FXML
private Canvas connectionCanvas;
@FXML
private Button searchOriginButton;
@FXML
private Button searchDestinationButton;
@FXML
private Button launchItinaryButton;
@FXML
private Button sendMessageButton;
@FXML
private TextField messageTextBox;
@FXML
private Pane chatContainer;
/**
* Shows a sad message when the API crashes.
*/
private void showSadMessage(String text){
UiUtils.dialog(Alert.AlertType.ERROR, "Erreur",
"Une erreur est survenue.", text);
}
/**
* Searches stops that matches the query.
* @param newValue The stop name query.
* @param transportApi The API to connect to
* @param target The combo box where to put the results.
*/
private void searchStops(String newValue, LinkAPI transportApi, ComboBox<String> target){
if (!newValue.isEmpty() && newValue.length() > 3 && !target.getItems().contains(newValue)){
try {
List<Location> locations = transportApi.getStations(newValue);
ArrayList<String> results = new ArrayList<>();
locations.forEach((location) -> results.add(location.getName()));
target.getItems().clear();
target.getItems().addAll(results);
target.show();
} catch (IOException e) {
showSadMessage(AppConfig.ERROR_API_UNREACHABLE);
}
}
}
/**
* Draws a connection between two places. Basically lines.
* @param connection The connection to draw
* @param x Where to draw
* @param y Where to draw but vertically
*/
private void drawConnection(Connection connection, int x, int y){
List<Section> sections = connection.getSections();
GraphicsContext gcx = connectionCanvas.getGraphicsContext2D();
//Draw starting station
gcx.setFill(Color.RED);
gcx.fillText(sections.get(0).getDeparture().getLocation().getName(), x, y - 20);
gcx.setFill(Color.BLACK);
gcx.fillText(sections.get(0).getDeparture().getDepartureTime().toString(), x, y - 40);
gcx.setFill(Color.RED);
gcx.fillOval(x - 5, y - 5, 10, 10);
gcx.strokeLine(x, y, x + 622 / (sections.size() + 1), y);
for (int i = 0; i < sections.size(); i++){
//Draw each step
drawConnectionStep(sections.get(i), sections.size(), x, y, i);
}
}
/**
* Draws a connection step between two places.
* @param section The section to draw
* @param size Number of section in the connection
* @param x Where to draw
* @param y Where to draw but vertically
* @param cnt Section position in connection list.
*/
private void drawConnectionStep(Section section, int size, int x, int y, int cnt) {
GraphicsContext gcx = connectionCanvas.getGraphicsContext2D();
int xSize = (AppConfig.APP_MAIN_VIEW_WIDTH / (size + 1));
gcx.strokeLine( x + xSize * (cnt + 1), y, AppConfig.APP_MAIN_VIEW_WIDTH / (size + 1), y);
gcx.setFill(Color.RED);
gcx.fillOval(x + xSize * (cnt + 1) - 5, y - 5, 10, 10);
gcx.fillText(section.getArrival().getLocation().getName(), x + xSize * (cnt + 1), y - 20);
gcx.setFill(Color.BLACK);
gcx.fillText(section.getArrival().getArrivalTime().toString(), x + xSize * (cnt + 1), y - 40);
Journey jrn = section.getJourney();
String transportType = "MARCHE"; //Draw the type of transport used on previous step
if (!(jrn instanceof Journey.EmptyJourney)) {
transportType = jrn.getCategory() + ", " + jrn.getNumber();
}
gcx.setFill(Color.BLUE);
gcx.fillText(transportType,x + xSize * (cnt), y - 55);
gcx.setFill(Color.RED);
}
/**
* Draws a newly received message
* @param message The message to draw
*/
private void drawMessage(User user, String message, String image, Color color){
Pane p = new Pane();
setChatPanelStyle(p, color);
Image lblImg = new Image(Main.class.getResourceAsStream(image));
Label msg = new Label();
msg.setWrapText(true);
msg.setStyle("-fx-padding: 8px");
msg.setText(message);
msg.setMaxWidth(310);
msg.setGraphic(new ImageView(lblImg));
p.getChildren().add(msg);
if (chatContainer.getChildren().size() >= 7) {
chatContainer.getChildren().remove(0);
}
insertMessageIntoQueue();
chatContainer.getChildren().add(p);
}
/**
* Style a chat panel before pushing
* @param p Panel to style
* @param color Background color of the gradient
*/
private void setChatPanelStyle(Pane p, Color color) {
p.setBackground(
new Background(
new BackgroundFill(
new LinearGradient(0, 0, 0, 1, true,
CycleMethod.NO_CYCLE,
new Stop(1, color),
new Stop(0, Color.WHITE)
),
new CornerRadii(5),
Insets.EMPTY)));
p.setBorder(new Border(new BorderStroke(Color.color(0.6, 0.6, 0.6), BorderStrokeStyle.SOLID, new CornerRadii(5),
BorderWidths.DEFAULT)));
p.setPrefWidth(312);
p.setMaxWidth(320);
}
/**
* Wrapper for local chat message
* @param message Message to print
*/
private void drawHelpMessage(String message) {
drawMessage(Main.getContext().getUser().get(), message, AppConfig.HELP_MESSAGE_ICON, Color.color(1, 0.9, 0.5, 0.3));
}
/**
* Print available commands in the chat
*/
private void drawCommands(){
StringBuilder buffer = new StringBuilder("/"+AppConfig.CHAT_COMMANDS.get(0));
for(int i = 1; i < AppConfig.CHAT_COMMANDS.size(); i++)
buffer.append(", /" + AppConfig.CHAT_COMMANDS.get(i));
drawHelpMessage(buffer.toString());
}
/**
* Moves the older messages downwards
*/
private void insertMessageIntoQueue(){
for (int i = 0; i < chatContainer.getChildren().size(); i++){
Pane sp = (Pane) chatContainer.getChildren().get(i);
TranslateTransition t = new TranslateTransition(Duration.seconds(0.25), sp);
t.setToY((chatContainer.getChildren().size() - i) * (sp.getHeight() + 4));
t.play();
}
}
/**
* Parse the line and search for chat command.
* @param cmd The line to parse.
*/
private void parseChatCommand(String cmd){
String[] command = cmd.split(" ", 2);
if (AppConfig.CHAT_COMMANDS.contains(command[0])){
if (command[0].equals("help")) {
drawCommands();
} else if (command[0].equals("ignore")){
if (command.length > 1){
Main.getContext().getUser().get().addIgnoredUser(new User(command[1]));
drawMessage(Main.getContext().getUser().get(), command[1] + " bloqué.", "/img/help.png", Color.color(1, 0.9, 0.5, 0.3));
}
} else if (command[0].equals("ignoredlist")) {
List<User> list = Main.getContext().getUser().get().getIgnoredUserList();
StringBuilder buffer = new StringBuilder(list.get(0).getName());
for(int i = 1; i < list.size(); i++)
buffer.append(", " + list.get(i).getName());
drawMessage(Main.getContext().getUser().get(), "Bloqués : " + buffer.toString(), "/img/help.png", Color.color(1, 0.9, 0.5, 0.3));
}
} else {
drawCommands();
}
}
/**
* Sets the form up
* @param url The JavaFX URL handler
* @param resourceBundle The JavaDX ResB handle
*/
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
currentJourneyLabel.setText("Vous n'avez prévu aucun voyage pour le moment.");
startStopLabel.setText(""); // No text should be visible when no journey has been selected.
messageTextBox.textProperty().addListener((ov, oldValue, newValue) -> {
if (messageTextBox.getText().length() > 60) {
messageTextBox.setText(messageTextBox.getText().substring(0, 60));
}
});
LinkAPI transportApi = new LinkAPI();
AppContext app = Main.getContext();
UiUtils.buttonWhenEnter(originComboBox, searchOriginButton);
UiUtils.buttonWhenEnter(destinationComboBox, searchDestinationButton);
UiUtils.buttonWhenEnter(messageTextBox, sendMessageButton);
searchOriginButton.
setOnAction(event -> { originComboBox.setValue(originComboBox.getEditor().getText());
searchStops(originComboBox.getValue(), transportApi, originComboBox);
});
searchDestinationButton.
setOnAction(event -> { destinationComboBox.setValue(destinationComboBox.getEditor().getText());
searchStops(destinationComboBox.getValue(), transportApi, destinationComboBox);
});
launchItinaryButton.setOnAction(event -> {
try {
connectionCanvas.getGraphicsContext2D()
.clearRect(0, 0, connectionCanvas.getWidth(), connectionCanvas.getHeight());
List<Connection> connections = transportApi.getConnections(
originComboBox.getValue(), destinationComboBox.getValue());
startStopLabel.setText(originComboBox.getValue() + " - " + destinationComboBox.getValue());
for (int i = 0; i < connections.size(); i++){
// Now iterating over connections
drawConnection(connections.get(i), 30, 100 + 100 * i);
}
} catch (IOException e) {
showSadMessage(AppConfig.ERROR_API_UNREACHABLE);
}
});
sendMessageButton.setOnAction(event -> {
if (app.getUser().isPresent() && !messageTextBox.getText().isEmpty()){
if ( messageTextBox.getText().charAt(0) != '/') {
app.getMessageManager().sendChatMessage(new ChatMessage(app.getUser().get(), messageTextBox.getText()));
} else {
parseChatCommand(messageTextBox.getText().substring(1, messageTextBox.getText().length()));
}
messageTextBox.clear();
}
});
// Subscribe to chat message
app.getMessageManager().conditionalSubscribeChatMessage(
chatMessage -> {
Platform.runLater(() -> {
User sender = chatMessage.getUser();
String message = sender.getName() + ": " + chatMessage.getMessage();
if (sender.equals(app.getUser().get())) {
drawMessage(sender, message, AppConfig.CHAT_MESSAGE_ICON_SELF, AppConfig.COLOR_BLUE_10_OPACITY);
} else {
drawMessage(sender, message, AppConfig.CHAT_MESSAGE_ICON, AppConfig.COLOR_BLUE_10_OPACITY);
}
});
},
chatMessage -> !(app.getUser().get().getIgnoredUserList().contains(chatMessage.getUser()))
);
// Subscribe to joined journey
app.getMessageManager().conditionalSubscribeJoinedJourney( joinedJourney -> {
Platform.runLater(() -> {
User sender = joinedJourney.getUser();
String message = sender.getName() + " voyage !";
if (sender.equals(app.getUser().get())) {
drawMessage(sender, message, AppConfig.CHAT_MESSAGE_ICON_SELF, AppConfig.COLOR_BLUE_10_OPACITY);
} else {
drawMessage(sender, message, AppConfig.CHAT_MESSAGE_ICON, AppConfig.COLOR_BLUE_10_OPACITY);
}
});
},
joinedJourney -> !(app.getUser().get().getIgnoredUserList().contains(joinedJourney.getUser()))
);
// Subscribe to left journey
app.getMessageManager().conditionalSubscribeLeftJourney( leftJourney -> {
Platform.runLater(() -> {
User sender = leftJourney.getUser();
String message = sender.getName() + " a terminé son voyage !";
if (sender.equals(app.getUser().get())) {
drawMessage(sender, message, AppConfig.CHAT_MESSAGE_ICON_SELF, AppConfig.COLOR_BLUE_10_OPACITY);
} else {
drawMessage(sender, message, AppConfig.CHAT_MESSAGE_ICON, AppConfig.COLOR_BLUE_10_OPACITY);
}
});
},
leftJourney -> !(app.getUser().get().getIgnoredUserList().contains(leftJourney.getUser()))
);
//Login messages:
drawCommands();
Platform.runLater(() -> {
drawHelpMessage("Bonjour " + app.getUser().get().getName() + " ! Les commandes à dispositions sont :");
});
}
}