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 cad51c79cdcfe95f9be28d5b01a1dab96954a894
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Thu Dec 2 12:40:42 2021 +0100

    Avoid creation of an unused `Accordion` control.
    Remember which title pane was expanded when switching view.
---
 .../apache/sis/gui/coverage/CoverageControls.java  | 21 ++++----
 .../apache/sis/gui/coverage/CoverageExplorer.java  | 13 +++--
 .../org/apache/sis/gui/coverage/GridControls.java  | 15 +++---
 .../apache/sis/gui/coverage/ViewAndControls.java   | 33 +++++++++++-
 .../apache/sis/gui/dataset/ResourceExplorer.java   | 59 +++++++++++++++-------
 5 files changed, 95 insertions(+), 46 deletions(-)

diff --git 
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageControls.java
 
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageControls.java
index 9b829ff..4286fca 100644
--- 
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageControls.java
+++ 
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageControls.java
@@ -17,8 +17,6 @@
 package org.apache.sis.gui.coverage;
 
 import java.util.Locale;
-import javafx.scene.control.Accordion;
-import javafx.scene.control.Control;
 import javafx.scene.control.TitledPane;
 import javafx.scene.layout.BorderPane;
 import javafx.scene.layout.GridPane;
@@ -70,7 +68,7 @@ final class CoverageControls extends ViewAndControls {
     /**
      * The controls for changing {@link #view}.
      */
-    private final Accordion controls;
+    private final TitledPane[] controls;
 
     /**
      * The image together with the status bar.
@@ -148,11 +146,12 @@ final class CoverageControls extends ViewAndControls {
          * Put all sections together and have the first one expanded by 
default.
          * The "Properties" section will be built by `PropertyPaneCreator` 
only if requested.
          */
-        final TitledPane p1 = new 
TitledPane(vocabulary.getString(Vocabulary.Keys.Display),  displayPane);
-        final TitledPane p2 = new 
TitledPane(vocabulary.getString(Vocabulary.Keys.Isolines), isolinesPane);
-        final TitledPane p3 = new 
TitledPane(vocabulary.getString(Vocabulary.Keys.Properties), null);
-        controls = new Accordion(p1, p2, p3);
-        controls.setExpandedPane(p1);
+        controls = new TitledPane[] {
+            new TitledPane(vocabulary.getString(Vocabulary.Keys.Display),  
displayPane),
+            new TitledPane(vocabulary.getString(Vocabulary.Keys.Isolines), 
isolinesPane),
+            new TitledPane(vocabulary.getString(Vocabulary.Keys.Properties), 
null)
+        };
+        final TitledPane delayed = controls[2];     // Control to be built 
only if requested.
         /*
          * Set listeners: changes on `CoverageCanvas` properties are 
propagated to the corresponding
          * `CoverageExplorer` properties. This constructor does not install 
listeners in the opposite
@@ -160,7 +159,7 @@ final class CoverageControls extends ViewAndControls {
          */
         view.resourceProperty.addListener((p,o,n) -> onPropertySet(n, null));
         view.coverageProperty.addListener((p,o,n) -> onPropertySet(null, n));
-        p3.expandedProperty().addListener(new PropertyPaneCreator(view, p3));
+        delayed.expandedProperty().addListener(new PropertyPaneCreator(view, 
delayed));
     }
 
     /**
@@ -213,9 +212,11 @@ final class CoverageControls extends ViewAndControls {
 
     /**
      * Returns the controls for controlling the view of tabular data.
+     * This method does not clone the returned array; do not modify!
      */
     @Override
-    final Control controls() {
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
+    final TitledPane[] controlPanes() {
         return controls;
     }
 }
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 6ddd16a..6a4ad70 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
@@ -25,6 +25,7 @@ import javafx.scene.control.SplitPane;
 import javafx.scene.control.Separator;
 import javafx.scene.control.ToggleGroup;
 import javafx.scene.control.Toggle;
+import javafx.scene.control.TitledPane;
 import javafx.scene.layout.Region;
 import javafx.event.ActionEvent;
 import javafx.beans.property.ObjectProperty;
@@ -259,8 +260,7 @@ public class CoverageExplorer extends Widget {
                 case IMAGE: c = new CoverageControls(this); break;
                 default: throw new AssertionError(type);
             }
-            SplitPane.setResizableWithParent(c.controls(), Boolean.FALSE);
-            SplitPane.setResizableWithParent(c.view(),     Boolean.TRUE);
+            SplitPane.setResizableWithParent(c.view(), Boolean.TRUE);
             views.put(type, c);
             load = true;
         }
