1.1 --- a/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java Fri Jul 18 15:49:37 2014 +0200
1.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java Fri Jul 18 15:50:06 2014 +0200
1.3 @@ -54,6 +54,10 @@
1.4 import java.util.logging.Level;
1.5 import java.util.logging.Logger;
1.6 import javafx.application.Platform;
1.7 +import javafx.collections.ObservableList;
1.8 +import javafx.scene.Node;
1.9 +import javafx.scene.Parent;
1.10 +import javafx.scene.layout.BorderPane;
1.11 import javafx.scene.web.WebEngine;
1.12 import javafx.scene.web.WebView;
1.13 import netscape.javascript.JSObject;
1.14 @@ -163,6 +167,13 @@
1.15 public void run() {
1.16 if (isInspectOn) {
1.17 view.setContextMenuEnabled(true);
1.18 + final Parent p = view.getParent();
1.19 + if (p instanceof BorderPane) {
1.20 + BorderPane bp = (BorderPane) p;
1.21 + if (bp.getTop() == null) {
1.22 + bp.setTop(new FXToolbar(view, bp));
1.23 + }
1.24 + }
1.25 }
1.26 engine.load(resource.toExternalForm());
1.27 }
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXToolbar.java Fri Jul 18 15:50:06 2014 +0200
2.3 @@ -0,0 +1,362 @@
2.4 +/**
2.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2.6 + *
2.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
2.8 + *
2.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
2.10 + * Other names may be trademarks of their respective owners.
2.11 + *
2.12 + * The contents of this file are subject to the terms of either the GNU
2.13 + * General Public License Version 2 only ("GPL") or the Common
2.14 + * Development and Distribution License("CDDL") (collectively, the
2.15 + * "License"). You may not use this file except in compliance with the
2.16 + * License. You can obtain a copy of the License at
2.17 + * http://www.netbeans.org/cddl-gplv2.html
2.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
2.19 + * specific language governing permissions and limitations under the
2.20 + * License. When distributing the software, include this License Header
2.21 + * Notice in each file and include the License file at
2.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
2.23 + * particular file as subject to the "Classpath" exception as provided
2.24 + * by Oracle in the GPL Version 2 section of the License file that
2.25 + * accompanied this code. If applicable, add the following below the
2.26 + * License Header, with the fields enclosed by brackets [] replaced by
2.27 + * your own identifying information:
2.28 + * "Portions Copyrighted [year] [name of copyright owner]"
2.29 + *
2.30 + * Contributor(s):
2.31 + *
2.32 + * The Original Software is NetBeans. The Initial Developer of the Original
2.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
2.34 + *
2.35 + * If you wish your version of this file to be governed by only the CDDL
2.36 + * or only the GPL Version 2, indicate your decision by adding
2.37 + * "[Contributor] elects to include this software in this distribution
2.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
2.39 + * single choice of license, a recipient has the option to distribute
2.40 + * your version of this file under either the CDDL, the GPL Version 2 or
2.41 + * to extend the choice of license to its licensees as provided above.
2.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
2.43 + * Version 2 license, then the option applies only if the new code is
2.44 + * made subject to such option by the copyright holder.
2.45 + */
2.46 +package org.netbeans.html.boot.fx;
2.47 +
2.48 +import java.util.ArrayList;
2.49 +import java.util.List;
2.50 +import javafx.beans.InvalidationListener;
2.51 +import javafx.beans.Observable;
2.52 +import javafx.beans.value.ChangeListener;
2.53 +import javafx.beans.value.ObservableValue;
2.54 +import javafx.collections.FXCollections;
2.55 +import javafx.scene.control.ComboBox;
2.56 +import javafx.scene.control.ScrollPane;
2.57 +import javafx.scene.control.Separator;
2.58 +import javafx.scene.control.Toggle;
2.59 +import javafx.scene.control.ToggleButton;
2.60 +import javafx.scene.control.ToggleGroup;
2.61 +import javafx.scene.control.ToolBar;
2.62 +import javafx.scene.control.Tooltip;
2.63 +import javafx.scene.image.Image;
2.64 +import javafx.scene.image.ImageView;
2.65 +import javafx.scene.layout.BorderPane;
2.66 +import javafx.scene.web.WebView;
2.67 +
2.68 +final class FXToolbar extends ToolBar {
2.69 + private final ArrayList<ResizeBtn> resizeButtons;
2.70 + private final WebView webView;
2.71 + private final BorderPane container;
2.72 + private final ToggleGroup resizeGroup = new ToggleGroup();
2.73 + private final ComboBox<String> comboZoom = new ComboBox<String>();
2.74 +
2.75 + FXToolbar(WebView webView, BorderPane container) {
2.76 + this.webView = webView;
2.77 + this.container = container;
2.78 +
2.79 + List<ResizeOption> options = ResizeOption.loadAll();
2.80 + options.add( 0, ResizeOption.SIZE_TO_FIT );
2.81 + resizeButtons = new ArrayList<ResizeBtn>( options.size() );
2.82 +
2.83 + for( ResizeOption ro : options ) {
2.84 + ResizeBtn button = new ResizeBtn(ro);
2.85 + resizeButtons.add( button );
2.86 + resizeGroup.getToggles().add( button );
2.87 + getItems().add( button );
2.88 + }
2.89 + resizeButtons.get( 0 ).setSelected( true );
2.90 + resizeGroup.selectedToggleProperty().addListener( new InvalidationListener() {
2.91 +
2.92 + @Override
2.93 + public void invalidated( Observable o ) {
2.94 + resize();
2.95 + }
2.96 + });
2.97 +
2.98 + getItems().add( new Separator() );
2.99 +
2.100 + getItems().add( comboZoom );
2.101 + ArrayList<String> zoomModel = new ArrayList<String>( 6 );
2.102 + zoomModel.add( "200%" ); //NOI18N
2.103 + zoomModel.add( "150%" ); //NOI18N
2.104 + zoomModel.add( "100%" ); //NOI18N
2.105 + zoomModel.add( "75%" ); //NOI18N
2.106 + zoomModel.add( "50%" ); //NOI18N
2.107 + comboZoom.setItems( FXCollections.observableList( zoomModel ) );
2.108 + comboZoom.setEditable( true );
2.109 + comboZoom.setValue( "100%" ); //NOI18N
2.110 + comboZoom.valueProperty().addListener( new ChangeListener<String>() {
2.111 +
2.112 + @Override
2.113 + public void changed( ObservableValue<? extends String> ov, String t, String t1 ) {
2.114 + String newZoom = zoom( t1 );
2.115 + comboZoom.setValue( newZoom );
2.116 + }
2.117 + });
2.118 + }
2.119 +
2.120 + private String zoom( String zoomFactor ) {
2.121 + if( zoomFactor.trim().isEmpty() )
2.122 + return null;
2.123 +
2.124 + try {
2.125 + zoomFactor = zoomFactor.replaceAll( "\\%", ""); //NOI18N
2.126 + zoomFactor = zoomFactor.trim();
2.127 + double zoom = Double.parseDouble( zoomFactor );
2.128 + zoom = Math.abs( zoom )/100;
2.129 + if( zoom <= 0.0 )
2.130 + return null;
2.131 + webView.setScaleX(zoom);
2.132 + webView.setScaleY(zoom);
2.133 + webView.setScaleZ(zoom);
2.134 + return (int)(100*zoom) + "%"; //NOI18N
2.135 + } catch( NumberFormatException nfe ) {
2.136 + //ignore
2.137 + }
2.138 + return null;
2.139 + }
2.140 +
2.141 + private void resize() {
2.142 + Toggle selection = resizeGroup.getSelectedToggle();
2.143 + if( selection instanceof ResizeBtn ) {
2.144 + ResizeOption ro = ((ResizeBtn)selection).getResizeOption();
2.145 + if( ro == ResizeOption.SIZE_TO_FIT ) {
2.146 + _autofit();
2.147 + } else {
2.148 + _resize( ro.getWidth(), ro.getHeight() );
2.149 + }
2.150 + }
2.151 +
2.152 + }
2.153 +
2.154 + private void _resize( final double width, final double height ) {
2.155 + ScrollPane scroll;
2.156 + if (container.getCenter() == webView) {
2.157 + container.setCenter(scroll = new ScrollPane(webView));
2.158 + } else {
2.159 + scroll = (ScrollPane) container.getCenter();
2.160 + }
2.161 + scroll.setPrefViewportWidth( width );
2.162 + scroll.setPrefViewportHeight(height );
2.163 + webView.setMaxWidth( width );
2.164 + webView.setMaxHeight( height );
2.165 + webView.setMinWidth( width );
2.166 + webView.setMinHeight( height );
2.167 + }
2.168 +
2.169 + private void _autofit() {
2.170 + if (container.getCenter() != webView) {
2.171 + container.setCenter(webView);
2.172 + }
2.173 + webView.setMaxWidth( Integer.MAX_VALUE );
2.174 + webView.setMaxHeight( Integer.MAX_VALUE );
2.175 + webView.setMinWidth( -1 );
2.176 + webView.setMinHeight( -1 );
2.177 + webView.autosize();
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 Binary file boot-fx/src/main/resources/org/netbeans/html/boot/fx/desktop.png has changed
4.1 Binary file boot-fx/src/main/resources/org/netbeans/html/boot/fx/handheldLandscape.png has changed
5.1 Binary file boot-fx/src/main/resources/org/netbeans/html/boot/fx/handheldPortrait.png has changed
6.1 Binary file boot-fx/src/main/resources/org/netbeans/html/boot/fx/netbook.png has changed
7.1 Binary file boot-fx/src/main/resources/org/netbeans/html/boot/fx/selectionMode.png has changed
8.1 Binary file boot-fx/src/main/resources/org/netbeans/html/boot/fx/sizeToFit.png has changed
9.1 Binary file boot-fx/src/main/resources/org/netbeans/html/boot/fx/tabletLandscape.png has changed
10.1 Binary file boot-fx/src/main/resources/org/netbeans/html/boot/fx/tabletPortrait.png has changed
11.1 Binary file boot-fx/src/main/resources/org/netbeans/html/boot/fx/widescreen.png has changed