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 dbec36d Apply CRS choice on the coordinate values displayed.
dbec36d is described below
commit dbec36d6bf66abf99a7de0ebdb77ba043704dd3d
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Thu Apr 23 00:49:50 2020 +0200
Apply CRS choice on the coordinate values displayed.
---
.../java/org/apache/sis/gui/coverage/GridView.java | 25 +-
.../org/apache/sis/gui/coverage/ImageRequest.java | 3 +-
.../java/org/apache/sis/gui/map/StatusBar.java | 283 +++++++++++++++++----
.../gui/referencing/RecentReferenceSystems.java | 10 +-
.../java/org/apache/sis/internal/gui/Styles.java | 5 +
.../org/apache/sis/geometry/CoordinateFormat.java | 1 +
6 files changed, 260 insertions(+), 67 deletions(-)
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridView.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridView.java
index 891f583..54aa1f4 100644
---
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridView.java
+++
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridView.java
@@ -142,8 +142,9 @@ public class GridView extends Control {
* This size includes the {@linkplain #cellSpacing cell spacing}.
* It shall be a number strictly greater than zero.
*
- * <p>We do not define getter/setter for this property; use {@link
DoubleProperty#set(double)}
- * directly instead. We omit the "Property" suffix for making this
operation more natural.</p>
+ * <div class="note"><b>API note:</b>
+ * We do not provide getter/setter for this property; use {@link
DoubleProperty#set(double)}
+ * directly instead. We omit the "Property" suffix for making this
operation more natural.</div>
*/
public final DoubleProperty headerWidth;
@@ -152,8 +153,9 @@ public class GridView extends Control {
* This size includes the {@linkplain #cellSpacing cell spacing}.
* It shall be a number strictly greater than zero.
*
- * <p>We do not define getter/setter for this property; use {@link
DoubleProperty#set(double)}
- * directly instead. We omit the "Property" suffix for making this
operation more natural.</p>
+ * <div class="note"><b>API note:</b>
+ * We do not provide getter/setter for this property; use {@link
DoubleProperty#set(double)}
+ * directly instead. We omit the "Property" suffix for making this
operation more natural.</div>
*/
public final DoubleProperty cellWidth;
@@ -161,8 +163,9 @@ public class GridView extends Control {
* Height of all rows in the grid.
* It shall be a number strictly greater than zero.
*
- * <p>We do not define getter/setter for this property; use {@link
DoubleProperty#set(double)}
- * directly instead. We omit the "Property" suffix for making this
operation more natural.</p>
+ * <div class="note"><b>API note:</b>
+ * We do not provide getter/setter for this property; use {@link
DoubleProperty#set(double)}
+ * directly instead. We omit the "Property" suffix for making this
operation more natural.</div>
*/
public final DoubleProperty cellHeight;
@@ -171,16 +174,18 @@ public class GridView extends Control {
* There is no property for vertical cell spacing because increasing the
* {@linkplain #cellHeight cell height} should be sufficient.
*
- * <p>We do not define getter/setter for this property; use {@link
DoubleProperty#set(double)}
- * directly instead. We omit the "Property" suffix for making this
operation more natural.</p>
+ * <div class="note"><b>API note:</b>
+ * We do not provide getter/setter for this property; use {@link
DoubleProperty#set(double)}
+ * directly instead. We omit the "Property" suffix for making this
operation more natural.</div>
*/
public final DoubleProperty cellSpacing;
/**
* The background color of row and column headers.
*
- * <p>We do not define getter/setter for this property; use {@link
ObjectProperty#set(Object)}
- * directly instead. We omit the "Property" suffix for making this
operation more natural.</p>
+ * <div class="note"><b>API note:</b>
+ * We do not provide getter/setter for this property; use {@link
ObjectProperty#set(Object)}
+ * directly instead. We omit the "Property" suffix for making this
operation more natural.</div>
*/
public final ObjectProperty<Paint> headerBackground;
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/ImageRequest.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/ImageRequest.java
index 9431c33..7310a21 100644
---
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/ImageRequest.java
+++
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/ImageRequest.java
@@ -268,7 +268,8 @@ public class ImageRequest {
for (int i=0; i<origin.length; i++) {
origin[i] = request.getLow(i);
}
-
bar.setLocalToCRS(MathTransforms.concatenate(MathTransforms.translation(origin),
bar.getLocalToCRS()));
+ bar.setLocalToObjectiveCRS(MathTransforms.concatenate(
+ MathTransforms.translation(origin),
bar.getLocalToObjectiveCRS()));
}
}
}
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/gui/map/StatusBar.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/map/StatusBar.java
index 5f4abe9..5a16356 100644
--- a/application/sis-javafx/src/main/java/org/apache/sis/gui/map/StatusBar.java
+++ b/application/sis-javafx/src/main/java/org/apache/sis/gui/map/StatusBar.java
@@ -36,15 +36,20 @@ import javafx.beans.value.ObservableValue;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
+import javafx.concurrent.Task;
+import org.opengis.geometry.Envelope;
import org.opengis.geometry.MismatchedDimensionException;
+import org.opengis.util.FactoryException;
import org.opengis.referencing.ReferenceSystem;
import org.opengis.referencing.datum.PixelInCell;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.operation.Matrix;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
+import org.opengis.referencing.operation.CoordinateOperation;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.apache.sis.referencing.operation.transform.MathTransforms;
+import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
import org.apache.sis.geometry.GeneralDirectPosition;
import org.apache.sis.geometry.CoordinateFormat;
import org.apache.sis.coverage.grid.GridGeometry;
@@ -56,12 +61,16 @@ import org.apache.sis.measure.Units;
import org.apache.sis.util.Classes;
import org.apache.sis.util.Exceptions;
import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.logging.Logging;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.gui.Widget;
import org.apache.sis.gui.referencing.RecentReferenceSystems;
+import org.apache.sis.internal.gui.BackgroundThreads;
import org.apache.sis.internal.gui.ExceptionReporter;
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.referencing.CRS;
/**
@@ -126,10 +135,44 @@ public class StatusBar extends Widget implements
EventHandler<MouseEvent> {
private double lastX, lastY;
/**
- * Conversion from local coordinates to geographic or projected
coordinates.
+ * The area of interest, or {@code null} if none. This is a reference to
the
+ * {@link RecentReferenceSystems#areaOfInterest} property. We do not make
this
+ * property public because it does not belong to this object.
+ */
+ private final ObjectProperty<Envelope> areaOfInterest;
+
+ /**
+ * The reference system used for rendering the data for which this status
bar is providing cursor coordinates.
+ * This is the "{@linkplain RecentReferenceSystems#setPreferred(boolean,
ReferenceSystem) preferred}" or native
+ * data CRS. It may not be the same than the CRS of coordinates actually
shown in the status bar.
+ *
+ * @see #getObjectiveCRS()
+ * @see MapCanvas#getObjectiveCRS()
+ */
+ private CoordinateReferenceSystem objectiveCRS;
+
+ /**
+ * Conversion from local coordinates to geographic or projected
coordinates of rendered data.
+ * This is not necessarily the conversion to the coordinates shown in this
status bar.
* This conversion shall never be null but may be the identity transform.
+ * It should have no {@linkplain
CoordinateOperation#getCoordinateOperationAccuracy() inaccuracy}
+ * (ignoring rounding error). This transform is usually (but not
necessarily) affine.
+ *
+ * @see #getLocalToObjectiveCRS()
+ * @see MapCanvas#getObjectiveToDisplay()
*/
- private MathTransform localToCRS;
+ private MathTransform localToObjectiveCRS;
+
+ /**
+ * Conversion from local coordinates to geographic or projected
coordinates shown in this status bar.
+ * This is the concatenation of {@link #localToObjectiveCRS} with the
transform from {@link #objectiveCRS}
+ * to the user-selected CRS for displaying in the status bar. This
conversion shall never be null but may be
+ * the identity transform. It is usually non-affine if the display CRS is
not the same than the objective CRS.
+ * This transform may have a {@linkplain
CoordinateOperation#getCoordinateOperationAccuracy() limited accuracy}.
+ *
+ * <p>The target CRS can be obtained by {@link
CoordinateFormat#getDefaultCRS()}.</p>
+ */
+ private MathTransform localToTargetCRS;
/**
* The source local indices before conversion to geospatial coordinates.
@@ -147,7 +190,7 @@ public class StatusBar extends Widget implements
EventHandler<MouseEvent> {
/**
* The desired precisions for each dimension in the {@link
#targetCoordinates} to format.
- * It may vary for each position if the {@link #localToCRS} transform is
non-linear.
+ * It may vary for each position if the {@link #localToTargetCRS}
transform is non-linear.
* This array is initially {@code null} and created when first needed.
*/
private double[] precisions;
@@ -196,24 +239,29 @@ public class StatusBar extends Widget implements
EventHandler<MouseEvent> {
* @param referenceSystems the manager of reference systems chosen by
the user, or {@code null} if none.
*/
public StatusBar(final RecentReferenceSystems referenceSystems) {
- localToCRS = MathTransforms.identity(BIDIMENSIONAL);
- targetCoordinates = new GeneralDirectPosition(BIDIMENSIONAL);
- sourceCoordinates = targetCoordinates.coordinates;
- lastX = lastY = Double.NaN;
- format = new CoordinateFormat();
- coordinates = new Label();
- message = new Label();
- progress = new ProgressBar();
+ localToObjectiveCRS = MathTransforms.identity(BIDIMENSIONAL);
+ localToTargetCRS = localToObjectiveCRS;
+ targetCoordinates = new GeneralDirectPosition(BIDIMENSIONAL);
+ sourceCoordinates = targetCoordinates.coordinates;
+ lastX = lastY = Double.NaN;
+ format = new CoordinateFormat();
+ coordinates = new Label();
+ message = new Label();
+ progress = new ProgressBar();
progress.setVisible(false);
- message.setTextFill(Color.RED);
+ message.setTextFill(Styles.ERROR_TEXT);
message.setMaxWidth(Double.POSITIVE_INFINITY);
HBox.setHgrow(message, Priority.ALWAYS);
+ coordinates.minWidthProperty().bind(coordinates.widthProperty());
view = new HBox(12, progress, message, coordinates);
view.setPadding(PADDING);
canvasProperty = new SimpleObjectProperty<>(this, "canvas");
canvasProperty.addListener(this::onCanvasSpecified);
- if (referenceSystems != null) {
- final ContextMenu menu = new
ContextMenu(referenceSystems.createMenuItems((e,o,n) -> setDisplayCRS(n)));
+ if (referenceSystems == null) {
+ areaOfInterest = null;
+ } else {
+ areaOfInterest = referenceSystems.areaOfInterest;
+ final ContextMenu menu = new
ContextMenu(referenceSystems.createMenuItems(this::onSelectCRS));
view.setOnMousePressed((MouseEvent event) -> {
if (event.isSecondaryButtonDown()) {
menu.show((HBox) event.getSource(), event.getScreenX(),
event.getScreenY());
@@ -245,8 +293,8 @@ public class StatusBar extends Widget implements
EventHandler<MouseEvent> {
/**
* Sets the canvas that this status bar is tracking.
- * This method register all necessary listeners.
- * A value of {@code null} unregister all listeners.
+ * This method registers all necessary listeners.
+ * A value of {@code null} unregisters all listeners.
*
* @param canvas the canvas to track, or {@code null} if none.
*
@@ -278,9 +326,8 @@ public class StatusBar extends Widget implements
EventHandler<MouseEvent> {
}
/**
- * Listener notified when {@link MapCanvas} completed its rendering.
- * This listener set {@link StatusBar#localToCRS} to the inverse of
- * {@link MapCanvas#objectiveToDisplay}.
+ * Listener notified when {@link MapCanvas} completed its rendering. This
listener sets
+ * {@link StatusBar#localToObjectiveCRS} to the inverse of {@link
MapCanvas#objectiveToDisplay}.
*/
private final class RenderingListener implements ChangeListener<Boolean> {
@Override public void changed(final ObservableValue<? extends Boolean>
property,
@@ -303,32 +350,35 @@ public class StatusBar extends Widget implements
EventHandler<MouseEvent> {
* <li>{@link GridGeometry#getCoordinateReferenceSystem()} defines the
CRS of the coordinates to format.</li>
* <li>{@link GridGeometry#getGridToCRS(PixelInCell)
GridGeometry.getGridToCRS(PixelInCell.CELL_CENTER)}
* defines the conversion from coordinate values locale to the
canvas to coordinate values in the CRS
- * (the {@linkplain #getLocalToCRS() local to CRS} conversion).</li>
+ * (the {@linkplain #getLocalToObjectiveCRS() local to objective
CRS} conversion).</li>
* <li>{@link GridGeometry#getExtent()} provides the view size in
pixels, used for estimating a resolution.</li>
* <li>{@link GridGeometry#getResolution(boolean)} is also used for
estimating a resolution.</li>
* </ul>
*
- * All above properties are optional.
- * The "local to CRS" conversion can be updated after this method call
with {@link #setLocalToCRS(MathTransform)}.
+ * All above properties are optional. The "local to objective CRS"
conversion can be updated
+ * after this method call with {@link
#setLocalToObjectiveCRS(MathTransform)}.
*
* @param geometry geometry of the coverage shown in {@link MapCanvas},
or {@code null}.
*/
public void applyCanvasGeometry(final GridGeometry geometry) {
- localToCRS = null;
- precisions = null;
- inflatePrecisions = null;
+ /*
+ * Compute values in local variables without modifying `StatusBar`
fields for now.
+ * The fields will be updated only after we know that this operation
is successful.
+ */
+ MathTransform localToCRS = null;
CoordinateReferenceSystem crs = null;
double resolution = 1;
+ double[] inflate = null;
Unit<?> unit = Units.PIXEL;
if (geometry != null) {
+ if (geometry.isDefined(GridGeometry.CRS)) {
+ crs = geometry.getCoordinateReferenceSystem();
+ }
if (geometry.isDefined(GridGeometry.GRID_TO_CRS)) {
localToCRS = geometry.getGridToCRS(PixelInCell.CELL_CENTER);
- if (geometry.isDefined(GridGeometry.CRS)) {
- crs = geometry.getCoordinateReferenceSystem();
- }
}
/*
- * Computes the precision of coordinates to format. We use the
finest resolution,
+ * Compute the precision of coordinates to format. We use the
finest resolution,
* looking only at axes having the same units of measurement than
the first axis.
* This will be used as a fallback if we can not compute the
precision specific
* to a coordinate, for example if we can not compute the
derivative.
@@ -353,13 +403,14 @@ public class StatusBar extends Widget implements
EventHandler<MouseEvent> {
if (geometry.isDefined(GridGeometry.EXTENT)) {
final GridExtent extent = geometry.getExtent();
final int n = extent.getDimension();
- inflatePrecisions = new double[n];
+ inflate = new double[n];
for (int i=0; i<n; i++) {
- inflatePrecisions[i] = (0.5 / extent.getSize(i)) + 1;
+ inflate[i] = (0.5 / extent.getSize(i)) + 1;
}
}
}
/*
+ * Remaining code should not fail, so we can modify `StatusBar` fields.
* Prepare objects to be reused for each coordinate transformation.
* Configure the `CoordinateFormat` with the CRS.
*/
@@ -371,53 +422,163 @@ public class StatusBar extends Widget implements
EventHandler<MouseEvent> {
targetCoordinates = new GeneralDirectPosition(BIDIMENSIONAL);
sourceCoordinates = targetCoordinates.coordinates; // Okay to
share array if same dimension.
}
- setDisplayCRS(crs);
+ objectiveCRS = crs;
+ localToObjectiveCRS = localToTargetCRS = localToCRS;
+ inflatePrecisions = inflate;
+ precisions = null;
+ format.setDefaultCRS(crs);
format.setGroundPrecision(Quantities.create(resolution, unit));
- lastX = lastY = Double.NaN;
+ refresh();
}
/**
- * Sets the coordinate reference systems to use for representing
coordinates in status bar.
+ * Invoked when the user selects a new reference system for the
coordinates to show in status bar.
*
- * @param crs the coordinate reference system to use for coordinates in
the status bar.
+ * @param property the {@link org.apache.sis.gui.referencing.MenuSync}
property.
+ * @param oldValue the old reference system, or {@code null} if none.
+ * @param newValue the CRS to use for formatting coordinates in this
status bar.
+ */
+ private void onSelectCRS(ObservableValue<? extends ReferenceSystem>
property,
+ ReferenceSystem oldValue, ReferenceSystem
newValue)
+ {
+ setTargetCRS(newValue instanceof CoordinateReferenceSystem ?
(CoordinateReferenceSystem) newValue : null);
+ }
+
+ /**
+ * Sets the coordinate reference system of the coordinates shown in this
status bar.
+ * The change may not appear immediately after method return; this method
may use a
+ * background thread for computing the coordinate operation.
*/
- private void setDisplayCRS(final ReferenceSystem crs) {
- if (crs instanceof CoordinateReferenceSystem) {
- format.setDefaultCRS((CoordinateReferenceSystem) crs);
+ private void setTargetCRS(final CoordinateReferenceSystem crs) {
+ if (objectiveCRS != null && objectiveCRS != crs) {
+ coordinates.setTextFill(Styles.OUTDATED_TEXT);
+ final Envelope aoi = (areaOfInterest != null) ?
areaOfInterest.get() : null;
+ BackgroundThreads.execute(new Task<MathTransform>() {
+ /**
+ * The operation used for computing the transform to target
CRS.
+ * This is used for configuring format with positional
accuracy.
+ */
+ private CoordinateOperation operation;
+
+ /**
+ * Invoked in a background thread for fetching transformation
to target CRS.
+ * This operation may be long the first time that it is
executed, but should
+ * be fast on subsequent invocations.
+ */
+ @Override protected MathTransform call() throws
FactoryException {
+ DefaultGeographicBoundingBox bbox = null;
+ if (aoi != null) try {
+ bbox = new DefaultGeographicBoundingBox();
+ bbox.setBounds(aoi);
+ } catch (TransformException e) {
+ bbox = null;
+
Logging.recoverableException(Logging.getLogger(Modules.APPLICATION),
+ StatusBar.class,
"setTargetCRS", e);
+ }
+ operation = CRS.findOperation(objectiveCRS, crs, bbox);
+ return MathTransforms.concatenate(localToObjectiveCRS,
operation.getMathTransform());
+ }
+
+ /**
+ * Invoked in JavaFX thread on success. The {@link
StatusBar#localToTargetCRS} transform
+ * is set to the transform that we computed in background and
the {@link CoordinateFormat}
+ * is configured with auxiliary information such as positional
accuracy.
+ */
+ @Override protected void succeeded() {
+ final CoordinateReferenceSystem targetCRS =
operation.getTargetCRS();
+ format.setDefaultCRS(targetCRS != null ? targetCRS : crs);
+ localToTargetCRS = getValue();
+// TODO: CRS.getLinearAccuracy(op);
+ coordinates.setTextFill(Styles.NORMAL_TEXT);
+ refresh();
+ }
+
+ /**
+ * Invoked in JavaFX thread on failure. The previous CRS is
keep unchanged but
+ * the coordinates will appear in red for telling user that
there is a problem.
+ */
+ @Override protected void failed() {
+ setErrorMessage(null, getException());
+ resetTargetCRS(Styles.ERROR_TEXT);
+ }
+ });
} else {
- format.setDefaultCRS(null);
+ resetTargetCRS(Styles.NORMAL_TEXT);
}
}
/**
- * Returns the conversion from local coordinates to geographic or
projected coordinates.
- * The local coordinates are the coordinates of the view, as given for
example in {@link MouseEvent}.
+ * Resets {@link #localToTargetCRS} to its default value. This is invoked
either when the specified
+ * target CRS is {@link #objectiveCRS}, or when an attempt to use another
CRS failed.
+ */
+ private void resetTargetCRS(final Color textFill) {
+ localToTargetCRS = localToObjectiveCRS;
+ format.setDefaultCRS(objectiveCRS);
+ coordinates.setTextFill(textFill);
+ }
+
+ /**
+ * Returns the reference systems used by the coordinates shown in this
status bar.
+ * This is initially the same value than {@link #getObjectiveCRS()}, but
may become
+ * different if the user selects another reference system through
contextual menu.
+ *
+ * @return reference systems used by the coordinates shown in this status
bar.
+ */
+ public final Optional<ReferenceSystem> getFormatReferenceSystem() {
+ return Optional.ofNullable(format.getDefaultCRS());
+ }
+
+ /**
+ * Returns the reference system used for rendering the data for which this
status bar is providing cursor coordinates.
+ * This is the "{@linkplain RecentReferenceSystems#setPreferred(boolean,
ReferenceSystem) preferred}" or native
+ * data CRS. It may not be the same than the CRS of coordinates actually
shown in the status bar.
+ *
+ * @return the reference system used for rendering the data for which this
status bar
+ * is providing cursor coordinates, or {@code null} if unknown.
+ *
+ * @see MapCanvas#getObjectiveCRS()
+ */
+ public final Optional<CoordinateReferenceSystem> getObjectiveCRS() {
+ return Optional.ofNullable(objectiveCRS);
+ }
+
+ /**
+ * Returns the conversion from local coordinates to geographic or
projected coordinates of rendered data.
+ * The local coordinates are the coordinates of the JavaFX view, as given
for example in {@link MouseEvent}.
* This is initially an identity transform and can be computed by {@link
#applyCanvasGeometry(GridGeometry)}.
+ * This transform ignores all CRS changes resulting from user selecting a
different CRS in the contextual menu.
+ * This transform is usually (but not necessarily) affine.
*
- * @return conversion from local coordinates to "real world" coordinates.
+ * @return conversion from local coordinates to "real world" coordinates
of rendered data.
+ * This is not necessarily the conversion to coordinates shown in
the status bar.
+ *
+ * @see MapCanvas#getObjectiveToDisplay()
*/
- public final MathTransform getLocalToCRS() {
- return localToCRS;
+ public final MathTransform getLocalToObjectiveCRS() {
+ return localToObjectiveCRS;
}
/**
- * Sets the conversion from local coordinates to geographic or projected
coordinates.
- * The given value must have the same number of source and target
dimensions than the
- * previous value. If a change in the number of dimension is desired,
- * use {@link #applyCanvasGeometry(GridGeometry)} instead.
+ * Sets the conversion from local coordinates to geographic or projected
coordinates of rendered data.
+ * The given transform must have the same number of source and target
dimensions than the previous value
+ * (if a change in the number of dimension is desired, use {@link
#applyCanvasGeometry(GridGeometry)} instead).
+ * The conversion should have no {@linkplain
CoordinateOperation#getCoordinateOperationAccuracy() inaccuracy}
+ * (ignoring rounding error). The status bar is updated as if the new
conversion was applied <em>before</em>
+ * any CRS changes resulting from user selecting a different CRS in the
contextual menu.
*
- * @param conversion the new conversion from local coordinates to "real
world" coordinates.
+ * @param conversion the new conversion from local coordinates to "real
world" coordinates of rendered data.
* @throws MismatchedDimensionException if the number of dimensions is not
the same than previous conversion.
*/
- public final void setLocalToCRS(final MathTransform conversion) {
+ public final void setLocalToObjectiveCRS(final MathTransform conversion) {
ArgumentChecks.ensureNonNull("conversion", conversion);
- int expected = localToCRS.getSourceDimensions();
+ int expected = localToObjectiveCRS.getSourceDimensions();
int actual = conversion.getSourceDimensions();
if (expected == actual) {
- expected = localToCRS.getTargetDimensions();
+ expected = localToObjectiveCRS.getTargetDimensions();
actual = conversion.getTargetDimensions();
if (expected == actual) {
- localToCRS = conversion;
+ localToObjectiveCRS = conversion;
+ setTargetCRS(format.getDefaultCRS());
// Recompute `localToTargetCRS`.
return;
}
}
@@ -439,6 +600,18 @@ public class StatusBar extends Widget implements
EventHandler<MouseEvent> {
}
/**
+ * Rewrites the coordinates. This method is invoked after a change of
coordinate reference system.
+ */
+ private void refresh() {
+ final double x = lastX;
+ final double y = lastY;
+ lastX = lastY = Double.NaN;
+ if (!Double.isNaN(x) && !Double.isNaN(y)) {
+ setLocalCoordinates(x, y);
+ }
+ }
+
+ /**
* Converts and formats the given pixel coordinates. Those coordinates
will be automatically
* converted to geographic or projected coordinates if a "local to CRS"
conversion is available.
*
@@ -455,7 +628,7 @@ public class StatusBar extends Widget implements
EventHandler<MouseEvent> {
try {
Matrix derivative;
try {
- derivative =
MathTransforms.derivativeAndTransform(localToCRS,
+ derivative =
MathTransforms.derivativeAndTransform(localToTargetCRS,
sourceCoordinates, 0,
targetCoordinates.coordinates, 0);
} catch (TransformException ignore) {
/*
@@ -463,7 +636,7 @@ public class StatusBar extends Widget implements
EventHandler<MouseEvent> {
* derivative calculation. Try again without derivative
(the precision will be set
* to the default resolution computed in
`setCanvasGeometry(…)`).
*/
- localToCRS.transform(sourceCoordinates, 0,
targetCoordinates.coordinates, 0, 1);
+ localToTargetCRS.transform(sourceCoordinates, 0,
targetCoordinates.coordinates, 0, 1);
derivative = null;
}
if (derivative == null) {
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/gui/referencing/RecentReferenceSystems.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/referencing/RecentReferenceSystems.java
index cba3feb..6355f7a 100644
---
a/application/sis-javafx/src/main/java/org/apache/sis/gui/referencing/RecentReferenceSystems.java
+++
b/application/sis-javafx/src/main/java/org/apache/sis/gui/referencing/RecentReferenceSystems.java
@@ -105,6 +105,10 @@ public class RecentReferenceSystems {
/**
* The area of interest, or {@code null} if none. This is used for
filtering the reference systems added by
* {@code addAlternatives(…)} and for providing some guidance to user when
{@link CRSChooser} is shown.
+ *
+ * <div class="note"><b>API note:</b>
+ * We do not provide getter/setter for this property; use {@link
ObjectProperty#set(Object)}
+ * directly instead. We omit the "Property" suffix for making this
operation more natural.</div>
*/
public final ObjectProperty<Envelope> areaOfInterest;
@@ -116,6 +120,10 @@ public class RecentReferenceSystems {
/**
* The comparison criterion for considering two reference systems as a
duplication.
* The default value is {@link ComparisonMode#ALLOW_VARIANT}, i.e. axis
orders are ignored.
+ *
+ * <div class="note"><b>API note:</b>
+ * We do not provide getter/setter for this property; use {@link
ObjectProperty#set(Object)}
+ * directly instead. We omit the "Property" suffix for making this
operation more natural.</div>
*/
public final ObjectProperty<ComparisonMode> duplicationCriterion;
@@ -182,7 +190,7 @@ public class RecentReferenceSystems {
/**
* {@code true} if {@code RecentReferenceSystems} is in the process of
modifying {@link #referenceSystems} list.
- * In such we want to temporarily disable the {@link Listener}. This field
is read and updated in JavaFX thread.
+ * In such case we want to temporarily disable the {@link Listener}. This
field is read and updated in JavaFX thread.
*/
private boolean isAdjusting;
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Styles.java
b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Styles.java
index 735a77d..225d50e 100644
---
a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Styles.java
+++
b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Styles.java
@@ -81,6 +81,11 @@ public final class Styles extends Static {
public static final Color CODE_TEXT = Color.LIGHTSLATEGREY;
/**
+ * Color of text used for outdated information while a background thread
is refreshing data.
+ */
+ public static final Color OUTDATED_TEXT = Color.GRAY;
+
+ /**
* Color of text shown in place of data that we failed to load.
*/
public static final Color ERROR_TEXT = Color.RED;
diff --git
a/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java
b/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java
index b1e925d..db94513 100644
---
a/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java
+++
b/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java
@@ -319,6 +319,7 @@ public class CoordinateFormat extends
CompoundFormat<DirectPosition> {
* @param crs the default coordinate reference system, or {@code null}
if none.
*/
public void setDefaultCRS(final CoordinateReferenceSystem crs) {
+ isPrecisionApplied &= (crs == defaultCRS);
defaultCRS = crs;
}