@@ -342,17 +342,16 @@ public class CoverageExplorer extends Widget {
     }
 
     /**
-     * Returns the region containing only the controls, without data 
visualization component.
-     * The {@link Region} subclass returned by this method is implementation 
dependent and may
-     * change in any future version.
+     * Returns the panes containing the controls, without data visualization 
component.
+     * The {@link TitledPane} contents are implementation dependent and may 
change in any future version.
      *
      * @param  type  whether to obtain controls for {@link GridView} or {@link 
CoverageCanvas}.
      * @return the controls on specified data view.
      */
-    public final Region getControls(final View type) {
+    public final TitledPane[] getControls(final View type) {
         assert Platform.isFxApplicationThread();
         ArgumentChecks.ensureNonNull("type", type);
-        return getViewAndControls(type, false).controls();
+        return getViewAndControls(type, false).controlPanes().clone();
     }
 
     /**
diff --git 
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridControls.java
 
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridControls.java
index 0c6c628..8300303 100644
--- 
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridControls.java
+++ 
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridControls.java
@@ -18,8 +18,6 @@ package org.apache.sis.gui.coverage;
 
 import javafx.beans.property.DoubleProperty;
 import javafx.collections.ObservableList;
-import javafx.scene.control.Accordion;
-import javafx.scene.control.Control;
 import javafx.scene.control.Slider;
 import javafx.scene.control.TableView;
 import javafx.scene.control.TitledPane;
@@ -52,7 +50,7 @@ final class GridControls extends ViewAndControls {
     /**
      * The controls for changing {@link #view}.
      */
-    private final Accordion controls;
+    private final TitledPane[] controls;
 
     /**
      * The control showing sample dimensions for the current coverage.
@@ -90,13 +88,12 @@ final class GridControls extends ViewAndControls {
                     labelOfGroup(vocabulary, Vocabulary.Keys.Cells, gp, 
false), gp);
         }
         /*
-         * Put all sections together and have the first one expanded by 
default.
+         * All sections put together.
          */
-        controls = new Accordion(
+        controls = new TitledPane[] {
             new TitledPane(vocabulary.getString(Vocabulary.Keys.Display), 
displayPane)
             // TODO: more controls to be added in a future version.
-        );
-        controls.setExpandedPane(controls.getPanes().get(0));
+        };
     }
 
     /**
@@ -150,9 +147,11 @@ final class GridControls extends ViewAndControls {
 
     /**
      * Returns the controls for controlling the view of tabular data.
+     * This method does not clone the returned array; do not modify!
      */
     @Override
-    final Control controls() {
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
+    final TitledPane[] controlPanes() {
         return controls;
     }
 }
diff --git 
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/ViewAndControls.java
 
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/ViewAndControls.java
index 9205b98..935e08f 100644
--- 
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/ViewAndControls.java
+++ 
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/ViewAndControls.java
@@ -20,6 +20,9 @@ import javafx.geometry.Insets;
 import javafx.scene.control.Control;
 import javafx.scene.control.Label;
 import javafx.scene.control.Toggle;
+import javafx.scene.control.TitledPane;
+import javafx.scene.control.Accordion;
+import javafx.scene.control.SplitPane;
 import javafx.scene.layout.Region;
 import javafx.scene.text.Font;
 import javafx.scene.text.FontWeight;
