You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2021/11/02 13:12:43 UTC
[sis] branch geoapi-4.0 updated: Better recording of recently used
file (ordered by file closed instead of file opened,
remove from menu the opened files).
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
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new b957357 Better recording of recently used file (ordered by file closed instead of file opened, remove from menu the opened files).
b957357 is described below
commit b957357d51d50e7aa8e3aca9a1a8754853ebfa2c
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Tue Nov 2 13:57:47 2021 +0100
Better recording of recently used file (ordered by file closed instead of file opened, remove from menu the opened files).
---
.../main/java/org/apache/sis/gui/RecentFiles.java | 55 +++++---
.../java/org/apache/sis/gui/dataset/LoadEvent.java | 31 +----
.../dataset/{LoadEvent.java => ResourceEvent.java} | 41 ++++--
.../apache/sis/gui/dataset/ResourceExplorer.java | 29 ++++-
.../org/apache/sis/gui/dataset/ResourceTree.java | 141 ++++++++++++++-------
.../apache/sis/internal/gui/ResourceLoader.java | 2 +-
6 files changed, 190 insertions(+), 109 deletions(-)
diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/RecentFiles.java b/application/sis-javafx/src/main/java/org/apache/sis/gui/RecentFiles.java
index 7a5a9fd..42ec7f6 100644
--- a/application/sis-javafx/src/main/java/org/apache/sis/gui/RecentFiles.java
+++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/RecentFiles.java
@@ -25,7 +25,7 @@ import javafx.event.EventHandler;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.collections.ObservableList;
-import org.apache.sis.gui.dataset.LoadEvent;
+import org.apache.sis.gui.dataset.ResourceEvent;
import org.apache.sis.gui.dataset.ResourceExplorer;
import org.apache.sis.internal.gui.Resources;
import org.apache.sis.internal.gui.RecentChoices;
@@ -36,7 +36,7 @@ import org.apache.sis.util.ArraysExt;
* Manages a list of recently opened files. The list of files is initialized from user preferences.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.2
* @since 1.1
*/
final class RecentFiles implements EventHandler<ActionEvent> {
@@ -65,9 +65,9 @@ final class RecentFiles implements EventHandler<ActionEvent> {
}
/**
- * Creates a menu for a list of recently used files. The menu is initialized with a list of files
- * fetched for user preferences. The user preferences are updated when {@link #opened(LoadEvent)}
- * is invoked.
+ * Creates a menu for a list of recently used files.
+ * The menu is initialized with a list of files fetched from user preferences.
+ * The user preferences are updated when {@link #touched(ResourceEvent, boolean)} is invoked.
*/
static Menu create(final ResourceExplorer explorer, final Resources localized) {
final Menu menu = new Menu(localized.getString(Resources.Keys.OpenRecentFile));
@@ -82,7 +82,8 @@ final class RecentFiles implements EventHandler<ActionEvent> {
}
}
handler.items.setAll(ArraysExt.resize(items, n));
- explorer.setOnResourceLoaded(handler::opened);
+ explorer.setOnResourceLoaded((e) -> handler.touched(e, false));
+ explorer.setOnResourceClosed((e) -> handler.touched(e, true));
return menu;
}
@@ -93,15 +94,17 @@ final class RecentFiles implements EventHandler<ActionEvent> {
final MenuItem item = new MenuItem(file.getName());
item.setUserData(file);
item.setOnAction(this);
+ item.setDisable(!file.exists());
return item;
}
/**
- * Notifies that a file has been opened. A new menu items is created for the specified file
- * and is inserted at the beginning of the list of recent files. If the list of recent files
- * has more than {@value #MAX_COUNT} elements, the latest item is discarded.
+ * Notifies that a file is opened or closed. If opened, the file item (if any) is temporarily removed.
+ * If closed, a new menu items is created for the specified file and is inserted at the beginning of
+ * the list of recent files. If the list of recent files has more than {@value #MAX_COUNT} elements,
+ * the latest item is discarded.
*/
- public void opened(final LoadEvent event) {
+ private void touched(final ResourceEvent event, final boolean closed) {
final Path path = event.getResourcePath();
final File file;
try {
@@ -113,7 +116,7 @@ final class RecentFiles implements EventHandler<ActionEvent> {
final int size = items.size();
/*
* Verifies if an item already exists for the given file.
- * If yes, we will just move it.
+ * If yes, we will remove it (if opening) or move it to the top (if closing).
*/
MenuItem item = null;
for (int i=0; i<size; i++) {
@@ -122,23 +125,35 @@ final class RecentFiles implements EventHandler<ActionEvent> {
break;
}
}
- if (item == null) {
- if (size >= MAX_COUNT) {
- item = items.remove(size-1);
- item.setText(file.getName());
- item.setUserData(file);
- } else {
- item = createItem(file);
+ /*
+ * The menu item has been removed. Reinsert it at the top of the list only if the file has been closed.
+ * But save in the preferences in all cases, in case the application shutdown without closing the files.
+ */
+ final StringJoiner s = new StringJoiner(System.lineSeparator());
+ int count = 0;
+ if (closed) {
+ if (item == null) {
+ if (size >= MAX_COUNT) {
+ item = items.remove(size-1);
+ item.setText(file.getName());
+ item.setUserData(file);
+ item.setDisable(false);
+ } else {
+ item = createItem(file);
+ }
}
+ items.add(0, item);
+ } else {
+ s.add(file.getPath()); // Explicit saved because that item is no longer in the menu.
+ count = 1;
}
- items.add(0, item);
/*
* At this point the menu items has been updated.
* Now save the file list in user preferences.
*/
- final StringJoiner s = new StringJoiner(System.lineSeparator());
for (final MenuItem i : items) {
s.add(((File) i.getUserData()).getPath());
+ if (++count >= MAX_COUNT) break;
}
RecentChoices.setFiles(s.toString());
}
diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/LoadEvent.java b/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/LoadEvent.java
index 6e0ed8d..5b97839 100644
--- a/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/LoadEvent.java
+++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/LoadEvent.java
@@ -17,50 +17,31 @@
package org.apache.sis.gui.dataset;
import java.nio.file.Path;
-import javafx.event.Event;
-import javafx.event.EventType;
/**
* Event sent when a resource is loaded.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.2
* @since 1.1
+ *
+ * @deprecated Renamed {@link ResourceEvent}.
*/
-public final class LoadEvent extends Event {
+@Deprecated
+public final class LoadEvent extends ResourceEvent {
/**
* For cross-version compatibility.
*/
private static final long serialVersionUID = 5935085957507976585L;
/**
- * The only valid type for the load event.
- */
- private static final EventType<LoadEvent> LOAD = new EventType<>("LOAD");
-
- /**
- * Path to the resource being loaded.
- */
- private final Path path;
-
- /**
* Creates a new event.
*
* @param source the source of this event.
* @param path path to the file being loaded.
*/
LoadEvent(final ResourceTree source, final Path path) {
- super(source, null, LOAD);
- this.path = path;
- }
-
- /**
- * Returns the path to the resource being loaded.
- *
- * @return path to the resource being loaded.
- */
- public Path getResourcePath() {
- return path;
+ super(source, path, LOADED);
}
}
diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/LoadEvent.java b/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/ResourceEvent.java
similarity index 53%
copy from application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/LoadEvent.java
copy to application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/ResourceEvent.java
index 6e0ed8d..fdd75cb 100644
--- a/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/LoadEvent.java
+++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/ResourceEvent.java
@@ -22,25 +22,41 @@ import javafx.event.EventType;
/**
- * Event sent when a resource is loaded.
+ * Event sent when a resource is loaded or closed. The {@linkplain #getSource() source}
+ * of this event are the {@link ResourceTree} instance on which handlers are registered.
+ * The event contains a {@link Path} to the resource opened or closed.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.1
- * @since 1.1
+ * @version 1.2
+ *
+ * @see ResourceTree#onResourceLoaded
+ * @see ResourceTree#onResourceClosed
+ *
+ * @since 1.2
*/
-public final class LoadEvent extends Event {
+@SuppressWarnings("CloneableImplementsClone")
+public class ResourceEvent extends Event {
/**
* For cross-version compatibility.
*/
- private static final long serialVersionUID = 5935085957507976585L;
+ private static final long serialVersionUID = -425980517754215310L;
/**
- * The only valid type for the load event.
+ * The type for load events.
+ *
+ * @see ResourceTree#onResourceLoaded
+ */
+ static final EventType<ResourceEvent> LOADED = new EventType<>("LOADED");
+
+ /**
+ * The type for close events.
+ *
+ * @see ResourceTree#onResourceClosed
*/
- private static final EventType<LoadEvent> LOAD = new EventType<>("LOAD");
+ static final EventType<ResourceEvent> CLOSED = new EventType<>("CLOSED");
/**
- * Path to the resource being loaded.
+ * Path to the resource being loaded or closed.
*/
private final Path path;
@@ -49,16 +65,17 @@ public final class LoadEvent extends Event {
*
* @param source the source of this event.
* @param path path to the file being loaded.
+ * @param type the type of event.
*/
- LoadEvent(final ResourceTree source, final Path path) {
- super(source, null, LOAD);
+ ResourceEvent(final ResourceTree source, final Path path, final EventType<ResourceEvent> type) {
+ super(source, null, type);
this.path = path;
}
/**
- * Returns the path to the resource being loaded.
+ * Returns the path to the resource being loaded or closed.
*
- * @return path to the resource being loaded.
+ * @return path to the resource being loaded or closed.
*/
public Path getResourcePath() {
return path;
diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/ResourceExplorer.java b/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/ResourceExplorer.java
index 7156284..a5516b7 100644
--- a/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/ResourceExplorer.java
+++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/dataset/ResourceExplorer.java
@@ -264,7 +264,7 @@ public class ResourceExplorer extends WindowManager {
*
* @return current function to be called after a resource has been loaded, or {@code null} if none.
*/
- public EventHandler<LoadEvent> getOnResourceLoaded() {
+ public EventHandler<ResourceEvent> getOnResourceLoaded() {
return resources.onResourceLoaded.get();
}
@@ -275,11 +275,36 @@ public class ResourceExplorer extends WindowManager {
*
* @param handler new function to be called after a resource has been loaded, or {@code null} if none.
*/
- public void setOnResourceLoaded(final EventHandler<LoadEvent> handler) {
+ public void setOnResourceLoaded(final EventHandler<ResourceEvent> handler) {
resources.onResourceLoaded.set(handler);
}
/**
+ * Returns the function to be called when a resource is closed.
+ * This is an accessor for the {@link ResourceTree#onResourceClosed} property value.
+ *
+ * @return current function to be called when a resource is closed, or {@code null} if none.
+ *
+ * @since 1.2
+ */
+ public EventHandler<ResourceEvent> getOnResourceClosed() {
+ return resources.onResourceClosed.get();
+ }
+
+ /**
+ * Specifies a function to be called when a resource is closed.
+ * This is a setter for the {@link ResourceTree#onResourceClosed} property value.
+ * If this method is never invoked, then the default value is {@code null}.
+ *
+ * @param handler new function to be called when a resource is closed, or {@code null} if none.
+ *
+ * @since 1.2
+ */
+ public void setOnResourceClosed(final EventHandler<ResourceEvent> handler) {
+ resources.onResourceClosed.set(handler);
+ }
+
+ /**
* Loads all given sources in background threads and add them to the resource tree.
* The given collection typically contains files to load,
* but may also contain {@link Resource} instances to add directly.
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 f79ab40..a4fc1d9 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
@@ -69,6 +69,7 @@ import org.apache.sis.internal.gui.Resources;
import org.apache.sis.internal.gui.Styles;
import org.apache.sis.internal.system.Modules;
import org.apache.sis.internal.util.Strings;
+import org.apache.sis.storage.DataStoreProvider;
import org.apache.sis.util.logging.Logging;
@@ -107,8 +108,20 @@ public class ResourceTree extends TreeView<Resource> {
* The default value is {@code null}.
*
* @see #loadResource(Object)
+ * @see ResourceEvent#LOADED
*/
- public final ObjectProperty<EventHandler<LoadEvent>> onResourceLoaded;
+ public final ObjectProperty<EventHandler<ResourceEvent>> onResourceLoaded;
+
+ /**
+ * Function to be called after a resource has been closed from a file or URL.
+ * The default value is {@code null}.
+ *
+ * @see #removeAndClose(Resource)
+ * @see ResourceEvent#CLOSED
+ *
+ * @since 1.2
+ */
+ public final ObjectProperty<EventHandler<ResourceEvent>> onResourceClosed;
/**
* Creates a new tree of resources with initially no resource to show.
@@ -120,6 +133,7 @@ public class ResourceTree extends TreeView<Resource> {
setOnDragOver(ResourceTree::onDragOver);
setOnDragDropped(this::onDragDropped);
onResourceLoaded = new SimpleObjectProperty<>(this, "onResourceLoaded");
+ onResourceClosed = new SimpleObjectProperty<>(this, "onResourceClosed");
}
/**
@@ -186,10 +200,10 @@ public class ResourceTree extends TreeView<Resource> {
addTo = (Root) root;
} else {
final TreeItem<Resource> group = new TreeItem<>();
- addTo = new Root(group, root);
- group.setValue(addTo);
- setRoot(group);
setShowRoot(false);
+ setRoot(group); // Also detach `item` from the TreeView root.
+ addTo = new Root(group, item); // Pseudo-resource for a group of data stores.
+ group.setValue(addTo);
}
return addTo.add(resource);
}
@@ -222,13 +236,12 @@ public class ResourceTree extends TreeView<Resource> {
addResource((Resource) source);
} else {
final ResourceLoader loader = new ResourceLoader(source);
- final Resource existing = loader.fromCache();
+ final DataStore existing = loader.fromCache();
if (existing != null) {
addResource(existing);
} else {
loader.setOnSucceeded((event) -> {
- addResource((Resource) event.getSource().getValue());
- notifyLoaded(source);
+ addLoadedResource((DataStore) event.getSource().getValue(), source);
});
loader.setOnFailed((event) -> ExceptionReporter.show(this, event));
BackgroundThreads.execute(loader);
@@ -238,23 +251,28 @@ public class ResourceTree extends TreeView<Resource> {
}
/**
- * Notifies {@link #onResourceLoaded} handler that a resource at the given path has been loaded.
+ * Adds the given store as a resource, then notifies {@link #onResourceLoaded}
+ * handler that a resource at the given path has been loaded.
* This method is invoked from JavaFX thread.
- *
- * <p>Those notifications are not used by {@code ResourceTree} itself.
- * They are useful to other packages, for example for managing a list of opened files.</p>
*/
- private void notifyLoaded(final Object source) {
- final EventHandler<LoadEvent> handler = onResourceLoaded.getValue();
+ private void addLoadedResource(final DataStore store, final Object source) {
+ addResource(store);
+ final EventHandler<ResourceEvent> handler = onResourceLoaded.getValue();
if (handler != null) {
final Path path;
try {
path = IOUtilities.toPathOrNull(source);
} catch (IllegalArgumentException | FileSystemNotFoundException e) {
- Logging.recoverableException(Logging.getLogger(Modules.APPLICATION), ResourceTree.class, "loadResource", e);
+ recoverableException("loadResource", e);
return;
}
if (path != null) {
+ /*
+ * Following call should be quick because it starts the search from last item.
+ * A `NullPointerException` or `ClassCastException` here would be a bug in our
+ * wrapping of resources.
+ */
+ ((Item) findOrRemove(store, false)).path = path;
handler.handle(new LoadEvent(this, path));
}
}
@@ -318,6 +336,11 @@ public class ResourceTree extends TreeView<Resource> {
* Children of {@link Aggregate} resource and not scanned.
* If the given resource can not be removed, then this method does nothing.</p>
*
+ * <h4>Notifications</h4>
+ * If {@link #onResourceClosed} has a non-null value, the {@link EventHandler} will be notified.
+ * The notification may happen in same time that the resource is closing in a background thread.
+ * If an exception occurs while closing the resource, the error is reported in a dialog box.
+ *
* @param resource the resource to remove. Null values are ignored.
*
* @see #setResource(Resource)
@@ -325,9 +348,27 @@ public class ResourceTree extends TreeView<Resource> {
* @see ResourceExplorer#removeAndClose(Resource)
*/
public void removeAndClose(final Resource resource) {
- if (findOrRemove(resource, true)) {
- if (resource instanceof DataStore) {
- ResourceLoader.removeAndClose((DataStore) resource, this);
+ final TreeItem<Resource> item = findOrRemove(resource, true);
+ if (item != null && resource instanceof DataStore) {
+ final DataStore store = (DataStore) resource;
+ ResourceLoader.removeAndClose(store, this);
+ final EventHandler<ResourceEvent> handler = onResourceClosed.get();
+ if (handler != null) {
+ Path path = null;
+ if (item instanceof Item) {
+ path = ((Item) item).path;
+ }
+ if (path == null) try {
+ path = store.getOpenParameters()
+ .map((p) -> IOUtilities.toPathOrNull(p.parameter(DataStoreProvider.LOCATION).getValue()))
+ .orElse(null);
+ } catch (IllegalArgumentException | FileSystemNotFoundException e) {
+ // Ignore because the location parameter is optional.
+ recoverableException("removeAndClose", e);
+ }
+ if (path != null) {
+ handler.handle(new ResourceEvent(this, path, ResourceEvent.CLOSED));
+ }
}
}
}
@@ -337,9 +378,9 @@ public class ResourceTree extends TreeView<Resource> {
*
* @param resource the resource to search of remove, or {@code null}.
* @param remove {@code true} for removing the resource, or {@code false} for checking only.
- * @return whether the resource has been found in the roots.
+ * @return the item wrapping the resource, or {@code null} if the resource has been found in the roots.
*/
- private boolean findOrRemove(final Resource resource, final boolean remove) {
+ private TreeItem<Resource> findOrRemove(final Resource resource, final boolean remove) {
assert Platform.isFxApplicationThread();
if (resource != null) {
/*
@@ -365,19 +406,15 @@ public class ResourceTree extends TreeView<Resource> {
if (remove) {
setRoot(null);
}
- return true;
+ return item;
}
if (root instanceof Root) {
- if (remove) {
- return ((Root) root).remove(resource);
- } else {
- return ((Root) root).contains(resource);
- }
+ return ((Root) root).contains(resource, remove);
}
}
}
}
- return false;
+ return null;
}
/**
@@ -475,6 +512,13 @@ public class ResourceTree extends TreeView<Resource> {
}
/**
+ * Reports an ignorable exception in the given method.
+ */
+ private static void recoverableException(final String method, final Exception e) {
+ Logging.recoverableException(Logging.getLogger(Modules.APPLICATION), ResourceTree.class, method, e);
+ }
+
+ /**
* Reports an unexpected but non-fatal exception in the given method.
*/
static void unexpectedException(final String method, final Exception e) {
@@ -566,7 +610,7 @@ public class ResourceTree extends TreeView<Resource> {
* If the resource is one of the "root" resources, add a menu for removing it.
* If we find that the cell already has a menu, we do not need to build it again.
*/
- if (tree.findOrRemove(resource, false)) {
+ if (tree.findOrRemove(resource, false) != null) {
menu = getContextMenu();
if (menu == null) {
menu = new ContextMenu();
@@ -617,6 +661,12 @@ public class ResourceTree extends TreeView<Resource> {
*/
private static final class Item extends TreeItem<Resource> {
/**
+ * The path to the resource, or {@code null} if none or unknown. This is used for notifications only;
+ * this information does not play an important role for {@link ResourceTree} itself.
+ */
+ Path path;
+
+ /**
* The text of this node, computed and cached when first needed.
* Computation is done by invoking {@link #findLabel(Resource, Locale)} in a background thread.
*
@@ -785,6 +835,7 @@ public class ResourceTree extends TreeView<Resource> {
* Invoked in JavaFX thread if children can not be loaded.
*/
@Override
+ @SuppressWarnings("unchecked")
protected void failed() {
Item.super.getChildren().setAll(new Item(getException()));
}
@@ -795,7 +846,7 @@ public class ResourceTree extends TreeView<Resource> {
/**
- * The root resource when there is more than one resources to display.
+ * The root pseudo-resource when there is more than one resources to display.
* This root node should be hidden in the {@link ResourceTree}.
*/
private static final class Root implements Aggregate {
@@ -805,31 +856,33 @@ public class ResourceTree extends TreeView<Resource> {
private final List<TreeItem<Resource>> components;
/**
- * Creates a new aggregate which is going to be wrapped in the given item.
- * Caller should invoke {@code group.setValue(root)} after this constructor.
+ * Creates a new aggregate which is going to be wrapped in the given node.
+ * Caller shall invoke {@code group.setValue(root)} after this constructor.
*
- * @param group the new tree root which will contain "real" resources.
+ * @param group the new tree root which will contain "real" resources.
* @param previous the previous root, to be added in the new group.
*/
- Root(final TreeItem<Resource> group, final Resource previous) {
+ Root(final TreeItem<Resource> group, final TreeItem<Resource> previous) {
components = group.getChildren();
- add(previous);
+ components.add(previous);
}
/**
- * Returns whether this root contains the given resource as a direct child.
+ * Checks whether this root contains the given resource as a direct child.
* This method does not search recursively in sub-trees.
*
* @param resource the resource to search.
- * @return whether the given resource is present.
+ * @param remove whether to remove the resource if found.
+ * @return the resource wrapper, or {@code null} if not found.
*/
- boolean contains(final Resource resource) {
+ TreeItem<Resource> contains(final Resource resource, final boolean remove) {
for (int i=components.size(); --i >= 0;) {
- if (components.get(i).getValue() == resource) {
- return true;
+ final TreeItem<Resource> item = components.get(i);
+ if (item.getValue() == resource) {
+ return remove ? components.remove(i) : item;
}
}
- return false;
+ return null;
}
/**
@@ -848,16 +901,6 @@ public class ResourceTree extends TreeView<Resource> {
}
/**
- * Removes the given resource if presents.
- *
- * @param resource the resource to remove.
- * @return whether the resource has been removed.
- */
- boolean remove(final Resource resource) {
- return components.removeIf((i) -> i.getValue() == resource);
- }
-
- /**
* Returns a read-only view of the components. This method is not used directly by {@link ResourceTree}
* but is defined in case a user invoke {@link ResourceTree#getResource()}. For this reason, it is not
* worth to cache the list created in this method.
diff --git a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/ResourceLoader.java b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/ResourceLoader.java
index 1191b40..10e44f2 100644
--- a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/ResourceLoader.java
+++ b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/ResourceLoader.java
@@ -71,7 +71,7 @@ import org.apache.sis.gui.DataViewer;
* @since 1.1
* @module
*/
-public final class ResourceLoader extends Task<Resource> {
+public final class ResourceLoader extends Task<DataStore> {
/**
* The cache of previously loaded resources.
* Used for avoiding to load the same resource twice.