mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-22 07:30:24 +00:00
Accessibility fixes
This commit is contained in:
parent
2ffea800b5
commit
cc9941e276
11 changed files with 54 additions and 18 deletions
|
@ -1,6 +1,6 @@
|
|||
<img src="https://user-images.githubusercontent.com/72509152/213873342-7638e830-8a95-4b5d-ad3e-5a9a0b4bf538.png" alt="drawing" width="250"/>
|
||||
|
||||
### The remote file browser for professionals
|
||||
### The revolutionary remote file browser for professionals
|
||||
|
||||
XPipe is a brand-new type of remote file browser that works by interacting with your installed command-line programs to establish and utilize local and remote shell connections. This approach makes it much more flexible as it doesn't have to deal with any file system APIs, remote file handling protocols, or libraries at all.
|
||||
|
||||
|
|
|
@ -68,7 +68,8 @@ public class DataSourceTargetChoiceComp extends Comp<CompStructure<ComboBox<Node
|
|||
var addMoreLabel = new Label(AppI18n.get("addMore"), new FontIcon("mdmz-plus"));
|
||||
|
||||
var builder = new CustomComboBoxBuilder<DataSourceTarget>(
|
||||
selectedApplication, app -> createLabel(app), dataSourceTarget -> dataSourceTarget.getName().getValue(), new Label(""), v -> true);
|
||||
selectedApplication, app -> createLabel(app), new Label(""), v -> true);
|
||||
builder.setAccessibleNames(dataSourceTarget -> dataSourceTarget.getName().getValue());
|
||||
|
||||
// builder.addFilter((v, s) -> v.getName().getValue().toLowerCase().contains(s));
|
||||
|
||||
|
|
|
@ -72,7 +72,8 @@ public class DsProviderChoiceComp extends Comp<CompStructure<ComboBox<Node>>> im
|
|||
|
||||
@Override
|
||||
public CompStructure<ComboBox<Node>> createBase() {
|
||||
var comboBox = new CustomComboBoxBuilder<>(provider, this::createGraphic, dataSourceProvider -> dataSourceProvider.getDisplayName(), createDefaultNode(), v -> true);
|
||||
var comboBox = new CustomComboBoxBuilder<>(provider, this::createGraphic, createDefaultNode(), v -> true);
|
||||
comboBox.setAccessibleNames(dataSourceProvider -> dataSourceProvider != null ? dataSourceProvider.getDisplayName() : null);
|
||||
comboBox.add(null);
|
||||
comboBox.addSeparator();
|
||||
comboBox.addFilter((v, s) -> v.getDisplayName().toLowerCase().contains(s.toLowerCase()));
|
||||
|
|
|
@ -30,7 +30,8 @@ public class DsStorageGroupSelector extends SimpleComp {
|
|||
@Override
|
||||
protected ComboBox<Node> createSimple() {
|
||||
var comboBox = new CustomComboBoxBuilder<DataSourceCollection>(
|
||||
selected, DsStorageGroupSelector::createGraphic, dataSourceCollection -> dataSourceCollection.getName(), createGraphic(null), v -> true);
|
||||
selected, DsStorageGroupSelector::createGraphic, createGraphic(null), v -> true);
|
||||
comboBox.setAccessibleNames(dataSourceCollection -> dataSourceCollection.getName());
|
||||
|
||||
DataStorage.get().getSourceCollections().stream()
|
||||
.filter(dataSourceCollection ->
|
||||
|
|
|
@ -50,7 +50,8 @@ public class DsTypeChoiceComp extends Comp<CompStructure<StackPane>> {
|
|||
return;
|
||||
}
|
||||
|
||||
var builder = new CustomComboBoxBuilder<>(selectedType, app -> createLabel(app), dataSourceType -> dataSourceType.toString(), new Label(""), v -> true);
|
||||
var builder = new CustomComboBoxBuilder<>(selectedType, app -> createLabel(app), new Label(""), v -> true);
|
||||
builder.setAccessibleNames(dataSourceType -> dataSourceType.toString());
|
||||
builder.add(provider.getValue().getPrimaryType());
|
||||
|
||||
var list = Arrays.stream(DataSourceType.values())
|
||||
|
|
|
@ -49,7 +49,8 @@ public class DsStoreProviderChoiceComp extends Comp<CompStructure<ComboBox<Node>
|
|||
|
||||
@Override
|
||||
public CompStructure<ComboBox<Node>> createBase() {
|
||||
var comboBox = new CustomComboBoxBuilder<>(provider, this::createGraphic, dataStoreProvider -> dataStoreProvider.getDisplayName(), createDefaultNode(), v -> true);
|
||||
var comboBox = new CustomComboBoxBuilder<>(provider, this::createGraphic, createDefaultNode(), v -> true);
|
||||
comboBox.setAccessibleNames(dataStoreProvider -> dataStoreProvider.getDisplayName());
|
||||
getProviders().stream()
|
||||
.filter(p -> AppPrefs.get().developerShowHiddenProviders().get() || p.shouldShow())
|
||||
.forEach(comboBox::add);
|
||||
|
|
|
@ -24,8 +24,9 @@ public class CharsetChoiceComp extends SimpleComp {
|
|||
return new Label(streamCharset.getCharset().displayName()
|
||||
+ (streamCharset.hasByteOrderMark() ? " (BOM)" : ""));
|
||||
},
|
||||
streamCharset -> streamCharset.getNames().get(0), new Label(AppI18n.get("app.none")),
|
||||
new Label(AppI18n.get("app.none")),
|
||||
null);
|
||||
builder.setAccessibleNames(streamCharset -> streamCharset.getNames().get(0));
|
||||
builder.addFilter((charset, filter) -> {
|
||||
return charset.getCharset().displayName().contains(filter);
|
||||
});
|
||||
|
|
|
@ -96,9 +96,9 @@ public class DataStoreChoiceComp<T extends DataStore> extends SimpleComp {
|
|||
.findFirst()
|
||||
.orElseThrow()
|
||||
.createRegion(),
|
||||
t -> toName(t),
|
||||
new Label(AppI18n.get("none")),
|
||||
n -> true);
|
||||
comboBox.setAccessibleNames(t -> toName(t));
|
||||
comboBox.setSelectedDisplay(t -> createGraphic(t));
|
||||
comboBox.setUnknownNode(t -> createGraphic(t));
|
||||
|
||||
|
|
|
@ -60,7 +60,8 @@ public class FileSystemStoreChoiceComp extends SimpleComp {
|
|||
});
|
||||
|
||||
var comboBox =
|
||||
new CustomComboBoxBuilder<FileSystemStore>(fileSystemProperty, this::createGraphic, store -> getName(store), null, v -> true);
|
||||
new CustomComboBoxBuilder<>(fileSystemProperty, this::createGraphic, null, v -> true);
|
||||
comboBox.setAccessibleNames(store -> getName(store));
|
||||
comboBox.setSelectedDisplay(this::createDisplayGraphic);
|
||||
DataStorage.get().getUsableStores().stream()
|
||||
.filter(e -> e instanceof FileSystemStore)
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
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.binding.Bindings;
|
||||
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;
|
||||
|
@ -26,7 +27,8 @@ public class CustomComboBoxBuilder<T> {
|
|||
|
||||
private final Property<T> selected;
|
||||
private final Function<T, Node> nodeFunction;
|
||||
private final Function<T, String> accessibleNameFunction;
|
||||
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<>();
|
||||
|
@ -41,11 +43,10 @@ public class CustomComboBoxBuilder<T> {
|
|||
private Function<T, Node> unknownNode;
|
||||
|
||||
public CustomComboBoxBuilder(
|
||||
Property<T> selected, Function<T, Node> nodeFunction, Function<T, String> accessibleNameFunction, Node emptyNode, Predicate<T> veto) {
|
||||
Property<T> selected, Function<T, Node> nodeFunction, Node emptyNode, Predicate<T> veto) {
|
||||
this.selected = selected;
|
||||
this.nodeFunction = nodeFunction;
|
||||
this.selectedDisplayNodeFunction = nodeFunction;
|
||||
this.accessibleNameFunction = accessibleNameFunction;
|
||||
this.emptyNode = emptyNode;
|
||||
this.veto = veto;
|
||||
}
|
||||
|
@ -54,6 +55,14 @@ public class CustomComboBoxBuilder<T> {
|
|||
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);
|
||||
|
@ -69,7 +78,6 @@ public class CustomComboBoxBuilder<T> {
|
|||
|
||||
public Node add(T val) {
|
||||
var node = nodeFunction.apply(val);
|
||||
node.setAccessibleText(accessibleNameFunction.apply(val));
|
||||
nodeMap.put(node, val);
|
||||
nodes.add(node);
|
||||
if (filterPredicate != null) {
|
||||
|
@ -110,10 +118,8 @@ public class CustomComboBoxBuilder<T> {
|
|||
|
||||
public ComboBox<Node> build() {
|
||||
var cb = new ComboBox<Node>();
|
||||
cb.accessibleTextProperty().bind(Bindings.createStringBinding(() -> {
|
||||
return selected.getValue() != null ? accessibleNameFunction.apply(selected.getValue()) : null;
|
||||
}, selected));
|
||||
cb.getItems().addAll(nodes);
|
||||
|
||||
cb.setCellFactory((lv) -> {
|
||||
return new Cell();
|
||||
});
|
||||
|
@ -166,6 +172,13 @@ public class CustomComboBoxBuilder<T> {
|
|||
});
|
||||
}
|
||||
|
||||
if (emptyNode != null) {
|
||||
emptyNode.setAccessibleText(emptyAccessibilityName.getValue());
|
||||
}
|
||||
if (accessibleNameFunction != null) {
|
||||
nodes.forEach(node -> node.setAccessibleText(accessibleNameFunction.apply(nodeMap.get(node))));
|
||||
}
|
||||
|
||||
return cb;
|
||||
}
|
||||
|
||||
|
@ -174,6 +187,16 @@ public class CustomComboBoxBuilder<T> {
|
|||
@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;
|
||||
}
|
||||
|
@ -186,12 +209,15 @@ public class CustomComboBoxBuilder<T> {
|
|||
// 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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,9 +238,12 @@ public class CustomComboBoxBuilder<T> {
|
|||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
-fx-border-radius: 1px;
|
||||
}
|
||||
|
||||
.bookmark-list .tree-cell:hover {
|
||||
.bookmark-list .tree-cell:filled:hover {
|
||||
-fx-background-color: -color-accent-muted;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue