Ticket #19169: 19169.patch

File 19169.patch, 4.0 KB (added by taylor.smock, 4 years ago)
  • src/org/openstreetmap/josm/plugins/javafx/gui/JavaFxWrapper.java

     
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.plugins.javafx.gui;
    3 
    43import java.awt.Dimension;
     4import java.util.concurrent.ExecutionException;
     5import java.util.concurrent.FutureTask;
    56
    67import org.openstreetmap.josm.tools.Logging;
    78
     
    2324    transient T node;
    2425
    2526    /**
     27     * Catch exceptions in the JavaFX thread (only instantiated with the JavaFxWrapper).
     28     * Since most exceptions should be seen through the `future.get()` method in initialize, this is (mostly) safe.
     29     */
     30    private static class UncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
     31        private final Thread.UncaughtExceptionHandler currentHandler;
     32        public UncaughtExceptionHandler() {
     33            currentHandler = Thread.currentThread().getUncaughtExceptionHandler();
     34            Thread.currentThread().setUncaughtExceptionHandler(this);
     35        }
     36        @Override
     37        public void uncaughtException(Thread t, Throwable e) {
     38            if (currentHandler != null && !(e instanceof NoClassDefFoundError)) {
     39                currentHandler.uncaughtException(t, e);
     40            } else {
     41                Logging.error(e);
     42            }
     43        }
     44    }
     45
     46    private static UncaughtExceptionHandler handler;
     47
     48    /**
    2649     * <p>
    2750     * <b>Implementation note</b>: when the first {@code JFXPanel} object is
    2851     * created, it implicitly initializes the JavaFX runtime. This is the preferred
     
    3154     *
    3255     * @param node The JavaFX node that will be returned later with
    3356     *             {@link JavaFxWrapper#getNode}.
     57     * @throws ExecutionException If something happened during execution. If this happens, fall back to something else!
    3458     */
    35     public JavaFxWrapper(Class<T> node) {
     59    public JavaFxWrapper(Class<T> node) throws ExecutionException {
    3660        try {
    3761            initialize(node.getConstructor().newInstance());
    3862        } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
     
    4973     *
    5074     * @param node The JavaFX node that will be returned later with
    5175     *             {@link JavaFxWrapper#getNode}.
     76     * @throws ExecutionException If something happened during execution. If this happens, fall back to something else!
    5277     */
    53     public JavaFxWrapper(T node) {
     78    public JavaFxWrapper(T node) throws ExecutionException {
    5479        initialize(node);
    5580    }
    5681
     
    5883     * This holds common initialization code
    5984     *
    6085     * @param node The node that should be set to this.node
     86     * @throws ExecutionException If something happened during execution. If this happens, fall back to something else!
    6187     */
    62     private void initialize(T node) {
     88    private void initialize(T node) throws ExecutionException {
    6389        this.node = node;
    64         Platform.runLater(this::initFX);
     90        FutureTask<Scene> task = new FutureTask<>(this::initFX);
     91        Platform.runLater(task);
    6592        Platform.setImplicitExit(false);
    6693        this.setFocusTraversalKeysEnabled(node.isFocusTraversable());
     94        try {
     95            task.get();
     96        } catch (InterruptedException e) {
     97            Thread.currentThread().interrupt();
     98            Logging.error(e);
     99        }
    67100    }
    68101
    69     private void initFX() {
     102    /**
     103     * @return The scene to be used for initializing JavaFX
     104     */
     105    protected Scene initFX() {
     106        initializeExceptionHandler();
    70107        Scene scene = createScene();
    71108        setScene(scene);
     109        return scene;
    72110    }
    73111
     112    private static void initializeExceptionHandler() {
     113        if (handler == null)
     114            handler = new UncaughtExceptionHandler();
     115    }
     116
    74117    private Scene createScene() {
    75118        Group group = new Group();
    76119        Scene scene = new Scene(group);