LetterTileGroup.java
package com.example.project.controllers.gameScreens;
import com.example.project.controllers.tileViewControllers.EmptyTileController;
import com.example.project.controllers.tileViewControllers.LetterTileController;
import com.example.project.models.tiles.EmptyTileSlot;
import com.example.project.models.tiles.LetterTile;
import com.example.project.services.TileLoader;
import javafx.beans.property.ReadOnlyListProperty;
import javafx.collections.ObservableList;
import javafx.scene.layout.Pane;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* tile group that observes an observable list and updates the ui Tile Controller's nodes into their EmptyTileController nodes.
*/
public class LetterTileGroup
{
private final List<EmptyTileController> tileSlots = new ArrayList<>();
private final List<LetterTileController> tileControllers = new ArrayList<>();
private final Pane container;
private final int numberOfEmptyTileSlots;
private final Consumer<LetterTileController> onClickHandler;
/**
* Gets the groups tile controllers.
* @return the letter tile groups controllers
*/
public List<LetterTileController> getControllers(){
return tileControllers;
}
/**
* Constructor
* @param numberOfEmptyTileSlots number of max tiles in group (empty slots)
* @param container container to place all in.
* @param observedList the observed list.
* @param onClickHandler On tile click action.
* @param afterSyncActions additional synchronisation actions that need to happen when this observed list changes.
*/
public LetterTileGroup(int numberOfEmptyTileSlots, Pane container,
ReadOnlyListProperty<LetterTile> observedList,
Consumer<LetterTileController> onClickHandler,
List<Runnable> afterSyncActions)
{
this(numberOfEmptyTileSlots, container, observedList, onClickHandler);
observedList.addListener((obs, oldVal, newVal) -> {
afterSyncActions.forEach(Runnable::run);
});
}
/**
* Constructor
* @param numberOfEmptyTileSlots number of max tiles in group (empty slots)
* @param container container to place all in.
* @param observedList the observed list.
* @param onClickHandler On tile click action.
*/
public LetterTileGroup(int numberOfEmptyTileSlots, Pane container,
ReadOnlyListProperty<LetterTile> observedList,
Consumer<LetterTileController> onClickHandler)
{
this.container = container;
this.numberOfEmptyTileSlots = numberOfEmptyTileSlots;
this.onClickHandler = onClickHandler;
createEmptySlots();
observedList.addListener((obs, oldVal, newVal) -> {
syncLetterTiles(newVal);
});
syncLetterTiles(observedList);
}
/**
* Create empty slots for both word area and tile rack
*/
private void createEmptySlots()
{
for (var i = 0; i < numberOfEmptyTileSlots; i++)
{
var emptyTileController = loadEmptySlotIntoContainer();
tileSlots.add(emptyTileController);
}
}
/**
* Load a new empty slot into a container
*/
private EmptyTileController loadEmptySlotIntoContainer()
{
var emptyTile = new EmptyTileSlot();
EmptyTileController controller = TileLoader.createEmptyTileController(emptyTile);
container.getChildren().add(controller.getRoot());
return controller;
}
/**
* Regenerate letter tiles as observed from the model.
*/
private void syncLetterTiles(ObservableList<LetterTile> modelList)
{
tileControllers.clear();
for (LetterTile tile : modelList)
{
var controller = TileLoader.createLetterTile(tile);
controller.getRoot().setOnMouseClicked(e -> onClickHandler.accept(controller));
tileControllers.add(controller);
}
// Clear all word area slots
for (EmptyTileController rowsEmptyTile : tileSlots) {
rowsEmptyTile.clearLetterTile();
}
for (int i = 0; i < tileControllers.size(); i++){
tileSlots.get(i).setLetter(tileControllers.get(i));
}
}
}