Skip to content

Commit

Permalink
Merge pull request #15 from Mw3y/step-8
Browse files Browse the repository at this point in the history
Step 8
  • Loading branch information
Mw3y authored Apr 20, 2024
2 parents 7bb5fa0 + c65b32b commit 8d22aa1
Show file tree
Hide file tree
Showing 8 changed files with 606 additions and 0 deletions.
30 changes: 30 additions & 0 deletions resources/decks.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#decks {
-fx-spacing: 5px;
-fx-padding: 5px;
}

#NORMAL {
-fx-image: url(256/NORMAL.jpg);
}

#MENHIR {
-fx-image: url(256/MENHIR.jpg);
}

#decks Text {
-fx-font-size: 84;
-fx-font-weight: bold;
-fx-text-alignment: center;
-fx-fill: white;
-fx-effect: dropshadow(two-pass-box,#333,10,0,5,5);
}

#next-tile {
-fx-padding: 3;
}

#next-tile Text {
-fx-font-size: 200%;
-fx-font-weight: bold;
-fx-text-alignment: center;
}
4 changes: 4 additions & 0 deletions resources/message-board.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#message-board {
-fx-padding: 5px;
-fx-spacing: 3px;
}
17 changes: 17 additions & 0 deletions resources/players.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#players {
-fx-spacing: 5;
-fx-padding: 5;
}

.player {
-fx-padding: 5;
-fx-line-spacing: 5;
-fx-border-radius: 4;
-fx-border-width: 2;
-fx-border-style: solid;
-fx-border-color: transparent;
}

.player.current {
-fx-border-color: slategray;
}
126 changes: 126 additions & 0 deletions src/ch/epfl/chacun/gui/DecksUI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package ch.epfl.chacun.gui;

import ch.epfl.chacun.Occupant;
import ch.epfl.chacun.Tile;
import javafx.beans.value.ObservableValue;
import javafx.scene.Node;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;

import java.util.function.Consumer;

import static ch.epfl.chacun.gui.ImageLoader.LARGE_TILE_FIT_SIZE;
import static ch.epfl.chacun.gui.ImageLoader.NORMAL_TILE_FIT_SIZE;

/**
* Helper class to create the decks UI.
*
* @author Maxence Espagnet (sciper: 372808)
* @author Balthazar Baillat (sciper: 373420)
*/
public final class DecksUI {

/**
* The factor to apply to the tile fit size to get the wrapping width of the tile count.
*/
private static final double TILE_COUNT_WRAPPING_FACTOR = .8;

/**
* Non-instantiable class constructor
*/
private DecksUI() {
}

/**
* Creates the decks UI.
*
* @param tileToPlaceO the observable value of the tile to place
* @param normalTileDeckSizeO the observable value of the size of the normal tile deck
* @param menhirTileDeckSizeO the observable value of the size of the menhir tile deck
* @param textToDisplayO the observable value of the text to display
* @param occupantConsumer the consumer of the occupant to skip the special action of retaking a pawn
* @return the decks UI
*/
public static Node create(ObservableValue<Tile> tileToPlaceO, ObservableValue<Integer> normalTileDeckSizeO,
ObservableValue<Integer> menhirTileDeckSizeO, ObservableValue<String> textToDisplayO,
Consumer<Occupant> occupantConsumer) {
VBox container = new VBox();
container.getStylesheets().add("/decks.css");
// Create the decks container
HBox decks = new HBox();
decks.setId("decks");
// Create the decks UI
decks.getChildren().add(createDeckCover(Tile.Kind.NORMAL, normalTileDeckSizeO));
decks.getChildren().add(createDeckCover(Tile.Kind.MENHIR, menhirTileDeckSizeO));
container.getChildren().add(decks);
// Create the next tile to place UI
container.getChildren().add(createNextTileCover(tileToPlaceO, textToDisplayO, occupantConsumer));

return container;
}

/**
* Creates a deck cover UI.
*
* @param kind the kind of the deck
* @param sizeO the observable value of the size of the deck
* @return the deck cover UI
*/
private static StackPane createDeckCover(Tile.Kind kind, ObservableValue<Integer> sizeO) {
ImageView view = new ImageView();
Text tileCount = new Text();

// Configure the view
view.setFitHeight(NORMAL_TILE_FIT_SIZE);
view.setFitWidth(NORMAL_TILE_FIT_SIZE);
view.setId(kind.toString());
// Configure the text
tileCount.textProperty().bind(sizeO.map(String::valueOf));
tileCount.visibleProperty().bind(sizeO.map(size -> size > 0));
tileCount.setWrappingWidth(TILE_COUNT_WRAPPING_FACTOR * NORMAL_TILE_FIT_SIZE);

return new StackPane(view, tileCount);
}

/**
* Creates the next tile to place cover UI.
*
* @param tileToPlaceO the observable value of the tile to place
* @param textToDisplayO the observable value of the text to display
* @param occupantConsumer the consumer of the occupant
* @return the next tile to place cover UI
*/
private static StackPane createNextTileCover(ObservableValue<Tile> tileToPlaceO,
ObservableValue<String> textToDisplayO,
Consumer<Occupant> occupantConsumer) {
StackPane tileToPlace = new StackPane();
tileToPlace.setId("next-tile");

// Configure the view
ImageView view = new ImageView();
view.setFitHeight(LARGE_TILE_FIT_SIZE);
view.setFitWidth(LARGE_TILE_FIT_SIZE);
view.visibleProperty().bind(textToDisplayO.map(String::isEmpty));
// Display the image of the tile to place
Image image = ImageLoader.largeImageForTile(tileToPlaceO.getValue().id());
view.setImage(image);
tileToPlaceO.addListener((o, oldTile, newTile) -> {
Image newImage = ImageLoader.largeImageForTile(newTile.id());
view.setImage(newImage);
});

// Display the text of the special action and register a mouse click event to skip it
Text text = new Text();
text.textProperty().bind(textToDisplayO);
text.visibleProperty().bind(textToDisplayO.map(s -> !s.isEmpty()));
text.setWrappingWidth(TILE_COUNT_WRAPPING_FACTOR * LARGE_TILE_FIT_SIZE);
text.setOnMouseClicked(e -> occupantConsumer.accept(null));

tileToPlace.getChildren().addAll(view, text);
return tileToPlace;
}
}
70 changes: 70 additions & 0 deletions src/ch/epfl/chacun/gui/ImageLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package ch.epfl.chacun.gui;

