UICompositor.java
package edu.ntnu.idi.idatt.view.components.ui;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
import java.util.function.Consumer;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
/**
* UICompositor class
*
* <p>
* Builder class for simpler UI layout creation.
* </p>
*/
public class UICompositor {
private final Pane parent;
/**
* Constructor for UICompositor.
*
* @param builder - UICompositor.Builder object.
*/
public UICompositor(Builder builder) {
this.parent = builder.parent;
}
/**
* Method for obtaining the root element.
*
* @return root pane.
*/
public Parent makeUI() {
return parent;
}
/**
* Builder class for UICompositor instances.
*/
public static class Builder {
private Pane parent;
private Deque<Pane> wrappers = new ArrayDeque<>();
/**
* Setter for UICompositor parent/root element.
*
* @param parent - Root element
* @return Builder - self
*/
public Builder parent(Pane parent) {
this.parent = parent;
return this;
}
/**
* Method for streching a node and positioning within.
*
* <p>
* Works for HBox and VBox instances.
*
* @param position - Position of inner nodes.
* @return builder - self.
*/
public Builder growWithAlignment(Pos position) {
Pane root = getRoot();
if (root instanceof HBox) {
((HBox) root).setAlignment(position);
root.setMaxWidth(Double.MAX_VALUE);
HBox.setHgrow(root, Priority.ALWAYS);
}
if (root instanceof VBox) {
((VBox) root).setAlignment(position);
root.setMaxHeight(Double.MAX_VALUE);
VBox.setVgrow(root, Priority.ALWAYS);
}
return this;
}
/**
* Method for obtaining newest layout node on the stack.
*
* @return newest element on the stack.
*/
private Pane getRoot() {
return wrappers.isEmpty() ? parent : wrappers.peek();
}
/**
* Method for adding content to newest stack element.
*
* @param child - Node/content
* @return bulder - self.
*/
public Builder addContent(Parent child) {
Pane root = getRoot();
root.getChildren().add(child);
return this;
}
/**
* Method for adding multiple contents to newest stack element.
*
* @param children - array of nodes/content.
* @return builder - self.
*/
public Builder addAllContent(Parent... children) {
Pane root = getRoot();
root.getChildren().addAll(List.of(children));
return this;
}
/**
* Method for adding a layer to the stack.
*
* @param wrapper - Pane type.
* @return builder - self.
*/
public Builder wrap(Pane wrapper) {
wrappers.push(wrapper);
return this;
}
/**
* Method for adding newest stack element to previous on stack element.
*
* @return builder - self.
*/
public Builder unwrap() {
Pane current = wrappers.pop();
if (wrappers.isEmpty()) {
parent.getChildren().add(current);
} else {
wrappers.peek().getChildren().add(current);
}
return this;
}
/**
* Method for changing newest stack element properties.
*
* @param handle - Functional interface with reference to newest stack element.
* @return builder - self.
*/
public Builder properties(Consumer<Pane> handle) {
handle.accept(getRoot());
return this;
}
/**
* Method for adding filler to newest stack element.
*
* <p>
* Creates a filler for layered stack elements type HBox, VBox.
* </p>
*
* @return builder = self.
*/
public Builder filler() {
Pane root = getRoot();
Region filler = new Region();
if (root instanceof HBox) {
HBox.setHgrow(filler, Priority.ALWAYS);
}
if (root instanceof VBox) {
VBox.setVgrow(filler, Priority.ALWAYS);
}
root.getChildren().add(filler);
return this;
}
/**
* Method for applying the builder method.
*
* @return instance of created UICompositor.
*/
public UICompositor build() {
return new UICompositor(this);
}
}
}