boot-fx/src/main/java/org/netbeans/html/boot/fx/FXBrwsr.java
author Jaroslav Tulach <jaroslav.tulach@netbeans.org>
Fri, 07 Feb 2014 07:44:34 +0100
changeset 551 7ca2253fa86d
parent 534 15907d1499fb
child 636 d31666353dc4
permissions -rw-r--r--
Updating copyright headers to mention current year
jaroslav@288
     1
/**
jaroslav@358
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jaroslav@288
     3
 *
jaroslav@551
     4
 * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
jaroslav@288
     5
 *
jaroslav@358
     6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
jaroslav@358
     7
 * Other names may be trademarks of their respective owners.
jaroslav@288
     8
 *
jaroslav@358
     9
 * The contents of this file are subject to the terms of either the GNU
jaroslav@358
    10
 * General Public License Version 2 only ("GPL") or the Common
jaroslav@358
    11
 * Development and Distribution License("CDDL") (collectively, the
jaroslav@358
    12
 * "License"). You may not use this file except in compliance with the
jaroslav@358
    13
 * License. You can obtain a copy of the License at
jaroslav@358
    14
 * http://www.netbeans.org/cddl-gplv2.html
jaroslav@358
    15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jaroslav@358
    16
 * specific language governing permissions and limitations under the
jaroslav@358
    17
 * License.  When distributing the software, include this License Header
jaroslav@358
    18
 * Notice in each file and include the License file at
jaroslav@358
    19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
jaroslav@358
    20
 * particular file as subject to the "Classpath" exception as provided
jaroslav@358
    21
 * by Oracle in the GPL Version 2 section of the License file that
jaroslav@358
    22
 * accompanied this code. If applicable, add the following below the
jaroslav@358
    23
 * License Header, with the fields enclosed by brackets [] replaced by
jaroslav@358
    24
 * your own identifying information:
jaroslav@358
    25
 * "Portions Copyrighted [year] [name of copyright owner]"
jaroslav@358
    26
 *
jaroslav@358
    27
 * Contributor(s):
jaroslav@358
    28
 *
jaroslav@358
    29
 * The Original Software is NetBeans. The Initial Developer of the Original
jaroslav@551
    30
 * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
jaroslav@358
    31
 *
jaroslav@358
    32
 * If you wish your version of this file to be governed by only the CDDL
jaroslav@358
    33
 * or only the GPL Version 2, indicate your decision by adding
jaroslav@358
    34
 * "[Contributor] elects to include this software in this distribution
jaroslav@358
    35
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
jaroslav@358
    36
 * single choice of license, a recipient has the option to distribute
jaroslav@358
    37
 * your version of this file under either the CDDL, the GPL Version 2 or
jaroslav@358
    38
 * to extend the choice of license to its licensees as provided above.
jaroslav@358
    39
 * However, if you add GPL Version 2 code and therefore, elected the GPL
jaroslav@358
    40
 * Version 2 license, then the option applies only if the new code is
jaroslav@358
    41
 * made subject to such option by the copyright holder.
jaroslav@288
    42
 */
jaroslav@362
    43
package org.netbeans.html.boot.fx;
jaroslav@288
    44
jaroslav@288
    45
import java.net.URL;
jaroslav@288
    46
import java.util.concurrent.CountDownLatch;
jaroslav@288
    47
import java.util.concurrent.Executors;
jaroslav@318
    48
import java.util.logging.Level;
jaroslav@318
    49
import java.util.logging.Logger;
jaroslav@288
    50
import javafx.application.Application;
jaroslav@288
    51
import javafx.application.Platform;
jaroslav@288
    52
import javafx.beans.value.ChangeListener;
jaroslav@288
    53
import javafx.beans.value.ObservableValue;
jaroslav@288
    54
import javafx.concurrent.Worker;
jaroslav@288
    55
import javafx.event.ActionEvent;
jaroslav@288
    56
import javafx.event.EventHandler;
jaroslav@288
    57
import javafx.geometry.Insets;
jaroslav@288
    58
