Initial attempt to use JavaFX: When running with -Dvmtest.brwsrs=fx, it runs the tests inside of WebView fx
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 13 Mar 2013 16:20:03 +0100
branchfx
changeset 844023cda5b8b0b
parent 843 140c739c607f
child 845 859804c78010
Initial attempt to use JavaFX: When running with -Dvmtest.brwsrs=fx, it runs the tests inside of WebView
rt/launcher/pom.xml
rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java
rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java
rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/WebViewLauncher.java
     1.1 --- a/rt/launcher/pom.xml	Tue Mar 12 21:22:33 2013 +0100
     1.2 +++ b/rt/launcher/pom.xml	Wed Mar 13 16:20:03 2013 +0100
     1.3 @@ -48,6 +48,13 @@
     1.4        <version>2.2.19</version>
     1.5      </dependency>
     1.6      <dependency>
     1.7 +      <groupId>com.oracle</groupId>
     1.8 +      <artifactId>javafx</artifactId>
     1.9 +      <version>2.2</version>
    1.10 +      <scope>system</scope>
    1.11 +      <systemPath>${java.home}/lib/jfxrt.jar</systemPath>
    1.12 +    </dependency>
    1.13 +    <dependency>
    1.14        <groupId>${project.groupId}</groupId>
    1.15        <artifactId>vm4brwsr</artifactId>
    1.16        <version>${project.version}</version>
     2.1 --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Tue Mar 12 21:22:33 2013 +0100
     2.2 +++ b/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Wed Mar 13 16:20:03 2013 +0100
     2.3 @@ -56,7 +56,7 @@
     2.4   * Supports execution in native browser as well as Java's internal 
     2.5   * execution engine.
     2.6   */
     2.7 -final class Bck2BrwsrLauncher extends Launcher implements Closeable {
     2.8 +class Bck2BrwsrLauncher extends Launcher implements Closeable {
     2.9      private static final Logger LOG = Logger.getLogger(Bck2BrwsrLauncher.class.getName());
    2.10      private static final InvocationContext END = new InvocationContext(null, null, null);
    2.11      private final Set<ClassLoader> loaders = new LinkedHashSet<>();
    2.12 @@ -333,31 +333,7 @@
    2.13          int port = listener.getPort();
    2.14          
    2.15          URI uri = new URI("http://localhost:" + port + page);
    2.16 -        LOG.log(Level.INFO, "Showing {0}", uri);
    2.17 -        if (cmd == null) {
    2.18 -            try {
    2.19 -                LOG.log(Level.INFO, "Trying Desktop.browse on {0} {2} by {1}", new Object[] {
    2.20 -                    System.getProperty("java.vm.name"),
    2.21 -                    System.getProperty("java.vm.vendor"),
    2.22 -                    System.getProperty("java.vm.version"),
    2.23 -                });
    2.24 -                java.awt.Desktop.getDesktop().browse(uri);
    2.25 -                LOG.log(Level.INFO, "Desktop.browse successfully finished");
    2.26 -                return null;
    2.27 -            } catch (UnsupportedOperationException ex) {
    2.28 -                LOG.log(Level.INFO, "Desktop.browse not supported: {0}", ex.getMessage());
    2.29 -                LOG.log(Level.FINE, null, ex);
    2.30 -            }
    2.31 -        }
    2.32 -        {
    2.33 -            String cmdName = cmd == null ? "xdg-open" : cmd;
    2.34 -            String[] cmdArr = { 
    2.35 -                cmdName, uri.toString()
    2.36 -            };
    2.37 -            LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr));
    2.38 -            final Process process = Runtime.getRuntime().exec(cmdArr);
    2.39 -            return new Object[] { process, null };
    2.40 -        }
    2.41 +        return showBrwsr(uri);
    2.42      }
    2.43      private static String toUTF8(String value) throws UnsupportedEncodingException {
    2.44          byte[] arr = new byte[value.length()];
    2.45 @@ -432,6 +408,34 @@
    2.46          shutdown();
    2.47      }
    2.48  
    2.49 +    protected Object[] showBrwsr(URI uri) throws IOException {
    2.50 +        LOG.log(Level.INFO, "Showing {0}", uri);
    2.51 +        if (cmd == null) {
    2.52 +            try {
    2.53 +                LOG.log(Level.INFO, "Trying Desktop.browse on {0} {2} by {1}", new Object[] {
    2.54 +                    System.getProperty("java.vm.name"),
    2.55 +                    System.getProperty("java.vm.vendor"),
    2.56 +                    System.getProperty("java.vm.version"),
    2.57 +                });
    2.58 +                java.awt.Desktop.getDesktop().browse(uri);
    2.59 +                LOG.log(Level.INFO, "Desktop.browse successfully finished");
    2.60 +                return null;
    2.61 +            } catch (UnsupportedOperationException ex) {
    2.62 +                LOG.log(Level.INFO, "Desktop.browse not supported: {0}", ex.getMessage());
    2.63 +                LOG.log(Level.FINE, null, ex);
    2.64 +            }
    2.65 +        }
    2.66 +        {
    2.67 +            String cmdName = cmd == null ? "xdg-open" : cmd;
    2.68 +            String[] cmdArr = { 
    2.69 +                cmdName, uri.toString()
    2.70 +            };
    2.71 +            LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr));
    2.72 +            final Process process = Runtime.getRuntime().exec(cmdArr);
    2.73 +            return new Object[] { process, null };
    2.74 +        }
    2.75 +    }
    2.76 +
    2.77      private class Res implements Bck2Brwsr.Resources {
    2.78          @Override
    2.79          public InputStream get(String resource) throws IOException {
     3.1 --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java	Tue Mar 12 21:22:33 2013 +0100
     3.2 +++ b/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java	Wed Mar 13 16:20:03 2013 +0100
     3.3 @@ -20,6 +20,7 @@
     3.4  import java.io.Closeable;
     3.5  import java.io.File;
     3.6  import java.io.IOException;
     3.7 +import java.lang.reflect.Method;
     3.8  import java.net.URLClassLoader;
     3.9  import org.apidesign.vm4brwsr.Bck2Brwsr;
    3.10  
    3.11 @@ -70,14 +71,21 @@
    3.12          return l;
    3.13      }
    3.14      
    3.15 -    /** Creates launcher that is using external browser.
    3.16 +    /** Creates launcher that is using external browser. Value of <code>cmd</code>
    3.17 +     * may be <code>"fx"</code> to indicate one wants to use JavaFX's WebView
    3.18 +     * instead of command line browser.
    3.19       * 
    3.20       * @param cmd <code>null</code> to use <code>java.awt.Desktop</code> to show the launcher
    3.21       *    or a string to execute in an external process (with a parameter to the URL)
    3.22       * @return launcher executing in external browser.
    3.23       */
    3.24      public static Launcher createBrowser(String cmd) {
    3.25 -        final Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(cmd);
    3.26 +        final Bck2BrwsrLauncher l;
    3.27 +        if ("fx".equals(cmd)) {
    3.28 +            l = new WebViewLauncher();
    3.29 +        } else {
    3.30 +            l = new Bck2BrwsrLauncher(cmd);
    3.31 +        }
    3.32          l.addClassLoader(Bck2Brwsr.class.getClassLoader());
    3.33          l.setTimeout(180000);
    3.34          return l;
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/WebViewLauncher.java	Wed Mar 13 16:20:03 2013 +0100
     4.3 @@ -0,0 +1,178 @@
     4.4 +/**
     4.5 + * Back 2 Browser Bytecode Translator
     4.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4.7 + *
     4.8 + * This program is free software: you can redistribute it and/or modify
     4.9 + * it under the terms of the GNU General Public License as published by
    4.10 + * the Free Software Foundation, version 2 of the License.
    4.11 + *
    4.12 + * This program is distributed in the hope that it will be useful,
    4.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.15 + * GNU General Public License for more details.
    4.16 + *
    4.17 + * You should have received a copy of the GNU General Public License
    4.18 + * along with this program. Look for COPYING file in the top folder.
    4.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    4.20 + */
    4.21 +package org.apidesign.bck2brwsr.launcher;
    4.22 +
    4.23 +import java.io.IOException;
    4.24 +import java.lang.reflect.Method;
    4.25 +import java.net.URI;
    4.26 +import java.net.URL;
    4.27 +import java.net.URLClassLoader;
    4.28 +
    4.29 +import java.util.List;
    4.30 +import java.util.concurrent.Executors;
    4.31 +import javafx.application.Application;
    4.32 +import javafx.application.Platform;
    4.33 +import javafx.beans.value.ChangeListener;
    4.34 +import javafx.beans.value.ObservableValue;
    4.35 +import javafx.event.ActionEvent;
    4.36 +import javafx.event.EventHandler;
    4.37 +import javafx.geometry.HPos;
    4.38 +import javafx.geometry.Insets;
    4.39 +import javafx.geometry.VPos;
    4.40 +import javafx.scene.Node;
    4.41 +import javafx.scene.Scene;
    4.42 +import javafx.scene.control.Button;
    4.43 +import javafx.scene.control.TextField;
    4.44 +import javafx.scene.layout.ColumnConstraints;
    4.45 +import javafx.scene.layout.GridPane;
    4.46 +import javafx.scene.layout.Pane;
    4.47 +import javafx.scene.layout.Priority;
    4.48 +import javafx.scene.layout.VBox;
    4.49 +import javafx.scene.web.WebEngine;
    4.50 +import javafx.scene.web.WebView;
    4.51 +import javafx.stage.Stage;
    4.52 +
    4.53 +/**
    4.54 + *
    4.55 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    4.56 + */
    4.57 +final class WebViewLauncher extends Bck2BrwsrLauncher {
    4.58 +    static {
    4.59 +        try {
    4.60 +            Method m = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
    4.61 +            m.setAccessible(true);
    4.62 +            URL l = new URL("file://" + System.getProperty("java.home") + "/lib/jfxrt.jar");
    4.63 +            System.err.println("url : " + l);
    4.64 +            m.invoke(ClassLoader.getSystemClassLoader(), l);
    4.65 +        } catch (Exception ex) {
    4.66 +            throw new LinkageError("Can't add jfxrt.jar on the classpath", ex);
    4.67 +        }
    4.68 +    }
    4.69 +    
    4.70 +    public WebViewLauncher() {
    4.71 +        super(null);
    4.72 +    }
    4.73 +
    4.74 +    @Override
    4.75 +    protected Object[] showBrwsr(final URI url) throws IOException {
    4.76 +        try {
    4.77 +            Executors.newSingleThreadExecutor().submit(new Runnable() {
    4.78 +                @Override
    4.79 +                public void run() {
    4.80 +                    WebViewBrowser.launch(WebViewBrowser.class, url.toString());
    4.81 +                }
    4.82 +            });
    4.83 +        } catch (Throwable ex) {
    4.84 +            ex.printStackTrace();
    4.85 +        }
    4.86 +        return null;
    4.87 +    }
    4.88 +
    4.89 +    @Override
    4.90 +    public void close() throws IOException {
    4.91 +        Platform.exit();
    4.92 +    }
    4.93 +    
    4.94 +    
    4.95 +
    4.96 +    /**
    4.97 +     * Demonstrates a WebView object accessing a web page.
    4.98 +     *
    4.99 +     * @see javafx.scene.web.WebView
   4.100 +     * @see javafx.scene.web.WebEngine
   4.101 +     */
   4.102 +    public static class WebViewBrowser extends Application {
   4.103 +
   4.104 +        @Override
   4.105 +        public void start(Stage primaryStage) throws Exception {
   4.106 +            Pane root = new WebViewPane(getParameters().getUnnamed());
   4.107 +            primaryStage.setScene(new Scene(root, 1024, 768));
   4.108 +            primaryStage.show();
   4.109 +        }
   4.110 +
   4.111 +        /**
   4.112 +         * Create a resizable WebView pane
   4.113 +         */
   4.114 +        public class WebViewPane extends Pane {
   4.115 +
   4.116 +            public WebViewPane(List<String> params) {
   4.117 +                VBox.setVgrow(this, Priority.ALWAYS);
   4.118 +                setMaxWidth(Double.MAX_VALUE);
   4.119 +                setMaxHeight(Double.MAX_VALUE);
   4.120 +
   4.121 +                WebView view = new WebView();
   4.122 +                view.setMinSize(500, 400);
   4.123 +                view.setPrefSize(500, 400);
   4.124 +                final WebEngine eng = view.getEngine();
   4.125 +                final TextField locationField = new TextField();
   4.126 +                System.err.println("params : " + params);
   4.127 +                if (params.size() > 0) {
   4.128 +                    eng.load(params.get(0));
   4.129 +                    locationField.setText(params.get(0));
   4.130 +                }
   4.131 +                locationField.setMaxHeight(Double.MAX_VALUE);
   4.132 +                Button goButton = new Button("Go");
   4.133 +                goButton.setDefaultButton(true);
   4.134 +                EventHandler<ActionEvent> goAction = new EventHandler<ActionEvent>() {
   4.135 +                    @Override
   4.136 +                    public void handle(ActionEvent event) {
   4.137 +                        eng.load(locationField.getText().startsWith("http://") ? locationField.getText()
   4.138 +                            : "http://" + locationField.getText());
   4.139 +                    }
   4.140 +                };
   4.141 +                goButton.setOnAction(goAction);
   4.142 +                locationField.setOnAction(goAction);
   4.143 +                eng.locationProperty().addListener(new ChangeListener<String>() {
   4.144 +                    @Override
   4.145 +                    public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
   4.146 +                        locationField.setText(newValue);
   4.147 +                    }
   4.148 +                });
   4.149 +                GridPane grid = new GridPane();
   4.150 +                grid.setVgap(5);
   4.151 +                grid.setHgap(5);
   4.152 +                GridPane.setConstraints(locationField, 0, 0, 1, 1, HPos.CENTER, VPos.CENTER, Priority.ALWAYS, Priority.SOMETIMES);
   4.153 +                GridPane.setConstraints(goButton, 1, 0);
   4.154 +                GridPane.setConstraints(view, 0, 1, 2, 1, HPos.CENTER, VPos.CENTER, Priority.ALWAYS, Priority.ALWAYS);
   4.155 +                grid.getColumnConstraints().addAll(
   4.156 +                    new ColumnConstraints(100, 100, Double.MAX_VALUE, Priority.ALWAYS, HPos.CENTER, true),
   4.157 +                    new ColumnConstraints(40, 40, 40, Priority.NEVER, HPos.CENTER, true));
   4.158 +                grid.getChildren().addAll(locationField, goButton, view);
   4.159 +                getChildren().add(grid);
   4.160 +            }
   4.161 +
   4.162 +            @Override
   4.163 +            protected void layoutChildren() {
   4.164 +                List<Node> managed = getManagedChildren();
   4.165 +                double width = getWidth();
   4.166 +                double height = getHeight();
   4.167 +                double top = getInsets().getTop();
   4.168 +                double right = getInsets().getRight();
   4.169 +                double left = getInsets().getLeft();
   4.170 +                double bottom = getInsets().getBottom();
   4.171 +                for (int i = 0; i < managed.size(); i++) {
   4.172 +                    Node child = managed.get(i);
   4.173 +                    layoutInArea(child, left, top,
   4.174 +                        width - left - right, height - top - bottom,
   4.175 +                        0, Insets.EMPTY, true, true, HPos.CENTER, VPos.CENTER);
   4.176 +                }
   4.177 +            }
   4.178 +        }
   4.179 +    }
   4.180 +    
   4.181 +}