1.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/FXBrwsrLauncher.java Tue May 28 21:49:38 2013 +0200
1.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/FXBrwsrLauncher.java Thu May 30 06:09:42 2013 +0200
1.3 @@ -67,7 +67,11 @@
1.4 public void run() {
1.5 LOG.log(Level.INFO, "In FX thread. Launching!");
1.6 try {
1.7 - FXBrwsr.launch(FXBrwsr.class, url.toString());
1.8 + if (isDebugged()) {
1.9 + FXBrwsr.launch(FXBrwsr.class, url.toString(), "--toolbar=true");
1.10 + } else {
1.11 + FXBrwsr.launch(FXBrwsr.class, url.toString());
1.12 + }
1.13 LOG.log(Level.INFO, "Launcher is back. Closing");
1.14 close();
1.15 System.exit(0);
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/BrowserToolbar.java Thu May 30 06:09:42 2013 +0200
2.3 @@ -0,0 +1,362 @@
2.4 +/**
2.5 + * Back 2 Browser Bytecode Translator
2.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
2.7 + *
2.8 + * This program is free software: you can redistribute it and/or modify
2.9 + * it under the terms of the GNU General Public License as published by
2.10 + * the Free Software Foundation, version 2 of the License.
2.11 + *
2.12 + * This program is distributed in the hope that it will be useful,
2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2.15 + * GNU General Public License for more details.
2.16 + *
2.17 + * You should have received a copy of the GNU General Public License
2.18 + * along with this program. Look for COPYING file in the top folder.
2.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
2.20 + */
2.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
2.22 +
2.23 +import java.util.ArrayList;
2.24 +import java.util.List;
2.25 +import javafx.beans.InvalidationListener;
2.26 +import javafx.beans.Observable;
2.27 +import javafx.beans.value.ChangeListener;
2.28 +import javafx.beans.value.ObservableValue;
2.29 +import javafx.collections.FXCollections;
2.30 +import javafx.scene.control.ComboBox;
2.31 +import javafx.scene.control.ScrollPane;
2.32 +import javafx.scene.control.Separator;
2.33 +import javafx.scene.control.Toggle;
2.34 +import javafx.scene.control.ToggleButton;
2.35 +import javafx.scene.control.ToggleGroup;
2.36 +import javafx.scene.control.ToolBar;
2.37 +import javafx.scene.control.Tooltip;
2.38 +import javafx.scene.image.Image;
2.39 +import javafx.scene.image.ImageView;
2.40 +import javafx.scene.layout.Pane;
2.41 +import javafx.scene.web.WebView;
2.42 +
2.43 +final class BrowserToolbar extends ToolBar {
2.44 + private final ArrayList<ResizeBtn> resizeButtons;
2.45 + private final WebView webView;
2.46 + private final Pane container;
2.47 + private final ToggleGroup resizeGroup = new ToggleGroup();
2.48 + private final ComboBox<String> comboZoom = new ComboBox<String>();
2.49 +
2.50 + private BrowserToolbar( WebView webView, Pane container ) {
2.51 + this.webView = webView;
2.52 + this.container = container;
2.53 +
2.54 + List<ResizeOption> options = ResizeOption.loadAll();
2.55 + options.add( 0, ResizeOption.SIZE_TO_FIT );
2.56 + resizeButtons = new ArrayList<ResizeBtn>( options.size() );
2.57 +
2.58 + for( ResizeOption ro : options ) {
2.59 + ResizeBtn button = new ResizeBtn(ro);
2.60 + resizeButtons.add( button );
2.61 + resizeGroup.getToggles().add( button );
2.62 + getItems().add( button );
2.63 + }
2.64 + resizeButtons.get( 0 ).setSelected( true );
2.65 + resizeGroup.selectedToggleProperty().addListener( new InvalidationListener() {
2.66 +
2.67 + @Override
2.68 + public void invalidated( Observable o ) {
2.69 + resize();
2.70 + }
2.71 + });
2.72 +
2.73 + getItems().add( new Separator() );
2.74 +
2.75 + getItems().add( comboZoom );
2.76 + ArrayList<String> zoomModel = new ArrayList<String>( 6 );
2.77 + zoomModel.add( "200%" ); //NOI18N
2.78 + zoomModel.add( "150%" ); //NOI18N
2.79 + zoomModel.add( "100%" ); //NOI18N
2.80 + zoomModel.add( "75%" ); //NOI18N
2.81 + zoomModel.add( "50%" ); //NOI18N
2.82 + comboZoom.setItems( FXCollections.observableList( zoomModel ) );
2.83 + comboZoom.setEditable( true );
2.84 + comboZoom.setValue( "100%" ); //NOI18N
2.85 + comboZoom.valueProperty().addListener( new ChangeListener<String>() {
2.86 +
2.87 + @Override
2.88 + public void changed( ObservableValue<? extends String> ov, String t, String t1 ) {
2.89 + String newZoom = zoom( t1 );
2.90 + comboZoom.setValue( newZoom );
2.91 + }
2.92 + });
2.93 +
2.94 + /*
2.95 + final ToggleButton btnSelMode = new ToggleButton( null, new ImageView(
2.96 + new Image(BrowserToolbar.class.getResourceAsStream("selectionMode.png"))
2.97 + ));
2.98 + btnSelMode.setTooltip( new Tooltip( "Toggle selection mode" ) );
2.99 + btnSelMode.selectedProperty().addListener( new InvalidationListener() {
2.100 +
2.101 + @Override
2.102 + public void invalidated( Observable o ) {
2.103 + toggleSelectionMode( btnSelMode.isSelected() );
2.104 + }
2.105 + });
2.106 + getItems().add( btnSelMode );
2.107 + */
2.108 + }
2.109 +
2.110 + public static ToolBar create( WebView view, Pane container ) {
2.111 + return new BrowserToolbar( view, container );
2.112 + }
2.113 +
2.114 + private String zoom( String zoomFactor ) {
2.115 + if( zoomFactor.trim().isEmpty() )
2.116 + return null;
2.117 +
2.118 + try {
2.119 + zoomFactor = zoomFactor.replaceAll( "\\%", ""); //NOI18N
2.120 + zoomFactor = zoomFactor.trim();
2.121 + double zoom = Double.parseDouble( zoomFactor );
2.122 + zoom = Math.abs( zoom )/100;
2.123 + if( zoom <= 0.0 )
2.124 + return null;
2.125 + webView.impl_setScale( zoom );
2.126 + return (int)(100*zoom) + "%"; //NOI18N
2.127 + } catch( NumberFormatException nfe ) {
2.128 + //ignore
2.129 + }
2.130 + return null;
2.131 + }
2.132 +
2.133 + private void resize() {
2.134 + Toggle selection = resizeGroup.getSelectedToggle();
2.135 + if( selection instanceof ResizeBtn ) {
2.136 + ResizeOption ro = ((ResizeBtn)selection).getResizeOption();
2.137 + if( ro == ResizeOption.SIZE_TO_FIT ) {
2.138 + _autofit();
2.139 + } else {
2.140 + _resize( ro.getWidth(), ro.getHeight() );
2.141 + }
2.142 + }
2.143 +
2.144 + }
2.145 +
2.146 + private void _resize( final double width, final double height ) {
2.147 + ScrollPane scroll;
2.148 + if( !(container.getChildren().get( 0) instanceof ScrollPane) ) {
2.149 + scroll = new ScrollPane();
2.150 + scroll.setContent( webView );
2.151 + container.getChildren().clear();
2.152 + container.getChildren().add( scroll );
2.153 + } else {
2.154 + scroll = ( ScrollPane ) container.getChildren().get( 0 );
2.155 + }
2.156 + scroll.setPrefViewportWidth( width );
2.157 + scroll.setPrefViewportHeight(height );
2.158 + webView.setMaxWidth( width );
2.159 + webView.setMaxHeight( height );
2.160 + webView.setMinWidth( width );
2.161 + webView.setMinHeight( height );
2.162 + }
2.163 +
2.164 + private void _autofit() {
2.165 + if( container.getChildren().get( 0) instanceof ScrollPane ) {
2.166 + container.getChildren().clear();
2.167 + container.getChildren().add( webView );
2.168 + }
2.169 + webView.setMaxWidth( Integer.MAX_VALUE );
2.170 + webView.setMaxHeight( Integer.MAX_VALUE );
2.171 + webView.setMinWidth( -1 );
2.172 + webView.setMinHeight( -1 );
2.173 + webView.autosize();
2.174 + }
2.175 +
2.176 + private void toggleSelectionMode( boolean selMode ) {
2.177 + System.err.println( "selection mode: " + selMode );
2.178 + }
2.179 +
2.180 + /**
2.181 + * Button to resize the browser window.
2.182 + * Taken from NetBeans. Kept GPLwithCPEx license.
2.183 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
2.184 + *
2.185 + * @author S. Aubrecht
2.186 + */
2.187 + static final class ResizeBtn extends ToggleButton {
2.188 +
2.189 + private final ResizeOption resizeOption;
2.190 +
2.191 + ResizeBtn(ResizeOption resizeOption) {
2.192 + super(null, new ImageView(toImage(resizeOption)));
2.193 + this.resizeOption = resizeOption;
2.194 + setTooltip(new Tooltip(resizeOption.getToolTip()));
2.195 + }
2.196 +
2.197 + ResizeOption getResizeOption() {
2.198 + return resizeOption;
2.199 + }
2.200 +
2.201 + static Image toImage(ResizeOption ro) {
2.202 + if (ro == ResizeOption.SIZE_TO_FIT) {
2.203 + return ResizeOption.Type.CUSTOM.getImage();
2.204 + }
2.205 + return ro.getType().getImage();
2.206 + }
2.207 + }
2.208 +
2.209 + /**
2.210 + * Immutable value class describing a single button to resize web browser window.
2.211 + * Taken from NetBeans. Kept GPLwithCPEx license.
2.212 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
2.213 + *
2.214 + * @author S. Aubrecht
2.215 + */
2.216 + static final class ResizeOption {
2.217 +
2.218 + private final Type type;
2.219 + private final String displayName;
2.220 + private final int width;
2.221 + private final int height;
2.222 + private final boolean isDefault;
2.223 +
2.224 + enum Type {
2.225 + DESKTOP("desktop.png"),
2.226 + TABLET_PORTRAIT("tabletPortrait.png"),
2.227 + TABLET_LANDSCAPE("tabletLandscape.png"),
2.228 + SMARTPHONE_PORTRAIT("handheldPortrait.png"),
2.229 + SMARTPHONE_LANDSCAPE("handheldLandscape.png"),
2.230 + WIDESCREEN("widescreen.png"),
2.231 + NETBOOK("netbook.png"),
2.232 + CUSTOM("sizeToFit.png");
2.233 +
2.234 +
2.235 + private final String resource;
2.236 +
2.237 + private Type(String r) {
2.238 + resource = r;
2.239 + }
2.240 +
2.241 + public Image getImage() {
2.242 + return new Image(Type.class.getResourceAsStream(resource));
2.243 + }
2.244 + }
2.245 +
2.246 + private ResizeOption(Type type, String displayName, int width, int height, boolean showInToolbar, boolean isDefault) {
2.247 + super();
2.248 + this.type = type;
2.249 + this.displayName = displayName;
2.250 + this.width = width;
2.251 + this.height = height;
2.252 + this.isDefault = isDefault;
2.253 + }
2.254 +
2.255 + static List<ResizeOption> loadAll() {
2.256 + List<ResizeOption> res = new ArrayList<ResizeOption>(10);
2.257 + res.add(ResizeOption.create(ResizeOption.Type.DESKTOP, "Desktop", 1280, 1024, true, true));
2.258 + res.add(ResizeOption.create(ResizeOption.Type.TABLET_LANDSCAPE, "Tablet Landscape", 1024, 768, true, true));
2.259 + res.add(ResizeOption.create(ResizeOption.Type.TABLET_PORTRAIT, "Tablet Portrait", 768, 1024, true, true));
2.260 + res.add(ResizeOption.create(ResizeOption.Type.SMARTPHONE_LANDSCAPE, "Smartphone Landscape", 480, 320, true, true));
2.261 + res.add(ResizeOption.create(ResizeOption.Type.SMARTPHONE_PORTRAIT, "Smartphone Portrait", 320, 480, true, true));
2.262 + res.add(ResizeOption.create(ResizeOption.Type.WIDESCREEN, "Widescreen", 1680, 1050, false, true));
2.263 + res.add(ResizeOption.create(ResizeOption.Type.NETBOOK, "Netbook", 1024, 600, false, true));
2.264 + return res;
2.265 + }
2.266 +
2.267 + /**
2.268 + * Creates a new instance.
2.269 + * @param type
2.270 + * @param displayName Display name to show in tooltip, cannot be empty.
2.271 + * @param width Screen width
2.272 + * @param height Screen height
2.273 + * @param showInToolbar True to show in web developer toolbar.
2.274 + * @param isDefault True if this is a predefined option that cannot be removed.
2.275 + * @return New instance.
2.276 + */
2.277 + public static ResizeOption create(Type type, String displayName, int width, int height, boolean showInToolbar, boolean isDefault) {
2.278 + if (width <= 0 || height <= 0) {
2.279 + throw new IllegalArgumentException("Invalid screen dimensions: " + width + " x " + height); //NOI18N
2.280 + }
2.281 + return new ResizeOption(type, displayName, width, height, showInToolbar, isDefault);
2.282 + }
2.283 + /**
2.284 + * An extra option to size the browser content to fit its window.
2.285 + */
2.286 + public static final ResizeOption SIZE_TO_FIT = new ResizeOption(Type.CUSTOM, "Size To Fit", -1, -1, true, true);
2.287 +
2.288 + public String getDisplayName() {
2.289 + return displayName;
2.290 + }
2.291 +
2.292 + public Type getType() {
2.293 + return type;
2.294 + }
2.295 +
2.296 + public int getWidth() {
2.297 + return width;
2.298 + }
2.299 +
2.300 + public int getHeight() {
2.301 + return height;
2.302 + }
2.303 +
2.304 + public boolean isDefault() {
2.305 + return isDefault;
2.306 + }
2.307 +
2.308 + @Override
2.309 + public String toString() {
2.310 + return displayName;
2.311 + }
2.312 +
2.313 + public String getToolTip() {
2.314 + if (width < 0 || height < 0) {
2.315 + return displayName;
2.316 + }
2.317 + StringBuilder sb = new StringBuilder();
2.318 + sb.append(width);
2.319 + sb.append(" x "); //NOI18N
2.320 + sb.append(height);
2.321 + sb.append(" ("); //NOI18N
2.322 + sb.append(displayName);
2.323 + sb.append(')'); //NOI18N
2.324 + return sb.toString();
2.325 + }
2.326 +
2.327 + @Override
2.328 + public boolean equals(Object obj) {
2.329 + if (obj == null) {
2.330 + return false;
2.331 + }
2.332 + if (getClass() != obj.getClass()) {
2.333 + return false;
2.334 + }
2.335 + final ResizeOption other = (ResizeOption) obj;
2.336 + if (this.type != other.type) {
2.337 + return false;
2.338 + }
2.339 + if ((this.displayName == null) ? (other.displayName != null) : !this.displayName.equals(other.displayName)) {
2.340 + return false;
2.341 + }
2.342 + if (this.width != other.width) {
2.343 + return false;
2.344 + }
2.345 + if (this.height != other.height) {
2.346 + return false;
2.347 + }
2.348 + if (this.isDefault != other.isDefault) {
2.349 + return false;
2.350 + }
2.351 + return true;
2.352 + }
2.353 +
2.354 + @Override
2.355 + public int hashCode() {
2.356 + int hash = 7;
2.357 + hash = 11 * hash + (this.type != null ? this.type.hashCode() : 0);
2.358 + hash = 11 * hash + (this.displayName != null ? this.displayName.hashCode() : 0);
2.359 + hash = 11 * hash + this.width;
2.360 + hash = 11 * hash + this.height;
2.361 + hash = 11 * hash + (this.isDefault ? 1 : 0);
2.362 + return hash;
2.363 + }
2.364 + }
2.365 +}
3.1 --- a/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXBrwsr.java Tue May 28 21:49:38 2013 +0200
3.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXBrwsr.java Thu May 30 06:09:42 2013 +0200
3.3 @@ -34,8 +34,11 @@
3.4 import javafx.scene.Node;
3.5 import javafx.scene.Scene;
3.6 import javafx.scene.control.Button;
3.7 +import javafx.scene.control.ToolBar;
3.8 +import javafx.scene.layout.BorderPane;
3.9 import javafx.scene.layout.ColumnConstraints;
3.10 import javafx.scene.layout.GridPane;
3.11 +import javafx.scene.layout.HBox;
3.12 import javafx.scene.layout.Pane;
3.13 import javafx.scene.layout.Priority;
3.14 import javafx.scene.layout.VBox;
3.15 @@ -58,27 +61,42 @@
3.16
3.17 @Override
3.18 public void start(Stage primaryStage) throws Exception {
3.19 - Pane root = new WebViewPane(getParameters().getUnnamed());
3.20 - primaryStage.setScene(new Scene(root, 1024, 768));
3.21 - LOG.info("Showing the stage");
3.22 + WebView view = new WebView();
3.23 + WebController wc = new WebController(view, getParameters().getUnnamed());
3.24 +
3.25 + final VBox vbox = new VBox();
3.26 + vbox.setAlignment( Pos.CENTER );
3.27 + vbox.setStyle( "-fx-background-color: #808080;");
3.28 +
3.29 +
3.30 + HBox hbox = new HBox();
3.31 + hbox.setStyle( "-fx-background-color: #808080;");
3.32 + hbox.setAlignment(Pos.CENTER);
3.33 + hbox.getChildren().add(vbox);
3.34 + vbox.getChildren().add(view);
3.35 +
3.36 + BorderPane root = new BorderPane();
3.37 + if ("true".equals(this.getParameters().getNamed().get("toolbar"))) { // NOI18N
3.38 + final ToolBar toolbar = BrowserToolbar.create(view, vbox);
3.39 + root.setTop( toolbar );
3.40 + }
3.41 + root.setCenter(hbox);
3.42 +
3.43 + Scene scene = new Scene(root, 800, 600);
3.44 +
3.45 + primaryStage.setTitle( "Device Emulator" );
3.46 + primaryStage.setScene( scene );
3.47 primaryStage.show();
3.48 - LOG.log(Level.INFO, "State shown: {0}", primaryStage.isShowing());
3.49 }
3.50
3.51 /**
3.52 * Create a resizable WebView pane
3.53 */
3.54 - private class WebViewPane extends Pane {
3.55 + private static class WebController {
3.56 private final JVMBridge bridge = new JVMBridge();
3.57
3.58 - public WebViewPane(List<String> params) {
3.59 + public WebController(WebView view, List<String> params) {
3.60 LOG.log(Level.INFO, "Initializing WebView with {0}", params);
3.61 - VBox.setVgrow(this, Priority.ALWAYS);
3.62 - setMaxWidth(Double.MAX_VALUE);
3.63 - setMaxHeight(Double.MAX_VALUE);
3.64 - WebView view = new WebView();
3.65 - view.setMinSize(500, 400);
3.66 - view.setPrefSize(500, 400);
3.67 final WebEngine eng = view.getEngine();
3.68 try {
3.69 JVMBridge.addBck2BrwsrLoad(new InitBck2Brwsr(eng));
3.70 @@ -120,13 +138,6 @@
3.71 dialogStage.showAndWait();
3.72 }
3.73 });
3.74 - GridPane grid = new GridPane();
3.75 - grid.setVgap(5);
3.76 - grid.setHgap(5);
3.77 - GridPane.setConstraints(view, 0, 1, 2, 1, HPos.CENTER, VPos.CENTER, Priority.ALWAYS, Priority.ALWAYS);
3.78 - 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));
3.79 - grid.getChildren().addAll(view);
3.80 - getChildren().add(grid);
3.81 }
3.82
3.83 boolean initBck2Brwsr(WebEngine webEngine) {
3.84 @@ -141,21 +152,6 @@
3.85 return false;
3.86 }
3.87
3.88 - @Override
3.89 - protected void layoutChildren() {
3.90 - List<Node> managed = getManagedChildren();
3.91 - double width = getWidth();
3.92 - double height = getHeight();
3.93 - double top = getInsets().getTop();
3.94 - double right = getInsets().getRight();
3.95 - double left = getInsets().getLeft();
3.96 - double bottom = getInsets().getBottom();
3.97 - for (int i = 0; i < managed.size(); i++) {
3.98 - Node child = managed.get(i);
3.99 - layoutInArea(child, left, top, width - left - right, height - top - bottom, 0, Insets.EMPTY, true, true, HPos.CENTER, VPos.CENTER);
3.100 - }
3.101 - }
3.102 -
3.103 private class InitBck2Brwsr implements ChangeListener<Void>, Runnable {
3.104 private final WebEngine eng;
3.105
4.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/desktop.png has changed
5.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/handheldLandscape.png has changed
6.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/handheldPortrait.png has changed
7.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/netbook.png has changed
8.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/selectionMode.png has changed
9.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/sizeToFit.png has changed
10.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/tabletLandscape.png has changed
11.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/tabletPortrait.png has changed
12.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/widescreen.png has changed