launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/BrowserToolbar.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sun, 15 Sep 2013 18:24:48 +0200
changeset 1283 1d0e583ac981
parent 1169 c19ac78b940e
child 1391 4cd2c7e22646
permissions -rw-r--r--
Use the new netbeans.inspect property to connect to the IDE
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@1166
   120
            webView.impl_setScale( zoom );
jaroslav@1166
   121
            return (int)(100*zoom) + "%"; //NOI18N
jaroslav@1166
   122
        } catch( NumberFormatException nfe ) {
jaroslav@1166
   123
            //ignore
jaroslav@1166
   124
        }
jaroslav@1166
   125
        return null;
jaroslav@1166
   126
    }
jaroslav@1166
   127
jaroslav@1166
   128
    private void resize() {
jaroslav@1166
   129
        Toggle selection = resizeGroup.getSelectedToggle();
jaroslav@1166
   130
        if( selection instanceof ResizeBtn ) {
jaroslav@1166
   131
            ResizeOption ro = ((ResizeBtn)selection).getResizeOption();
jaroslav@1166
   132
            if( ro == ResizeOption.SIZE_TO_FIT ) {
jaroslav@1166
   133
                _autofit();
jaroslav@1166
   134
            } else {
jaroslav@1166
   135
                _resize( ro.getWidth(), ro.getHeight() );
jaroslav@1166
   136
            }
jaroslav@1166
   137
        }
jaroslav@1166
   138
jaroslav@1166
   139
    }
jaroslav@1166
   140
jaroslav@1166
   141
    private void _resize( final double width, final double height ) {
jaroslav@1166
   142
        ScrollPane scroll;
jaroslav@1166
   143
        if( !(container.getChildren().get( 0) instanceof ScrollPane) ) {
jaroslav@1166
   144
            scroll = new ScrollPane();
jaroslav@1166
   145
            scroll.setContent( webView );
jaroslav@1166
   146
            container.getChildren().clear();
jaroslav@1166
   147
            container.getChildren().add( scroll );
jaroslav@1166
   148
        } else {
jaroslav@1166
   149
            scroll = ( ScrollPane ) container.getChildren().get( 0 );
jaroslav@1166
   150
        }
jaroslav@1166
   151
        scroll.setPrefViewportWidth( width );
jaroslav@1166
   152
        scroll.setPrefViewportHeight(height );
jaroslav@1166
   153
        webView.setMaxWidth( width );
jaroslav@1166
   154
        webView.setMaxHeight( height );
jaroslav@1166
   155
        webView.setMinWidth( width );
jaroslav@1166
   156
        webView.setMinHeight( height );
jaroslav@1166
   157
    }
jaroslav@1166
   158
jaroslav@1166
   159
    private void _autofit() {
jaroslav@1166
   160
        if( container.getChildren().get( 0) instanceof ScrollPane ) {
jaroslav@1166
   161
            container.getChildren().clear();
jaroslav@1166
   162
            container.getChildren().add( webView );
jaroslav@1166
   163
        }
jaroslav@1166
   164
        webView.setMaxWidth( Integer.MAX_VALUE );
jaroslav@1166
   165
        webView.setMaxHeight( Integer.MAX_VALUE );
jaroslav@1166
   166
        webView.setMinWidth( -1 );
jaroslav@1166
   167
        webView.setMinHeight( -1 );
jaroslav@1166
   168
        webView.autosize();
jaroslav@1166
   169
    }
jaroslav@1166
   170
