# HG changeset patch # User Jaroslav Tulach # Date 1363188003 -3600 # Node ID 023cda5b8b0bfd4cf3af11d8de17210125317754 # Parent 140c739c607fddcb6f7c4725514b22ef7b6226e4 Initial attempt to use JavaFX: When running with -Dvmtest.brwsrs=fx, it runs the tests inside of WebView diff -r 140c739c607f -r 023cda5b8b0b rt/launcher/pom.xml --- a/rt/launcher/pom.xml Tue Mar 12 21:22:33 2013 +0100 +++ b/rt/launcher/pom.xml Wed Mar 13 16:20:03 2013 +0100 @@ -48,6 +48,13 @@ 2.2.19 + com.oracle + javafx + 2.2 + system + ${java.home}/lib/jfxrt.jar + + ${project.groupId} vm4brwsr ${project.version} diff -r 140c739c607f -r 023cda5b8b0b rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Tue Mar 12 21:22:33 2013 +0100 +++ b/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Wed Mar 13 16:20:03 2013 +0100 @@ -56,7 +56,7 @@ * Supports execution in native browser as well as Java's internal * execution engine. */ -final class Bck2BrwsrLauncher extends Launcher implements Closeable { +class Bck2BrwsrLauncher extends Launcher implements Closeable { private static final Logger LOG = Logger.getLogger(Bck2BrwsrLauncher.class.getName()); private static final InvocationContext END = new InvocationContext(null, null, null); private final Set loaders = new LinkedHashSet<>(); @@ -333,31 +333,7 @@ int port = listener.getPort(); URI uri = new URI("http://localhost:" + port + page); - LOG.log(Level.INFO, "Showing {0}", uri); - if (cmd == null) { - try { - LOG.log(Level.INFO, "Trying Desktop.browse on {0} {2} by {1}", new Object[] { - System.getProperty("java.vm.name"), - System.getProperty("java.vm.vendor"), - System.getProperty("java.vm.version"), - }); - java.awt.Desktop.getDesktop().browse(uri); - LOG.log(Level.INFO, "Desktop.browse successfully finished"); - return null; - } catch (UnsupportedOperationException ex) { - LOG.log(Level.INFO, "Desktop.browse not supported: {0}", ex.getMessage()); - LOG.log(Level.FINE, null, ex); - } - } - { - String cmdName = cmd == null ? "xdg-open" : cmd; - String[] cmdArr = { - cmdName, uri.toString() - }; - LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr)); - final Process process = Runtime.getRuntime().exec(cmdArr); - return new Object[] { process, null }; - } + return showBrwsr(uri); } private static String toUTF8(String value) throws UnsupportedEncodingException { byte[] arr = new byte[value.length()]; @@ -432,6 +408,34 @@ shutdown(); } + protected Object[] showBrwsr(URI uri) throws IOException { + LOG.log(Level.INFO, "Showing {0}", uri); + if (cmd == null) { + try { + LOG.log(Level.INFO, "Trying Desktop.browse on {0} {2} by {1}", new Object[] { + System.getProperty("java.vm.name"), + System.getProperty("java.vm.vendor"), + System.getProperty("java.vm.version"), + }); + java.awt.Desktop.getDesktop().browse(uri); + LOG.log(Level.INFO, "Desktop.browse successfully finished"); + return null; + } catch (UnsupportedOperationException ex) { + LOG.log(Level.INFO, "Desktop.browse not supported: {0}", ex.getMessage()); + LOG.log(Level.FINE, null, ex); + } + } + { + String cmdName = cmd == null ? "xdg-open" : cmd; + String[] cmdArr = { + cmdName, uri.toString() + }; + LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr)); + final Process process = Runtime.getRuntime().exec(cmdArr); + return new Object[] { process, null }; + } + } + private class Res implements Bck2Brwsr.Resources { @Override public InputStream get(String resource) throws IOException { diff -r 140c739c607f -r 023cda5b8b0b rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java Tue Mar 12 21:22:33 2013 +0100 +++ b/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java Wed Mar 13 16:20:03 2013 +0100 @@ -20,6 +20,7 @@ import java.io.Closeable; import java.io.File; import java.io.IOException; +import java.lang.reflect.Method; import java.net.URLClassLoader; import org.apidesign.vm4brwsr.Bck2Brwsr; @@ -70,14 +71,21 @@ return l; } - /** Creates launcher that is using external browser. + /** Creates launcher that is using external browser. Value of cmd + * may be "fx" to indicate one wants to use JavaFX's WebView + * instead of command line browser. * * @param cmd null to use java.awt.Desktop to show the launcher * or a string to execute in an external process (with a parameter to the URL) * @return launcher executing in external browser. */ public static Launcher createBrowser(String cmd) { - final Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(cmd); + final Bck2BrwsrLauncher l; + if ("fx".equals(cmd)) { + l = new WebViewLauncher(); + } else { + l = new Bck2BrwsrLauncher(cmd); + } l.addClassLoader(Bck2Brwsr.class.getClassLoader()); l.setTimeout(180000); return l; diff -r 140c739c607f -r 023cda5b8b0b rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/WebViewLauncher.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/WebViewLauncher.java Wed Mar 13 16:20:03 2013 +0100 @@ -0,0 +1,178 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.bck2brwsr.launcher; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; + +import java.util.List; +import java.util.concurrent.Executors; +import javafx.application.Application; +import javafx.application.Platform; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.geometry.HPos; +import javafx.geometry.Insets; +import javafx.geometry.VPos; +import javafx.scene.Node; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.TextField; +import javafx.scene.layout.ColumnConstraints; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.Pane; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import javafx.scene.web.WebEngine; +import javafx.scene.web.WebView; +import javafx.stage.Stage; + +/** + * + * @author Jaroslav Tulach + */ +final class WebViewLauncher extends Bck2BrwsrLauncher { + static { + try { + Method m = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); + m.setAccessible(true); + URL l = new URL("file://" + System.getProperty("java.home") + "/lib/jfxrt.jar"); + System.err.println("url : " + l); + m.invoke(ClassLoader.getSystemClassLoader(), l); + } catch (Exception ex) { + throw new LinkageError("Can't add jfxrt.jar on the classpath", ex); + } + } + + public WebViewLauncher() { + super(null); + } + + @Override + protected Object[] showBrwsr(final URI url) throws IOException { + try { + Executors.newSingleThreadExecutor().submit(new Runnable() { + @Override + public void run() { + WebViewBrowser.launch(WebViewBrowser.class, url.toString()); + } + }); + } catch (Throwable ex) { + ex.printStackTrace(); + } + return null; + } + + @Override + public void close() throws IOException { + Platform.exit(); + } + + + + /** + * Demonstrates a WebView object accessing a web page. + * + * @see javafx.scene.web.WebView + * @see javafx.scene.web.WebEngine + */ + public static class WebViewBrowser extends Application { + + @Override + public void start(Stage primaryStage) throws Exception { + Pane root = new WebViewPane(getParameters().getUnnamed()); + primaryStage.setScene(new Scene(root, 1024, 768)); + primaryStage.show(); + } + + /** + * Create a resizable WebView pane + */ + public class WebViewPane extends Pane { + + public WebViewPane(List params) { + VBox.setVgrow(this, Priority.ALWAYS); + setMaxWidth(Double.MAX_VALUE); + setMaxHeight(Double.MAX_VALUE); + + WebView view = new WebView(); + view.setMinSize(500, 400); + view.setPrefSize(500, 400); + final WebEngine eng = view.getEngine(); + final TextField locationField = new TextField(); + System.err.println("params : " + params); + if (params.size() > 0) { + eng.load(params.get(0)); + locationField.setText(params.get(0)); + } + locationField.setMaxHeight(Double.MAX_VALUE); + Button goButton = new Button("Go"); + goButton.setDefaultButton(true); + EventHandler goAction = new EventHandler() { + @Override + public void handle(ActionEvent event) { + eng.load(locationField.getText().startsWith("http://") ? locationField.getText() + : "http://" + locationField.getText()); + } + }; + goButton.setOnAction(goAction); + locationField.setOnAction(goAction); + eng.locationProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, String oldValue, String newValue) { + locationField.setText(newValue); + } + }); + GridPane grid = new GridPane(); + grid.setVgap(5); + grid.setHgap(5); + GridPane.setConstraints(locationField, 0, 0, 1, 1, HPos.CENTER, VPos.CENTER, Priority.ALWAYS, Priority.SOMETIMES); + GridPane.setConstraints(goButton, 1, 0); + GridPane.setConstraints(view, 0, 1, 2, 1, HPos.CENTER, VPos.CENTER, Priority.ALWAYS, Priority.ALWAYS); + grid.getColumnConstraints().addAll( + new ColumnConstraints(100, 100, Double.MAX_VALUE, Priority.ALWAYS, HPos.CENTER, true), + new ColumnConstraints(40, 40, 40, Priority.NEVER, HPos.CENTER, true)); + grid.getChildren().addAll(locationField, goButton, view); + getChildren().add(grid); + } + + @Override + protected void layoutChildren() { + List managed = getManagedChildren(); + double width = getWidth(); + double height = getHeight(); + double top = getInsets().getTop(); + double right = getInsets().getRight(); + double left = getInsets().getLeft(); + double bottom = getInsets().getBottom(); + for (int i = 0; i < managed.size(); i++) { + Node child = managed.get(i); + layoutInArea(child, left, top, + width - left - right, height - top - bottom, + 0, Insets.EMPTY, true, true, HPos.CENTER, VPos.CENTER); + } + } + } + } + +}