mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-22 07:30:24 +00:00
Rework comboboxes
This commit is contained in:
parent
aee7b65bce
commit
0f9cae0681
6 changed files with 41 additions and 406 deletions
|
@ -1,17 +1,16 @@
|
|||
package io.xpipe.app.comp.store;
|
||||
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.ext.DataStoreProvider;
|
||||
import io.xpipe.app.ext.DataStoreProviders;
|
||||
import io.xpipe.app.fxcomps.Comp;
|
||||
import io.xpipe.app.fxcomps.CompStructure;
|
||||
import io.xpipe.app.fxcomps.SimpleCompStructure;
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
import io.xpipe.app.util.CustomComboBoxBuilder;
|
||||
import io.xpipe.app.util.JfxHelper;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.ListCell;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.layout.Region;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
@ -19,27 +18,23 @@ import lombok.experimental.FieldDefaults;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
|
||||
@AllArgsConstructor
|
||||
public class DsStoreProviderChoiceComp extends Comp<CompStructure<ComboBox<Node>>> {
|
||||
public class DataStoreProviderChoiceComp extends Comp<CompStructure<ComboBox<DataStoreProvider>>> {
|
||||
|
||||
Predicate<DataStoreProvider> filter;
|
||||
Property<DataStoreProvider> provider;
|
||||
boolean staticDisplay;
|
||||
|
||||
private Region createDefaultNode() {
|
||||
return JfxHelper.createNamedEntry(
|
||||
AppI18n.get("selectType"), AppI18n.get("selectTypeDescription"), "connection_icon.svg");
|
||||
}
|
||||
|
||||
private List<DataStoreProvider> getProviders() {
|
||||
return DataStoreProviders.getAll().stream().filter(filter).toList();
|
||||
}
|
||||
|
||||
private Region createGraphic(DataStoreProvider provider) {
|
||||
if (provider == null) {
|
||||
return createDefaultNode();
|
||||
return null;
|
||||
}
|
||||
|
||||
var graphic = provider.getDisplayIconFileName(null);
|
||||
|
@ -47,20 +42,40 @@ public class DsStoreProviderChoiceComp extends Comp<CompStructure<ComboBox<Node>
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompStructure<ComboBox<Node>> createBase() {
|
||||
var comboBox = new CustomComboBoxBuilder<>(provider, this::createGraphic, createDefaultNode(), v -> true);
|
||||
comboBox.setAccessibleNames(dataStoreProvider -> dataStoreProvider.getDisplayName());
|
||||
public CompStructure<ComboBox<DataStoreProvider>> createBase() {
|
||||
Supplier<ListCell<DataStoreProvider>> cellFactory = () -> new ListCell<>() {
|
||||
@Override
|
||||
protected void updateItem(DataStoreProvider item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
setGraphic(createGraphic(item));
|
||||
setAccessibleText(item != null ? item.getDisplayName() : null);
|
||||
setAccessibleHelp(item != null ? item.getDisplayDescription() : null);
|
||||
}
|
||||
};
|
||||
var cb = new ComboBox<DataStoreProvider>();
|
||||
cb.setCellFactory(param -> {
|
||||
return cellFactory.get();
|
||||
});
|
||||
cb.setButtonCell(cellFactory.get());
|
||||
var l = getProviders().stream()
|
||||
.filter(p -> AppPrefs.get().developerShowHiddenProviders().get() || p.getCreationCategory() != null || staticDisplay).toList();
|
||||
l
|
||||
.forEach(comboBox::add);
|
||||
if (l.size() == 1) {
|
||||
provider.setValue(l.get(0));
|
||||
.filter(p -> AppPrefs.get().developerShowHiddenProviders().get() || p.getCreationCategory() != null || staticDisplay)
|
||||
.toList();
|
||||
l.forEach(dataStoreProvider -> cb.getItems().add(dataStoreProvider));
|
||||
if (provider.getValue() == null) {
|
||||
provider.setValue(l.getFirst());
|
||||
}
|
||||
ComboBox<Node> cb = comboBox.build();
|
||||
cb.getStyleClass().add("data-source-type");
|
||||
cb.setValue(provider.getValue());
|
||||
provider.bind(cb.valueProperty());
|
||||
cb.getStyleClass().add("choice-comp");
|
||||
cb.setAccessibleText("Choose connection type");
|
||||
cb.setOnKeyPressed(event -> {
|
||||
if (!event.getCode().equals(KeyCode.ENTER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
cb.show();
|
||||
event.consume();
|
||||
});
|
||||
return new SimpleCompStructure<>(cb);
|
||||
}
|
||||
}
|
|
@ -276,7 +276,7 @@ public class GuiDsStoreCreator extends MultiStepComp.Step<CompStructure<?>> {
|
|||
var layout = new BorderPane();
|
||||
layout.getStyleClass().add("store-creator");
|
||||
layout.setPadding(new Insets(20));
|
||||
var providerChoice = new DsStoreProviderChoiceComp(filter, provider, staticDisplay);
|
||||
var providerChoice = new DataStoreProviderChoiceComp(filter, provider, staticDisplay);
|
||||
if (staticDisplay) {
|
||||
providerChoice.apply(struc -> struc.get().setDisable(true));
|
||||
}
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
package io.xpipe.app.fxcomps.impl;
|
||||
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.fxcomps.SimpleComp;
|
||||
import io.xpipe.app.util.CustomComboBoxBuilder;
|
||||
import io.xpipe.core.charsetter.StreamCharset;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.Region;
|
||||
|
||||
public class CharsetChoiceComp extends SimpleComp {
|
||||
|
||||
private final Property<StreamCharset> charset;
|
||||
|
||||
public CharsetChoiceComp(Property<StreamCharset> charset) {
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Region createSimple() {
|
||||
var builder = new CustomComboBoxBuilder<>(
|
||||
charset,
|
||||
streamCharset -> {
|
||||
return new Label(streamCharset.getCharset().displayName()
|
||||
+ (streamCharset.hasByteOrderMark() ? " (BOM)" : ""));
|
||||
},
|
||||
new Label(AppI18n.get("app.none")),
|
||||
null);
|
||||
builder.setAccessibleNames(streamCharset -> streamCharset.getNames().get(0));
|
||||
builder.addFilter((charset, filter) -> {
|
||||
return charset.getCharset().displayName().contains(filter);
|
||||
});
|
||||
builder.addHeader(AppI18n.get("app.common"));
|
||||
for (var e : StreamCharset.COMMON) {
|
||||
builder.add(e);
|
||||
}
|
||||
|
||||
builder.addHeader(AppI18n.get("app.other"));
|
||||
for (var e : StreamCharset.RARE) {
|
||||
builder.add(e);
|
||||
}
|
||||
var comboBox = builder.build();
|
||||
comboBox.setVisibleRowCount(16);
|
||||
return comboBox;
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@ import io.xpipe.app.fxcomps.util.SimpleChangeListener;
|
|||
import io.xpipe.app.storage.DataStoreEntryRef;
|
||||
import io.xpipe.core.store.FileSystemStore;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
@ -18,14 +17,12 @@ import org.kordamp.ikonli.javafx.FontIcon;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
public class FileReferenceChoiceComp extends SimpleComp {
|
||||
public class ContextualFileReferenceChoiceComp extends SimpleComp {
|
||||
|
||||
private final boolean hideFileSystem;
|
||||
private final Property<DataStoreEntryRef<? extends FileSystemStore>> fileSystem;
|
||||
private final Property<String> filePath;
|
||||
|
||||
public <T extends FileSystemStore> FileReferenceChoiceComp(ObservableValue<DataStoreEntryRef<T>> fileSystem, Property<String> filePath) {
|
||||
this.hideFileSystem = true;
|
||||
public <T extends FileSystemStore> ContextualFileReferenceChoiceComp(ObservableValue<DataStoreEntryRef<T>> fileSystem, Property<String> filePath) {
|
||||
this.fileSystem = new SimpleObjectProperty<>();
|
||||
SimpleChangeListener.apply(fileSystem, val -> {
|
||||
this.fileSystem.setValue(val);
|
||||
|
@ -33,27 +30,15 @@ public class FileReferenceChoiceComp extends SimpleComp {
|
|||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
public FileReferenceChoiceComp(boolean hideFileSystem, Property<DataStoreEntryRef<? extends FileSystemStore>> fileSystem, Property<String> filePath) {
|
||||
this.hideFileSystem = hideFileSystem;
|
||||
this.fileSystem = fileSystem != null ? fileSystem : new SimpleObjectProperty<>();
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Region createSimple() {
|
||||
var fileSystemChoiceComp =
|
||||
new FileSystemStoreChoiceComp(fileSystem).grow(false, true).styleClass(Styles.LEFT_PILL);
|
||||
if (hideFileSystem) {
|
||||
fileSystemChoiceComp.hide(new SimpleBooleanProperty(true));
|
||||
}
|
||||
|
||||
var fileNameComp = new TextFieldComp(filePath)
|
||||
.apply(struc -> HBox.setHgrow(struc.get(), Priority.ALWAYS))
|
||||
.styleClass(hideFileSystem ? Styles.LEFT_PILL : Styles.CENTER_PILL)
|
||||
.styleClass(Styles.LEFT_PILL)
|
||||
.grow(false, true);
|
||||
|
||||
var fileBrowseButton = new ButtonComp(null, new FontIcon("mdi2f-folder-open-outline"), () -> {
|
||||
StandaloneFileBrowser.openSingleFile(() -> hideFileSystem ? fileSystem.getValue() : null, fileStore -> {
|
||||
StandaloneFileBrowser.openSingleFile(() -> fileSystem.getValue(), fileStore -> {
|
||||
if (fileStore == null) {
|
||||
filePath.setValue(null);
|
||||
fileSystem.setValue(null);
|
||||
|
@ -66,7 +51,7 @@ public class FileReferenceChoiceComp extends SimpleComp {
|
|||
.styleClass(Styles.RIGHT_PILL)
|
||||
.grow(false, true);
|
||||
|
||||
var layout = new HorizontalComp(List.of(fileSystemChoiceComp, fileNameComp, fileBrowseButton))
|
||||
var layout = new HorizontalComp(List.of(fileNameComp, fileBrowseButton))
|
||||
.apply(struc -> struc.get().setFillHeight(true));
|
||||
|
||||
layout.apply(struc -> {
|
|
@ -1,53 +0,0 @@
|
|||
package io.xpipe.app.fxcomps.impl;
|
||||
|
||||
import io.xpipe.app.fxcomps.SimpleComp;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.app.storage.DataStoreEntry;
|
||||
import io.xpipe.app.storage.DataStoreEntryRef;
|
||||
import io.xpipe.app.util.CustomComboBoxBuilder;
|
||||
import io.xpipe.core.store.FileSystemStore;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.Region;
|
||||
|
||||
public class FileSystemStoreChoiceComp extends SimpleComp {
|
||||
|
||||
private final Property<DataStoreEntryRef<? extends FileSystemStore>> selected;
|
||||
|
||||
public FileSystemStoreChoiceComp(Property<DataStoreEntryRef<? extends FileSystemStore>> selected) {
|
||||
this.selected = selected;
|
||||
}
|
||||
|
||||
private static String getName(DataStoreEntryRef<? extends FileSystemStore> store) {
|
||||
return store.get().getName();
|
||||
}
|
||||
|
||||
private Region createGraphic(DataStoreEntryRef<? extends FileSystemStore> s) {
|
||||
var provider = s.get().getProvider();
|
||||
var img = PrettyImageHelper.ofFixedSquare(provider.getDisplayIconFileName(s.getStore()), 16);
|
||||
return new Label(getName(s), img.createRegion());
|
||||
}
|
||||
|
||||
private Region createDisplayGraphic(DataStoreEntryRef<? extends FileSystemStore> s) {
|
||||
var provider = s.get().getProvider();
|
||||
var img = PrettyImageHelper.ofFixedSquare(provider.getDisplayIconFileName(s.getStore()), 16);
|
||||
return new Label(null, img.createRegion());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Region createSimple() {
|
||||
var comboBox = new CustomComboBoxBuilder<>(selected, this::createGraphic, null, v -> true);
|
||||
comboBox.setAccessibleNames(FileSystemStoreChoiceComp::getName);
|
||||
comboBox.setSelectedDisplay(this::createDisplayGraphic);
|
||||
DataStorage.get().getUsableEntries().stream()
|
||||
.filter(e -> e.getStore() instanceof FileSystemStore)
|
||||
.map(DataStoreEntry::<FileSystemStore>ref)
|
||||
.forEach(comboBox::add);
|
||||
ComboBox<Node> cb = comboBox.build();
|
||||
cb.getStyleClass().add("choice-comp");
|
||||
cb.setMaxWidth(45);
|
||||
return cb;
|
||||
}
|
||||
}
|
|
@ -1,266 +0,0 @@
|
|||
package io.xpipe.app.util;
|
||||
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.fxcomps.impl.FilterComp;
|
||||
import io.xpipe.app.fxcomps.util.SimpleChangeListener;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.geometry.Orientation;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ListCell;
|
||||
import javafx.scene.control.Separator;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class CustomComboBoxBuilder<T> {
|
||||
|
||||
private final Property<T> selected;
|
||||
private final Function<T, Node> nodeFunction;
|
||||
private ObservableValue<String> emptyAccessibilityName = AppI18n.observable("none");
|
||||
private Function<T, String> accessibleNameFunction;
|
||||
private Function<T, Node> selectedDisplayNodeFunction;
|
||||
private final Map<Node, T> nodeMap = new HashMap<>();
|
||||
private final Map<Node, Runnable> actionsMap = new HashMap<>();
|
||||
private final List<Node> nodes = new ArrayList<>();
|
||||
private final Set<Node> disabledNodes = new HashSet<>();
|
||||
private final Node emptyNode;
|
||||
private final Predicate<T> veto;
|
||||
private final Property<String> filterString = new SimpleStringProperty();
|
||||
private final List<T> filterable = new ArrayList<>();
|
||||
private BiPredicate<T, String> filterPredicate;
|
||||
private Node filterNode;
|
||||
private Function<T, Node> unknownNode;
|
||||
|
||||
public CustomComboBoxBuilder(
|
||||
Property<T> selected, Function<T, Node> nodeFunction, Node emptyNode, Predicate<T> veto) {
|
||||
this.selected = selected;
|
||||
this.nodeFunction = nodeFunction;
|
||||
this.selectedDisplayNodeFunction = nodeFunction;
|
||||
this.emptyNode = emptyNode;
|
||||
this.veto = veto;
|
||||
}
|
||||
|
||||
public void setSelectedDisplay(Function<T, Node> nodeFunction) {
|
||||
selectedDisplayNodeFunction = nodeFunction;
|
||||
}
|
||||
|
||||
public void setAccessibleNames(Function<T, String> function) {
|
||||
accessibleNameFunction = function;
|
||||
}
|
||||
|
||||
public void setEmptyAccessibilityName(ObservableValue<String> n) {
|
||||
emptyAccessibilityName = n;
|
||||
}
|
||||
|
||||
public void addAction(Node node, Runnable run) {
|
||||
nodes.add(node);
|
||||
actionsMap.put(node, run);
|
||||
}
|
||||
|
||||
public void disable(Node node) {
|
||||
disabledNodes.add(node);
|
||||
}
|
||||
|
||||
public void setUnknownNode(Function<T, Node> node) {
|
||||
unknownNode = node;
|
||||
}
|
||||
|
||||
public Node add(T val) {
|
||||
var node = nodeFunction.apply(val);
|
||||
nodeMap.put(node, val);
|
||||
nodes.add(node);
|
||||
if (filterPredicate != null) {
|
||||
filterable.add(val);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
public void addSeparator() {
|
||||
var sep = new Separator(Orientation.HORIZONTAL);
|
||||
nodes.add(sep);
|
||||
disabledNodes.add(sep);
|
||||
}
|
||||
|
||||
public void addHeader(String name) {
|
||||
var spacer = new Region();
|
||||
spacer.setPrefHeight(10);
|
||||
var header = new Label(name);
|
||||
header.setAlignment(Pos.CENTER);
|
||||
var v = new VBox(spacer, header, new Separator(Orientation.HORIZONTAL));
|
||||
v.setAccessibleText(name);
|
||||
v.setAlignment(Pos.CENTER);
|
||||
nodes.add(v);
|
||||
disabledNodes.add(v);
|
||||
}
|
||||
|
||||
public void addFilter(BiPredicate<T, String> filterPredicate) {
|
||||
this.filterPredicate = filterPredicate;
|
||||
|
||||
var spacer = new Region();
|
||||
spacer.setPrefHeight(10);
|
||||
var header = new FilterComp(filterString).createStructure();
|
||||
var v = new VBox(header.get());
|
||||
v.setAlignment(Pos.CENTER);
|
||||
nodes.add(v);
|
||||
filterNode = header.getText();
|
||||
}
|
||||
|
||||
public ComboBox<Node> build() {
|
||||
var cb = new ComboBox<Node>();
|
||||
cb.getItems().addAll(nodes);
|
||||
|
||||
cb.setCellFactory((lv) -> {
|
||||
return new Cell();
|
||||
});
|
||||
cb.setButtonCell(new SelectedCell());
|
||||
SimpleChangeListener.apply(selected, c -> {
|
||||
var item = nodeMap.entrySet().stream()
|
||||
.filter(e -> Objects.equals(c, e.getValue()))
|
||||
.map(e -> e.getKey())
|
||||
.findAny()
|
||||
.orElse(c == null || unknownNode == null ? emptyNode : unknownNode.apply(c));
|
||||
cb.setValue(item);
|
||||
});
|
||||
cb.valueProperty().addListener((c, o, n) -> {
|
||||
if (nodeMap.containsKey(n)) {
|
||||
if (veto != null && !veto.test(nodeMap.get(n))) {
|
||||
return;
|
||||
}
|
||||
selected.setValue(nodeMap.get(n));
|
||||
}
|
||||
|
||||
if (actionsMap.containsKey(n)) {
|
||||
cb.setValue(o);
|
||||
actionsMap.get(n).run();
|
||||
}
|
||||
});
|
||||
|
||||
if (filterPredicate != null) {
|
||||
SimpleChangeListener.apply(filterString, c -> {
|
||||
var filteredNodes = nodes.stream()
|
||||
.filter(e -> e.equals(cb.getValue())
|
||||
|| !(nodeMap.get(e) != null
|
||||
&& (filterable.contains(nodeMap.get(e))
|
||||
&& filterString.getValue() != null
|
||||
&& !filterPredicate.test(nodeMap.get(e), c))))
|
||||
.toList();
|
||||
cb.setItems(FXCollections.observableList(filteredNodes));
|
||||
});
|
||||
|
||||
filterNode.sceneProperty().addListener((c, o, n) -> {
|
||||
if (n != null) {
|
||||
n.getWindow().focusedProperty().addListener((c2, o2, n2) -> {
|
||||
Platform.runLater(() -> {
|
||||
filterNode.requestFocus();
|
||||
});
|
||||
});
|
||||
}
|
||||
Platform.runLater(() -> {
|
||||
filterNode.requestFocus();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (emptyNode != null) {
|
||||
emptyNode.setAccessibleText(emptyAccessibilityName.getValue());
|
||||
}
|
||||
if (accessibleNameFunction != null) {
|
||||
nodes.forEach(node -> node.setAccessibleText(accessibleNameFunction.apply(nodeMap.get(node))));
|
||||
}
|
||||
|
||||
return cb;
|
||||
}
|
||||
|
||||
private class SelectedCell extends ListCell<Node> {
|
||||
|
||||
@Override
|
||||
protected void updateItem(Node item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
accessibleTextProperty().unbind();
|
||||
if (empty || item.equals(emptyNode)) {
|
||||
if (emptyAccessibilityName != null) {
|
||||
accessibleTextProperty().bind(emptyAccessibilityName);
|
||||
} else {
|
||||
setAccessibleText(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.equals(emptyNode)) {
|
||||
setGraphic(item);
|
||||
return;
|
||||
}
|
||||
|
||||
// Case for dynamically created unknown nodes
|
||||
if (!nodeMap.containsKey(item)) {
|
||||
setGraphic(item);
|
||||
// Don't expect the accessible name function to properly map this item
|
||||
setAccessibleText(null);
|
||||
return;
|
||||
}
|
||||
|
||||
var val = nodeMap.get(item);
|
||||
var newNode = selectedDisplayNodeFunction.apply(val);
|
||||
setGraphic(newNode);
|
||||
setAccessibleText(newNode.getAccessibleText());
|
||||
}
|
||||
}
|
||||
|
||||
private class Cell extends ListCell<Node> {
|
||||
|
||||
public Cell() {
|
||||
addEventFilter(MouseEvent.MOUSE_PRESSED, event -> {
|
||||
if (!nodeMap.containsKey(getItem())) {
|
||||
event.consume();
|
||||
}
|
||||
});
|
||||
addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
||||
if (event.getCode() == KeyCode.ENTER && !nodeMap.containsKey(getItem())) {
|
||||
event.consume();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateItem(Node item, boolean empty) {
|
||||
setGraphic(item);
|
||||
if (getItem() == item) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.updateItem(item, empty);
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
setGraphic(item);
|
||||
if (disabledNodes.contains(item)) {
|
||||
this.setDisable(true);
|
||||
this.setFocusTraversable(false);
|
||||
// this.setPadding(Insets.EMPTY);
|
||||
} else {
|
||||
this.setDisable(false);
|
||||
this.setFocusTraversable(true);
|
||||
setAccessibleText(item.getAccessibleText());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue