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 145b4a415a2e825614d3026eb8aee9ddfe36a080
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Wed Mar 13 13:10:59 2024 +0100

    Add javafx Glyph and FontGIS dependency (work by Johann Sorel).
---
 .gitignore                                         |   3 +
 optional/build.gradle.kts                          |  29 ++
 .../main/org/apache/sis/gui/DataViewer.java        |   7 +-
 .../apache/sis/gui/coverage/CoverageExplorer.java  |  25 +-
 .../org/apache/sis/gui/coverage/package-info.java  |   2 +-
 .../org/apache/sis/gui/dataset/WindowManager.java  |   7 +-
 .../org/apache/sis/gui/dataset/package-info.java   |   2 +-
 .../main/org/apache/sis/gui/internal/FontGIS.java  | 517 +++++++++++++++++++++
 .../main/org/apache/sis/gui/internal/Styles.java   |   7 -
 .../org/apache/sis/gui/internal/ToolbarButton.java |   7 +-
 .../sis/gui/controls/ValueColorMapperApp.java      |   3 +-
 11 files changed, 581 insertions(+), 28 deletions(-)

diff --git a/.gitignore b/.gitignore
index 2e320d0e3d..ef94da589c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,9 @@ build/
 *.tmp
 *.log
 
+# Specific to this project
+optional/cache/
+
 # Legacy systems (should not be used anymore)
 target/
 .svn/
diff --git a/optional/build.gradle.kts b/optional/build.gradle.kts
index 3f3e90f4eb..1a7be341ac 100644
--- a/optional/build.gradle.kts
+++ b/optional/build.gradle.kts
@@ -14,6 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import java.nio.file.Files
+
 group = "org.apache.sis"
 // The version is specified in `gradle.properties`.
 
@@ -129,6 +131,32 @@ fun patchForTests(args : MutableList<String>) {
     addExport(args, "org.apache.sis.util", "org.apache.sis.test", 
"org.apache.sis.gui")
 }
 
+/*
+ * Download the FontGIS glyphs if not already present — 
https://viglino.github.io/font-gis/
+ * The license is OFL-1.1 (SIL Open Font License), classified by ASF as 
Category B:
+ * the file may be included in binary-only form in convenience binaries,
+ * but shall not be included in source releases.
+ */
+fun downloadFontGIS() {
+    val targetFile = File(file("build"), 
"classes/java/main/org.apache.sis.gui/org/apache/sis/gui/internal/font-gis.ttf")
+    if (!targetFile.exists()) {
+        val archiveFolder = File(file("cache"), "fontgis")
+        val archiveFile   = File(archiveFolder, "fontgis.tgz")
+        val archiveEntry  = File(archiveFolder, "package/fonts/font-gis.ttf")
+        val archiveURL    = 
"https://registry.npmjs.org/font-gis/-/font-gis-1.0.5.tgz";
+        if (!archiveEntry.exists()) {
+            if (!archiveFile.exists()) {
+                archiveFolder.mkdirs()
+                println("Downloading " + archiveURL)
+                ant.invokeMethod("get", mapOf("src" to archiveURL, "dest" to 
archiveFile))
+            }
+            ant.invokeMethod("untar", mapOf("src"  to archiveFile, "dest" to 
archiveFolder, "compression" to "gzip"))
+        }
+        targetFile.getParentFile().mkdirs()
+        Files.createLink(targetFile.toPath(), archiveEntry.toPath())
+    }
+}
+
 /*
  * Discover and execute JUnit-based tests.
  */
