launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/BrowserToolbar.java
2 * Back 2 Browser Bytecode Translator
3 * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 2 of the License.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. Look for COPYING file in the top folder.
16 * If not, see http://opensource.org/licenses/GPL-2.0.
18 package org.apidesign.bck2brwsr.launcher.fximpl;
20 import java.util.ArrayList;
21 import java.util.List;
22 import javafx.beans.InvalidationListener;
23 import javafx.beans.Observable;
24 import javafx.beans.value.ChangeListener;
25 import javafx.beans.value.ObservableValue;
26 import javafx.collections.FXCollections;
27 import javafx.scene.control.ComboBox;
28 import javafx.scene.control.ScrollPane;
29 import javafx.scene.control.Separator;
30 import javafx.scene.control.Toggle;
31 import javafx.scene.control.ToggleButton;
32 import javafx.scene.control.ToggleGroup;
33 import javafx.scene.control.ToolBar;
34 import javafx.scene.control.Tooltip;
35 import javafx.scene.image.Image;
36 import javafx.scene.image.ImageView;
37 import javafx.scene.layout.Pane;
38 import javafx.scene.web.WebEngine;
39 import javafx.scene.web.WebView;
41 final class BrowserToolbar extends ToolBar {
42 private final ArrayList<ResizeBtn> resizeButtons;
43 private final WebView webView;
44 private final Pane container;
45 private final ToggleGroup resizeGroup = new ToggleGroup();
46 private final ComboBox<String> comboZoom = new ComboBox<String>();
48 BrowserToolbar(WebView webView, Pane container, boolean useFirebug, final WebDebug webDebug) {
49 this.webView = webView;
50 this.container = container;
52 List<ResizeOption> options = ResizeOption.loadAll();
53 options.add( 0, ResizeOption.SIZE_TO_FIT );
54 resizeButtons = new ArrayList<ResizeBtn>( options.size() );
56 for( ResizeOption ro : options ) {
57 ResizeBtn button = new ResizeBtn(ro);
58 resizeButtons.add( button );
59 resizeGroup.getToggles().add( button );
60 getItems().add( button );
62 resizeButtons.get( 0 ).setSelected( true );
63 resizeGroup.selectedToggleProperty().addListener( new InvalidationListener() {
66 public void invalidated( Observable o ) {
71 getItems().add( new Separator() );
73 getItems().add( comboZoom );
74 ArrayList<String> zoomModel = new ArrayList<String>( 6 );
75 zoomModel.add( "200%" ); //NOI18N
76 zoomModel.add( "150%" ); //NOI18N
77 zoomModel.add( "100%" ); //NOI18N
78 zoomModel.add( "75%" ); //NOI18N
79 zoomModel.add( "50%" ); //NOI18N
80 comboZoom.setItems( FXCollections.observableList( zoomModel ) );
81 comboZoom.setEditable( true );
82 comboZoom.setValue( "100%" ); //NOI18N
83 comboZoom.valueProperty().addListener( new ChangeListener<String>() {
86 public void changed( ObservableValue<? extends String> ov, String t, String t1 ) {
87 String newZoom = zoom( t1 );
88 comboZoom.setValue( newZoom );
93 getItems().add(new Separator());
95 final ToggleButton firebug = new ToggleButton(null, new ImageView(
96 new Image(BrowserToolbar.class.getResourceAsStream("firebug.png"))
98 firebug.setTooltip(new Tooltip("Show/Hide firebug"));
99 firebug.selectedProperty().addListener(new InvalidationListener() {
101 public void invalidated(Observable o) {
102 toggleFireBug(firebug.isSelected());
105 getItems().add(firebug);
108 if (webDebug != null) {
109 final ToggleButton btnSelMode = new ToggleButton(null, new ImageView(
110 new Image(BrowserToolbar.class.getResourceAsStream("selectionMode.png"))));
111 btnSelMode.setTooltip(new Tooltip("Toggle selection mode"));
112 btnSelMode.selectedProperty().addListener(new InvalidationListener() {
114 public void invalidated(Observable o) {
115 toggleSelectionMode(webDebug, btnSelMode.isSelected());
118 getItems().add(btnSelMode);
122 private String zoom( String zoomFactor ) {
123 if( zoomFactor.trim().isEmpty() )
127 zoomFactor = zoomFactor.replaceAll( "\\%", ""); //NOI18N
128 zoomFactor = zoomFactor.trim();
129 double zoom = Double.parseDouble( zoomFactor );
130 zoom = Math.abs( zoom )/100;
133 webView.impl_setScale( zoom );
134 return (int)(100*zoom) + "%"; //NOI18N
135 } catch( NumberFormatException nfe ) {
141 private void resize() {
142 Toggle selection = resizeGroup.getSelectedToggle();
143 if( selection instanceof ResizeBtn ) {
144 ResizeOption ro = ((ResizeBtn)selection).getResizeOption();
145 if( ro == ResizeOption.SIZE_TO_FIT ) {
148 _resize( ro.getWidth(), ro.getHeight() );
154 private void _resize( final double width, final double height ) {
156 if( !(container.getChildren().get( 0) instanceof ScrollPane) ) {
157 scroll = new ScrollPane();
158 scroll.setContent( webView );
159 container.getChildren().clear();
160 container.getChildren().add( scroll );
162 scroll = ( ScrollPane ) container.getChildren().get( 0 );
164 scroll.setPrefViewportWidth( width );
165 scroll.setPrefViewportHeight(height );
166 webView.setMaxWidth( width );
167 webView.setMaxHeight( height );
168 webView.setMinWidth( width );
169 webView.setMinHeight( height );
172 private void _autofit() {
173 if( container.getChildren().get( 0) instanceof ScrollPane ) {
174 container.getChildren().clear();
175 container.getChildren().add( webView );
177 webView.setMaxWidth( Integer.MAX_VALUE );
178 webView.setMaxHeight( Integer.MAX_VALUE );
179 webView.setMinWidth( -1 );
180 webView.setMinHeight( -1 );
184 private void toggleSelectionMode(WebDebug dbg, boolean selMode) {
186 dbg.call("{\"message\":\"selection_mode\",\"selectionMode\":" + selMode + "}");
189 final void toggleFireBug(boolean enable) {
190 WebEngine eng = webView.getEngine();
191 Object installed = eng.executeScript("window.Firebug");
192 if ("undefined".equals(installed)) {
193 StringBuilder sb = new StringBuilder();
194 sb.append("var scr = window.document.createElement('script');\n");
195 sb.append("scr.type = 'text/javascript';\n");
196 sb.append("scr.src = 'https://getfirebug.com/firebug-lite.js';\n");
197 sb.append("scr.text = '{ startOpened: true }';\n");
198 sb.append("var head = window.document.getElementsByTagName('head')[0];");
199 sb.append("head.appendChild(scr);\n");
200 sb.append("var html = window.document.getElementsByTagName('html')[0];");
201 sb.append("html.debug = true;\n");
202 eng.executeScript(sb.toString());
205 eng.executeScript("Firebug.chrome.open()");
207 eng.executeScript("Firebug.chrome.close()");
213 * Button to resize the browser window.
214 * Taken from NetBeans. Kept GPLwithCPEx license.
215 * Portions Copyrighted 2012 Sun Microsystems, Inc.
217 * @author S. Aubrecht
219 static final class ResizeBtn extends ToggleButton {
221 private final ResizeOption resizeOption;
223 ResizeBtn(ResizeOption resizeOption) {
224 super(null, new ImageView(toImage(resizeOption)));
225 this.resizeOption = resizeOption;
226 setTooltip(new Tooltip(resizeOption.getToolTip()));
229 ResizeOption getResizeOption() {
233 static Image toImage(ResizeOption ro) {
234 if (ro == ResizeOption.SIZE_TO_FIT) {
235 return ResizeOption.Type.CUSTOM.getImage();
237 return ro.getType().getImage();
242 * Immutable value class describing a single button to resize web browser window.
243 * Taken from NetBeans. Kept GPLwithCPEx license.
244 * Portions Copyrighted 2012 Sun Microsystems, Inc.
246 * @author S. Aubrecht
248 static final class ResizeOption {
250 private final Type type;
251 private final String displayName;
252 private final int width;
253 private final int height;
254 private final boolean isDefault;
257 DESKTOP("desktop.png"),
258 TABLET_PORTRAIT("tabletPortrait.png"),
259 TABLET_LANDSCAPE("tabletLandscape.png"),
260 SMARTPHONE_PORTRAIT("handheldPortrait.png"),
261 SMARTPHONE_LANDSCAPE("handheldLandscape.png"),
262 WIDESCREEN("widescreen.png"),
263 NETBOOK("netbook.png"),
264 CUSTOM("sizeToFit.png");
267 private final String resource;
269 private Type(String r) {
273 public Image getImage() {
274 return new Image(Type.class.getResourceAsStream(resource));
278 private ResizeOption(Type type, String displayName, int width, int height, boolean showInToolbar, boolean isDefault) {
281 this.displayName = displayName;
283 this.height = height;
284 this.isDefault = isDefault;
287 static List<ResizeOption> loadAll() {
288 List<ResizeOption> res = new ArrayList<ResizeOption>(10);
289 res.add(ResizeOption.create(ResizeOption.Type.DESKTOP, "Desktop", 1280, 1024, true, true));
290 res.add(ResizeOption.create(ResizeOption.Type.TABLET_LANDSCAPE, "Tablet Landscape", 1024, 768, true, true));
291 res.add(ResizeOption.create(ResizeOption.Type.TABLET_PORTRAIT, "Tablet Portrait", 768, 1024, true, true));
292 res.add(ResizeOption.create(ResizeOption.Type.SMARTPHONE_LANDSCAPE, "Smartphone Landscape", 480, 320, true, true));
293 res.add(ResizeOption.create(ResizeOption.Type.SMARTPHONE_PORTRAIT, "Smartphone Portrait", 320, 480, true, true));
294 res.add(ResizeOption.create(ResizeOption.Type.WIDESCREEN, "Widescreen", 1680, 1050, false, true));
295 res.add(ResizeOption.create(ResizeOption.Type.NETBOOK, "Netbook", 1024, 600, false, true));
300 * Creates a new instance.
302 * @param displayName Display name to show in tooltip, cannot be empty.
303 * @param width Screen width
304 * @param height Screen height
305 * @param showInToolbar True to show in web developer toolbar.
306 * @param isDefault True if this is a predefined option that cannot be removed.
307 * @return New instance.
309 public static ResizeOption create(Type type, String displayName, int width, int height, boolean showInToolbar, boolean isDefault) {
310 if (width <= 0 || height <= 0) {
311 throw new IllegalArgumentException("Invalid screen dimensions: " + width + " x " + height); //NOI18N
313 return new ResizeOption(type, displayName, width, height, showInToolbar, isDefault);
316 * An extra option to size the browser content to fit its window.
318 public static final ResizeOption SIZE_TO_FIT = new ResizeOption(Type.CUSTOM, "Size To Fit", -1, -1, true, true);
320 public String getDisplayName() {
324 public Type getType() {
328 public int getWidth() {
332 public int getHeight() {
336 public boolean isDefault() {
341 public String toString() {
345 public String getToolTip() {
346 if (width < 0 || height < 0) {
349 StringBuilder sb = new StringBuilder();
351 sb.append(" x "); //NOI18N
353 sb.append(" ("); //NOI18N
354 sb.append(displayName);
355 sb.append(')'); //NOI18N
356 return sb.toString();
360 public boolean equals(Object obj) {
364 if (getClass() != obj.getClass()) {
367 final ResizeOption other = (ResizeOption) obj;
368 if (this.type != other.type) {
371 if ((this.displayName == null) ? (other.displayName != null) : !this.displayName.equals(other.displayName)) {
374 if (this.width != other.width) {
377 if (this.height != other.height) {
380 if (this.isDefault != other.isDefault) {
387 public int hashCode() {
389 hash = 11 * hash + (this.type != null ? this.type.hashCode() : 0);
390 hash = 11 * hash + (this.displayName != null ? this.displayName.hashCode() : 0);
391 hash = 11 * hash + this.width;
392 hash = 11 * hash + this.height;
393 hash = 11 * hash + (this.isDefault ? 1 : 0);