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