@@ -153,6 +181,7 @@ tasks.test {
  * Other attributes are hard-coded in `../buildSrc`.
  */
 tasks.jar {
+    downloadFontGIS();
     manifest {
         attributes["Main-Class"] = "org.apache.sis.gui.DataViewer"
     }
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/DataViewer.java 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/DataViewer.java
index a575166f6f..8fd1d72eec 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/DataViewer.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/DataViewer.java
@@ -17,6 +17,7 @@
 package org.apache.sis.gui;
 
 import java.io.File;
+import java.net.URL;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
@@ -48,7 +49,6 @@ import org.apache.sis.gui.internal.ExceptionReporter;
 import org.apache.sis.gui.internal.LogHandler;
 import org.apache.sis.gui.internal.Resources;
 import org.apache.sis.gui.internal.RecentChoices;
-import org.apache.sis.gui.internal.Styles;
 import org.apache.sis.storage.DataStoreProvider;
 import org.apache.sis.storage.DataStores;
 import org.apache.sis.storage.DataStore;
@@ -190,7 +190,10 @@ public class DataViewer extends Application {
         pane.setTop(menus);
         pane.setCenter(content.getView());
         final Scene scene = new Scene(pane);
-        scene.getStylesheets().add(Styles.STYLESHEET);
+        final URL css = DataViewer.class.getResource("pseudo-classes.css");
+        if (css != null) {
+            scene.getStylesheets().add(css.toExternalForm());
+        }
         final Rectangle2D bounds = Screen.getPrimary().getVisualBounds();
         window.setTitle("Apache Spatial Information System");
         window.getIcons().addAll(new 
Image(DataViewer.class.getResourceAsStream("SIS_64px.png")),
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java
index 0bb555922f..8e6f1b9e4b 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java
@@ -37,6 +37,7 @@ import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.GridCoverageResource;
 import org.apache.sis.coverage.grid.GridCoverage;
 import org.apache.sis.gui.Widget;
+import org.apache.sis.gui.internal.FontGIS;
 import org.apache.sis.gui.internal.DataStoreOpener;
 import org.apache.sis.gui.internal.Resources;
 import org.apache.sis.gui.internal.ToolbarButton;
@@ -71,7 +72,7 @@ import org.apache.sis.gui.map.StatusBar;
  * implementation may generalize to {@link org.opengis.coverage.Coverage} 
instances.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.4
+ * @version 1.5
  *
  * @see CoverageCanvas
  * @see GridView
@@ -92,12 +93,12 @@ public class CoverageExplorer extends Widget {
         /**
          * Shows the coverage visual as an image. This view uses {@link 
CoverageCanvas}.
          */
-        IMAGE("\uD83D\uDDFA\uFE0F", Resources.Keys.TabularData),    // 🗺 — 
World map.
+        IMAGE(FontGIS.Code.WORLD_MAP_ALT, "\uD83D\uDDFA\uFE0F", 
Resources.Keys.TabularData),    // 🗺 — World map.
 
         /**
          * Shows the coverage numerical value in a table. This view uses 
{@link GridView}.
          */
-        TABLE("\uD83D\uDD22\uFE0F", Resources.Keys.Visualize);      // 🔢 — 
Input symbol for numbers.
+        TABLE(FontGIS.Code.GRID, "\uD83D\uDD22\uFE0F", 
Resources.Keys.Visualize);   // 🔢 — Input symbol for numbers.
 
         /**
          * Number of enumeration values.
@@ -105,9 +106,14 @@ public class CoverageExplorer extends Widget {
         static final int COUNT = 2;
 
         /**
-         * The Unicode characters to use as icon.
+         * The Unicode character to use as icon, as a {@link FontGIS} code.
          */
-        final String icon;
+        final char icon;
+
+        /**
+         * The fallback text if the icon cannot be shown.
+         */
+        final String fallback;
 
         /**
          * Key from {@link Resources} bundle for the localized text to use as 
tooltip.
@@ -117,9 +123,10 @@ public class CoverageExplorer extends Widget {
         /**
          * Creates a new enumeration value.
          */
-        private View(final String icon, short tooltip) {
-            this.icon = icon;
-            this.tooltip = tooltip;
+        private View(final char icon, final String fallback, short tooltip) {
+            this.icon     = icon;
+            this.fallback = fallback;
+            this.tooltip  = tooltip;
         }
     }
 
@@ -360,7 +367,7 @@ public class CoverageExplorer extends Widget {
             final Resources localized = Resources.forLocale(getLocale());
             buttons[0] = new Separator();
             for (final View type : View.values()) {
-                buttons[1 + type.ordinal()] = new 
Selector(type).createButton(group, type.icon, localized, type.tooltip);
+                buttons[1 + type.ordinal()] = new 
Selector(type).createButton(group, type.icon, type.fallback, localized, 
type.tooltip);
             }
             final View type = getViewType();
             final ViewAndControls c = getViewAndControls(type, false);
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/package-info.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/package-info.java
index 871ee06932..253e1efc8a 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/package-info.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/package-info.java
@@ -19,7 +19,7 @@
  * Widgets showing {@link org.apache.sis.coverage.grid.GridCoverage} images or 
sample values.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.4
+ * @version 1.5
  * @since   1.1
  */
 package org.apache.sis.gui.coverage;
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/dataset/WindowManager.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/dataset/WindowManager.java
index 9cc76a9f62..7889e4199c 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/dataset/WindowManager.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/dataset/WindowManager.java
@@ -31,6 +31,7 @@ import javafx.scene.text.Font;
 import javafx.geometry.Rectangle2D;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
+import org.apache.sis.gui.internal.FontGIS;
 import org.apache.sis.gui.internal.Resources;
 import org.apache.sis.gui.internal.ToolbarButton;
 
@@ -44,7 +45,7 @@ import org.apache.sis.gui.internal.ToolbarButton;
  * or synchronized between windows, at user's choice.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.3
+ * @version 1.5
  * @since   1.3
  */
 public final class WindowManager {          // Not designed for subclassing.
@@ -94,8 +95,8 @@ public final class WindowManager {          // Not designed 
for subclassing.
      */
     final Stage newWindow(final Region content) {
         final Stage     stage      = new Stage();
-        final Button    mainWindow = new Button("\u2302\uFE0F");        // ⌂ — 
house
-        final Button    fullScreen = new Button("\u21F1\uFE0F");        // ⇱ — 
North West Arrow to Corner
+        final Button    mainWindow = FontGIS.button((char) 0,                 
"\uD83D\uDDD4");   // 🗔 — Desktop Window
+        final Button    fullScreen = FontGIS.button(FontGIS.Code.FULL_SCREEN, 
"\u21F1\uFE0F");   // ⇱ — North West Arrow to Corner
         final Resources localized  = Resources.forLocale(locale);
         mainWindow.setTooltip(new 
Tooltip(localized.getString(Resources.Keys.MainWindow)));
         fullScreen.setTooltip(new 
Tooltip(localized.getString(Resources.Keys.FullScreen)));
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/dataset/package-info.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/dataset/package-info.java
index 81a21094de..a8ed392e25 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/dataset/package-info.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/dataset/package-info.java
@@ -24,7 +24,7 @@
  * @author  Smaniotto Enzo (GSoC)
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.4
+ * @version 1.5
  * @since   1.1
  */
 package org.apache.sis.gui.dataset;
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/FontGIS.java 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/FontGIS.java
new file mode 100644
index 0000000000..1403029ebf
--- /dev/null
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/FontGIS.java
@@ -0,0 +1,517 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.gui.internal;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.logging.Logger;
+import javafx.scene.text.Font;
+import javafx.scene.control.Button;
+import javafx.scene.control.Labeled;
+import javafx.scene.control.ToggleButton;
+import org.apache.sis.util.Static;
+import org.apache.sis.system.Modules;
+import org.apache.sis.util.logging.Logging;
+
+
+/**
+ * Creates labels with an icon rendered using Font-GIS.
+ * Font-GIS is a set of SVG icons and font to use with GIS and spatial 
analysis tools.
+ * Those font are not included in source code and are not managed as a Maven 
dependency neither.
+ * They are downloaded from the <a 
href="https://www.npmjs.com/package/font-gis";>NPM package</a>
+ * by the {@code build.gradle.kts} script where the {@code jar} task is 
executed.
+ *
+ * @author Johann Sorel (Geomatys)
+ * @author Martin Desruisseaux (Geomatys)
+ *
+ * @see <a href="https://viglino.github.io/font-gis/";>Font-GIS project</a>
+ */
+public final class FontGIS extends Static {
+    /**
+     * The font, or {@code null} if not found or if an error occurred.
+     * This is loaded at class-initialization time.
+     */
+    private static final Font FONT;
+    static {
+        Font font = null;
+        final String filename = "font-gis.ttf";
+        try {
+            InputStream in = Code.class.getResourceAsStream(filename);
+            if (in != null) try (in) {
+                font = Font.loadFont(in, 0);
+            } else {
+                // Intentionally caught immediately below.
+                throw new FileNotFoundException(filename);
+            }
+        } catch (IOException e) {
+            Logging.unexpectedException(Logger.getLogger(Modules.APPLICATION), 
FontGIS.class, "<cinit>", e);
+        }
+        FONT = font;
+    }
+
+    /**
+     * Default font size in points. The value was choosen empirically.
+     */
+    private static final int DEFAULT_SIZE = 18;
+
+    /**
+     * Default horizontal and vertical padding, in points. The value was 
chosen empirically.
+     */
+    private static final int DEFAULT_PADDING = 3;
+
+    /**
+     * The default fallback for a glyph than cannot be rendered.
+     * Current implementation uses the dotted square.
+     */
+    private static final String FALLBACK = "\u2B1A";
+
+    /**
+     * Do not allow instantiation of this class.
+     */
+    private FontGIS() {
+    }
+
+    /**
+     * Creates a button with a Font-GIS glyph for the given code.
+     * The code should be one of the {@link Code} constants.
+     * The font size and the padding are set to empirical values.
+     *
+     * @param  code  one of the {@link Code} constants, or 0 for using {@code 
text} with the default font.
+     * @param  text  a fallback to show if Font-GIS couldn't be loaded, or 
{@code null} for a default fallback.
+     * @return the button to use as a scaled glyph for the given code.
+     */
+    public static Button button(final char code, final String text) {
+        final var glyph = new Button();
+        setGlyph(glyph, code, text, DEFAULT_SIZE, DEFAULT_PADDING);
+        return glyph;
+    }
+
+    /**
+     * Creates a taggle button with a Font-GIS glyph for the given code.
+     * The code should be one of the {@link Code} constants.
+     * The font size and the padding are set to empirical values.
+     *
+     * @param  code  one of the {@link Code} constants, or 0 for using {@code 
text} with the default font.
+     * @param  text  a fallback to show if Font-GIS couldn't be loaded, or 
{@code null} for a default fallback.
+     * @return the button to use as a scaled glyph for the given code.
+     */
+    public static ToggleButton toggle(final char code, final String text) {
+        final var glyph = new ToggleButton();
+        setGlyph(glyph, code, text, DEFAULT_SIZE, DEFAULT_PADDING);
+        return glyph;
+    }
+
+    /**
+     * Sets the font, the padding and the text of the given button or label 
using CSS styles.
+     * This method is used because {@link Labeled#setFont(Font)} seems to have 
no effect on buttons
+     * (tested on OpenJFX 20.0.1 and 21.0.2).
+     *
+     * @param  ctrl  the label or button on which to set the text and font.
+     * @param  code  one of the {@link Code} constants, or 0 for using {@code 
text} with the default font.
+     * @param  text  a fallback to show if Font-GIS couldn't be loaded, or 
{@code null} for a default fallback.
+     * @param  size  the font size in points, or -1 for the default size.
+     * @param  pads  horizontal and vertical padding in points, or -1 for the 
default padding.
+     */
+    public static void setGlyph(final Labeled ctrl, final char code, String 
text, final int size, final int pads) {
+        /*
+         * Note 1: in our tests, "-fx-font" didn't worked. We have to use 
"-fx-font-family".
+         * Note 2: setting different values for horizontal and vertical 
padding does not seem to work.
+         */
+        final var style = new StringBuilder();
+        if (code != 0 && FONT != null) {
+            
style.append("-fx-font-family:'").append(FONT.getFamily()).append("';");
+            text = new String(new char[] {code});
+        } else if (text == null) {
+            text = FALLBACK;
+        }
+        if (size >= 0) {
+            style.append(" -fx-font-size:").append(size).append("pt;");
+        }
+        if (pads >= 0) {
+            style.append(" -fx-padding:").append(pads).append("pt;");
+        }
+        ctrl.setStyle(style.toString());
+        ctrl.setText(text);
+    }
+
+    /**
+     * Unicode values for Font-GIS icons.
+     * See the <a href="https://viglino.github.io/font-gis/";>Font-GIS 
project</a> for browsing the icons.
+     *
+     * <h2>Implementation note</h2>
+     * Those constants are defined in a separated class for avoiding to load 
hundreds of field names in memory.
+     * Because all field values are constants of primitive type, the compiler 
should inline them in the caller code.
+     */
+    public static final class Code extends Static {
+        /**
+         * Do not allow instantiation of this class.
+         */
+        private Code() {
+        }
+
+        /**
+         * Unicode value of a Font-GIS icon.
+         */
+        public static final char
+            NORTH_ARROW         = '\uEA8B',
+            NORTH_ARROW_N       = '\uEA8C',
+            COMPASS             = '\uEA90',
+            COMPASS_NEEDLE      = '\uEA91',
+            COMPASS_ROSE        = '\uEA92',
+            COMPASS_ROSE_N      = '\uEA93',
+            COMPASS_ALT         = '\uEB06',
+            COMPASS_ALT_O       = '\uEB07',
+            ARROW_O             = '\uEA3A',
+            ARROW               = '\uEA3B',
+            MODIFY_LINE         = '\uEA3C',
+            MODIFY_POLY         = '\uEA3D',
+            MODIFY_POLY_O       = '\uEA40',
+            COPY_POINT          = '\uEA4F',
+            COPY_LINE           = '\uEA50',
+            COPY_POLY           = '\uEA51',
+            BUFFER              = '\uEA6E',
+            DIFFERENCE          = '\uEA6F',
+            INTERSECTION        = '\uEA70',
+            UNION               = '\uEA71',
+            SYM_DIFFERENCE      = '\uEA72',
+            MOVE                = '\uEA73',
+            MOVE_ALT            = '\uEA74',
+            OFFSET              = '\uEA75',
+            SNAP                = '\uEA76',
+            SPLIT               = '\uEA77',
+            SPLIT_LINE          = '\uEA78',
+            SPLIT_POLYGON       = '\uEA79',
+            CONVEX_HULL         = '\uEAA8',
+            SELECT_EXTENT       = '\uEAAD',
+            SNAP_ORTHO          = '\uEAAE',
+            COLOR               = '\uEAAF',
+            ROTATE              = '\uEAE3',
+            FLIP_H              = '\uEAE4',
+            FLIP_V              = '\uEAE5',
+            SIMPLIFY            = '\uEAE6',
+            PROJ_POINT          = '\uEAE7',
+            SCALE_POLY          = '\uEAE8',
+            SKELETONIZE         = '\uEB17',
+            DILATATION          = '\uEB18',
+            EROSION             = '\uEB19',
+            TRANSLATE           = '\uEB26',
+            TRANSLATE_X         = '\uEB27',
+            TRANSLATE_Y         = '\uEB28',
+            GPX_FILE            = '\uEA99',
+            GEOJSON_FILE        = '\uEA9A',
+            KML_FILE            = '\uEA9B',
+            WMS                 = '\uEA9C',
+            WMTS                = '\uEA9D',
+            WFS                 = '\uEA9E',
+            WFS_T               = '\uEA9F',
+            MVT                 = '\uEAA0',
+            XYZ                 = '\uEAA1',
+            SHAPE_FILE          = '\uEAA2',
+            ESRI_JSON_FILE      = '\uEAA3',
+            TOPOJSON_FILE       = '\uEAA4',
+            FOLDER_MAP          = '\uEB2F',
+            WORLD_FOLDER_O      = '\uEB30',
+            WORLD_FOLDER        = '\uEB31',
+            FOLDER_GLOBE        = '\uEB32',
+            FOLDER_GLOBE_O      = '\uEB33',
+            FOLDER_MAPS         = '\uEB34',
+            FOLDER_POI          = '\uEB35',
+            FOLDER_POI_O        = '\uEB36',
+            FOLDER_POIS         = '\uEB37',
+            EARTH_NET           = '\uEB38',
+            EARTH_NET_O         = '\uEB39',
+            WCS                 = '\uEB59',
+            POINT               = '\uEA01',
+            POLYLINE_PT         = '\uEA02',
+            POLYGON_PT          = '\uEA03',
+            POLYGON_HOLE_PT     = '\uEA04',
+            RECTANGLE_PT        = '\uEA05',
+            SQUARE_PT           = '\uEA06',
+            CIRCLE_O            = '\uEA07',
+            POLYLINE            = '\uEA09',
+            POLYGON_O           = '\uEA0A',
+            POLYGON_HOLE_O      = '\uEA0B',
+            RECTANGLE_O         = '\uEA0C',
+            SQUARE_O            = '\uEA0D',
+            POLYGON_HOLE        = '\uEA0E',
+            POLYGON             = '\uEA0F',
+            RECTANGLE           = '\uEA10',
+            SQUARE              = '\uEA11',
+            CIRCLE              = '\uEA12',
+            MULTIPOINT          = '\uEA52',
+            BBOX_ALT            = '\uEAA9',
+            EXTENT_ALT          = '\uEAAA',
+            BBOX                = '\uEAAB',
+            EXTENT              = '\uEAAC',
+            MAP_EXTENT          = '\uEAB0',
+            REGULAR_SHAPE_PT    = '\uEAEB',
+            REGULAR_SHAPE_O     = '\uEAEC',
+            REGULAR_SHAPE       = '\uEAED',
+            LAYER               = '\uEA41',
+            LAYER_O             = '\uEA42',
+            LAYERS              = '\uEA43',
+            LAYERS_O            = '\uEA44',
+            LAYER_UP            = '\uEA45',
+            LAYER_DOWN          = '\uEA46',
+            LAYER_ALT           = '\uEA47',
+            LAYER_ALT_O         = '\uEA48',
+            LAYER_STACK         = '\uEA49',
+            LAYER_STACK_O       = '\uEA4A',
+            LAYER_ADD           = '\uEA4B',
+            LAYER_ADD_O         = '\uEA4C',
+            LAYER_RM            = '\uEA4D',
+            LAYER_RM_O          = '\uEA4E',
+            LAYER_POI           = '\uEA6A',
+            LAYER_DOWNLOAD      = '\uEA97',
+            LAYER_UPLOAD        = '\uEA98',
+            LAYER_ROAD          = '\uEAF0',
+            LAYER_HYDRO         = '\uEAF1',
+            LAYER_LANDCOVER     = '\uEAF2',
+            LAYER_CONTOUR       = '\uEAF3',
+            LAYER_STAT          = '\uEAF4',
+            LAYER_STAT_ALT      = '\uEB29',
+            LAYER_EDIT          = '\uEB2D',
+            LAYER_ALT_EDIT      = '\uEB2E',
+            LAYER_HEIGHT        = '\uEB41',
+            LAYER_2_ADD_O       = '\uEB46',
+            LAYER_2_RM_O        = '\uEB47',
+            LAYER_ALT_ADD_O     = '\uEB48',
+            LAYER_ALT_RM_O      = '\uEB49',
+            LAYER_ALT_X_O       = '\uEB4A',
+            LAYERS_POI          = '\uEB4F',
+            LAYER_ALT_POI       = '\uEB50',
+            EARTH               = '\uEA22',
+            EARTH_EURO_AFRICA   = '\uEA23',
+            EARTH_ATLANTIC      = '\uEA24',
+            EARTH_AMERICA       = '\uEA25',
+            EARTH_PACIFIC       = '\uEA26',
+            EARTH_AUSTRALIA     = '\uEA27',
+            EARTH_ASIA          = '\uEA28',
+            EARTH_NORTH         = '\uEA29',
+            EARTH_SOUTH         = '\uEA2A',
+            EARTH_O             = '\uEA2B',
+            EARTH_EURO_AFRICA_O = '\uEA2C',
+            EARTH_ATLANTIC_O    = '\uEA2D',
+            EARTH_AMERICA_O     = '\uEA2E',
+            EARTH_PACIFIC_O     = '\uEA2F',
+            EARTH_AUSTRALIA_O   = '\uEA30',
+            EARTH_ASIA_O        = '\uEA31',
+            EARTH_NORTH_O       = '\uEA32',
+            EARTH_SOUTH_O       = '\uEA33',
+            GLOBE               = '\uEA36',
+            GLOBE_O             = '\uEA37',
+            GLOBE_ALT           = '\uEA38',
+            GLOBE_ALT_O         = '\uEA39',
+            GLOBE_POI           = '\uEA82',
+            NETWORK             = '\uEABB',
+            NETWORK_O           = '\uEABC',
+            TAG                 = '\uEAC1',
+            TAG_O               = '\uEAC2',
+            TAGS                = '\uEAC3',
+            TAGS_O              = '\uEAC4',
+            EARTH_GEAR          = '\uEAD5',
+            GLOBE_EARTH         = '\uEAF8',
+            GLOBE_EARTH_ALT     = '\uEAF9',
+            GLOBE_FAVORITE      = '\uEAFB',
+            GLOBE_OPTIONS       = '\uEAFC',
+            GLOBE_SHARE         = '\uEAFD',
+            GLOBE_STAR          = '\uEAFE',
+            GLOBE_SMILEY        = '\uEAFF',
+            GLOBE_USER          = '\uEB0C',
+            GLOBE_USERS         = '\uEB0D',
+            GLOBE_SHIELD        = '\uEB0E',
+            EARTH_NETWORK       = '\uEB0F',
+            EARTH_NETWORK_O     = '\uEB10',
+            GLOBE_GEAR          = '\uEB11',
+            MAP                 = '\uEA53',
+            MAP_O               = '\uEA54',
+            MAP_POI             = '\uEA55',
+            WORLD_MAP_ALT       = '\uEA56',
+            MAP_ROUTE           = '\uEA57',
+            ROAD_MAP            = '\uEA58',
+            CADASTRE_MAP        = '\uEA59',
+            LANDCOVER_MAP       = '\uEA5A',
+            BUS_MAP             = '\uEA5B',
+            CONTOUR_MAP         = '\uEA5C',
+            HYDRO_MAP           = '\uEA5D',
+            WORLD_MAP           = '\uEA68',
+            PIRATE_MAP          = '\uEA6B',
+            STORY_MAP           = '\uEA6D',
+            MAP_BOOK            = '\uEA7A',
+            MAP_LEGEND          = '\uEA85',
+            MAP_LEGEND_O        = '\uEA86',
+            MAP_OPTIONS         = '\uEA94',
+            MAP_OPTIONS_ALT     = '\uEA95',
+            MAP_PRINT           = '\uEA96',
+            WORLD_MAP_ALT_O     = '\uEAB1',
+            FLOW_MAP            = '\uEAB2',
+            MAP_STAT            = '\uEAB3',
+            STATISTIC_MAP       = '\uEAB4',
+            VORONOI_MAP         = '\uEAB7',
+            TRIANGLE_MAP        = '\uEAB8',
+            PHONE_MAP           = '\uEAB9',
+            HEX_MAP             = '\uEABA',
+            MAP_BOOKMARK        = '\uEABD',
+            MAP_TAG             = '\uEABF',
+            MAP_TAGS            = '\uEAC0',
+            COMPARE_MAP         = '\uEAD8',
+            SWIPE_MAP_V         = '\uEAD9',
+            SWIPE_MAP_H         = '\uEADA',
+            MAGNIFY_MAP         = '\uEADB',
+            MAP_SHARE           = '\uEAE0',
+            MAP_SEND            = '\uEAE1',
+            MAP_SHARE_ALT       = '\uEAE2',
+            MAP_ADD             = '\uEAE9',
+            MAP_RM              = '\uEAEA',
+            MAP_TIME            = '\uEAEE',
+            TIME_MAP            = '\uEAEF',
+            MAP_PLAY            = '\uEAF5',
+            MAP_STAR            = '\uEAF6',
+            MAP_FAVORITE        = '\uEAF7',
+            MAP_SMILEY          = '\uEB00',
+            MAP_CONTROL         = '\uEB02',
+            MAP_LOCK            = '\uEB04',
+            MAP_UNLOCK          = '\uEB05',
+            WEATHER_MAP         = '\uEB0B',
+            STORY_MAP_O         = '\uEB2A',
+            STORY_MAPS          = '\uEB2B',
+            MAP_EDIT            = '\uEB2C',
+            HEIGHT_MAP          = '\uEB40',
+            MAP_USER            = '\uEB4B',
+            MAP_USERS           = '\uEB4C',
+            MEASURE             = '\uEA08',
+            MEASURE_LINE        = '\uEA13',
+            MEASURE_AREA        = '\uEA14',
+            MEASURE_AREA_ALT    = '\uEA15',
+            SCALE               = '\uEB01',
+            AZIMUTH             = '\uEB53',
+            HELP_LARROW         = '\uEA3E',
+            HELP_RARROW         = '\uEA3F',
+            HOME                = '\uEB14',
+            SATELLITE           = '\uEB3A',
+            SATELLITE_EARTH     = '\uEB3B',
+            DRONE               = '\uEB3F',
+            POI                 = '\uEA16',
+            POI_O               = '\uEA17',
+            POI_ALT             = '\uEA18',
+            POI_ALT_O           = '\uEA19',
+            PIN                 = '\uEA1A',
+            PUSHPIN             = '\uEA1B',
+            POIS                = '\uEA1C',
+            POIS_O              = '\uEA1D',
+            POI_FAVORITE        = '\uEA1E',
+            POI_FAVORITE_O      = '\uEA1F',
+            POI_HOME            = '\uEA20',
+            POI_HOME_O          = '\uEA21',
+            POI_EARTH           = '\uEA34',
+            PIN_EARTH           = '\uEA35',
+            PIRATE_POI          = '\uEA6C',
+            LOCATION_POI        = '\uEA83',
+            LOCATION_POI_O      = '\uEA84',
+            BOOKMARK_POI        = '\uEABE',
+            BOOKMARK_POI_B      = '\uEACF',
+            POI_MAP             = '\uEAD6',
+            POI_MAP_O           = '\uEAD7',
+            LOCATION_MAN        = '\uEB15',
+            LOCATION_MAN_ALT    = '\uEB16',
+            POI_INFO            = '\uEB1C',
+            POI_INFO_O          = '\uEB1D',
+            POSITION            = '\uEB22',
+            POSITION_O          = '\uEB23',
+            POSITION_MAN        = '\uEB24',
+            POI_SLASH           = '\uEB4D',
+            POI_SLASH_O         = '\uEB4E',
+            ROUTE               = '\uEA7B',
+            ROUTE_START         = '\uEA7C',
+            ROUTE_END           = '\uEA7D',
+            CAR                 = '\uEA7E',
+            BICYCLE             = '\uEA7F',
+            PEDESTRIAN          = '\uEA80',
+            HIKER               = '\uEA81',
+            LOCATION_ARROW      = '\uEA87',
+            LOCATION_ARROW_O    = '\uEA88',
+            LOCATION            = '\uEA89',
+            LOCATION_ON         = '\uEA8A',
+            DIRECT              = '\uEA8D',
+            REVERS              = '\uEA8E',
+            TIMER               = '\uEA8F',
+            SIGNPOST            = '\uEAB5',
+            DIRECTION           = '\uEAB6',
+            FLAG                = '\uEAC5',
+            FLAG_O              = '\uEAC6',
+            FLAG_START          = '\uEAC7',
+            FLAG_START_O        = '\uEAC8',
+            FLAG_FINISH         = '\uEAC9',
+            FLAG_B              = '\uEACA',
+            FLAB_B_O            = '\uEACB',
+            FLAG_START_B        = '\uEACC',
+            FLAG_START_B_O      = '\uEACD',
+            FLAG_FINISH_B_O     = '\uEACE',
+            START               = '\uEAD0',
+            START_O             = '\uEAD1',
+            STEP                = '\uEAD2',
+            STEP_O              = '\uEAD3',
+            FINISH              = '\uEAD4',
+            DIRECTIONS          = '\uEB03',
+            PHONE_ROUTE         = '\uEB08',
+            PHONE_ROUTE_ALT     = '\uEB09',
+            PHONE_ROUTE_ALT_R   = '\uEB0A',
+            MAP_SEARCH          = '\uEA5E',
+            SEARCH_MAP          = '\uEA5F',
+            SEARCH_POI          = '\uEA60',
+            SEARCH_GLOBE        = '\uEA61',
+            SEARCH_HOME         = '\uEA62',
+            SEARCH_ADDRESS      = '\uEA63',
+            SEARCH_ATTRIBTUES   = '\uEA64',
+            SEARCH_PROPERTIE    = '\uEA65',
+            SEARCH_FEATURE      = '\uEA66',
+            SEARCH_LAYER        = '\uEA67',
+            SEARCH_COUNTRY      = '\uEA69',
+            SEARCH_GLOBE_ALT    = '\uEAFA',
+            SEARCH_COORD        = '\uEB12',
+            SEARCH_DATA         = '\uEB13',
+            ZOOM_IN             = '\uEAA5',
+            ZOOM_OUT            = '\uEAA6',
+            FULL_SCREEN         = '\uEAA7',
+            SCREEN_DUB          = '\uEADC',
+            SCREEN_SPLIT_H      = '\uEADD',
+            SCREEN_SPLIT_V      = '\uEADE',
+            SCREEN_MAG          = '\uEADF',
+            COORD_SYSTEM        = '\uEB1A',
+            COORD_SYSTEM_3D     = '\uEB1B',
+            COORD_SYSTEM_ALT    = '\uEB1E',
+            COORD_SYSTEM_3D_ALT = '\uEB1F',
+            GRID                = '\uEB20',
+            CUBE_3D             = '\uEB21',
+            COORD_GRID          = '\uEB25',
+            PHOTOGRAMMETRY      = '\uEB3C',
+            D360                = '\uEB3D',
+            TOPOGRAPHY          = '\uEB3E',
+            GNSS                = '\uEB42',
+            GNSS_ANTENNA        = '\uEB43',
+            TACHEOMETER         = '\uEB44',
+            THEODOLITE          = '\uEB45',
+            PROFILE             = '\uEB51',
+            PROFILE_O           = '\uEB52',
+            SCREEN_DUB1         = '\uEB54',
+            SCREEN_DUB2         = '\uEB55',
+            SCREEN_DUB_O        = '\uEB56',
+            SCREEN_MAG_O        = '\uEB57',
+            SCREEN_MAG_ALT      = '\uEB58';
+    }
+}
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Styles.java 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Styles.java
index 4cd3a126e8..f72e0b6589 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Styles.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/Styles.java
@@ -44,13 +44,6 @@ import static org.apache.sis.gui.internal.LogHandler.LOGGER;
  * @author  Martin Desruisseaux (Geomatys)
  */
 public final class Styles extends Static {
-    /**
-     * Path to the CSS file defining pseudo-classes. This is the file defining 
appearance
-     * of controls in some situation defining by pseudo-classes, for example 
when a text
-     * field is flagged with {@link #ERROR}.
-     */
-    public static final String STYLESHEET = 
"org/apache/sis/gui/pseudo-classes.css";
-
     /**
      * Approximate size of vertical scroll bar.
      */
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/ToolbarButton.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/ToolbarButton.java
index 0983a61fbc..6054b31a03 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/ToolbarButton.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/ToolbarButton.java
@@ -88,13 +88,14 @@ public abstract class ToolbarButton implements 
EventHandler<ActionEvent> {
      * The action handler will be {@code this}.
      *
      * @param  group      the group of the toggle button.
-     * @param  icon       the text to put in the button, as a Unicode emoji.
+     * @param  icon       the character to put in the button, as a {@link 
FontGIS} code.
+     * @param  fallback   the text to put in the button as a Unicode emoji if 
Font-GIS is not available.
      * @param  localized  an instance of {@link Resources} for current locale.
      * @param  tooltip    the {@link Resources.Keys} value for the tooltip.
      * @return the button configured with text or icon, tooltip and action.
      */
-    public final ToggleButton createButton(final ToggleGroup group, final 
String icon, final Resources localized, final short tooltip) {
-        final ToggleButton tb = new ToggleButton(icon);
+    public final ToggleButton createButton(final ToggleGroup group, final char 
icon, final String fallback, final Resources localized, final short tooltip) {
+        final ToggleButton tb = FontGIS.toggle(icon, fallback);
         tb.setToggleGroup(group);
         tb.setTooltip(new Tooltip(localized.getString(tooltip)));
         tb.setOnAction(this);
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 55f4a35217..659a604e82 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
@@ -23,7 +23,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.Styles;
 import org.apache.sis.gui.internal.Resources;
 import org.apache.sis.util.resources.Vocabulary;
 
@@ -60,7 +59,7 @@ public final class ValueColorMapperApp extends Application {
         pane.setCenter(createIsolineTable());
         pane.setBottom(new Button("Focus here"));
         final Scene scene = new Scene(pane);
-        scene.getStylesheets().add(Styles.STYLESHEET);
+        scene.getStylesheets().add("org/apache/sis/gui/pseudo-classes.css");
         window.setTitle("ValueColorMapper Test");
         window.setScene(scene);
         window.setWidth (400);


Reply via email to