1.1 --- a/launcher/fx/pom.xml Fri May 31 09:16:23 2013 +0200
1.2 +++ b/launcher/fx/pom.xml Sat Jun 08 12:09:10 2013 +0200
1.3 @@ -54,5 +54,15 @@
1.4 <scope>system</scope>
1.5 <systemPath>${jfxrt.jar}</systemPath>
1.6 </dependency>
1.7 + <dependency>
1.8 + <groupId>org.testng</groupId>
1.9 + <artifactId>testng</artifactId>
1.10 + <scope>test</scope>
1.11 + </dependency>
1.12 + <dependency>
1.13 + <groupId>org.netbeans.modules</groupId>
1.14 + <artifactId>org-netbeans-bootstrap</artifactId>
1.15 + <version>RELEASE73</version>
1.16 + </dependency>
1.17 </dependencies>
1.18 </project>
2.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/FXBrwsrLauncher.java Fri May 31 09:16:23 2013 +0200
2.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/FXBrwsrLauncher.java Sat Jun 08 12:09:10 2013 +0200
2.3 @@ -73,6 +73,10 @@
2.4 if (isDebugged()) {
2.5 params.add("--toolbar=true");
2.6 params.add("--firebug=true");
2.7 + String ud = System.getProperty("netbeans.user");
2.8 + if (ud != null) {
2.9 + params.add("--userdir=" + ud);
2.10 + }
2.11 }
2.12 FXBrwsr.launch(FXBrwsr.class, params.toArray(new String[params.size()]));
2.13 LOG.log(Level.INFO, "Launcher is back. Closing");
3.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/BrowserToolbar.java Fri May 31 09:16:23 2013 +0200
3.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/BrowserToolbar.java Sat Jun 08 12:09:10 2013 +0200
3.3 @@ -45,7 +45,7 @@
3.4 private final ToggleGroup resizeGroup = new ToggleGroup();
3.5 private final ComboBox<String> comboZoom = new ComboBox<String>();
3.6
3.7 - BrowserToolbar(WebView webView, Pane container, boolean useFirebug) {
3.8 + BrowserToolbar(WebView webView, Pane container, boolean useFirebug, final WebDebug webDebug) {
3.9 this.webView = webView;
3.10 this.container = container;
3.11
3.12 @@ -105,20 +105,18 @@
3.13 getItems().add(firebug);
3.14 }
3.15
3.16 - /*
3.17 - final ToggleButton btnSelMode = new ToggleButton( null, new ImageView(
3.18 - new Image(BrowserToolbar.class.getResourceAsStream("selectionMode.png"))
3.19 - ));
3.20 - btnSelMode.setTooltip( new Tooltip( "Toggle selection mode" ) );
3.21 - btnSelMode.selectedProperty().addListener( new InvalidationListener() {
3.22 -
3.23 - @Override
3.24 - public void invalidated( Observable o ) {
3.25 - toggleSelectionMode( btnSelMode.isSelected() );
3.26 - }
3.27 - });
3.28 - getItems().add( btnSelMode );
3.29 - */
3.30 + if (webDebug != null) {
3.31 + final ToggleButton btnSelMode = new ToggleButton(null, new ImageView(
3.32 + new Image(BrowserToolbar.class.getResourceAsStream("selectionMode.png"))));
3.33 + btnSelMode.setTooltip(new Tooltip("Toggle selection mode"));
3.34 + btnSelMode.selectedProperty().addListener(new InvalidationListener() {
3.35 + @Override
3.36 + public void invalidated(Observable o) {
3.37 + toggleSelectionMode(webDebug, btnSelMode.isSelected());
3.38 + }
3.39 + });
3.40 + getItems().add(btnSelMode);
3.41 + }
3.42 }
3.43
3.44 private String zoom( String zoomFactor ) {
3.45 @@ -183,8 +181,9 @@
3.46 webView.autosize();
3.47 }
3.48
3.49 - private void toggleSelectionMode( boolean selMode ) {
3.50 - System.err.println( "selection mode: " + selMode );
3.51 + private void toggleSelectionMode(WebDebug dbg, boolean selMode) {
3.52 + // "inspect"
3.53 + dbg.call("{\"message\":\"selection_mode\",\"selectionMode\":" + selMode + "}");
3.54 }
3.55
3.56 final void toggleFireBug(boolean enable) {
4.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXBrwsr.java Fri May 31 09:16:23 2013 +0200
4.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXBrwsr.java Sat Jun 08 12:09:10 2013 +0200
4.3 @@ -27,20 +27,13 @@
4.4 import javafx.beans.value.ObservableValue;
4.5 import javafx.event.ActionEvent;
4.6 import javafx.event.EventHandler;
4.7 -import javafx.geometry.HPos;
4.8 import javafx.geometry.Insets;
4.9 import javafx.geometry.Pos;
4.10 -import javafx.geometry.VPos;
4.11 -import javafx.scene.Node;
4.12 import javafx.scene.Scene;
4.13 import javafx.scene.control.Button;
4.14 import javafx.scene.control.ToolBar;
4.15 import javafx.scene.layout.BorderPane;
4.16 -import javafx.scene.layout.ColumnConstraints;
4.17 -import javafx.scene.layout.GridPane;
4.18 import javafx.scene.layout.HBox;
4.19 -import javafx.scene.layout.Pane;
4.20 -import javafx.scene.layout.Priority;
4.21 import javafx.scene.layout.VBox;
4.22 import javafx.scene.text.Text;
4.23 import javafx.scene.web.WebEngine;
4.24 @@ -58,11 +51,12 @@
4.25 */
4.26 public class FXBrwsr extends Application {
4.27 private static final Logger LOG = Logger.getLogger(FXBrwsr.class.getName());
4.28 -
4.29 +
4.30 @Override
4.31 public void start(Stage primaryStage) throws Exception {
4.32 WebView view = new WebView();
4.33 - WebController wc = new WebController(view, getParameters().getUnnamed());
4.34 + final String nbUserDir = this.getParameters().getNamed().get("userdir"); // NOI18N
4.35 + WebController wc = new WebController(view, nbUserDir, getParameters().getUnnamed());
4.36
4.37 final VBox vbox = new VBox();
4.38 vbox.setAlignment( Pos.CENTER );
4.39 @@ -79,7 +73,7 @@
4.40 final boolean showToolbar = "true".equals(this.getParameters().getNamed().get("toolbar")); // NOI18N
4.41 final boolean useFirebug = "true".equals(this.getParameters().getNamed().get("firebug")); // NOI18N
4.42 if (showToolbar) {
4.43 - final ToolBar toolbar = new BrowserToolbar(view, vbox, useFirebug);
4.44 + final ToolBar toolbar = new BrowserToolbar(view, vbox, useFirebug, wc.dbg);
4.45 root.setTop( toolbar );
4.46 }
4.47 root.setCenter(hbox);
4.48 @@ -96,8 +90,11 @@
4.49 */
4.50 private static class WebController {
4.51 private final JVMBridge bridge = new JVMBridge();
4.52 + private final WebDebug dbg;
4.53 + private final String ud;
4.54
4.55 - public WebController(WebView view, List<String> params) {
4.56 + public WebController(WebView view, String ud, List<String> params) {
4.57 + this.ud = ud;
4.58 LOG.log(Level.INFO, "Initializing WebView with {0}", params);
4.59 final WebEngine eng = view.getEngine();
4.60 try {
4.61 @@ -140,6 +137,15 @@
4.62 dialogStage.showAndWait();
4.63 }
4.64 });
4.65 + WebDebug wd = null;
4.66 + try {
4.67 + if (ud != null) {
4.68 + wd = WebDebug.create(eng.impl_getDebugger(), ud);
4.69 + }
4.70 + } catch (Exception ex) {
4.71 + LOG.log(Level.WARNING, null, ex);
4.72 + }
4.73 + this.dbg = wd;
4.74 }
4.75
4.76 boolean initBck2Brwsr(WebEngine webEngine) {
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/WebDebug.java Sat Jun 08 12:09:10 2013 +0200
5.3 @@ -0,0 +1,187 @@
5.4 +/**
5.5 + * Back 2 Browser Bytecode Translator
5.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
5.7 + *
5.8 + * This program is free software: you can redistribute it and/or modify
5.9 + * it under the terms of the GNU General Public License as published by
5.10 + * the Free Software Foundation, version 2 of the License.
5.11 + *
5.12 + * This program is distributed in the hope that it will be useful,
5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.15 + * GNU General Public License for more details.
5.16 + *
5.17 + * You should have received a copy of the GNU General Public License
5.18 + * along with this program. Look for COPYING file in the top folder.
5.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
5.20 + */
5.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
5.22 +
5.23 +import com.sun.javafx.scene.web.Debugger;
5.24 +import java.io.File;
5.25 +import java.io.IOException;
5.26 +import java.io.InputStream;
5.27 +import java.io.InterruptedIOException;
5.28 +import java.io.OutputStream;
5.29 +import java.io.UnsupportedEncodingException;
5.30 +import java.lang.reflect.Method;
5.31 +import java.util.concurrent.ArrayBlockingQueue;
5.32 +import java.util.concurrent.Executors;
5.33 +import java.util.concurrent.TimeUnit;
5.34 +import java.util.concurrent.atomic.AtomicReference;
5.35 +import java.util.logging.Level;
5.36 +import java.util.logging.Logger;
5.37 +import javafx.application.Platform;
5.38 +import javafx.util.Callback;
5.39 +
5.40 +/** Simulates WebKit protocol over WebSockets.
5.41 + *
5.42 + * @author Jaroslav Tulach
5.43 + */
5.44 +abstract class WebDebug extends OutputStream
5.45 +implements Callback<String, Void>, Runnable {
5.46 + private static final Logger LOG = Logger.getLogger(WebDebug.class.getName());
5.47 +
5.48 + private final Debugger debug;
5.49 + private final StringBuilder cmd = new StringBuilder();
5.50 + private final ToDbgInputStream toDbg;
5.51 + private final String ud;
5.52 +
5.53 + WebDebug(Debugger debug, String ud) throws Exception {
5.54 + this.debug = debug;
5.55 + this.ud = ud;
5.56 + toDbg = new ToDbgInputStream();
5.57 + debug.setEnabled(true);
5.58 + debug.setMessageCallback(this);
5.59 + }
5.60 +
5.61 + static WebDebug create(Debugger debug, String ud) throws Exception {
5.62 + WebDebug web = new WebDebug(debug, ud) {};
5.63 +
5.64 + Executors.newFixedThreadPool(1).execute(web);
5.65 +
5.66 + return web;
5.67 + }
5.68 +
5.69 + @Override
5.70 + public void run() {
5.71 + try {
5.72 + String p = "/home/jarda/src/bck2brwsr/html~demo/twitter/src/main/resources/org/apidesign/html/demo/twitter/index.html";
5.73 + File f = new File(p);
5.74 + String[] args = {"--livehtml", f.getAbsolutePath()};
5.75 + File dir = f.getParentFile();
5.76 + cliHandler(args, toDbg, this, System.err, dir);
5.77 + } catch (Exception ex) {
5.78 + LOG.log(Level.SEVERE, null, ex);
5.79 + }
5.80 + }
5.81 +
5.82 + @Override
5.83 + public void close() {
5.84 + try {
5.85 + toDbg.close();
5.86 + } catch (IOException ex) {
5.87 + LOG.log(Level.SEVERE, null, ex);
5.88 + }
5.89 + }
5.90 +
5.91 + @Override
5.92 + public Void call(String p) {
5.93 + assert p.indexOf('\n') == -1 : "No new line: " + p;
5.94 + LOG.log(Level.INFO, "toDbgr: {0}", p);
5.95 + toDbg.pushMsg(p);
5.96 + return null;
5.97 + }
5.98 +
5.99 + @Override
5.100 + public void write(int b) throws IOException {
5.101 + if (b == '\n') {
5.102 + final String msg = cmd.toString();
5.103 + Platform.runLater(new Runnable() {
5.104 + @Override
5.105 + public void run() {
5.106 + LOG.log(Level.INFO, "toView: {0}", msg);
5.107 + debug.sendMessage(msg);
5.108 + }
5.109 + });
5.110 + cmd.setLength(0);
5.111 + } else {
5.112 + if (cmd.length() > 100000) {
5.113 + LOG.log(Level.WARNING, "Too big:\n{0}", cmd);
5.114 + }
5.115 + cmd.append((char)b);
5.116 + }
5.117 + }
5.118 +
5.119 + private void cliHandler(
5.120 + String[] args, InputStream is, OutputStream os, OutputStream err, File dir
5.121 + ) {
5.122 + try {
5.123 + Class<?> main = Class.forName("org.netbeans.MainImpl");
5.124 + Method m = main.getDeclaredMethod("execute", String[].class, InputStream.class,
5.125 + OutputStream.class, OutputStream.class, AtomicReference.class
5.126 + );
5.127 + m.setAccessible(true);
5.128 + System.setProperty("netbeans.user", ud);
5.129 + int ret = (Integer)m.invoke(null, args, is, os, err, null);
5.130 + LOG.log(Level.INFO, "Return value: {0}", ret);
5.131 + } catch (Exception ex) {
5.132 + LOG.log(Level.SEVERE, null, ex);
5.133 + } finally {
5.134 + LOG.info("Communication is over");
5.135 + }
5.136 +
5.137 + }
5.138 +
5.139 + private class ToDbgInputStream extends InputStream {
5.140 + private byte[] current;
5.141 + private int currentPos;
5.142 + private final ArrayBlockingQueue<byte[]> pending = new ArrayBlockingQueue<byte[]>(64);
5.143 +
5.144 + public ToDbgInputStream() {
5.145 + }
5.146 +
5.147 + @Override
5.148 + public int read() throws IOException {
5.149 + return read(null, 0, 1);
5.150 + }
5.151 +
5.152 + @Override
5.153 + public int read(byte[] arr, int offset, int len) throws IOException {
5.154 + if (current == null || current.length <= currentPos) {
5.155 + for (;;) {
5.156 + WebDebug.this.flush();
5.157 + try {
5.158 + current = pending.poll(100, TimeUnit.MILLISECONDS);
5.159 + if (current == null) {
5.160 + return 0;
5.161 + }
5.162 + break;
5.163 + } catch (InterruptedException ex) {
5.164 + throw (InterruptedIOException)new InterruptedIOException().initCause(ex);
5.165 + }
5.166 + }
5.167 + LOG.info("Will return: " + new String(current));
5.168 + currentPos = 0;
5.169 + }
5.170 + int cnt = 0;
5.171 + while (len-- > 0 && currentPos < current.length) {
5.172 + final byte nextByte = current[currentPos++];
5.173 + if (arr == null) {
5.174 + return nextByte;
5.175 + }
5.176 + arr[offset + cnt++] = nextByte;
5.177 + }
5.178 + LOG.log(Level.INFO, "read returns: {0}", new String(arr, offset, cnt));
5.179 + return cnt;
5.180 + }
5.181 +
5.182 + private void pushMsg(String p) {
5.183 + try {
5.184 + pending.offer((p + '\n').getBytes("UTF-8"));
5.185 + } catch (UnsupportedEncodingException ex) {
5.186 + throw new IllegalStateException(ex);
5.187 + }
5.188 + }
5.189 + }
5.190 +}