Initial attempt to use JavaFX: When running with -Dvmtest.brwsrs=fx, it runs the tests inside of WebView
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 +}