sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 05/06: First draft of a CoverageView window showing the image (identity transform only for now).
Date Sat, 22 Feb 2020 17:04:16 GMT
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 719310030f34cd0ace29dd3fb2f75eecff64caee
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Sat Feb 22 15:32:32 2020 +0100

    First draft of a CoverageView window showing the image (identity transform only for now).
---
 .../apache/sis/gui/coverage/CoverageExplorer.java  |  37 +++++--
 .../org/apache/sis/gui/coverage/CoverageView.java  | 113 +++++++++++++++++++--
 2 files changed, 136 insertions(+), 14 deletions(-)

diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageExplorer.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageExplorer.java
index 09bf287..158c106 100644
--- a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageExplorer.java
+++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageExplorer.java
@@ -87,6 +87,12 @@ public class CoverageExplorer {
     public final ObjectProperty<GridCoverage> coverageProperty;
 
     /**
+     * Whether the {@link #coverageProperty} is in process of being set, in which case some
+     * listeners should not react.
+     */
+    private boolean isCoverageAdjusting;
+
+    /**
      * The component for showing sample values.
      */
     private final GridView gridView;
@@ -198,7 +204,9 @@ addRows:    for (int row = 0;; row++) {
 
             /** Creates a visualization of the coverage. */
             @Override public Region createView(final Locale locale) {
-                return new CoverageView(locale).getView();
+                final CoverageView view = new CoverageView(locale);
+                view.coverageProperty.bind(coverageProperty);
+                return view.getView();
             }
         });
     }
