feat: extract abstract OrderedEditableListCell<T>

Abstracts the editable list cell code to make it extendable.

Also includes fix for index (now starts at 1)
This commit is contained in:
Zhongheng Liu 2025-12-04 21:39:55 +01:00
commit 5dd6c89f73
Signed by: steven
GPG key ID: F69B980899C1C09D
4 changed files with 86 additions and 149 deletions

View file

@ -1,78 +1,18 @@
package client.scenes.recipe;
import javafx.scene.control.ListCell;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
/**
* A custom ListCell for displaying and editing ingredients in an
* A custom {@link OrderedEditableListCell<String>} for displaying and editing ingredients in an
* IngredientList. Allows inline editing of ingredient names.
*
* @see IngredientListCtrl
*/
public class IngredientListCell extends ListCell<String> {
public class IngredientListCell extends OrderedEditableListCell<String> {
// TODO: change all this to use actual Ingredient objects
// and all that :)
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
this.setText(null);
} else {
this.setText(item);
}
}
@Override
public void startEdit() {
super.startEdit();
TextField textField = new TextField(this.getItem());
// Commit edit on Enter key press
textField.setOnAction(event -> {
this.commitEdit(textField.getText());
});
// Cancel edit on Escape key press
textField.setOnKeyReleased(event -> {
if (event.getCode() == KeyCode.ESCAPE) {
this.cancelEdit();
}
});
this.setText(null);
this.setGraphic(textField);
}
/**
* Check if the input is valid (non-empty).
*
* @param input The input string to validate.
* @return true if valid, false otherwise.
*/
private boolean isInputValid(String input) {
return input != null && !input.trim().isEmpty();
}
@Override
public void cancelEdit() {
super.cancelEdit();
this.setText(this.getItem());
this.setGraphic(null);
}
@Override
public void commitEdit(String newValue) {
this.setGraphic(null);
if (!isInputValid(newValue)) {
newValue = this.getItem(); // Revert to old value if input is invalid
}
super.commitEdit(newValue);
protected String fromInput(TextField inputField) {
return inputField.getText();
}
}

View file

@ -137,7 +137,7 @@ public class IngredientListCtrl implements Initializable {
this.ingredientListView.setEditable(true);
this.ingredientListView.setCellFactory(
list -> {
return new RecipeStepListCell();
return new IngredientListCell();
});
this.ingredientListView.setOnEditCommit(this::handleIngredientEdit);

View file

@ -0,0 +1,78 @@
package client.scenes.recipe;
import javafx.scene.control.ListCell;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
public abstract class OrderedEditableListCell<T> extends ListCell<T> {
/**
* Get the display text for the given item, prefixed with its index.
* Looks like "1. description".
*
* @param item The description.
* @return The display text.
*/
private String getDisplayText(String item) {
return (this.getIndex() + 1) + ". " + item;
}
@Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
this.setText(null);
} else {
this.setText(this.getDisplayText(item.toString()));
}
}
public void startEdit() {
super.startEdit();
TextField textField = new TextField(this.getItem().toString());
// Commit edit on Enter key press
textField.setOnAction(event -> {
this.commitEdit(fromInput(textField));
});
// Cancel edit on Escape key press
textField.setOnKeyReleased(event -> {
if (event.getCode() == KeyCode.ESCAPE) {
this.cancelEdit();
}
});
this.setText(null);
this.setGraphic(textField);
}
protected abstract T fromInput(TextField inputField);
/**
* Check if the input is valid (non-empty).
*
* @param input The input string to validate.
* @return true if valid, false otherwise.
*/
private boolean isInputValid(String input) {
return input != null && !input.trim().isEmpty();
}
@Override
public void cancelEdit() {
super.cancelEdit();
this.setText(this.getItem().toString());
this.setGraphic(null);
}
@Override
public void commitEdit(T newValue) {
this.setGraphic(null);
if (!isInputValid(newValue.toString())) {
newValue = this.getItem(); // Revert to old value if input is invalid
}
super.commitEdit(newValue);
}
}

View file

@ -1,96 +1,15 @@
package client.scenes.recipe;
import javafx.scene.control.ListCell;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
/**
* A custom ListCell for displaying and editing ingredients in an
* RecipeStepList. Allows inline editing of ingredient names.
*
* @see RecipeStepListCtrl
*/
public class RecipeStepListCell extends ListCell<String> {
/**
* Get the display text for the given item, prefixed with its index.
* Looks like "1. Step description".
*
* @param item The step description.
* @return The display text.
*/
private String getDisplayText(String item) {
return this.getIndex() + ". " + item;
}
/**
* Get the display text for the current item.
* Looks like "1. Step description".
*
* @return The display text.
*/
private String getDisplayText() {
return this.getDisplayText(this.getItem());
}
public class RecipeStepListCell extends OrderedEditableListCell<String> {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
this.setText(null);
} else {
this.setText(this.getDisplayText(item));
}
}
@Override
public void startEdit() {
super.startEdit();
TextField textField = new TextField(this.getItem());
// Commit edit on Enter key press
textField.setOnAction(event -> {
this.commitEdit(textField.getText());
});
// Cancel edit on Escape key press
textField.setOnKeyReleased(event -> {
if (event.getCode() == KeyCode.ESCAPE) {
this.cancelEdit();
}
});
this.setText(null);
this.setGraphic(textField);
}
/**
* Check if the input is valid (non-empty).
*
* @param input The input string to validate.
* @return true if valid, false otherwise.
*/
private boolean isInputValid(String input) {
return input != null && !input.trim().isEmpty();
}
@Override
public void cancelEdit() {
super.cancelEdit();
this.setText(this.getDisplayText());
this.setGraphic(null);
}
@Override
public void commitEdit(String newValue) {
this.setGraphic(null);
if (!isInputValid(newValue)) {
newValue = this.getItem(); // Revert to old value if input is invalid
}
super.commitEdit(newValue);
protected String fromInput(TextField inputField) {
return inputField.getText();
}
}