import javafx.scene.image.Image;

import static java.util.FormatProcessor.FMT;

/**
* Helper class to load images.
*
* @author Maxence Espagnet (sciper: 372808)
* @author Balthazar Baillat (sciper: 373420)
*/
public final class ImageLoader {

/**
* Size of large tiles, in pixels.
*/
public static final int LARGE_TILE_PIXEL_SIZE = 512;

/**
* Display size of large tiles, in pixels.
*/
public static final int LARGE_TILE_FIT_SIZE = 256;

/**
* Size of normal tiles, in pixels.
*/
public static final int NORMAL_TILE_PIXEL_SIZE = 256;

/**
* Display size of normal tiles, in pixels.
*/
public static final int NORMAL_TILE_FIT_SIZE = 128;

/**
* Size of the marker, in pixels.
*/
public static final int MARKER_PIXEL_SIZE = 96;

/**
* Display size of the marker, in pixels.
*/
public final int MARKER_FIT_SIZE = 48;

/**
* Non-instantiable class constructor
*/
private ImageLoader() {
}

/**
* Loads the 512x512 image for the given tile id.
*
* @param tileId the id of the tile
* @return the 512x512 tile image
*/
public static Image normalImageForTile(int tileId) {
return new Image(FMT."/\{NORMAL_TILE_PIXEL_SIZE}/%02d\{tileId}.jpg");
}

/**
* Loads the 256x256 image for the given tile id.
*
* @param tileId the id of the tile
* @return the 256x256 tile image
*/
public static Image largeImageForTile(int tileId) {
return new Image(FMT."/\{LARGE_TILE_PIXEL_SIZE}/%02d\{tileId}.jpg");
}
}
75 changes: 75 additions & 0 deletions src/ch/epfl/chacun/gui/MessageBoardUI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package ch.epfl.chacun.gui;

import ch.epfl.chacun.MessageBoard;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Node;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;

import java.util.List;
import java.util.Set;

import static ch.epfl.chacun.gui.ImageLoader.LARGE_TILE_FIT_SIZE;

/**
* Helper class to create the message board UI.
*
* @author Maxence Espagnet (sciper: 372808)
* @author Balthazar Baillat (sciper: 373420)
*/
public final class MessageBoardUI {

/**
* The width of the scroll bar, in pixels.
*/
private static final int SCROLL_BAR_WIDTH = 8;

/**
* The spacing between messages, in pixels.
*/
private static final int MESSAGES_SPACING = 10;

/**
* Non-instantiable class constructor
*/
private MessageBoardUI() {
}

/**
* Creates the message board UI.
*
* @param messagesO the observable value of the messages
* @param tileIdsP the property of the tile ids
* @return the message board UI
*/
public static Node create(ObservableValue<List<MessageBoard.Message>> messagesO,
ObjectProperty<Set<Integer>> tileIdsP) {
ScrollPane container = new ScrollPane();
container.getStylesheets().add("/message-board.css");
container.setId("message-board");

VBox wrapper = new VBox();
messagesO.addListener((o, previousMessages, currentMessages) -> {
// Add the new messages to the container
currentMessages.stream().skip(previousMessages.size()).forEach(newMessage -> {
Text message = new Text(newMessage.text());
message.setTextAlignment(TextAlignment.JUSTIFY);
message.setWrappingWidth(LARGE_TILE_FIT_SIZE - SCROLL_BAR_WIDTH);
// Dynamically update the tile ids mentioned in the message if needed
message.setOnMouseEntered(e -> tileIdsP.set(newMessage.tileIds()));
message.setOnMouseExited(e -> tileIdsP.set(Set.of()));
wrapper.getChildren().add(message);
});
// Scroll to the last message
Platform.runLater(() -> container.setVvalue(1));
});

wrapper.setSpacing(MESSAGES_SPACING);
container.setContent(wrapper);
return container;
}
}
Loading

0 comments on commit 8d22aa1

Please sign in to comment.