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 be6773070529e6bdcbf5d6863b91626d5483fa31 Author: Martin Desruisseaux <[email protected]> AuthorDate: Fri Aug 14 00:11:14 2020 +0200 Ask user to specify JavaFX installation directory on the first execution. --- application/sis-javafx/src/main/artifact/bin/sisfx | 14 +- .../sis-javafx/src/main/artifact/conf/setenv.sh | 2 + .../org/apache/sis/internal/setup/FXFinder.java | 176 +++++++++++++++++++++ 3 files changed, 191 insertions(+), 1 deletion(-) diff --git a/application/sis-javafx/src/main/artifact/bin/sisfx b/application/sis-javafx/src/main/artifact/bin/sisfx index b2d9448..a13852b 100755 --- a/application/sis-javafx/src/main/artifact/bin/sisfx +++ b/application/sis-javafx/src/main/artifact/bin/sisfx @@ -20,13 +20,25 @@ set -o errexit BASE_DIR="`readlink --canonicalize-existing $0`" BASE_DIR="`dirname $BASE_DIR`/.." +source $BASE_DIR/conf/setenv.sh + +if [ -z "$PATH_TO_FX" ] +then + java --class-path "$BASE_DIR/lib/*" org.apache.sis.internal.setup.FXFinder $BASE_DIR/conf/setenv.sh + if [ $? -ne 0 ] + then + exit + fi + source $BASE_DIR/conf/setenv.sh +fi + SIS_DATA="${SIS_DATA:-$BASE_DIR/data}" export SIS_DATA # Execute SIS with any optional JAR that the user may put in the `lib` directory. java -splash:"$BASE_DIR/lib/logo.jpg" \ --add-modules javafx.graphics,javafx.controls \ - --module-path $PATH_TO_FX \ + --module-path "$PATH_TO_FX" \ --class-path "$BASE_DIR/lib/*" \ -Djava.util.logging.config.class="org.apache.sis.internal.setup.LoggingConfiguration" \ -Djava.util.logging.config.file="$BASE_DIR/conf/logging.properties" \ diff --git a/application/sis-javafx/src/main/artifact/conf/setenv.sh b/application/sis-javafx/src/main/artifact/conf/setenv.sh new file mode 100644 index 0000000..f4f3c84 --- /dev/null +++ b/application/sis-javafx/src/main/artifact/conf/setenv.sh @@ -0,0 +1,2 @@ +# Environment variables required for SIS execution. +# Contents may be added at Apache SIS setup time. diff --git a/application/sis-javafx/src/main/java/org/apache/sis/internal/setup/FXFinder.java b/application/sis-javafx/src/main/java/org/apache/sis/internal/setup/FXFinder.java new file mode 100644 index 0000000..708af4c --- /dev/null +++ b/application/sis-javafx/src/main/java/org/apache/sis/internal/setup/FXFinder.java @@ -0,0 +1,176 @@ +/* + * 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.internal.setup; + +import java.awt.Desktop; +import java.awt.Font; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + + +/** + * Ask user to specify the path to JavaFX installation directory. + * This is used one JavaFX can not be found on the classpath. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.1 + * @since 1.1 + * @module + */ +public final class FXFinder { + /** + * Do not allow instantiation of this class. + */ + private FXFinder() { + } + + /** + * Popups a modal dialog box asking user to choose a directory. + * + * @param args command line arguments. Should have a length of 1, + * with {@code args[0]} containing the path of the file to edit. + */ + public static void main(String[] args) { + boolean success = false; + try { + success = askDirectory(Paths.get(args[0]).normalize()); + } catch (Exception e) { + JOptionPane.showMessageDialog(null, e.toString(), "Error", JOptionPane.ERROR_MESSAGE); + } + System.exit(success ? 0 : 1); + } + + /** + * Popups a modal dialog box asking user to choose a directory. + * + * @param setenv path of the {@code setenv.sh} file to edit. + * @return {@code true} if we can continue with application launch, + * or {@code false} on error or cancellation. + */ + private static boolean askDirectory(final Path setenv) throws Exception { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (ReflectiveOperationException | UnsupportedLookAndFeelException e) { + // Ignore. + } + /* + * Checks now that we can edit `setenv.sh` content in order to not show the next + * dialog box if we czn not read that file (e.g. because the file was not found). + */ + if (!Files.isReadable(setenv) || !Files.isWritable(setenv)) { + JOptionPane.showMessageDialog(null, "Can not edit " + setenv, + "Configuration error", JOptionPane.WARNING_MESSAGE); + return false; + } + /* + * Ask the user what he wants to do. + */ + final JLabel description = new JLabel( + "<html><body><p style=\"width:400px; text-align:justify;\">" + + "This application requires <b>JavaFX</b> version 13 or later. " + + "Click on “Download” for opening the free download page. " + + "If JavaFX is already installed on this computer, " + + "click on “Set directory” for specifying the installation directory." + + "</p></body></html>"); + + description.setFont(description.getFont().deriveFont(Font.PLAIN)); + final Object[] options = {"Download", "Set directory", "Cancel"}; + final int choice = JOptionPane.showOptionDialog(null, description, + "JavaFX installation directory", + JOptionPane.YES_NO_CANCEL_OPTION, + JOptionPane.QUESTION_MESSAGE, + null, + options, + options[2]); + + if (choice == 0) { + if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { + Desktop.getDesktop().browse(URI.create("https://openjfx.io/")); + } else { + JOptionPane.showMessageDialog(null, "See https://openjfx.io/", + "JavaFX download", JOptionPane.INFORMATION_MESSAGE); + } + } else if (choice == 1) { + final JFileChooser fd = new JFileChooser(); + fd.setDialogTitle("JavaFX installation directory"); + fd.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + while (fd.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { + final File dir = findSubDirectory(fd.getSelectedFile()); + if (dir == null) { + JOptionPane.showMessageDialog(null, "Not a JavaFX directory.", + "JavaFX installation directory", JOptionPane.WARNING_MESSAGE); + } else { + setDirectory(setenv, dir); + return true; + } + } + } + return false; + } + + /** + * Tries to locate the {@code lib} sub-folder in a JavaFX installation directory. + * + * @param dir the directory from where to start the search. + * @return the {@code lib} directory, or {@code null} if not found. + */ + private static File findSubDirectory(final File dir) { + if (new File(dir, "javafx.controls.jar").exists()) { + return dir; + } + final File lib = new File(dir, "lib"); + if (new File(lib, "javafx.controls.jar").exists()) { + return lib; + } + return null; + } + + /** + * Sets the JavaFX directory. + * + * @param setenv path to the {@code setenv.sh} file to edit. + * @param dir directory selected by user. + */ + private static void setDirectory(final Path setenv, final File dir) throws IOException { + final ArrayList<String> content = new ArrayList<>(); + int insertAt = -1; + for (String line : Files.readAllLines(setenv)) { + line = line.trim(); + if (line.startsWith("PATH_TO_FX")) { + insertAt = content.size(); + } else { + content.add(line); + } + } + if (insertAt < 0) { + insertAt = content.size(); + } + content.add(insertAt, "PATH_TO_FX=" + dir); + Files.write(setenv, content, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING); + } +}
