package regexgolf2.ui.util; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.ContentDisplay; import javafx.scene.control.ListCell; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import regexgolf2.ui.subcomponents.editablelabel.EditableLabel; /** * The EditableListCell consists of two main UI components. On the left is the * editable Label and on the right is a Panel that can be filled by Subclasses * via the {@link #setContent(Node)} method. To access the text of the editable * Label, simply use the {@link #textProperty()}. */ public class EditableListCell<T> extends ListCell<T> { private HBox _rootNode; private EditableLabel _editLabel; private AnchorPane _extraContentPanel; public EditableListCell() { initComponents(); this.setPrefWidth(0.0); _rootNode.prefWidthProperty().bind(this.widthProperty().subtract(10)); this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY); } private void initComponents() { _editLabel = new EditableLabel(); _editLabel.editableProperty().bind(this.editableProperty()); _editLabel.editIconAppearsProperty().bind(this.hoverProperty()); _editLabel.textProperty().bindBidirectional(this.textProperty()); // If editLabel exits editmode, commit edit. _editLabel.editModeProperty().addListener((o, oV, editMode) -> { if (!editMode) EditableListCell.this.commitEdit(EditableListCell.this.getItem()); }); _extraContentPanel = new AnchorPane(); HBox.setHgrow(_editLabel.getUINode(), Priority.ALWAYS); _rootNode = new HBox(_editLabel.getUINode(), _extraContentPanel); _rootNode.setAlignment(Pos.CENTER); } /** * Sets the content for the Panel to the right of the editable Label. * * @param node * The content node, or null to clear the Panel. */ protected void setContent(Node node) { JavafxUtil.setAsContent(node, _extraContentPanel); } /** * This method is called if the item changes. Inside this method, every * Property that was bound to the Item somehow; should unbind again. * {@link #getItem()} will not return null, it is save to call. */ protected void unbind() { } /** * This method is called after the item was updated. If you need to make * bindings to the item, do them here. */ protected void bind() { } @Override public final void startEdit() { super.startEdit(); _editLabel.tryEnterEditMode(); } @Override protected final void updateItem(T item, boolean empty) { // If the new item is equal to the current, we only call super if (item == getItem()) { super.updateItem(item, empty); return; } if (getItem() != null) unbind(); super.updateItem(item, empty); if (getItem() != null) bind(); if (getItem() != null) setGraphic(_rootNode); else setGraphic(null); } }