launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/BrowserToolbar.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 30 Oct 2013 11:24:41 +0100
changeset 1391 4cd2c7e22646
parent 1283 1d0e583ac981
child 1787 ea12a3bb4b33
permissions -rw-r--r--
JavaFX from JDK8 does not have this impl method anymore
jaroslav@1166
     1
/**
jaroslav@1166
     2
 * Back 2 Browser Bytecode Translator
jaroslav@1166
     3
 * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
jaroslav@1166
     4
 *
jaroslav@1166
     5
 * This program is free software: you can redistribute it and/or modify
jaroslav@1166
     6
 * it under the terms of the GNU General Public License as published by
jaroslav@1166
     7
 * the Free Software Foundation, version 2 of the License.
jaroslav@1166
     8
 *
jaroslav@1166
     9
 * This program is distributed in the hope that it will be useful,
jaroslav@1166
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
jaroslav@1166
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
jaroslav@1166
    12
 * GNU General Public License for more details.
jaroslav@1166
    13
 *
jaroslav@1166
    14
 * You should have received a copy of the GNU General Public License
jaroslav@1166
    15
 * along with this program. Look for COPYING file in the top folder.
jaroslav@1166
    16
 * If not, see http://opensource.org/licenses/GPL-2.0.
jaroslav@1166
    17
 */
jaroslav@1166
    18
package org.apidesign.bck2brwsr.launcher.fximpl;
jaroslav@1166
    19
jaroslav@1166
    20
import java.util.ArrayList;
jaroslav@1166
    21
import java.util.List;
jaroslav@1166
    22
import javafx.beans.InvalidationListener;
jaroslav@1166
    23
import javafx.beans.Observable;
jaroslav@1166
    24
import javafx.beans.value.ChangeListener;
jaroslav@1166
    25
import javafx.beans.value.ObservableValue;
jaroslav@1166
    26
import javafx.collections.FXCollections;
jaroslav@1166
    27
import javafx.scene.control.ComboBox;
jaroslav@1166
    28
import javafx.scene.control.ScrollPane;
jaroslav@1166
    29
import javafx.scene.control.Separator;
jaroslav@1166
    30
import javafx.scene.control.Toggle;
jaroslav@1166
    31
import javafx.scene.control.ToggleButton;
jaroslav@1166
    32
import javafx.scene.control.ToggleGroup;
jaroslav@1166
    33
import javafx.scene.control.ToolBar;
jaroslav@1166
    34
import javafx.scene.control.Tooltip;
jaroslav@1166
    35
import javafx.scene.image.Image;
jaroslav@1166
    36
import javafx.scene.image.ImageView;
jaroslav@1166
    37
import javafx.scene.layout.Pane;
jaroslav@1167
    38
import javafx.scene.web.WebEngine;
jaroslav@1166
    39
import javafx.scene.web.WebView;
jaroslav@1166
    40
jaroslav@1166
    41
