This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit 940d30674b21a48fd8e93bf161200ba5e7c3576d Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Tue Dec 28 21:13:35 2021 +0100 Add a menu for opening the folder containing a file. --- .../dataset/{CopyAction.java => PathAction.java} | 38 +++++++++++++++++++--- .../org/apache/sis/gui/dataset/ResourceTree.java | 8 +++-- .../org/apache/sis/internal/gui/Resources.java | 5 +++ .../apache/sis/internal/gui/Resources.properties | 1 + .../sis/internal/gui/Resources_fr.properties | 1 + .../sis/internal/storage/io/IOUtilities.java | 23 ++++++++++++- 6 files changed, 67 insertions(+), 9 deletions(-) diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/CopyAction.java b/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/PathAction.java similarity index 80% rename from application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/CopyAction.java rename to application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/PathAction.java index 206c014..29ea6ae 100644 --- a/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/CopyAction.java +++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/PathAction.java @@ -16,6 +16,7 @@ */ package org.apache.sis.gui.dataset; +import java.awt.Desktop; import java.util.List; import java.util.ArrayList; import java.util.Collections; @@ -37,27 +38,43 @@ import org.apache.sis.storage.Resource; /** - * The "Copy file path" action. This class gets the file path of a resource and copies it in the clipboard. + * The "Copy file path" or "Open containing folder" action. + * This class gets the file path of a resource and copies it in the clipboard + * or open the containing folder using native file browser. * * @author Martin Desruisseaux (Geomatys) - * @version 1.1 + * @version 1.2 * @since 1.1 * @module */ -final class CopyAction implements EventHandler<ActionEvent> { +final class PathAction implements EventHandler<ActionEvent> { /** * The cell for which to provide a copy action. */ private final TreeCell<Resource> cell; /** + * {@code true} for opening native file browser, or {@code false} for copying to clipboard. + */ + private final boolean browser; + + /** * Creates a new instance. + * + * @param browser {@code true} for opening native file browser, or {@code false} for copying to clipboard. */ - CopyAction(final TreeCell<Resource> source) { - this.cell = source; + PathAction(final TreeCell<Resource> source, final boolean browser) { + this.cell = source; + this.browser = browser; } /** + * Whether the "Open containing folder" operation is disabled. + */ + static final boolean isBrowseDisabled = !(Desktop.isDesktopSupported() && + Desktop.getDesktop().isSupported(Desktop.Action.BROWSE_FILE_DIR)); + + /** * Invoked when the user selected "Copy file path" item in the contextual menu of a {@link ResourceTree} cell. * This method copies the path of the selected resource to the clipboard. */ @@ -103,6 +120,17 @@ final class CopyAction implements EventHandler<ActionEvent> { // Ignore. The `uri` or `text` field that we failed to assign keep its original value. } /* + * If this action is for opening the native file browser, we can do it now. + */ + if (browser) { + if (file instanceof File) try { + Desktop.getDesktop().browseFileDirectory((File) file); + } catch (Exception e) { + ExceptionReporter.show(cell.getTreeView(), null, null, e); + } + return; + } + /* * Above code obtained a single path, considered the main one. But a resource may also be * associated with many files (some kinds of data are actually provided as a group of files). * We put in the clipboard all `java.io.File` instances that we can get from the resource. diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/ResourceTree.java b/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/ResourceTree.java index c258b41..a88cdc0 100644 --- a/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/ResourceTree.java +++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/ResourceTree.java @@ -685,8 +685,9 @@ public class ResourceTree extends TreeView<Resource> { menu = new ContextMenu(); final Resources localized = tree.localized(); final MenuItem[] items = new MenuItem[CLOSE + 1]; - items[COPY_PATH] = localized.menu(Resources.Keys.CopyFilePath, new CopyAction(this)); - items[CLOSE] = localized.menu(Resources.Keys.Close, (e) -> { + items[COPY_PATH] = localized.menu(Resources.Keys.CopyFilePath, new PathAction(this, false)); + items[OPEN_FOLDER] = localized.menu(Resources.Keys.OpenContainingFolder, new PathAction(this, true)); + items[CLOSE] = localized.menu(Resources.Keys.Close, (e) -> { ((ResourceTree) getTreeView()).removeAndClose(getItem()); }); menu.getItems().setAll(items); @@ -703,6 +704,7 @@ public class ResourceTree extends TreeView<Resource> { unexpectedException("updateItem", e); } menu.getItems().get(COPY_PATH).setDisable(!IOUtilities.isKindOfPath(path)); + menu.getItems().get(OPEN_FOLDER).setDisable(PathAction.isBrowseDisabled || IOUtilities.toFile(path) == null); } } setText(text); @@ -715,7 +717,7 @@ public class ResourceTree extends TreeView<Resource> { * Position of menu items in the contextual menu built by {@link #updateItem(Resource, boolean)}. * Above method assumes that {@link #CLOSE} is the last menu item. */ - private static final int COPY_PATH = 0, CLOSE = 1; + private static final int COPY_PATH = 0, OPEN_FOLDER = 1, CLOSE = 2; } diff --git a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Resources.java b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Resources.java index 518467f..6011b18 100644 --- a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Resources.java +++ b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Resources.java @@ -303,6 +303,11 @@ public final class Resources extends IndexedResourceBundle { public static final short Open = 28; /** + * Open containing folder + */ + public static final short OpenContainingFolder = 66; + + /** * Open data file */ public static final short OpenDataFile = 29; diff --git a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Resources.properties b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Resources.properties index 70125be..9444b62 100644 --- a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Resources.properties +++ b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Resources.properties @@ -69,6 +69,7 @@ MainWindow = Main window NewWindow = New window NoFeatureTypeInfo = No feature type information. Open = Open\u2026 +OpenContainingFolder = Open containing folder OpenDataFile = Open data file OpenRecentFile = Open recent file Orthographic = Orthographic diff --git a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Resources_fr.properties b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Resources_fr.properties index d580bee..eece6be 100644 --- a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Resources_fr.properties +++ b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Resources_fr.properties @@ -74,6 +74,7 @@ MainWindow = Fen\u00eatre principale NewWindow = Nouvelle fen\u00eatre NoFeatureTypeInfo = Pas d\u2019information sur le type d\u2019entit\u00e9. Open = Ouvrir\u2026 +OpenContainingFolder = Ouvrir le dossier contenant OpenDataFile = Ouvrir un fichier de donn\u00e9es OpenRecentFile = Ouvrir un fichier r\u00e9cent Orthographic = Orthographique diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java index 2c65096..f9a6cba 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java @@ -59,7 +59,7 @@ import org.apache.sis.internal.storage.Resources; * * @author Martin Desruisseaux (Geomatys) * @author Johann Sorel (Geomatys) - * @version 1.1 + * @version 1.2 * @since 0.3 * @module */ @@ -181,6 +181,27 @@ public final class IOUtilities extends Static { } /** + * Returns the given path as a {@link File}, or {@code null} if it can not be converted. + * + * @param path the object to convert to a {@link File}. Can be {@code null}. + * @return the given path as a {@link File}, or {@code null} if it can not be converted. + */ + public static File toFile(final Object path) { + if (path instanceof File) { + return (File) path; + } else if (path instanceof Path) try { + return ((Path) path).toFile(); + } catch (UnsupportedOperationException e) { + // Ignore. + } else if (path instanceof URI) try { + return new File((URI) path); + } catch (IllegalArgumentException e) { + // Ignore. + } + return null; + } + + /** * Returns the given path without the directories and without the extension. * For example if the given path is {@code "/Users/name/Map.png"}, then this * method returns {@code "Map"}.