From f645e0d40067bdde2af4505d587aec258dedb291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20S=C3=A4ume?= Date: Fri, 17 May 2024 12:06:33 +0200 Subject: [PATCH] #18: Creating Custom ListCell for Ingredients --- .../nhplus/medication/IngredientListCell.java | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/main/java/de/hitec/nhplus/medication/IngredientListCell.java diff --git a/src/main/java/de/hitec/nhplus/medication/IngredientListCell.java b/src/main/java/de/hitec/nhplus/medication/IngredientListCell.java new file mode 100644 index 0000000..0e15a32 --- /dev/null +++ b/src/main/java/de/hitec/nhplus/medication/IngredientListCell.java @@ -0,0 +1,92 @@ +package de.hitec.nhplus.medication; + +import javafx.beans.value.ObservableValue; +import javafx.geometry.Insets; +import javafx.scene.control.Button; +import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; +import javafx.scene.control.TextField; +import javafx.scene.layout.BorderPane; +import javafx.scene.text.Text; + +public class IngredientListCell extends ListCell { + private final TextField textField; + private final Button deleteButton; + + private static final double BUILTIN_BORDER_WIDTH = 1; + private static final double CELL_SPACING = 4; + private static final double CELL_PADDING = 4; + private static final double BUTTON_PADDING_X = 8; + private static final double BUTTON_PADDING_Y = 4; + private final double totalSpacing; + + public IngredientListCell() { + this.setPadding(new Insets(CELL_PADDING)); + + textField = new TextField(); + textField.setPromptText("Inhaltsstoff"); + textField.textProperty().addListener(this::onTextFieldUpdate); + + deleteButton = new Button("-"); + deleteButton.setPadding(new Insets( + BUTTON_PADDING_Y, + BUTTON_PADDING_X, + BUTTON_PADDING_Y, + BUTTON_PADDING_X + )); + deleteButton.setOnAction(event -> getListView().getItems().remove(this)); + + // Calculate Delete Button Width + Text textNode = new Text(deleteButton.getText()); + textNode.setFont(deleteButton.getFont()); + double calculatedDeleteButtonWidth = textNode.getLayoutBounds().getWidth() + BUTTON_PADDING_X * 2; + + totalSpacing = BUILTIN_BORDER_WIDTH * 2 // List View + + CELL_PADDING * 2 + + CELL_SPACING + + calculatedDeleteButtonWidth; + } + + @Override + protected void updateItem(Ingredient item, boolean empty) { + super.updateItem(item, empty); + if (empty || item == null) { + setGraphic(null); + } else { + String oldText = textField.getText(); + String newText = oldText != null && !oldText.isEmpty() ? oldText : item.getName(); + textField.setText(newText); + + BorderPane cellPane = new BorderPane(); + cellPane.setCenter(textField); + cellPane.setRight(deleteButton); + BorderPane.setMargin(deleteButton, new Insets(0, 0, 0, CELL_SPACING)); + setGraphic(cellPane); + } + } + + private void onTextFieldUpdate(ObservableValue observable, String oldValue, String newValue) { + getItem().setName(textField.getText()); + + textField.setMinWidth(getTextFieldRequiredWidth(textField)); + + ListView listView = getListView(); + double max = listView.lookupAll("*") + .stream() + .filter(node -> node instanceof IngredientListCell) + .mapToDouble(node -> getTextFieldRequiredWidth(((IngredientListCell) node).textField)) + .max() + .orElse(0); + + getListView().setMinWidth(max + totalSpacing); + } + + private double getTextFieldRequiredWidth(TextField textField) { + Text textNode = new Text(textField.getText()); + textNode.setFont(textField.getFont()); + return textNode.getLayoutBounds().getWidth() + + textField.getPadding().getLeft() + + textField.getPadding().getRight() + + BUILTIN_BORDER_WIDTH * 2; + } +}