package com.faforever.client.game; import com.faforever.client.fx.FxmlLoader; import com.faforever.client.fx.StringCell; import com.faforever.client.i18n.I18n; import com.faforever.client.map.MapService; import com.faforever.client.remote.domain.RatingRange; import com.faforever.client.theme.ThemeService; import javafx.application.Platform; import javafx.beans.Observable; import javafx.beans.binding.Bindings; import javafx.beans.binding.ObjectBinding; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.collections.ObservableList; import javafx.collections.transformation.SortedList; import javafx.fxml.FXML; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableRow; import javafx.scene.control.TableView; import javafx.scene.image.Image; import org.jetbrains.annotations.NotNull; import javax.annotation.PostConstruct; import javax.annotation.Resource; public class GamesTableController { private final ObjectProperty<GameInfoBean> selectedGame; @FXML TableView<GameInfoBean> gamesTable; @FXML TableColumn<GameInfoBean, Image> mapPreviewColumn; @FXML TableColumn<GameInfoBean, String> gameTitleColumn; @FXML TableColumn<GameInfoBean, PlayerFill> playersColumn; @FXML TableColumn<GameInfoBean, RatingRange> ratingColumn; @FXML TableColumn<GameInfoBean, String> hostColumn; @FXML TableColumn<GameInfoBean, Boolean> passwordProtectionColumn; @Resource FxmlLoader fxmlLoader; @Resource MapService mapService; @Resource JoinGameHelper joinGameHelper; @Resource I18n i18n; public GamesTableController() { this.selectedGame = new SimpleObjectProperty<>(); } public ObjectProperty<GameInfoBean> selectedGameProperty() { return selectedGame; } @PostConstruct void postConstruct() { joinGameHelper.setParentNode(getRoot()); } public Node getRoot() { return gamesTable; } public void initializeGameTable(ObservableList<GameInfoBean> gameInfoBeans) { SortedList<GameInfoBean> sortedList = new SortedList<>(gameInfoBeans); sortedList.comparatorProperty().bind(gamesTable.comparatorProperty()); gamesTable.setPlaceholder(new Label(i18n.get("games.noGamesAvailable"))); gamesTable.setRowFactory(param1 -> gamesRowFactory()); gamesTable.setItems(sortedList); sortedList.addListener((Observable observable) -> selectFirstGame()); selectFirstGame(); passwordProtectionColumn.setCellValueFactory(param -> param.getValue().passwordProtectedProperty()); passwordProtectionColumn.setCellFactory(param -> passwordIndicatorColumn()); mapPreviewColumn.setCellFactory(param -> new MapPreviewTableCell(fxmlLoader)); mapPreviewColumn.setCellValueFactory(param -> new ObjectBinding<Image>() { { bind(param.getValue().mapFolderNameProperty()); } @Override protected Image computeValue() { return mapService.loadSmallPreview(param.getValue().getMapFolderName()); } }); gameTitleColumn.setCellValueFactory(param -> param.getValue().titleProperty()); gameTitleColumn.setCellFactory(param -> new StringCell<>(title -> title)); playersColumn.setCellValueFactory(param -> Bindings.createObjectBinding( () -> new PlayerFill(param.getValue().getNumPlayers(), param.getValue().getMaxPlayers()), param.getValue().numPlayersProperty(), param.getValue().maxPlayersProperty()) ); playersColumn.setCellFactory(param -> playersCell()); ratingColumn.setCellValueFactory(param -> new SimpleObjectProperty<>(new RatingRange(param.getValue().getMinRating(), param.getValue().getMaxRating()))); ratingColumn.setCellFactory(param -> ratingTableCell()); hostColumn.setCellValueFactory(param -> param.getValue().hostProperty()); hostColumn.setCellFactory(param -> new StringCell<>(title -> title)); gamesTable.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { Platform.runLater(() -> selectedGame.set(newValue)); }); } private void selectFirstGame() { TableView.TableViewSelectionModel<GameInfoBean> selectionModel = gamesTable.getSelectionModel(); if (selectionModel.getSelectedItem() == null && !gamesTable.getItems().isEmpty()) { Platform.runLater(() -> selectionModel.select(0)); } } @NotNull private TableRow<GameInfoBean> gamesRowFactory() { TableRow<GameInfoBean> row = new TableRow<>(); row.setOnMouseClicked(event -> { if (event.getClickCount() == 2) { GameInfoBean gameInfoBean = row.getItem(); joinGameHelper.join(gameInfoBean); } }); return row; } private TableCell<GameInfoBean, Boolean> passwordIndicatorColumn() { return new StringCell<>( isPasswordProtected -> isPasswordProtected ? i18n.get("game.protected.symbol") : "", Pos.CENTER, ThemeService.CSS_CLASS_FONTAWESOME); } private TableCell<GameInfoBean, PlayerFill> playersCell() { return new StringCell<>(playerFill -> i18n.get("game.players.format", playerFill.getPlayers(), playerFill.getMaxPlayers()), Pos.CENTER); } private TableCell<GameInfoBean, RatingRange> ratingTableCell() { return new StringCell<>(ratingRange -> { if (ratingRange.getMin() == null && ratingRange.getMax() == null) { return ""; } if (ratingRange.getMin() != null && ratingRange.getMax() != null) { return i18n.get("game.ratingFormat.minMax", ratingRange.getMin(), ratingRange.getMax()); } if (ratingRange.getMin() != null) { return i18n.get("game.ratingFormat.minOnly", ratingRange.getMin()); } return i18n.get("game.ratingFormat.maxOnly", ratingRange.getMax()); }, Pos.CENTER); } }