import javafx.geometry.Pos;
jaroslav@288
    59
import javafx.scene.Scene;
jaroslav@288
    60
import javafx.scene.control.Button;
jaroslav@288
    61
import javafx.scene.layout.BorderPane;
jaroslav@288
    62
import javafx.scene.layout.VBox;
jaroslav@288
    63
import javafx.scene.text.Text;
jaroslav@288
    64
import javafx.scene.web.WebEvent;
jaroslav@288
    65
import javafx.scene.web.WebView;
jaroslav@288
    66
import javafx.stage.Modality;
jaroslav@288
    67
import javafx.stage.Stage;
jaroslav@288
    68
jaroslav@534
    69
/** This is an implementation class, to implement browser builder API. Just
jaroslav@534
    70
 * include this JAR on classpath and the browser builder API will find
jaroslav@288
    71
 * this implementation automatically.
jaroslav@288
    72
 */
jaroslav@288
    73
public class FXBrwsr extends Application {
jaroslav@318
    74
    private static final Logger LOG = Logger.getLogger(FXBrwsr.class.getName());
jaroslav@288
    75
    private static FXBrwsr INSTANCE;
jaroslav@288
    76
    private static final CountDownLatch FINISHED = new CountDownLatch(1);
jaroslav@288
    77
    private BorderPane root;
jaroslav@288
    78
jaroslav@288
    79
    public static synchronized WebView findWebView(final URL url, final FXPresenter onLoad) {
jaroslav@288
    80
        if (INSTANCE == null) {
jaroslav@288
    81
            Executors.newFixedThreadPool(1).submit(new Runnable() {
jaroslav@288
    82
                @Override
jaroslav@288
    83
                public void run() {
jaroslav@288
    84
                    try {
jaroslav@288
    85
                        FXBrwsr.launch(FXBrwsr.class);
jaroslav@288
    86
                    } catch (Throwable ex) {
jaroslav@288
    87
                        ex.printStackTrace();
jaroslav@288
    88
                    } finally {
jaroslav@288
    89
                        FINISHED.countDown();
jaroslav@288
    90
                    }
jaroslav@288
    91
                }
jaroslav@288
    92
            });
jaroslav@288
    93
        }
jaroslav@288
    94
        while (INSTANCE == null) {
jaroslav@288
    95
            try {
jaroslav@288
    96
                FXBrwsr.class.wait();
jaroslav@288
    97
            } catch (InterruptedException ex) {
jaroslav@288
    98
                // wait more
jaroslav@288
    99
            }
jaroslav@288
   100
        }
jaroslav@288
   101
        if (!Platform.isFxApplicationThread()) {
jaroslav@288
   102
            final WebView[] arr = {null};
jaroslav@288
   103
            final CountDownLatch waitForResult = new CountDownLatch(1);
jaroslav@288
   104
            Platform.runLater(new Runnable() {
jaroslav@288
   105
                @Override
jaroslav@288
   106
                public void run() {
jaroslav@288
   107
                    arr[0] = INSTANCE.newView(url, onLoad);
jaroslav@288
   108
                    waitForResult.countDown();
jaroslav@288
   109
                }
jaroslav@288
   110
            });
jaroslav@288
   111
            for (;;) {
jaroslav@288
   112
                try {
jaroslav@288
   113
                    waitForResult.await();
jaroslav@288
   114
                    break;
jaroslav@288
   115
                } catch (InterruptedException ex) {
jaroslav@318
   116
                    LOG.log(Level.INFO, null, ex);
jaroslav@288
   117
                }
jaroslav@288
   118
            }
jaroslav@288
   119
            return arr[0];
jaroslav@288
   120
        } else {
jaroslav@288
   121
            return INSTANCE.newView(url, onLoad);
jaroslav@288
   122
        }
jaroslav@288
   123
    }
jaroslav@288
   124
jaroslav@288
   125
    @Override
jaroslav@288
   126
    public void start(Stage primaryStage) throws Exception {
jaroslav@288
   127
        synchronized (FXBrwsr.class) {
jaroslav@288
   128
            INSTANCE = this;
jaroslav@288
   129
            FXBrwsr.class.notifyAll();
jaroslav@288
   130
        }
jaroslav@288
   131
        BorderPane r = new BorderPane();
jaroslav@288
   132
        Scene scene = new Scene(r, 800, 600);
jaroslav@288
   133
        primaryStage.setScene(scene);
jaroslav@288
   134
        primaryStage.show();
jaroslav@288
   135
        this.root = r;
jaroslav@288
   136
    }
jaroslav@288
   137
jaroslav@288
   138
    private WebView newView(final URL url, final FXPresenter onLoad) {
jaroslav@288
   139
        final WebView view = new WebView();
jaroslav@288
   140
        view.setContextMenuEnabled(false);
jaroslav@288
   141
        view.getEngine().setOnAlert(new EventHandler<WebEvent<String>>() {
jaroslav@288
   142
            @Override
jaroslav@288
   143
            public void handle(WebEvent<String> t) {
jaroslav@288
   144
                final Stage dialogStage = new Stage();
jaroslav@288
   145
                dialogStage.initModality(Modality.WINDOW_MODAL);
jaroslav@288
   146
                dialogStage.setTitle("Warning");
jaroslav@288
   147
                final Button button = new Button("Close");
jaroslav@288
   148
                final Text text = new Text(t.getData());
jaroslav@288
   149
                VBox box = new VBox();
jaroslav@288
   150
                box.setAlignment(Pos.CENTER);
jaroslav@288
   151
                box.setSpacing(10);
jaroslav@288
   152
                box.setPadding(new Insets(10));
jaroslav@288
   153
                box.getChildren().addAll(text, button);
jaroslav@288
   154
                dialogStage.setScene(new Scene(box));
jaroslav@288
   155
                button.setCancelButton(true);
jaroslav@288
   156
                button.setOnAction(new EventHandler<ActionEvent>() {
jaroslav@288
   157
                    @Override
jaroslav@288
   158
                    public void handle(ActionEvent t) {
jaroslav@288
   159
                        dialogStage.close();
jaroslav@288
   160
                    }
jaroslav@288
   161
                });
jaroslav@288
   162
                dialogStage.centerOnScreen();
jaroslav@288
   163
                dialogStage.showAndWait();
jaroslav@288
   164
            }
jaroslav@288
   165
        });
jaroslav@288
   166
        root.setCenter(view);
jaroslav@288
   167
        final Worker<Void> w = view.getEngine().getLoadWorker();
jaroslav@288
   168
        w.stateProperty().addListener(new ChangeListener<Worker.State>() {
jaroslav@288
   169
            @Override
jaroslav@288
   170
            public void changed(ObservableValue<? extends Worker.State> ov, Worker.State t, Worker.State newState) {
jaroslav@288
   171
                if (newState.equals(Worker.State.SUCCEEDED)) {
jaroslav@435
   172
                    FXConsole.register(view.getEngine());
jaroslav@288
   173
                    onLoad.onPageLoad();
jaroslav@288
   174
                }
jaroslav@288
   175
                if (newState.equals(Worker.State.FAILED)) {
jaroslav@288
   176
                    throw new IllegalStateException("Failed to load " + url);
jaroslav@288
   177
                }
jaroslav@288
   178
            }
jaroslav@288
   179
        });
jaroslav@288
   180
        return view;
jaroslav@288
   181
    }
jaroslav@288
   182
jaroslav@288
   183
    static void waitFinished() {
jaroslav@288
   184
        for (;;) {
jaroslav@288
   185
            try {
jaroslav@288
   186
                FINISHED.await();
jaroslav@288
   187
                break;
jaroslav@288
   188
            } catch (InterruptedException ex) {
jaroslav@318
   189
                LOG.log(Level.INFO, null, ex);
jaroslav@288
   190
            }
jaroslav@288
   191
        }
jaroslav@288
   192
    }
jaroslav@288
   193
    
jaroslav@288
   194
}