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 14a89a39bc Move the widget for configuring the isoline as a `MapItem`
to show in `MapContextView`.
14a89a39bc is described below
commit 14a89a39bcf5af7b0f90353676eab2594009ba0a
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Mon Mar 30 11:33:09 2026 +0200
Move the widget for configuring the isoline as a `MapItem` to show in
`MapContextView`.
---
.../apache/sis/gui/controls/FormatApplicator.java | 6 +-
.../apache/sis/gui/controls/ValueColorMapper.java | 12 ++--
.../apache/sis/gui/coverage/CoverageCanvas.java | 18 +++--
.../apache/sis/gui/coverage/CoverageControls.java | 27 ++-----
...IsolineRenderer.java => IsolineController.java} | 82 ++++++++++++++++------
.../apache/sis/gui/coverage/StyleController.java | 30 ++++----
.../sis/gui/coverage/StyledRenderingData.java | 6 +-
.../org/apache/sis/gui/internal/Resources.java | 10 +++
.../apache/sis/gui/internal/Resources.properties | 2 +
.../sis/gui/internal/Resources_fr.properties | 2 +
.../apache/sis/gui/map/style/ItemController.java | 39 ++++++++++
.../apache/sis/gui/map/style/MapContextView.java | 23 +++++-
.../sis/gui/controls/ValueColorMapperApp.java | 7 +-
13 files changed, 190 insertions(+), 74 deletions(-)
diff --git
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/controls/FormatApplicator.java
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/controls/FormatApplicator.java
index e1307edb72..ea24ba17b4 100644
---
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/controls/FormatApplicator.java
+++
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/controls/FormatApplicator.java
@@ -17,6 +17,7 @@
package org.apache.sis.gui.controls;
import java.math.BigDecimal;
+import java.util.Locale;
import java.text.Format;
import java.text.NumberFormat;
import java.text.DecimalFormat;
@@ -83,10 +84,11 @@ final class FormatApplicator<T> extends StringConverter<T>
* rounding errors that may surprise the user, for example if we need to
compute {@code n * scale}
* where <var>scale</var> has been specified by user as 0.1.
*
+ * @param locale the locale of the desired number format.
* @return an instance for parsing and formatting numbers.
*/
- public static FormatApplicator<Number> createNumberFormat() {
- final FormatApplicator<Number> f = new
FormatApplicator<>(Number.class, NumberFormat.getInstance());
+ public static FormatApplicator<Number> createNumberFormat(final Locale
locale) {
+ final var f = new FormatApplicator<Number>(Number.class,
NumberFormat.getInstance(locale));
if (f.format instanceof DecimalFormat) {
((DecimalFormat) f.format).setParseBigDecimal(true);
}
diff --git
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/controls/ValueColorMapper.java
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/controls/ValueColorMapper.java
index 7eb60b66d5..e9da2185a0 100644
---
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/controls/ValueColorMapper.java
+++
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/controls/ValueColorMapper.java
@@ -16,6 +16,7 @@
*/
package org.apache.sis.gui.controls;
+import java.util.Locale;
import java.util.Objects;
import java.math.BigDecimal;
import javafx.beans.property.BooleanProperty;
@@ -178,14 +179,13 @@ public final class ValueColorMapper extends TabularWidget
{
/**
* Creates a new "value-color mapper" widget.
*
- * @param resources localized resources, given because already known by
the caller.
- * @param vocabulary localized resources, given because already known by
the caller
- * (those arguments would be removed if this
constructor was public API).
+ * @param locale the locale to use in this widget.
*/
- public ValueColorMapper(final Resources resources, final Vocabulary
vocabulary) {
+ public ValueColorMapper(final Locale locale) {
table = newTable();
- textConverter = FormatApplicator.createNumberFormat();
- createIsolineTable(vocabulary);
+ textConverter = FormatApplicator.createNumberFormat(locale);
+ createIsolineTable(Vocabulary.forLocale(locale));
+ final Resources resources = Resources.forLocale(locale);
final MenuItem rangeMenu = new
MenuItem(resources.getString(Resources.Keys.RangeOfValues));
final MenuItem clearAll = new
MenuItem(resources.getString(Resources.Keys.ClearAll));
rangeMenu.setOnAction((e) -> insertRangeOfValues());
diff --git
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
index 7433c89b84..ca1a9b00ae 100644
---
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
+++
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
@@ -289,7 +289,7 @@ public class CoverageCanvas extends MapCanvasAWT {
* references to {@link javafx.scene.control.TableView} list of items,
which are the list of isoline levels
* with their colors.
*/
- IsolineRenderer isolines;
+ IsolineController isolines;
/**
* Listener notified when tiles are read, for showing them on top of the
image as translucent tiles.
@@ -775,6 +775,10 @@ public class CoverageCanvas extends MapCanvasAWT {
* If the {@link StyledRenderingData#clear()} method is not invoked, then
the map projection,
* zoom, <i>etc.</i> are preserved.
*
+ * <p>The caller is responsible for invoking {@link #requestRepaint()} or
something equivalent,
+ * possibly indirectly through a listener on a modified property. The
{@link #requestRepaint()}
+ * method is not invoked by this method because the caller will typically
do more cleaning.</p>
+ *
* @see #clear()
*/
private void clearRenderedImage() {
@@ -844,6 +848,10 @@ public class CoverageCanvas extends MapCanvasAWT {
/**
* Clears all information that are derived from the raw image projected to
objective CRS.
* In current version this is only isolines.
+ *
+ * <p>The caller is responsible for invoking {@link #requestRepaint()} or
something equivalent,
+ * possibly indirectly through a listener on a modified property. The
{@link #requestRepaint()}
+ * method is not invoked by this method because the caller will typically
do more cleaning.</p>
*/
private void clearIsolines() {
if (isolines != null) {
@@ -995,7 +1003,7 @@ public class CoverageCanvas extends MapCanvasAWT {
/**
* Snapshot of information required for rendering isolines, or {@code
null} if none.
*/
- private IsolineRenderer.Snapshot[] isolines;
+ private IsolineController.Snapshot[] isolines;
/**
* Creates a new renderer. Shall be invoked in JavaFX thread.
@@ -1124,7 +1132,7 @@ public class CoverageCanvas extends MapCanvasAWT {
prefetchedImage = data.prefetch(resampledImage,
resampledToDisplay, displayBounds);
}
if (newIsolines != null) {
- IsolineRenderer.complete(isolines, newIsolines);
+ IsolineController.complete(isolines, newIsolines);
}
} finally {
LogHandler.loadingStop(id);
@@ -1151,7 +1159,7 @@ public class CoverageCanvas extends MapCanvasAWT {
// Arbitrarily use a line tickness of 1/8 of source pixel size
for making apparent when zoom is strong.
gr.setStroke(new
BasicStroke(data.getDataPixelSize(objectivePOI) / 8));
gr.transform((AffineTransform) objectiveToDisplay); //
This cast is safe in PlanarCanvas subclass.
- for (final IsolineRenderer.Snapshot s : isolines) {
+ for (final IsolineController.Snapshot s : isolines) {
s.paint(gr, objectiveAOI);
}
gr.setTransform(at);
@@ -1176,7 +1184,7 @@ public class CoverageCanvas extends MapCanvasAWT {
tileReadListener.takeSnapshotOfObjectiveCRS();
}
if (isolines != null) {
- for (final IsolineRenderer.Snapshot s : isolines) {
+ for (final IsolineController.Snapshot s : isolines) {
s.commit();
}
}
diff --git
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageControls.java
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageControls.java
index 2daf592fc9..a3ea19acd9 100644
---
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageControls.java
+++
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageControls.java
@@ -16,7 +16,6 @@
*/
package org.apache.sis.gui.coverage;
-import java.util.List;
import java.util.Locale;
import javafx.application.Platform;
import javafx.scene.control.TitledPane;
@@ -25,7 +24,6 @@ import javafx.scene.control.Label;
import javafx.scene.control.TableView;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.GridPane;
-import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.layout.Priority;
import javafx.collections.ObservableList;
@@ -44,7 +42,6 @@ import org.apache.sis.gui.internal.Resources;
import org.apache.sis.gui.internal.DataStoreOpener;
import org.apache.sis.gui.internal.BackgroundThreads;
import static org.apache.sis.gui.internal.LogHandler.LOGGER;
-import org.apache.sis.gui.controls.ValueColorMapper;
import org.apache.sis.gui.controls.SyncWindowList;
import org.apache.sis.util.resources.Vocabulary;
import org.apache.sis.util.logging.Logging;
@@ -91,11 +88,6 @@ final class CoverageControls extends ViewAndControls {
*/
private final ChoiceBox<Interpolation> interpolation;
- /**
- * The renderer of isolines.
- */
- private final IsolineRenderer isolines;
-
/**
* Creates a new set of coverage controls.
*
@@ -118,7 +110,7 @@ final class CoverageControls extends ViewAndControls {
* - Tree of layers associated to the coverage (styling, isolines,
visual indication of loaded tiles).
*/
final var layers = new MapContextView(resources);
- style = new StyleController(view, resources);
+ style = new StyleController(view);
layers.setRootItem(style);
/*
* "Display" section with the following controls:
@@ -161,14 +153,10 @@ final class CoverageControls extends ViewAndControls {
* "Isolines" section with the following controls:
* - Colors for each isoline levels
*/
- final VBox isolinesPane;
- { // Block for making variables locale to this scope.
- final ValueColorMapper mapper = new ValueColorMapper(resources,
vocabulary);
- isolines = new IsolineRenderer(view);
- isolines.setIsolineTables(List.of(mapper.getSteps()));
- final Region style = mapper.getView();
- VBox.setVgrow(style, Priority.ALWAYS);
- isolinesPane = new VBox(style); // TODO:
add band selector
+ if (view.isolines == null) {
+ final var isolines = new IsolineController(view,
vocabulary.getString(Vocabulary.Keys.Isolines));
+ style.getChildren().add(isolines);
+ view.isolines = isolines;
}
/*
* Synchronized windows. A synchronized windows is a window which can
reproduce the same gestures
@@ -182,9 +170,8 @@ final class CoverageControls extends ViewAndControls {
*/
final TitledPane deferred; // Control to be built
only if requested.
controlPanes = new TitledPane[] {
- new TitledPane(vocabulary.getString(Vocabulary.Keys.Layers),
layers.getView()),
- new TitledPane(vocabulary.getString(Vocabulary.Keys.Display),
displayPane),
- new TitledPane(vocabulary.getString(Vocabulary.Keys.Isolines),
isolinesPane),
+ new TitledPane(vocabulary.getString(Vocabulary.Keys.Layers),
layers.getView()),
+ new TitledPane(vocabulary.getString(Vocabulary.Keys.Display),
displayPane),
new TitledPane(resources.getString(Resources.Keys.Windows),
windows.getView()),
deferred = new
TitledPane(vocabulary.getString(Vocabulary.Keys.Properties), null)
};
diff --git
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/IsolineRenderer.java
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/IsolineController.java
similarity index 86%
rename from
optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/IsolineRenderer.java
rename to
optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/IsolineController.java
index 19b59ba0a1..fbecd75e17 100644
---
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/IsolineRenderer.java
+++
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/IsolineController.java
@@ -31,6 +31,9 @@ import java.awt.geom.Rectangle2D;
import java.awt.image.RenderedImage;
import javafx.application.Platform;
import javafx.scene.control.TableView;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.Region;
+import javafx.scene.layout.VBox;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
@@ -38,7 +41,10 @@ import javafx.collections.ListChangeListener;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.apache.sis.gui.controls.ColorRamp;
+import org.apache.sis.gui.controls.ValueColorMapper;
import org.apache.sis.gui.controls.ValueColorMapper.Step;
+import org.apache.sis.gui.map.style.MapItem;
+import org.apache.sis.gui.map.style.ItemController;
import org.apache.sis.image.processing.isoline.Isolines;
import org.apache.sis.image.internal.shared.ImageUtilities;
import org.apache.sis.geometry.wrapper.j2d.EmptyShape;
@@ -47,15 +53,16 @@ import org.apache.sis.util.ArraysExt;
/**
- * Caches and draws isoline shapes in a {@link CoverageCanvas}. This class is
designed for interactive use
- * in JavaFX widget; this is not a class for doing symbology e.g. in a web
service. Most of the work done
- * by {@code IsolineRenderer} is about listening to changes in {@link
TableView}, managing data exchanges
- * between JavaFX thread and background thread, and computes only isolines
that are new compared to previous
- * rendering.
+ * Configures, draws and caches isoline shapes in a {@link CoverageCanvas}.
+ * This class is designed for interactive use in JavaFX widget.
+ * This is not a class for doing symbology e.g. in a web service.
+ * Most of the work done by {@code IsolineController} is about listening to
changes in {@link TableView},
+ * managing data exchanges between JavaFX thread and background thread,
+ * and computes only isolines that are new compared to previous rendering.
*
* @author Martin Desruisseaux (Geomatys)
*/
-final class IsolineRenderer {
+final class IsolineController extends ItemController {
/**
* The canvas where isolines are drawn.
*/
@@ -66,17 +73,25 @@ final class IsolineRenderer {
*/
private Band[] bands;
+ /**
+ * The widgets for configuring the isolines. Created when first requested.
+ *
+ * @see #getConfigurationPanel()
+ */
+ private Region configurationPanel;
+
/**
* Creates an initially empty set of isolines.
+ * The controller is unselected by default.
*
* @param canvas the canvas where isolines are drawn.
+ * @param title the title to show in the tree view. Usually "Isolines"
in the current locale.
*/
- public IsolineRenderer(final CoverageCanvas canvas) {
- if (canvas.isolines != null) {
- throw new IllegalArgumentException();
- }
+ public IsolineController(final CoverageCanvas canvas, final String title) {
+ super(new MapItem(title));
this.canvas = canvas;
- canvas.isolines = this;
+ setIndependent(true);
+ selectedProperty().addListener((invalid) -> canvas.requestRepaint());
}
/**
@@ -99,6 +114,10 @@ final class IsolineRenderer {
/**
* Clears the cache. This method shall be invoked when the image used for
computing isolines has changed,
* or when the {@code gridToCRS} transform has changed. This method shall
be invoked in JavaFX thread.
+ *
+ * <p>The caller is responsible for invoking {@link
CoverageCanvas#requestRepaint()}.
+ * This is not done by this method because the caller will typically need
to do more
+ * cleaning before to request a repaint.</p>
*/
final void clear() {
assert Platform.isFxApplicationThread();
@@ -109,6 +128,24 @@ final class IsolineRenderer {
}
}
+ /**
+ * Returns the panel of JavaFX controls for configuring the isolines.
+ * This method must be invoked from the JavaFX thread.
+ *
+ * @return the isoline configuration panel.
+ */
+ @Override
+ protected Region getConfigurationPanel() {
+ if (configurationPanel == null) {
+ final var mapper = new ValueColorMapper(canvas.getLocale());
+ setIsolineTables(List.of(mapper.getSteps()));
+ final Region style = mapper.getView();
+ VBox.setVgrow(style, Priority.ALWAYS);
+ configurationPanel = new VBox(style); // TODO: add band
selector
+ }
+ return configurationPanel;
+ }
+
/**
* Sets the isoline values for all bands from the content of tables edited
by user.
* This method registers listener on the given lists for repainting the
isolines
@@ -152,6 +189,7 @@ final class IsolineRenderer {
*
* @param steps the list of isoline levels to render.
*/
+ @SuppressWarnings("this-escape")
Band(final ObservableList<Step> steps) {
this.steps = steps;
addListeners(steps);
@@ -162,7 +200,7 @@ final class IsolineRenderer {
* Clears the cache. This method shall be invoked when the image used
for computing isolines has changed,
* or when the {@code gridToCRS} transform has changed. This method
shall be invoked in JavaFX thread.
*
- * @see IsolineRenderer#clear()
+ * @see IsolineController#clear()
*/
final void clear() {
// Force new instance instead of `Map.clear()` because previous
instance may be used by `Snapshot`.
@@ -191,7 +229,11 @@ final class IsolineRenderer {
addListeners(change.getAddedSubList());
}
}
- canvas.requestRepaint();
+ final boolean isEmpty = isEmpty();
+ if (isSelected() == isEmpty) {
+ setSelected(!isEmpty);
+ canvas.requestRepaint();
+ }
}
/**
@@ -237,7 +279,7 @@ final class IsolineRenderer {
* @param keep an empty set used by this method for listing the
levels to keep in the cache.
* @return a snapshot of current {@code Band} state for use by a
background thread.
*
- * @see IsolineRenderer#prepare()
+ * @see IsolineController#prepare()
*/
final Snapshot prepare(final Set<Double> keep) {
if (isolines == null) {
@@ -271,11 +313,11 @@ final class IsolineRenderer {
*/
final Snapshot[] prepare() {
assert Platform.isFxApplicationThread();
- if (isEmpty()) {
+ if (!isSelected() || isEmpty()) {
return null;
}
- final Snapshot[] snapshots = new Snapshot[bands.length];
- final Set<Double> keep = new HashSet<>();
+ final var snapshots = new Snapshot[bands.length];
+ final var keep = new HashSet<Double>();
for (int i=0; i < snapshots.length; i++) {
snapshots[i] = bands[i].prepare(keep);
}
@@ -325,7 +367,7 @@ final class IsolineRenderer {
*/
if (levels != null) {
if (CoverageCanvas.TRACE) {
- System.out.println("IsolineRenderer.complete(…):");
+ System.out.println("IsolineController.complete(…):");
for (int i=0; i<levels.length; i++) {
System.out.printf("\tFor band %d: %s%n", i,
Arrays.toString(levels[i]));
}
@@ -389,7 +431,7 @@ final class IsolineRenderer {
* the {@link #isolines} map after the isoline painting is completed.
Stored in a separated map
* because we must wait to be back to JavaFX thread before we can
write in {@link #isolines}.
*/
- private Map<Double,Shape> newIsolines;
+ private Map<Double, Shape> newIsolines;
/**
* The isoline shapes to draw. May contain {@code null} elements if
some shapes are missing.
@@ -454,7 +496,7 @@ final class IsolineRenderer {
*/
private void complete(final Isolines isolines) {
newIsolines = isolines.polylines();
- for (final Map.Entry<Double,Shape> entry : newIsolines.entrySet())
{
+ for (final Map.Entry<Double, Shape> entry :
newIsolines.entrySet()) {
final Integer j = missingLevels.get(entry.getKey());
if (j != null) shapes[j] = entry.getValue();
}
diff --git
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/StyleController.java
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/StyleController.java
index 18548647a8..514f2aa75e 100644
---
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/StyleController.java
+++
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/StyleController.java
@@ -32,26 +32,28 @@ import
org.apache.sis.storage.tiling.TiledGridCoverageResource;
* @author Martin Desruisseaux (Geomatys)
*/
final class StyleController extends ItemController {
+ /**
+ * The canvas for which to control the rendering.
+ */
+ private final CoverageCanvas canvas;
+
/**
* Whether to show a visual indication of which tiles are read.
+ * Creates when first needed.
*/
- private final ItemController showTileReads;
+ private ItemController showTileReads;
/**
* Creates a controller for a map layer.
* The controller is initially selected.
*
- * @param view where the coverage will be rendered.
- * @param resources resources for localized <abbr>GUI</abbr> elements.
+ * @param canvas where the coverage will be rendered.
*/
- StyleController(final CoverageCanvas view, final Resources resources) {
+ StyleController(final CoverageCanvas canvas) {
+ this.canvas = canvas;
setSelected(true);
setIndependent(true);
- selectedProperty().addListener((p,o,n) -> view.setCoverageHidden(!n));
- showTileReads = new ItemController(new
MapItem(resources.getString(Resources.Keys.ShowTileReadEvents)));
- showTileReads.selectedProperty().addListener((p,o,n) ->
view.showTileReads(n));
- showTileReads.setIndependent(true);
- getChildren().add(showTileReads);
+ selectedProperty().addListener((p,o,n) ->
canvas.setCoverageHidden(!n));
}
/**
@@ -68,10 +70,14 @@ final class StyleController extends ItemController {
if (!isTiled) {
children.remove(last);
}
- } else {
- if (isTiled) {
- children.add(showTileReads);
+ } else if (isTiled) {
+ if (showTileReads == null) {
+ final Resources resources =
Resources.forLocale(canvas.getLocale());
+ showTileReads = new ItemController(new
MapItem(resources.getString(Resources.Keys.ShowTileReadEvents)));
+ showTileReads.selectedProperty().addListener((p,o,n) ->
canvas.showTileReads(n));
+ showTileReads.setIndependent(true);
}
+ children.add(showTileReads);
}
}
}
diff --git
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/StyledRenderingData.java
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/StyledRenderingData.java
index 95ecbabc4e..24eff709b8 100644
---
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/StyledRenderingData.java
+++
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/StyledRenderingData.java
@@ -81,14 +81,14 @@ final class StyledRenderingData extends RenderingData {
* This method shall be invoked in a background thread after image
rendering has been completed (because this
* method uses some image computation results).
*
- * @param isolines value of {@link IsolineRenderer#prepare()}, or {@code
null} if none.
+ * @param isolines value of {@link IsolineController#prepare()}, or
{@code null} if none.
* @return result of isolines generation, or {@code null} if there are no
isolines to compute.
* @throws TransformException if an interpolated point cannot be
transformed using the given transform.
*/
- final Future<Isolines[]> generate(final IsolineRenderer.Snapshot[]
isolines) throws TransformException {
+ final Future<Isolines[]> generate(final IsolineController.Snapshot[]
isolines) throws TransformException {
if (isolines == null) return null;
final MathTransform centerToObjective =
getDataToObjective(PixelInCell.CELL_CENTER);
- return IsolineRenderer.generate(isolines, getSourceImage(),
centerToObjective);
+ return IsolineController.generate(isolines, getSourceImage(),
centerToObjective);
}
/**
diff --git
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Resources.java
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Resources.java
index f0224a4976..d7a52b71bd 100644
---
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Resources.java
+++
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Resources.java
@@ -311,6 +311,16 @@ public class Resources extends IndexedResourceBundle {
*/
public static final short NoFeatureTypeInfo = 27;
+ /**
+ * No selected item.
+ */
+ public static final short NoSelectedItem = 78;
+
+ /**
+ * Nothing to configure.
+ */
+ public static final short NothingToConfigure = 79;
+
/**
* Open…
*/
diff --git
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Resources.properties
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Resources.properties
index 616e05df42..3238bad540 100644
---
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Resources.properties
+++
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Resources.properties
@@ -71,6 +71,8 @@ Mercator = Mercator
MainWindow = Main window
NewWindow = New window
NoFeatureTypeInfo = No feature type information.
+NoSelectedItem = No selected item.
+NothingToConfigure = Nothing to configure.
Open = Open\u2026
OpenURL = Open URL\u2026
OpenContainingFolder = Open containing folder
diff --git
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Resources_fr.properties
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Resources_fr.properties
index 5d24f447dd..b4d044e410 100644
---
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Resources_fr.properties
+++
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Resources_fr.properties
@@ -76,6 +76,8 @@ Mercator = Mercator
MainWindow = Fen\u00eatre principale
NewWindow = Nouvelle fen\u00eatre
NoFeatureTypeInfo = Pas d\u2019information sur le type d\u2019entit\u00e9.
+NoSelectedItem = Pas d\u2019item de s\u00e9lectionn\u00e9.
+NothingToConfigure = Rien \u00e0 configurer.
Open = Ouvrir\u2026
OpenURL = Ouvrir un URL\u2026
OpenContainingFolder = Ouvrir le dossier contenant
diff --git
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/style/ItemController.java
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/style/ItemController.java
index 86e14a75ff..734e9d394f 100644
---
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/style/ItemController.java
+++
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/style/ItemController.java
@@ -16,7 +16,12 @@
*/
package org.apache.sis.gui.map.style;
+import javafx.geometry.Pos;
+import javafx.scene.layout.VBox;
+import javafx.scene.layout.Region;
+import javafx.scene.control.Label;
import javafx.scene.control.CheckBoxTreeItem;
+import org.apache.sis.gui.internal.Resources;
/**
@@ -33,18 +38,52 @@ import javafx.scene.control.CheckBoxTreeItem;
* @author Martin Desruisseaux (Geomatys)
*/
public class ItemController extends CheckBoxTreeItem<MapItem> {
+ /**
+ * A default configuration panel which said that there is nothing to
configure.
+ * Created when first needed.
+ */
+ private Region configurationPanel;
+
/**
* Creates an initially empty controller.
+ * The controller is unselected by default.
*/
public ItemController() {
}
/**
* Creates a controller for the given map item.
+ * The controller is unselected by default.
*
* @param item the map item, or {@code null} if none.
*/
public ItemController(final MapItem item) {
super(item);
}
+
+ /**
+ * Returns a panel of JavaFX controls for configuring the map item.
+ * This method should create the panel when first requested, then cache it.
+ * This method will be invoked from the JavaFX thread.
+ *
+ * @return the configuration panel for the map item.
+ */
+ protected Region getConfigurationPanel() {
+ if (configurationPanel == null) {
+ configurationPanel =
createLabel(Resources.Keys.NothingToConfigure);
+ }
+ return configurationPanel;
+ }
+
+ /**
+ * Creates a panel showing a label such a "No selected item".
+ *
+ * @param label one of the {@link Resources} constants.
+ * @return the label to show.
+ */
+ static Region createLabel(final short label) {
+ final var box = new VBox(new Label(Resources.format(label)));
+ box.setAlignment(Pos.CENTER);
+ return box;
+ }
}
diff --git
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/style/MapContextView.java
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/style/MapContextView.java
index 0c3d8d7cef..666c8c5c0a 100644
---
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/style/MapContextView.java
+++
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/style/MapContextView.java
@@ -87,6 +87,11 @@ public class MapContextView extends Widget {
*/
private final SplitPane itemsAndConfiguration;
+ /**
+ * The node to show when no map item is selected.
+ */
+ private final Region noSelection;
+
/**
* Creates an initially empty tree.
*
@@ -96,8 +101,10 @@ public class MapContextView extends Widget {
public MapContextView(final Resources resources) {
items = new TreeView<>();
items.setCellFactory(CellFactory.INSTANCE);
- itemsAndConfiguration = new SplitPane(items);
+ noSelection =
ItemController.createLabel(Resources.Keys.NoSelectedItem);
+ itemsAndConfiguration = new SplitPane(items, noSelection);
itemsAndConfiguration.setOrientation(Orientation.VERTICAL);
+ items.getSelectionModel().selectedItemProperty().addListener((p,o,n)
-> onSelected(n));
}
/**
@@ -119,4 +126,18 @@ public class MapContextView extends Widget {
public void setRootItem(final ItemController root) {
items.setRoot(root);
}
+
+ /**
+ * Invoked when a new map item is selected.
+ * This method shows the configuration panel of the selected item.
+ *
+ * @param item the selected map item, or {@code null} if none.
+ */
+ private void onSelected(final TreeItem<MapItem> item) {
+ Region config = noSelection;
+ if (item instanceof ItemController) {
+ config = ((ItemController) item).getConfigurationPanel();
+ }
+ itemsAndConfiguration.getItems().set(1, config);
+ }
}
diff --git
a/optional/src/org.apache.sis.gui/test/org/apache/sis/gui/controls/ValueColorMapperApp.java
b/optional/src/org.apache.sis.gui/test/org/apache/sis/gui/controls/ValueColorMapperApp.java
index 659a604e82..92df9595f0 100644
---
a/optional/src/org.apache.sis.gui/test/org/apache/sis/gui/controls/ValueColorMapperApp.java
+++
b/optional/src/org.apache.sis.gui/test/org/apache/sis/gui/controls/ValueColorMapperApp.java
@@ -16,6 +16,7 @@
*/
package org.apache.sis.gui.controls;
+import java.util.Locale;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
@@ -23,8 +24,6 @@ import javafx.scene.control.Button;
import javafx.scene.layout.Region;
import javafx.scene.layout.BorderPane;
import javafx.application.Application;
-import org.apache.sis.gui.internal.Resources;
-import org.apache.sis.util.resources.Vocabulary;
/**
@@ -71,9 +70,7 @@ public final class ValueColorMapperApp extends Application {
* Creates a table with arbitrary isolines to show.
*/
private static Region createIsolineTable() {
- final ValueColorMapper handler = new ValueColorMapper(
- Resources.forLocale(null),
- Vocabulary.forLocale(null));
+ final ValueColorMapper handler = new
ValueColorMapper(Locale.getDefault());
handler.getSteps().setAll(
new ValueColorMapper.Step( 10, Color.BLUE),
new ValueColorMapper.Step( 25, Color.GREEN),