#23: Creating Custom ListCell<T> for Ingredients
This commit is contained in:
parent
c7d60802ab
commit
71fd693f37
1 changed files with 92 additions and 0 deletions
|
@ -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<Ingredient> {
|
||||||
|
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<? extends String> observable, String oldValue, String newValue) {
|
||||||
|
getItem().setName(textField.getText());
|
||||||
|
|
||||||
|
textField.setMinWidth(getTextFieldRequiredWidth(textField));
|
||||||
|
|
||||||
|
ListView<Ingredient> 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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue