launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/BrowserToolbar.java
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/BrowserToolbar.java Thu May 30 06:09:42 2013 +0200
1.3 @@ -0,0 +1,362 @@
1.4 +/**
1.5 + * Back 2 Browser Bytecode Translator
1.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
1.7 + *
1.8 + * This program is free software: you can redistribute it and/or modify
1.9 + * it under the terms of the GNU General Public License as published by
1.10 + * the Free Software Foundation, version 2 of the License.
1.11 + *
1.12 + * This program is distributed in the hope that it will be useful,
1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.15 + * GNU General Public License for more details.
1.16 + *
1.17 + * You should have received a copy of the GNU General Public License
1.18 + * along with this program. Look for COPYING file in the top folder.
1.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
1.20 + */
1.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
1.22 +
1.23 +import java.util.ArrayList;
1.24 +import java.util.List;
1.25 +import javafx.beans.InvalidationListener;
1.26 +import javafx.beans.Observable;
1.27 +import javafx.beans.value.ChangeListener;
1.28 +import javafx.beans.value.ObservableValue;
1.29 +import javafx.collections.FXCollections;
1.30 +import javafx.scene.control.ComboBox;
1.31 +import javafx.scene.control.ScrollPane;
1.32 +import javafx.scene.control.Separator;
1.33 +import javafx.scene.control.Toggle;
1.34 +import javafx.scene.control.ToggleButton;
1.35 +import javafx.scene.control.ToggleGroup;
1.36 +import javafx.scene.control.ToolBar;
1.37 +import javafx.scene.control.Tooltip;
1.38 +import javafx.scene.image.Image;
1.39 +import javafx.scene.image.ImageView;
1.40 +import javafx.scene.layout.Pane;
1.41 +import javafx.scene.web.WebView;
1.42 +
1.43 +final class BrowserToolbar extends ToolBar {
1.44 + private final ArrayList<ResizeBtn> resizeButtons;
1.45 + private final WebView webView;
1.46 + private final Pane container;
1.47 + private final ToggleGroup resizeGroup = new ToggleGroup();
1.48 + private final ComboBox<String> comboZoom = new ComboBox<String>();
1.49 +
1.50 + private BrowserToolbar( WebView webView, Pane container ) {
1.51 + this.webView = webView;
1.52 + this.container = container;
1.53 +
1.54 + List<ResizeOption> options = ResizeOption.loadAll();
1.55 + options.add( 0, ResizeOption.SIZE_TO_FIT );
1.56 + resizeButtons = new ArrayList<ResizeBtn>( options.size() );
1.57 +
1.58 + for( ResizeOption ro : options ) {
1.59 + ResizeBtn button = new ResizeBtn(ro);
1.60 + resizeButtons.add( button );
1.61 + resizeGroup.getToggles().add( button );
1.62 + getItems().add( button );
1.63 + }
1.64 + resizeButtons.get( 0 ).setSelected( true );
1.65 + resizeGroup.selectedToggleProperty().addListener( new InvalidationListener() {
1.66 +
1.67 + @Override
1.68 + public void invalidated( Observable o ) {
1.69 + resize();
1.70 + }
1.71 + });
1.72 +
1.73 + getItems().add( new Separator() );
1.74 +
1.75 + getItems().add( comboZoom );
1.76 + ArrayList<String> zoomModel = new ArrayList<String>( 6 );
1.77 + zoomModel.add( "200%" ); //NOI18N
1.78 + zoomModel.add( "150%" ); //NOI18N
1.79 + zoomModel.add( "100%" ); //NOI18N
1.80 + zoomModel.add( "75%" ); //NOI18N
1.81 + zoomModel.add( "50%" ); //NOI18N
1.82 + comboZoom.setItems( FXCollections.observableList( zoomModel ) );
1.83 + comboZoom.setEditable( true );
1.84 + comboZoom.setValue( "100%" ); //NOI18N
1.85 + comboZoom.valueProperty().addListener( new ChangeListener<String>() {
1.86 +
1.87 + @Override
1.88 + public void changed( ObservableValue<? extends String> ov, String t, String t1 ) {
1.89 + String newZoom = zoom( t1 );
1.90 + comboZoom.setValue( newZoom );
1.91 + }
1.92 + });
1.93 +
1.94 + /*
1.95 + final ToggleButton btnSelMode = new ToggleButton( null, new ImageView(
1.96 + new Image(BrowserToolbar.class.getResourceAsStream("selectionMode.png"))
1.97 + ));
1.98 + btnSelMode.setTooltip( new Tooltip( "Toggle selection mode" ) );
1.99 + btnSelMode.selectedProperty().addListener( new InvalidationListener() {
1.100 +
1.101 + @Override
1.102 + public void invalidated( Observable o ) {
1.103 + toggleSelectionMode( btnSelMode.isSelected() );
1.104 + }
1.105 + });
1.106 + getItems().add( btnSelMode );
1.107 + */
1.108 + }
1.109 +
1.110 + public static ToolBar create( WebView view, Pane container ) {
1.111 + return new BrowserToolbar( view, container );
1.112 + }
1.113 +
1.114 + private String zoom( String zoomFactor ) {
1.115 + if( zoomFactor.trim().isEmpty() )
1.116 + return null;
1.117 +
1.118 + try {
1.119 + zoomFactor = zoomFactor.replaceAll( "\\%", ""); //NOI18N
1.120 + zoomFactor = zoomFactor.trim();
1.121 + double zoom = Double.parseDouble( zoomFactor );
1.122 + zoom = Math.abs( zoom )/100;
1.123 + if( zoom <= 0.0 )
1.124 + return null;
1.125 + webView.impl_setScale( zoom );
1.126 + return (int)(100*zoom) + "%"; //NOI18N
1.127 + } catch( NumberFormatException nfe ) {
1.128 + //ignore
1.129 + }
1.130 + return null;
1.131 + }
1.132 +
1.133 + private void resize() {
1.134 + Toggle selection = resizeGroup.getSelectedToggle();
1.135 + if( selection instanceof ResizeBtn ) {
1.136 + ResizeOption ro = ((ResizeBtn)selection).getResizeOption();
1.137 + if( ro == ResizeOption.SIZE_TO_FIT ) {
1.138 + _autofit();
1.139 + } else {
1.140 + _resize( ro.getWidth(), ro.getHeight() );
1.141 + }
1.142 + }
1.143 +
1.144 + }
1.145 +
1.146 + private void _resize( final double width, final double height ) {
1.147 + ScrollPane scroll;
1.148 + if( !(container.getChildren().get( 0) instanceof ScrollPane) ) {
1.149 + scroll = new ScrollPane();
1.150 + scroll.setContent( webView );
1.151 + container.getChildren().clear();
1.152 + container.getChildren().add( scroll );
1.153 + } else {
1.154 + scroll = ( ScrollPane ) container.getChildren().get( 0 );
1.155 + }
1.156 + scroll.setPrefViewportWidth( width );
1.157 + scroll.setPrefViewportHeight(height );
1.158 + webView.setMaxWidth( width );
1.159 + webView.setMaxHeight( height );
1.160 + webView.setMinWidth( width );
1.161 + webView.setMinHeight( height );
1.162 + }
1.163 +
1.164 + private void _autofit() {
1.165 + if( container.getChildren().get( 0) instanceof ScrollPane ) {
1.166 + container.getChildren().clear();
1.167 + container.getChildren().add( webView );
1.168 + }
1.169 + webView.setMaxWidth( Integer.MAX_VALUE );
1.170 + webView.setMaxHeight( Integer.MAX_VALUE );
1.171 + webView.setMinWidth( -1 );
1.172 + webView.setMinHeight( -1 );
1.173 + webView.autosize();
1.174 + }
1.175 +
1.176 + private void toggleSelectionMode( boolean selMode ) {
1.177 + System.err.println( "selection mode: " + selMode );
1.178 + }
1.179 +
1.180 + /**
1.181 + * Button to resize the browser window.
1.182 + * Taken from NetBeans. Kept GPLwithCPEx license.
1.183 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
1.184 + *
1.185 + * @author S. Aubrecht
1.186 + */
1.187 + static final class ResizeBtn extends ToggleButton {
1.188 +
1.189 + private final ResizeOption resizeOption;
1.190 +
1.191 + ResizeBtn(ResizeOption resizeOption) {
1.192 + super(null, new ImageView(toImage(resizeOption)));
1.193 + this.resizeOption = resizeOption;
1.194 + setTooltip(new Tooltip(resizeOption.getToolTip()));
1.195 + }
1.196 +
1.197 + ResizeOption getResizeOption() {
1.198 + return resizeOption;
1.199 + }
1.200 +
1.201 + static Image toImage(ResizeOption ro) {
1.202 + if (ro == ResizeOption.SIZE_TO_FIT) {
1.203 + return ResizeOption.Type.CUSTOM.getImage();
1.204 + }
1.205 + return ro.getType().getImage();
1.206 + }
1.207 + }
1.208 +
1.209 + /**
1.210 + * Immutable value class describing a single button to resize web browser window.
1.211 + * Taken from NetBeans. Kept GPLwithCPEx license.
1.212 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
1.213 + *
1.214 + * @author S. Aubrecht
1.215 + */
1.216 + static final class ResizeOption {
1.217 +
1.218 + private final Type type;
1.219 + private final String displayName;
1.220 + private final int width;
1.221 + private final int height;
1.222 + private final boolean isDefault;
1.223 +
1.224 + enum Type {
1.225 + DESKTOP("desktop.png"),
1.226 + TABLET_PORTRAIT("tabletPortrait.png"),
1.227 + TABLET_LANDSCAPE("tabletLandscape.png"),
1.228 + SMARTPHONE_PORTRAIT("handheldPortrait.png"),
1.229 + SMARTPHONE_LANDSCAPE("handheldLandscape.png"),
1.230 + WIDESCREEN("widescreen.png"),
1.231 + NETBOOK("netbook.png"),
1.232 + CUSTOM("sizeToFit.png");
1.233 +
1.234 +
1.235 + private final String resource;
1.236 +
1.237 + private Type(String r) {
1.238 + resource = r;
1.239 + }
1.240 +
1.241 + public Image getImage() {
1.242 + return new Image(Type.class.getResourceAsStream(resource));
1.243 + }
1.244 + }
1.245 +
1.246 + private ResizeOption(Type type, String displayName, int width, int height, boolean showInToolbar, boolean isDefault) {
1.247 + super();
1.248 + this.type = type;
1.249 + this.displayName = displayName;
1.250 + this.width = width;
1.251 + this.height = height;
1.252 + this.isDefault = isDefault;
1.253 + }
1.254 +
1.255 + static List<ResizeOption> loadAll() {
1.256 + List<ResizeOption> res = new ArrayList<ResizeOption>(10);
1.257 + res.add(ResizeOption.create(ResizeOption.Type.DESKTOP, "Desktop", 1280, 1024, true, true));
1.258 + res.add(ResizeOption.create(ResizeOption.Type.TABLET_LANDSCAPE, "Tablet Landscape", 1024, 768, true, true));
1.259 + res.add(ResizeOption.create(ResizeOption.Type.TABLET_PORTRAIT, "Tablet Portrait", 768, 1024, true, true));
1.260 + res.add(ResizeOption.create(ResizeOption.Type.SMARTPHONE_LANDSCAPE, "Smartphone Landscape", 480, 320, true, true));
1.261 + res.add(ResizeOption.create(ResizeOption.Type.SMARTPHONE_PORTRAIT, "Smartphone Portrait", 320, 480, true, true));
1.262 + res.add(ResizeOption.create(ResizeOption.Type.WIDESCREEN, "Widescreen", 1680, 1050, false, true));
1.263 + res.add(ResizeOption.create(ResizeOption.Type.NETBOOK, "Netbook", 1024, 600, false, true));
1.264 + return res;
1.265 + }
1.266 +
1.267 + /**
1.268 + * Creates a new instance.
1.269 + * @param type
1.270 + * @param displayName Display name to show in tooltip, cannot be empty.
1.271 + * @param width Screen width
1.272 + * @param height Screen height
1.273 + * @param showInToolbar True to show in web developer toolbar.
1.274 + * @param isDefault True if this is a predefined option that cannot be removed.
1.275 + * @return New instance.
1.276 + */
1.277 + public static ResizeOption create(Type type, String displayName, int width, int height, boolean showInToolbar, boolean isDefault) {
1.278 + if (width <= 0 || height <= 0) {
1.279 + throw new IllegalArgumentException("Invalid screen dimensions: " + width + " x " + height); //NOI18N
1.280 + }
1.281 + return new ResizeOption(type, displayName, width, height, showInToolbar, isDefault);
1.282 + }
1.283 + /**
1.284 + * An extra option to size the browser content to fit its window.
1.285 + */
1.286 + public static final ResizeOption SIZE_TO_FIT = new ResizeOption(Type.CUSTOM, "Size To Fit", -1, -1, true, true);
1.287 +
1.288 + public String getDisplayName() {
1.289 + return displayName;
1.290 + }
1.291 +
1.292 + public Type getType() {
1.293 + return type;
1.294 + }
1.295 +
1.296 + public int getWidth() {
1.297 + return width;
1.298 + }
1.299 +
1.300 + public int getHeight() {
1.301 + return height;
1.302 + }
1.303 +
1.304 + public boolean isDefault() {
1.305 + return isDefault;
1.306 + }
1.307 +
1.308 + @Override
1.309 + public String toString() {
1.310 + return displayName;
1.311 + }
1.312 +
1.313 + public String getToolTip() {
1.314 + if (width < 0 || height < 0) {
1.315 + return displayName;
1.316 + }
1.317 + StringBuilder sb = new StringBuilder();
1.318 + sb.append(width);
1.319 + sb.append(" x "); //NOI18N
1.320 + sb.append(height);
1.321 + sb.append(" ("); //NOI18N
1.322 + sb.append(displayName);
1.323 + sb.append(')'); //NOI18N
1.324 + return sb.toString();
1.325 + }
1.326 +
1.327 + @Override
1.328 + public boolean equals(Object obj) {
1.329 + if (obj == null) {
1.330 + return false;
1.331 + }
1.332 + if (getClass() != obj.getClass()) {
1.333 + return false;
1.334 + }
1.335 + final ResizeOption other = (ResizeOption) obj;
1.336 + if (this.type != other.type) {
1.337 + return false;
1.338 + }
1.339 + if ((this.displayName == null) ? (other.displayName != null) : !this.displayName.equals(other.displayName)) {
1.340 + return false;
1.341 + }
1.342 + if (this.width != other.width) {
1.343 + return false;
1.344 + }
1.345 + if (this.height != other.height) {
1.346 + return false;
1.347 + }
1.348 + if (this.isDefault != other.isDefault) {
1.349 + return false;
1.350 + }
1.351 + return true;
1.352 + }
1.353 +
1.354 + @Override
1.355 + public int hashCode() {
1.356 + int hash = 7;
1.357 + hash = 11 * hash + (this.type != null ? this.type.hashCode() : 0);
1.358 + hash = 11 * hash + (this.displayName != null ? this.displayName.hashCode() : 0);
1.359 + hash = 11 * hash + this.width;
1.360 + hash = 11 * hash + this.height;
1.361 + hash = 11 * hash + (this.isDefault ? 1 : 0);
1.362 + return hash;
1.363 + }
1.364 + }
1.365 +}