Clean up shortcut handling

This commit is contained in:
crschnick 2024-05-08 12:34:28 +00:00
parent 26823e4728
commit 933b3f6837
11 changed files with 37 additions and 120 deletions

View file

@ -39,7 +39,7 @@ public class BrowserFilterComp extends Comp<BrowserFilterComp.Structure> {
button.fire(); button.fire();
keyEvent.consume(); keyEvent.consume();
}); });
new TooltipAugment<>("app.search", new KeyCodeCombination(KeyCode.F, KeyCombination.CONTROL_DOWN)).augment(button); new TooltipAugment<>("app.search", new KeyCodeCombination(KeyCode.F, KeyCombination.SHORTCUT_DOWN)).augment(button);
text.focusedProperty().addListener((observable, oldValue, newValue) -> { text.focusedProperty().addListener((observable, oldValue, newValue) -> {
if (!newValue && filterString.getValue() == null) { if (!newValue && filterString.getValue() == null) {
if (button.isFocused()) { if (button.isFocused()) {

View file

@ -10,6 +10,7 @@ import io.xpipe.app.fxcomps.SimpleCompStructure;
import io.xpipe.app.fxcomps.augment.ContextMenuAugment; import io.xpipe.app.fxcomps.augment.ContextMenuAugment;
import io.xpipe.app.fxcomps.impl.PrettyImageHelper; import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
import io.xpipe.app.fxcomps.impl.TextFieldComp; import io.xpipe.app.fxcomps.impl.TextFieldComp;
import io.xpipe.app.fxcomps.impl.TooltipAugment;
import io.xpipe.app.util.BooleanScope; import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.ThreadHelper; import io.xpipe.app.util.ThreadHelper;
import javafx.application.Platform; import javafx.application.Platform;
@ -75,9 +76,6 @@ public class BrowserNavBar extends Comp<BrowserNavBar.Structure> {
struc.get().setPromptText("Overview of " + model.getName()); struc.get().setPromptText("Overview of " + model.getName());
}) })
.shortcut(new KeyCodeCombination(KeyCode.P, KeyCombination.SHORTCUT_DOWN), s -> {
s.get().requestFocus();
})
.accessibleText("Current path"); .accessibleText("Current path");
var graphic = Bindings.createStringBinding( var graphic = Bindings.createStringBinding(
@ -105,6 +103,7 @@ public class BrowserNavBar extends Comp<BrowserNavBar.Structure> {
historyButton.getStyleClass().add(Styles.RIGHT_PILL); historyButton.getStyleClass().add(Styles.RIGHT_PILL);
new ContextMenuAugment<>(event -> event.getButton() == MouseButton.PRIMARY, null, this::createContextMenu) new ContextMenuAugment<>(event -> event.getButton() == MouseButton.PRIMARY, null, this::createContextMenu)
.augment(new SimpleCompStructure<>(historyButton)); .augment(new SimpleCompStructure<>(historyButton));
new TooltipAugment<>("history", new KeyCodeCombination(KeyCode.H, KeyCombination.ALT_DOWN)).augment(historyButton);
var breadcrumbs = new BrowserBreadcrumbBar(model).grow(false, true); var breadcrumbs = new BrowserBreadcrumbBar(model).grow(false, true);
@ -114,6 +113,7 @@ public class BrowserNavBar extends Comp<BrowserNavBar.Structure> {
pathRegion.requestFocus(); pathRegion.requestFocus();
event.consume(); event.consume();
}); });
breadcrumbsRegion.setFocusTraversable(false);
breadcrumbsRegion.visibleProperty() breadcrumbsRegion.visibleProperty()
.bind(Bindings.createBooleanBinding( .bind(Bindings.createBooleanBinding(
() -> { () -> {

View file

@ -101,15 +101,26 @@ public class OpenFileSystemComp extends SimpleComp {
root.getChildren().addAll(topBar, content); root.getChildren().addAll(topBar, content);
VBox.setVgrow(content, Priority.ALWAYS); VBox.setVgrow(content, Priority.ALWAYS);
root.setPadding(Insets.EMPTY); root.setPadding(Insets.EMPTY);
InputHelper.onCtrlKeyCode(root, KeyCode.F, true, keyEvent -> { InputHelper.onKeyCombination(root, new KeyCodeCombination(KeyCode.F, KeyCombination.CONTROL_DOWN), true, keyEvent -> {
filter.toggleButton().fire(); filter.toggleButton().fire();
filter.textField().requestFocus(); filter.textField().requestFocus();
keyEvent.consume(); keyEvent.consume();
}); });
InputHelper.onCtrlKeyCode(root, KeyCode.L, true, keyEvent -> { InputHelper.onKeyCombination(root, new KeyCodeCombination(KeyCode.L, KeyCombination.CONTROL_DOWN), true, keyEvent -> {
navBar.textField().requestFocus(); navBar.textField().requestFocus();
keyEvent.consume(); keyEvent.consume();
}); });
InputHelper.onKeyCombination(root, new KeyCodeCombination(KeyCode.H, KeyCombination.ALT_DOWN), true, keyEvent -> {
navBar.historyButton().fire();
keyEvent.consume();
});
InputHelper.onKeyCombination(root, new KeyCodeCombination(KeyCode.UP, KeyCombination.ALT_DOWN), true, keyEvent -> {
var p = model.getCurrentParentDirectory();
if (p != null) {
model.cdAsync(p.getPath());
}
keyEvent.consume();
});
return root; return root;
} }

View file

@ -19,9 +19,6 @@ import javafx.geometry.Insets;
import javafx.geometry.Pos; import javafx.geometry.Pos;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.MenuButton; import javafx.scene.control.MenuButton;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority; import javafx.scene.layout.Priority;
import javafx.scene.layout.Region; import javafx.scene.layout.Region;
@ -102,9 +99,6 @@ public class StoreEntryListStatusComp extends SimpleComp {
}); });
}); });
var filter = new FilterComp(StoreViewState.get().getFilterString()); var filter = new FilterComp(StoreViewState.get().getFilterString());
filter.shortcut(new KeyCodeCombination(KeyCode.F, KeyCombination.SHORTCUT_DOWN), s -> {
s.getText().requestFocus();
});
filter.apply(struc -> struc.get().sceneProperty().addListener((observable, oldValue, newValue) -> { filter.apply(struc -> struc.get().sceneProperty().addListener((observable, oldValue, newValue) -> {
if (newValue != null) { if (newValue != null) {
struc.getText().requestFocus(); struc.getText().requestFocus();

View file

@ -5,6 +5,7 @@ import io.xpipe.app.core.AppActionLinkDetector;
import io.xpipe.app.core.AppLayoutModel; import io.xpipe.app.core.AppLayoutModel;
import io.xpipe.app.fxcomps.SimpleComp; import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.util.InputHelper;
import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination; import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination; import javafx.scene.input.KeyCombination;
@ -12,12 +13,6 @@ import javafx.scene.layout.Region;
public class StoreLayoutComp extends SimpleComp { public class StoreLayoutComp extends SimpleComp {
public StoreLayoutComp() {
shortcut(new KeyCodeCombination(KeyCode.V, KeyCombination.SHORTCUT_DOWN), structure -> {
AppActionLinkDetector.detectOnPaste();
});
}
@Override @Override
protected Region createSimple() { protected Region createSimple() {
var struc = new SideSplitPaneComp(new StoreSidebarComp(), new StoreEntryListComp()) var struc = new SideSplitPaneComp(new StoreSidebarComp(), new StoreEntryListComp())
@ -29,6 +24,10 @@ public class StoreLayoutComp extends SimpleComp {
struc.getLeft().setMinWidth(260); struc.getLeft().setMinWidth(260);
struc.getLeft().setMaxWidth(500); struc.getLeft().setMaxWidth(500);
struc.get().getStyleClass().add("store-layout"); struc.get().getStyleClass().add("store-layout");
InputHelper.onKeyCombination(struc.get(),new KeyCodeCombination(KeyCode.V, KeyCombination.SHORTCUT_DOWN), true, keyEvent -> {
AppActionLinkDetector.detectOnPaste();
keyEvent.consume();
});
return struc.get(); return struc.get();
} }
} }

View file

@ -63,8 +63,7 @@ public class StoreSectionComp extends Comp<CompStructure<VBox>> {
section.getWrapper().getName())) section.getWrapper().getName()))
.disable(quickAccessDisabled) .disable(quickAccessDisabled)
.focusTraversableForAccessibility() .focusTraversableForAccessibility()
.displayOnlyShortcut(new KeyCodeCombination(KeyCode.RIGHT)) .tooltipKey("accessSubConnections", new KeyCodeCombination(KeyCode.RIGHT));
.tooltipKey("accessSubConnections");
return quickAccessButton; return quickAccessButton;
} }
@ -84,8 +83,7 @@ public class StoreSectionComp extends Comp<CompStructure<VBox>> {
.apply(struc -> struc.get().setMinWidth(30)) .apply(struc -> struc.get().setMinWidth(30))
.apply(struc -> struc.get().setPrefWidth(30)) .apply(struc -> struc.get().setPrefWidth(30))
.focusTraversableForAccessibility() .focusTraversableForAccessibility()
.displayOnlyShortcut(new KeyCodeCombination(KeyCode.SPACE)) .tooltipKey("expand", new KeyCodeCombination(KeyCode.SPACE))
.tooltipKey("expand")
.accessibleText(Bindings.createStringBinding( .accessibleText(Bindings.createStringBinding(
() -> { () -> {
return "Expand " + section.getWrapper().getName().getValue(); return "Expand " + section.getWrapper().getName().getValue();

View file

@ -7,7 +7,6 @@ import io.xpipe.app.fxcomps.augment.GrowAugment;
import io.xpipe.app.fxcomps.impl.TooltipAugment; import io.xpipe.app.fxcomps.impl.TooltipAugment;
import io.xpipe.app.fxcomps.util.BindingsHelper; import io.xpipe.app.fxcomps.util.BindingsHelper;
import io.xpipe.app.fxcomps.util.PlatformThread; import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.fxcomps.util.Shortcuts;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets; import javafx.geometry.Insets;
@ -21,7 +20,6 @@ import javafx.scene.layout.VBox;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -179,14 +177,6 @@ public abstract class Comp<S extends CompStructure<?>> {
return apply(GrowAugment.create(width, height)); return apply(GrowAugment.create(width, height));
} }
public Comp<S> shortcut(KeyCombination shortcut, Consumer<S> con) {
return apply(struc -> Shortcuts.addShortcut(struc.get(), shortcut, r -> con.accept(struc)));
}
public Comp<S> displayOnlyShortcut(KeyCombination shortcut) {
return apply(struc -> Shortcuts.addDisplayShortcut(struc.get(), shortcut));
}
public Comp<S> tooltip(ObservableValue<String> text) { public Comp<S> tooltip(ObservableValue<String> text) {
return apply(new TooltipAugment<>(text, null)); return apply(new TooltipAugment<>(text, null));
} }

View file

@ -1,66 +0,0 @@
package io.xpipe.app.fxcomps.util;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.ButtonBase;
import javafx.scene.input.KeyCombination;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Region;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
public class Shortcuts {
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);
}
public static <T extends Region> void addShortcut(T region, KeyCombination comb, Consumer<T> exec) {
var filter = new EventHandler<KeyEvent>() {
public void handle(KeyEvent ke) {
if (!region.isVisible() || !region.isManaged() || region.isDisabled()) {
return;
}
if (comb.match(ke)) {
exec.accept(region);
ke.consume();
}
}
};
DISPLAY_SHORTCUTS.put(region, comb);
AtomicReference<Scene> scene = new AtomicReference<>();
region.sceneProperty().subscribe(s -> {
if (Objects.equals(s, scene.get())) {
return;
}
if (scene.get() != null) {
scene.get().removeEventHandler(KeyEvent.KEY_PRESSED, filter);
DISPLAY_SHORTCUTS.remove(region);
scene.set(null);
}
if (s != null) {
scene.set(s);
DISPLAY_SHORTCUTS.put(region, comb);
s.addEventHandler(KeyEvent.KEY_PRESSED, filter);
}
});
}
public static KeyCombination getDisplayShortcut(Region region) {
return DISPLAY_SHORTCUTS.get(region);
}
}

View file

@ -12,27 +12,6 @@ import java.util.function.Consumer;
public class InputHelper { public class InputHelper {
public static void onCtrlKeyCode(EventTarget target, KeyCode code, boolean filter, Consumer<KeyEvent> r) {
EventHandler<KeyEvent> keyEventEventHandler = event -> {
if (event.isAltDown() || event.isShiftDown()) {
return;
}
if (!event.isShortcutDown()) {
return;
}
if (code == event.getCode()) {
r.accept(event);
}
};
if (filter) {
target.addEventFilter(KeyEvent.KEY_PRESSED, keyEventEventHandler);
} else {
target.addEventHandler(KeyEvent.KEY_PRESSED, keyEventEventHandler);
}
}
public static void onKeyCombination(EventTarget target, KeyCombination c, boolean filter, Consumer<KeyEvent> r) { public static void onKeyCombination(EventTarget target, KeyCombination c, boolean filter, Consumer<KeyEvent> r) {
EventHandler<KeyEvent> keyEventEventHandler = event -> { EventHandler<KeyEvent> keyEventEventHandler = event -> {
if (c.match(event)) { if (c.match(event)) {

View file

@ -79,7 +79,11 @@
-fx-background-color: transparent; -fx-background-color: transparent;
} }
.browser .top-bar > .button:hover { .browser .top-bar .button:hover, .root:key-navigation .browser .top-bar .button:focused {
-fx-background-color: -color-accent-subtle;
}
.browser .top-bar .menu-button:hover, .root:key-navigation .browser .top-bar .menu-button:focused {
-fx-background-color: -color-accent-subtle; -fx-background-color: -color-accent-subtle;
} }

View file

@ -11,12 +11,20 @@ import io.xpipe.core.store.FileKind;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import org.kordamp.ikonli.javafx.FontIcon; import org.kordamp.ikonli.javafx.FontIcon;
import java.util.List; import java.util.List;
public class EditFileAction implements LeafAction { public class EditFileAction implements LeafAction {
@Override
public KeyCombination getShortcut() {
return new KeyCodeCombination(KeyCode.E, KeyCombination.SHORTCUT_DOWN);
}
@Override @Override
public void execute(OpenFileSystemModel model, List<BrowserEntry> entries) { public void execute(OpenFileSystemModel model, List<BrowserEntry> entries) {
for (BrowserEntry entry : entries) { for (BrowserEntry entry : entries) {