jaroslav@1167
   171
    final void toggleFireBug(boolean enable) {
jaroslav@1167
   172
        WebEngine eng = webView.getEngine();
jaroslav@1167
   173
        Object installed = eng.executeScript("window.Firebug");
jaroslav@1167
   174
        if ("undefined".equals(installed)) {
jaroslav@1167
   175
            StringBuilder sb = new StringBuilder();
jaroslav@1167
   176
            sb.append("var scr = window.document.createElement('script');\n");
jaroslav@1167
   177
            sb.append("scr.type = 'text/javascript';\n");
jaroslav@1167
   178
            sb.append("scr.src = 'https://getfirebug.com/firebug-lite.js';\n");
jaroslav@1167
   179
            sb.append("scr.text = '{ startOpened: true }';\n");
jaroslav@1167
   180
            sb.append("var head = window.document.getElementsByTagName('head')[0];");
jaroslav@1167
   181
            sb.append("head.appendChild(scr);\n");
jaroslav@1167
   182
            sb.append("var html = window.document.getElementsByTagName('html')[0];");
jaroslav@1167
   183
            sb.append("html.debug = true;\n");
jaroslav@1167
   184
            eng.executeScript(sb.toString());
jaroslav@1167
   185
        } else {
jaroslav@1167
   186
            if (enable) {
jaroslav@1167
   187
                eng.executeScript("Firebug.chrome.open()");
jaroslav@1167
   188
            } else {
jaroslav@1167
   189
                eng.executeScript("Firebug.chrome.close()");
jaroslav@1167
   190
            }
jaroslav@1167
   191
        }
jaroslav@1167
   192
    }
jaroslav@1166
   193
jaroslav@1166
   194
    /**
jaroslav@1166
   195
     * Button to resize the browser window.
jaroslav@1166
   196
     * Taken from NetBeans. Kept GPLwithCPEx license.
jaroslav@1166
   197
     * Portions Copyrighted 2012 Sun Microsystems, Inc.
jaroslav@1166
   198
     *
jaroslav@1166
   199
     * @author S. Aubrecht
jaroslav@1166
   200
     */
jaroslav@1166
   201
    static final class ResizeBtn extends ToggleButton {
jaroslav@1166
   202
jaroslav@1166
   203
        private final ResizeOption resizeOption;
jaroslav@1166
   204
jaroslav@1166
   205
        ResizeBtn(ResizeOption resizeOption) {
jaroslav@1166
   206
            super(null, new ImageView(toImage(resizeOption)));
jaroslav@1166
   207
            this.resizeOption = resizeOption;
jaroslav@1166
   208
            setTooltip(new Tooltip(resizeOption.getToolTip()));
jaroslav@1166
   209
        }
jaroslav@1166
   210
jaroslav@1166
   211
        ResizeOption getResizeOption() {
jaroslav@1166
   212
            return resizeOption;
jaroslav@1166
   213
        }
jaroslav@1166
   214
jaroslav@1166
   215
        static Image toImage(ResizeOption ro) {
jaroslav@1166
   216
            if (ro == ResizeOption.SIZE_TO_FIT) {
jaroslav@1166
   217
                return ResizeOption.Type.CUSTOM.getImage();
jaroslav@1166
   218
            }
jaroslav@1166
   219
            return ro.getType().getImage();
jaroslav@1166
   220
        }
jaroslav@1166
   221
    }
jaroslav@1166
   222
jaroslav@1166
   223
    /**
jaroslav@1166
   224
     * Immutable value class describing a single button to resize web browser window.
jaroslav@1166
   225
     * Taken from NetBeans. Kept GPLwithCPEx license.
jaroslav@1166
   226
     * Portions Copyrighted 2012 Sun Microsystems, Inc.
jaroslav@1166
   227
     *
jaroslav@1166
   228
     * @author S. Aubrecht
jaroslav@1166
   229
     */