@@ -65,6 +68,15 @@ abstract class ViewAndControls {
     Toggle selector;
 
     /**
+     * The controls put together in an accordion. Built only if requested
+     * (may never be requested if the caller creates its own accordion with 
additional panes,
+     * as {@link org.apache.sis.gui.dataset.ResourceExplorer} does).
+     *
+     * @see #controls()
+     */
+    private Accordion controls;
+
+    /**
      * The widget which contain this view. This is the widget to inform when 
the coverage changed.
      * Subclasses should define the following method:
      *
@@ -136,10 +148,27 @@ abstract class ViewAndControls {
     abstract Region view();
 
     /**
+     * Returns the list of control panels for controlling the view.
+     * They are the components to show on the left (smaller) part of the split 
pane.
+     * Callers will typically put those components in an {@link 
javafx.scene.control.Accordion}.
+     *
+     * @return the controls. This method does not clone the returned array; do 
not modify!
+     */
+    abstract TitledPane[] controlPanes();
+
+    /**
      * Returns the controls for controlling the view.
-     * This is the component to shown on the left (smaller) part of the split 
pane.
+     * This is the component to show on the left (smaller) part of the split 
pane.
      */
-    abstract Control controls();
+    final Accordion controls() {
+        if (controls == null) {
+            final TitledPane[] panes = controlPanes();
+            controls = new Accordion(panes);
+            controls.setExpandedPane(panes[0]);
+            SplitPane.setResizableWithParent(controls, Boolean.FALSE);
+        }
+        return controls;
+    }
 
     /**
      * Sets the view content to the given resource, coverage or image.
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 91668cd..9abe7c8 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
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.gui.dataset;
 
+import java.util.EnumMap;
 import java.util.Objects;
 import java.util.Collection;
 import java.util.logging.Level;
@@ -112,6 +113,20 @@ public class ResourceExplorer extends WindowManager {
     private FeatureTable features;
 
     /**
+     * The type of view (image or table) for the coverage, or {@code null} if 
the coverage is not currently shown.
+     * We save this information because we need to know what was the previous 
view when a new view is selected.
+     *
+     * @see #getCoverageView()
+     */
+    private CoverageExplorer.View coverageView;
+
+    /**
+     * The pane which is expanded for a given type of view.
+     * This is used for restoring the expanded tab when user switch tab.
+     */
+    private final EnumMap<CoverageExplorer.View, TitledPane> expandedPane;
+
+    /**
      * Controls for the image or tabular data. The first titled pane on top 
contains the
      * {@link #resources} tree and all other panes below are 
resource-dependent controls.
      *
@@ -166,6 +181,7 @@ public class ResourceExplorer extends WindowManager {
         final TitledPane resourcesPane = new 
TitledPane(vocabulary.getString(Vocabulary.Keys.Resources), resources);
         controls = new Accordion(resourcesPane);
         controls.setExpandedPane(resourcesPane);
+        expandedPane = new EnumMap<>(CoverageExplorer.View.class);
         /*
          * "Summary" tab showing a summary of resource metadata.
          */
@@ -417,6 +433,7 @@ public class ResourceExplorer extends WindowManager {
      * Returns the enumeration value that describe the kind of content to show 
in {@link CoverageExplorer}.
      * The type depends on which tab is visible. If no coverage data tab is 
visible, then returns null.
      *
+     * @see #coverageView
      * @see #dataShown
      */
     private CoverageExplorer.View getCoverageView() {
@@ -436,14 +453,14 @@ public class ResourceExplorer extends WindowManager {
      * @see #updateDataTabWithDefault(Resource)
      */
     private boolean updateDataTab(final Resource resource) {
-        Region        image = null;
-        Region        table = null;
-        FeatureSet    data  = null;
-        ImageRequest  grid  = null;
-        Region controlPanel = null;
-        CoverageExplorer.View type = null;
+        Region       image  = null;
+        Region       table  = null;
+        FeatureSet   data   = null;
+        ImageRequest grid   = null;
+        TitledPane[] cpanes = null;
+        final CoverageExplorer.View type = getCoverageView();
         if (resource instanceof GridCoverageResource) {
-            type = getCoverageView();       // A null value here would be a 
violation of method contract.
+            // A null `type` value here would be a violation of method 
contract.
             if (coverage == null) {
                 coverage = new CoverageExplorer(type);
             } else {
@@ -455,7 +472,7 @@ public class ResourceExplorer extends WindowManager {
                 case TABLE: table = view; break;
             }
             grid = new ImageRequest((GridCoverageResource) resource, null, 
null);
-            controlPanel = coverage.getControls(type);
+            cpanes = coverage.getControls(type);
         } else if (resource instanceof FeatureSet) {
             data = (FeatureSet) resource;
             if (features == null) {
@@ -474,23 +491,27 @@ public class ResourceExplorer extends WindowManager {
         final boolean isEmpty = (image == null & table == null);
         setNewWindowDisabled(isEmpty);
         /*
-         * Adds or removes controls for the selected view.
+         * Add or remove controls for the selected view.
+         * Information about the expanded pane needs to be saved before to 
remove controls,
+         * and restored (for a potentially different view) after new controls 
have been added.
          */
+        TitledPane expanded = controls.getExpandedPane();
+        if (expanded != null && coverageView != null) {
+            expandedPane.put(coverageView, expanded);
+        }
         final ObservableList<TitledPane> items = controls.getPanes();
         final int size = items.size();
         items.remove(1, size);
-        if (controlPanel != null) {
-            if (controlPanel instanceof Accordion) {
-                /*
-                 * It is okay to use the same controls in another JavaFX node 
because the `controlPanel` will
-                 * never be shown (we will only show its components). The 
children are in only one scene graph.
-                 */
-                items.addAll(((Accordion) controlPanel).getPanes());
-            } else {
-                items.add(new TitledPane(Vocabulary.getResources(getLocale())
-                        .getString(Vocabulary.Keys.Controls), controlPanel));
+        if (cpanes != null) {
+            items.addAll(cpanes);
+            if (!items.contains(expanded)) {
+                expanded = expandedPane.get(type);
+                if (expanded != null) {
+                    controls.setExpandedPane(expanded);
+                }
             }
         }
+        coverageView = type;
         return !isEmpty | (resource == null);
     }
 

Reply via email to