Accessibility fixes

This commit is contained in:
crschnick 2023-06-03 17:14:43 +00:00
parent 2ffea800b5
commit cc9941e276
11 changed files with 54 additions and 18 deletions

View file

@ -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.

View file

@ -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));

View file

@ -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()));

View file

@ -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 ->

View file

@ -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())

View file

@ -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);

View file

@ -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);
});

View file

@ -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));

View file

@ -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)

View file

@ -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());
}
}
}

View file

@ -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;
}