@@ -269,7 +277,7 @@ addRows:    for (int row = 0;; row++) {
     }
 
     /**
-     * Invoked when a new coverage has been specified
+     * Invoked when a new coverage has been specified.
      *
      * @param  property  the {@link #coverageProperty} (ignored).
      * @param  previous  ignored.
@@ -278,11 +286,13 @@ addRows:    for (int row = 0;; row++) {
     private void onCoverageSpecified(final ObservableValue<? extends GridCoverage>
property,
                                      final GridCoverage previous, final GridCoverage coverage)
     {
-        gridView.setImage((RenderedImage) null);
-        if (coverage != null) {
-            gridView.setImage(new ImageRequest(coverage, null));        // Start a background
thread.
+        if (!isCoverageAdjusting) {
+            gridView.setImage((RenderedImage) null);
+            setSampleDimensions(coverage);
+            if (coverage != null) {
+                gridView.setImage(new ImageRequest(coverage, null));        // Start a background
thread.
+            }
         }
-        onCoverageLoaded(coverage);
     }
 
     /**
@@ -294,6 +304,19 @@ addRows:    for (int row = 0;; row++) {
      * @param  coverage  the new coverage, or {@code null} if loading failed.
      */
     final void onCoverageLoaded(final GridCoverage coverage) {
+        setSampleDimensions(coverage);
+        isCoverageAdjusting = true;
+        try {
+            setCoverage(coverage);
+        } finally {
+            isCoverageAdjusting = false;
+        }
+    }
+
+    /**
+     * Sets the values in the sample dimensions table according information in the given
coverage.
+     */
+    private void setSampleDimensions(final GridCoverage coverage) {
         final ObservableList<SampleDimension> items = sampleDimensions.getItems();
         if (coverage != null) {
             items.setAll(coverage.getSampleDimensions());
@@ -304,7 +327,7 @@ addRows:    for (int row = 0;; row++) {
     }
 
     /**
-     * Invoked when the selected band changed. This method ensures that the selected row
+     * Invoked when the band property changed. This method ensures that the selected row
      * in the sample dimension table matches the band which is shown in the grid view.
      */
     private void onBandSpecified(final ObservableValue<? extends Number> property,
diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageView.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageView.java
index 8ba4aec..2bcfb14 100644
--- a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageView.java
+++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageView.java
@@ -31,9 +31,13 @@ import javafx.scene.image.PixelFormat;
 import javafx.scene.image.WritableImage;
 import javafx.scene.layout.Pane;
 import javafx.scene.layout.Region;
+import javafx.beans.value.ObservableValue;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
 import javafx.util.Callback;
 import org.opengis.referencing.datum.PixelInCell;
 import org.apache.sis.coverage.grid.GridCoverage;
+import org.apache.sis.coverage.grid.GridExtent;
 import org.apache.sis.coverage.grid.GridGeometry;
 import org.apache.sis.internal.coverage.j2d.ColorModelFactory;
 import org.apache.sis.internal.map.PlanarCanvas;
@@ -53,6 +57,28 @@ import org.apache.sis.internal.util.Numerics;
  */
 final class CoverageView extends PlanarCanvas {
     /**
+     * The data shown in this view. Note that setting this property to a non-null value may
not
+     * modify the view content immediately. Instead, a background process will request the
tiles.
+     *
+     * <p>Current implementation is restricted to {@link GridCoverage} instances, but
a future
+     * implementation may generalize to {@link org.opengis.coverage.Coverage} instances.</p>
+     *
+     * @see #getCoverage()
+     * @see #setCoverage(GridCoverage)
+     */
+    public final ObjectProperty<GridCoverage> coverageProperty;
+
+    /**
+     * A subspace of the grid coverage extent where all dimensions except two have a size
of 1 cell.
+     * May be {@code null} if this grid coverage has only two dimensions with a size greater
than 1 cell.
+     *
+     * @see #getSliceExtent()
+     * @see #setSliceExtent(GridExtent)
+     * @see GridCoverage#render(GridExtent)
+     */
+    public final ObjectProperty<GridExtent> sliceExtentProperty;
+
+    /**
      * The data to shown, or {@code null} if not yet specified. This image may be tiled,
      * and fetching tiles may require computations to be performed in background thread.
      * The size of this image is not necessarily {@link #buffer} or {@link #image} size.
@@ -104,12 +130,26 @@ final class CoverageView extends PlanarCanvas {
      */
     public CoverageView(final Locale locale) {
         super(locale);
+        coverageProperty    = new SimpleObjectProperty<>(this, "coverage");
+        sliceExtentProperty = new SimpleObjectProperty<>(this, "sliceExtent");
         dataToImage = new AffineTransform();
-        view        = new Pane();
-        image       = new ImageView();
+        view = new Pane() {
+            @Override protected void layoutChildren() {
+                super.layoutChildren();
+                repaint();
+            }
+        };
+        image = new ImageView();
         image.setPreserveRatio(true);
         view.getChildren().add(image);
-        view.setPrefSize(600, 400);
+        /*
+         * Do not set a preferred size, otherwise `repaint()` is invoked twice: once with
the preferred size
+         * and once with the actual size of the parent window. Actually the `repaint()` method
appears to be
+         * invoked twice anyway, but without preferred size the width appears to be 0, in
which case nothing
+         * is repainted.
+         */
+        coverageProperty   .addListener(this::onImageSpecified);
+        sliceExtentProperty.addListener(this::onImageSpecified);
     }
 
     /**
@@ -123,13 +163,69 @@ final class CoverageView extends PlanarCanvas {
     }
 
     /**
-     * Sets the image to display.
+     * Returns the source of image for this viewer.
+     * This method, like all other methods in this class, shall be invoked from the JavaFX
thread.
+     *
+     * @return the coverage shown in this explorer, or {@code null} if none.
+     *
+     * @see #coverageProperty
+     */
+    public final GridCoverage getCoverage() {
+        return coverageProperty.get();
+    }
+
+    /**
+     * Sets the coverage to show in this viewer.
+     * This method shall be invoked from JavaFX thread and returns immediately.
+     * The new data are loaded in a background thread and will appear after an
+     * undetermined amount of time.
+     *
+     * @param  coverage  the data to show in this viewer, or {@code null} if none.
+     *
+     * @see #coverageProperty
      */
-    private void setImage(final RenderedImage source) {
+    public final void setCoverage(final GridCoverage coverage) {
+        coverageProperty.set(coverage);
+    }
+
+    /**
+     * Returns a subspace of the grid coverage extent where all dimensions except two have
a size of 1 cell.
+     *
+     * @return subspace of the grid coverage extent where all dimensions except two have
a size of 1 cell.
+     *
+     * @see #sliceExtentProperty
+     * @see GridCoverage#render(GridExtent)
+     */
+    public final GridExtent getSliceExtent() {
+        return sliceExtentProperty.get();
+    }
+
+    /**
+     * Sets a subspace of the grid coverage extent where all dimensions except two have a
size of 1 cell.
+     *
+     * @param  sliceExtent  subspace of the grid coverage extent where all dimensions except
two have a size of 1 cell.
+     *
+     * @see #sliceExtentProperty
+     * @see GridCoverage#render(GridExtent)
+     */
+    public final void setSliceExtent(final GridExtent sliceExtent) {
+        sliceExtentProperty.set(sliceExtent);
+    }
+
+    /**
+     * Invoked when a new coverage has been specified or when the slice extent changed.
+     *
+     * @param  property  the {@link #coverageProperty} or {@link #sliceExtentProperty} (ignored).
+     * @param  previous  ignored.
+     * @param  value     ignored.
+     */
+    private void onImageSpecified(final ObservableValue<?> property, final Object previous,
final Object value) {
         image.setImage(null);
+        data   = null;
         buffer = null;
-        data = source;
-        if (source != null) {
+        final GridCoverage coverage = getCoverage();
+        if (coverage != null) {
+            data = coverage.render(getSliceExtent());     // TODO: background thread.
             repaint();
         }
     }
@@ -142,6 +238,9 @@ final class CoverageView extends PlanarCanvas {
     private void repaint() {
         final int width  = Numerics.clamp(Math.round(view.getWidth()));
         final int height = Numerics.clamp(Math.round(view.getHeight()));
+        if (width <= 0 || height <= 0) {
+            return;
+        }
         PixelBuffer<IntBuffer> wrapper = bufferWrapper;
         BufferedImage drawTo = buffer;
         if (drawTo == null || drawTo.getWidth() != width || drawTo.getHeight() != height)
{


Mime
View raw message