mirror of
https://github.com/xpipe-io/xpipe.git
synced 2024-11-25 00:50:31 +00:00
Browser shortcut rework
This commit is contained in:
parent
9e95c6b5b4
commit
26823e4728
23 changed files with 302 additions and 189 deletions
|
@ -1,19 +1,21 @@
|
||||||
package io.xpipe.app.browser;
|
package io.xpipe.app.browser;
|
||||||
|
|
||||||
|
import atlantafx.base.theme.Styles;
|
||||||
import io.xpipe.app.browser.fs.OpenFileSystemModel;
|
import io.xpipe.app.browser.fs.OpenFileSystemModel;
|
||||||
import io.xpipe.app.fxcomps.Comp;
|
import io.xpipe.app.fxcomps.Comp;
|
||||||
import io.xpipe.app.fxcomps.CompStructure;
|
import io.xpipe.app.fxcomps.CompStructure;
|
||||||
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.fxcomps.impl.TooltipAugment;
|
||||||
|
import io.xpipe.app.util.InputHelper;
|
||||||
import javafx.beans.property.Property;
|
import javafx.beans.property.Property;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
|
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 atlantafx.base.theme.Styles;
|
|
||||||
import org.kordamp.ikonli.javafx.FontIcon;
|
import org.kordamp.ikonli.javafx.FontIcon;
|
||||||
|
|
||||||
public class BrowserFilterComp extends Comp<BrowserFilterComp.Structure> {
|
public class BrowserFilterComp extends Comp<BrowserFilterComp.Structure> {
|
||||||
|
@ -29,9 +31,15 @@ public class BrowserFilterComp extends Comp<BrowserFilterComp.Structure> {
|
||||||
@Override
|
@Override
|
||||||
public Structure createBase() {
|
public Structure createBase() {
|
||||||
var expanded = new SimpleBooleanProperty();
|
var expanded = new SimpleBooleanProperty();
|
||||||
var text = new TextFieldComp(filterString, false).createRegion();
|
var text = new TextFieldComp(filterString, false).createStructure().get();
|
||||||
var button = new Button();
|
var button = new Button();
|
||||||
new TooltipAugment<>("app.search").augment(button);
|
button.setFocusTraversable(true);
|
||||||
|
InputHelper.onExactKeyCode(text, KeyCode.ESCAPE, true, keyEvent -> {
|
||||||
|
text.clear();
|
||||||
|
button.fire();
|
||||||
|
keyEvent.consume();
|
||||||
|
});
|
||||||
|
new TooltipAugment<>("app.search", new KeyCodeCombination(KeyCode.F, KeyCombination.CONTROL_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()) {
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
package io.xpipe.app.browser;
|
package io.xpipe.app.browser;
|
||||||
|
|
||||||
|
import atlantafx.base.theme.Styles;
|
||||||
import io.xpipe.app.browser.file.BrowserContextMenu;
|
import io.xpipe.app.browser.file.BrowserContextMenu;
|
||||||
import io.xpipe.app.browser.fs.OpenFileSystemModel;
|
import io.xpipe.app.browser.fs.OpenFileSystemModel;
|
||||||
import io.xpipe.app.browser.icon.FileIconManager;
|
import io.xpipe.app.browser.icon.FileIconManager;
|
||||||
import io.xpipe.app.fxcomps.Comp;
|
import io.xpipe.app.fxcomps.Comp;
|
||||||
import io.xpipe.app.fxcomps.SimpleComp;
|
import io.xpipe.app.fxcomps.CompStructure;
|
||||||
import io.xpipe.app.fxcomps.SimpleCompStructure;
|
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.HorizontalComp;
|
|
||||||
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
|
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
|
||||||
import io.xpipe.app.fxcomps.impl.StackComp;
|
|
||||||
import io.xpipe.app.fxcomps.impl.TextFieldComp;
|
import io.xpipe.app.fxcomps.impl.TextFieldComp;
|
||||||
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;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
@ -25,25 +23,16 @@ 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;
|
||||||
import javafx.scene.input.MouseButton;
|
import javafx.scene.input.MouseButton;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.Priority;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
import atlantafx.base.theme.Styles;
|
|
||||||
import org.kordamp.ikonli.javafx.FontIcon;
|
import org.kordamp.ikonli.javafx.FontIcon;
|
||||||
|
|
||||||
import java.util.List;
|
public class BrowserNavBar extends Comp<BrowserNavBar.Structure> {
|
||||||
|
|
||||||
public class BrowserNavBar extends SimpleComp {
|
|
||||||
|
|
||||||
private static final PseudoClass INVISIBLE = PseudoClass.getPseudoClass("invisible");
|
|
||||||
|
|
||||||
private final OpenFileSystemModel model;
|
|
||||||
|
|
||||||
public BrowserNavBar(OpenFileSystemModel model) {
|
|
||||||
this.model = model;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Region createSimple() {
|
public Structure createBase() {
|
||||||
var path = new SimpleStringProperty(model.getCurrentPath().get());
|
var path = new SimpleStringProperty(model.getCurrentPath().get());
|
||||||
model.getCurrentPath().subscribe((newValue) -> {
|
model.getCurrentPath().subscribe((newValue) -> {
|
||||||
path.set(newValue);
|
path.set(newValue);
|
||||||
|
@ -107,62 +96,61 @@ public class BrowserNavBar extends SimpleComp {
|
||||||
homeButton.getStyleClass().add(Styles.LEFT_PILL);
|
homeButton.getStyleClass().add(Styles.LEFT_PILL);
|
||||||
homeButton.getStyleClass().add("path-graphic-button");
|
homeButton.getStyleClass().add("path-graphic-button");
|
||||||
new ContextMenuAugment<>(event -> event.getButton() == MouseButton.PRIMARY, null, () -> {
|
new ContextMenuAugment<>(event -> event.getButton() == MouseButton.PRIMARY, null, () -> {
|
||||||
return model.getInOverview().get() ? null : new BrowserContextMenu(model, null);
|
return model.getInOverview().get() ? null : new BrowserContextMenu(model, null);
|
||||||
})
|
})
|
||||||
.augment(new SimpleCompStructure<>(homeButton));
|
.augment(new SimpleCompStructure<>(homeButton));
|
||||||
|
|
||||||
var historyButton = new Button(null, new FontIcon("mdi2h-history"));
|
var historyButton = new Button(null, new FontIcon("mdi2h-history"));
|
||||||
historyButton.setAccessibleText("History");
|
historyButton.setAccessibleText("History");
|
||||||
historyButton.getStyleClass().add(Styles.RIGHT_PILL);
|
historyButton.getStyleClass().add(Styles.RIGHT_PILL);
|
||||||
// historyButton.getStyleClass().add("path-graphic-button");
|
|
||||||
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));
|
||||||
|
|
||||||
var breadcrumbs = new BrowserBreadcrumbBar(model).grow(false, true);
|
var breadcrumbs = new BrowserBreadcrumbBar(model).grow(false, true);
|
||||||
var stack = new StackComp(List.of(pathBar, breadcrumbs))
|
|
||||||
.apply(struc -> struc.get().setAlignment(Pos.CENTER_LEFT))
|
|
||||||
.hgrow()
|
|
||||||
.apply(struc -> {
|
|
||||||
var t = struc.get().getChildren().get(0);
|
|
||||||
var b = struc.get().getChildren().get(1);
|
|
||||||
b.setOnMouseClicked(event -> {
|
|
||||||
t.requestFocus();
|
|
||||||
event.consume();
|
|
||||||
});
|
|
||||||
b.visibleProperty()
|
|
||||||
.bind(Bindings.createBooleanBinding(
|
|
||||||
() -> {
|
|
||||||
return !t.isFocused()
|
|
||||||
&& !model.getInOverview().get();
|
|
||||||
},
|
|
||||||
t.focusedProperty(),
|
|
||||||
model.getInOverview()));
|
|
||||||
})
|
|
||||||
.grow(false, true);
|
|
||||||
|
|
||||||
var topBox = new HorizontalComp(List.of(Comp.of(() -> homeButton), stack, Comp.of(() -> historyButton)))
|
var pathRegion = pathBar.createStructure().get();
|
||||||
.apply(struc -> struc.get().setAlignment(Pos.CENTER_LEFT))
|
var breadcrumbsRegion = breadcrumbs.createRegion();
|
||||||
.apply(struc -> {
|
breadcrumbsRegion.setOnMouseClicked(event -> {
|
||||||
((Region) struc.get().getChildren().get(0))
|
pathRegion.requestFocus();
|
||||||
.minHeightProperty()
|
event.consume();
|
||||||
.bind(((Region) struc.get().getChildren().get(1)).heightProperty());
|
});
|
||||||
((Region) struc.get().getChildren().get(0))
|
breadcrumbsRegion.visibleProperty()
|
||||||
.maxHeightProperty()
|
.bind(Bindings.createBooleanBinding(
|
||||||
.bind(((Region) struc.get().getChildren().get(1)).heightProperty());
|
() -> {
|
||||||
|
return !pathRegion.isFocused()
|
||||||
|
&& !model.getInOverview().get();
|
||||||
|
},
|
||||||
|
pathRegion.focusedProperty(),
|
||||||
|
model.getInOverview()));
|
||||||
|
var stack = new StackPane(pathRegion, breadcrumbsRegion);
|
||||||
|
stack.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
HBox.setHgrow(stack, Priority.ALWAYS);
|
||||||
|
|
||||||
((Region) struc.get().getChildren().get(2))
|
var topBox = new HBox(homeButton, stack, historyButton);
|
||||||
.minHeightProperty()
|
homeButton.minHeightProperty().bind(stack.heightProperty());
|
||||||
.bind(((Region) struc.get().getChildren().get(1)).heightProperty());
|
homeButton.maxHeightProperty().bind(stack.heightProperty());
|
||||||
((Region) struc.get().getChildren().get(2))
|
historyButton.minHeightProperty().bind(stack.heightProperty());
|
||||||
.maxHeightProperty()
|
historyButton.maxHeightProperty().bind(stack.heightProperty());
|
||||||
.bind(((Region) struc.get().getChildren().get(1)).heightProperty());
|
topBox.setPickOnBounds(false);
|
||||||
})
|
HBox.setHgrow(topBox, Priority.ALWAYS);
|
||||||
.apply(struc -> {
|
|
||||||
struc.get().setPickOnBounds(false);
|
|
||||||
})
|
|
||||||
.hgrow();
|
|
||||||
|
|
||||||
return topBox.createRegion();
|
return new Structure(topBox,pathRegion, historyButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Structure(HBox box, TextField textField, Button historyButton) implements CompStructure<HBox> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HBox get() {
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final PseudoClass INVISIBLE = PseudoClass.getPseudoClass("invisible");
|
||||||
|
|
||||||
|
private final OpenFileSystemModel model;
|
||||||
|
|
||||||
|
public BrowserNavBar(OpenFileSystemModel model) {
|
||||||
|
this.model = model;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ContextMenu createContextMenu() {
|
private ContextMenu createContextMenu() {
|
||||||
|
|
|
@ -78,7 +78,7 @@ public class BrowserTransferComp extends SimpleComp {
|
||||||
})
|
})
|
||||||
.hide(Bindings.isEmpty(syncItems))
|
.hide(Bindings.isEmpty(syncItems))
|
||||||
.disable(syncAllDownloaded)
|
.disable(syncAllDownloaded)
|
||||||
.apply(new TooltipAugment<>("downloadStageDescription"));
|
.tooltipKey("downloadStageDescription");
|
||||||
var clearButton = new IconButtonComp("mdi2c-close", () -> {
|
var clearButton = new IconButtonComp("mdi2c-close", () -> {
|
||||||
model.clear();
|
model.clear();
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,14 +4,13 @@ import io.xpipe.app.browser.file.BrowserEntry;
|
||||||
import io.xpipe.app.browser.fs.OpenFileSystemModel;
|
import io.xpipe.app.browser.fs.OpenFileSystemModel;
|
||||||
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.Shortcuts;
|
|
||||||
import io.xpipe.app.util.BooleanScope;
|
import io.xpipe.app.util.BooleanScope;
|
||||||
import io.xpipe.app.util.LicenseProvider;
|
import io.xpipe.app.util.LicenseProvider;
|
||||||
import io.xpipe.app.util.ThreadHelper;
|
import io.xpipe.app.util.ThreadHelper;
|
||||||
|
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.MenuItem;
|
import javafx.scene.control.MenuItem;
|
||||||
|
import javafx.scene.input.KeyEvent;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
import org.kordamp.ikonli.javafx.FontIcon;
|
import org.kordamp.ikonli.javafx.FontIcon;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -20,7 +19,7 @@ public interface LeafAction extends BrowserAction {
|
||||||
|
|
||||||
void execute(OpenFileSystemModel model, List<BrowserEntry> entries) throws Exception;
|
void execute(OpenFileSystemModel model, List<BrowserEntry> entries) throws Exception;
|
||||||
|
|
||||||
default Button toButton(OpenFileSystemModel model, List<BrowserEntry> selected) {
|
default Button toButton(Region root, OpenFileSystemModel model, List<BrowserEntry> selected) {
|
||||||
var b = new Button();
|
var b = new Button();
|
||||||
b.setOnAction(event -> {
|
b.setOnAction(event -> {
|
||||||
// Only accept shortcut actions in the current tab
|
// Only accept shortcut actions in the current tab
|
||||||
|
@ -37,17 +36,20 @@ public interface LeafAction extends BrowserAction {
|
||||||
});
|
});
|
||||||
event.consume();
|
event.consume();
|
||||||
});
|
});
|
||||||
if (getShortcut() != null) {
|
|
||||||
Shortcuts.addShortcut(b, getShortcut());
|
|
||||||
}
|
|
||||||
var name = getName(model, selected);
|
var name = getName(model, selected);
|
||||||
new TooltipAugment<>(name).augment(b);
|
new TooltipAugment<>(name, getShortcut()).augment(b);
|
||||||
var graphic = getIcon(model, selected);
|
var graphic = getIcon(model, selected);
|
||||||
if (graphic != null) {
|
if (graphic != null) {
|
||||||
b.setGraphic(graphic);
|
b.setGraphic(graphic);
|
||||||
}
|
}
|
||||||
b.setMnemonicParsing(false);
|
b.setMnemonicParsing(false);
|
||||||
b.accessibleTextProperty().bind(name);
|
b.accessibleTextProperty().bind(name);
|
||||||
|
root.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
||||||
|
if (getShortcut() != null && getShortcut().match(event)) {
|
||||||
|
b.fire();
|
||||||
|
event.consume();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
b.setDisable(!isActive(model, selected));
|
b.setDisable(!isActive(model, selected));
|
||||||
model.getCurrentPath().addListener((observable, oldValue, newValue) -> {
|
model.getCurrentPath().addListener((observable, oldValue, newValue) -> {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import io.xpipe.app.browser.action.BrowserAction;
|
||||||
import io.xpipe.app.browser.action.LeafAction;
|
import io.xpipe.app.browser.action.LeafAction;
|
||||||
import io.xpipe.app.browser.fs.OpenFileSystemModel;
|
import io.xpipe.app.browser.fs.OpenFileSystemModel;
|
||||||
import io.xpipe.app.core.AppFont;
|
import io.xpipe.app.core.AppFont;
|
||||||
|
import io.xpipe.app.util.InputHelper;
|
||||||
import io.xpipe.app.util.LicenseProvider;
|
import io.xpipe.app.util.LicenseProvider;
|
||||||
|
|
||||||
import javafx.scene.control.ContextMenu;
|
import javafx.scene.control.ContextMenu;
|
||||||
|
@ -38,6 +39,11 @@ public final class BrowserContextMenu extends ContextMenu {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createMenu() {
|
private void createMenu() {
|
||||||
|
InputHelper.onLeft(this, false, e -> {
|
||||||
|
hide();
|
||||||
|
e.consume();
|
||||||
|
});
|
||||||
|
|
||||||
AppFont.normal(this.getStyleableNode());
|
AppFont.normal(this.getStyleableNode());
|
||||||
|
|
||||||
var empty = source == null;
|
var empty = source == null;
|
||||||
|
|
|
@ -10,9 +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.util.PlatformThread;
|
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||||
import io.xpipe.app.util.BooleanScope;
|
import io.xpipe.app.util.*;
|
||||||
import io.xpipe.app.util.HumanReadableFormat;
|
|
||||||
import io.xpipe.app.util.ThreadHelper;
|
|
||||||
import io.xpipe.core.process.OsType;
|
import io.xpipe.core.process.OsType;
|
||||||
import io.xpipe.core.store.FileKind;
|
import io.xpipe.core.store.FileKind;
|
||||||
import io.xpipe.core.store.FileNames;
|
import io.xpipe.core.store.FileNames;
|
||||||
|
@ -26,12 +24,16 @@ import javafx.collections.ListChangeListener;
|
||||||
import javafx.css.PseudoClass;
|
import javafx.css.PseudoClass;
|
||||||
import javafx.geometry.Bounds;
|
import javafx.geometry.Bounds;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.geometry.Side;
|
||||||
import javafx.scene.AccessibleRole;
|
import javafx.scene.AccessibleRole;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.control.skin.TableViewSkin;
|
import javafx.scene.control.skin.TableViewSkin;
|
||||||
import javafx.scene.control.skin.VirtualFlow;
|
import javafx.scene.control.skin.VirtualFlow;
|
||||||
import javafx.scene.input.*;
|
import javafx.scene.input.DragEvent;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
|
import javafx.scene.input.MouseButton;
|
||||||
|
import javafx.scene.input.MouseEvent;
|
||||||
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;
|
||||||
|
@ -128,7 +130,6 @@ public final class BrowserFileListComp extends SimpleComp {
|
||||||
} else {
|
} else {
|
||||||
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
|
table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
table.getSelectionModel().setCellSelectionEnabled(false);
|
table.getSelectionModel().setCellSelectionEnabled(false);
|
||||||
|
|
||||||
table.getSelectionModel().getSelectedItems().addListener((ListChangeListener<? super BrowserEntry>) c -> {
|
table.getSelectionModel().getSelectedItems().addListener((ListChangeListener<? super BrowserEntry>) c -> {
|
||||||
|
@ -158,18 +159,24 @@ public final class BrowserFileListComp extends SimpleComp {
|
||||||
private void prepareTableShortcuts(TableView<BrowserEntry> table) {
|
private void prepareTableShortcuts(TableView<BrowserEntry> table) {
|
||||||
table.setOnKeyPressed(event -> {
|
table.setOnKeyPressed(event -> {
|
||||||
var selected = fileList.getSelection();
|
var selected = fileList.getSelection();
|
||||||
BrowserAction.getFlattened(fileList.getFileSystemModel(), selected).stream()
|
var action = BrowserAction.getFlattened(fileList.getFileSystemModel(), selected).stream().filter(
|
||||||
.filter(browserAction -> browserAction.isApplicable(fileList.getFileSystemModel(), selected)
|
browserAction -> browserAction.isApplicable(fileList.getFileSystemModel(), selected) &&
|
||||||
&& browserAction.isActive(fileList.getFileSystemModel(), selected))
|
browserAction.isActive(fileList.getFileSystemModel(), selected)).filter(
|
||||||
.filter(browserAction -> browserAction.getShortcut() != null)
|
browserAction -> browserAction.getShortcut() != null).filter(browserAction -> browserAction.getShortcut().match(event)).findAny();
|
||||||
.filter(browserAction -> browserAction.getShortcut().match(event))
|
action.ifPresent(browserAction -> {
|
||||||
.findAny()
|
|
||||||
.ifPresent(browserAction -> {
|
|
||||||
ThreadHelper.runFailableAsync(() -> {
|
ThreadHelper.runFailableAsync(() -> {
|
||||||
browserAction.execute(fileList.getFileSystemModel(), selected);
|
browserAction.execute(fileList.getFileSystemModel(), selected);
|
||||||
});
|
});
|
||||||
event.consume();
|
event.consume();
|
||||||
});
|
});
|
||||||
|
if (action.isPresent()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.getCode() == KeyCode.ESCAPE) {
|
||||||
|
table.getSelectionModel().clearSelection();
|
||||||
|
event.consume();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,7 +351,6 @@ public final class BrowserFileListComp extends SimpleComp {
|
||||||
// Sort the list ourselves as sorting the table would incur a lot of cell updates
|
// Sort the list ourselves as sorting the table would incur a lot of cell updates
|
||||||
var obs = FXCollections.observableList(newItems);
|
var obs = FXCollections.observableList(newItems);
|
||||||
table.getItems().setAll(obs);
|
table.getItems().setAll(obs);
|
||||||
// table.sort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentDirectory = fileList.getFileSystemModel().getCurrentDirectory();
|
var currentDirectory = fileList.getFileSystemModel().getCurrentDirectory();
|
||||||
|
@ -488,9 +494,6 @@ public final class BrowserFileListComp extends SimpleComp {
|
||||||
.not()
|
.not()
|
||||||
.not())
|
.not())
|
||||||
.focusTraversable(false)
|
.focusTraversable(false)
|
||||||
.apply(struc -> struc.get().focusedProperty().addListener((observable, oldValue, newValue) -> {
|
|
||||||
getTableRow().requestFocus();
|
|
||||||
}))
|
|
||||||
.createRegion();
|
.createRegion();
|
||||||
|
|
||||||
editing.addListener((observable, oldValue, newValue) -> {
|
editing.addListener((observable, oldValue, newValue) -> {
|
||||||
|
@ -520,13 +523,20 @@ public final class BrowserFileListComp extends SimpleComp {
|
||||||
graphic.setAlignment(Pos.CENTER_LEFT);
|
graphic.setAlignment(Pos.CENTER_LEFT);
|
||||||
setGraphic(graphic);
|
setGraphic(graphic);
|
||||||
|
|
||||||
tableView.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
InputHelper.onExactKeyCode(tableView, KeyCode.RIGHT, true, event -> {
|
||||||
if (event.getCode() == KeyCode.RIGHT) {
|
var selected = fileList.getSelection();
|
||||||
var selected = fileList.getSelection();
|
if (selected.size() == 1 && selected.getFirst() == getTableRow().getItem()) {
|
||||||
if (selected.size() == 1 && selected.getFirst() == getTableRow().getItem()) {
|
((ButtonBase) quickAccess).fire();
|
||||||
((ButtonBase) quickAccess).fire();
|
event.consume();
|
||||||
event.consume();
|
}
|
||||||
}
|
});
|
||||||
|
InputHelper.onExactKeyCode(tableView, KeyCode.SPACE, true, event -> {
|
||||||
|
var selected = fileList.getSelection();
|
||||||
|
// Only show one menu across all selected entries
|
||||||
|
if (selected.size() > 0 && selected.getLast() == getTableRow().getItem()) {
|
||||||
|
var cm = new BrowserContextMenu(fileList.getFileSystemModel(), getTableRow().getItem());
|
||||||
|
ContextMenuHelper.toggleShow(cm, this, Side.RIGHT);
|
||||||
|
event.consume();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,16 @@
|
||||||
package io.xpipe.app.browser.file;
|
package io.xpipe.app.browser.file;
|
||||||
|
|
||||||
import io.xpipe.app.browser.fs.OpenFileSystemModel;
|
import io.xpipe.app.browser.fs.OpenFileSystemModel;
|
||||||
import io.xpipe.app.fxcomps.util.ListBindingsHelper;
|
|
||||||
import io.xpipe.app.issue.ErrorEvent;
|
import io.xpipe.app.issue.ErrorEvent;
|
||||||
import io.xpipe.core.store.FileKind;
|
import io.xpipe.core.store.FileKind;
|
||||||
import io.xpipe.core.store.FileNames;
|
import io.xpipe.core.store.FileNames;
|
||||||
import io.xpipe.core.store.FileSystem;
|
import io.xpipe.core.store.FileSystem;
|
||||||
|
|
||||||
import javafx.beans.property.Property;
|
import javafx.beans.property.Property;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -37,8 +34,6 @@ public final class BrowserFileListModel {
|
||||||
private final Property<List<BrowserEntry>> shown = new SimpleObjectProperty<>(new ArrayList<>());
|
private final Property<List<BrowserEntry>> shown = new SimpleObjectProperty<>(new ArrayList<>());
|
||||||
private final ObservableList<BrowserEntry> previousSelection = FXCollections.observableArrayList();
|
private final ObservableList<BrowserEntry> previousSelection = FXCollections.observableArrayList();
|
||||||
private final ObservableList<BrowserEntry> selection = FXCollections.observableArrayList();
|
private final ObservableList<BrowserEntry> selection = FXCollections.observableArrayList();
|
||||||
private final ObservableList<FileSystem.FileEntry> selectedRaw =
|
|
||||||
ListBindingsHelper.mappedContentBinding(selection, entry -> entry.getRawFileEntry());
|
|
||||||
|
|
||||||
private final Property<BrowserEntry> draggedOverDirectory = new SimpleObjectProperty<>();
|
private final Property<BrowserEntry> draggedOverDirectory = new SimpleObjectProperty<>();
|
||||||
private final Property<Boolean> draggedOverEmpty = new SimpleBooleanProperty();
|
private final Property<Boolean> draggedOverEmpty = new SimpleBooleanProperty();
|
||||||
|
|
|
@ -4,9 +4,6 @@ import io.xpipe.app.browser.fs.OpenFileSystemModel;
|
||||||
import io.xpipe.app.fxcomps.SimpleComp;
|
import io.xpipe.app.fxcomps.SimpleComp;
|
||||||
import io.xpipe.app.fxcomps.impl.IconButtonComp;
|
import io.xpipe.app.fxcomps.impl.IconButtonComp;
|
||||||
import io.xpipe.app.util.InputHelper;
|
import io.xpipe.app.util.InputHelper;
|
||||||
|
|
||||||
import javafx.application.Platform;
|
|
||||||
import javafx.scene.control.Menu;
|
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
@ -34,11 +31,6 @@ public class BrowserQuickAccessButtonComp extends SimpleComp {
|
||||||
}
|
}
|
||||||
event.consume();
|
event.consume();
|
||||||
});
|
});
|
||||||
cm.addEventFilter(Menu.ON_HIDDEN, e -> {
|
|
||||||
Platform.runLater(() -> {
|
|
||||||
struc.get().requestFocus();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
InputHelper.onRight(struc.get(), false, keyEvent -> {
|
InputHelper.onRight(struc.get(), false, keyEvent -> {
|
||||||
cm.showMenu(struc.get());
|
cm.showMenu(struc.get());
|
||||||
keyEvent.consume();
|
keyEvent.consume();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.xpipe.app.browser.fs;
|
package io.xpipe.app.browser.fs;
|
||||||
|
|
||||||
|
import atlantafx.base.controls.Spacer;
|
||||||
import io.xpipe.app.browser.BrowserFilterComp;
|
import io.xpipe.app.browser.BrowserFilterComp;
|
||||||
import io.xpipe.app.browser.BrowserNavBar;
|
import io.xpipe.app.browser.BrowserNavBar;
|
||||||
import io.xpipe.app.browser.BrowserOverviewComp;
|
import io.xpipe.app.browser.BrowserOverviewComp;
|
||||||
|
@ -13,9 +14,9 @@ import io.xpipe.app.fxcomps.Comp;
|
||||||
import io.xpipe.app.fxcomps.SimpleComp;
|
import io.xpipe.app.fxcomps.SimpleComp;
|
||||||
import io.xpipe.app.fxcomps.SimpleCompStructure;
|
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.TooltipAugment;
|
||||||
import io.xpipe.app.fxcomps.impl.VerticalComp;
|
import io.xpipe.app.fxcomps.impl.VerticalComp;
|
||||||
import io.xpipe.app.fxcomps.util.Shortcuts;
|
import io.xpipe.app.util.InputHelper;
|
||||||
|
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
|
@ -28,8 +29,6 @@ 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;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
|
|
||||||
import atlantafx.base.controls.Spacer;
|
|
||||||
import org.kordamp.ikonli.javafx.FontIcon;
|
import org.kordamp.ikonli.javafx.FontIcon;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -53,17 +52,24 @@ public class OpenFileSystemComp extends SimpleComp {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Region createContent() {
|
private Region createContent() {
|
||||||
|
var root = new VBox();
|
||||||
var overview = new Button(null, new FontIcon("mdi2m-monitor"));
|
var overview = new Button(null, new FontIcon("mdi2m-monitor"));
|
||||||
overview.setOnAction(e -> model.cdAsync(null));
|
overview.setOnAction(e -> model.cdAsync(null));
|
||||||
|
new TooltipAugment<>("overview", new KeyCodeCombination(KeyCode.HOME, KeyCombination.ALT_DOWN)).augment(overview);
|
||||||
overview.disableProperty().bind(model.getInOverview());
|
overview.disableProperty().bind(model.getInOverview());
|
||||||
overview.setAccessibleText("System overview");
|
overview.setAccessibleText("System overview");
|
||||||
|
InputHelper.onKeyCombination(root, new KeyCodeCombination(KeyCode.HOME, KeyCombination.ALT_DOWN), true, keyEvent -> {
|
||||||
|
overview.fire();
|
||||||
|
keyEvent.consume();
|
||||||
|
});
|
||||||
|
|
||||||
var backBtn = BrowserAction.byId("back", model, List.of()).toButton(model, List.of());
|
var backBtn = BrowserAction.byId("back", model, List.of()).toButton(root, model, List.of());
|
||||||
var forthBtn = BrowserAction.byId("forward", model, List.of()).toButton(model, List.of());
|
var forthBtn = BrowserAction.byId("forward", model, List.of()).toButton(root, model, List.of());
|
||||||
var refreshBtn = BrowserAction.byId("refresh", model, List.of()).toButton(model, List.of());
|
var refreshBtn = BrowserAction.byId("refresh", model, List.of()).toButton(root, model, List.of());
|
||||||
var terminalBtn = BrowserAction.byId("openTerminal", model, List.of()).toButton(model, List.of());
|
var terminalBtn = BrowserAction.byId("openTerminal", model, List.of()).toButton(root, model, List.of());
|
||||||
|
|
||||||
var menuButton = new MenuButton(null, new FontIcon("mdral-folder_open"));
|
var menuButton = new MenuButton(null, new FontIcon
|
||||||
|
("mdral-folder_open"));
|
||||||
new ContextMenuAugment<>(
|
new ContextMenuAugment<>(
|
||||||
event -> event.getButton() == MouseButton.PRIMARY,
|
event -> event.getButton() == MouseButton.PRIMARY,
|
||||||
null,
|
null,
|
||||||
|
@ -73,18 +79,18 @@ public class OpenFileSystemComp extends SimpleComp {
|
||||||
menuButton.setAccessibleText("Directory options");
|
menuButton.setAccessibleText("Directory options");
|
||||||
|
|
||||||
var filter = new BrowserFilterComp(model, model.getFilter()).createStructure();
|
var filter = new BrowserFilterComp(model, model.getFilter()).createStructure();
|
||||||
Shortcuts.addShortcut(filter.toggleButton(), new KeyCodeCombination(KeyCode.F, KeyCombination.SHORTCUT_DOWN));
|
|
||||||
|
|
||||||
var topBar = new HBox();
|
var topBar = new HBox();
|
||||||
topBar.setAlignment(Pos.CENTER);
|
topBar.setAlignment(Pos.CENTER);
|
||||||
topBar.getStyleClass().add("top-bar");
|
topBar.getStyleClass().add("top-bar");
|
||||||
|
var navBar = new BrowserNavBar(model).createStructure();
|
||||||
topBar.getChildren()
|
topBar.getChildren()
|
||||||
.setAll(
|
.setAll(
|
||||||
overview,
|
overview,
|
||||||
backBtn,
|
backBtn,
|
||||||
forthBtn,
|
forthBtn,
|
||||||
new Spacer(10),
|
new Spacer(10),
|
||||||
new BrowserNavBar(model).hgrow().createRegion(),
|
navBar.get(),
|
||||||
new Spacer(5),
|
new Spacer(5),
|
||||||
filter.get(),
|
filter.get(),
|
||||||
refreshBtn,
|
refreshBtn,
|
||||||
|
@ -92,9 +98,18 @@ public class OpenFileSystemComp extends SimpleComp {
|
||||||
menuButton);
|
menuButton);
|
||||||
|
|
||||||
var content = createFileListContent();
|
var content = createFileListContent();
|
||||||
var root = new VBox(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 -> {
|
||||||
|
filter.toggleButton().fire();
|
||||||
|
filter.textField().requestFocus();
|
||||||
|
keyEvent.consume();
|
||||||
|
});
|
||||||
|
InputHelper.onCtrlKeyCode(root, KeyCode.L, true, keyEvent -> {
|
||||||
|
navBar.textField().requestFocus();
|
||||||
|
keyEvent.consume();
|
||||||
|
});
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||||
import io.xpipe.app.storage.DataStorage;
|
import io.xpipe.app.storage.DataStorage;
|
||||||
import io.xpipe.app.util.BooleanScope;
|
import io.xpipe.app.util.BooleanScope;
|
||||||
|
|
||||||
|
import io.xpipe.app.util.InputHelper;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
|
@ -21,6 +22,7 @@ import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.Tab;
|
import javafx.scene.control.Tab;
|
||||||
import javafx.scene.control.TabPane;
|
import javafx.scene.control.TabPane;
|
||||||
import javafx.scene.input.DragEvent;
|
import javafx.scene.input.DragEvent;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
|
|
||||||
|
@ -164,6 +166,24 @@ public class BrowserSessionTabsComp extends SimpleComp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
InputHelper.onInput(tabs, true, keyEvent -> {
|
||||||
|
var current = tabs.getSelectionModel().getSelectedItem();
|
||||||
|
if (current == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyEvent.getCode() == KeyCode.W && keyEvent.isShortcutDown()) {
|
||||||
|
tabs.getTabs().remove(current);
|
||||||
|
keyEvent.consume();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyEvent.getCode() == KeyCode.W && keyEvent.isShortcutDown() && keyEvent.isShiftDown()) {
|
||||||
|
tabs.getTabs().clear();
|
||||||
|
keyEvent.consume();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return tabs;
|
return tabs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +236,7 @@ public class BrowserSessionTabsComp extends SimpleComp {
|
||||||
if (color != null) {
|
if (color != null) {
|
||||||
c.getStyleClass().add(color.getId());
|
c.getStyleClass().add(color.getId());
|
||||||
}
|
}
|
||||||
new TooltipAugment<>(new SimpleStringProperty(model.getTooltip())).augment(c);
|
new TooltipAugment<>(new SimpleStringProperty(model.getTooltip()), null).augment(c);
|
||||||
c.addEventHandler(
|
c.addEventHandler(
|
||||||
DragEvent.DRAG_ENTERED,
|
DragEvent.DRAG_ENTERED,
|
||||||
mouseEvent -> Platform.runLater(
|
mouseEvent -> Platform.runLater(
|
||||||
|
|
|
@ -70,8 +70,8 @@ public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
|
||||||
for (int i = 0; i < entries.size(); i++) {
|
for (int i = 0; i < entries.size(); i++) {
|
||||||
var e = entries.get(i);
|
var e = entries.get(i);
|
||||||
var b = new IconButtonComp(e.icon(), () -> value.setValue(e));
|
var b = new IconButtonComp(e.icon(), () -> value.setValue(e));
|
||||||
b.shortcut(new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + i]));
|
var shortcut = new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + i]);
|
||||||
b.apply(new TooltipAugment<>(e.name()));
|
b.apply(new TooltipAugment<>(e.name(), shortcut));
|
||||||
b.apply(struc -> {
|
b.apply(struc -> {
|
||||||
AppFont.setSize(struc.get(), 2);
|
AppFont.setSize(struc.get(), 2);
|
||||||
struc.get().pseudoClassStateChanged(selected, value.getValue().equals(e));
|
struc.get().pseudoClassStateChanged(selected, value.getValue().equals(e));
|
||||||
|
@ -123,9 +123,9 @@ public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
|
var shortcut = new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + entries.size()]);
|
||||||
var b = new IconButtonComp("mdi2g-github", () -> Hyperlinks.open(Hyperlinks.GITHUB))
|
var b = new IconButtonComp("mdi2g-github", () -> Hyperlinks.open(Hyperlinks.GITHUB))
|
||||||
.shortcut(new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + entries.size()]))
|
.tooltipKey("visitGithubRepository", shortcut)
|
||||||
.apply(new TooltipAugment<>("visitGithubRepository"))
|
|
||||||
.apply(simpleBorders)
|
.apply(simpleBorders)
|
||||||
.accessibleTextKey("visitGithubRepository");
|
.accessibleTextKey("visitGithubRepository");
|
||||||
b.apply(struc -> {
|
b.apply(struc -> {
|
||||||
|
@ -135,9 +135,9 @@ public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
var shortcut = new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + entries.size() + 1]);
|
||||||
var b = new IconButtonComp("mdi2d-discord", () -> Hyperlinks.open(Hyperlinks.DISCORD))
|
var b = new IconButtonComp("mdi2d-discord", () -> Hyperlinks.open(Hyperlinks.DISCORD))
|
||||||
.shortcut(new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + entries.size() + 1]))
|
.tooltipKey("discord", shortcut)
|
||||||
.apply(new TooltipAugment<>("discord"))
|
|
||||||
.apply(simpleBorders)
|
.apply(simpleBorders)
|
||||||
.accessibleTextKey("discord");
|
.accessibleTextKey("discord");
|
||||||
b.apply(struc -> {
|
b.apply(struc -> {
|
||||||
|
@ -147,9 +147,9 @@ public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
var shortcut = new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + entries.size() + 2]);
|
||||||
var b = new IconButtonComp("mdi2t-translate", () -> Hyperlinks.open(Hyperlinks.TRANSLATE))
|
var b = new IconButtonComp("mdi2t-translate", () -> Hyperlinks.open(Hyperlinks.TRANSLATE))
|
||||||
.shortcut(new KeyCodeCombination(KeyCode.values()[KeyCode.DIGIT1.ordinal() + entries.size() + 2]))
|
.tooltipKey("translate", shortcut)
|
||||||
.apply(new TooltipAugment<>("translate"))
|
|
||||||
.apply(simpleBorders)
|
.apply(simpleBorders)
|
||||||
.accessibleTextKey("translate");
|
.accessibleTextKey("translate");
|
||||||
b.apply(struc -> {
|
b.apply(struc -> {
|
||||||
|
@ -160,7 +160,7 @@ public class SideMenuBarComp extends Comp<CompStructure<VBox>> {
|
||||||
|
|
||||||
{
|
{
|
||||||
var b = new IconButtonComp("mdi2u-update", () -> UpdateAvailableAlert.showIfNeeded())
|
var b = new IconButtonComp("mdi2u-update", () -> UpdateAvailableAlert.showIfNeeded())
|
||||||
.apply(new TooltipAugment<>("updateAvailableTooltip"))
|
.tooltipKey("updateAvailableTooltip")
|
||||||
.accessibleTextKey("updateAvailableTooltip");
|
.accessibleTextKey("updateAvailableTooltip");
|
||||||
b.apply(struc -> {
|
b.apply(struc -> {
|
||||||
AppFont.setSize(struc.get(), 2);
|
AppFont.setSize(struc.get(), 2);
|
||||||
|
|
|
@ -190,7 +190,7 @@ public abstract class StoreEntryComp extends SimpleComp {
|
||||||
var imageComp = PrettyImageHelper.ofFixedSize(img, w, h);
|
var imageComp = PrettyImageHelper.ofFixedSize(img, w, h);
|
||||||
var storeIcon = imageComp.createRegion();
|
var storeIcon = imageComp.createRegion();
|
||||||
if (wrapper.getValidity().getValue().isUsable()) {
|
if (wrapper.getValidity().getValue().isUsable()) {
|
||||||
new TooltipAugment<>(wrapper.getEntry().getProvider().displayName()).augment(storeIcon);
|
new TooltipAugment<>(wrapper.getEntry().getProvider().displayName(), null).augment(storeIcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
var stack = new StackPane(storeIcon);
|
var stack = new StackPane(storeIcon);
|
||||||
|
@ -227,7 +227,7 @@ public abstract class StoreEntryComp extends SimpleComp {
|
||||||
button.accessibleText(
|
button.accessibleText(
|
||||||
actionProvider.getName(wrapper.getEntry().ref()).getValue());
|
actionProvider.getName(wrapper.getEntry().ref()).getValue());
|
||||||
button.apply(new TooltipAugment<>(
|
button.apply(new TooltipAugment<>(
|
||||||
actionProvider.getName(wrapper.getEntry().ref())));
|
actionProvider.getName(wrapper.getEntry().ref()), null));
|
||||||
if (actionProvider.activeType() == ActionProvider.DataStoreCallSite.ActiveType.ONLY_SHOW_IF_ENABLED) {
|
if (actionProvider.activeType() == ActionProvider.DataStoreCallSite.ActiveType.ONLY_SHOW_IF_ENABLED) {
|
||||||
button.hide(Bindings.not(p.getValue()));
|
button.hide(Bindings.not(p.getValue()));
|
||||||
} else if (actionProvider.activeType() == ActionProvider.DataStoreCallSite.ActiveType.ALWAYS_SHOW) {
|
} else if (actionProvider.activeType() == ActionProvider.DataStoreCallSite.ActiveType.ALWAYS_SHOW) {
|
||||||
|
@ -266,7 +266,7 @@ public abstract class StoreEntryComp extends SimpleComp {
|
||||||
event -> event.getButton() == MouseButton.PRIMARY,
|
event -> event.getButton() == MouseButton.PRIMARY,
|
||||||
null,
|
null,
|
||||||
() -> StoreEntryComp.this.createContextMenu()));
|
() -> StoreEntryComp.this.createContextMenu()));
|
||||||
settingsButton.apply(new TooltipAugment<>("more"));
|
settingsButton.tooltipKey("more");
|
||||||
return settingsButton;
|
return settingsButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,10 @@ import io.xpipe.app.fxcomps.Comp;
|
||||||
import io.xpipe.app.fxcomps.SimpleComp;
|
import io.xpipe.app.fxcomps.SimpleComp;
|
||||||
import io.xpipe.app.fxcomps.impl.FilterComp;
|
import io.xpipe.app.fxcomps.impl.FilterComp;
|
||||||
import io.xpipe.app.fxcomps.impl.IconButtonComp;
|
import io.xpipe.app.fxcomps.impl.IconButtonComp;
|
||||||
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.ListBindingsHelper;
|
import io.xpipe.app.fxcomps.util.ListBindingsHelper;
|
||||||
import io.xpipe.app.util.ThreadHelper;
|
import io.xpipe.app.util.ThreadHelper;
|
||||||
import io.xpipe.core.process.OsType;
|
import io.xpipe.core.process.OsType;
|
||||||
|
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.property.Property;
|
import javafx.beans.property.Property;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
@ -29,7 +27,6 @@ import javafx.scene.layout.Priority;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.scene.text.TextAlignment;
|
import javafx.scene.text.TextAlignment;
|
||||||
|
|
||||||
import org.kordamp.ikonli.javafx.FontIcon;
|
import org.kordamp.ikonli.javafx.FontIcon;
|
||||||
|
|
||||||
public class StoreEntryListStatusComp extends SimpleComp {
|
public class StoreEntryListStatusComp extends SimpleComp {
|
||||||
|
@ -186,7 +183,7 @@ public class StoreEntryListStatusComp extends SimpleComp {
|
||||||
sortMode));
|
sortMode));
|
||||||
});
|
});
|
||||||
alphabetical.accessibleTextKey("sortAlphabetical");
|
alphabetical.accessibleTextKey("sortAlphabetical");
|
||||||
alphabetical.apply(new TooltipAugment<>("sortAlphabetical"));
|
alphabetical.tooltipKey("sortAlphabetical");
|
||||||
return alphabetical;
|
return alphabetical;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +222,7 @@ public class StoreEntryListStatusComp extends SimpleComp {
|
||||||
sortMode));
|
sortMode));
|
||||||
});
|
});
|
||||||
date.accessibleTextKey("sortLastUsed");
|
date.accessibleTextKey("sortLastUsed");
|
||||||
date.apply(new TooltipAugment<>("sortLastUsed"));
|
date.tooltipKey("sortLastUsed");
|
||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import io.xpipe.app.prefs.AppPrefs;
|
||||||
import io.xpipe.app.prefs.CloseBehaviourAlert;
|
import io.xpipe.app.prefs.CloseBehaviourAlert;
|
||||||
import io.xpipe.app.util.ThreadHelper;
|
import io.xpipe.app.util.ThreadHelper;
|
||||||
import io.xpipe.core.process.OsType;
|
import io.xpipe.core.process.OsType;
|
||||||
|
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.BooleanProperty;
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
import javafx.geometry.Rectangle2D;
|
import javafx.geometry.Rectangle2D;
|
||||||
|
@ -17,18 +16,17 @@ import javafx.scene.input.KeyEvent;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
import javafx.stage.Screen;
|
import javafx.stage.Screen;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.jackson.Jacksonized;
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
|
|
||||||
public class AppMainWindow {
|
public class AppMainWindow {
|
||||||
|
|
||||||
|
@ -157,6 +155,13 @@ public class AppMainWindow {
|
||||||
e.consume();
|
e.consume();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
stage.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
||||||
|
if (event.getCode().equals(KeyCode.Q) && event.isShortcutDown()) {
|
||||||
|
stage.close();
|
||||||
|
event.consume();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
TrackEvent.debug("Window listeners added");
|
TrackEvent.debug("Window listeners added");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,12 +161,10 @@ public class AppWindowHelper {
|
||||||
event.consume();
|
event.consume();
|
||||||
});
|
});
|
||||||
a.getDialogPane().getScene().addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
a.getDialogPane().getScene().addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
||||||
if (OsType.getLocal().equals(OsType.LINUX) || OsType.getLocal().equals(OsType.MACOS)) {
|
if (event.getCode().equals(KeyCode.W) && event.isShortcutDown()) {
|
||||||
if (event.getCode().equals(KeyCode.W) && event.isShortcutDown()) {
|
s.close();
|
||||||
s.close();
|
event.consume();
|
||||||
event.consume();
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.getCode().equals(KeyCode.ESCAPE)) {
|
if (event.getCode().equals(KeyCode.ESCAPE)) {
|
||||||
|
@ -274,11 +272,9 @@ public class AppWindowHelper {
|
||||||
});
|
});
|
||||||
|
|
||||||
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
||||||
if (OsType.getLocal().equals(OsType.LINUX) || OsType.getLocal().equals(OsType.MACOS)) {
|
if (event.getCode().equals(KeyCode.W) && event.isShortcutDown()) {
|
||||||
if (event.getCode().equals(KeyCode.W) && event.isShortcutDown()) {
|
stage.close();
|
||||||
stage.close();
|
event.consume();
|
||||||
event.consume();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.xpipe.app.fxcomps;
|
package io.xpipe.app.fxcomps;
|
||||||
|
|
||||||
|
import atlantafx.base.controls.Spacer;
|
||||||
import io.xpipe.app.core.AppI18n;
|
import io.xpipe.app.core.AppI18n;
|
||||||
import io.xpipe.app.fxcomps.augment.Augment;
|
import io.xpipe.app.fxcomps.augment.Augment;
|
||||||
import io.xpipe.app.fxcomps.augment.GrowAugment;
|
import io.xpipe.app.fxcomps.augment.GrowAugment;
|
||||||
|
@ -7,12 +8,10 @@ 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 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;
|
||||||
import javafx.geometry.Orientation;
|
import javafx.geometry.Orientation;
|
||||||
import javafx.scene.control.ButtonBase;
|
|
||||||
import javafx.scene.control.Separator;
|
import javafx.scene.control.Separator;
|
||||||
import javafx.scene.input.KeyCombination;
|
import javafx.scene.input.KeyCombination;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
|
@ -20,8 +19,6 @@ import javafx.scene.layout.Priority;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
|
|
||||||
import atlantafx.base.controls.Spacer;
|
|
||||||
|
|
||||||
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.Consumer;
|
||||||
|
@ -186,20 +183,20 @@ public abstract class Comp<S extends CompStructure<?>> {
|
||||||
return apply(struc -> Shortcuts.addShortcut(struc.get(), shortcut, r -> con.accept(struc)));
|
return apply(struc -> Shortcuts.addShortcut(struc.get(), shortcut, r -> con.accept(struc)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Comp<S> shortcut(KeyCombination shortcut) {
|
|
||||||
return apply(struc -> Shortcuts.addShortcut((ButtonBase) struc.get(), shortcut));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Comp<S> displayOnlyShortcut(KeyCombination shortcut) {
|
public Comp<S> displayOnlyShortcut(KeyCombination shortcut) {
|
||||||
return apply(struc -> Shortcuts.addDisplayShortcut(struc.get(), 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));
|
return apply(new TooltipAugment<>(text, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Comp<S> tooltipKey(String key) {
|
public Comp<S> tooltipKey(String key) {
|
||||||
return apply(new TooltipAugment<>(key));
|
return apply(new TooltipAugment<>(key, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Comp<S> tooltipKey(String key, KeyCombination shortcut) {
|
||||||
|
return apply(new TooltipAugment<>(key, shortcut));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Region createRegion() {
|
public Region createRegion() {
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class ContextMenuAugment<S extends CompStructure<?>> implements Augment<S
|
||||||
};
|
};
|
||||||
|
|
||||||
var r = struc.get();
|
var r = struc.get();
|
||||||
r.addEventFilter(MouseEvent.MOUSE_CLICKED, event -> {
|
r.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
|
||||||
if (mouseEventCheck != null && mouseEventCheck.test(event)) {
|
if (mouseEventCheck != null && mouseEventCheck.test(event)) {
|
||||||
if (!hide.get()) {
|
if (!hide.get()) {
|
||||||
var cm = contextMenu.get();
|
var cm = contextMenu.get();
|
||||||
|
@ -55,18 +55,18 @@ public class ContextMenuAugment<S extends CompStructure<?>> implements Augment<S
|
||||||
event.consume();
|
event.consume();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
r.addEventFilter(MouseEvent.MOUSE_PRESSED, event -> {
|
r.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> {
|
||||||
if (mouseEventCheck != null && mouseEventCheck.test(event)) {
|
if (mouseEventCheck != null && mouseEventCheck.test(event)) {
|
||||||
event.consume();
|
event.consume();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
r.addEventFilter(KeyEvent.KEY_RELEASED, event -> {
|
r.addEventHandler(KeyEvent.KEY_RELEASED, event -> {
|
||||||
if (keyEventCheck != null && keyEventCheck.test(event)) {
|
if (keyEventCheck != null && keyEventCheck.test(event)) {
|
||||||
event.consume();
|
event.consume();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
r.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
r.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
|
||||||
if (keyEventCheck != null && keyEventCheck.test(event)) {
|
if (keyEventCheck != null && keyEventCheck.test(event)) {
|
||||||
if (!hide.get()) {
|
if (!hide.get()) {
|
||||||
var cm = contextMenu.get();
|
var cm = contextMenu.get();
|
||||||
|
@ -80,7 +80,7 @@ public class ContextMenuAugment<S extends CompStructure<?>> implements Augment<S
|
||||||
});
|
});
|
||||||
|
|
||||||
if (r instanceof ButtonBase buttonBase && keyEventCheck == null) {
|
if (r instanceof ButtonBase buttonBase && keyEventCheck == null) {
|
||||||
buttonBase.addEventFilter(ActionEvent.ACTION, event -> {
|
buttonBase.addEventHandler(ActionEvent.ACTION, event -> {
|
||||||
if (buttonBase.getOnAction() != null) {
|
if (buttonBase.getOnAction() != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,7 @@ public class ContextualFileReferenceChoiceComp extends Comp<CompStructure<HBox>>
|
||||||
ErrorEvent.fromThrowable(e).handle();
|
ErrorEvent.fromThrowable(e).handle();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
gitShareButton.apply(new TooltipAugment<>("gitShareFileTooltip"));
|
gitShareButton.tooltipKey("gitShareFileTooltip");
|
||||||
gitShareButton.styleClass(Styles.RIGHT_PILL).grow(false, true);
|
gitShareButton.styleClass(Styles.RIGHT_PILL).grow(false, true);
|
||||||
|
|
||||||
var layout = new HorizontalComp(List.of(fileNameComp, fileBrowseButton, gitShareButton))
|
var layout = new HorizontalComp(List.of(fileNameComp, fileBrowseButton, gitShareButton))
|
||||||
|
|
|
@ -4,47 +4,46 @@ import io.xpipe.app.core.AppI18n;
|
||||||
import io.xpipe.app.fxcomps.CompStructure;
|
import io.xpipe.app.fxcomps.CompStructure;
|
||||||
import io.xpipe.app.fxcomps.augment.Augment;
|
import io.xpipe.app.fxcomps.augment.Augment;
|
||||||
import io.xpipe.app.fxcomps.util.PlatformThread;
|
import io.xpipe.app.fxcomps.util.PlatformThread;
|
||||||
import io.xpipe.app.fxcomps.util.Shortcuts;
|
|
||||||
|
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.scene.control.Tooltip;
|
import javafx.scene.control.Tooltip;
|
||||||
|
import javafx.scene.input.KeyCombination;
|
||||||
import javafx.stage.Window;
|
import javafx.stage.Window;
|
||||||
|
|
||||||
public class TooltipAugment<S extends CompStructure<?>> implements Augment<S> {
|
public class TooltipAugment<S extends CompStructure<?>> implements Augment<S> {
|
||||||
|
|
||||||
private final ObservableValue<String> text;
|
private final ObservableValue<String> text;
|
||||||
|
private final KeyCombination shortcut;
|
||||||
|
|
||||||
public TooltipAugment(ObservableValue<String> text) {
|
public TooltipAugment(ObservableValue<String> text, KeyCombination shortcut) {
|
||||||
this.text = PlatformThread.sync(text);
|
this.text = text;
|
||||||
|
this.shortcut = shortcut;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TooltipAugment(String key) {
|
public TooltipAugment(String key, KeyCombination shortcut) {
|
||||||
this.text = AppI18n.observable(key);
|
this.text = AppI18n.observable(key);
|
||||||
|
this.shortcut = shortcut;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void augment(S struc) {
|
public void augment(S struc) {
|
||||||
var region = struc.get();
|
|
||||||
var tt = new FixedTooltip();
|
var tt = new FixedTooltip();
|
||||||
if (Shortcuts.getDisplayShortcut(region) != null) {
|
if (shortcut != null) {
|
||||||
var s = AppI18n.observable("shortcut");
|
var s = AppI18n.observable("shortcut");
|
||||||
var binding = Bindings.createStringBinding(
|
var binding = Bindings.createStringBinding(
|
||||||
() -> {
|
() -> {
|
||||||
return text.getValue() + "\n\n" + s.getValue() + ": "
|
return text.getValue() + "\n\n" + s.getValue() + ": " + shortcut.getDisplayText();
|
||||||
+ Shortcuts.getDisplayShortcut(region).getDisplayText();
|
|
||||||
},
|
},
|
||||||
text,
|
text,
|
||||||
s);
|
s);
|
||||||
tt.textProperty().bind(binding);
|
tt.textProperty().bind(PlatformThread.sync(binding));
|
||||||
} else {
|
} else {
|
||||||
tt.textProperty().bind(text);
|
tt.textProperty().bind(PlatformThread.sync(text));
|
||||||
}
|
}
|
||||||
tt.setStyle("-fx-font-size: 11pt;");
|
tt.setStyle("-fx-font-size: 11pt;");
|
||||||
tt.setWrapText(true);
|
tt.setWrapText(true);
|
||||||
tt.setMaxWidth(400);
|
tt.setMaxWidth(400);
|
||||||
tt.getStyleClass().add("fancy-tooltip");
|
tt.getStyleClass().add("fancy-tooltip");
|
||||||
|
|
||||||
Tooltip.install(struc.get(), tt);
|
Tooltip.install(struc.get(), tt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package io.xpipe.app.util;
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
import javafx.event.EventTarget;
|
import javafx.event.EventTarget;
|
||||||
import javafx.scene.input.KeyCode;
|
import javafx.scene.input.KeyCode;
|
||||||
|
import javafx.scene.input.KeyCombination;
|
||||||
import javafx.scene.input.KeyEvent;
|
import javafx.scene.input.KeyEvent;
|
||||||
import javafx.scene.input.MouseEvent;
|
import javafx.scene.input.MouseEvent;
|
||||||
|
|
||||||
|
@ -11,9 +12,17 @@ import java.util.function.Consumer;
|
||||||
|
|
||||||
public class InputHelper {
|
public class InputHelper {
|
||||||
|
|
||||||
public static void onLeft(EventTarget target, boolean filter, Consumer<KeyEvent> r) {
|
public static void onCtrlKeyCode(EventTarget target, KeyCode code, boolean filter, Consumer<KeyEvent> r) {
|
||||||
EventHandler<KeyEvent> keyEventEventHandler = event -> {
|
EventHandler<KeyEvent> keyEventEventHandler = event -> {
|
||||||
if (event.getCode() == KeyCode.LEFT || event.getCode() == KeyCode.NUMPAD4) {
|
if (event.isAltDown() || event.isShiftDown()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!event.isShortcutDown()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code == event.getCode()) {
|
||||||
r.accept(event);
|
r.accept(event);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -24,9 +33,9 @@ public class InputHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onRight(EventTarget target, 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 (event.getCode() == KeyCode.RIGHT || event.getCode() == KeyCode.NUMPAD6) {
|
if (c.match(event)) {
|
||||||
r.accept(event);
|
r.accept(event);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -37,6 +46,60 @@ public class InputHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void onExactKeyCode(EventTarget target, KeyCode code, boolean filter, Consumer<KeyEvent> r) {
|
||||||
|
EventHandler<KeyEvent> keyEventEventHandler = event -> {
|
||||||
|
if (event.isAltDown() || event.isShiftDown() || 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 onInput(EventTarget target, boolean filter, Consumer<KeyEvent> r) {
|
||||||
|
EventHandler<KeyEvent> keyEventEventHandler = event -> {
|
||||||
|
r.accept(event);
|
||||||
|
};
|
||||||
|
if (filter) {
|
||||||
|
target.addEventFilter(KeyEvent.KEY_PRESSED, keyEventEventHandler);
|
||||||
|
} else {
|
||||||
|
target.addEventHandler(KeyEvent.KEY_PRESSED, keyEventEventHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onLeft(EventTarget target, boolean filter, Consumer<KeyEvent> r) {
|
||||||
|
EventHandler<KeyEvent> e = event -> {
|
||||||
|
if (event.getCode() == KeyCode.LEFT || event.getCode() == KeyCode.NUMPAD4) {
|
||||||
|
r.accept(event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (filter) {
|
||||||
|
target.addEventFilter(KeyEvent.KEY_PRESSED, e);
|
||||||
|
} else {
|
||||||
|
target.addEventHandler(KeyEvent.KEY_PRESSED, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onRight(EventTarget target, boolean filter, Consumer<KeyEvent> r) {
|
||||||
|
EventHandler<KeyEvent> e = event -> {
|
||||||
|
if (event.getCode() == KeyCode.RIGHT || event.getCode() == KeyCode.NUMPAD6) {
|
||||||
|
r.accept(event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (filter) {
|
||||||
|
target.addEventFilter(KeyEvent.KEY_PRESSED, e);
|
||||||
|
} else {
|
||||||
|
target.addEventHandler(KeyEvent.KEY_PRESSED, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void onNavigationInput(EventTarget target, Consumer<Boolean> r) {
|
public static void onNavigationInput(EventTarget target, Consumer<Boolean> r) {
|
||||||
target.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
target.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
|
||||||
var c = event.getCode();
|
var c = event.getCode();
|
||||||
|
|
|
@ -182,10 +182,14 @@
|
||||||
-fx-background-color: -color-accent-subtle;
|
-fx-background-color: -color-accent-subtle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.browser .table-row-cell:selected, .browser .table-row-cell:hover:selected {
|
.browser .table-row-cell:selected, .browser .table-row-cell:hover:selected, .root:key-navigation .browser .table-row-cell:focused:selected {
|
||||||
-fx-background-color: -color-success-subtle;
|
-fx-background-color: -color-success-subtle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root:key-navigation .browser .table-row-cell:focused {
|
||||||
|
-fx-background-color: -color-warning-subtle;
|
||||||
|
}
|
||||||
|
|
||||||
.root.nord .browser .table-row-cell:selected, .root.nord .browser .table-row-cell:hover:selected {
|
.root.nord .browser .table-row-cell:selected, .root.nord .browser .table-row-cell:hover:selected {
|
||||||
-fx-background-color: -color-success-7;
|
-fx-background-color: -color-success-7;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,9 @@ 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;
|
||||||
|
@ -34,6 +37,11 @@ public class OpenDirectoryInNewTabAction implements LeafAction {
|
||||||
return Category.OPEN;
|
return Category.OPEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyCombination getShortcut() {
|
||||||
|
return new KeyCodeCombination(KeyCode.ENTER, KeyCombination.SHIFT_DOWN);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean acceptsEmptySelection() {
|
public boolean acceptsEmptySelection() {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -10,6 +10,9 @@ import io.xpipe.core.process.ShellControl;
|
||||||
import io.xpipe.core.store.FileNames;
|
import io.xpipe.core.store.FileNames;
|
||||||
|
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
|
import javafx.scene.input.KeyCodeCombination;
|
||||||
|
import javafx.scene.input.KeyCombination;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -62,6 +65,11 @@ public class OpenNativeFileDetailsAction implements LeafAction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeyCombination getShortcut() {
|
||||||
|
return new KeyCodeCombination(KeyCode.ENTER,KeyCombination.ALT_DOWN);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Category getCategory() {
|
public Category getCategory() {
|
||||||
return Category.NATIVE;
|
return Category.NATIVE;
|
||||||
|
|
Loading…
Reference in a new issue