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 d6ca8baa263ac788e4d140502099af3977b7a7b4 Author: Martin Desruisseaux <[email protected]> AuthorDate: Wed Feb 10 15:41:54 2021 +0100 Better catching of exceptions to be reported to user. --- .../apache/sis/gui/coverage/CoverageCanvas.java | 41 ++++++++++------------ .../org/apache/sis/gui/coverage/RenderingData.java | 8 ++--- .../apache/sis/gui/coverage/CoverageCanvasApp.java | 27 ++------------ 3 files changed, 24 insertions(+), 52 deletions(-) diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageCanvas.java b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageCanvas.java index ff1a09e..389ef6d 100644 --- a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageCanvas.java +++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageCanvas.java @@ -62,7 +62,6 @@ import org.apache.sis.referencing.operation.transform.MathTransforms; import org.apache.sis.geometry.Envelope2D; import org.apache.sis.geometry.Shapes2D; import org.apache.sis.image.PlanarImage; -import org.apache.sis.image.ErrorHandler; import org.apache.sis.image.Interpolation; import org.apache.sis.coverage.Category; import org.apache.sis.gui.map.MapCanvas; @@ -183,6 +182,15 @@ public class CoverageCanvas extends MapCanvasAWT { StatusBar statusBar; /** + * If errors occurred during tile computations, details about the error. Otherwise {@code null}. + * This field is set once by some background thread if one or more errors occurred during calls + * to {@link RenderedImage#getTile(int, int)}. In such case, we store information about the error + * and let the rendering process continue with a tile placeholder (by default a cross (X) in a box). + * This field is read in JavaFX thread for transferring the error description to {@link #errorProperty()}. + */ + private volatile LogRecord errorReport; + + /** * The resource from which the data has been read, or {@code null} if unknown. * This is used only for determining a target window for logging records. * @@ -212,7 +220,7 @@ public class CoverageCanvas extends MapCanvasAWT { */ CoverageCanvas(final Locale locale) { super(locale); - data = new RenderingData(); + data = new RenderingData((report) -> errorReport = report.getDescription()); derivedImages = new EnumMap<>(Stretching.class); coverageProperty = new SimpleObjectProperty<>(this, "coverage"); sliceExtentProperty = new SimpleObjectProperty<>(this, "sliceExtent"); @@ -528,7 +536,7 @@ public class CoverageCanvas extends MapCanvasAWT { * <li>Paint the image.</li> * </ol> */ - private static final class Worker extends Renderer implements ErrorHandler { + private static final class Worker extends Renderer { /** * Value of {@link CoverageCanvas#data} at the time this worker has been initialized. */ @@ -611,11 +619,6 @@ public class CoverageCanvas extends MapCanvasAWT { private IsolineRenderer.Snapshot[] isolines; /** - * If errors occurred during tile computations, details about the error. Otherwise {@code null}. - */ - private LogRecord errorReport; - - /** * Creates a new renderer. Shall be invoked in JavaFX thread. */ Worker(final CoverageCanvas canvas) { @@ -732,7 +735,7 @@ public class CoverageCanvas extends MapCanvasAWT { if (prefetchedImage instanceof TileErrorHandler.Executor) { ((TileErrorHandler.Executor) prefetchedImage).execute( () -> gr.drawRenderedImage(prefetchedImage, resampledToDisplay), - new TileErrorHandler(this, CoverageCanvas.class, "paint")); + new TileErrorHandler(data.processor.getErrorHandler(), CoverageCanvas.class, "paint")); } else { gr.drawRenderedImage(prefetchedImage, resampledToDisplay); } @@ -751,16 +754,6 @@ public class CoverageCanvas extends MapCanvasAWT { } /** - * Invoked if an error occurred during a call to {@link RenderedImage#getTile(int, int)}. - * This method stores information about the error and let the rendering process continue - * with a tile placeholder (by default a cross (X) in a box). - */ - @Override - public void handle(final Report details) { - errorReport = details.getDescription(); - } - - /** * Invoked in JavaFX thread after successful {@link #paint(Graphics2D)} completion. * This method stores the computation results. */ @@ -781,7 +774,7 @@ public class CoverageCanvas extends MapCanvasAWT { * If the resampled image changed, all previously cached images are discarded. */ private void cacheRenderingData(final Worker worker) { - if (TRACE && data.changed(worker.data)) { + if (TRACE && data.hasChanged(worker.data)) { trace("cacheRenderingData(…): new visual coverage:%n%s", worker.data); } data = worker.data; @@ -822,10 +815,12 @@ public class CoverageCanvas extends MapCanvasAWT { } /* * If error(s) occurred during calls to `RenderedImage.getTile(tx, ty)`, reports those errors. + * The `errorReport` field is reset to `null` in preparation for the next rendering operation. */ - final LogRecord errorReport = worker.errorReport; - if (errorReport != null) { - errorOccurred(errorReport.getThrown()); + final LogRecord report = errorReport; + if (report != null) { + errorReport = null; + errorOccurred(report.getThrown()); } } diff --git a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/RenderingData.java b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/RenderingData.java index 2ba2b33..9d7b3c3 100644 --- a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/RenderingData.java +++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/RenderingData.java @@ -202,12 +202,12 @@ final class RenderingData implements Cloneable { /** * Creates a new instance initialized to no image. * - * @todo Listen to logging messages. We need to create a logging panel first. + * @param errorHandler where to report errors during tile computations. */ - RenderingData() { + RenderingData(final ErrorHandler errorHandler) { selectedDerivative = Stretching.NONE; processor = new ImageProcessor(); - processor.setErrorHandler(ErrorHandler.LOG); + processor.setErrorHandler(errorHandler); processor.setImageResizingPolicy(ImageProcessor.Resizing.EXPAND); } @@ -543,7 +543,7 @@ final class RenderingData implements Cloneable { * Returns whether {@link #dataGeometry} or {@link #objectiveToCenter} changed since a previous rendering. * This is used for information purposes only. */ - final boolean changed(final RenderingData previous) { + final boolean hasChanged(final RenderingData previous) { /* * Really !=, not Object.equals(Object), because we rely on new instances to be created * (even if equal) as a way to detect that cached values have not been reused. diff --git a/application/sis-javafx/src/test/java/org/apache/sis/gui/coverage/CoverageCanvasApp.java b/application/sis-javafx/src/test/java/org/apache/sis/gui/coverage/CoverageCanvasApp.java index bcba2d9..ce23aaa 100644 --- a/application/sis-javafx/src/test/java/org/apache/sis/gui/coverage/CoverageCanvasApp.java +++ b/application/sis-javafx/src/test/java/org/apache/sis/gui/coverage/CoverageCanvasApp.java @@ -20,8 +20,6 @@ import java.util.Random; import java.awt.Point; import java.awt.image.DataBuffer; import javafx.application.Application; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; import javafx.scene.layout.BorderPane; import javafx.scene.Scene; import javafx.stage.Stage; @@ -46,7 +44,7 @@ import org.apache.sis.referencing.operation.transform.MathTransforms; * @since 1.1 * @module */ -public class CoverageCanvasApp extends Application implements ChangeListener<Throwable> { +public class CoverageCanvasApp extends Application { /** * Size of the artificial tiles. Should be small enough so we can have many of them. * Width and height should be different in order to increase the chance to see bugs @@ -72,7 +70,6 @@ public class CoverageCanvasApp extends Application implements ChangeListener<Thr @Override public void start(final Stage window) { final CoverageCanvas canvas = new CoverageCanvas(); - canvas.errorProperty().addListener(this); final StatusBar statusBar = new StatusBar(null, canvas); canvas.statusBar = statusBar; canvas.setCoverage(createImage()); @@ -101,12 +98,7 @@ public class CoverageCanvasApp extends Application implements ChangeListener<Thr * have artificial errors in order to see the error controls. */ private static GridCoverage2D createImage() { - /* - * A few interresting seeds for debugging: - * -638852012230008460L, 987724905110811687L, - * 4120510106559901474L, 4533692522112080642L, 2518316107261433588L - */ - final Random random = new Random(987724905110811687L); + final Random random = new Random(); final int width = TILE_WIDTH * 4; final int height = TILE_HEIGHT * 2; final TiledImageMock image = new TiledImageMock( @@ -134,19 +126,4 @@ public class CoverageCanvasApp extends Application implements ChangeListener<Thr return new GridCoverage2D(new GridGeometry(null, PixelInCell.CELL_CORNER, MathTransforms.identity(2), CommonCRS.Engineering.DISPLAY.crs()), null, image); } - - /** - * Invoked when an exception occurred during rendering. - * - * @param property the {@link CoverageCanvas#errorProperty()}. - * @param oldValue the previous error, or {@code null} if none. - * @param newValue the new error, or {@code null} if cleared. - */ - @Override - @SuppressWarnings("CallToPrintStackTrace") - public void changed(ObservableValue<? extends Throwable> property, Throwable oldValue, Throwable newValue) { - if (newValue != null) { - newValue.printStackTrace(); - } - } }
