Listen on changes and automatically reload whenever file next to index.html changes
1.1 --- a/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXInspect.java Fri Jul 18 15:50:06 2014 +0200
1.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXInspect.java Fri Jul 18 17:02:21 2014 +0200
1.3 @@ -59,7 +59,7 @@
1.4 * @author Jaroslav Tulach <jtulach@netbeans.org>
1.5 */
1.6 final class FXInspect implements Runnable {
1.7 - private static final Logger LOG = Logger.getLogger(FXInspect.class.getName());
1.8 + static final Logger LOG = Logger.getLogger(FXInspect.class.getName());
1.9
1.10
1.11 private final WebEngine engine;
2.1 --- a/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXToolbar.java Fri Jul 18 15:50:06 2014 +0200
2.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXToolbar.java Fri Jul 18 17:02:21 2014 +0200
2.3 @@ -42,13 +42,21 @@
2.4 */
2.5 package org.netbeans.html.boot.fx;
2.6
2.7 +import java.io.IOException;
2.8 +import java.net.URISyntaxException;
2.9 import java.util.ArrayList;
2.10 import java.util.List;
2.11 +import java.util.logging.Level;
2.12 +import java.util.prefs.Preferences;
2.13 import javafx.beans.InvalidationListener;
2.14 import javafx.beans.Observable;
2.15 import javafx.beans.value.ChangeListener;
2.16 import javafx.beans.value.ObservableValue;
2.17 import javafx.collections.FXCollections;
2.18 +import javafx.event.ActionEvent;
2.19 +import javafx.event.EventHandler;
2.20 +import javafx.scene.control.Button;
2.21 +import javafx.scene.control.CheckBox;
2.22 import javafx.scene.control.ComboBox;
2.23 import javafx.scene.control.ScrollPane;
2.24 import javafx.scene.control.Separator;
2.25 @@ -68,9 +76,10 @@
2.26 private final BorderPane container;
2.27 private final ToggleGroup resizeGroup = new ToggleGroup();
2.28 private final ComboBox<String> comboZoom = new ComboBox<String>();
2.29 + private WatchDir watcher;
2.30
2.31 - FXToolbar(WebView webView, BorderPane container) {
2.32 - this.webView = webView;
2.33 + FXToolbar(WebView wv, BorderPane container) {
2.34 + this.webView = wv;
2.35 this.container = container;
2.36
2.37 List<ResizeOption> options = ResizeOption.loadAll();
2.38 @@ -112,6 +121,34 @@
2.39 comboZoom.setValue( newZoom );
2.40 }
2.41 });
2.42 +
2.43 + getItems().add(new Separator());
2.44 + final CheckBox automatic = new CheckBox("Automatic");
2.45 + final Preferences prefs = Preferences.userNodeForPackage(FXToolbar.class);
2.46 + final String ar = "automaticReload"; // NOI18N
2.47 + automatic.setSelected(prefs.getBoolean(ar, true));
2.48 + getItems().add(automatic);
2.49 + final Button reload = new Button("Reload");
2.50 + getItems().add(reload);
2.51 + reload.setOnAction(new EventHandler<ActionEvent>() {
2.52 + @Override
2.53 + public void handle(ActionEvent event) {
2.54 + webView.getEngine().reload();
2.55 + }
2.56 + });
2.57 + automatic.setOnAction(new EventHandler<ActionEvent>() {
2.58 + @Override
2.59 + public void handle(ActionEvent event) {
2.60 + prefs.putBoolean(ar, automatic.isSelected());
2.61 + listenOnChanges(automatic.isSelected());
2.62 + }
2.63 + });
2.64 + webView.getEngine().locationProperty().addListener(new ChangeListener<String>() {
2.65 + @Override
2.66 + public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
2.67 + listenOnChanges(automatic.isSelected());
2.68 + }
2.69 + });
2.70 }
2.71
2.72 private String zoom( String zoomFactor ) {
2.73 @@ -359,4 +396,18 @@
2.74 return hash;
2.75 }
2.76 }
2.77 +
2.78 + private void listenOnChanges(boolean turnOn) {
2.79 + try {
2.80 + if (watcher != null) {
2.81 + watcher.close();
2.82 + watcher = null;
2.83 + }
2.84 + if (turnOn) {
2.85 + watcher = new WatchDir(webView.getEngine());
2.86 + }
2.87 + } catch (Exception ex) {
2.88 + FXInspect.LOG.log(Level.SEVERE, null, ex);
2.89 + }
2.90 + }
2.91 }
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/WatchDir.java Fri Jul 18 17:02:21 2014 +0200
3.3 @@ -0,0 +1,117 @@
3.4 +/**
3.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3.6 + *
3.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
3.8 + *
3.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
3.10 + * Other names may be trademarks of their respective owners.
3.11 + *
3.12 + * The contents of this file are subject to the terms of either the GNU
3.13 + * General Public License Version 2 only ("GPL") or the Common
3.14 + * Development and Distribution License("CDDL") (collectively, the
3.15 + * "License"). You may not use this file except in compliance with the
3.16 + * License. You can obtain a copy of the License at
3.17 + * http://www.netbeans.org/cddl-gplv2.html
3.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
3.19 + * specific language governing permissions and limitations under the
3.20 + * License. When distributing the software, include this License Header
3.21 + * Notice in each file and include the License file at
3.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
3.23 + * particular file as subject to the "Classpath" exception as provided
3.24 + * by Oracle in the GPL Version 2 section of the License file that
3.25 + * accompanied this code. If applicable, add the following below the
3.26 + * License Header, with the fields enclosed by brackets [] replaced by
3.27 + * your own identifying information:
3.28 + * "Portions Copyrighted [year] [name of copyright owner]"
3.29 + *
3.30 + * Contributor(s):
3.31 + *
3.32 + * The Original Software is NetBeans. The Initial Developer of the Original
3.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
3.34 + *
3.35 + * If you wish your version of this file to be governed by only the CDDL
3.36 + * or only the GPL Version 2, indicate your decision by adding
3.37 + * "[Contributor] elects to include this software in this distribution
3.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
3.39 + * single choice of license, a recipient has the option to distribute
3.40 + * your version of this file under either the CDDL, the GPL Version 2 or
3.41 + * to extend the choice of license to its licensees as provided above.
3.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
3.43 + * Version 2 license, then the option applies only if the new code is
3.44 + * made subject to such option by the copyright holder.
3.45 + */
3.46 +package org.netbeans.html.boot.fx;
3.47 +
3.48 +import java.io.IOException;
3.49 +import java.net.URI;
3.50 +import java.net.URISyntaxException;
3.51 +import java.nio.file.ClosedWatchServiceException;
3.52 +import java.nio.file.Path;
3.53 +import java.nio.file.Paths;
3.54 +import java.nio.file.StandardWatchEventKinds;
3.55 +import java.nio.file.WatchKey;
3.56 +import java.nio.file.WatchService;
3.57 +import java.util.logging.Level;
3.58 +import java.util.logging.Logger;
3.59 +import javafx.application.Platform;
3.60 +import javafx.scene.web.WebEngine;
3.61 +
3.62 +/**
3.63 + *
3.64 + * @author Jaroslav Tulach
3.65 + */
3.66 +final class WatchDir implements Runnable {
3.67 + private final Path dir;
3.68 + private final WatchKey key;
3.69 + private final WatchService ws;
3.70 + private final Thread watcher;
3.71 + private final WebEngine engine;
3.72 +
3.73 + WatchDir(WebEngine eng) throws URISyntaxException, IOException {
3.74 + dir = Paths.get(new URI(eng.getLocation())).getParent();
3.75 + engine = eng;
3.76 + ws = dir.getFileSystem().newWatchService();
3.77 + key = dir.register(ws,
3.78 + StandardWatchEventKinds.ENTRY_CREATE,
3.79 + StandardWatchEventKinds.ENTRY_DELETE,
3.80 + StandardWatchEventKinds.ENTRY_MODIFY
3.81 + );
3.82 + watcher = new Thread(this, "Watching files in " + dir);
3.83 + watcher.setDaemon(true);
3.84 + watcher.setPriority(Thread.MIN_PRIORITY);
3.85 + watcher.start();
3.86 + }
3.87 +
3.88 + public void close() throws IOException {
3.89 + key.cancel();
3.90 + ws.close();
3.91 + watcher.interrupt();
3.92 + }
3.93 +
3.94 + @Override
3.95 + public void run() {
3.96 + if (Platform.isFxApplicationThread()) {
3.97 + engine.reload();
3.98 + return;
3.99 + }
3.100 + try {
3.101 + while (key.isValid()) {
3.102 + WatchKey changed;
3.103 + try {
3.104 + changed = ws.take();
3.105 + if (changed != key || changed.pollEvents().isEmpty()) {
3.106 + continue;
3.107 + }
3.108 + } catch (ClosedWatchServiceException ex) {
3.109 + continue;
3.110 + }
3.111 + Platform.runLater(this);
3.112 + if (!key.reset()) {
3.113 + break;
3.114 + }
3.115 + }
3.116 + } catch (InterruptedException ex) {
3.117 + FXInspect.LOG.log(Level.SEVERE, null, ex);
3.118 + }
3.119 + }
3.120 +}