#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