Rework keyboard usage

This commit is contained in:
crschnick 2024-03-30 00:24:50 +00:00
parent 9ad5b6f7f5
commit 3f01bb0028
17 changed files with 240 additions and 125 deletions

View file

@ -2,6 +2,7 @@ package io.xpipe.app.browser;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.impl.IconButtonComp;
import io.xpipe.app.util.InputHelper;
import javafx.application.Platform;
import javafx.scene.control.Menu;
import javafx.scene.layout.Region;
@ -36,7 +37,7 @@ public class BrowserQuickAccessButtonComp extends SimpleComp {
struc.get().requestFocus();
});
});
BrowserQuickAccessContextMenu.onRight(struc.get(), false, keyEvent -> {
InputHelper.onRight(struc.get(), false, keyEvent -> {
cm.showMenu(struc.get());
keyEvent.consume();
});

View file

@ -3,12 +3,11 @@ package io.xpipe.app.browser;
import io.xpipe.app.browser.icon.FileIconManager;
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
import io.xpipe.app.util.BooleanAnimationTimer;
import io.xpipe.app.util.InputHelper;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.store.FileKind;
import javafx.application.Platform;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.event.EventHandler;
import javafx.event.EventTarget;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.control.ContextMenu;
@ -24,38 +23,11 @@ import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public class BrowserQuickAccessContextMenu extends ContextMenu {
static void onLeft(EventTarget target, boolean filter, Consumer<KeyEvent> r) {
EventHandler<KeyEvent> keyEventEventHandler = event -> {
if (event.getCode() == KeyCode.LEFT || event.getCode() == KeyCode.NUMPAD4) {
r.accept(event);
}
};
if (filter) {
target.addEventFilter(KeyEvent.KEY_PRESSED, keyEventEventHandler);
} else {
target.addEventHandler(KeyEvent.KEY_PRESSED, keyEventEventHandler);
}
}
static void onRight(EventTarget target, boolean filter, Consumer<KeyEvent> r) {
EventHandler<KeyEvent> keyEventEventHandler = event -> {
if (event.getCode() == KeyCode.RIGHT || event.getCode() == KeyCode.NUMPAD6) {
r.accept(event);
}
};
if (filter) {
target.addEventFilter(KeyEvent.KEY_PRESSED, keyEventEventHandler);
} else {
target.addEventHandler(KeyEvent.KEY_PRESSED, keyEventEventHandler);
}
}
@Getter
class QuickAccessMenu {
private final BrowserEntry browserEntry;
@ -107,7 +79,7 @@ public class BrowserQuickAccessContextMenu extends ContextMenu {
var empty = new MenuItem("...");
empty.setDisable(true);
menu.getItems().add(empty);
onRight(empty, true, keyEvent -> {
InputHelper.onRight(empty, true, keyEvent -> {
keyEvent.consume();
});
}
@ -233,7 +205,7 @@ public class BrowserQuickAccessContextMenu extends ContextMenu {
this.browserActionMenu.setOnAction(e -> {
hide();
});
onLeft(this.browserActionMenu, true, keyEvent -> {
InputHelper.onLeft(this.browserActionMenu, true, keyEvent -> {
this.browserActionMenu.hide();
keyEvent.consume();
});
@ -271,7 +243,7 @@ public class BrowserQuickAccessContextMenu extends ContextMenu {
getItems().getFirst().getStyleableNode().requestFocus();
});
});
onLeft(this, false, e -> {
InputHelper.onLeft(this, false, e -> {
hide();
e.consume();
});

View file

@ -20,6 +20,8 @@ import javafx.beans.binding.Bindings;
import javafx.beans.property.Property;
import javafx.css.PseudoClass;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
@ -67,8 +69,11 @@ public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
Platform.getPreferences().accentColorProperty());
var selected = PseudoClass.getPseudoClass("selected");
entries.forEach(e -> {
var b = new IconButtonComp(e.icon(), () -> value.setValue(e)).apply(new FancyTooltipAugment<>(e.name()));
for (int i = 0; i < entries.size(); i++) {
var e = entries.get(i);
var b = new IconButtonComp(e.icon(), () -> value.setValue(e));
b.shortcut(new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + i]));
b.apply(new FancyTooltipAugment<>(e.name()));
b.apply(struc -> {
AppFont.setSize(struc.get(), 2);
struc.get().pseudoClassStateChanged(selected, value.getValue().equals(e));
@ -99,7 +104,7 @@ public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
});
b.accessibleText(e.name());
vbox.getChildren().add(b.createRegion());
});
}
Augment<CompStructure<Button>> simpleBorders = struc -> {
struc.get()
@ -127,6 +132,7 @@ public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
}
UserReportComp.show(event.build());
})
.shortcut(new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + entries.size()]))
.apply(new FancyTooltipAugment<>("reportIssue"))
.apply(simpleBorders)
.accessibleTextKey("reportIssue");
@ -138,6 +144,7 @@ public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
{
var b = new IconButtonComp("mdi2g-github", () -> Hyperlinks.open(Hyperlinks.GITHUB))
.shortcut(new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + entries.size() + 1]))
.apply(new FancyTooltipAugment<>("visitGithubRepository"))
.apply(simpleBorders)
.accessibleTextKey("visitGithubRepository");
@ -149,6 +156,7 @@ public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
{
var b = new IconButtonComp("mdi2d-discord", () -> Hyperlinks.open(Hyperlinks.DISCORD))
.shortcut(new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + entries.size() + 2]))
.apply(new FancyTooltipAugment<>("discord"))
.apply(simpleBorders)
.accessibleTextKey("discord");
@ -160,6 +168,7 @@ public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
{
var b = new IconButtonComp("mdi2u-update", () -> UpdateAvailableAlert.showIfNeeded())
.shortcut(new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + entries.size() + 3]))
.apply(new FancyTooltipAugment<>("updateAvailableTooltip"))
.accessibleTextKey("updateAvailableTooltip");
b.apply(struc -> {

View file

@ -1,19 +1,20 @@
package io.xpipe.app.comp.store;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.fxcomps.CompStructure;
import io.xpipe.app.fxcomps.impl.IconButtonComp;
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.Region;
import java.util.ArrayList;
import java.util.function.Consumer;
public class StoreQuickAccessButtonComp extends SimpleComp {
public class StoreQuickAccessButtonComp extends Comp<CompStructure<Button>> {
private final StoreSection section;
private final Consumer<StoreEntryWrapper> action;
@ -23,17 +24,6 @@ public class StoreQuickAccessButtonComp extends SimpleComp {
this.action = action;
}
@Override
protected Region createSimple() {
var button = new IconButtonComp("mdi2c-chevron-double-right");
button.apply(struc -> {
struc.get().setOnAction(event -> {
showMenu(struc.get());
});
});
return button.createRegion();
}
private void showMenu(Node anchor) {
var cm = createMenu();
if (cm == null) {
@ -94,4 +84,15 @@ public class StoreQuickAccessButtonComp extends SimpleComp {
});
return m;
}
@Override
public CompStructure<Button> createBase() {
var button = new IconButtonComp("mdi2c-chevron-double-right");
button.apply(struc -> {
struc.get().setOnAction(event -> {
showMenu(struc.get());
});
});
return button.createStructure();
}
}

View file

@ -13,6 +13,10 @@ import io.xpipe.app.storage.DataStoreColor;
import io.xpipe.app.util.ThreadHelper;
import javafx.beans.binding.Bindings;
import javafx.css.PseudoClass;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import java.util.ArrayList;
@ -35,17 +39,7 @@ public class StoreSectionComp extends Comp<CompStructure<VBox>> {
this.topLevel = topLevel;
}
@Override
public CompStructure<VBox> createBase() {
var expanded = BindingsHelper.persist(Bindings.createBooleanBinding(
() -> {
return section.getWrapper().getExpanded().get()
&& section.getShownChildren().size() > 0;
},
section.getWrapper().getExpanded(),
section.getShownChildren()));
var root = StoreEntryComp.customSection(section, topLevel);
private Comp<CompStructure<Button>> createQuickAccessButton() {
var quickAccessDisabled = BindingsHelper.persist(Bindings.createBooleanBinding(
() -> {
return section.getShownChildren().isEmpty();
@ -62,21 +56,31 @@ public class StoreSectionComp extends Comp<CompStructure<VBox>> {
.apply(struc -> struc.get().setMinWidth(30))
.apply(struc -> struc.get().setPrefWidth(30))
.maxHeight(100)
.disable(quickAccessDisabled);
.disable(quickAccessDisabled)
.focusTraversableForAccessibility()
.dislayOnlyShortcut(new KeyCodeCombination(KeyCode.RIGHT))
.tooltipKey("accessSubConnections");
return quickAccessButton;
}
private Comp<CompStructure<Button>> createExpandButton() {
var expandButton = new IconButtonComp(
Bindings.createStringBinding(
() -> section.getWrapper().getExpanded().get()
&& section.getShownChildren().size() > 0
? "mdal-keyboard_arrow_down"
: "mdal-keyboard_arrow_right",
section.getWrapper().getExpanded(),
section.getShownChildren()),
() -> {
section.getWrapper().toggleExpanded();
})
Bindings.createStringBinding(
() -> section.getWrapper().getExpanded().get()
&& section.getShownChildren().size() > 0
? "mdal-keyboard_arrow_down"
: "mdal-keyboard_arrow_right",
section.getWrapper().getExpanded(),
section.getShownChildren()),
() -> {
section.getWrapper().toggleExpanded();
});
expandButton
.apply(struc -> struc.get().setMinWidth(30))
.apply(struc -> struc.get().setPrefWidth(30))
.focusTraversable()
.focusTraversableForAccessibility()
.dislayOnlyShortcut(new KeyCodeCombination(KeyCode.SPACE))
.tooltipKey("expand")
.accessibleText(Bindings.createStringBinding(
() -> {
return "Expand " + section.getWrapper().getName().getValue();
@ -87,13 +91,38 @@ public class StoreSectionComp extends Comp<CompStructure<VBox>> {
.styleClass("expand-button")
.maxHeight(100)
.vgrow();
return expandButton;
}
@Override
public CompStructure<VBox> createBase() {
var entryButton = StoreEntryComp.customSection(section, topLevel);
var quickAccessButton = createQuickAccessButton();
var expandButton = createExpandButton();
var buttonList = new ArrayList<Comp<?>>();
if (root.isFullSize()) {
if (entryButton.isFullSize()) {
buttonList.add(quickAccessButton);
}
buttonList.add(expandButton);
var buttons = new VerticalComp(buttonList);
List<Comp<?>> topEntryList = List.of(buttons, root.hgrow());
var topEntryList = new HorizontalComp(List.of(buttons, entryButton.hgrow()));
topEntryList.apply(struc -> {
var mainButton = struc.get().getChildren().get(1);
mainButton.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if (event.getCode() == KeyCode.SPACE) {
section.getWrapper().toggleExpanded();
event.consume();
}
if (event.getCode() == KeyCode.RIGHT) {
var ref = (VBox) struc.get().getChildren().getFirst();
if (entryButton.isFullSize()) {
var btn = (Button) ref.getChildren().getFirst();
btn.fire();
}
event.consume();
}
});
});
// Optimization for large sections. If there are more than 20 children, only add the nodes to the scene if the
// section is actually expanded
@ -109,18 +138,23 @@ public class StoreSectionComp extends Comp<CompStructure<VBox>> {
.minHeight(0)
.hgrow();
return new VerticalComp(List.of(
new HorizontalComp(topEntryList)
.apply(struc -> struc.get().setFillHeight(true)),
Comp.separator().hide(BindingsHelper.persist(expanded.not())),
new HorizontalComp(List.of(content))
.styleClass("content")
.apply(struc -> struc.get().setFillHeight(true))
.hide(BindingsHelper.persist(Bindings.or(
Bindings.not(section.getWrapper().getExpanded()),
Bindings.size(section.getShownChildren())
.isEqualTo(0))))))
.styleClass("store-entry-section-comp")
var expanded = BindingsHelper.persist(Bindings.createBooleanBinding(
() -> {
return section.getWrapper().getExpanded().get()
&& section.getShownChildren().size() > 0;
},
section.getWrapper().getExpanded(),
section.getShownChildren()));
var full = new VerticalComp(List.of(
topEntryList,
Comp.separator().hide(BindingsHelper.persist(expanded.not())),
new HorizontalComp(List.of(content))
.styleClass("content")
.apply(struc -> struc.get().setFillHeight(true))
.hide(BindingsHelper.persist(Bindings.or(
Bindings.not(section.getWrapper().getExpanded()),
Bindings.size(section.getShownChildren()).isEqualTo(0))))));
return full.styleClass("store-entry-section-comp")
.apply(struc -> {
struc.get().setFillWidth(true);
SimpleChangeListener.apply(expanded, val -> {
@ -128,27 +162,27 @@ public class StoreSectionComp extends Comp<CompStructure<VBox>> {
});
struc.get().pseudoClassStateChanged(EVEN, section.getDepth() % 2 == 0);
struc.get().pseudoClassStateChanged(ODD, section.getDepth() % 2 != 0);
})
.apply(struc -> SimpleChangeListener.apply(section.getWrapper().getColor(), val -> {
if (!topLevel) {
return;
}
var newList = new ArrayList<>(struc.get().getStyleClass());
newList.removeIf(s -> Arrays.stream(DataStoreColor.values())
.anyMatch(dataStoreColor -> dataStoreColor.getId().equals(s)));
newList.remove("none");
newList.add("color-box");
if (val != null) {
newList.add(val.getId());
} else {
newList.add("none");
}
struc.get().getStyleClass().setAll(newList);
}))
.apply(struc -> {
struc.get().pseudoClassStateChanged(ROOT, topLevel);
struc.get().pseudoClassStateChanged(SUB, !topLevel);
SimpleChangeListener.apply(section.getWrapper().getColor(), val -> {
if (!topLevel) {
return;
}
var newList = new ArrayList<>(struc.get().getStyleClass());
newList.removeIf(s -> Arrays.stream(DataStoreColor.values())
.anyMatch(
dataStoreColor -> dataStoreColor.getId().equals(s)));
newList.remove("none");
newList.add("color-box");
if (val != null) {
newList.add(val.getId());
} else {
newList.add("none");
}
struc.get().getStyleClass().setAll(newList);
});
})
.createStructure();
}

View file

@ -4,10 +4,12 @@ import io.xpipe.app.comp.base.LoadingOverlayComp;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.issue.TrackEvent;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.util.InputHelper;
import io.xpipe.app.util.ThreadHelper;
import io.xpipe.core.process.OsType;
import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
import javafx.css.PseudoClass;
import javafx.geometry.Insets;
import javafx.geometry.Rectangle2D;
import javafx.scene.Node;
@ -216,7 +218,7 @@ public class AppWindowHelper {
public static void setupStylesheets(Scene scene) {
AppStyle.addStylesheets(scene);
scene.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if (AppProperties.get().isDeveloperMode() && event.getCode().equals(KeyCode.F3)) {
AppStyle.reloadStylesheets(scene);
TrackEvent.debug("Reloaded stylesheets");
@ -224,6 +226,24 @@ public class AppWindowHelper {
}
});
TrackEvent.debug("Set stylesheet reload listener");
InputHelper.onNavigationInput(scene, (kb) -> {
var r = scene.getRoot();
if (r != null) {
r.pseudoClassStateChanged(PseudoClass.getPseudoClass("key-navigation"), kb);
r.pseudoClassStateChanged(PseudoClass.getPseudoClass("normal-navigation"), !kb);
r.pseudoClassStateChanged(PseudoClass.getPseudoClass("accessibility-navigation"), false);
}
});
Platform.accessibilityActiveProperty().addListener((observable, oldValue, newValue) -> {
var r = scene.getRoot();
if (r != null) {
r.pseudoClassStateChanged(PseudoClass.getPseudoClass("key-navigation"), false);
r.pseudoClassStateChanged(PseudoClass.getPseudoClass("normal-navigation"), false);
r.pseudoClassStateChanged(PseudoClass.getPseudoClass("accessibility-navigation"), true);
}
});
}
public static void setupContent(

View file

@ -24,6 +24,7 @@ public class AppUserDirectoryCheck {
+ ". Please make sure that you have the appropriate permissions and no Antivirus program is blocking the access. "
+ "In case you use cloud storage, verify that your cloud storage is working and you are logged in."))
.term()
.expected()
.handle();
}
}

View file

@ -4,14 +4,15 @@ import atlantafx.base.controls.Spacer;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.fxcomps.augment.Augment;
import io.xpipe.app.fxcomps.augment.GrowAugment;
import io.xpipe.app.fxcomps.impl.FancyTooltipAugment;
import io.xpipe.app.fxcomps.util.Shortcuts;
import io.xpipe.app.fxcomps.util.SimpleChangeListener;
import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.scene.control.ButtonBase;
import javafx.scene.control.Separator;
import javafx.scene.control.Tooltip;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
@ -20,6 +21,7 @@ import javafx.scene.layout.VBox;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
@ -124,6 +126,10 @@ public abstract class Comp<S extends CompStructure<?>> {
return apply(struc -> struc.get().setFocusTraversable(b));
}
public Comp<S> focusTraversableForAccessibility() {
return apply(struc -> struc.get().focusTraversableProperty().bind(Platform.accessibilityActiveProperty()));
}
public Comp<S> visible(ObservableValue<Boolean> o) {
return apply(struc -> struc.get().visibleProperty().bind(o));
}
@ -179,8 +185,22 @@ public abstract class Comp<S extends CompStructure<?>> {
return apply(struc -> Shortcuts.addShortcut((ButtonBase) struc.get(), shortcut));
}
public Comp<S> tooltip(Supplier<String> text) {
return apply(r -> Tooltip.install(r.get(), new Tooltip(text.get())));
public Comp<S> dislayOnlyShortcut(KeyCombination shortcut) {
return apply(struc -> Shortcuts.addDisplayShortcut(struc.get(), shortcut));
}
public Comp<S> tooltip(ObservableValue<String> text) {
return apply(new FancyTooltipAugment<>(text));
}
public Comp<S> tooltipKey(String key) {
return apply(new FancyTooltipAugment<>(key));
}
public <T1 extends CompStructure<?>, T2 extends CompStructure<?>>void applyMultiple(Comp<T1> c1, Comp<T2> c2, BiConsumer<T1,T2> consumer) {
c1.apply(struc -> {
});
}
public Region createRegion() {

View file

@ -25,8 +25,8 @@ public class FancyTooltipAugment<S extends CompStructure<?>> implements Augment<
var region = struc.get();
var tt = new Tooltip();
var toDisplay = text.getValue();
if (Shortcuts.getShortcut(region) != null) {
toDisplay = toDisplay + " (" + Shortcuts.getShortcut(region).getDisplayText() + ")";
if (Shortcuts.getDisplayShortcut(region) != null) {
toDisplay = toDisplay + "\n\n(Shortcut: " + Shortcuts.getDisplayShortcut(region).getDisplayText() + ")";
}
tt.textProperty().setValue(toDisplay);
tt.setStyle("-fx-font-size: 11pt;");

View file

@ -15,7 +15,11 @@ import java.util.function.Consumer;
public class Shortcuts {
private static final Map<Region, KeyCombination> SHORTCUTS = new HashMap<>();
private static final Map<Region, KeyCombination> DISPLAY_SHORTCUTS = new HashMap<>();
public static void addDisplayShortcut(Region region, KeyCombination comb) {
DISPLAY_SHORTCUTS.put(region, comb);
}
public static <T extends ButtonBase> void addShortcut(T region, KeyCombination comb) {
addShortcut(region, comb, ButtonBase::fire);
@ -35,8 +39,8 @@ public class Shortcuts {
}
};
DISPLAY_SHORTCUTS.put(region, comb);
AtomicReference<Scene> scene = new AtomicReference<>();
SHORTCUTS.put(region, comb);
SimpleChangeListener.apply(region.sceneProperty(), s -> {
if (Objects.equals(s, scene.get())) {
return;
@ -44,18 +48,19 @@ public class Shortcuts {
if (scene.get() != null) {
scene.get().removeEventFilter(KeyEvent.KEY_PRESSED, filter);
SHORTCUTS.remove(region);
DISPLAY_SHORTCUTS.remove(region);
scene.set(null);
}
if (s != null) {
scene.set(s);
DISPLAY_SHORTCUTS.put(region, comb);
s.addEventFilter(KeyEvent.KEY_PRESSED, filter);
}
});
}
public static KeyCombination getShortcut(Region region) {
return SHORTCUTS.get(region);
public static KeyCombination getDisplayShortcut(Region region) {
return DISPLAY_SHORTCUTS.get(region);
}
}

View file

@ -0,0 +1,50 @@
package io.xpipe.app.util;
import javafx.event.EventHandler;
import javafx.event.EventTarget;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import java.util.List;
import java.util.function.Consumer;
public class InputHelper {
public static void onLeft(EventTarget target, boolean filter, Consumer<KeyEvent> r) {
EventHandler<KeyEvent> keyEventEventHandler = event -> {
if (event.getCode() == KeyCode.LEFT || event.getCode() == KeyCode.NUMPAD4) {
r.accept(event);
}
};
if (filter) {
target.addEventFilter(KeyEvent.KEY_PRESSED, keyEventEventHandler);
} else {
target.addEventHandler(KeyEvent.KEY_PRESSED, keyEventEventHandler);
}
}
public static void onRight(EventTarget target, boolean filter, Consumer<KeyEvent> r) {
EventHandler<KeyEvent> keyEventEventHandler = event -> {
if (event.getCode() == KeyCode.RIGHT || event.getCode() == KeyCode.NUMPAD6) {
r.accept(event);
}
};
if (filter) {
target.addEventFilter(KeyEvent.KEY_PRESSED, keyEventEventHandler);
} else {
target.addEventHandler(KeyEvent.KEY_PRESSED, keyEventEventHandler);
}
}
public static void onNavigationInput(EventTarget target, Consumer<Boolean> r) {
target.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
var c = event.getCode();
var list = List.of(KeyCode.LEFT, KeyCode.RIGHT, KeyCode.UP, KeyCode.DOWN, KeyCode.SPACE, KeyCode.TAB, KeyCode.NUMPAD2, KeyCode.NUMPAD4, KeyCode.NUMPAD6, KeyCode.NUMPAD8);
r.accept(list.stream().anyMatch(keyCode -> keyCode == c));
});
target.addEventFilter(MouseEvent.MOUSE_PRESSED, event -> {
r.accept(false);
});
}
}

View file

@ -111,6 +111,8 @@ newLine=Newline
crlf=CRLF (Windows)
lf=LF (Linux)
none=None
expand=Expand
accessSubConnections=Access sub connections
common=Common
key=Key
color=Color

View file

@ -14,7 +14,7 @@
-fx-opacity: 1.0;
}
.category-button:hover, .category-button:focused {
.category-button:hover, .root:key-navigation .category-button:focused {
-fx-background-color: -color-bg-default;
}

View file

@ -15,7 +15,7 @@
-fx-opacity: 1.0;
}
.sidebar-comp .icon-button-comp:hover, .sidebar-comp .icon-button-comp:focused {
.sidebar-comp .icon-button-comp:hover, .root:key-navigation .sidebar-comp .icon-button-comp:focused {
-fx-background-color: -color-neutral-muted;
}

View file

@ -64,7 +64,7 @@
-fx-background-color: derive(-color-neutral-muted, 25%);
}
.store-entry-comp:hover, .store-entry-comp:focused {
.store-entry-comp:hover, .root:key-navigation .store-entry-comp:focused {
-fx-background-color: -color-neutral-muted;
}
@ -76,7 +76,7 @@
-fx-opacity: 1.0;
}
.expand-button:hover, .expand-button:focused, .quick-access-button:hover, .quick-access-button:focused {
.expand-button:hover, .root:key-navigation .expand-button:focused, .quick-access-button:hover, .root:key-navigation .quick-access-button:focused {
-fx-background-color: -color-neutral-muted;
}

View file

@ -23,7 +23,7 @@
-fx-background-radius: 0;
}
.store-section-mini-comp .item:hover, .store-section-mini-comp .item:focused {
.store-section-mini-comp .item:hover, .root:key-navigation .store-section-mini-comp .item:focused {
-fx-background-color: -color-accent-subtle;
}
@ -37,7 +37,7 @@
-fx-border-color: -color-border-subtle;
}
.store-section-mini-comp .expand-button:hover, .store-section-mini-comp .expand-button:focused {
.store-section-mini-comp .expand-button:hover, .root:key-navigation .store-section-mini-comp .expand-button:focused {
-fx-background-color: -color-neutral-muted;
}
@ -53,7 +53,7 @@
-fx-background-radius: 4 0 0 4;
}
.store-section-mini-comp .quick-access-button:hover, .store-section-mini-comp .quick-access-button:focused {
.store-section-mini-comp .quick-access-button:hover, .root:key-navigation .store-section-mini-comp .quick-access-button:focused {
-fx-background-color: -color-neutral-muted;
}

View file

@ -27,7 +27,7 @@
-fx-border-color: -color-neutral-emphasis;
}
.edit-button.icon-button-comp:hover, .edit-button.icon-button-comp:focused {
.edit-button.icon-button-comp:hover, .root:key-navigation .edit-button.icon-button-comp:focused {
-fx-background-color: -color-accent-muted;
}