final class BrowserToolbar extends ToolBar {
jaroslav@1166
    42
    private final ArrayList<ResizeBtn> resizeButtons;
jaroslav@1166
    43
    private final WebView webView;
jaroslav@1166
    44
    private final Pane container;
jaroslav@1166
    45
    private final ToggleGroup resizeGroup = new ToggleGroup();
jaroslav@1166
    46
    private final ComboBox<String> comboZoom = new ComboBox<String>();
jaroslav@1166
    47
    
jaroslav@1283
    48
    BrowserToolbar(WebView webView, Pane container, boolean useFirebug) {
jaroslav@1166
    49
        this.webView = webView;
jaroslav@1166
    50
        this.container = container;
jaroslav@1166
    51
        
jaroslav@1166
    52
        List<ResizeOption> options = ResizeOption.loadAll();
jaroslav@1166
    53
        options.add( 0, ResizeOption.SIZE_TO_FIT );
jaroslav@1166
    54
        resizeButtons = new ArrayList<ResizeBtn>( options.size() );
jaroslav@1166
    55
jaroslav@1166
    56
        for( ResizeOption ro : options ) {
jaroslav@1166
    57
            ResizeBtn button = new ResizeBtn(ro);
jaroslav@1166
    58
            resizeButtons.add( button );
jaroslav@1166
    59
            resizeGroup.getToggles().add( button );
jaroslav@1166
    60
            getItems().add( button );
jaroslav@1166
    61
        }
jaroslav@1166
    62
        resizeButtons.get( 0 ).setSelected( true );
jaroslav@1166
    63
        resizeGroup.selectedToggleProperty().addListener( new InvalidationListener() {
jaroslav@1166
    64
jaroslav@1166
    65
            @Override
jaroslav@1166
    66
            public void invalidated( Observable o ) {
jaroslav@1166
    67
                resize();
jaroslav@1166
    68
            }
jaroslav@1166
    69
        });
jaroslav@1166
    70
        
jaroslav@1166
    71
        getItems().add( new Separator() );
jaroslav@1166
    72
jaroslav@1166
    73
        getItems().add( comboZoom );
jaroslav@1166
    74
        ArrayList<String> zoomModel = new ArrayList<String>( 6 );
jaroslav@1166
    75
        zoomModel.add( "200%" ); //NOI18N
jaroslav@1166
    76
        zoomModel.add( "150%" ); //NOI18N
jaroslav@1166
    77
        zoomModel.add( "100%" ); //NOI18N
jaroslav@1166
    78
        zoomModel.add( "75%" ); //NOI18N
jaroslav@1166
    79
        zoomModel.add( "50%" ); //NOI18N
jaroslav@1166
    80
        comboZoom.setItems( FXCollections.observableList( zoomModel ) );
jaroslav@1166
    81
        comboZoom.setEditable( true );
jaroslav@1166
    82
        comboZoom.setValue( "100%" ); //NOI18N
jaroslav@1166
    83
        comboZoom.valueProperty().addListener( new ChangeListener<String>() {
jaroslav@1166
    84
jaroslav@1166
    85
            @Override
jaroslav@1166
    86
            public void changed( ObservableValue<? extends String> ov, String t, String t1 ) {
jaroslav@1166
    87
                String newZoom = zoom( t1 );
jaroslav@1166
    88
                comboZoom.setValue( newZoom );
jaroslav@1166
    89
            }
jaroslav@1166
    90
        });
jaroslav@1167
    91
        
jaroslav@1167
    92
        if (useFirebug) {
jaroslav@1167
    93
            getItems().add(new Separator());
jaroslav@1166
    94
jaroslav@1167
    95
            final ToggleButton firebug = new ToggleButton(null, new ImageView(
jaroslav@1167
    96
                new Image(BrowserToolbar.class.getResourceAsStream("firebug.png"))
jaroslav@1167
    97
            ));
jaroslav@1167
    98
            firebug.setTooltip(new Tooltip("Show/Hide firebug"));
jaroslav@1167
    99
            firebug.selectedProperty().addListener(new InvalidationListener() {
jaroslav@1167
   100
                @Override
jaroslav@1167
   101
                public void invalidated(Observable o) {
jaroslav@1167
   102
                    toggleFireBug(firebug.isSelected());
jaroslav@1167
   103
                }
jaroslav@1167
   104
            });
jaroslav@1167
   105
            getItems().add(firebug);
jaroslav@1167
   106
        }
jaroslav@1166
   107
    }
jaroslav@1166
   108
jaroslav@1166
   109
    private String zoom( String zoomFactor ) {
jaroslav@1166
   110
        if( zoomFactor.trim().isEmpty() )
jaroslav@1166
   111
            return null;
jaroslav@1166
   112
jaroslav@1166
   113
        try {
jaroslav@1166
   114
            zoomFactor = zoomFactor.replaceAll( "\\%", ""); //NOI18N
jaroslav@1166
   115
            zoomFactor = zoomFactor.trim();
jaroslav@1166
   116
            double zoom = Double.parseDouble( zoomFactor );
jaroslav@1166
   117
            zoom = Math.abs( zoom )/100;
jaroslav@1166
   118
            if( zoom <= 0.0 )
jaroslav@1166
   119
                return null;
jaroslav@1391
   120
            webView.setScaleX(zoom);
jaroslav@1391
   121
            webView.setScaleY(zoom);
jaroslav@1391
   122
            webView.setScaleZ(zoom);
jaroslav@1166
   123
            return (int)(100*zoom) + "%"; //NOI18N
jaroslav@1166
   124
        } catch( NumberFormatException nfe ) {
jaroslav@1166
   125
            //ignore
jaroslav@1166
   126
        }
jaroslav@1166
   127
        return null;
jaroslav@1166
   128
    }
jaroslav@1166
   129
jaroslav@1166
   130
    private void resize() {
jaroslav@1166
   131
        Toggle selection = resizeGroup.getSelectedToggle();
jaroslav@1166
   132
        if( selection instanceof ResizeBtn ) {
jaroslav@1166
   133
            ResizeOption ro = ((ResizeBtn)selection).getResizeOption();
jaroslav@1166
   134
            if( ro == ResizeOption.SIZE_TO_FIT ) {
jaroslav@1166
   135
                _autofit();
jaroslav@1166
   136
            } else {
jaroslav@1166
   137
                _resize( ro.getWidth(), ro.getHeight() );
jaroslav@1166
   138
            }
jaroslav@1166
   139
        }
jaroslav@1166
   140
jaroslav@1166
   141
    }
jaroslav@1166
   142
jaroslav@1166
   143
    private void _resize( final double width, final double height ) {
jaroslav@1166
   144
        ScrollPane scroll;
jaroslav@1166
   145
        if( !(container.getChildren().get( 0) instanceof ScrollPane) ) {
jaroslav@1166
   146
            scroll = new ScrollPane();
jaroslav@1166
   147
            scroll.setContent( webView );
jaroslav@1166
   148
            container.getChildren().clear();
jaroslav@1166
   149
            container.getChildren().add( scroll );
jaroslav@1166
   150
        } else {
jaroslav@1166
   151
            scroll = ( ScrollPane ) container.getChildren().get( 0 );
jaroslav@1166
   152
        }
jaroslav@1166
   153
        scroll.setPrefViewportWidth( width );
jaroslav@1166
   154
        scroll.setPrefViewportHeight(height );
jaroslav@1166
   155
        webView.setMaxWidth( width );
jaroslav@1166
   156
        webView.setMaxHeight( height );
jaroslav@1166
   157
        webView.setMinWidth( width );
jaroslav@1166
   158
        webView.setMinHeight( height );
jaroslav@1166
   159
    }
jaroslav@1166
   160
jaroslav@1166
   161
    private void _autofit() {
jaroslav@1166
   162
        if( container.getChildren().get( 0) instanceof ScrollPane ) {
jaroslav@1166
   163
            container.getChildren().clear();
jaroslav@1166
   164
            container.getChildren().add( webView );
jaroslav@1166
   165
        }
jaroslav@1166
   166
        webView.setMaxWidth( Integer.MAX_VALUE );
jaroslav@1166
   167
        webView.setMaxHeight( Integer.MAX_VALUE );
jaroslav@1166
   168
        webView.setMinWidth( -1 );
jaroslav@1166
   169
        webView.setMinHeight( -1 );
jaroslav@1166
   170
        webView.autosize();
jaroslav@1166
   171
    }
jaroslav@1166
   172
jaroslav@1167
   173
    final void toggleFireBug(boolean enable) {
jaroslav@1167
   174
        WebEngine eng = webView.getEngine();
jaroslav@1167
   175
        Object installed = eng.executeScript("window.Firebug");
jaroslav@1167
   176
        if ("undefined".equals(installed)) {
jaroslav@1167
   177
            StringBuilder sb = new StringBuilder();
jaroslav@1167
   178
            sb.append("var scr = window.document.createElement('script');\n");
jaroslav@1167
   179
            sb.append("scr.type = 'text/javascript';\n");
jaroslav@1167
   180
            sb.append("scr.src = 'https://getfirebug.com/firebug-lite.js';\n");
jaroslav@1167
   181
            sb.append("scr.text = '{ startOpened: true }';\n");
jaroslav@1167
   182
            sb.append("var head = window.document.getElementsByTagName('head')[0];");
jaroslav@1167
   183
            sb.append("head.appendChild(scr);\n");
jaroslav@1167
   184
            sb.append("var html = window.document.getElementsByTagName('html')[0];");
jaroslav@1167
   185
            sb.append("html.debug = true;\n");
jaroslav@1167
   186
            eng.executeScript(sb.toString());
jaroslav@1167
   187
        } else {
jaroslav@1167
   188
            if (enable) {
jaroslav@1167
   189
                eng.executeScript("Firebug.chrome.open()");
jaroslav@1167
   190
            } else {
jaroslav@1167
   191
                eng.executeScript("Firebug.chrome.close()");
jaroslav@1167
   192
            }
jaroslav@1167
   193
        }
jaroslav@1167
   194
    }
jaroslav@1166
   195
jaroslav@1166
   196
    /**
jaroslav@1166
   197
     * Button to resize the browser window.
jaroslav@1166
   198
     * Taken from NetBeans. Kept GPLwithCPEx license.
jaroslav@1166
   199
     * Portions Copyrighted 2012 Sun Microsystems, Inc.
jaroslav@1166
   200
     *
jaroslav@1166
   201
     * @author S. Aubrecht
jaroslav@1166
   202
     */
jaroslav@1166
   203
    static final class ResizeBtn extends ToggleButton {
jaroslav@1166
   204
jaroslav@1166
   205
        private final ResizeOption resizeOption;
jaroslav@1166
   206
jaroslav@1166
   207
        ResizeBtn(ResizeOption resizeOption) {
jaroslav@1166
   208
            super(null, new ImageView(toImage(resizeOption)));
jaroslav@1166
   209
            this.resizeOption = resizeOption;
jaroslav@1166
   210
            setTooltip(new Tooltip(resizeOption.getToolTip()));
jaroslav@1166
   211
        }
jaroslav@1166
   212
jaroslav@1166
   213
        ResizeOption getResizeOption() {
jaroslav@1166
   214
            return resizeOption;
jaroslav@1166
   215
        }
jaroslav@1166
   216
jaroslav@1166
   217
        static Image toImage(ResizeOption ro) {
jaroslav@1166
   218
            if (ro == ResizeOption.SIZE_TO_FIT) {
jaroslav@1166
   219
                return ResizeOption.Type.CUSTOM.getImage();
jaroslav@1166
   220
            }
jaroslav@1166
   221
            return ro.getType().getImage();
jaroslav@1166
   222
        }
jaroslav@1166
   223
    }
jaroslav@1166
   224
jaroslav@1166
   225
    /**
jaroslav@1166
   226
     * Immutable value class describing a single button to resize web browser window.
jaroslav@1166
   227
     * Taken from NetBeans. Kept GPLwithCPEx license.
jaroslav@1166
   228
     * Portions Copyrighted 2012 Sun Microsystems, Inc.
jaroslav@1166
   229
     *
jaroslav@1166
   230
     * @author S. Aubrecht
jaroslav@1166
   231
     */
jaroslav@1166
   232
    static final class ResizeOption {
jaroslav@1166
   233
jaroslav@1166
   234
        private final Type type;
jaroslav@1166
   235
        private final String displayName;
jaroslav@1166
   236
        private final int width;
jaroslav@1166
   237
        private final int height;
jaroslav@1166
   238
        private final boolean isDefault;
jaroslav@1166
   239
jaroslav@1166
   240
        enum Type {
jaroslav@1166
   241
            DESKTOP("desktop.png"), 
jaroslav@1166
   242
            TABLET_PORTRAIT("tabletPortrait.png"), 
jaroslav@1166
   243
            TABLET_LANDSCAPE("tabletLandscape.png"), 
jaroslav@1166
   244
            SMARTPHONE_PORTRAIT("handheldPortrait.png"), 
jaroslav@1166
   245
            SMARTPHONE_LANDSCAPE("handheldLandscape.png"), 
jaroslav@1166
   246
            WIDESCREEN("widescreen.png"), 
jaroslav@1166
   247
            NETBOOK("netbook.png"), 
jaroslav@1166
   248
            CUSTOM("sizeToFit.png");
jaroslav@1166
   249
            
jaroslav@1166
   250
            
jaroslav@1166
   251
            private final String resource;
jaroslav@1166
   252
jaroslav@1166
   253
            private Type(String r) {
jaroslav@1166
   254
                resource = r;
jaroslav@1166
   255
            }
jaroslav@1166
   256
jaroslav@1166
   257
            public Image getImage() {
jaroslav@1166
   258
                return new Image(Type.class.getResourceAsStream(resource));
jaroslav@1166
   259
            }
jaroslav@1166
   260
        }
jaroslav@1166
   261
jaroslav@1166
   262
        private ResizeOption(Type type, String displayName, int width, int height, boolean showInToolbar, boolean isDefault) {
jaroslav@1166
   263
            super();
jaroslav@1166
   264
            this.type = type;
jaroslav@1166
   265
            this.displayName = displayName;
jaroslav@1166
   266
            this.width = width;
jaroslav@1166
   267
            this.height = height;
jaroslav@1166
   268
            this.isDefault = isDefault;
jaroslav@1166
   269
        }
jaroslav@1166
   270
jaroslav@1166
   271
        static List<ResizeOption> loadAll() {
jaroslav@1166
   272
            List<ResizeOption> res = new ArrayList<ResizeOption>(10);
jaroslav@1166
   273
            res.add(ResizeOption.create(ResizeOption.Type.DESKTOP, "Desktop", 1280, 1024, true, true));
jaroslav@1166
   274
            res.add(ResizeOption.create(ResizeOption.Type.TABLET_LANDSCAPE, "Tablet Landscape", 1024, 768, true, true));
jaroslav@1166
   275
            res.add(ResizeOption.create(ResizeOption.Type.TABLET_PORTRAIT, "Tablet Portrait", 768, 1024, true, true));
jaroslav@1166
   276
            res.add(ResizeOption.create(ResizeOption.Type.SMARTPHONE_LANDSCAPE, "Smartphone Landscape", 480, 320, true, true));
jaroslav@1166
   277
            res.add(ResizeOption.create(ResizeOption.Type.SMARTPHONE_PORTRAIT, "Smartphone Portrait", 320, 480, true, true));
jaroslav@1166
   278
            res.add(ResizeOption.create(ResizeOption.Type.WIDESCREEN, "Widescreen", 1680, 1050, false, true));
jaroslav@1166
   279
            res.add(ResizeOption.create(ResizeOption.Type.NETBOOK, "Netbook", 1024, 600, false, true));
jaroslav@1166
   280
            return res;
jaroslav@1166
   281
        }
jaroslav@1166
   282
        
jaroslav@1166
   283
        /**
jaroslav@1166
   284
         * Creates a new instance.
jaroslav@1166
   285
         * @param type
jaroslav@1166
   286
         * @param displayName Display name to show in tooltip, cannot be empty.
jaroslav@1166
   287
         * @param width Screen width
jaroslav@1166
   288
         * @param height Screen height
jaroslav@1166
   289
         * @param showInToolbar True to show in web developer toolbar.
jaroslav@1166
   290
         * @param isDefault True if this is a predefined option that cannot be removed.
jaroslav@1166
   291
         * @return New instance.
jaroslav@1166
   292
         */
jaroslav@1166
   293
        public static ResizeOption create(Type type, String displayName, int width, int height, boolean showInToolbar, boolean isDefault) {
jaroslav@1166
   294
            if (width <= 0 || height <= 0) {
jaroslav@1166
   295
                throw new IllegalArgumentException("Invalid screen dimensions: " + width + " x " + height); //NOI18N
jaroslav@1166
   296
            }
jaroslav@1166
   297
            return new ResizeOption(type, displayName, width, height, showInToolbar, isDefault);
jaroslav@1166
   298
        }
jaroslav@1166
   299
        /**
jaroslav@1166
   300
         * An extra option to size the browser content to fit its window.
jaroslav@1166
   301
         */
jaroslav@1166
   302
        public static final ResizeOption SIZE_TO_FIT = new ResizeOption(Type.CUSTOM, "Size To Fit", -1, -1, true, true);
jaroslav@1166
   303
jaroslav@1166
   304
        public String getDisplayName() {
jaroslav@1166
   305
            return displayName;
jaroslav@1166
   306
        }
jaroslav@1166
   307
jaroslav@1166
   308
        public Type getType() {
jaroslav@1166
   309
            return type;
jaroslav@1166
   310
        }
jaroslav@1166
   311
jaroslav@1166
   312
        public int getWidth() {
jaroslav@1166
   313
            return width;
jaroslav@1166
   314
        }
jaroslav@1166
   315
jaroslav@1166
   316
        public int getHeight() {
jaroslav@1166
   317
            return height;
jaroslav@1166
   318
        }
jaroslav@1166
   319
jaroslav@1166
   320
        public boolean isDefault() {
jaroslav@1166
   321
            return isDefault;
jaroslav@1166
   322
        }
jaroslav@1166
   323
jaroslav@1166
   324
        @Override
jaroslav@1166
   325
        public String toString() {
jaroslav@1166
   326
            return displayName;
jaroslav@1166
   327
        }
jaroslav@1166
   328
jaroslav@1166
   329
        public String getToolTip() {
jaroslav@1166
   330
            if (width < 0 || height < 0) {
jaroslav@1166
   331
                return displayName;
jaroslav@1166
   332
            }
jaroslav@1166
   333
            StringBuilder sb = new StringBuilder();
jaroslav@1166
   334
            sb.append(width);
jaroslav@1166
   335
            sb.append(" x "); //NOI18N
jaroslav@1166
   336
            sb.append(height);
jaroslav@1166
   337
            sb.append(" ("); //NOI18N
jaroslav@1166
   338
            sb.append(displayName);
jaroslav@1166
   339
            sb.append(')'); //NOI18N
jaroslav@1166
   340
            return sb.toString();
jaroslav@1166
   341
        }
jaroslav@1166
   342
jaroslav@1166
   343
        @Override
jaroslav@1166
   344
        public boolean equals(Object obj) {
jaroslav@1166
   345
            if (obj == null) {
jaroslav@1166
   346
                return false;
jaroslav@1166
   347
            }
jaroslav@1166
   348
            if (getClass() != obj.getClass()) {
jaroslav@1166
   349
                return false;
jaroslav@1166
   350
            }
jaroslav@1166
   351
            final ResizeOption other = (ResizeOption) obj;
jaroslav@1166
   352
            if (this.type != other.type) {
jaroslav@1166
   353
                return false;
jaroslav@1166
   354
            }
jaroslav@1166
   355
            if ((this.displayName == null) ? (other.displayName != null) : !this.displayName.equals(other.displayName)) {
jaroslav@1166
   356
                return false;
jaroslav@1166
   357
            }
jaroslav@1166
   358
            if (this.width != other.width) {
jaroslav@1166
   359
                return false;
jaroslav@1166
   360
            }
jaroslav@1166
   361
            if (this.height != other.height) {
jaroslav@1166
   362
                return false;
jaroslav@1166
   363
            }
jaroslav@1166
   364
            if (this.isDefault != other.isDefault) {
jaroslav@1166
   365
                return false;
jaroslav@1166
   366
            }
jaroslav@1166
   367
            return true;
jaroslav@1166
   368
        }
jaroslav@1166
   369
jaroslav@1166
   370
        @Override
jaroslav@1166
   371
        public int hashCode() {
jaroslav@1166
   372
            int hash = 7;
jaroslav@1166
   373
            hash = 11 * hash + (this.type != null ? this.type.hashCode() : 0);
jaroslav@1166
   374
            hash = 11 * hash + (this.displayName != null ? this.displayName.hashCode() : 0);
jaroslav@1166
   375
            hash = 11 * hash + this.width;
jaroslav@1166
   376
            hash = 11 * hash + this.height;
jaroslav@1166
   377
            hash = 11 * hash + (this.isDefault ? 1 : 0);
jaroslav@1166
   378
            return hash;
jaroslav@1166
   379
        }
jaroslav@1166
   380
    }
jaroslav@1166
   381
}