FIx: Fixed Coverage Screenshots And htmlRepot.

This commit is contained in:
GabrieleRadice
2026-06-19 22:57:43 +02:00
parent a4dc8b2540
commit 0129efe400
316 changed files with 4566 additions and 4497 deletions
@@ -0,0 +1,493 @@
<!DOCTYPE html>
<html id="htmlId">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Coverage Report > LeaderboardFXMLController</title>
<style type="text/css">
@import "../../css/coverage.css";
@import "../../css/idea.min.css";
</style>
<script type="text/javascript" src="../../js/highlight.min.js"></script>
<script type="text/javascript" src="../../js/highlightjs-line-numbers.min.js"></script>
</head>
<body>
<div class="content">
<div class="breadCrumbs">
Current scope: <a href="../../index.html">all classes</a>
<span class="separator">|</span>
<a href="../index.html">it.polimi.ingsw.gc14.View.GUI</a>
</div>
<h1>Coverage Summary for Class: LeaderboardFXMLController (it.polimi.ingsw.gc14.View.GUI)</h1>
<table class="coverageStats">
<tr>
<th class="name">Class</th>
<th class="coverageStat
">
Class, %
</th>
<th class="coverageStat
">
Method, %
</th>
<th class="coverageStat
">
Branch, %
</th>
<th class="coverageStat
">
Line, %
</th>
</tr>
<tr>
<td class="name">LeaderboardFXMLController</td>
<td class="coverageStat">
<span class="percent">
0%
</span>
<span class="absValue">
(0/1)
</span>
</td>
<td class="coverageStat">
<span class="percent">
0%
</span>
<span class="absValue">
(0/19)
</span>
</td>
<td class="coverageStat">
<span class="percent">
0%
</span>
<span class="absValue">
(0/34)
</span>
</td>
<td class="coverageStat">
<span class="percent">
0%
</span>
<span class="absValue">
(0/181)
</span>
</td>
</tr>
</table>
<br/>
<br/>
<pre>
<code class="sourceCode" id="sourceCode">&nbsp;package it.polimi.ingsw.gc14.View.GUI;
&nbsp;
&nbsp;import it.polimi.ingsw.gc14.Controller.ClientController;
&nbsp;import it.polimi.ingsw.gc14.Model.Player;
&nbsp;import javafx.animation.ScaleTransition;
&nbsp;import it.polimi.ingsw.gc14.Model.PlayableCard;
&nbsp;import javafx.event.Event;
&nbsp;import javafx.fxml.FXML;
&nbsp;import javafx.scene.control.ScrollPane;
&nbsp;import javafx.stage.Popup;
&nbsp;import javafx.geometry.Insets;
&nbsp;import javafx.geometry.Pos;
&nbsp;import javafx.scene.Cursor;
&nbsp;import javafx.scene.Node;
&nbsp;import javafx.scene.control.Label;
&nbsp;import javafx.scene.effect.DropShadow;
&nbsp;import javafx.scene.image.Image;
&nbsp;import javafx.scene.image.ImageView;
&nbsp;import javafx.scene.input.MouseEvent;
&nbsp;import javafx.scene.layout.*;
&nbsp;import javafx.scene.paint.Color;
&nbsp;import javafx.scene.paint.LinearGradient;
&nbsp;import javafx.scene.paint.Stop;
&nbsp;import javafx.scene.paint.CycleMethod;
&nbsp;import javafx.scene.text.Font;
&nbsp;import javafx.stage.Window;
&nbsp;import javafx.util.Duration;
&nbsp;
&nbsp;import java.util.*;
&nbsp;
&nbsp;/**
&nbsp; * FXML controller for the end-of-game leaderboard scene.
&nbsp; *
&nbsp; * &lt;p&gt;Displays the final player rankings and a winner/game-over banner.
&nbsp; */
<b class="nc">&nbsp;public class LeaderboardFXMLController {</b>
&nbsp; /** Root pane of the leaderboard scene; used to set the background and anchor the popup. */
&nbsp; @FXML private StackPane rootPane;
&nbsp; /** Main vertical container holding the outcome label and ranking rows. */
&nbsp; @FXML private VBox mainVBox;
&nbsp; /** Vertical list populated with one {@code HBox} row per ranked player. */
&nbsp; @FXML private VBox rankingList;
&nbsp;
&nbsp; /** Client controller for fetching game state and sending actions. */
&nbsp; private ClientController controller;
&nbsp; /** Auto-hiding popup that shows detailed player card information. */
&nbsp; private Popup popup;
&nbsp; /** Content container inside {@link #popup}. */
&nbsp; private VBox popupContent;
&nbsp; /** Shared image cache to avoid reloading resources multiple times. */
<b class="nc">&nbsp; private static final Map&lt;String, Image&gt; imageCache = new HashMap&lt;&gt;();</b>
&nbsp; /** Action run when the player returns to the login screen (disconnect + scene switch). */
&nbsp; private Runnable action;
&nbsp;
&nbsp; /** Returns a cached {@link Image} for the given classpath {@code path}, loading it on first access. */
&nbsp; private Image loadImage(String path) {
<b class="nc">&nbsp; return imageCache.computeIfAbsent(path,</b>
<b class="nc">&nbsp; p -&gt; new Image(Objects.requireNonNull(getClass().getResourceAsStream(p))));</b>
&nbsp; }
&nbsp;
&nbsp;
&nbsp; /**
&nbsp; * Injects the client controller, a post-game action, and the login scene reference.
&nbsp; *
&nbsp; * @param controller the client controller.
&nbsp; * @param action the action to run when the player returns to the login screen.
&nbsp; */
&nbsp; public void setController(ClientController controller, Runnable action) {
<b class="nc">&nbsp; this.controller = controller;</b>
<b class="nc">&nbsp; this.action = action;</b>
&nbsp; }
&nbsp;
&nbsp;
&nbsp; /** Initializes the scene: loads fonts, sets up the background, and initializes the popup. */
&nbsp; @FXML
&nbsp; public void initialize() {
<b class="nc">&nbsp; Font.loadFont(getClass().getResourceAsStream(&quot;/Fonts/InknutAntiqua-Regular.ttf&quot;), 14);</b>
<b class="nc">&nbsp; mainVBox.sceneProperty().addListener((obs, oldScene, newScene) -&gt; {</b>
<b class="nc">&nbsp; if (newScene != null) newScene.getRoot().applyCss();</b>
&nbsp; });
<b class="nc">&nbsp; renderBackground();</b>
<b class="nc">&nbsp; initPopup();</b>
&nbsp; }
&nbsp;
&nbsp;
&nbsp; /** Populates the ranking list with the final player standings and shows the outcome banner. */
&nbsp; public void render() {
<b class="nc">&nbsp; rankingList.getChildren().clear();</b>
<b class="nc">&nbsp; if(!controller.getMiniModel().standingPlayers.isEmpty())</b>
&nbsp; {
<b class="nc">&nbsp; List&lt;Player&gt; sorted = controller.getMiniModel().standingPlayers;</b>
&nbsp;
<b class="nc">&nbsp; boolean iWon = sorted.get(0).getUserName().equals(controller.getMyUsername());</b>
&nbsp;
&nbsp; // Label grande Winner / Game Over
<b class="nc">&nbsp; Label outcomeLabel = new Label(iWon ? &quot;\uD83C\uDFC6 WINNER! \uD83C\uDFC6&quot; : &quot;GAME OVER&quot;);</b>
<b class="nc">&nbsp; outcomeLabel.setStyle(</b>
&nbsp; &quot;-fx-font-size: 64px;&quot; +
&nbsp; &quot;-fx-font-weight: bold;&quot; +
<b class="nc">&nbsp; &quot;-fx-text-fill: &quot; + (iWon ? &quot;#FFD700;&quot; : &quot;#FF4444;&quot;)</b>
&nbsp; );
<b class="nc">&nbsp; DropShadow glow = new DropShadow();</b>
<b class="nc">&nbsp; glow.setColor(iWon ? Color.rgb(255, 200, 0, 0.95) : Color.rgb(220, 0, 0, 0.95));</b>
<b class="nc">&nbsp; glow.setRadius(35);</b>
<b class="nc">&nbsp; glow.setSpread(0.35);</b>
<b class="nc">&nbsp; outcomeLabel.setEffect(glow);</b>
<b class="nc">&nbsp; rankingList.getChildren().add(outcomeLabel);</b>
&nbsp;
<b class="nc">&nbsp; Region sep = new Region();</b>
<b class="nc">&nbsp; sep.setPrefHeight(16);</b>
<b class="nc">&nbsp; rankingList.getChildren().add(sep);</b>
&nbsp;
<b class="nc">&nbsp; for (int i = 0; i &lt; sorted.size(); i++) {</b>
<b class="nc">&nbsp; rankingList.getChildren().add(createPlayerRow(i + 1, sorted.get(i)));</b>
&nbsp; }
&nbsp; }
&nbsp; }
&nbsp;
&nbsp;
&nbsp; // ==== EFFECTS ====
&nbsp; /** Scales {@code node} to 1.02× on hover and sets a hand cursor. */
&nbsp; private void addHoverZoom(Node node) {
<b class="nc">&nbsp; ScaleTransition scaleUp = new ScaleTransition(Duration.millis(150), node);</b>
<b class="nc">&nbsp; scaleUp.setToX(1.02);</b>
<b class="nc">&nbsp; scaleUp.setToY(1.02);</b>
<b class="nc">&nbsp; ScaleTransition scaleDown = new ScaleTransition(Duration.millis(150), node);</b>
<b class="nc">&nbsp; scaleDown.setToX(1.0);</b>
<b class="nc">&nbsp; scaleDown.setToY(1.0);</b>
<b class="nc">&nbsp; node.addEventHandler(MouseEvent.MOUSE_ENTERED, e -&gt; { scaleUp.play(); node.setCursor(Cursor.HAND); });</b>
<b class="nc">&nbsp; node.addEventHandler(MouseEvent.MOUSE_EXITED, e -&gt; { scaleDown.play(); node.setCursor(Cursor.DEFAULT); });</b>
&nbsp; }
&nbsp;
&nbsp; /** Applies a static drop-shadow to {@code node}. */
&nbsp; private void addShadow(Node node) {
<b class="nc">&nbsp; DropShadow shadow = new DropShadow();</b>
<b class="nc">&nbsp; shadow.setColor(Color.rgb(0, 0, 0, 0.6));</b>
<b class="nc">&nbsp; shadow.setRadius(12);</b>
<b class="nc">&nbsp; shadow.setOffsetX(3);</b>
<b class="nc">&nbsp; shadow.setOffsetY(3);</b>
<b class="nc">&nbsp; node.setEffect(shadow);</b>
&nbsp; }
&nbsp;
&nbsp;
&nbsp; // ==== ROW ====
&nbsp; /** Builds a styled leaderboard row showing rank, totem, username, stats, and prestige for {@code player}. */
&nbsp; private HBox createPlayerRow(int position, Player player) {
<b class="nc">&nbsp; HBox row = new HBox(20);</b>
<b class="nc">&nbsp; row.setAlignment(Pos.CENTER_LEFT);</b>
<b class="nc">&nbsp; row.setPadding(new Insets(14, 28, 14, 28));</b>
<b class="nc">&nbsp; row.setMaxWidth(Double.MAX_VALUE);</b>
&nbsp;
<b class="nc">&nbsp; LinearGradient gradient = new LinearGradient(</b>
&nbsp; 0, 0, 1, 0, true, CycleMethod.NO_CYCLE,
<b class="nc">&nbsp; new Stop(0.0, Color.rgb(0, 0, 0, 0.75)),</b>
<b class="nc">&nbsp; new Stop(0.5, Color.rgb(0, 0, 0, 0.60)),</b>
<b class="nc">&nbsp; new Stop(1.0, Color.rgb(0, 0, 0, 0.75))</b>
&nbsp; );
<b class="nc">&nbsp; row.setBackground(new Background(new BackgroundFill(</b>
&nbsp; gradient,
&nbsp; new CornerRadii(12),
&nbsp; Insets.EMPTY
&nbsp; )));
<b class="nc">&nbsp; addShadow(row);</b>
<b class="nc">&nbsp; addHoverZoom(row);</b>
&nbsp;
<b class="nc">&nbsp; Label posLabel = new Label(position + &quot;°&quot;);</b>
<b class="nc">&nbsp; posLabel.setMinWidth(55);</b>
<b class="nc">&nbsp; String medalColor = switch (position) {</b>
<b class="nc">&nbsp; case 1 -&gt; &quot;#FFD700&quot;; // oro</b>
<b class="nc">&nbsp; case 2 -&gt; &quot;#C0C0C0&quot;; // argento</b>
<b class="nc">&nbsp; case 3 -&gt; &quot;#CD7F32&quot;; // bronzo</b>
<b class="nc">&nbsp; default -&gt; &quot;#EEEEEE&quot;;</b>
<b class="nc">&nbsp; };</b>
<b class="nc">&nbsp; posLabel.setStyle(&quot;-fx-font-size: 28px; -fx-font-weight: bold; -fx-text-fill: &quot; + medalColor + &quot;;&quot;);</b>
&nbsp;
&nbsp;
<b class="nc">&nbsp; ImageView totem = new ImageView(loadImage(</b>
<b class="nc">&nbsp; &quot;/GUIImages/Totems/totem_&quot; + player.getTotem().toString().toLowerCase(Locale.ROOT) + &quot;.png&quot;));</b>
<b class="nc">&nbsp; totem.setFitHeight(55);</b>
<b class="nc">&nbsp; totem.setPreserveRatio(true);</b>
&nbsp;
<b class="nc">&nbsp; Label nameLabel = new Label(player.getUserName());</b>
<b class="nc">&nbsp; nameLabel.setStyle(</b>
&nbsp; &quot;-fx-font-size: 22px; -fx-font-weight: bold; -fx-text-fill: &quot; +
<b class="nc">&nbsp; (player.getUserName().equals(controller.getMyUsername()) ? &quot;#ff6b6b;&quot; : &quot;#FFFFFF;&quot;)</b>
&nbsp; );
<b class="nc">&nbsp; HBox.setHgrow(nameLabel, Priority.ALWAYS);</b>
&nbsp;
<b class="nc">&nbsp; HBox stats = createStatsBox(player);</b>
&nbsp;
<b class="nc">&nbsp; HBox ppBox = new HBox(6);</b>
<b class="nc">&nbsp; ppBox.setAlignment(Pos.CENTER);</b>
<b class="nc">&nbsp; ImageView ppIcon = new ImageView(loadImage(&quot;/GUIImages/Icons/PrestigePoint.png&quot;));</b>
<b class="nc">&nbsp; ppIcon.setFitHeight(45);</b>
<b class="nc">&nbsp; ppIcon.setPreserveRatio(true);</b>
<b class="nc">&nbsp; Label ppLabel = new Label(String.valueOf(player.getPrestigeValue()));</b>
<b class="nc">&nbsp; ppLabel.setStyle(&quot;-fx-font-size: 28px; -fx-font-weight: bold; -fx-text-fill: #FFD700;&quot;);</b>
<b class="nc">&nbsp; ppBox.getChildren().addAll(ppIcon, ppLabel);</b>
&nbsp;
<b class="nc">&nbsp; row.getChildren().addAll(posLabel, totem, nameLabel, stats, ppBox);</b>
<b class="nc">&nbsp; row.setOnMouseClicked(e -&gt; openPlayerPopup(player));</b>
<b class="nc">&nbsp; return row;</b>
&nbsp; }
&nbsp;
&nbsp; /** Creates a compact icon+count stats strip for all card types of {@code player}. */
&nbsp; private HBox createStatsBox(Player player) {
<b class="nc">&nbsp; HBox stats = new HBox(14);</b>
<b class="nc">&nbsp; stats.setAlignment(Pos.CENTER);</b>
&nbsp;
<b class="nc">&nbsp; stats.getChildren().add(createStatItem(&quot;/GUIImages/Icons/Food.png&quot;, String.valueOf(player.getFoodValue()), 26));</b>
<b class="nc">&nbsp; stats.getChildren().add(createStatItem(&quot;/GUIImages/Icons/Artist.png&quot;, String.valueOf(player.getArtists().size()), 26));</b>
<b class="nc">&nbsp; stats.getChildren().add(createStatItem(&quot;/GUIImages/Icons/Gatherer.png&quot;, String.valueOf(player.getGatherers().size()), 26));</b>
<b class="nc">&nbsp; stats.getChildren().add(createStatItem(&quot;/GUIImages/Icons/Inventor.png&quot;, String.valueOf(player.getInventors().size()), 26));</b>
<b class="nc">&nbsp; stats.getChildren().add(createStatItem(&quot;/GUIImages/Icons/Builder.png&quot;, String.valueOf(player.getBuilders().size()), 26));</b>
<b class="nc">&nbsp; stats.getChildren().add(createStatItem(&quot;/GUIImages/Icons/Shaman.png&quot;, String.valueOf(player.getShamans().size()), 26));</b>
<b class="nc">&nbsp; stats.getChildren().add(createStatItem(&quot;/GUIImages/Icons/Hunter.png&quot;, String.valueOf(player.getHunters().size()), 26));</b>
<b class="nc">&nbsp; stats.getChildren().add(createStatItem(&quot;/GUIImages/Icons/Building.png&quot;, String.valueOf(player.getBuildingCards().size()), 26));</b>
&nbsp;
<b class="nc">&nbsp; return stats;</b>
&nbsp; }
&nbsp;
&nbsp; /** Creates a single icon + label widget for one stat type. */
&nbsp; private HBox createStatItem(String iconPath, String value, double iconHeight) {
<b class="nc">&nbsp; HBox box = new HBox(4);</b>
<b class="nc">&nbsp; box.setAlignment(Pos.CENTER);</b>
<b class="nc">&nbsp; ImageView icon = new ImageView(loadImage(iconPath));</b>
<b class="nc">&nbsp; icon.setFitHeight(iconHeight);</b>
<b class="nc">&nbsp; icon.setPreserveRatio(true);</b>
<b class="nc">&nbsp; Label label = new Label(value);</b>
<b class="nc">&nbsp; label.setStyle(&quot;-fx-font-size: 16px; -fx-text-fill: #FFFFFF; -fx-font-weight: bold;&quot;);</b>
<b class="nc">&nbsp; DropShadow textShadow = new DropShadow();</b>
<b class="nc">&nbsp; textShadow.setColor(Color.rgb(0, 0, 0, 0.9));</b>
<b class="nc">&nbsp; textShadow.setRadius(4);</b>
<b class="nc">&nbsp; label.setEffect(textShadow);</b>
<b class="nc">&nbsp; box.getChildren().addAll(icon, label);</b>
<b class="nc">&nbsp; return box;</b>
&nbsp; }
&nbsp;
&nbsp;
&nbsp; // ==== POPUP ====
&nbsp; /** Creates and configures the auto-hiding player-detail popup. */
&nbsp; private void initPopup() {
<b class="nc">&nbsp; popupContent = new VBox(12);</b>
<b class="nc">&nbsp; popupContent.setAlignment(Pos.CENTER);</b>
<b class="nc">&nbsp; popupContent.setPadding(new Insets(16));</b>
<b class="nc">&nbsp; popupContent.setStyle(</b>
&nbsp; &quot;-fx-background-color: rgba(20,10,5,0.97);&quot; +
&nbsp; &quot;-fx-border-color: #8B4513;&quot; +
&nbsp; &quot;-fx-border-width: 3;&quot; +
&nbsp; &quot;-fx-border-radius: 14;&quot; +
&nbsp; &quot;-fx-background-radius: 14;&quot;
&nbsp; );
&nbsp;
<b class="nc">&nbsp; popup = new Popup();</b>
<b class="nc">&nbsp; popup.getContent().add(popupContent);</b>
<b class="nc">&nbsp; popup.setAutoHide(true);</b>
<b class="nc">&nbsp; popup.addEventHandler(Event.ANY, e -&gt; {</b>
<b class="nc">&nbsp; if (popup.getScene() != null) popup.getScene().setFill(Color.TRANSPARENT);</b>
&nbsp; });
&nbsp; }
&nbsp;
&nbsp; /** Opens the player-detail popup showing all cards held by {@code player}, grouped by type. */
&nbsp; private void openPlayerPopup(Player player) {
<b class="nc">&nbsp; popupContent.getChildren().clear();</b>
&nbsp;
<b class="nc">&nbsp; HBox header = new HBox(10);</b>
<b class="nc">&nbsp; header.setAlignment(Pos.CENTER);</b>
<b class="nc">&nbsp; ImageView totem = new ImageView(loadImage(</b>
<b class="nc">&nbsp; &quot;/GUIImages/Totems/totem_&quot; + player.getTotem().toString().toLowerCase(Locale.ROOT) + &quot;.png&quot;));</b>
<b class="nc">&nbsp; totem.setFitHeight(30);</b>
<b class="nc">&nbsp; totem.setPreserveRatio(true);</b>
<b class="nc">&nbsp; Label nameLabel = new Label(player.getUserName());</b>
<b class="nc">&nbsp; nameLabel.setStyle(&quot;-fx-font-size: 18px; -fx-font-weight: bold; -fx-text-fill: #FFD700;&quot;);</b>
<b class="nc">&nbsp; header.getChildren().addAll(totem, nameLabel);</b>
<b class="nc">&nbsp; popupContent.getChildren().add(header);</b>
&nbsp;
<b class="nc">&nbsp; String[][] types = {</b>
&nbsp; {&quot;Artist&quot;, &quot;artists&quot;},
&nbsp; {&quot;Gatherer&quot;, &quot;gatherers&quot;},
&nbsp; {&quot;Inventor&quot;, &quot;inventors&quot;},
&nbsp; {&quot;Builder&quot;, &quot;builders&quot;},
&nbsp; {&quot;Shaman&quot;, &quot;shamans&quot;},
&nbsp; {&quot;Hunter&quot;, &quot;hunters&quot;},
&nbsp; {&quot;Building&quot;, &quot;buildingCards&quot;}
&nbsp; };
&nbsp;
<b class="nc">&nbsp; VBox grid = new VBox(6);</b>
<b class="nc">&nbsp; grid.setAlignment(Pos.CENTER_LEFT);</b>
<b class="nc">&nbsp; boolean hasAnyCard = false;</b>
&nbsp;
<b class="nc">&nbsp; for (String[] type : types) {</b>
<b class="nc">&nbsp; String typeName = type[0];</b>
<b class="nc">&nbsp; String field = type[1];</b>
<b class="nc">&nbsp; ArrayList&lt;PlayableCard&gt; cards = getPlayerCards(player.getUserName(), field);</b>
<b class="nc">&nbsp; if (cards.isEmpty()) continue;</b>
<b class="nc">&nbsp; hasAnyCard = true;</b>
&nbsp;
<b class="nc">&nbsp; HBox row = new HBox(6);</b>
<b class="nc">&nbsp; row.setAlignment(Pos.CENTER_LEFT);</b>
&nbsp;
<b class="nc">&nbsp; ImageView typeIcon = new ImageView(loadImage(&quot;/GUIImages/Icons/&quot;+typeName+&quot;.png&quot;));</b>
<b class="nc">&nbsp; typeIcon.setFitHeight(22);</b>
<b class="nc">&nbsp; typeIcon.setPreserveRatio(true);</b>
<b class="nc">&nbsp; row.getChildren().add(typeIcon);</b>
&nbsp;
<b class="nc">&nbsp; for (PlayableCard card : cards) {</b>
<b class="nc">&nbsp; ImageView img = new ImageView(loadImage(&quot;/GUIImages/Fronts/card-&quot; + card.getIdIMG() + &quot;.png&quot;));</b>
<b class="nc">&nbsp; img.setFitHeight(230);</b>
<b class="nc">&nbsp; img.setPreserveRatio(true);</b>
<b class="nc">&nbsp; img.setCursor(Cursor.HAND);</b>
<b class="nc">&nbsp; row.getChildren().add(img);</b>
&nbsp; }
&nbsp;
<b class="nc">&nbsp; grid.getChildren().add(row);</b>
&nbsp; }
&nbsp;
<b class="nc">&nbsp; if (!hasAnyCard) {</b>
<b class="nc">&nbsp; Label empty = new Label(&quot;No cards&quot;);</b>
<b class="nc">&nbsp; empty.setStyle(&quot;-fx-font-size: 14px; -fx-text-fill: #888888;&quot;);</b>
<b class="nc">&nbsp; grid.getChildren().add(empty);</b>
&nbsp; }
&nbsp;
<b class="nc">&nbsp; ScrollPane scrollPane = new ScrollPane(grid);</b>
<b class="nc">&nbsp; scrollPane.setFitToWidth(true);</b>
<b class="nc">&nbsp; scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);</b>
<b class="nc">&nbsp; scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);</b>
<b class="nc">&nbsp; scrollPane.setStyle(&quot;-fx-background: transparent; -fx-background-color: transparent;&quot;);</b>
&nbsp;
<b class="nc">&nbsp; Window window = rootPane.getScene().getWindow();</b>
<b class="nc">&nbsp; scrollPane.setMaxHeight(window.getHeight() * 0.8); // cap scroll area to 80% of window height</b>
<b class="nc">&nbsp; popupContent.getChildren().add(scrollPane);</b>
<b class="nc">&nbsp; popup.show(window, 0, 0);</b>
<b class="nc">&nbsp; popup.getScene().setFill(Color.TRANSPARENT);</b>
<b class="nc">&nbsp; popup.setX(window.getX() + (window.getWidth() - popup.getWidth()) / 2);</b>
<b class="nc">&nbsp; popup.setY(window.getY() + (window.getHeight() - popup.getHeight()) / 2);</b>
&nbsp; }
&nbsp;
&nbsp; /** Returns a copy of the named card collection for {@code username}. */
&nbsp; private ArrayList&lt;PlayableCard&gt; getPlayerCards(String username, String type) {
<b class="nc">&nbsp; Player p = controller.getMiniModel().players.get(username);</b>
<b class="nc">&nbsp; return switch (type) {</b>
<b class="nc">&nbsp; case &quot;artists&quot; -&gt; new ArrayList&lt;&gt;(p.getArtists());</b>
<b class="nc">&nbsp; case &quot;gatherers&quot; -&gt; new ArrayList&lt;&gt;(p.getGatherers());</b>
<b class="nc">&nbsp; case &quot;inventors&quot; -&gt; new ArrayList&lt;&gt;(p.getInventors());</b>
<b class="nc">&nbsp; case &quot;builders&quot; -&gt; new ArrayList&lt;&gt;(p.getBuilders());</b>
<b class="nc">&nbsp; case &quot;shamans&quot; -&gt; new ArrayList&lt;&gt;(p.getShamans());</b>
<b class="nc">&nbsp; case &quot;hunters&quot; -&gt; new ArrayList&lt;&gt;(p.getHunters());</b>
<b class="nc">&nbsp; case &quot;buildingCards&quot; -&gt; new ArrayList&lt;&gt;(p.getBuildingCards());</b>
<b class="nc">&nbsp; default -&gt; new ArrayList&lt;&gt;();</b>
&nbsp; };
&nbsp; }
&nbsp;
&nbsp; // ==== BACKGROUND ====
&nbsp; /** Sets the full-cover background image on the root pane. */
&nbsp; private void renderBackground() {
<b class="nc">&nbsp; BackgroundSize size = new BackgroundSize(</b>
&nbsp; BackgroundSize.AUTO, BackgroundSize.AUTO,
&nbsp; false, false, true, true
&nbsp; );
<b class="nc">&nbsp; rootPane.setBackground(new Background(new BackgroundImage(</b>
<b class="nc">&nbsp; loadImage(&quot;/GUIImages/Background.png&quot;),</b>
&nbsp; BackgroundRepeat.NO_REPEAT,
&nbsp; BackgroundRepeat.NO_REPEAT,
&nbsp; BackgroundPosition.CENTER,
&nbsp; size
&nbsp; )));
&nbsp; }
&nbsp;
&nbsp;
&nbsp; // ==== ACTIONS ====
&nbsp; /** Disconnects the client and invokes the post-game action to return to the login scene. */
&nbsp; @FXML
&nbsp; private void onNewGame() {
<b class="nc">&nbsp; controller.disconnect();</b>
<b class="nc">&nbsp; action.run();</b>
&nbsp; }
&nbsp;}
</code>
</pre>
</div>
<script type="text/javascript">
(function() {
var msie = false, msie9 = false;
/*@cc_on
msie = true;
@if (@_jscript_version >= 9)
msie9 = true;
@end
@*/
if (!msie || msie && msie9) {
hljs.highlightAll()
hljs.initLineNumbersOnLoad();
}
})();
</script>
<div class="footer">
<div style="float:right;">generated on 2026-06-19 22:53</div>
</div>
</body>
</html>