Show a resizing toolbar when running with inspection on
authorJaroslav Tulach <jtulach@netbeans.org>
Fri, 18 Jul 2014 15:50:06 +0200
changeset 7385b88d9ecc21c
parent 737 8478a57cc613
child 739 7a2f7066fc67
Show a resizing toolbar when running with inspection on
boot-fx/src/main/java/org/netbeans/html/boot/fx/AbstractFXPresenter.java
boot-fx/src/main/java/org/netbeans/html/boot/fx/FXToolbar.java
boot-fx/src/main/resources/org/netbeans/html/boot/fx/desktop.png
boot-fx/src/main/resources/org/netbeans/html/boot/fx/handheldLandscape.png
boot-fx/src/main/resources/org/netbeans/html/boot/fx/handheldPortrait.png
boot-fx/src/main/resources/org/netbeans/html/boot/fx/netbook.png
boot-fx/src/main/resources/org/netbeans/html/boot/fx/selectionMode.png
boot-fx/src/main/resources/org/netbeans/html/boot/fx/sizeToFit.png
boot-fx/src/main/resources/org/netbeans/html/boot/fx/tabletLandscape.png
boot-fx/src/main/resources/org/netbeans/html/boot/fx/tabletPortrait.png
boot-fx/src/main/resources/org/netbeans/html/boot/fx/widescreen.png
     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