commit d7ed6161c63eee163c607ab54cf0f7eff2341efc parent 4d8085ca1bf845b086d740d32e407181af5c7191 Author: A Koens <[email protected]> Date: Tue, 7 Feb 2023 14:24:45 +0100 Squashed commit of the following: commit a94004160ff1527147066e530e42441341706384 Author: A Koens <[email protected]> Date: Tue Feb 7 14:03:42 2023 +0100 update colors commit ea5f2dee6a5fe278a529489fd9dd6f166524b53b Author: A Koens <[email protected]> Date: Tue Feb 7 11:22:45 2023 +0100 TicTacToe working again commit ea1b80add41dc610634b3d700ea1afec56b44f08 Author: A Koens <[email protected]> Date: Sat Feb 4 21:17:57 2023 +0100 Change Game controller en menu controller Added a menu controller interface for game menu controllers and changed the game controller from an abstract class to an interface . commit 618b1d9371fa6236cc82a1527d9967b427932f6a Author: A Koens <[email protected]> Date: Fri Feb 3 08:48:11 2023 +0100 Othello Multiplayer commit 6f60c17181f1a3e7d04ffa54adbbd5d5acfc171d Author: A Koens <[email protected]> Date: Thu Feb 2 18:57:56 2023 +0100 Navigation App now has navigation to different pages. Games can now also be started properly. commit 218da32ee4a3cb13cbccef6da1727feb5e7a0954 Author: A Koens <[email protected]> Date: Sun Jan 29 15:22:57 2023 +0100 Library implementation commit 7430acc0b4b64f7c3cca11283d0b3fa157e8999d Author: A Koens <[email protected]> Date: Sun Jan 22 22:24:03 2023 +0100 Start integration new GUI Diffstat:
65 files changed, 2366 insertions(+), 1613 deletions(-)
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java @@ -14,31 +14,32 @@ module nl.isygameclient { requires com.google.gson; exports nl.isygameclient; - // Controllers + exports nl.isygameclient.controllers.games.tictactoe; - exports nl.isygameclient.controllers.game_selector; - // Models + + exports nl.isygameclient.controllers; exports nl.isygameclient.models; + exports nl.isygameclient.views; exports nl.isygameclient.util; - exports nl.isygameclient.models.settings; - exports nl.isygameclient.models.games.tictactoe; - exports nl.isygameclient.models.games.othello; exports nl.isygameclient.models.board; + exports nl.isygameclient.models.games; + exports nl.isygameclient.settings; opens nl.isygameclient to javafx.fxml; + opens nl.isygameclient.views to javafx.fxml; + + opens nl.isygameclient.controllers to javafx.fxml; opens nl.isygameclient.controllers.games to javafx.fxml; - opens nl.isygameclient.controllers.game_selector to javafx.fxml; opens nl.isygameclient.controllers.games.tictactoe to javafx.fxml; opens nl.isygameclient.controllers.games.othello to javafx.fxml; - opens nl.isygameclient.util to com.google.gson; opens nl.isygameclient.models to com.google.gson; opens nl.isygameclient.models.board to com.google.gson; - opens nl.isygameclient.models.settings to com.google.gson; - opens nl.isygameclient.models.games.othello to com.google.gson; - opens nl.isygameclient.models.games.tictactoe to com.google.gson; + opens nl.isygameclient.settings to com.google.gson; + opens nl.isygameclient.models.games to com.google.gson; + opens nl.isygameclient.util to com.google.gson; } diff --git a/src/main/java/nl/isygameclient/Application.java b/src/main/java/nl/isygameclient/Application.java @@ -2,6 +2,9 @@ package nl.isygameclient; import javafx.stage.Stage; import nl.isygameclient.util.StageHandler; +import nl.isygameclient.views.GameCardControl; + +import java.util.List; /** * This class is the start of the javafx application. @@ -15,6 +18,9 @@ import nl.isygameclient.util.StageHandler; */ public class Application extends javafx.application.Application { + public static final List<GameCardControl> GAMES = List.of( + new GameCardControl("Tic Tac Toe", "/nl/isygameclient/imgs/tictactoe_logo.png", "/nl/isygameclient/views/games/tictactoe/TicTacToeMainMenu.fxml"), + new GameCardControl("Othello", "/nl/isygameclient/imgs/othello_logo.png", "/nl/isygameclient/views/games/othello/OthelloMainMenu.fxml")); public static void main(String[] args) { launch(); @@ -22,6 +28,7 @@ public class Application extends javafx.application.Application { /** * The start preforms the initialization of the stage. + * * @param stage a javafx stage. */ @Override @@ -29,14 +36,14 @@ public class Application extends javafx.application.Application { StageHandler stageHandler = StageHandler.get(); stageHandler.loadStages(); + stageHandler.changeSceneOfStage(Window.APP, "/nl/isygameclient/views/app.fxml"); + stageHandler.focusStage(Window.APP); - String stageName = "GameSelector"; - stageHandler.changeSceneOfStage(stageName, "views/game_selector/GameSelector.fxml"); - - stageHandler.focusStage(stageName); - - stageHandler.getStage(stageName).setOnCloseRequest((e) -> { + stageHandler.getStage(Window.APP).setOnCloseRequest((e) -> { stageHandler.saveStages(); + stageHandler.closeStages(); }); } + + } diff --git a/src/main/java/nl/isygameclient/Window.java b/src/main/java/nl/isygameclient/Window.java @@ -0,0 +1,6 @@ +package nl.isygameclient; + +public enum Window { + APP, + GAME +} diff --git a/src/main/java/nl/isygameclient/controllers/AppController.java b/src/main/java/nl/isygameclient/controllers/AppController.java @@ -0,0 +1,72 @@ +package nl.isygameclient.controllers; + +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.VBox; +import nl.isygameclient.util.StageHandler; +import nl.isygameclient.views.NavButtonControl; + +import java.io.IOException; +import java.net.URL; +import java.util.Map; +import java.util.ResourceBundle; +import java.util.TreeMap; + +public class AppController implements Initializable { + + private final TreeMap<Integer, NavButtonControl> navButtons = new TreeMap<>(Map.ofEntries( + Map.entry(0, new NavButtonControl("Store", "LOCAL_MALL", null)), + Map.entry(1, new NavButtonControl("Library", "GAMES", "/nl/isygameclient/views/game-library.fxml")), + Map.entry(2, new NavButtonControl("Community", "QUESTION_ANSWER", null)), + Map.entry(3, new NavButtonControl("Servers", "FORMAT_LIST_BULLETED", null)) + )); + private NavButtonControl activeButton; + @FXML + public BorderPane app; + @FXML + private VBox navBar; + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + navButtons.forEach((index, button) -> { + button.setOnAction(this::onNavButtonPress); + navBar.getChildren().add(button); + }); + + activeButton = navButtons.get(1); + activeButton.activate(); + loadScene(activeButton.getSource()); + } + + @FXML + public void onNavButtonPress(ActionEvent e) { + var newButton = (NavButtonControl) e.getSource(); + activeButton.deactivate(); + activeButton = newButton; + newButton.activate(); + + loadScene(activeButton.getSource()); + } + + @FXML + public void onSettingsButtonPressed(){ + loadScene("/nl/isygameclient/views/app-settings.fxml"); + } + + private void loadScene(String path) { + app.getChildren().remove(app.getCenter()); + + if (path == null) return; + + URL url = StageHandler.class.getResource(path); + FXMLLoader fxmlLoader = new FXMLLoader(url); + try { + app.setCenter(fxmlLoader.load()); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/nl/isygameclient/controllers/AppSettingsController.java b/src/main/java/nl/isygameclient/controllers/AppSettingsController.java @@ -0,0 +1,13 @@ +package nl.isygameclient.controllers; + +import javafx.fxml.Initializable; + +import java.net.URL; +import java.util.ResourceBundle; + +public class AppSettingsController implements Initializable { + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + + } +} diff --git a/src/main/java/nl/isygameclient/controllers/GameLibraryController.java b/src/main/java/nl/isygameclient/controllers/GameLibraryController.java @@ -0,0 +1,47 @@ +package nl.isygameclient.controllers; + +import com.jfoenix.controls.JFXButton; +import com.jfoenix.controls.JFXTextField; +import javafx.beans.binding.Bindings; +import javafx.collections.FXCollections; +import javafx.collections.transformation.FilteredList; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.layout.FlowPane; +import nl.isygameclient.views.GameCardControl; + +import java.net.URL; +import java.util.ResourceBundle; + +import static nl.isygameclient.Application.GAMES; + +public class GameLibraryController implements Initializable { + @FXML + public FlowPane gameCards; + @FXML + public JFXTextField searchTextField; + @FXML + public JFXButton searchButton; + @FXML + public JFXButton searchClear; + @FXML + public JFXButton searchOptions; + private FilteredList<GameCardControl> filteredList; + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + filteredList = new FilteredList<>(FXCollections.observableList(GAMES)); + searchTextField.textProperty().addListener((observable, oldValue, newValue) -> { + String searchText = searchTextField.getText().toLowerCase(); + filteredList.setPredicate(n -> n.getGameTitle().toLowerCase().contains(searchText)); + }); + Bindings.bindContent(gameCards.getChildren(), filteredList); + } + + @FXML + protected void onClearSearchButtonClick() { + searchTextField.clear(); + } + + +} +\ No newline at end of file diff --git a/src/main/java/nl/isygameclient/controllers/game_selector/GameCardController.java b/src/main/java/nl/isygameclient/controllers/game_selector/GameCardController.java @@ -1,46 +0,0 @@ -package nl.isygameclient.controllers.game_selector; - -import javafx.fxml.FXML; -import javafx.scene.control.Label; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; -import javafx.scene.input.MouseEvent; -import nl.isygameclient.Application; -import nl.isygameclient.models.settings.GameCard; - -public class GameCardController { - - private GameCard gameCard; - - @FXML - private ImageView gameImage; - - @FXML - private Label gameTitle; - - public void initializeCard(GameCard gameCard) { - this.gameCard = gameCard; - // Set Title - gameTitle.setText(gameCard.getName()); - loadImage(); - } - - public void loadImage() { - // Load Image - if (gameCard.getImgSrc() != null) { - var imageSrc = Application.class.getResource(gameCard.getImgSrc()); - if (imageSrc != null) { - gameImage.setImage(new Image(imageSrc.toExternalForm())); - } else { - System.err.printf("Image for: %s at %s, doen not exist\n", gameCard.getName(), gameCard.getImgSrc()); - } - } else { - System.err.printf("ImgSrc for: %s, not provided\n", gameCard.getName()); - } - } - - @FXML - protected void onCardMouseClick(MouseEvent event) { - GameSelectorController.onGameClick(event, gameCard); - } -} diff --git a/src/main/java/nl/isygameclient/controllers/game_selector/GameSelectorController.java b/src/main/java/nl/isygameclient/controllers/game_selector/GameSelectorController.java @@ -1,110 +0,0 @@ -package nl.isygameclient.controllers.game_selector; - -import javafx.collections.FXCollections; -import javafx.fxml.FXML; -import javafx.fxml.FXMLLoader; -import javafx.fxml.Initializable; -import javafx.scene.Node; -import javafx.scene.control.ListCell; -import javafx.scene.control.ListView; -import javafx.scene.control.TextField; -import javafx.scene.input.MouseEvent; -import javafx.scene.layout.FlowPane; -import javafx.scene.layout.VBox; -import nl.isygameclient.Application; -import nl.isygameclient.models.settings.GameCard; -import nl.isygameclient.util.SettingsFileHandler; -import nl.isygameclient.util.StageHandler; - -import java.io.IOException; -import java.net.URL; -import java.util.List; -import java.util.ResourceBundle; -import java.util.stream.Collectors; - -public class GameSelectorController implements Initializable { - - private final List<GameCard> gameCards = SettingsFileHandler.load().gameCards; - - @FXML - public TextField searchBox; - @FXML - public ListView<GameCard> gamesList; - @FXML - public VBox gameDetail; - - @FXML - public FlowPane gameContainer; - - public static void onGameClick(MouseEvent event, GameCard gameCard) { - var stageHandler = StageHandler.get(); - var stageName = "Game"; - if (event.getClickCount() == 2 && gameCard.getViewSrc() != null && !stageHandler.getStage(stageName).isShowing()) { - stageHandler.changeSceneOfStage(stageName, gameCard.getViewSrc()); - var stage = stageHandler.getStage(stageName); - stage.setTitle(gameCard.getName()); - stage.show(); - stageHandler.iconifyStage("GameSelector"); - } - } - - @Override - public void initialize(URL url, ResourceBundle resourceBundle) { - initializeGamesListView(); - initializeGamesListCells(); - initializeGameCards(); - } - - private void initializeGamesListView() { - gamesList.setItems(FXCollections.observableList(gameCards)); - searchBox.textProperty().addListener((observable, oldValue, newValue) -> { - var filteredList = FXCollections.observableList(filterGameCards(newValue)); - gamesList.setItems(filteredList); - }); - } - - private void initializeGamesListCells() { - gamesList.setCellFactory(lv -> { - ListCell<GameCard> listCell = new ListCell<>() { - @Override - protected void updateItem(GameCard item, boolean empty) { - super.updateItem(item, empty); - - if (empty || item == null || item.getName() == null) { - setText(null); - } else { - setText(item.getName()); - } - } - }; - listCell.setOnMouseClicked((event) -> { - GameCard gameCard = listCell.getItem(); - onGameClick(event, gameCard); - }); - return listCell; - }); - } - - private void initializeGameCards() { - try { - for (GameCard gameCard : gameCards) { - FXMLLoader fxmlLoader = new FXMLLoader(Application.class.getResource("views/game_selector/GameCard.fxml")); - Node node = fxmlLoader.load(); - GameCardController controller = fxmlLoader.getController(); - controller.initializeCard(gameCard); - gameContainer.getChildren().add(node); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - private List<GameCard> filterGameCards(String value) { - return gameCards.stream().filter(gameCard -> gameCard.getName().contains(value)).collect(Collectors.toList()); - } - - @FXML - protected void onClearSearchButtonClick() { - searchBox.clear(); - } -} diff --git a/src/main/java/nl/isygameclient/controllers/games/GameController.java b/src/main/java/nl/isygameclient/controllers/games/GameController.java @@ -1,17 +1,9 @@ package nl.isygameclient.controllers.games; -import javafx.fxml.FXML; -import nl.isygameclient.models.Game; -import nl.isygameclient.util.StageHandler; +import javafx.event.ActionEvent; -public abstract class GameController { +public interface GameController { - protected Game game; - - @FXML - protected void onExitButtonClick() { - var settingsHandler = StageHandler.get(); - settingsHandler.getStage("Game").hide(); - settingsHandler.focusStage("GameSelector"); - } + void onNewGameButtonClick(ActionEvent e) throws InterruptedException; + void onMainMenuButtonClick(ActionEvent e); } diff --git a/src/main/java/nl/isygameclient/controllers/games/GameMenuController.java b/src/main/java/nl/isygameclient/controllers/games/GameMenuController.java @@ -0,0 +1,15 @@ +package nl.isygameclient.controllers.games; + +import javafx.event.ActionEvent; +import javafx.fxml.FXML; + +public interface GameMenuController { + + @FXML + void onSinglePlayerButtonClick(ActionEvent e); + @FXML + void onMultiPlayerButtonClick(ActionEvent e); + + @FXML + void onExitGameButtonClick(ActionEvent e); +} diff --git a/src/main/java/nl/isygameclient/controllers/games/othello/OthelloMainMenuController.java b/src/main/java/nl/isygameclient/controllers/games/othello/OthelloMainMenuController.java @@ -0,0 +1,27 @@ +package nl.isygameclient.controllers.games.othello; + +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import nl.isygameclient.Window; +import nl.isygameclient.controllers.games.GameController; +import nl.isygameclient.controllers.games.GameMenuController; +import nl.isygameclient.util.StageHandler; + +public class OthelloMainMenuController implements GameMenuController { + @Override + public void onSinglePlayerButtonClick(ActionEvent e) { + StageHandler.get().changeSceneOfStage(Window.GAME, "/nl/isygameclient/views/games/othello/OthelloSinglePlayer.fxml"); + } + + @Override + public void onMultiPlayerButtonClick(ActionEvent e) { + StageHandler.get().changeSceneOfStage(Window.GAME,"/nl/isygameclient/views/games/othello/OthelloMultiPlayer.fxml"); + } + + @Override + public void onExitGameButtonClick(ActionEvent e) { + var stageHandler = StageHandler.get(); + stageHandler.getStage(Window.GAME).hide(); + stageHandler.focusStage(Window.APP); + } +} diff --git a/src/main/java/nl/isygameclient/controllers/games/othello/OthelloMultiPlayerController.java b/src/main/java/nl/isygameclient/controllers/games/othello/OthelloMultiPlayerController.java @@ -0,0 +1,266 @@ +package nl.isygameclient.controllers.games.othello; + +import com.jfoenix.controls.JFXButton; +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.TextField; +import javafx.scene.layout.GridPane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Circle; +import nl.isygameclient.Window; +import nl.isygameclient.controllers.games.GameController; +import nl.isygameclient.models.Ai; +import nl.isygameclient.models.Game; +import nl.isygameclient.models.Player; +import nl.isygameclient.models.PlayerManager; +import nl.isygameclient.models.games.Othello; +import nl.isygameclient.network.GameClient; +import nl.isygameclient.network.GameType; +import nl.isygameclient.network.Match; +import nl.isygameclient.util.StageHandler; +import nl.isygameclient.util.Vector2D; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.ResourceBundle; +import java.util.stream.Stream; + +public class OthelloMultiPlayerController implements GameController, Initializable, Runnable { + + private Game game; + private Thread gameThread; + private boolean running; + + private GameClient client; + private Match match; + private String playerSelf = "X", playerOther = "O"; + + private JFXButton[][] boardButtons; + + @FXML + private TextField hostField; + @FXML + private TextField portField; + @FXML + private TextField nameField; + + @FXML + private TextField opponentField; + @FXML + private GridPane boardGrid; + + private int[][] heuristics = { + {4, 3, 3, 3, 3, 3, 3, 4}, + {3, 2, 2, 2, 2, 2, 2, 3}, + {3, 2, 1, 1, 1, 1, 2, 3}, + {3, 2, 1, 1, 1, 1, 2, 3}, + {3, 2, 1, 1, 1, 1, 2, 3}, + {3, 2, 1, 1, 1, 1, 2, 3}, + {3, 2, 2, 2, 2, 2, 2, 3}, + {4, 3, 3, 3, 3, 3, 3, 4} + }; + + private boolean hasClicked = false; + private Vector2D<Integer, Integer> clickedPos; + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + var player = new Player("player1", "white") { + @Override + public Vector2D<Integer, Integer> onPlayerTurn() { + return clickedPos; + } + }; + var players = List.of(player, new Ai("player2", "black", heuristics)); + var manager = new PlayerManager(0, new ArrayList<>(players)); + game = new Othello(manager); + initializeBoard(); + updateButtons(); + } + + private void initializeBoard() { + var board = game.getBoard(); + boardButtons = new JFXButton[board.getHeight()][board.getWidth()]; + for (int i = 0; i < board.getHeight(); i++) { + for (int j = 0; j < board.getWidth(); j++) { + JFXButton button = new JFXButton(); + var index = i + "," + j; + button.setId(index); + button.setMinSize(60.0, 60.0); + button.setMaxSize(60.0, 60.0); + + var styleClass = button.getStyleClass(); + styleClass.add("othello-button"); + styleClass.add("headline-small"); + button.setOnAction((ActionEvent event) -> onMoveButtonClick(button)); + boardButtons[i][j] = button; + boardGrid.add(button, i, j); + } + } + } + + private void updateButtons() { + clearBoardButtons(); + var board = game.getBoard(); + for (int i = 0; i < board.getHeight(); i++) { + for (int j = 0; j < board.getWidth(); j++) { + var index = board.get(new Vector2D<>(i, j)); + if (index == null) continue; + if (Objects.equals("white", index.getPlayingAs())) { + addStone(boardButtons[i][j], Color.WHITE); + } else if (Objects.equals("black", index.getPlayingAs())) { + addStone(boardButtons[i][j], Color.BLACK); + } + } + } + } + + private void addStone(JFXButton button, Color color) { + var circle = new Circle(); + circle.setRadius(20); + circle.setFill(color); + button.setGraphic(circle); + } + + private void onMoveButtonClick(JFXButton button) { + // Move + var id = button.getId().split(","); + var index = Stream.of(id).mapToInt(Integer::parseInt).toArray(); + var manager = game.getPlayerManager(); + var currentPlayer = manager.getCurrentPlayer(); + if (game.getValidMoves(currentPlayer).isEmpty()) { + manager.nextPlayer(); + return; + } + if (game.isMoveValid(currentPlayer, new Vector2D<>(index[0], index[1]))) { + game.move(currentPlayer, new Vector2D<>(index[0], index[1])); + updateButtons(); + } + + if (game.isGameOver()) { + disableBoardButtons(); + } + } + + public void run() { + running = true; +// try { +// client = new GameClient(hostField.getText(), Integer.parseInt(portField.getText())); +// client.login(nameField.getText()); +// +// if (opponentField.getText().length() == 0) +// match = client.match(GameType.TICTACTOE); +// else +// match = client.match(GameType.TICTACTOE, opponentField.getText()); +// +// while (running) { +// match.update(); +// +// if (!match.isStarted()) +// continue; +// +// // game.setCurrentPlayer(match.isYourTurn() ? playerSelf : playerOther); +// // game.move(Integer.parseInt(moveMap.get("move"))); +// Platform.runLater(() -> { +// playingAgainstLabel.setText(match.getOpponent()); +// +// if (match.isYourTurn()) { +// currentPlayer.setText(playerSelf); +// enableBoardButtons(); +// } else { +// currentPlayer.setText(playerOther); +// disableBoardButtons(); +// } +// for (int i = 0; i < 3 * 3; i++) { +// switch (match.getMove(i)) { +// case -1 -> boardButtons.get(i).setText(playerOther); +// case 0 -> boardButtons.get(i).setText(""); +// case 1 -> boardButtons.get(i).setText(playerSelf); +// } +// } +// }); +// +// if (match.getOutcome() == null) +// continue; +// +// running = false; +// +// Platform.runLater(() -> { +// switch (match.getOutcome().type) { +// case DRAW: +// System.out.println("Draw!"); +// gameOverText.setText("Draw!"); +// gameOverText.setVisible(true); +// break; +// case LOSS: +// System.out.printf("%s, Is the Winner!\n\n", playerOther); +// gameOverText.setText(String.format("%s, is the Winner!\n\n", playerOther)); +// gameOverText.setVisible(true); +// break; +// case WIN: +// System.out.printf("%s, Is the Winner!\n\n", playerSelf); +// gameOverText.setText(String.format("%s, is the Winner!\n\n", playerSelf)); +// gameOverText.setVisible(true); +// default: +// } +// }); +// } +// match.abort(); +// client.close(); +// } catch (IOException e) { +// e.printStackTrace(); +// } + } + + + private void clearBoardButtons() { + for (JFXButton[] row : boardButtons) { + for (JFXButton button : row) { + button.setGraphic(null); + } + } + } + + private void disableBoardButtons() { + for (JFXButton[] row : boardButtons) { + for (JFXButton button : row) { + button.setDisable(true); + } + } + } + + private void enableBoardButtons() { + for (JFXButton[] row : boardButtons) { + for (JFXButton button : row) { + button.setDisable(false); + } + } + } + + @FXML + public void onNewGameButtonClick(ActionEvent e) throws NumberFormatException, InterruptedException { + game.restart(); +// gameOverText.setVisible(false); + + if (gameThread != null && running) { + running = false; + gameThread.join(); + } + gameThread = new Thread(this); + gameThread.start(); + + updateButtons(); + enableBoardButtons(); + } + + @Override + public void onMainMenuButtonClick(ActionEvent e) { + StageHandler.get().changeSceneOfStage(Window.GAME, "/nl/isygameclient/views/games/othello/OthelloMainMenu.fxml"); + + } +} diff --git a/src/main/java/nl/isygameclient/controllers/games/othello/OthelloSinglePlayerController.java b/src/main/java/nl/isygameclient/controllers/games/othello/OthelloSinglePlayerController.java @@ -4,32 +4,57 @@ import com.jfoenix.controls.JFXButton; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; -import javafx.scene.control.Label; import javafx.scene.layout.GridPane; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; +import nl.isygameclient.Window; import nl.isygameclient.controllers.games.GameController; +import nl.isygameclient.models.Ai; +import nl.isygameclient.models.Game; import nl.isygameclient.models.Player; import nl.isygameclient.models.PlayerManager; -import nl.isygameclient.models.games.othello.Othello; +import nl.isygameclient.models.games.Othello; +import nl.isygameclient.util.StageHandler; import nl.isygameclient.util.Vector2D; import java.net.URL; import java.util.*; import java.util.stream.Stream; -public class OthelloSinglePlayerController extends GameController implements Initializable { +public class OthelloSinglePlayerController implements GameController, Initializable { + private Game game; private JFXButton[][] boardButtons; @FXML private GridPane boardGrid; + private int[][] heuristics = { + {4, 3, 3, 3, 3, 3, 3, 4}, + {3, 2, 2, 2, 2, 2, 2, 3}, + {3, 2, 1, 1, 1, 1, 2, 3}, + {3, 2, 1, 1, 1, 1, 2, 3}, + {3, 2, 1, 1, 1, 1, 2, 3}, + {3, 2, 1, 1, 1, 1, 2, 3}, + {3, 2, 2, 2, 2, 2, 2, 3}, + {4, 3, 3, 3, 3, 3, 3, 4} + }; + + private boolean hasClicked = false; + private Vector2D<Integer, Integer> clickedPos; + private boolean againstAi = false; + @Override public void initialize(URL url, ResourceBundle resourceBundle) { -// var players = List.of(new Player("player1", "white"), new Player("player2", "black")); -// var manager = new PlayerManager(0, new ArrayList<>(players)); -// game = new Othello(manager); + var player = new Player("player1", "white") { + @Override + public Vector2D<Integer, Integer> onPlayerTurn() { + return clickedPos; + } + }; + var players = List.of(player, new Ai("player2", "black", heuristics)); + var manager = new PlayerManager(0, new ArrayList<>(players)); + game = new Othello(manager); initializeBoard(); updateButtons(); } @@ -37,10 +62,10 @@ public class OthelloSinglePlayerController extends GameController implements Ini private void initializeBoard() { var board = game.getBoard(); boardButtons = new JFXButton[board.getHeight()][board.getWidth()]; - for (int i = 0; i < board.getHeight(); i++) { - for (int j = 0; j < board.getWidth(); j++) { + for (int x = 0; x < board.getHeight(); x++) { + for (int y = 0; y < board.getWidth(); y++) { JFXButton button = new JFXButton(); - var index = i + "," + j; + var index = x + "," + y; button.setId(index); button.setMinSize(60.0, 60.0); button.setMaxSize(60.0, 60.0); @@ -49,8 +74,8 @@ public class OthelloSinglePlayerController extends GameController implements Ini styleClass.add("othello-button"); styleClass.add("headline-small"); button.setOnAction((ActionEvent event) -> onMoveButtonClick(button)); - boardButtons[i][j] = button; - boardGrid.add(button, i, j); + boardButtons[y][x] = button; + boardGrid.add(button, x, y); } } } @@ -58,14 +83,14 @@ public class OthelloSinglePlayerController extends GameController implements Ini private void updateButtons() { clearBoardButtons(); var board = game.getBoard(); - for (int i = 0; i < board.getHeight(); i++) { - for (int j = 0; j < board.getWidth(); j++) { - var index = board.get(new Vector2D<>(j,i)); + for (int x = 0; x < board.getHeight(); x++) { + for (int y = 0; y < board.getWidth(); y++) { + var index = board.get(new Vector2D<>(x, y)); if (index == null) continue; - if (Objects.equals( "white", index.getPlayingAs())) { - addStone(boardButtons[i][j], Color.WHITE); - } else if(Objects.equals( "black", index.getPlayingAs())) { - addStone(boardButtons[i][j], Color.BLACK); + if (Objects.equals("white", index.getPlayingAs())) { + addStone(boardButtons[y][x], Color.WHITE); + } else if (Objects.equals("black", index.getPlayingAs())) { + addStone(boardButtons[y][x], Color.BLACK); } } } @@ -77,21 +102,32 @@ public class OthelloSinglePlayerController extends GameController implements Ini circle.setFill(color); button.setGraphic(circle); } - - private void onMoveButtonClick(JFXButton button) { - // Move - var id = button.getId().split(","); - var index = Stream.of(id).mapToInt(Integer::parseInt).toArray(); + private void doMove(Vector2D<Integer, Integer> move) { var manager = game.getPlayerManager(); var currentPlayer = manager.getCurrentPlayer(); + if (game.getValidMoves(currentPlayer).isEmpty()) { manager.nextPlayer(); return; } - if (game.isMoveValid(currentPlayer, new Vector2D<>(index[0], index[1]))) { - game.move(currentPlayer, new Vector2D<>(index[0], index[1])); + if (game.isMoveValid(currentPlayer, move)) { + game.move(currentPlayer, move); updateButtons(); - manager.nextPlayer(); + } + } + + private void onMoveButtonClick(JFXButton button) { + // Move + var id = button.getId().split(","); + var index = Stream.of(id).mapToInt(Integer::parseInt).toArray(); + + var playerMove = new Vector2D<>(index[0], index[1]); + doMove(playerMove); + + if (againstAi) { + var manager = game.getPlayerManager(); + var move = manager.getCurrentPlayer().onPlayerTurn(); + doMove(move); } if (game.isGameOver()) { @@ -123,12 +159,15 @@ public class OthelloSinglePlayerController extends GameController implements Ini } } + @Override public void onNewGameButtonClick(ActionEvent actionEvent) { game.restart(); updateButtons(); enableBoardButtons(); } + + @Override public void onMainMenuButtonClick(ActionEvent actionEvent) { + StageHandler.get().changeSceneOfStage(Window.GAME, "/nl/isygameclient/views/games/othello/OthelloMainMenu.fxml"); } - } diff --git a/src/main/java/nl/isygameclient/controllers/games/tictactoe/TicTacToeMainMenuController.java b/src/main/java/nl/isygameclient/controllers/games/tictactoe/TicTacToeMainMenuController.java @@ -1,18 +1,27 @@ package nl.isygameclient.controllers.games.tictactoe; +import javafx.event.ActionEvent; import javafx.fxml.FXML; -import nl.isygameclient.controllers.games.GameController; +import nl.isygameclient.Window; +import nl.isygameclient.controllers.games.GameMenuController; import nl.isygameclient.util.StageHandler; -public class TicTacToeMainMenuController extends GameController { +public class TicTacToeMainMenuController implements GameMenuController { @FXML - public void onSinglePlayerButtonClick() { - StageHandler.get().changeSceneOfStage("Game", "views/Games/TicTacToe/TicTacToeSinglePlayer.fxml"); + public void onSinglePlayerButtonClick(ActionEvent e) { + StageHandler.get().changeSceneOfStage(Window.GAME, "/nl/isygameclient/views/games/tictactoe/TicTacToeSinglePlayer.fxml"); } @FXML - public void onMultiplayerButtonClick() { - StageHandler.get().changeSceneOfStage("Game","views/Games/TicTacToe/TicTacToeMultiPlayer.fxml"); + public void onMultiPlayerButtonClick(ActionEvent e) { + StageHandler.get().changeSceneOfStage(Window.GAME,"/nl/isygameclient/views/games/tictactoe/TicTacToeMultiPlayer.fxml"); + } + + @FXML + public void onExitGameButtonClick(ActionEvent e) { + var stageHandler = StageHandler.get(); + stageHandler.getStage(Window.GAME).hide(); + stageHandler.focusStage(Window.APP); } } diff --git a/src/main/java/nl/isygameclient/controllers/games/tictactoe/TicTacToeMultiPlayerController.java b/src/main/java/nl/isygameclient/controllers/games/tictactoe/TicTacToeMultiPlayerController.java @@ -14,16 +14,18 @@ import javafx.fxml.Initializable; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.layout.GridPane; +import nl.isygameclient.Window; import nl.isygameclient.controllers.games.GameController; -import nl.isygameclient.models.games.tictactoe.TicTacToe; +import nl.isygameclient.models.Game; import nl.isygameclient.network.GameClient; import nl.isygameclient.network.GameType; import nl.isygameclient.network.Match; import nl.isygameclient.util.StageHandler; -public class TicTacToeMultiPlayerController extends GameController implements Runnable, Initializable { +public class TicTacToeMultiPlayerController implements GameController, Initializable, Runnable { private final ArrayList<JFXButton> boardButtons = new ArrayList<>(); - private final String[] players = { "X", "O" }; + private final String[] players = { "X", "O" }; + private Game game; @FXML private Label playingAgainstLabel; @@ -142,17 +144,7 @@ public class TicTacToeMultiPlayerController extends GameController implements Ru } } - @FXML - private void onNewGameButtonClick() throws NumberFormatException, InterruptedException { - gameOverText.setVisible(false); - if (gameThread != null && running) { - running = false; - gameThread.join(); - } - gameThread = new Thread(this); - gameThread.start(); - } private void onMoveButtonClick(JFXButton button) { try { @@ -196,8 +188,20 @@ public class TicTacToeMultiPlayerController extends GameController implements Ru } } - @FXML - protected void onMainMenuButtonClick() { - StageHandler.get().changeSceneOfStage("Game","views/Games/TicTacToe/TicTacToeMainMenu.fxml"); + @Override + public void onNewGameButtonClick(ActionEvent e) throws NumberFormatException, InterruptedException { + gameOverText.setVisible(false); + + if (gameThread != null && running) { + running = false; + gameThread.join(); + } + gameThread = new Thread(this); + gameThread.start(); + } + + @Override + public void onMainMenuButtonClick(ActionEvent e) { + StageHandler.get().changeSceneOfStage(Window.GAME,"/nl/isygameclient/views/games/tictactoe/TicTacToeMainMenu.fxml"); } } diff --git a/src/main/java/nl/isygameclient/controllers/games/tictactoe/TicTacToeSettingsController.java b/src/main/java/nl/isygameclient/controllers/games/tictactoe/TicTacToeSettingsController.java @@ -0,0 +1,28 @@ +package nl.isygameclient.controllers.games.tictactoe; + +import com.jfoenix.controls.JFXComboBox; +import javafx.event.ActionEvent; +import javafx.fxml.Initializable; + +import java.net.URL; +import java.util.ResourceBundle; + +public class TicTacToeSettingsController implements Initializable { + public JFXComboBox<String> opponentCombo; + public JFXComboBox<String> playingAsCombo; + public JFXComboBox<String> difficultyCombo; + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + + } + + public void onDifficultyComboSelect(ActionEvent actionEvent) { + } + + public void onPlayingAsComboSelect(ActionEvent actionEvent) { + } + + public void onOpponentComboSelect(ActionEvent actionEvent) { + } +} diff --git a/src/main/java/nl/isygameclient/controllers/games/tictactoe/TicTacToeSinglePlayerController.java b/src/main/java/nl/isygameclient/controllers/games/tictactoe/TicTacToeSinglePlayerController.java @@ -11,22 +11,19 @@ import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.layout.GridPane; +import nl.isygameclient.Window; import nl.isygameclient.controllers.games.GameController; +import nl.isygameclient.models.Game; import nl.isygameclient.models.Player; import nl.isygameclient.models.PlayerManager; -import nl.isygameclient.models.games.tictactoe.TicTacToe; +import nl.isygameclient.models.games.TicTacToe; import nl.isygameclient.util.StageHandler; import nl.isygameclient.util.Vector2D; -public class TicTacToeSinglePlayerController extends GameController { - private final ArrayList<JFXButton> boardButtons = new ArrayList<>(); +public class TicTacToeSinglePlayerController implements GameController { - @FXML - public JFXComboBox<String> difficultyCombo; - @FXML - public JFXComboBox<String> playingAsCombo; - @FXML - public JFXComboBox<String> opponentCombo; + private Game game; + private final ArrayList<JFXButton> boardButtons = new ArrayList<>(); @FXML protected Label currentPlayer; @@ -36,7 +33,6 @@ public class TicTacToeSinglePlayerController extends GameController { @FXML protected GridPane grid; - private Thread gameThread; @FXML protected void initialize() { @@ -46,9 +42,19 @@ public class TicTacToeSinglePlayerController extends GameController { } private void initializeGame() { -// var players = new ArrayList<>(List.of(new Player("player1", "x"), new Player("player2", "o"))); -// var manager = new PlayerManager(0, players); -// game = new TicTacToe(manager); + var players = new ArrayList<>(List.of(new Player("player1", "x") { + @Override + public Vector2D<Integer, Integer> onPlayerTurn() { + return null; + } + }, new Player("player2", "o") { + @Override + public Vector2D<Integer, Integer> onPlayerTurn() { + return null; + } + })); + var manager = new PlayerManager(0, players); + game = new TicTacToe(manager); } @@ -86,7 +92,6 @@ public class TicTacToeSinglePlayerController extends GameController { game.move(currentPlayer, new Vector2D<>(index[0], index[1])); button.setText(currentPlayer.getPlayingAs()); updateCurrentPlayerLabel(); - manager.nextPlayer(); } // Game Over @@ -97,14 +102,12 @@ public class TicTacToeSinglePlayerController extends GameController { private void onGameOver() { disableBoardButtons(); - System.out.println("Game Over"); if (game.isDraw()) { - System.out.println("Draw!"); gameOverText.setText("Draw!"); gameOverText.setVisible(true); } else { - System.out.printf("%s, Is the Winner!\n\n", game.getWinners().get(0)); - gameOverText.setText(String.format("%s, is the Winner!\n\n", game.getWinners().get(0))); + var winner = game.getWinners().get(0).getPlayingAs().toUpperCase(); + gameOverText.setText(String.format("%s, is the Winner!\n\n", winner)); gameOverText.setVisible(true); } } @@ -127,8 +130,8 @@ public class TicTacToeSinglePlayerController extends GameController { } } - @FXML - protected void onNewGameButtonClick() { + @Override + public void onNewGameButtonClick(ActionEvent e) { // Make new Game game.restart(); @@ -137,8 +140,8 @@ public class TicTacToeSinglePlayerController extends GameController { gameOverText.setVisible(false); } - @FXML - protected void onMainMenuButtonClick() { - StageHandler.get().changeSceneOfStage("Game","views/Games/TicTacToe/TicTacToeMainMenu.fxml"); + @Override + public void onMainMenuButtonClick(ActionEvent e) { + StageHandler.get().changeSceneOfStage(Window.GAME,"/nl/isygameclient/views/games/tictactoe/TicTacToeMainMenu.fxml"); } } diff --git a/src/main/java/nl/isygameclient/models/games/Othello.java b/src/main/java/nl/isygameclient/models/games/Othello.java @@ -0,0 +1,180 @@ +package nl.isygameclient.models.games; + +import java.util.*; +import java.util.stream.Collectors; +import nl.isygameclient.models.Game; +import nl.isygameclient.models.Player; +import nl.isygameclient.models.PlayerManager; +import nl.isygameclient.models.board.HistoryBoard; +import nl.isygameclient.util.Vector2D; + +public class Othello extends Game { + + public Othello(PlayerManager playerManager) { + super(playerManager, new HistoryBoard<>(8, 8)); + initializeBoard(); + } + + @Override + public void restart() { + playerManager.restart(); + board.clear(); + initializeBoard(); + } + + public void initializeBoard() { + board.set(playerManager.getCurrentPlayer(), new Vector2D<>(3, 4)); + board.set(playerManager.getCurrentPlayer(), new Vector2D<>(4, 3)); + playerManager.nextPlayer(); + board.set(playerManager.getCurrentPlayer(), new Vector2D<>(3, 3)); + board.set(playerManager.getCurrentPlayer(), new Vector2D<>(4, 4)); + playerManager.nextPlayer(); + } + + @Override + public boolean isDraw() { + var scores = getScores(); + return scores.values().stream().distinct().count() == 1; + } + + @Override + public boolean isGameOver() { + for (Player player : playerManager.getPlayers()) { + if (getValidMoves(player).size() > 0) { + return false; + } + } + return true; + } + + @Override + public boolean isWinner(Player player) { + Player winner = null; + int score = 0; + for (Map.Entry<Player, Integer> entry : getScores().entrySet()) { + if (entry.getValue() > score) { + winner = entry.getKey(); + score = entry.getValue(); + } + } + return Objects.equals(player, winner); + } + + + @Override + public boolean move(Player player, Vector2D<Integer, Integer> pos) { + if (!isMoveValid(player, pos)) { + return false; + } + + var flippable = checkNeighbours(player, pos); + + Map<Vector2D<Integer, Integer>, Player> changes = flippable.stream().collect(Collectors.toMap(e -> e, e -> player)); + board.add(player, changes); + playerManager.nextPlayer(); + return true; + } + + + @Override + public boolean isMoveValid(Player player, Vector2D<Integer, Integer> pos) { + if (board.get(pos) != null) + return false; + + var flippable = checkNeighbours(player, pos); + return !flippable.isEmpty(); + } + + + private List<Vector2D<Integer, Integer>> rangeContains(Player player, Vector2D<Integer, Integer> pos, Vector2D<Integer, Integer> dir) { + List<Vector2D<Integer, Integer>> flippable = new ArrayList<>(); + int x = pos.getX() + dir.getX(); + int y = pos.getY() + dir.getY(); + while (x >= 0 && x < board.getWidth() && y >= 0 && y < board.getHeight()) { + var newPos = new Vector2D<>(x, y); + flippable.add(newPos); + if (Objects.equals(board.get(newPos), player)) { + return flippable; + } else if (board.get(newPos) == null) { + return null; + } + x += dir.getX(); + y += dir.getY(); + } + return null; + } + + + private Set<Vector2D<Integer, Integer>> checkNeighbours(Player player, Vector2D<Integer, Integer> pos) { + Set<Vector2D<Integer, Integer>> flippable = new HashSet<>(); + for (int dx = -1; dx <= 1; dx++) { + if ((pos.getX() + dx) < 0 || (pos.getX() + dx) >= board.getWidth()) + continue; + + for (int dy = -1; dy <= 1; dy++) { + if ((pos.getY() + dy) < 0 || (pos.getY() + dy) >= board.getHeight()) + continue; + + if (dx == 0 && dy == 0) + continue; + + var checkPos = board.get(new Vector2D<>(pos.getX() + dx, pos.getY() + dy)); + if (checkPos != null && checkPos != player) { + List<Vector2D<Integer, Integer>> flip = rangeContains(player, pos, new Vector2D<>(dx, dy)); + if (flip != null) + flippable.addAll(flip); + } + } + } + if (!flippable.isEmpty()) { + flippable.add(pos); + } + return flippable; + } + + @Override + public List<Vector2D<Integer, Integer>> getValidMoves(Player player) { + List<Vector2D<Integer, Integer>> valid = new ArrayList<>(); + for (int y = 0; y < board.getHeight(); y++) { + for (int x = 0; x < board.getWidth(); x++) { + if (isMoveValid(player, new Vector2D<>(x, y))) { + valid.add(new Vector2D<>(x, y)); + } + } + } + return valid; + } + + @Override + public List<Player> getWinners() { + ArrayList<Player> winners = new ArrayList<>(); + for (Player player : playerManager.getPlayers()) { + if (isWinner(player)) { + winners.add(player); + } + } + return winners; + } + + @Override + public int getPlayerScore(Player player) { + int score = 0; + for (int y = 0; y < board.getHeight(); y++) { + for (int x = 0; x < board.getWidth(); x++) { + if (Objects.equals(player, board.get(new Vector2D<>(x, y)))) { + score += 1; + } + } + } + return score; + } + + private HashMap<Player, Integer> getScores() { + HashMap<Player, Integer> scores = new HashMap<>(); + for (Player player : playerManager.getPlayers()) { + int score = getPlayerScore(player); + scores.put(player, score); + } + return scores; + } +} diff --git a/src/main/java/nl/isygameclient/models/games/TicTacToe.java b/src/main/java/nl/isygameclient/models/games/TicTacToe.java @@ -0,0 +1,107 @@ +package nl.isygameclient.models.games; + +import nl.isygameclient.models.Game; +import nl.isygameclient.models.Player; +import nl.isygameclient.models.PlayerManager; +import nl.isygameclient.models.board.HistoryBoard; +import nl.isygameclient.util.Vector2D; + +import java.util.*; + +public class TicTacToe extends Game { + + public TicTacToe(PlayerManager playerManager) { + super(playerManager, new HistoryBoard<>(3,3){}); + } + + @Override + public void restart() { + playerManager.restart(); + board = new HistoryBoard<>(3,3){}; + } + + @Override + public boolean move(Player player, Vector2D<Integer, Integer> pos) { + if (!isMoveValid(player, pos)) { + return false; + } + + Map<Vector2D<Integer, Integer>, Player> changes = new HashMap<>(); + changes.put(pos, player); + board.add(player, changes); + + playerManager.nextPlayer(); + return true; + } + + @Override + public boolean isMoveValid(Player player, Vector2D<Integer, Integer> pos) { + boolean positionOnBoard = (pos.getX() >= 0 && pos.getX() < board.getWidth()) && (pos.getY() >= 0 && pos.getY() < board.getHeight()); + boolean positionEmpty = (board.get(pos) == null); + return positionOnBoard && positionEmpty; + } + + @Override + public boolean isDraw() { + for (Player player : playerManager.getPlayers()) { + if (getValidMoves(player).size() > 0) { + return false; + } + } + return true; + } + + @Override + public boolean isGameOver() { + return getWinners().size() > 0 || isDraw(); + } + + + private boolean isPlayer(Player player, Vector2D<Integer, Integer> pos) { + return Objects.equals(player, board.get(pos)); + } + @Override + public boolean isWinner(Player player) { + boolean topRow = isPlayer(player, new Vector2D<>(0,0)) && isPlayer(player, new Vector2D<>(0,1)) && isPlayer(player, new Vector2D<>(0,2)); + boolean middleRow = isPlayer(player, new Vector2D<>(1,0)) && isPlayer(player, new Vector2D<>(1,1)) && isPlayer(player, new Vector2D<>(1,2)); + boolean bottomRow = isPlayer(player, new Vector2D<>(2,0)) && isPlayer(player, new Vector2D<>(2,1)) && isPlayer(player, new Vector2D<>(2,2)); + + boolean leftColumn = isPlayer(player, new Vector2D<>(0,0)) && isPlayer(player, new Vector2D<>(1,0)) && isPlayer(player, new Vector2D<>(2,0)); + boolean midColumn = isPlayer(player, new Vector2D<>(0,1)) && isPlayer(player, new Vector2D<>(1,1)) && isPlayer(player, new Vector2D<>(2,1)); + boolean rightColumn = isPlayer(player, new Vector2D<>(0,2)) && isPlayer(player, new Vector2D<>(1,2)) && isPlayer(player, new Vector2D<>(2,2)); + + boolean lrCross = isPlayer(player, new Vector2D<>(0,0)) && isPlayer(player, new Vector2D<>(1,1)) && isPlayer(player, new Vector2D<>(2,2)); + boolean rlCross = isPlayer(player, new Vector2D<>(0,2)) && isPlayer(player, new Vector2D<>(1,1)) && isPlayer(player, new Vector2D<>(2,0)); + + return topRow || middleRow || bottomRow || leftColumn || midColumn || rightColumn || lrCross || rlCross; + } + + @Override + public List<Vector2D<Integer, Integer>> getValidMoves(Player player) { + List<Vector2D<Integer, Integer>> valid = new ArrayList<>(); + for (int y = 0; y < board.getHeight(); y++) { + for (int x = 0; x < board.getWidth(); x++) { + if (isMoveValid(player, new Vector2D<>(x, y))) valid.add(new Vector2D<>(x,y)); + } + } + return valid; + } + + public List<Player> getWinners(){ + List<Player> players = new ArrayList<>(); + for (Player player: playerManager.getPlayers()) { + if (isWinner(player)) { + players.add(player); + } + } + return players; + } + + @Override + public int getPlayerScore(Player player){ + if (isGameOver() && isWinner(player)) { + return 1; + } + return 0; + } +} +\ No newline at end of file diff --git a/src/main/java/nl/isygameclient/models/games/othello/Othello.java b/src/main/java/nl/isygameclient/models/games/othello/Othello.java @@ -1,180 +0,0 @@ -package nl.isygameclient.models.games.othello; - -import java.util.*; -import java.util.stream.Collectors; -import nl.isygameclient.models.Game; -import nl.isygameclient.models.Player; -import nl.isygameclient.models.PlayerManager; -import nl.isygameclient.models.board.HistoryBoard; -import nl.isygameclient.util.Vector2D; - -public class Othello extends Game { - - public Othello(PlayerManager playerManager) { - super(playerManager, new HistoryBoard<>(8, 8)); - initializeBoard(); - } - - @Override - public void restart() { - playerManager.restart(); - board.clear(); - initializeBoard(); - } - - public void initializeBoard() { - board.set(playerManager.getCurrentPlayer(), new Vector2D<>(3, 4)); - board.set(playerManager.getCurrentPlayer(), new Vector2D<>(4, 3)); - playerManager.nextPlayer(); - board.set(playerManager.getCurrentPlayer(), new Vector2D<>(3, 3)); - board.set(playerManager.getCurrentPlayer(), new Vector2D<>(4, 4)); - playerManager.nextPlayer(); - } - - @Override - public boolean isDraw() { - var scores = getScores(); - return scores.values().stream().distinct().count() == 1; - } - - @Override - public boolean isGameOver() { - for (Player player : playerManager.getPlayers()) { - if (getValidMoves(player).size() > 0) { - return false; - } - } - return true; - } - - @Override - public boolean isWinner(Player player) { - Player winner = null; - int score = 0; - for (Map.Entry<Player, Integer> entry : getScores().entrySet()) { - if (entry.getValue() > score) { - winner = entry.getKey(); - score = entry.getValue(); - } - } - return Objects.equals(player, winner); - } - - - @Override - public boolean move(Player player, Vector2D<Integer, Integer> pos) { - if (!isMoveValid(player, pos)) { - return false; - } - - var flippable = checkNeighbours(player, pos); - - Map<Vector2D<Integer, Integer>, Player> changes = flippable.stream().collect(Collectors.toMap(e -> e, e -> player)); - board.add(player, changes); - playerManager.nextPlayer(); - return true; - } - - - @Override - public boolean isMoveValid(Player player, Vector2D<Integer, Integer> pos) { - if (board.get(pos) != null) - return false; - - var flippable = checkNeighbours(player, pos); - return !flippable.isEmpty(); - } - - - private List<Vector2D<Integer, Integer>> rangeContains(Player player, Vector2D<Integer, Integer> pos, Vector2D<Integer, Integer> dir) { - List<Vector2D<Integer, Integer>> flippable = new ArrayList<>(); - int x = pos.getX() + dir.getX(); - int y = pos.getY() + dir.getY(); - while (x >= 0 && x < board.getWidth() && y >= 0 && y < board.getHeight()) { - var newPos = new Vector2D<>(x, y); - flippable.add(newPos); - if (Objects.equals(board.get(newPos), player)) { - return flippable; - } else if (board.get(newPos) == null) { - return null; - } - x += dir.getX(); - y += dir.getY(); - } - return null; - } - - - private Set<Vector2D<Integer, Integer>> checkNeighbours(Player player, Vector2D<Integer, Integer> pos) { - Set<Vector2D<Integer, Integer>> flippable = new HashSet<>(); - for (int dx = -1; dx <= 1; dx++) { - if ((pos.getX() + dx) < 0 || (pos.getX() + dx) >= board.getWidth()) - continue; - - for (int dy = -1; dy <= 1; dy++) { - if ((pos.getY() + dy) < 0 || (pos.getY() + dy) >= board.getHeight()) - continue; - - if (dx == 0 && dy == 0) - continue; - - var checkPos = board.get(new Vector2D<>(pos.getX() + dx, pos.getY() + dy)); - if (checkPos != null && checkPos != player) { - List<Vector2D<Integer, Integer>> flip = rangeContains(player, pos, new Vector2D<>(dx, dy)); - if (flip != null) - flippable.addAll(flip); - } - } - } - if (!flippable.isEmpty()) { - flippable.add(pos); - } - return flippable; - } - - @Override - public List<Vector2D<Integer, Integer>> getValidMoves(Player player) { - List<Vector2D<Integer, Integer>> valid = new ArrayList<>(); - for (int y = 0; y < board.getHeight(); y++) { - for (int x = 0; x < board.getWidth(); x++) { - if (isMoveValid(player, new Vector2D<>(x, y))) { - valid.add(new Vector2D<>(x, y)); - } - } - } - return valid; - } - - @Override - public List<Player> getWinners() { - ArrayList<Player> winners = new ArrayList<>(); - for (Player player : playerManager.getPlayers()) { - if (isWinner(player)) { - winners.add(player); - } - } - return winners; - } - - @Override - public int getPlayerScore(Player player) { - int score = 0; - for (int y = 0; y < board.getHeight(); y++) { - for (int x = 0; x < board.getWidth(); x++) { - if (Objects.equals(player, board.get(new Vector2D<>(x, y)))) { - score += 1; - } - } - } - return score; - } - - private HashMap<Player, Integer> getScores() { - HashMap<Player, Integer> scores = new HashMap<>(); - for (Player player : playerManager.getPlayers()) { - int score = getPlayerScore(player); - scores.put(player, score); - } - return scores; - } -} diff --git a/src/main/java/nl/isygameclient/models/games/tictactoe/TicTacToe.java b/src/main/java/nl/isygameclient/models/games/tictactoe/TicTacToe.java @@ -1,103 +0,0 @@ -package nl.isygameclient.models.games.tictactoe; - -import nl.isygameclient.models.Game; -import nl.isygameclient.models.Player; -import nl.isygameclient.models.PlayerManager; -import nl.isygameclient.models.board.HistoryBoard; -import nl.isygameclient.util.Vector2D; - -import java.util.*; - -public class TicTacToe extends Game { - - public TicTacToe(PlayerManager playerManager) { - super(playerManager, new HistoryBoard<>(3,3){}); - } - - @Override - public void restart() { - playerManager.restart(); - board = new HistoryBoard<>(3,3){}; - } - - @Override - public boolean move(Player player, Vector2D<Integer, Integer> pos) { - if (!isMoveValid(player, pos)) { - return false; - } - - var currentPlayer = playerManager.getCurrentPlayer(); - Map<Vector2D<Integer, Integer>, Player> changes = new HashMap<>(); - changes.put(pos, currentPlayer); - board.add(currentPlayer, changes); - - playerManager.nextPlayer(); - return true; - } - - @Override - public boolean isMoveValid(Player player, Vector2D<Integer, Integer> pos) { - boolean positionOnBoard = (pos.getX() >= 0 && pos.getX() < board.getWidth()) && (pos.getY() >= 0 && pos.getY() < board.getHeight()); - boolean positionEmpty = (board.get(pos) == null); - return positionOnBoard && positionEmpty; - } - - @Override - public boolean isDraw() { - return !Objects.equals(board, null); - } - - @Override - public boolean isGameOver() { - return getWinners().size() < 1 || isDraw(); - } - - - private boolean isPlayer(Player player, Vector2D<Integer, Integer> pos) { - return Objects.equals(player, board.get(pos)); - } - @Override - public boolean isWinner(Player player) { - boolean topRow = isPlayer(player, new Vector2D<>(0,0)) && isPlayer(player, new Vector2D<>(0,1)) && isPlayer(player, new Vector2D<>(0,2)); - boolean middleRow = isPlayer(player, new Vector2D<>(1,0)) && isPlayer(player, new Vector2D<>(1,1)) && isPlayer(player, new Vector2D<>(1,2)); - boolean bottomRow = isPlayer(player, new Vector2D<>(2,0)) && isPlayer(player, new Vector2D<>(2,1)) && isPlayer(player, new Vector2D<>(2,2)); - - boolean leftColumn = isPlayer(player, new Vector2D<>(0,0)) && isPlayer(player, new Vector2D<>(0,1)) && isPlayer(player, new Vector2D<>(0,2)); - boolean midColumn = isPlayer(player, new Vector2D<>(1,0)) && isPlayer(player, new Vector2D<>(1,1)) && isPlayer(player, new Vector2D<>(1,2)); - boolean rightColumn = isPlayer(player, new Vector2D<>(2,0)) && isPlayer(player, new Vector2D<>(2,1)) && isPlayer(player, new Vector2D<>(2,2)); - - boolean lrCross = isPlayer(player, new Vector2D<>(0,0)) && isPlayer(player, new Vector2D<>(1,1)) && isPlayer(player, new Vector2D<>(2,2)); - boolean rlCross = isPlayer(player, new Vector2D<>(0,2)) && isPlayer(player, new Vector2D<>(1,1)) && isPlayer(player, new Vector2D<>(2,0)); - - return topRow || middleRow || bottomRow || leftColumn || midColumn || rightColumn || lrCross || rlCross; - } - - @Override - public List<Vector2D<Integer, Integer>> getValidMoves(Player player) { - List<Vector2D<Integer, Integer>> valid = new ArrayList<>(); - for (int y = 0; y < board.getHeight(); y++) { - for (int x = 0; x < board.getWidth(); x++) { - if (isMoveValid(player, new Vector2D<>(x, y))) valid.add(new Vector2D<>(x,y)); - } - } - return valid; - } - - public List<Player> getWinners(){ - List<Player> players = new ArrayList<>(); - for (Player player: playerManager.getPlayers()) { - if (isWinner(player)) { - players.add(player); - } - } - return players; - } - - @Override - public int getPlayerScore(Player player){ - if (isGameOver() && isWinner(player)) { - return 1; - } - return 0; - } -} -\ No newline at end of file diff --git a/src/main/java/nl/isygameclient/models/settings/GameCard.java b/src/main/java/nl/isygameclient/models/settings/GameCard.java @@ -1,38 +0,0 @@ -package nl.isygameclient.models.settings; - -public class GameCard { - - private String name; - private String viewSrc; - private String imgSrc; - - public GameCard(String name, String viewSrc, String imgSrc) { - this.name = name; - this.viewSrc = viewSrc; - this.imgSrc = imgSrc; - } - - public String getName() { - return name; - } - - public String getViewSrc() { - return viewSrc; - } - - public String getImgSrc() { - return imgSrc; - } - - public void setName(String name) { - this.name = name; - } - - public void setViewSrc(String viewSrc) { - this.viewSrc = viewSrc; - } - - public void setImgSrc(String imgSrc) { - this.imgSrc = imgSrc; - } -} diff --git a/src/main/java/nl/isygameclient/models/settings/Settings.java b/src/main/java/nl/isygameclient/models/settings/Settings.java @@ -1,25 +0,0 @@ -package nl.isygameclient.models.settings; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - - -/** - * This Class holds default settings for the application. - * It also provides the format of the settings that are saved to a file. - * - * @author A F Koens - */ -public class Settings { - public Map<String, StageSettings> stages = new HashMap<>(); - - public boolean tournamentMode = false; - - public ArrayList<GameCard> gameCards = new ArrayList<>(Arrays.asList( - new GameCard("TicTacToe", "views/games/tictactoe/TicTacToeMainMenu.fxml", "images/tictactoe_logo.png"), - new GameCard("Othello", "views/games/othello/OthelloSinglePlayer.fxml", "images/othello_logo.png"), - new GameCard("Starvation", null, null)) - ); -} diff --git a/src/main/java/nl/isygameclient/models/settings/StageSettings.java b/src/main/java/nl/isygameclient/models/settings/StageSettings.java @@ -1,61 +0,0 @@ -package nl.isygameclient.models.settings; - -import javafx.stage.Stage; - -public class StageSettings { - public String Title = "ISYGameClient"; - public double x = 0; - public double y = 0; - public double width = 680; - public double height = 480; - public double minWidth = 0; - public double minHeight = 0; - public double maxWidth = 1.7976931348623157E308; - public double maxHeight = 1.7976931348623157E308; - public boolean isIconified = false; - public boolean isAlwaysOnTop = false; - public boolean isFullScreen = true; - public boolean isResizable = true; - public boolean isMaximized = false; - public boolean isShowing = false; - - - public static StageSettings createSettingsFromStage(Stage stage) { - var stageSettings = new StageSettings(); - stageSettings.Title = stage.getTitle(); - stageSettings.x = stage.getX(); - stageSettings.y = stage.getY(); - stageSettings.width = stage.getWidth(); - stageSettings.height = stage.getHeight(); - stageSettings.minWidth = stage.getMinWidth(); - stageSettings.minHeight = stage.getMinHeight(); - stageSettings.maxWidth = stage.getMaxWidth(); - stageSettings.maxHeight = stage.getMaxHeight(); - stageSettings.isIconified = stage.isIconified(); - stageSettings.isAlwaysOnTop = stage.isAlwaysOnTop(); - stageSettings.isFullScreen = stage.isFullScreen(); - stageSettings.isResizable = stage.isResizable(); - stageSettings.isMaximized = stage.isMaximized(); - stageSettings.isShowing = stage.isShowing(); - return stageSettings; - } - - public static Stage configureStageFromSettings(StageSettings stageSettings) { - Stage stage = new Stage(); - stage.setTitle(stageSettings.Title); - stage.setX(stageSettings.x); - stage.setY(stageSettings.y); - stage.setWidth(stageSettings.width); - stage.setHeight(stageSettings.height); - stage.setMinWidth(stageSettings.minWidth); - stage.setMinHeight(stageSettings.minHeight); - stage.setMaxWidth(stageSettings.maxWidth); - stage.setMaxHeight(stageSettings.maxHeight); - stage.setIconified(stageSettings.isIconified); - stage.setAlwaysOnTop(stageSettings.isAlwaysOnTop); - stage.setFullScreen(stageSettings.isFullScreen); - stage.setResizable(stageSettings.isResizable); - stage.setMaximized(stageSettings.isMaximized); - return stage; - } -} diff --git a/src/main/java/nl/isygameclient/settings/Settings.java b/src/main/java/nl/isygameclient/settings/Settings.java @@ -0,0 +1,20 @@ +package nl.isygameclient.settings; + +import nl.isygameclient.Window; + +import java.util.HashMap; +import java.util.Map; + + +/** + * This Class holds default settings for the application. + * It also provides the format of the settings that are saved to a file. + * + * @author A F Koens + */ +public class Settings { + public Map<Window, StageSettings> stages = new HashMap<>(); + + public boolean darkMode = true; + public boolean tournamentMode = false; +} diff --git a/src/main/java/nl/isygameclient/settings/StageSettings.java b/src/main/java/nl/isygameclient/settings/StageSettings.java @@ -0,0 +1,61 @@ +package nl.isygameclient.settings; + +import javafx.stage.Stage; + +public class StageSettings { + public String Title = "ISYGameClient"; + public double x = 0; + public double y = 0; + public double width = 680; + public double height = 480; + public double minWidth = 0; + public double minHeight = 0; + public double maxWidth = 1.7976931348623157E308; + public double maxHeight = 1.7976931348623157E308; + public boolean isIconified = false; + public boolean isAlwaysOnTop = false; + public boolean isFullScreen = true; + public boolean isResizable = true; + public boolean isMaximized = true; + public boolean isShowing = false; + + + public static StageSettings createSettingsFromStage(Stage stage) { + var stageSettings = new StageSettings(); + stageSettings.Title = stage.getTitle(); + stageSettings.x = stage.getX(); + stageSettings.y = stage.getY(); + stageSettings.width = stage.getWidth(); + stageSettings.height = stage.getHeight(); + stageSettings.minWidth = stage.getMinWidth(); + stageSettings.minHeight = stage.getMinHeight(); + stageSettings.maxWidth = stage.getMaxWidth(); + stageSettings.maxHeight = stage.getMaxHeight(); + stageSettings.isIconified = stage.isIconified(); + stageSettings.isAlwaysOnTop = stage.isAlwaysOnTop(); + stageSettings.isFullScreen = stage.isFullScreen(); + stageSettings.isResizable = stage.isResizable(); + stageSettings.isMaximized = stage.isMaximized(); + stageSettings.isShowing = stage.isShowing(); + return stageSettings; + } + + public static Stage configureStageFromSettings(StageSettings stageSettings) { + Stage stage = new Stage(); + stage.setTitle(stageSettings.Title); + stage.setX(stageSettings.x); + stage.setY(stageSettings.y); + stage.setWidth(stageSettings.width); + stage.setHeight(stageSettings.height); + stage.setMinWidth(stageSettings.minWidth); + stage.setMinHeight(stageSettings.minHeight); + stage.setMaxWidth(stageSettings.maxWidth); + stage.setMaxHeight(stageSettings.maxHeight); + stage.setIconified(stageSettings.isIconified); + stage.setAlwaysOnTop(stageSettings.isAlwaysOnTop); + stage.setFullScreen(stageSettings.isFullScreen); + stage.setResizable(stageSettings.isResizable); + stage.setMaximized(stageSettings.isMaximized); + return stage; + } +} diff --git a/src/main/java/nl/isygameclient/util/SettingsFileHandler.java b/src/main/java/nl/isygameclient/util/SettingsFileHandler.java @@ -2,7 +2,7 @@ package nl.isygameclient.util; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import nl.isygameclient.models.settings.Settings; +import nl.isygameclient.settings.Settings; import java.io.FileWriter; import java.io.IOException; diff --git a/src/main/java/nl/isygameclient/util/StageHandler.java b/src/main/java/nl/isygameclient/util/StageHandler.java @@ -3,15 +3,16 @@ package nl.isygameclient.util; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.stage.Stage; -import nl.isygameclient.models.settings.Settings; -import nl.isygameclient.models.settings.StageSettings; +import nl.isygameclient.Window; +import nl.isygameclient.settings.Settings; +import nl.isygameclient.settings.StageSettings; import java.io.IOException; import java.util.HashMap; import java.util.Map; -import static nl.isygameclient.models.settings.StageSettings.configureStageFromSettings; -import static nl.isygameclient.models.settings.StageSettings.createSettingsFromStage; +import static nl.isygameclient.settings.StageSettings.configureStageFromSettings; +import static nl.isygameclient.settings.StageSettings.createSettingsFromStage; /** * This class is a singleton that stores and manages all the active stages in the application. @@ -19,7 +20,7 @@ import static nl.isygameclient.models.settings.StageSettings.createSettingsFromS */ public class StageHandler { private static StageHandler instance; - private final Map<String, Stage> stages = new HashMap<>(); + private final Map<Window, Stage> stages = new HashMap<>(); private StageHandler() { } @@ -40,7 +41,7 @@ public class StageHandler { * @param stageName the key for map of stages. * @return a stage object. */ - public Stage getStage(String stageName) { + public Stage getStage(Window stageName) { Stage stage = stages.get(stageName); if (stage == null) stage = new Stage(); stages.put(stageName, stage); @@ -51,7 +52,7 @@ public class StageHandler { * This function is for iconifying also known as minifying a stage window. * @param stageName the key for map of stages. */ - public void iconifyStage(String stageName) { + public void iconifyStage(Window stageName) { stages.get(stageName).setIconified(true); } @@ -59,7 +60,7 @@ public class StageHandler { * This function is for bringing a stage into view and focussing on it. * @param stageName the key for map of stages. */ - public void focusStage(String stageName) { + public void focusStage(Window stageName) { Stage stage = stages.get(stageName); stage.setIconified(false); stage.show(); @@ -71,14 +72,22 @@ public class StageHandler { * @param stageName the key for map of stages. * @param viewSource the source of the nieuw view for the scene. */ - public void changeSceneOfStage(String stageName, String viewSource) { + public void changeSceneOfStage(Window stageName, String viewSource) { Stage stage = getStage(stageName); try { - FXMLLoader fxmlSceneLoader = new FXMLLoader(getClass().getResource("/nl/isygameclient/" + viewSource)); + FXMLLoader fxmlSceneLoader = new FXMLLoader(getClass().getResource(viewSource)); Scene scene = new Scene(fxmlSceneLoader.load()); stage.setScene(scene); } catch (IOException e) { e.printStackTrace(); + throw new RuntimeException(e); + } + } + + public void closeStages() { + for (Stage stage : + stages.values()) { + stage.hide(); } } @@ -87,7 +96,7 @@ public class StageHandler { */ public void loadStages() { Settings settings = SettingsFileHandler.load(); - for (Map.Entry<String, StageSettings> entry : settings.stages.entrySet()) { + for (Map.Entry<Window, StageSettings> entry : settings.stages.entrySet()) { stages.put(entry.getKey(), configureStageFromSettings(entry.getValue())); } } @@ -97,11 +106,9 @@ public class StageHandler { */ public void saveStages() { Settings settings = SettingsFileHandler.load(); - for (Map.Entry<String, Stage> entry : stages.entrySet()) { + for (Map.Entry<Window, Stage> entry : stages.entrySet()) { settings.stages.put(entry.getKey(), createSettingsFromStage(entry.getValue())); } SettingsFileHandler.save(settings); } - - } diff --git a/src/main/java/nl/isygameclient/views/GameCardControl.java b/src/main/java/nl/isygameclient/views/GameCardControl.java @@ -0,0 +1,76 @@ +package nl.isygameclient.views; + +import com.jfoenix.controls.JFXButton; +import javafx.beans.NamedArg; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.VBox; +import nl.isygameclient.Window; +import nl.isygameclient.util.StageHandler; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ResourceBundle; + +public class GameCardControl extends VBox implements Initializable { + + private final String gameTitle; + private final String gameImageUrl; + private final String gameSource; + + @FXML + private Label label; + + @FXML + private JFXButton button; + + @FXML + private ImageView imageView; + + + public GameCardControl(@NamedArg("gameTitle") String gameTitle, @NamedArg("gameImageUrl") String gameImageUrl, @NamedArg("gameSource") String gameSource) { + this.gameTitle = gameTitle; + this.gameImageUrl = gameImageUrl; + this.gameSource = gameSource; + + URL url = getClass().getResource("/nl/isygameclient/views/game-card.fxml"); + FXMLLoader fxmlLoader = new FXMLLoader(url); + fxmlLoader.setRoot(this); + fxmlLoader.setController(this); + + try { + fxmlLoader.load(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + this.label.textProperty().set(gameTitle); + + InputStream imageURL = getClass().getResourceAsStream(gameImageUrl); + if (imageURL != null) { + Image image = new Image(imageURL, 250, 200, false, false); + this.imageView.setImage(image); + } + + button.setOnAction(this::onStartGameButtonClick); + } + + public void onStartGameButtonClick(ActionEvent e) { + var stageHandler = StageHandler.get(); + stageHandler.changeSceneOfStage(Window.GAME, gameSource); + stageHandler.focusStage(Window.GAME); + } + + public String getGameTitle() { + return gameTitle; + } +} diff --git a/src/main/java/nl/isygameclient/views/NavButtonControl.java b/src/main/java/nl/isygameclient/views/NavButtonControl.java @@ -0,0 +1,55 @@ +package nl.isygameclient.views; + +import com.jfoenix.controls.JFXButton; +import de.jensd.fx.glyphs.materialicons.MaterialIconView; +import javafx.beans.NamedArg; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; + +import java.io.IOException; +import java.net.URL; +import java.util.ResourceBundle; + +public class NavButtonControl extends JFXButton implements Initializable { + + private final String glyphName; + private final String source; + + @FXML + private MaterialIconView iconView; + + public NavButtonControl(@NamedArg("text") String text, @NamedArg("glyphName") String glyphName, @NamedArg("source") String source) { + super(text); + this.glyphName = glyphName; + this.source = source; + + URL url = getClass().getResource("/nl/isygameclient/views/nav-button.fxml"); + FXMLLoader fxmlLoader = new FXMLLoader(url); + fxmlLoader.setRoot(this); + fxmlLoader.setController(this); + + try { + fxmlLoader.load(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + iconView.setGlyphName(this.glyphName); + } + + public void activate() { + this.getStyleClass().add("active"); + } + + public void deactivate() { + this.getStyleClass().remove("active"); + } + + public String getSource() { + return source; + } +} diff --git a/src/main/resources/nl/isygameclient/css/modules/colors.module.css b/src/main/resources/nl/isygameclient/css/modules/colors.module.css @@ -1,318 +1,74 @@ -/* -- Primary -- */ -/* Inverse Primary */ -.inverse-primary { - -fx-background-color: -md-sys-color-inverse-primary; -} -.inverse-primary-text { - -fx-text-fill: -md-sys-color-inverse-primary; -} -.inverse-primary-fill { - -fx-fill: -md-sys-color-inverse-primary; +.background { + -fx-background-color: -background; } -/* On Primary Container */ -.on-primary-container { - -fx-background-color: -md-sys-color-on-primary-container; -} -.on-primary-container-text { - -fx-text-fill: -md-sys-color-on-primary-container; -} -.on-primary-container-fill { - -fx-fill: -md-sys-color-on-primary-container; +/* Surface */ +.surface { + -fx-background-color: -surface; } -/* On Primary */ -.on-primary { - -fx-background-color: -md-sys-color-on-primary; -} -.on-primary-text { - -fx-text-fill: -md-sys-color-on-primary; -} -.on-primary-fill { - -fx-fill: -md-sys-color-on-primary; +.surface-text { + -fx-fill: -surface-text; + -fx-text-fill: -surface-text; } -/* Primary Container */ -.primary-container { - -fx-background-color: -md-sys-color-primary-container; -} -.primary-container-text { - -fx-text-fill: -md-sys-color-primary-container; +/* On Surface */ +.on-surface { + -fx-fill: -on-surface; + -fx-background-color: -on-surface; } -.primary-container-fill { - -fx-fill: -md-sys-color-primary-container; + +.on-surface-text { + -fx-fill: -on-surface-text; + -fx-text-fill: -on-surface-text; } /* Primary */ .primary { - -fx-background-color: -md-sys-color-primary; -} -.primary-text { - -fx-text-fill: -md-sys-color-primary; -} -.primary-fill { - -fx-fill: -md-sys-color-primary; + -fx-background-color: -primary; } -/* -- Secondary -- */ -/* On Secondary Container */ -.on-secondary-container { - -fx-background-color: -md-sys-color-on-secondary-container; -} -.on-secondary-container-text { - -fx-text-fill: -md-sys-color-on-secondary-container; -} -.on-secondary-container-fill { - -fx-fill: -md-sys-color-on-secondary-container; -} - -/* On Secondary */ -.on-secondary { - -fx-background-color: -md-sys-color-on-secondary; -} -.on-secondary-text { - -fx-text-fill: -md-sys-color-on-secondary; -} -.on-secondary-fill { - -fx-fill: -md-sys-color-on-secondary; -} - -/* Secondary Container */ -.secondary-container { - -fx-background-color: -md-sys-color-secondary-container; -} -.secondary-container-text { - -fx-text-fill: -md-sys-color-secondary-container; -} -.secondary-container-fill { - -fx-fill: -md-sys-color-secondary-container; +.primary-text { + -fx-fill: -primary-text; + -fx-text-fill: -primary-text; } /* Secondary */ .secondary { - -fx-background-color: -md-sys-color-secondary; -} -.secondary-text { - -fx-text-fill: -md-sys-color-secondary; -} -.secondary-fill { - -fx-fill: -md-sys-color-secondary; -} - -/* -- Tertiary -- */ -/* On Tertiary Container */ -.on-tertiary-container { - -fx-background-color: -md-sys-color-on-tertiary-container; -} -.on-tertiary-container-text { - -fx-text-fill: -md-sys-color-on-tertiary-container; -} -.on-tertiary-container-fill { - -fx-fill: -md-sys-color-on-tertiary-container; + -fx-background-color: -secondary; } -/* On Tertiary */ -.on-tertiary { - -fx-background-color: -md-sys-color-on-tertiary; -} -.on-tertiary-text { - -fx-text-fill: -md-sys-color-on-tertiary; -} -.on-tertiary-fill { - -fx-fill: -md-sys-color-on-tertiary; -} - -/* Tertiary Container */ -.tertiary-container { - -fx-background-color: -md-sys-color-tertiary-container; -} -.tertiary-container-text { - -fx-text-fill: -md-sys-color-tertiary-container; -} -.tertiary-container-text { - -fx-fill: -md-sys-color-tertiary-container; +.secondary-text { + -fx-fill: -secondary-text; + -fx-text-fill: -secondary-text; } /* Tertiary */ .tertiary { - -fx-background-color: -md-sys-color-tertiary; -} -.tertiary-text { - -fx-text-fill: -md-sys-color-tertiary; -} -.tertiary-fill { - -fx-text-fill: -md-sys-color-tertiary; -} - -/* -- Error -- */ -/* On Error Container */ -.on-error-container { - -fx-background-color: -md-sys-color-on-error-container; -} -.on-error-container-text { - -fx-text-fill: -md-sys-color-on-error-container; -} -.on-error-container-fill { - -fx-fill: -md-sys-color-on-error-container; -} - -/* On Error */ -.on-error { - -fx-background-color: -md-sys-color-on-error; -} -.on-error-text { - -fx-text-fill: -md-sys-color-on-error; -} -.on-error-fill { - -fx-fill: -md-sys-color-on-error; + -fx-background-color: -tertiary; } -/* Error Container */ -.error-container { - -fx-background-color: -md-sys-color-error-container; -} -.error-container-text { - -fx-text-fill: -md-sys-color-error-container; -} -.error-container-fill { - -fx-fill: -md-sys-color-error-container; -} - -/* Error */ -.error { - -fx-background-color: -md-sys-color-error; -} -.error-text { - -fx-text-fill: -md-sys-color-error; -} -.error-fill { - -fx-fill: -md-sys-color-error; -} - -/* -- Surface -- */ -/* Inverse On Surface */ -.inverse-on-surface { - -fx-background-color: -md-sys-color-inverse-on-surface; -} -.inverse-on-surface-text { - -fx-text-fill: -md-sys-color-inverse-on-surface; -} -.inverse-on-surface-fill { - -fx-fill: -md-sys-color-inverse-on-surface; -} - -/* Inverse surface */ -.inverse-surface { - -fx-background-color: -md-sys-color-inverse-surface; -} -.inverse-surface-text { - -fx-text-fill: -md-sys-color-inverse-surface; -} -.inverse-surface-fill { - -fx-fill: -md-sys-color-inverse-surface; -} - -/* Inverse On Surface Variant */ -.on-surface-variant { - -fx-background-color: -md-sys-color-on-surface-variant; -} -.on-surface-variant-text { - -fx-text-fill: -md-sys-color-on-surface-variant; -} -.on-surface-variant-fill { - -fx-fill: -md-sys-color-on-surface-variant; -} - -/* On Surface */ -.on-surface { - -fx-background-color: -md-sys-color-on-surface; -} -.on-surface-text { - -fx-text-fill: -md-sys-color-on-surface; -} -.on-surface-fill { - -fx-fill: -md-sys-color-on-surface; -} - -/* Surface Variant */ -.surface-variant { - -fx-background-color: -md-sys-color-surface-variant; -} -.surface-variant-text { - -fx-text-fill: -md-sys-color-surface-variant; -} -.surface-variant-fill { - -fx-fill: -md-sys-color-surface-variant; -} - -/* Surface */ -.surface { - -fx-background-color: -md-sys-color-surface; -} -.surface-text { - -fx-text-fill: -md-sys-color-surface; -} -.surface-fill { - -fx-fill: -md-sys-color-surface; -} - -/* Surface Tint */ -.surface-tint { - -fx-background-color: -md-sys-color-surface-tint; -} -.surface-tint-text { - -fx-text-fill: -md-sys-color-surface-tint; -} -.surface-tint-fill { - -fx-fill: -md-sys-color-surface-tint; +.tertiary-text { + -fx-fill: -tertiary-text; + -fx-text-fill: -tertiary-text; } -/* Surface Tint Color */ -.surface-tint-color { - -fx-background-color: -md-sys-color-surface-tint-color; -} -.surface-tint-color-text { - -fx-text-fill: -md-sys-color-surface-tint-color; -} -.surface-tint-color-fill { - -fx-fill: -md-sys-color-surface-tint-color; +/* Negative */ +.negative { + -fx-background-color: -negative; } -/* -- Background -- */ -.on-background { - -fx-background-color: -md-sys-color-on-background; -} -.on-background-text { - -fx-text-fill: -md-sys-color-on-background; -} -.background { - -fx-background-color: -md-sys-color-background; -} -.background-text { - -fx-text-fill: -md-sys-color-background; -} -.background-fill { - -fx-text-fill: -md-sys-color-background; +.negative-text { + -fx-fill: -negative-text; + -fx-text-fill: -negative-text; } -/* -- Outline -- */ -.outline { - -fx-background-color: -md-sys-color-outline; -} -.outline-text { - -fx-text-fill: -md-sys-color-outline; -} -.outline-fill { - -fx--fill: -md-sys-color-outline; +/* Positive */ +.positive { + -fx-background-color: -positive; } -/* -- Shadow -- */ -.shadow { - -fx-background-color: -md-sys-color-shadow; -} -.shadow-text { - -fx-text-fill: -md-sys-color-shadow; -} -.shadow-fill { - -fx-fill: -md-sys-color-shadow; -} +.positive-text { + -fx-fill: -positive-text; + -fx-text-fill: -positive-text; +} +\ No newline at end of file diff --git a/src/main/resources/nl/isygameclient/css/modules/typography.module.css b/src/main/resources/nl/isygameclient/css/modules/typography.module.css @@ -1,109 +1,114 @@ +@font-face { + font-family: 'Roboto'; + src: url('../../fonts/Roboto-Medium.ttf'); +} + /* Lable */ .lable-small { - -fx-font-family: sans-serif; - -fx-font-size: 11; + -fx-font-family: "Roboto"; + -fx-font-size: .9em; -fx-font-style: normal; -fx-font-weight: 500; } .lable-medium { - -fx-font-family: sans-serif; - -fx-font-size: 13; + -fx-font-family: "Roboto"; + -fx-font-size: 1.1em; -fx-font-style: normal; -fx-font-weight: 500; } .lable-large { - -fx-font-family: sans-serif; - -fx-font-size: 14; + -fx-font-family: "Roboto"; + -fx-font-size: 1.2em; -fx-font-style: normal; -fx-font-weight: 500; } /* Body */ .body-small { - -fx-font-family: sans-serif; - -fx-font-size: 12; + -fx-font-family: "Roboto"; + -fx-font-size: 1em; -fx-font-style: normal; -fx-font-weight: 400; } .body-medium { - -fx-font-family: sans-serif; - -fx-font-size: 14; + -fx-font-family: "Roboto"; + -fx-font-size: 1.2em; -fx-font-style: normal; -fx-font-weight: 400; } .body-large { - -fx-font-family: sans-serif; - -fx-font-size: 16; + -fx-font-family: "Roboto"; + -fx-font-size: 1.4em; -fx-font-style: normal; -fx-font-weight: 400; } /* Headline */ .headline-small { - -fx-font-family: sans-serif; - -fx-font-size: 24; + -fx-font-family: "Roboto"; + -fx-font-size: 2em; -fx-font-style: normal; -fx-font-weight: 400; } .headline-medium { - -fx-font-family: sans-serif; - -fx-font-size: 28; + -fx-font-family: "Roboto"; + -fx-font-size: 2.2em; -fx-font-style: normal; -fx-font-weight: 400; } .headline-large { - -fx-font-family: sans-serif; - -fx-font-size: 32; + -fx-font-family: "Roboto"; + -fx-font-size: 2.8em; -fx-font-style: normal; -fx-font-weight: 400; } /* Display */ .display-small { - -fx-font-family: sans-serif; - -fx-font-size: 36; + -fx-font-family: "Roboto"; + -fx-font-size: 3em; -fx-font-style: normal; -fx-font-weight: 400; } .display-medium { - -fx-font-family: sans-serif; - -fx-font-size: 45; + -fx-font-family: "Roboto"; + -fx-font-size: 3.8em; -fx-font-style: normal; -fx-font-weight: 400; } .display-large { - -fx-font-family: sans-serif; - -fx-font-size: 58; + -fx-font-family: "Roboto"; + -fx-font-size: 4.4em; -fx-font-style: normal; -fx-font-weight: 400; } /* Title */ .title-small { - -fx-font-family: sans-serif; - -fx-font-size: 14; + -fx-font-family: "Roboto"; + -fx-font-size: 1.2em; -fx-font-style: normal; -fx-font-weight: 500; } .title-medium { - -fx-font-family: sans-serif; - -fx-font-size: 16; + -fx-font-family: "Roboto"; + -fx-font-size: 1.4em; -fx-font-style: normal; -fx-font-weight: 500; } .title-large { - -fx-font-family: sans-serif; - -fx-font-size: 22; + -fx-font-family: "Roboto"; + -fx-font-size: 1.8em; -fx-font-style: normal; -fx-font-weight: 400; } \ No newline at end of file diff --git a/src/main/resources/nl/isygameclient/css/style.css b/src/main/resources/nl/isygameclient/css/style.css @@ -1,3 +1,113 @@ +@import url(./modules/typography.module.css); +@import url(./modules/colors.module.css); +@import url(./tokens.css); + .transparent { -fx-background-color: transparent; + -fx-control-inner-background: transparent; + -fx-text-fill: transparent; + -fx-fill: transparent; +} + +.scroll-pane > .viewport { + -fx-background-color: transparent; +} + +.rounded { + -fx-border-radius: 10px; + -fx-background-radius: 10px; +} + +.nav-button { + -fx-fill: -primary-text; + + -fx-border-color: -primary; + -fx-border-width: 0 0 0 0.4em; + + -fx-text-fill: -primary; +} + +.nav-button .icon { + -fx-fill: -primary; + -glyph-size: 24; +} + +.nav-button.active { + -fx-background-color: -primary; + -fx-fill: -primary-text; + + -fx-border-color: -primary-text; + -fx-border-width: 0 0 0 0.4em; + + -fx-text-fill: -primary-text; +} + +.nav-button.active .icon { + -fx-fill: -primary-text; + -glyph-size: 24; +} + +.search-bar { + -fx-background-color: -surface; + -fx-background-radius: 10px; +} + +.search-bar .icon { + -fx-fill: -surface-text; +} + +.search-textfield { + -fx-text-fill: -primary; + + -fx-highlight-fill: -primary; + + -jfx-focus-color: -primary; + -jfx-unfocus-color: -surface; +} + +.search-loop, +.search-close, +.search-options { + -fx-background-color: -surface; + -fx-background-radius: 10px; +} + +.search-loop .icon, +.search-close .icon, +.search-options .icon { + -fx-fill: -primary; + -glyph-size: 24; +} + +.user-account { + -fx-text-fill: -on-surface-text; +} + +.user-account .icon { + -fx-fill: -primary; +} + +.settings {} + +.play-arrow { + +} + +.play-arrow .icon { + -fx-fill: -positive; +} + +.othello-button { + -fx-background-color: #388E3C; +} + +.ttt-grid { + -fx-border-color: -on-surface; + -fx-border-width: 5; + -fx-border-radius: 2; + } + +.ttt-button { + -fx-background-color: -on-surface; + -fx-text-fill: -on-surface-text; } diff --git a/src/main/resources/nl/isygameclient/css/temp.css b/src/main/resources/nl/isygameclient/css/temp.css @@ -0,0 +1,387 @@ +.root { + -fx-font-family: Roboto; + src: "/resources/roboto/Roboto-Regular.ttf" +} + +.jfx-hamburger { + -fx-spacing: 5; + -fx-cursor: hand +} + +.jfx-hamburger StackPane { + -fx-pref-width: 40px; + -fx-pref-height: 7px; + -fx-background-color: #3CC; + -fx-background-radius: 5px +} + +.text-field { + -fx-max-width: 800 +} + +.jfx-text-field, +.jfx-password-field { + -fx-background-color: #fff; + -fx-font-weight: BOLD; + -fx-prompt-text-fill: gray; + -fx-alignment: top-left; + -fx-focus-color: #3CC; + -fx-unfocus-color: #4d4d4d +} + +.jfx-decorator { + -fx-decorator-color: RED +} + +.jfx-decorator .jfx-decorator-buttons-container { + -fx-background-color: -fx-decorator-color +} + +.jfx-decorator .resize-border { + -fx-border-color: -fx-decorator-color; + -fx-border-width: 0 4 4 4 +} + +.jfx-text-area, +.text-area { + -fx-font-weight: BOLD +} + +.jfx-text-field:error, +.jfx-password-field:error, +.jfx-text-area:error { + -fx-focus-color: #D34336; + -fx-unfocus-color: #D34336 +} + +.jfx-text-field .errorLabel, +.jfx-password-field .errorLabel, +.jfx-text-area .errorLabel { + -fx-text-fill: #C0F; + -fx-font-size: .75em +} + +.jfx-text-field .errorIcon, +.jfx-password-field .errorIcon, +.jfx-text-area .errorIcon { + -fx-text-fill: #C0F; + -fx-font-size: 1em +} + +.progress-bar>.bar { + -fx-min-width: 500 +} + +.jfx-progress-bar>.bar { + -fx-min-width: 500 +} + +.jfx-progress-bar { + -fx-track-color: #C8C8C8; + -fx-progress-color: #0F9D58; + -fx-stroke-width: 3 +} + +.icon { + -fx-text-fill: #FE774D; + -fx-padding: 10; + -fx-cursor: hand +} + +.icons-rippler { + -fx-rippler-fill: BLUE; + -fx-mask-type: CIRCLE +} + +.icons-rippler:hover { + -fx-cursor: hand +} + +.icons-badge { + -fx-badge-fill: BLUE; + -fx-badge-scale: 3; + -fx-mask-type: CIRCLE +} + +.jfx-check-box { + -fx-font-weight: BOLD +} + +.custom-jfx-check-box { + -fx-checked-color: RED; + -fx-unchecked-color: #3CC +} + +.button { + -fx-padding: .7em .57em; + -fx-font-size: 14px +} + +.button-raised { + -fx-padding: .7em .57em; + -fx-font-size: 14px; + -fx-button-type: RAISED; + -fx-background-color: #C0F; + -fx-pref-width: 200; + -fx-text-fill: #fff +} + +.mylistview .scroll-bar:horizontal .track, +.mylistview .scroll-bar:vertical .track { + -fx-background-color: transparent; + -fx-border-color: transparent; + -fx-background-radius: 0; + -fx-border-radius: 2em +} + +.mylistview .scroll-bar:horizontal .increment-button, +.mylistview .scroll-bar:horizontal .decrement-button { + -fx-background-color: transparent; + -fx-background-radius: 0; + -fx-padding: 0 0 10 0 +} + +.mylistview .scroll-bar:vertical .increment-button, +.mylistview .scroll-bar:vertical .decrement-button { + -fx-background-color: transparent; + -fx-background-radius: 0; + -fx-padding: 0 10 0 0 +} + +.mylistview .scroll-bar .increment-arrow, +.mylistview .scroll-bar .decrement-arrow { + -fx-shape: " "; + -fx-padding: 0 +} + +.mylistview .scroll-bar:horizontal .thumb, +.mylistview .scroll-bar:vertical .thumb { + -fx-background-color: derive(black, 90%); + -fx-background-insets: 2, 0, 0; + -fx-background-radius: 2em +} + +.jfx-list-cell-container { + -fx-alignment: center-left +} + +.jfx-list-cell-container>.label { + -fx-text-fill: #000 +} + +.jfx-list-cell:odd:selected .jfx-list-cell-container, +.jfx-list-cell:even:selected .jfx-list-cell-container { + -fx-background-color: #3CC +} + +.jfx-list-cell { + -fx-background-insets: 0; + -fx-text-fill: #000 +} + +.jfx-list-cell:odd, +.jfx-list-cell:even { + -fx-background-color: #fff +} + +.jfx-list-cell:filled:hover { + -fx-text-fill: #000 +} + +.jfx-list-cell .jfx-rippler { + -fx-rippler-fill: BLUE +} + +.jfx-list-view { + -fx-background-insets: 0; + -fx-cell-horizontal-margin: 0; + -fx-cell-vertical-margin: 5; + -fx-vertical-gap: 10; + -fx-expanded: false; + -fx-pref-width: 200 +} + +.jfx-toggle-button { + -fx-toggle-color: RED +} + +.jfx-tool-bar { + -fx-font-size: 20; + -fx-font-weight: BOLD; + -fx-background-color: #5264AE; + -fx-pref-width: 100%; + -fx-pref-height: 64px +} + +.jfx-tool-bar HBox { + -fx-alignment: center; + -fx-spacing: 25; + -fx-padding: 0 10 +} + +.jfx-tool-bar Label { + -fx-text-fill: #fff +} + +.jfx-popup-container { + -fx-background-color: #fff +} + +.jfx-snackbar-content { + -fx-background-color: #323232; + -fx-padding: 5; + -fx-spacing: 5 +} + +.jfx-snackbar-toast { + -fx-text-fill: #fff +} + +.jfx-snackbar-action { + -fx-text-fill: #ff4081 +} + +.jfx-list-cell-content-container { + -fx-alignment: center-left +} + +.jfx-list-cell-container .label { + -fx-text-fill: #000 +} + +.combo-box-popup .list-view .jfx-list-cell:odd:selected .jfx-list-cell-container, +.combo-box-popup .list-view .jfx-list-cell:even:selected .jfx-list-cell-container { + -fx-background-color: rgba(0.0, 0.0, 255.0, 0.2) +} + +.combo-box-popup .list-view .jfx-list-cell { + -fx-background-insets: 0; + -fx-text-fill: #000 +} + +.combo-box-popup .list-view .jfx-list-cell:odd, +.combo-box-popup .list-view .jfx-list-cell:even { + -fx-background-color: #fff +} + +.combo-box-popup .list-view .jfx-list-cell:filled:hover { + -fx-text-fill: #000 +} + +.combo-box-popup .list-view .jfx-list-cell .jfx-rippler { + -fx-rippler-fill: #5264AE +} + +.tree-table-view { + -fx-tree-table-color: rgba(255, 0, 0, 0.2); + -fx-tree-table-rippler-color: #3CC +} + +.tree-table-view:focused .tree-table-row-cell:selected { + -fx-background-color: -fx-tree-table-color; + -fx-table-cell-border-color: -fx-tree-table-color; + -fx-text-fill: #000 +} + +.tree-table-view:focused .tree-table-row-cell:selected .tree-table-cell { + -fx-text-fill: #000 +} + +.tree-table-view .jfx-rippler { + -fx-rippler-fill: -fx-tree-table-rippler-color +} + +.tree-table-view .column-header, +.tree-table-view .column-header-background, +.tree-table-view .column-header-background .filler { + -fx-background-color: TRANSPARENT +} + +.tree-table-view .column-header { + -fx-border-width: 0 1 0 1; + -fx-border-color: #F3F3F3 +} + +.tree-table-view .column-header .label { + -fx-text-fill: #3CC; + -fx-padding: 16 0 16 0 +} + +.tree-table-view .column-header .arrow, +.tree-table-view .column-header .sort-order-dot { + -fx-background-color: #3CC +} + +.tree-table-view .column-header:last-visible { + -fx-border-width: 0 2 0 1 +} + +.tree-table-view .column-header-background { + -fx-border-width: 0 0 1 0; + -fx-border-color: #F3F3F3 +} + +.tree-table-view .tree-table-cell { + -fx-border-width: 0 0 0 0; + -fx-padding: 16 0 16 0 +} + +.tree-table-view .column-overlay { + -fx-background-color: -fx-tree-table-color +} + +.tree-table-view .column-resize-line, +.tree-table-view .column-drag-header { + -fx-background-color: -fx-tree-table-rippler-color +} + +.tree-table-view:focused { + -fx-background-color: -fx-tree-table-color, -fx-box-border, -fx-control-inner-background; + -fx-background-insets: -1.4, 0, 1; + -fx-background-radius: 1.4, 0, 0; + -fx-padding: 1 +} + +.tree-table-row-cell>.tree-disclosure-node>.arrow { + -fx-background-color: -fx-text-fill; + -fx-padding: .333333em .229em .333333em .229em; + -fx-shape: "M 0 -3.5 L 4 0 L 0 3.5 z" +} + +.tree-table-row-cell .jfx-text-field { + -fx-focus-color: rgba(240, 40, 40) +} + +.tree-table-row-group { + -fx-background-color: rgba(230, 230, 230) +} + +.animated-option-button { + -fx-pref-width: 40px; + -fx-background-color: #44B449; + -fx-background-radius: 30px; + -fx-pref-height: 30px; + -fx-text-fill: #fff; + -fx-border-radius: 30px +} + +.animated-option-sub-button { + -fx-background-color: #43609C +} + +.animated-option-sub-button2 { + -fx-background-color: #cb6860 +} + +.tree-table-view .menu-item:focused { + -fx-background-color: -fx-tree-table-color +} + +.tree-table-view .menu-item .label { + -fx-padding: 5 0 5 0 +} + +.jfx-combo-box .combo-box-button-container { + -fx-border-color: #b4b4b4; + -fx-border-width: 0 0 2 0 +} +\ No newline at end of file diff --git a/src/main/resources/nl/isygameclient/css/theme.css b/src/main/resources/nl/isygameclient/css/theme.css @@ -1,8 +0,0 @@ -@import url(tokens.css); - -/* Modules */ -@import url(./modules/colors.module.css); -@import url(./modules/typography.module.css); - -@import url(./themes/theme.dark.css); -@import url(style.css); -\ No newline at end of file diff --git a/src/main/resources/nl/isygameclient/css/themes/dark.theme.css b/src/main/resources/nl/isygameclient/css/themes/dark.theme.css @@ -0,0 +1,17 @@ +* { + -background: -background-dark; + -surface: -surface-dark; + -surface-text: -surface-text-dark; + -on-surface: -on-surface-dark; + -on-surface-text: -on-surface-text-dark; + -primary: -primary-dark; + -primary-text: -primary-text-dark; + -secondary: -secondary-dark; + -secondary-text: -secondary-text-dark; + -tertiary: -tertiary-dark; + -tertiary-text: -tertiary-text-dark; + -negative: -negative-dark; + -negative-text: -negative-text-dark; + -positive: -positive-dark; + -positive-text: -positive-text-dark; +} diff --git a/src/main/resources/nl/isygameclient/css/themes/light.theme.css b/src/main/resources/nl/isygameclient/css/themes/light.theme.css @@ -0,0 +1,17 @@ +* { + -background: -background-light; + -surface: -surface-light; + -surface-text: -surface-text-light; + -on-surface: -on-surface-light; + -on-surface-text: -on-surface-text-light; + -primary: -primary-light; + -primary-text: -primary-text-light; + -secondary: -secondary-light; + -secondary-text: -secondary-text-light; + -tertiary: -tertiary-light; + -tertiary-text: -tertiary-text-light; + -negative: -negative-light; + -negative-text: -negative-text-light; + -positive: -positive-light; + -positive-text: -positive-text-light; +} diff --git a/src/main/resources/nl/isygameclient/css/themes/theme.dark.css b/src/main/resources/nl/isygameclient/css/themes/theme.dark.css @@ -1,31 +0,0 @@ -* { - -md-sys-color-surface-tint: -md-sys-color-surface-tint-dark; - -md-sys-color-surface-tint-color: -md-sys-color-surface-tint-color-dark; - -md-sys-color-on-error-container: -md-sys-color-on-error-container-dark; - -md-sys-color-on-error: -md-sys-color-on-error-dark; - -md-sys-color-error-container: -md-sys-color-error-container-dark; - -md-sys-color-on-tertiary-container: -md-sys-color-on-tertiary-container-dark; - -md-sys-color-on-tertiary: -md-sys-color-on-tertiary-dark; - -md-sys-color-tertiary-container: -md-sys-color-tertiary-container-dark; - -md-sys-color-tertiary: -md-sys-color-tertiary-dark; - -md-sys-color-shadow: -md-sys-color-shadow-dark; - -md-sys-color-error: -md-sys-color-error-dark; - -md-sys-color-outline: -md-sys-color-outline-dark; - -md-sys-color-on-background: -md-sys-color-on-background-dark; - -md-sys-color-background: -md-sys-color-background-dark; - -md-sys-color-inverse-on-surface: -md-sys-color-inverse-on-surface-dark; - -md-sys-color-inverse-surface: -md-sys-color-inverse-surface-dark; - -md-sys-color-on-surface-variant: -md-sys-color-on-surface-variant-dark; - -md-sys-color-on-surface: -md-sys-color-on-surface-dark; - -md-sys-color-surface-variant: -md-sys-color-surface-variant-dark; - -md-sys-color-surface: -md-sys-color-surface-dark; - -md-sys-color-on-secondary-container: -md-sys-color-on-secondary-container-dark; - -md-sys-color-on-secondary: -md-sys-color-on-secondary-dark; - -md-sys-color-secondary-container: -md-sys-color-secondary-container-dark; - -md-sys-color-secondary: -md-sys-color-secondary-dark; - -md-sys-color-inverse-primary: -md-sys-color-inverse-primary-dark; - -md-sys-color-on-primary-container: -md-sys-color-on-primary-container-dark; - -md-sys-color-on-primary: -md-sys-color-on-primary-dark; - -md-sys-color-primary-container: -md-sys-color-primary-container-dark; - -md-sys-color-primary: -md-sys-color-primary-dark; -} diff --git a/src/main/resources/nl/isygameclient/css/themes/theme.light.css b/src/main/resources/nl/isygameclient/css/themes/theme.light.css @@ -1,31 +0,0 @@ -* { - -md-sys-color-surface-tint: -md-sys-color-surface-tint-light; - -md-sys-color-surface-tint-color: -md-sys-color-surface-tint-color-light; - -md-sys-color-on-error-container: -md-sys-color-on-error-container-light; - -md-sys-color-on-error: -md-sys-color-on-error-light; - -md-sys-color-error-container: -md-sys-color-error-container-light; - -md-sys-color-on-tertiary-container: -md-sys-color-on-tertiary-container-light; - -md-sys-color-on-tertiary: -md-sys-color-on-tertiary-light; - -md-sys-color-tertiary-container: -md-sys-color-tertiary-container-light; - -md-sys-color-tertiary: -md-sys-color-tertiary-light; - -md-sys-color-shadow: -md-sys-color-shadow-light; - -md-sys-color-error: -md-sys-color-error-light; - -md-sys-color-outline: -md-sys-color-outline-light; - -md-sys-color-on-background: -md-sys-color-on-background-light; - -md-sys-color-background: -md-sys-color-background-light; - -md-sys-color-inverse-on-surface: -md-sys-color-inverse-on-surface-light; - -md-sys-color-inverse-surface: -md-sys-color-inverse-surface-light; - -md-sys-color-on-surface-variant: -md-sys-color-on-surface-variant-light; - -md-sys-color-on-surface: -md-sys-color-on-surface-light; - -md-sys-color-surface-variant: -md-sys-color-surface-variant-light; - -md-sys-color-surface: -md-sys-color-surface-light; - -md-sys-color-on-secondary-container: -md-sys-color-on-secondary-container-light; - -md-sys-color-on-secondary: -md-sys-color-on-secondary-light; - -md-sys-color-secondary-container: -md-sys-color-secondary-container-light; - -md-sys-color-secondary: -md-sys-color-secondary-light; - -md-sys-color-inverse-primary: -md-sys-color-inverse-primary-light; - -md-sys-color-on-primary-container: -md-sys-color-on-primary-container-light; - -md-sys-color-on-primary: -md-sys-color-on-primary-light; - -md-sys-color-primary-container: -md-sys-color-primary-container-light; - -md-sys-color-primary: -md-sys-color-primary-light; -} diff --git a/src/main/resources/nl/isygameclient/css/tokens.css b/src/main/resources/nl/isygameclient/css/tokens.css @@ -1,223 +1,114 @@ -* { - /* Primary */ - -md-ref-palette-primary0: #000000; - -md-ref-palette-primary5: #0a1400; - -md-ref-palette-primary10: #131f00; - -md-ref-palette-primary15: #1b2a00; - -md-ref-palette-primary20: #233600; - -md-ref-palette-primary25: #2c4200; - -md-ref-palette-primary30: #354e00; - -md-ref-palette-primary35: #3e5b00; - -md-ref-palette-primary40: #49680d; - -md-ref-palette-primary50: #618127; - -md-ref-palette-primary60: #7a9c3e; - -md-ref-palette-primary70: #93b756; - -md-ref-palette-primary80: #aed36e; - -md-ref-palette-primary90: #c9f087; - -md-ref-palette-primary95: #d7fe94; - -md-ref-palette-primary98: #f1ffd3; - -md-ref-palette-primary99: #f9ffe6; - -md-ref-palette-primary100: #ffffff; - - /* Secondary */ - -md-ref-palette-secondary0: #000000; - -md-ref-palette-secondary5: #0c1303; - -md-ref-palette-secondary10: #171e0a; - -md-ref-palette-secondary15: #212813; - -md-ref-palette-secondary20: #2b331d; - -md-ref-palette-secondary25: #363e27; - -md-ref-palette-secondary30: #414a32; - -md-ref-palette-secondary35: #4d563d; - -md-ref-palette-secondary40: #596248; - -md-ref-palette-secondary50: #727a5f; - -md-ref-palette-secondary60: #8b9478; - -md-ref-palette-secondary70: #a6af91; - -md-ref-palette-secondary80: #c1caab; - -md-ref-palette-secondary90: #dde6c6; - -md-ref-palette-secondary95: #ebf5d4; - -md-ref-palette-secondary98: #f4fddc; - -md-ref-palette-secondary99: #f9ffe6; - -md-ref-palette-secondary100: #ffffff; - - /* Tertiary */ - -md-ref-palette-tertiary0: #000000; - -md-ref-palette-tertiary5: #001412; - -md-ref-palette-tertiary10: #00201d; - -md-ref-palette-tertiary15: #002b28; - -md-ref-palette-tertiary20: #013733; - -md-ref-palette-tertiary25: #11423e; - -md-ref-palette-tertiary30: #1f4e49; - -md-ref-palette-tertiary35: #2c5a55; - -md-ref-palette-tertiary40: #396661; - -md-ref-palette-tertiary50: #527f7a; - -md-ref-palette-tertiary60: #6b9993; - -md-ref-palette-tertiary70: #85b4ae; - -md-ref-palette-tertiary80: #a0d0c9; - -md-ref-palette-tertiary90: #bcece5; - -md-ref-palette-tertiary95: #cafaf3; - -md-ref-palette-tertiary98: #e4fffa; - -md-ref-palette-tertiary99: #f2fffc; - -md-ref-palette-tertiary100: #ffffff; - - /* Error */ - -md-ref-palette-error0: #000000; - -md-ref-palette-error5: #2d0001; - -md-ref-palette-error10: #410002; - -md-ref-palette-error15: #540003; - -md-ref-palette-error20: #690005; - -md-ref-palette-error25: #7e0007; - -md-ref-palette-error30: #93000a; - -md-ref-palette-error35: #a80710; - -md-ref-palette-error40: #ba1a1a; - -md-ref-palette-error50: #de3730; - -md-ref-palette-error60: #ff5449; - -md-ref-palette-error70: #ff897d; - -md-ref-palette-error80: #ffb4ab; - -md-ref-palette-error90: #ffdad6; - -md-ref-palette-error95: #ffedea; - -md-ref-palette-error98: #fff8f7; - -md-ref-palette-error99: #fffbff; - -md-ref-palette-error100: #ffffff; +* { + -neutral-100: #242429; + -neutral-200: #303036; + -neutral-300: #484851; + -neutral-400: #60606C; + -neutral-500: #A0A0AB; + -neutral-600: #BBBBC3; + -neutral-700: #C9C9CF; + -neutral-800: #E4E4E7; + -neutral-900: #FAFAFA; + + -primary-100: #291D49; + -primary-200: #3A2866; + -primary-300: #493280; + -primary-400: #573D9A; + -primary-500: #6E4FBA; + -primary-600: #866DC5; + -primary-700: #9E8AD1; + -primary-800: #B3A4DB; + -primary-900: #D2C8E9; + + -secondary-100: #1D2749; + -secondary-200: #293666; + -secondary-300: #334380; + -secondary-400: #3D5199; + -secondary-500: #5067B9; + -secondary-600: #6D80C5; + -secondary-700: #8A99D0; + -secondary-800: #A4B0DB; + -secondary-900: #C8CFE9; + + -tertiary-100: #663200; + -tertiary-200: #994C00; + -tertiary-300: #D66A00; + -tertiary-400: #FF8914; + -tertiary-500: #FF9833; + -tertiary-600: #FFA54C; + -tertiary-700: #FFB770; + -tertiary-800: #FFCB99; + -tertiary-900: #FFE3C7; + + -negative-100: #5C0A0A; + -negative-200: #8A0F0F; + -negative-300: #A11212; + -negative-400: #B81414; + -negative-500: #CF1717; + -negative-600: #E93F3F; + -negative-700: #ED5F5F; + -negative-800: #F28C8D; + -negative-900: #F7BABA; + + -positive-100: #194D1D; + -positive-200: #206024; + -positive-300: #2D8632; + -positive-400: #33993A; + -positive-500: #39AC41; + -positive-600: #53C65A; + -positive-700: #79D27F; + -positive-800: #9FDFA3; + -positive-900: #C6ECC8; + + -black: #000; + -white: #fff; + + + /* Dark Theme Variables */ + -background-dark: -neutral-100; - /* Neutral */ - -md-ref-palette-neutral0: #000000; - -md-ref-palette-neutral5: #10110d; - -md-ref-palette-neutral10: #1b1c18; - -md-ref-palette-neutral15: #252621; - -md-ref-palette-neutral20: #30312c; - -md-ref-palette-neutral25: #3b3c37; - -md-ref-palette-neutral30: #464742; - -md-ref-palette-neutral35: #52534d; - -md-ref-palette-neutral40: #5e5f59; - -md-ref-palette-neutral50: #777771; - -md-ref-palette-neutral60: #91918a; - -md-ref-palette-neutral70: #acaba5; - -md-ref-palette-neutral80: #c7c7bf; - -md-ref-palette-neutral90: #e4e3db; - -md-ref-palette-neutral95: #f2f1e9; - -md-ref-palette-neutral98: #fbf9f2; - -md-ref-palette-neutral99: #fefcf4; - -md-ref-palette-neutral100: #ffffff; - - /* Neutral Variant */ - -md-ref-palette-neutral-variant0: #000000; - -md-ref-palette-neutral-variant5: #0f1209; - -md-ref-palette-neutral-variant10: #1a1d13; - -md-ref-palette-neutral-variant15: #24271d; - -md-ref-palette-neutral-variant20: #2e3227; - -md-ref-palette-neutral-variant25: #393d32; - -md-ref-palette-neutral-variant30: #45483d; - -md-ref-palette-neutral-variant35: #515448; - -md-ref-palette-neutral-variant40: #5d6054; - -md-ref-palette-neutral-variant50: #75786c; - -md-ref-palette-neutral-variant60: #8f9284; - -md-ref-palette-neutral-variant70: #aaad9e; - -md-ref-palette-neutral-variant80: #c5c8b9; - -md-ref-palette-neutral-variant90: #e2e4d4; - -md-ref-palette-neutral-variant95: #f0f2e2; - -md-ref-palette-neutral-variant98: #f9fbeb; - -md-ref-palette-neutral-variant99: #fcfeee; - -md-ref-palette-neutral-variant100: #ffffff; - - - /* System Colors */ - -md-sys-color-primary: #bdcca0; - -md-sys-color-on-primary: #293414; - -md-sys-color-primary-container: #3f4b29; - -md-sys-color-on-primary-container: #d9e8ba; - -md-sys-color-secondary: #c6c8ba; - -md-sys-color-on-secondary: #2f3228; - -md-sys-color-secondary-container: #45483d; - -md-sys-color-on-secondary-container: #e2e4d5; - -md-sys-color-tertiary: #b9cac7; - -md-sys-color-on-tertiary: #243331; - -md-sys-color-tertiary-container: #3a4a48; - -md-sys-color-on-tertiary-container: #d5e6e3; - -md-sys-color-error: #ffb4ab; - -md-sys-color-on-error: #690005; - -md-sys-color-error-container: #93000a; - -md-sys-color-on-error-container: #ffb4ab; - -md-sys-color-background: #1c1c1a; - -md-sys-color-on-background: #e5e2de; - -md-sys-color-surface: #1c1c1a; - -md-sys-color-on-surface: #e5e2de; - -md-sys-color-surface-variant: #464742; - -md-sys-color-on-surface-variant: #c7c7c0; - -md-sys-color-outline: #91918b; - -md-sys-color-outline-variant: #464742; - -md-sys-color-shadow: #000000; - -md-sys-color-scrim: #000000; - -md-sys-color-inverse-surface: #e5e2de; - -md-sys-color-inverse-on-surface: #31302e; - -md-sys-color-inverse-primary: #56633e; - -md-sys-color-surface-tint: #bdcca0; - -md-sys-color-surface-tint-color: #bdcca0; - - /* Light Colors */ - -md-sys-color-primary-light: #56633e; - -md-sys-color-on-primary-light: #ffffff; - -md-sys-color-primary-container-light: #d9e8ba; - -md-sys-color-on-primary-container-light: #141f03; - -md-sys-color-secondary-light: #5d6054; - -md-sys-color-on-secondary-light: #ffffff; - -md-sys-color-secondary-container-light: #e2e4d5; - -md-sys-color-on-secondary-container-light: #1a1d14; - -md-sys-color-tertiary-light: #52625f; - -md-sys-color-on-tertiary-light: #ffffff; - -md-sys-color-tertiary-container-light: #d5e6e3; - -md-sys-color-on-tertiary-container-light: #0f1e1c; - -md-sys-color-error-light: #ba1a1a; - -md-sys-color-on-error-light: #ffffff; - -md-sys-color-error-container-light: #ffdad6; - -md-sys-color-on-error-container-light: #410002; - -md-sys-color-background-light: #fffcf8; - -md-sys-color-on-background-light: #1c1c1a; - -md-sys-color-surface-light: #fffcf8; - -md-sys-color-on-surface-light: #1c1c1a; - -md-sys-color-surface-variant-light: #e4e3db; - -md-sys-color-on-surface-variant-light: #464742; - -md-sys-color-outline-light: #777772; - -md-sys-color-outline-variant-light: #c7c7c0; - -md-sys-color-shadow-light: #000000; - -md-sys-color-scrim-light: #000000; - -md-sys-color-inverse-surface-light: #31302e; - -md-sys-color-inverse-on-surface-light: #f3f0ec; - -md-sys-color-inverse-primary-light: #bdcca0; - -md-sys-color-surface-tint-light: #56633e; - -md-sys-color-surface-tint-color-light: #56633e; - - /* Dark Colors */ - -md-sys-color-primary-dark: #bdcca0; - -md-sys-color-on-primary-dark: #293414; - -md-sys-color-primary-container-dark: #3f4b29; - -md-sys-color-on-primary-container-dark: #d9e8ba; - -md-sys-color-secondary-dark: #c6c8ba; - -md-sys-color-on-secondary-dark: #2f3228; - -md-sys-color-secondary-container-dark: #45483d; - -md-sys-color-on-secondary-container-dark: #e2e4d5; - -md-sys-color-tertiary-dark: #b9cac7; - -md-sys-color-on-tertiary-dark: #243331; - -md-sys-color-tertiary-container-dark: #3a4a48; - -md-sys-color-on-tertiary-container-dark: #d5e6e3; - -md-sys-color-error-dark: #ffb4ab; - -md-sys-color-on-error-dark: #690005; - -md-sys-color-error-container-dark: #93000a; - -md-sys-color-on-error-container-dark: #ffb4ab; - -md-sys-color-background-dark: #1c1c1a; - -md-sys-color-on-background-dark: #e5e2de; - -md-sys-color-surface-dark: #1c1c1a; - -md-sys-color-on-surface-dark: #e5e2de; - -md-sys-color-surface-variant-dark: #464742; - -md-sys-color-on-surface-variant-dark: #c7c7c0; - -md-sys-color-outline-dark: #91918b; - -md-sys-color-outline-variant-dark: #464742; - -md-sys-color-shadow-dark: #000000; - -md-sys-color-scrim-dark: #000000; - -md-sys-color-inverse-surface-dark: #e5e2de; - -md-sys-color-inverse-on-surface-dark: #31302e; - -md-sys-color-inverse-primary-dark: #56633e; - -md-sys-color-surface-tint-dark: #bdcca0; - -md-sys-color-surface-tint-color-dark: #bdcca0; - - -md-ref-palette-neutralNaN: #FFFFFF; + -surface-dark: -neutral-200; + -surface-text-dark: -neutral-400; + + -on-surface-dark: -neutral-300; + -on-surface-text-dark: -neutral-700; + + -primary-dark: -primary-800; + -primary-text-dark: -primary-400; + + -secondary-dark: -secondary-800; + -secondary-text-dark: -secondary-400; + + -tertiary-dark: -tertiary-800; + -tertiary-text-dark: -tertiary-400; + + -negative-dark: -negative-800; + -negative-text-dark: -negative-400; + + -positive-dark: -positive-800; + -positive-text-dark: -positive-400; + + + /* Light Theme Variables */ + -background-light: -neutral-700; + + -surface-light: -neutral-800; + -surface-text-light: -neutral-400; + + -on-surface-light: -neutral-900; + -on-surface-text-light: -neutral-400; + + -primary-light: -primary-500; + -primary-text-light: -primary-800; + + -secondary-light: -secondary-500; + -secondary-text-light: -secondary-800; + + -tertiary-light: -tertiary-500; + -tertiary-text-light: -tertiary-800; + + -negative-light: -negative-500; + -negative-text-light: -negative-800; + + -positive-light: -positive-500; + -positive-text-light: -positive-800; } \ No newline at end of file diff --git a/src/main/resources/nl/isygameclient/css/views/game-select-menu.css b/src/main/resources/nl/isygameclient/css/views/game-select-menu.css @@ -1,61 +0,0 @@ -@import url(../theme.css) -/* Menu Bar */ -.menu-bar { - -fx-effect: dropshadow(three-pass-box, black, 10, 0, 0, 0); -} -.menu-bar-settings { - -fx-fill: -md-sys-color-inverse-surface; -} - -/* Search Bar */ -.search-bar { - -fx-border-color: -md-sys-color-on-surface; - -fx-border-width: 1; - -fx-border-radius: 2; -} - -.search-field { - -fx-text-fill: -md-sys-color-inverse-surface; -} - -/* Game List */ -#gamesList { - -fx-background-radius: 0; - -fx-vbar-policy: never; -} - -#gamesList .list-cell { - -fx-background-color: transparent; - -fx-text-fill: -md-sys-color-inverse-surface; - - /* Large Body Type Style */ - -fx-font-size: 16; - -fx-font-style: normal; - -fx-font-weight: 400; -} - -#gamesList .list-cell:filled:selected:focused, -.list-cell:filled:selected { - -fx-background-color: -md-ref-palette-tertiary50; - -fx-text-fill: white; -} - -#gamesList .list-cell:even { - -fx-background-color: -md-sys-color-surface-variant; -} - -#gamesList .list-cell:odd { - -fx-background-color: -md-sys-color-inverse-on-surface; -} - -#gamesList .list-cell:filled:hover { - -fx-background-color: -md-ref-palette-tertiary60; - -fx-text-fill: white; -} - -/* Game Detail */ - -#gameDetail { - -fx-border-color: -md-sys-color-surface; - -fx-border-width: 0 5 0 0; -} diff --git a/src/main/resources/nl/isygameclient/css/views/othello.css b/src/main/resources/nl/isygameclient/css/views/othello.css @@ -1,5 +0,0 @@ -@import url(../theme.css) - .othello-button { - -fx-background-color: #388E3C; - -fx-text-fill: -md-sys-color-on-surface-variant - } diff --git a/src/main/resources/nl/isygameclient/css/views/tictactoe.css b/src/main/resources/nl/isygameclient/css/views/tictactoe.css @@ -1,11 +0,0 @@ -@import url(../theme.css) -.ttt-grid { - -fx-border-color: -md-sys-color-surface-variant; - -fx-border-width: 5; - -fx-border-radius: 2; - } - - .ttt-button { - -fx-background-color: -md-sys-color-surface-variant; - -fx-text-fill: -md-sys-color-on-surface-variant - } diff --git a/src/main/resources/nl/isygameclient/fonts/Roboto-Medium.ttf b/src/main/resources/nl/isygameclient/fonts/Roboto-Medium.ttf Binary files differ. diff --git a/src/main/resources/nl/isygameclient/images/icons/svg/hello.css b/src/main/resources/nl/isygameclient/images/icons/svg/hello.css @@ -1,3 +0,0 @@ -.button { - -fx-background-color: #2196F3; -} -\ No newline at end of file diff --git a/src/main/resources/nl/isygameclient/images/icons/svg/icons8_close.svg b/src/main/resources/nl/isygameclient/images/icons/svg/icons8_close.svg @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?><s -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="480" height="480"> - <path d="M4.7070312 3.2929688L3.2929688 4.7070312L10.585938 12L3.2929688 19.292969L4.7070312 20.707031L12 13.414062L19.292969 20.707031L20.707031 19.292969L13.414062 12L20.707031 4.7070312L19.292969 3.2929688L12 10.585938L4.7070312 3.2929688 z" fill="#5B5B5B" /> -</svg> -\ No newline at end of file diff --git a/src/main/resources/nl/isygameclient/images/icons/svg/icons8_search_1.svg b/src/main/resources/nl/isygameclient/images/icons/svg/icons8_search_1.svg @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?><s -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="480" height="480"> - <path d="M9 2C5.1458514 2 2 5.1458514 2 9C2 12.854149 5.1458514 16 9 16C10.747998 16 12.345009 15.348024 13.574219 14.28125L14 14.707031L14 16L20 22L22 20L16 14L14.707031 14L14.28125 13.574219C15.348024 12.345009 16 10.747998 16 9C16 5.1458514 12.854149 2 9 2 z M 9 4C11.773268 4 14 6.2267316 14 9C14 11.773268 11.773268 14 9 14C6.2267316 14 4 11.773268 4 9C4 6.2267316 6.2267316 4 9 4 z" fill="#5B5B5B" /> -</svg> -\ No newline at end of file diff --git a/src/main/resources/nl/isygameclient/images/icons/svg/icons8_settings.svg b/src/main/resources/nl/isygameclient/images/icons/svg/icons8_settings.svg @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?><s -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="480" height="480"> - <path d="M11.423828 2C11.179828 2 10.969688 2.1769687 10.929688 2.4179688L10.646484 4.1230469C10.159736 4.2067166 9.689176 4.3360771 9.2363281 4.5039062L8.1347656 3.1679688C7.9797656 2.9789688 7.7100469 2.9297344 7.4980469 3.0527344L6.5019531 3.6289062C6.2899531 3.7509062 6.1972031 4.0083281 6.2832031 4.2363281L6.8886719 5.8535156C6.513238 6.1663963 6.1663963 6.513238 5.8535156 6.8886719L4.2363281 6.2832031C4.0083281 6.1972031 3.7509062 6.2899531 3.6289062 6.5019531L3.0527344 7.4980469C2.9297344 7.7100469 2.9789688 7.9797656 3.1679688 8.1347656L4.5039062 9.2363281C4.3360771 9.689176 4.2067166 10.159736 4.1230469 10.646484L2.4179688 10.929688C2.1769687 10.970688 2 11.178828 2 11.423828L2 12.576172C2 12.820172 2.1769687 13.030312 2.4179688 13.070312L4.1230469 13.353516C4.2067166 13.840264 4.3360771 14.310824 4.5039062 14.763672L3.1679688 15.865234C2.9789687 16.020234 2.9307344 16.289953 3.0527344 16.501953L3.6289062 17.498047C3.7509062 17.710047 4.0083281 17.802797 4.2363281 17.716797L5.8535156 17.111328C6.1663963 17.486762 6.513238 17.833604 6.8886719 18.146484L6.2832031 19.763672C6.1972031 19.992672 6.2909531 20.249094 6.5019531 20.371094L7.4980469 20.947266C7.7100469 21.069266 7.9797656 21.020031 8.1347656 20.832031L9.234375 19.496094C9.6877476 19.664236 10.15912 19.793178 10.646484 19.876953L10.929688 21.582031C10.970688 21.823031 11.178828 22 11.423828 22L12.576172 22C12.820172 22 13.030312 21.823031 13.070312 21.582031L13.353516 19.876953C13.840264 19.793283 14.310824 19.663923 14.763672 19.496094L15.865234 20.832031C16.020234 21.021031 16.289953 21.069266 16.501953 20.947266L17.498047 20.371094C17.710047 20.249094 17.802797 19.991672 17.716797 19.763672L17.111328 18.146484C17.486762 17.833604 17.833604 17.486762 18.146484 17.111328L19.763672 17.716797C19.992672 17.802797 20.249094 17.709047 20.371094 17.498047L20.947266 16.501953C21.069266 16.289953 21.020031 16.020234 20.832031 15.865234L19.496094 14.765625C19.664236 14.312252 19.793178 13.84088 19.876953 13.353516L21.582031 13.070312C21.823031 13.029312 22 12.821172 22 12.576172L22 11.423828C22 11.179828 21.823031 10.969688 21.582031 10.929688L19.876953 10.646484C19.793283 10.159736 19.663923 9.689176 19.496094 9.2363281L20.832031 8.1347656C21.021031 7.9797656 21.069266 7.7100469 20.947266 7.4980469L20.371094 6.5019531C20.249094 6.2899531 19.991672 6.1972031 19.763672 6.2832031L18.146484 6.8886719C17.833604 6.513238 17.486762 6.1663963 17.111328 5.8535156L17.716797 4.2363281C17.802797 4.0073281 17.709047 3.7509062 17.498047 3.6289062L16.501953 3.0527344C16.289953 2.9307344 16.020234 2.9799687 15.865234 3.1679688L14.765625 4.5039062C14.312252 4.3357635 13.84088 4.2068225 13.353516 4.1230469L13.070312 2.4179688C13.029312 2.1769687 12.821172 2 12.576172 2L11.423828 2 z M 11 6.0898438L11 9.1738281 A 3 3 0 0 0 9 12 A 3 3 0 0 0 9.0507812 12.548828L6.3789062 14.089844C6.1382306 13.438833 6 12.736987 6 12C6 9.0161425 8.1553612 6.5637988 11 6.0898438 z M 13 6.0898438C15.844639 6.5637988 18 9.0161425 18 12C18 12.737875 17.86037 13.440133 17.619141 14.091797L14.947266 12.546875 A 3 3 0 0 0 15 12 A 3 3 0 0 0 13 9.1757812L13 6.0898438 z M 13.947266 14.277344L16.628906 15.826172C15.530388 17.156023 13.868625 18 12 18C10.131375 18 8.4696124 17.156023 7.3710938 15.826172L10.050781 14.279297 A 3 3 0 0 0 12 15 A 3 3 0 0 0 13.947266 14.277344 z" fill="#5B5B5B" /> -</svg> -\ No newline at end of file diff --git a/src/main/resources/nl/isygameclient/imgs/dark-souls-3.jpg b/src/main/resources/nl/isygameclient/imgs/dark-souls-3.jpg Binary files differ. diff --git a/src/main/resources/nl/isygameclient/images/othello_logo.png b/src/main/resources/nl/isygameclient/imgs/othello_logo.png Binary files differ. diff --git a/src/main/resources/nl/isygameclient/images/tictactoe_logo.png b/src/main/resources/nl/isygameclient/imgs/tictactoe_logo.png Binary files differ. diff --git a/src/main/resources/nl/isygameclient/views/app-settings.fxml b/src/main/resources/nl/isygameclient/views/app-settings.fxml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?import javafx.scene.layout.*?> + +<AnchorPane xmlns="http://javafx.com/javafx" + xmlns:fx="http://javafx.com/fxml" + fx:controller="nl.isygameclient.controllers.AppSettingsController" + prefHeight="400.0" prefWidth="600.0"> + +</AnchorPane> diff --git a/src/main/resources/nl/isygameclient/views/app.fxml b/src/main/resources/nl/isygameclient/views/app.fxml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import com.jfoenix.controls.JFXButton?> +<?import de.jensd.fx.glyphs.materialicons.MaterialIconView?> +<?import java.lang.String?> +<?import java.net.URL?> +<?import javafx.geometry.Insets?> +<?import javafx.scene.Cursor?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.Region?> +<?import javafx.scene.layout.VBox?> + +<BorderPane fx:id="app" prefHeight="1024.0" prefWidth="1440.0" styleClass="background" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" +fx:controller="nl.isygameclient.controllers.AppController"> + <left> + <VBox alignment="CENTER_LEFT" prefHeight="994.0" prefWidth="200.0" spacing="15.0" BorderPane.alignment="CENTER_LEFT"> + <children> + <VBox fx:id="navBar" spacing="15.0"/> + <Region prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS" /> + <HBox alignment="CENTER_LEFT" prefHeight="60.0"> + <children> + <JFXButton alignment="BASELINE_LEFT" graphicTextGap="10.0" prefHeight="50.0" prefWidth="200.0" styleClass="user-account" text="UserName"> + <graphic> + <MaterialIconView glyphName="ACCOUNT_CIRCLE" size="30" styleClass="icon" /> + </graphic> + <cursor> + <Cursor fx:constant="HAND" /> + </cursor> + </JFXButton> + <Region HBox.hgrow="ALWAYS" /> + <JFXButton onAction="#onSettingsButtonPressed" alignment="CENTER" contentDisplay="CENTER" prefHeight="50.0" prefWidth="50.0" styleClass="settings"> + <graphic> + <MaterialIconView glyphName="SETTINGS" size="30" styleClass="surface-text" /> + </graphic> + <cursor> + <Cursor fx:constant="HAND" /> + </cursor> + </JFXButton> + </children> + <padding> + <Insets bottom="5.0" left="5.0" top="5.0" /> + </padding> + </HBox> + </children> + <BorderPane.margin> + <Insets right="15.0" /> + </BorderPane.margin> + <styleClass> + <String fx:value="surface" /> + <String fx:value="rounded" /> + </styleClass> + <padding> + <Insets right="5.0" top="15.0" /> + </padding> + <opaqueInsets> + <Insets /> + </opaqueInsets> + </VBox> + </left> + <center> + </center> + <stylesheets> + <URL value="@../css/style.css" /> + <URL value="@../css/themes/dark.theme.css" /> + <!-- <URL value="@../css/themes/light.theme.css" />--> + </stylesheets> + <padding> + <Insets bottom="15.0" left="15.0" right="15.0" top="15.0" /> + </padding> +</BorderPane> diff --git a/src/main/resources/nl/isygameclient/views/game-card.fxml b/src/main/resources/nl/isygameclient/views/game-card.fxml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import com.jfoenix.controls.JFXButton?> +<?import de.jensd.fx.glyphs.materialicons.MaterialIconView?> +<?import java.lang.String?> +<?import javafx.geometry.Insets?> +<?import javafx.scene.Cursor?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.image.ImageView?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.VBox?> + +<fx:root type="javafx.scene.layout.VBox" prefHeight="300.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/19" + xmlns:fx="http://javafx.com/fxml/1"> + <children> + <ImageView fx:id="imageView" fitHeight="250.0" fitWidth="200.0" pickOnBounds="true"/> + <HBox alignment="CENTER_LEFT" prefHeight="50.0" prefWidth="200.0" spacing="15.0"> + <children> + <JFXButton fx:id="button" alignment="CENTER" contentDisplay="CENTER" minHeight="-Infinity" minWidth="-Infinity" + prefHeight="40.0" prefWidth="40.0" styleClass="play-arrow"> + <graphic> + <MaterialIconView glyphName="PLAY_ARROW" size="30" styleClass="icon"/> + </graphic> + <cursor> + <Cursor fx:constant="HAND"/> + </cursor> + </JFXButton> + <Label fx:id="label"> + <styleClass> + <String fx:value="title-medium"/> + <String fx:value="on-surface-text"/> + </styleClass> + </Label> + </children> + <padding> + <Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/> + </padding> + </HBox> + </children> + <styleClass> + <String fx:value="on-surface"/> + <String fx:value="rounded"/> + </styleClass> +</fx:root> diff --git a/src/main/resources/nl/isygameclient/views/game-library.fxml b/src/main/resources/nl/isygameclient/views/game-library.fxml @@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import com.jfoenix.controls.JFXButton?> +<?import com.jfoenix.controls.JFXTextField?> +<?import de.jensd.fx.glyphs.materialicons.MaterialIconView?> +<?import java.lang.String?> +<?import javafx.geometry.Insets?> +<?import javafx.scene.Cursor?> +<?import javafx.scene.control.ScrollPane?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.FlowPane?> +<?import javafx.scene.layout.HBox?> + +<ScrollPane fitToHeight="true" fitToWidth="true" hbarPolicy="NEVER" prefWidth="1200.0" styleClass="transparent" + vbarPolicy="NEVER" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nl.isygameclient.controllers.GameLibraryController"> + <content> + <BorderPane styleClass="transparent"> + <top> + <HBox alignment="CENTER" spacing="15" BorderPane.alignment="CENTER"> + <children> + <HBox alignment="CENTER" prefWidth="500.0" spacing="5.0" styleClass="search-bar"> + <children> + <JFXButton fx:id="searchButton" alignment="CENTER" contentDisplay="CENTER" minHeight="-Infinity" + minWidth="-Infinity" prefHeight="40.0" prefWidth="40.0" + styleClass="search-loop" disable="true"> + <graphic> + <MaterialIconView glyphName="SEARCH" size="30" styleClass="icon"/> + </graphic> + <cursor> + <Cursor fx:constant="HAND"/> + </cursor> + </JFXButton> + <JFXTextField fx:id="searchTextField" promptText="Search" HBox.hgrow="ALWAYS"> + <styleClass> + <String fx:value="search-textfield"/> + <String fx:value="title-medium"/> + </styleClass> + </JFXTextField> + <JFXButton fx:id="searchClear" onAction="#onClearSearchButtonClick" minHeight="-Infinity" minWidth="-Infinity" prefHeight="40.0" prefWidth="40.0" + styleClass="search-close"> + <graphic> + <MaterialIconView glyphName="CLOSE" size="30" styleClass="icon"/> + </graphic> + <cursor> + <Cursor fx:constant="HAND"/> + </cursor> + </JFXButton> + <JFXButton fx:id="searchOptions" minHeight="-Infinity" minWidth="-Infinity" prefHeight="40.0" prefWidth="40.0" + styleClass="search-options"> + <graphic> + <MaterialIconView glyphName="TUNE" size="30" styleClass="icon"/> + </graphic> + <cursor> + <Cursor fx:constant="HAND"/> + </cursor> + </JFXButton> + </children> + <HBox.margin> + <Insets/> + </HBox.margin> + <padding> + <Insets bottom="5.0" left="5.0" right="5.0" top="5.0"/> + </padding> + </HBox> + </children> + <BorderPane.margin> + <Insets bottom="15.0"/> + </BorderPane.margin> + </HBox> + </top> + <center> + <FlowPane fx:id="gameCards" hgap="15.0" prefHeight="200.0" prefWidth="200.0" vgap="15.0" + BorderPane.alignment="CENTER" > + <padding> + <Insets bottom="15.0" left="15.0" right="15.0" top="15.0"/> + </padding> + <styleClass> + <String fx:value="surface"/> + <String fx:value="rounded"/> + </styleClass> + </FlowPane> + </center> + <left> + </left> + </BorderPane> + </content> +</ScrollPane> diff --git a/src/main/resources/nl/isygameclient/views/game_selector/GameCard.fxml b/src/main/resources/nl/isygameclient/views/game_selector/GameCard.fxml @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<?import java.lang.*?> -<?import javafx.scene.control.*?> -<?import javafx.scene.image.*?> -<?import javafx.scene.layout.*?> - -<VBox prefHeight="350.0" prefWidth="250.0" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" - alignment="CENTER" fx:controller="nl.isygameclient.controllers.game_selector.GameCardController" onMouseClicked="#onCardMouseClick"> - <styleClass> - <String fx:value="surface"/> - </styleClass> - <AnchorPane> - <ImageView fx:id="gameImage" fitWidth="250.0" preserveRatio="true"/> - </AnchorPane> - <Separator/> - <Label fx:id="gameTitle" alignment="TOP_RIGHT" text="Title"> - <styleClass> - <String fx:value="title-medium"/> - <String fx:value="on-surface-text"/> - </styleClass> - </Label> -</VBox> diff --git a/src/main/resources/nl/isygameclient/views/game_selector/GameSelector.fxml b/src/main/resources/nl/isygameclient/views/game_selector/GameSelector.fxml @@ -1,153 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<?import com.jfoenix.controls.*?> -<?import de.jensd.fx.glyphs.materialicons.MaterialIconView?> -<?import javafx.geometry.*?> -<?import javafx.scene.control.Label?> -<?import javafx.scene.control.ListView?> -<?import javafx.scene.control.ScrollPane?> -<?import javafx.scene.control.TextField?> -<?import javafx.scene.layout.*?> -<?import java.lang.*?> - -<AnchorPane minHeight="480.0" minWidth="600.0" prefHeight="1080.0" prefWidth="1920.0" styleClass="white" - stylesheets="@../../css/theme.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" - fx:controller="nl.isygameclient.controllers.game_selector.GameSelectorController"> - <BorderPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" - AnchorPane.topAnchor="0.0"> - <top> - <HBox prefHeight="50.0" prefWidth="Infinity"> - <styleClass> - <String fx:value="menu-bar"/> - <String fx:value="background"/> - </styleClass> - - <!-- Menu Buttons --> - <JFXButton text="Store" disable="true" prefHeight="Infinity"> - <styleClass> - <String fx:value="title-medium"/> - <String fx:value="on-surface-text"/> - </styleClass> - </JFXButton> - - <JFXButton text="Games" prefHeight="Infinity"> - <styleClass> - <String fx:value="title-medium"/> - <String fx:value="on-surface-text"/> - </styleClass> - </JFXButton> - - <JFXButton text="User" disable="true" prefHeight="Infinity"> - <styleClass> - <String fx:value="title-medium"/> - <String fx:value="on-surface-text"/> - </styleClass> - </JFXButton> - - <Pane HBox.hgrow="ALWAYS"/> - <JFXButton textAlignment="RIGHT" text="Settings" prefHeight="Infinity"> - <styleClass> - <String fx:value="title-medium"/> - <String fx:value="on-surface-text"/> - </styleClass> - </JFXButton> - </HBox> - </top> - <left> - <AnchorPane> - <HBox AnchorPane.topAnchor="0.0" AnchorPane.bottomAnchor="0.0"> - - <!-- Search Container --> - <VBox prefWidth="200.0" AnchorPane.topAnchor="0.0" AnchorPane.bottomAnchor="0.0" - AnchorPane.leftAnchor="0.0"> - <padding> - <Insets left="5" right="5"/> - </padding> - <styleClass> - <String fx:value="search-container"/> - <String fx:value="surface"/> - </styleClass> - - <!-- Search Field --> - <StackPane> - <styleClass> - <String fx:value="search-bar"/> - <String fx:value="inverse-on-surface"/> - </styleClass> - <VBox.margin> - <Insets bottom="5.0" top="10.0"/> - </VBox.margin> - - - <TextField fx:id="searchBox" promptText="Search"> - <padding> - <Insets left="35" right="35"/> - </padding> - <styleClass> - <String fx:value="search-field"/> - <String fx:value="transparent"/> - </styleClass> - </TextField> - - <JFXButton StackPane.alignment="CENTER_LEFT" disable="true"> - <graphic> - <MaterialIconView StackPane.alignment="CENTER_LEFT" glyphName="SEARCH" - glyphSize="20" styleClass="icon"> - <styleClass> - <String fx:value="on-surface-fill"/> - </styleClass> - </MaterialIconView> - </graphic> - </JFXButton> - - <JFXButton onAction="#onClearSearchButtonClick" StackPane.alignment="CENTER_RIGHT"> - <graphic> - <MaterialIconView glyphName="CLOSE" glyphSize="16" styleClass="icon"> - <styleClass> - <String fx:value="on-surface-fill"/> - </styleClass> - </MaterialIconView> - </graphic> - </JFXButton> - </StackPane> - - <!-- Search List --> - <ListView fx:id="gamesList" VBox.vgrow="ALWAYS" styleClass="surface"> - <padding> - <Insets topRightBottomLeft="1"/> - </padding> - </ListView> - </VBox> - - - <!-- Game Detail Container --> - <VBox fx:id="gameDetail" prefWidth="400" HBox.hgrow="ALWAYS" alignment="TOP_CENTER" - styleClass="inverse-on-surface"> - <padding> - <Insets topRightBottomLeft="20"/> - </padding> - <Label text="Game Title"> - <styleClass> - <String fx:value="display-small"/> - <String fx:value="on-surface-text"/> - <String fx:value="on-surface-fill"/> - </styleClass> - </Label> - </VBox> - </HBox> - </AnchorPane> - </left> - <center> - <ScrollPane fitToWidth="true" fitToHeight="true" styleClass="surface-variant"> - <FlowPane fx:id="gameContainer" hgap="5" vgap="10" > - <styleClass> - <String fx:value="surface-variant"/> - </styleClass> - <padding> - <Insets topRightBottomLeft="20"/> - </padding> - </FlowPane> - </ScrollPane> - </center> - </BorderPane> -</AnchorPane> diff --git a/src/main/resources/nl/isygameclient/views/games/othello/OthelloMainMenu.fxml b/src/main/resources/nl/isygameclient/views/games/othello/OthelloMainMenu.fxml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> + + +<?import com.jfoenix.controls.JFXButton?> +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.VBox?> +<?import java.lang.*?> +<?import java.net.URL?> +<AnchorPane xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" + fx:controller="nl.isygameclient.controllers.games.othello.OthelloMainMenuController" + prefWidth="680" prefHeight="480"> + <VBox alignment="CENTER" AnchorPane.rightAnchor="0" AnchorPane.leftAnchor="0" AnchorPane.bottomAnchor="0" AnchorPane.topAnchor="0"> + <styleClass> + <String fx:value="surface"/> + </styleClass> + <Label text="Othello"> + <styleClass> + <String fx:value="display-large"/> + <String fx:value="on-surface-text"/> + </styleClass> + <padding> + <Insets topRightBottomLeft="50"/> + </padding> + </Label> + <VBox spacing="10" alignment="CENTER" maxWidth="200"> + <JFXButton text="Single Player" onAction="#onSinglePlayerButtonClick" prefWidth="Infinity"> + <styleClass> + <String fx:value="primary"/> + <String fx:value="on-primary-text"/> + <String fx:value="title-medium"/> + </styleClass> + </JFXButton> + <JFXButton text="Multiplayer" onAction="#onMultiPlayerButtonClick" prefWidth="Infinity"> + <styleClass> + <String fx:value="primary"/> + <String fx:value="on-primary-text"/> + <String fx:value="title-medium"/> + </styleClass> + </JFXButton> + <JFXButton text="Exit" onAction="#onExitGameButtonClick" prefWidth="Infinity"> + <styleClass> + <String fx:value="primary"/> + <String fx:value="on-primary-text"/> + <String fx:value="title-medium"/> + </styleClass> + </JFXButton> + </VBox> + </VBox> + <stylesheets> + <URL value="@../../../css/style.css" /> + <URL value="@../../../css/themes/dark.theme.css" /> + <!-- <URL value="@../css/themes/light.theme.css" />--> + </stylesheets> +</AnchorPane> diff --git a/src/main/resources/nl/isygameclient/views/games/othello/OthelloMultiPlayer.fxml b/src/main/resources/nl/isygameclient/views/games/othello/OthelloMultiPlayer.fxml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import com.jfoenix.controls.JFXButton?> +<?import java.lang.String?> +<?import java.net.URL?> +<?import javafx.geometry.Insets?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.GridPane?> +<?import javafx.scene.layout.Pane?> +<?import javafx.scene.layout.VBox?> + +<?import javafx.scene.control.TextField?> +<?import javafx.scene.control.Label?> +<BorderPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" + fx:controller="nl.isygameclient.controllers.games.othello.OthelloMultiPlayerController"> + <styleClass> + <String fx:value="background" /> + </styleClass> + <left> + <VBox prefWidth="200" spacing="20" styleClass="surface"> + <padding> + <Insets topRightBottomLeft="20" /> + </padding> + <Label text="Host" styleClass="surface-text"/> + <TextField fx:id="hostField"/> + <Label text="Port" styleClass="surface-text"/> + <TextField fx:id="portField"/> + <Label text="Player Name" styleClass="surface-text"/> + <TextField fx:id="nameField" /> + <Label text="Opponent Name" styleClass="surface-text"/> + <TextField fx:id="opponentField"/> + <!-- Window Controls --> + <Pane VBox.vgrow="ALWAYS" /> + <VBox alignment="CENTER" spacing="10"> + <JFXButton onAction="#onNewGameButtonClick" prefWidth="Infinity" text="New Game"> + <styleClass> + <String fx:value="primary" /> + <String fx:value="primary-text" /> + <String fx:value="title-medium" /> + </styleClass> + </JFXButton> + <JFXButton onAction="#onMainMenuButtonClick" prefWidth="Infinity" text="Main Menu"> + <styleClass> + <String fx:value="primary" /> + <String fx:value="primary-text" /> + <String fx:value="title-medium" /> + </styleClass> + </JFXButton> + </VBox> + </VBox> + </left> + <center> + <GridPane fx:id="boardGrid" alignment="CENTER" hgap="2" vgap="2"> + <padding> + <Insets topRightBottomLeft="10" /> + </padding> + </GridPane> + </center> + <stylesheets> + <URL value="@../../../css/style.css" /> + <URL value="@../../../css/themes/dark.theme.css" /> + <!-- <URL value="@../../../css/themes/light.theme.css" />--> + </stylesheets> +</BorderPane> diff --git a/src/main/resources/nl/isygameclient/views/games/othello/OthelloSinglePlayer.fxml b/src/main/resources/nl/isygameclient/views/games/othello/OthelloSinglePlayer.fxml @@ -1,55 +1,53 @@ <?xml version="1.0" encoding="UTF-8"?> -<?import java.lang.*?> -<?import javafx.scene.layout.*?> - -<?import javafx.geometry.Insets?> <?import com.jfoenix.controls.JFXButton?> -<BorderPane xmlns="http://javafx.com/javafx" - xmlns:fx="http://javafx.com/fxml" - stylesheets="@../../../css/views/othello.css" - fx:controller="nl.isygameclient.controllers.games.othello.OthelloSinglePlayerController" - prefHeight="400.0" prefWidth="600.0"> +<?import java.lang.String?> +<?import java.net.URL?> +<?import javafx.geometry.Insets?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.GridPane?> +<?import javafx.scene.layout.Pane?> +<?import javafx.scene.layout.VBox?> + +<BorderPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nl.isygameclient.controllers.games.othello.OthelloSinglePlayerController"> <styleClass> - <String fx:value="surface"/> + <String fx:value="background" /> </styleClass> <left> - <VBox prefWidth="200" styleClass="surface-variant" spacing="20"> + <VBox prefWidth="200" spacing="20" styleClass="surface"> <padding> - <Insets topRightBottomLeft="20"/> + <Insets topRightBottomLeft="20" /> </padding> <!-- Window Controls --> - <Pane VBox.vgrow="ALWAYS"/> - <VBox spacing="10" alignment="CENTER"> - <JFXButton text="New Game" onAction="#onNewGameButtonClick" prefWidth="Infinity"> - <styleClass> - <String fx:value="primary"/> - <String fx:value="on-primary-text"/> - <String fx:value="title-medium"/> - </styleClass> - </JFXButton> - <JFXButton text="Main Menu" onAction="#onMainMenuButtonClick" prefWidth="Infinity"> + <Pane VBox.vgrow="ALWAYS" /> + <VBox alignment="CENTER" spacing="10"> + <JFXButton onAction="#onNewGameButtonClick" prefWidth="Infinity" text="New Game"> <styleClass> - <String fx:value="primary"/> - <String fx:value="on-primary-text"/> - <String fx:value="title-medium"/> + <String fx:value="primary" /> + <String fx:value="primary-text" /> + <String fx:value="title-medium" /> </styleClass> </JFXButton> - <JFXButton text="Exit" onAction="#onExitButtonClick" prefWidth="Infinity"> + <JFXButton onAction="#onMainMenuButtonClick" prefWidth="Infinity" text="Main Menu"> <styleClass> - <String fx:value="primary"/> - <String fx:value="on-primary-text"/> - <String fx:value="title-medium"/> + <String fx:value="primary" /> + <String fx:value="primary-text" /> + <String fx:value="title-medium" /> </styleClass> </JFXButton> </VBox> </VBox> </left> <center> - <GridPane fx:id="boardGrid" alignment="CENTER" vgap="2" hgap="2"> + <GridPane fx:id="boardGrid" alignment="CENTER" hgap="2" vgap="2"> <padding> - <Insets topRightBottomLeft="10"/> + <Insets topRightBottomLeft="10" /> </padding> </GridPane> </center> + <stylesheets> + <URL value="@../../../css/style.css" /> + <URL value="@../../../css/themes/dark.theme.css" /> + <!-- <URL value="@../../../css/themes/light.theme.css" />--> + </stylesheets> </BorderPane> diff --git a/src/main/resources/nl/isygameclient/views/games/tictactoe/TicTacToeMainMenu.fxml b/src/main/resources/nl/isygameclient/views/games/tictactoe/TicTacToeMainMenu.fxml @@ -7,7 +7,8 @@ <?import javafx.scene.layout.AnchorPane?> <?import javafx.scene.layout.VBox?> <?import java.lang.*?> -<AnchorPane stylesheets="@../../../css/theme.css" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" +<?import java.net.URL?> +<AnchorPane xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="nl.isygameclient.controllers.games.tictactoe.TicTacToeMainMenuController" prefWidth="680" prefHeight="480"> <VBox alignment="CENTER" AnchorPane.rightAnchor="0" AnchorPane.leftAnchor="0" AnchorPane.bottomAnchor="0" AnchorPane.topAnchor="0"> @@ -31,14 +32,14 @@ <String fx:value="title-medium"/> </styleClass> </JFXButton> - <JFXButton text="Multiplayer" onAction="#onMultiplayerButtonClick" prefWidth="Infinity"> + <JFXButton text="Multiplayer" onAction="#onMultiPlayerButtonClick" prefWidth="Infinity"> <styleClass> <String fx:value="primary"/> <String fx:value="on-primary-text"/> <String fx:value="title-medium"/> </styleClass> </JFXButton> - <JFXButton text="Exit" onAction="#onExitButtonClick" prefWidth="Infinity"> + <JFXButton text="Exit" onAction="#onExitGameButtonClick" prefWidth="Infinity"> <styleClass> <String fx:value="primary"/> <String fx:value="on-primary-text"/> @@ -47,4 +48,9 @@ </JFXButton> </VBox> </VBox> + <stylesheets> + <URL value="@../../../css/style.css" /> + <URL value="@../../../css/themes/dark.theme.css" /> + <!-- <URL value="@../css/themes/light.theme.css" />--> + </stylesheets> </AnchorPane> diff --git a/src/main/resources/nl/isygameclient/views/games/tictactoe/TicTacToeMultiPlayer.fxml b/src/main/resources/nl/isygameclient/views/games/tictactoe/TicTacToeMultiPlayer.fxml @@ -6,7 +6,8 @@ <?import javafx.scene.layout.*?> <?import java.lang.*?> -<BorderPane stylesheets="@../../../css/theme.css" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nl.isygameclient.controllers.games.tictactoe.TicTacToeMultiPlayerController"> +<?import java.net.URL?> +<BorderPane xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nl.isygameclient.controllers.games.tictactoe.TicTacToeMultiPlayerController"> <styleClass> <String fx:value="surface" /> </styleClass> @@ -97,13 +98,6 @@ <String fx:value="title-medium" /> </styleClass> </JFXButton> - <JFXButton onAction="#onExitButtonClick" prefWidth="Infinity" text="Exit"> - <styleClass> - <String fx:value="primary" /> - <String fx:value="on-primary-text" /> - <String fx:value="title-medium" /> - </styleClass> - </JFXButton> </VBox> </VBox> </left> @@ -192,4 +186,9 @@ </VBox> </HBox> </center> + <stylesheets> + <URL value="@../../../css/style.css" /> + <URL value="@../../../css/themes/dark.theme.css" /> + <!-- <URL value="@../css/themes/light.theme.css" />--> + </stylesheets> </BorderPane> \ No newline at end of file diff --git a/src/main/resources/nl/isygameclient/views/games/tictactoe/TicTacToeSettings.fxml b/src/main/resources/nl/isygameclient/views/games/tictactoe/TicTacToeSettings.fxml @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.layout.*?> + +<?import javafx.scene.control.Label?> +<?import java.lang.String?> +<?import javafx.scene.control.Separator?> +<?import com.jfoenix.controls.JFXComboBox?> +<AnchorPane xmlns="http://javafx.com/javafx" + xmlns:fx="http://javafx.com/fxml" + fx:controller="nl.isygameclient.controllers.games.tictactoe.TicTacToeSettingsController" + prefHeight="400.0" prefWidth="600.0"> + + + <!-- Difficulty Controls --> + <VBox> + <Label text="Difficulty"> + <styleClass> + <String fx:value="headline-small"/> + <String fx:value="on-surface-variant-text"/> + </styleClass> + </Label> + <Separator styleClass="on-surface-variant-text"/> + <JFXComboBox fx:id="difficultyCombo" prefWidth="Infinity" onAction="#onDifficultyComboSelect"> + <styleClass> + <String fx:value="primary"/> + <String fx:value="on-primary-text"/> + <String fx:value="body-large"/> + </styleClass> + </JFXComboBox> + </VBox> + + <!-- Playing As Controls --> + <VBox> + <Label text="Playing As"> + <styleClass> + <String fx:value="headline-small"/> + <String fx:value="on-surface-variant-text"/> + </styleClass> + </Label> + <Separator styleClass="on-surface-variant-text"/> + <JFXComboBox fx:id="playingAsCombo" prefWidth="Infinity" onAction="#onPlayingAsComboSelect"> + <styleClass> + <String fx:value="primary"/>--> + <String fx:value="on-primary-text"/> + <String fx:value="body-large"/> + </styleClass> + </JFXComboBox> + </VBox> + + <!-- Opponents Controls --> + <VBox> + <Label text="Opponent"> + <styleClass> + <String fx:value="headline-small"/> + <String fx:value="on-surface-variant-text"/> + </styleClass> + </Label> + <Separator styleClass="on-surface-variant-text"/> + <JFXComboBox fx:id="opponentCombo" prefWidth="Infinity" onAction="#onOpponentComboSelect"> + <styleClass> + <String fx:value="primary"/>--> + <String fx:value="on-primary-text"/> + <String fx:value="body-large"/> + </styleClass> + </JFXComboBox> + </VBox> + + <!-- Best of Controls --> + <VBox> + <Label text="Best Of"> + <styleClass> + <String fx:value="headline-small"/> + <String fx:value="on-surface-variant-text"/> + </styleClass> + </Label> + <Separator styleClass="on-surface-variant-text"/> + </VBox> + +</AnchorPane> diff --git a/src/main/resources/nl/isygameclient/views/games/tictactoe/TicTacToeSinglePlayer.fxml b/src/main/resources/nl/isygameclient/views/games/tictactoe/TicTacToeSinglePlayer.fxml @@ -5,13 +5,14 @@ <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <?import java.lang.*?> -<BorderPane stylesheets="@../../../css/theme.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" +<?import java.net.URL?> +<BorderPane xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="nl.isygameclient.controllers.games.tictactoe.TicTacToeSinglePlayerController"> <styleClass> - <String fx:value="surface"/> + <String fx:value="background"/> </styleClass> <left> - <VBox prefWidth="200" styleClass="surface-variant" spacing="20" > + <VBox prefWidth="200" styleClass="surface" spacing="20" > <padding> <Insets topRightBottomLeft="20"/> </padding> @@ -87,21 +88,14 @@ <JFXButton text="New Game" onAction="#onNewGameButtonClick" prefWidth="Infinity"> <styleClass> <String fx:value="primary"/> - <String fx:value="on-primary-text"/> + <String fx:value="primary-text"/> <String fx:value="title-medium"/> </styleClass> </JFXButton> <JFXButton text="Main Menu" onAction="#onMainMenuButtonClick" prefWidth="Infinity"> <styleClass> <String fx:value="primary"/> - <String fx:value="on-primary-text"/> - <String fx:value="title-medium"/> - </styleClass> - </JFXButton> - <JFXButton text="Exit" onAction="#onExitButtonClick" prefWidth="Infinity"> - <styleClass> - <String fx:value="primary"/> - <String fx:value="on-primary-text"/> + <String fx:value="primary-text"/> <String fx:value="title-medium"/> </styleClass> </JFXButton> @@ -193,4 +187,9 @@ </VBox> </HBox> </center> + <stylesheets> + <URL value="@../../../css/style.css" /> +<!-- <URL value="@../../../css/themes/light.theme.css" />--> + <URL value="@../../../css/themes/dark.theme.css" /> + </stylesheets> </BorderPane> diff --git a/src/main/resources/nl/isygameclient/views/nav-button.fxml b/src/main/resources/nl/isygameclient/views/nav-button.fxml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import de.jensd.fx.glyphs.materialicons.MaterialIconView?> +<?import java.lang.String?> +<?import javafx.scene.Cursor?> + + +<fx:root type="com.jfoenix.controls.JFXButton" alignment="CENTER" layoutX="80.0" layoutY="10.0" prefHeight="50.0" + prefWidth="200.0" xmlns="http://javafx.com/javafx/19" + xmlns:fx="http://javafx.com/fxml/1"> + <graphic> + <MaterialIconView fx:id="iconView"> + <styleClass> + <String fx:value="icon"/> + </styleClass> + </MaterialIconView> + </graphic> + <styleClass> + <String fx:value="nav-button"/> + <String fx:value="headline-small"/> + </styleClass> + <cursor> + <Cursor fx:constant="HAND"/> + </cursor> +</fx:root>