From 0eea4f3e3f72fcfa2d79e4f21d59939f4c9e9edf Mon Sep 17 00:00:00 2001 From: crschnick Date: Mon, 15 May 2023 19:39:50 +0000 Subject: [PATCH] Improve browser navigation bar --- .../io/xpipe/app/browser/BrowserNavBar.java | 50 +++++++++++++++++++ .../app/browser/FileBrowserBreadcrumbBar.java | 10 +++- .../xpipe/app/browser/OpenFileSystemComp.java | 13 +---- .../io/xpipe/app/resources/style/browser.css | 10 +++- .../java/io/xpipe/core/process/OsType.java | 17 +++++++ 5 files changed, 85 insertions(+), 15 deletions(-) create mode 100644 app/src/main/java/io/xpipe/app/browser/BrowserNavBar.java diff --git a/app/src/main/java/io/xpipe/app/browser/BrowserNavBar.java b/app/src/main/java/io/xpipe/app/browser/BrowserNavBar.java new file mode 100644 index 00000000..da210dd4 --- /dev/null +++ b/app/src/main/java/io/xpipe/app/browser/BrowserNavBar.java @@ -0,0 +1,50 @@ +package io.xpipe.app.browser; + +import io.xpipe.app.fxcomps.SimpleComp; +import io.xpipe.app.fxcomps.impl.TextFieldComp; +import io.xpipe.app.fxcomps.util.SimpleChangeListener; +import javafx.beans.property.SimpleStringProperty; +import javafx.css.PseudoClass; +import javafx.geometry.Pos; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.Region; +import javafx.scene.layout.StackPane; + +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 + protected Region createSimple() { + var path = new SimpleStringProperty(model.getCurrentPath().get()); + path.addListener((observable, oldValue, newValue) -> { + var changed = model.cd(newValue); + changed.ifPresent(path::set); + }); + var pathBar = new TextFieldComp(path, true).createRegion(); + pathBar.getStyleClass().add("path-text"); + model.getCurrentPath().addListener((observable, oldValue, newValue) -> { + path.set(newValue); + }); + SimpleChangeListener.apply(pathBar.focusedProperty(), val -> { + pathBar.pseudoClassStateChanged(INVISIBLE, !val); + }); + + var breadcrumbs = new FileBrowserBreadcrumbBar(model) + .hide(pathBar.focusedProperty()) + .createRegion(); + + var stack = new StackPane(pathBar, breadcrumbs); + HBox.setHgrow(stack, Priority.ALWAYS); + stack.setAlignment(Pos.CENTER_LEFT); + + return stack; + } +} diff --git a/app/src/main/java/io/xpipe/app/browser/FileBrowserBreadcrumbBar.java b/app/src/main/java/io/xpipe/app/browser/FileBrowserBreadcrumbBar.java index 12438bb0..83e9cba4 100644 --- a/app/src/main/java/io/xpipe/app/browser/FileBrowserBreadcrumbBar.java +++ b/app/src/main/java/io/xpipe/app/browser/FileBrowserBreadcrumbBar.java @@ -1,7 +1,6 @@ package io.xpipe.app.browser; import atlantafx.base.controls.Breadcrumbs; -import atlantafx.base.theme.Styles; import io.xpipe.app.fxcomps.SimpleComp; import io.xpipe.app.fxcomps.util.PlatformThread; import io.xpipe.app.fxcomps.util.SimpleChangeListener; @@ -9,6 +8,7 @@ import io.xpipe.core.impl.FileNames; import javafx.scene.Node; import javafx.scene.control.Button; import javafx.scene.control.ButtonBase; +import javafx.scene.control.Label; import javafx.scene.layout.Region; import javafx.util.Callback; @@ -24,7 +24,6 @@ public class FileBrowserBreadcrumbBar extends SimpleComp { protected Region createSimple() { Callback, ButtonBase> crumbFactory = crumb -> { var btn = new Button(FileNames.getFileName(crumb.getValue()), null); - btn.getStyleClass().add(Styles.FLAT); btn.setFocusTraversable(false); return btn; }; @@ -42,6 +41,13 @@ public class FileBrowserBreadcrumbBar extends SimpleComp { return; } + var sc = model.getFileSystem().getShell(); + if (sc.isEmpty()) { + breadcrumbs.setDividerFactory(item -> item != null && !item.isLast() ? new Label("/") : null); + } else { + breadcrumbs.setDividerFactory(item -> item != null && !item.isLast() ? new Label(sc.get().getOsType().getFileSystemSeparator()) : null); + } + var elements = FileNames.splitHierarchy(val); Breadcrumbs.BreadCrumbItem items = Breadcrumbs.buildTreeModel(elements.toArray(String[]::new)); breadcrumbs.setSelectedCrumb(items); diff --git a/app/src/main/java/io/xpipe/app/browser/OpenFileSystemComp.java b/app/src/main/java/io/xpipe/app/browser/OpenFileSystemComp.java index 56c6a972..b6261186 100644 --- a/app/src/main/java/io/xpipe/app/browser/OpenFileSystemComp.java +++ b/app/src/main/java/io/xpipe/app/browser/OpenFileSystemComp.java @@ -54,17 +54,6 @@ public class OpenFileSystemComp extends SimpleComp { forthBtn.setOnAction(e -> model.forth()); forthBtn.disableProperty().bind(model.getHistory().canGoForthProperty().not()); - var path = new SimpleStringProperty(model.getCurrentPath().get()); - var pathBar = new TextFieldComp(path, true).createRegion(); - path.addListener((observable, oldValue, newValue) -> { - var changed = model.cd(newValue); - changed.ifPresent(path::set); - }); - model.getCurrentPath().addListener((observable, oldValue, newValue) -> { - path.set(newValue); - }); - HBox.setHgrow(pathBar, Priority.ALWAYS); - var refreshBtn = new Button(null, new FontIcon("mdmz-refresh")); refreshBtn.setOnAction(e -> model.refresh()); Shortcuts.addShortcut(refreshBtn, new KeyCodeCombination(KeyCode.F5)); @@ -86,7 +75,7 @@ public class OpenFileSystemComp extends SimpleComp { var topBar = new ToolBar(); topBar.getItems() - .setAll(backBtn, forthBtn, new Spacer(10), new FileBrowserBreadcrumbBar(model).createRegion(), filter.get(), refreshBtn, terminalBtn, addBtn); + .setAll(backBtn, forthBtn, new Spacer(10), new BrowserNavBar(model).createRegion(), filter.get(), refreshBtn, terminalBtn, addBtn); // ~ diff --git a/app/src/main/resources/io/xpipe/app/resources/style/browser.css b/app/src/main/resources/io/xpipe/app/resources/style/browser.css index c8ac0b39..a363b3eb 100644 --- a/app/src/main/resources/io/xpipe/app/resources/style/browser.css +++ b/app/src/main/resources/io/xpipe/app/resources/style/browser.css @@ -82,7 +82,15 @@ } .browser .breadcrumbs .button { --fx-padding: 0; +-fx-padding: 3px 1px 3px 1px; +-fx-background-color: transparent; +} + +.browser .breadcrumbs .button:hover { +-fx-background-color: -color-neutral-muted; +} +.browser .path-text:invisible { +-fx-text-fill: transparent; } .browser .context-menu .accelerator-text { diff --git a/core/src/main/java/io/xpipe/core/process/OsType.java b/core/src/main/java/io/xpipe/core/process/OsType.java index 5d2a42c8..a911e897 100644 --- a/core/src/main/java/io/xpipe/core/process/OsType.java +++ b/core/src/main/java/io/xpipe/core/process/OsType.java @@ -25,6 +25,8 @@ public sealed interface OsType permits OsType.Windows, OsType.Linux, OsType.MacO String getHomeDirectory(ShellControl pc) throws Exception; + String getFileSystemSeparator(); + String getName(); String getTempDirectory(ShellControl pc) throws Exception; @@ -41,6 +43,11 @@ public sealed interface OsType permits OsType.Windows, OsType.Linux, OsType.MacO pc.getShellDialect().getPrintEnvironmentVariableCommand("USERPROFILE")); } + @Override + public String getFileSystemSeparator() { + return "\\"; + } + @Override public String getName() { return "Windows"; @@ -87,6 +94,11 @@ public sealed interface OsType permits OsType.Windows, OsType.Linux, OsType.MacO return pc.executeSimpleStringCommand(pc.getShellDialect().getPrintEnvironmentVariableCommand("HOME")); } + @Override + public String getFileSystemSeparator() { + return "/"; + } + @Override public String getTempDirectory(ShellControl pc) throws Exception { return "/tmp/"; @@ -157,6 +169,11 @@ public sealed interface OsType permits OsType.Windows, OsType.Linux, OsType.MacO return found; } + @Override + public String getFileSystemSeparator() { + return "/"; + } + @Override public String getName() { return "Mac";