jaroslav@1166
   230
    static final class ResizeOption {
jaroslav@1166
   231
jaroslav@1166
   232
        private final Type type;
jaroslav@1166
   233
        private final String displayName;
jaroslav@1166
   234
        private final int width;
jaroslav@1166
   235
        private final int height;
jaroslav@1166
   236
        private final boolean isDefault;
jaroslav@1166
   237
jaroslav@1166
   238
        enum Type {
jaroslav@1166
   239
            DESKTOP("desktop.png"), 
jaroslav@1166
   240
            TABLET_PORTRAIT("tabletPortrait.png"), 
jaroslav@1166
   241
            TABLET_LANDSCAPE("tabletLandscape.png"), 
jaroslav@1166
   242
            SMARTPHONE_PORTRAIT("handheldPortrait.png"), 
jaroslav@1166
   243
            SMARTPHONE_LANDSCAPE("handheldLandscape.png"), 
jaroslav@1166
   244
            WIDESCREEN("widescreen.png"), 
jaroslav@1166
   245
            NETBOOK("netbook.png"), 
jaroslav@1166
   246
            CUSTOM("sizeToFit.png");
jaroslav@1166
   247
            
jaroslav@1166
   248
            
jaroslav@1166
   249
            private final String resource;
jaroslav@1166
   250
jaroslav@1166
   251
            private Type(String r) {
jaroslav@1166
   252
                resource = r;
jaroslav@1166
   253
            }
jaroslav@1166
   254
jaroslav@1166
   255
            public Image getImage() {
jaroslav@1166
   256
                return new Image(Type.class.getResourceAsStream(resource));
jaroslav@1166
   257
            }
jaroslav@1166
   258
        }
jaroslav@1166
   259
jaroslav@1166
   260
        private ResizeOption(Type type, String displayName, int width, int height, boolean showInToolbar, boolean isDefault) {
jaroslav@1166
   261
            super();
jaroslav@1166
   262
            this.type = type;
jaroslav@1166
   263
            this.displayName = displayName;
jaroslav@1166
   264
            this.width = width;
jaroslav@1166
   265
            this.height = height;
jaroslav@1166
   266
            this.isDefault = isDefault;
jaroslav@1166
   267
        }
jaroslav@1166
   268
jaroslav@1166
   269
        static List<ResizeOption> loadAll() {
jaroslav@1166
   270
            List<ResizeOption> res = new ArrayList<ResizeOption>(10);
jaroslav@1166
   271
            res.add(ResizeOption.create(ResizeOption.Type.DESKTOP, "Desktop", 1280, 1024, true, true));
jaroslav@1166
   272
            res.add(ResizeOption.create(ResizeOption.Type.TABLET_LANDSCAPE, "Tablet Landscape", 1024, 768, true, true));
jaroslav@1166
   273
            res.add(ResizeOption.create(ResizeOption.Type.TABLET_PORTRAIT, "Tablet Portrait", 768, 1024, true, true));
jaroslav@1166
   274
            res.add(ResizeOption.create(ResizeOption.Type.SMARTPHONE_LANDSCAPE, "Smartphone Landscape", 480, 320, true, true));
jaroslav@1166
   275
            res.add(ResizeOption.create(ResizeOption.Type.SMARTPHONE_PORTRAIT, "Smartphone Portrait", 320, 480, true, true));
jaroslav@1166
   276
            res.add(ResizeOption.create(ResizeOption.Type.WIDESCREEN, "Widescreen", 1680, 1050, false, true));
jaroslav@1166
   277
            res.add(ResizeOption.create(ResizeOption.Type.NETBOOK, "Netbook", 1024, 600, false, true));
jaroslav@1166
   278
            return res;
jaroslav@1166
   279
        }
jaroslav@1166
   280
        
jaroslav@1166
   281
        /**
jaroslav@1166
   282
         * Creates a new instance.
jaroslav@1166
   283
         * @param type
jaroslav@1166
   284
         * @param displayName Display name to show in tooltip, cannot be empty.
jaroslav@1166
   285
         * @param width Screen width
jaroslav@1166
   286
         * @param height Screen height
jaroslav@1166
   287
         * @param showInToolbar True to show in web developer toolbar.
jaroslav@1166
   288
         * @param isDefault True if this is a predefined option that cannot be removed.
jaroslav@1166
   289
         * @return New instance.
jaroslav@1166
   290
         */
jaroslav@1166
   291
        public static ResizeOption create(Type type, String displayName, int width, int height, boolean showInToolbar, boolean isDefault) {
jaroslav@1166
   292
            if (width <= 0 || height <= 0) {
jaroslav@1166
   293
                throw new IllegalArgumentException("Invalid screen dimensions: " + width + " x " + height); //NOI18N
jaroslav@1166
   294
            }
jaroslav@1166
   295
            return new ResizeOption(type, displayName, width, height, showInToolbar, isDefault);
jaroslav@1166
   296
        }
jaroslav@1166
   297
        /**
jaroslav@1166
   298
         * An extra option to size the browser content to fit its window.
jaroslav@1166
   299
         */
jaroslav@1166
   300
        public static final ResizeOption SIZE_TO_FIT = new ResizeOption(Type.CUSTOM, "Size To Fit", -1, -1, true, true);
jaroslav@1166
   301
jaroslav@1166
   302
        public String getDisplayName() {
jaroslav@1166
   303
            return displayName;
jaroslav@1166
   304
        }
jaroslav@1166
   305
jaroslav@1166
   306
        public Type getType() {
jaroslav@1166
   307
            return type;
jaroslav@1166
   308
        }
jaroslav@1166
   309
jaroslav@1166
   310
        public int getWidth() {
jaroslav@1166
   311
            return width;
jaroslav@1166
   312
        }
jaroslav@1166
   313
jaroslav@1166
   314
        public int getHeight() {
jaroslav@1166
   315
            return height;
jaroslav@1166
   316
        }
jaroslav@1166
   317
jaroslav@1166
   318
        public boolean isDefault() {
jaroslav@1166
   319
            return isDefault;
jaroslav@1166
   320
        }
jaroslav@1166
   321
jaroslav@1166
   322
        @Override
jaroslav@1166
   323
        public String toString() {
jaroslav@1166
   324
            return displayName;
jaroslav@1166
   325
        }
jaroslav@1166
   326
jaroslav@1166
   327
        public String getToolTip() {
jaroslav@1166
   328
            if (width < 0 || height < 0) {
jaroslav@1166
   329
                return displayName;
jaroslav@1166
   330
            }
jaroslav@1166
   331
            StringBuilder sb = new StringBuilder();
jaroslav@1166
   332
            sb.append(width);
jaroslav@1166
   333
            sb.append(" x "); //NOI18N
jaroslav@1166
   334
            sb.append(height);
jaroslav@1166
   335
            sb.append(" ("); //NOI18N
jaroslav@1166
   336
            sb.append(displayName);
jaroslav@1166
   337
            sb.append(')'); //NOI18N
jaroslav@1166
   338
            return sb.toString();
jaroslav@1166
   339
        }
jaroslav@1166
   340
jaroslav@1166
   341
        @Override
jaroslav@1166
   342
        public boolean equals(Object obj) {
jaroslav@1166
   343
            if (obj == null) {
jaroslav@1166
   344
                return false;
jaroslav@1166
   345
            }
jaroslav@1166
   346
            if (getClass() != obj.getClass()) {
jaroslav@1166
   347
                return false;
jaroslav@1166
   348
            }
jaroslav@1166
   349
            final ResizeOption other = (ResizeOption) obj;
jaroslav@1166
   350
            if (this.type != other.type) {
jaroslav@1166
   351
                return false;
jaroslav@1166
   352
            }
jaroslav@1166
   353
            if ((this.displayName == null) ? (other.displayName != null) : !this.displayName.equals(other.displayName)) {
jaroslav@1166
   354
                return false;
jaroslav@1166
   355
            }
jaroslav@1166
   356
            if (this.width != other.width) {
jaroslav@1166
   357
                return false;
jaroslav@1166
   358
            }
jaroslav@1166
   359
            if (this.height != other.height) {
jaroslav@1166
   360
                return false;
jaroslav@1166
   361
            }
jaroslav@1166
   362
            if (this.isDefault != other.isDefault) {
jaroslav@1166
   363
                return false;
jaroslav@1166
   364
            }
jaroslav@1166
   365
            return true;
jaroslav@1166
   366
        }
jaroslav@1166
   367
jaroslav@1166
   368
        @Override
jaroslav@1166
   369
        public int hashCode() {
jaroslav@1166
   370
            int hash = 7;
jaroslav@1166
   371
            hash = 11 * hash + (this.type != null ? this.type.hashCode() : 0);
jaroslav@1166
   372
            hash = 11 * hash + (this.displayName != null ? this.displayName.hashCode() : 0);
jaroslav@1166
   373
            hash = 11 * hash + this.width;
jaroslav@1166
   374
            hash = 11 * hash + this.height;
jaroslav@1166
   375
            hash = 11 * hash + (this.isDefault ? 1 : 0);
jaroslav@1166
   376
            return hash;
jaroslav@1166
   377
        }
jaroslav@1166
   378
    }
jaroslav@1166
   379
}