#255831: BrowserBuilder.showAndWait can be used multiple times with JavaFX presenter. Demonstrated by running the boot-fx tests in 'fork once' mode.
1.1 --- a/boot-fx/pom.xml Sun Oct 04 14:55:01 2015 +0200
1.2 +++ b/boot-fx/pom.xml Sun Oct 11 07:24:32 2015 +0200
1.3 @@ -26,13 +26,6 @@
1.4 <groupId>org.netbeans.html</groupId>
1.5 <artifactId>html4j-maven-plugin</artifactId>
1.6 </plugin>
1.7 - <plugin>
1.8 - <groupId>org.apache.maven.plugins</groupId>
1.9 - <artifactId>maven-surefire-plugin</artifactId>
1.10 - <configuration>
1.11 - <forkMode>always</forkMode>
1.12 - </configuration>
1.13 - </plugin>
1.14 </plugins>
1.15 </build>
1.16 <dependencies>
2.1 --- a/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXBrwsr.java Sun Oct 04 14:55:01 2015 +0200
2.2 +++ b/boot-fx/src/main/java/org/netbeans/html/boot/fx/FXBrwsr.java Sun Oct 11 07:24:32 2015 +0200
2.3 @@ -92,11 +92,22 @@
2.4 Executors.newFixedThreadPool(1).submit(new Runnable() {
2.5 @Override
2.6 public void run() {
2.7 - try {
2.8 - FXBrwsr.launch(FXBrwsr.class, callee);
2.9 - } catch (Throwable ex) {
2.10 - ex.printStackTrace();
2.11 - } finally {
2.12 + if (!Platform.isFxApplicationThread()) {
2.13 + try {
2.14 + Platform.runLater(this);
2.15 + } catch (IllegalStateException ex) {
2.16 + try {
2.17 + FXBrwsr.launch(FXBrwsr.class, callee);
2.18 + } catch (Throwable t) {
2.19 + t.printStackTrace();
2.20 + } finally {
2.21 + FINISHED.countDown();
2.22 + }
2.23 + }
2.24 + } else {
2.25 + FXBrwsr brwsr = new FXBrwsr();
2.26 + brwsr.start(new Stage(), callee);
2.27 + INSTANCE = brwsr;
2.28 FINISHED.countDown();
2.29 }
2.30 }
2.31 @@ -144,8 +155,12 @@
2.32
2.33 @Override
2.34 public void start(Stage primaryStage) throws Exception {
2.35 + start(primaryStage, this.getParameters().getRaw().get(0));
2.36 + }
2.37 +
2.38 + final void start(Stage primaryStage, String callee) {
2.39 BorderPane r = new BorderPane();
2.40 - Object[] arr = findInitialSize(this.getParameters().getRaw().get(0));
2.41 + Object[] arr = findInitialSize(callee);
2.42 Scene scene = new Scene(r, (Double)arr[2], (Double)arr[3]);
2.43 primaryStage.setScene(scene);
2.44 this.root = r;
2.45 @@ -220,99 +235,22 @@
2.46 private WebView newView(final URL url, final FXPresenter onLoad) {
2.47 final WebView view = new WebView();
2.48 view.setContextMenuEnabled(false);
2.49 - view.getEngine().setOnAlert(new EventHandler<WebEvent<String>>() {
2.50 - @Override
2.51 - public void handle(WebEvent<String> t) {
2.52 - final Stage dialogStage = new Stage();
2.53 - dialogStage.initModality(Modality.WINDOW_MODAL);
2.54 - dialogStage.initOwner(stage);
2.55 - ResourceBundle r = ResourceBundle.getBundle("org/netbeans/html/boot/fx/Bundle"); // NOI18N
2.56 - dialogStage.setTitle(r.getString("AlertTitle")); // NOI18N
2.57 - final Button button = new Button(r.getString("AlertCloseButton")); // NOI18N
2.58 - final Text text = new Text(t.getData());
2.59 - VBox box = new VBox();
2.60 - box.setAlignment(Pos.CENTER);
2.61 - box.setSpacing(10);
2.62 - box.setPadding(new Insets(10));
2.63 - box.getChildren().addAll(text, button);
2.64 - dialogStage.setScene(new Scene(box));
2.65 - button.setCancelButton(true);
2.66 - button.setOnAction(new CloseDialogHandler(dialogStage, null));
2.67 - dialogStage.centerOnScreen();
2.68 - dialogStage.showAndWait();
2.69 - }
2.70 - });
2.71 - view.getEngine().setConfirmHandler(new Callback<String, Boolean>() {
2.72 - @Override
2.73 - public Boolean call(String question) {
2.74 - final Stage dialogStage = new Stage();
2.75 - dialogStage.initModality(Modality.WINDOW_MODAL);
2.76 - dialogStage.initOwner(stage);
2.77 - ResourceBundle r = ResourceBundle.getBundle("org/netbeans/html/boot/fx/Bundle"); // NOI18N
2.78 - dialogStage.setTitle(r.getString("ConfirmTitle")); // NOI18N
2.79 - final Button ok = new Button(r.getString("ConfirmOKButton")); // NOI18N
2.80 - final Button cancel = new Button(r.getString("ConfirmCancelButton")); // NOI18N
2.81 - final Text text = new Text(question);
2.82 - final Insets ins = new Insets(10);
2.83 - final VBox box = new VBox();
2.84 - box.setAlignment(Pos.CENTER);
2.85 - box.setSpacing(10);
2.86 - box.setPadding(ins);
2.87 - final HBox buttons = new HBox(10);
2.88 - buttons.getChildren().addAll(ok, cancel);
2.89 - buttons.setAlignment(Pos.CENTER);
2.90 - buttons.setPadding(ins);
2.91 - box.getChildren().addAll(text, buttons);
2.92 - dialogStage.setScene(new Scene(box));
2.93 - ok.setCancelButton(false);
2.94 + Stage newStage;
2.95 + BorderPane bp;
2.96 + if (root == null) {
2.97 + newStage = new Stage();
2.98 + newStage.initOwner(stage);
2.99 + bp = new BorderPane();
2.100 + newStage.setScene(new Scene(bp));
2.101 + newStage.show();
2.102 + } else {
2.103 + bp = root;
2.104 + newStage = stage;
2.105 + root = null;
2.106 + }
2.107
2.108 - final boolean[] res = new boolean[1];
2.109 - ok.setOnAction(new CloseDialogHandler(dialogStage, res));
2.110 - cancel.setCancelButton(true);
2.111 - cancel.setOnAction(new CloseDialogHandler(dialogStage, null));
2.112 - dialogStage.centerOnScreen();
2.113 - dialogStage.showAndWait();
2.114 - return res[0];
2.115 - }
2.116 - });
2.117 - view.getEngine().setPromptHandler(new Callback<PromptData, String>() {
2.118 - @Override
2.119 - public String call(PromptData prompt) {
2.120 - final Stage dialogStage = new Stage();
2.121 - dialogStage.initModality(Modality.WINDOW_MODAL);
2.122 - dialogStage.initOwner(stage);
2.123 - ResourceBundle r = ResourceBundle.getBundle("org/netbeans/html/boot/fx/Bundle"); // NOI18N
2.124 - dialogStage.setTitle(r.getString("PromptTitle")); // NOI18N
2.125 - final Button ok = new Button(r.getString("PromptOKButton")); // NOI18N
2.126 - final Button cancel = new Button(r.getString("PromptCancelButton")); // NOI18N
2.127 - final Text text = new Text(prompt.getMessage());
2.128 - final TextField line = new TextField();
2.129 - if (prompt.getDefaultValue() != null) {
2.130 - line.setText(prompt.getDefaultValue());
2.131 - }
2.132 - final Insets ins = new Insets(10);
2.133 - final VBox box = new VBox();
2.134 - box.setAlignment(Pos.CENTER);
2.135 - box.setSpacing(10);
2.136 - box.setPadding(ins);
2.137 - final HBox buttons = new HBox(10);
2.138 - buttons.getChildren().addAll(ok, cancel);
2.139 - buttons.setAlignment(Pos.CENTER);
2.140 - buttons.setPadding(ins);
2.141 - box.getChildren().addAll(text, line, buttons);
2.142 - dialogStage.setScene(new Scene(box));
2.143 - ok.setCancelButton(false);
2.144 -
2.145 - final boolean[] res = new boolean[1];
2.146 - ok.setOnAction(new CloseDialogHandler(dialogStage, res));
2.147 - cancel.setCancelButton(true);
2.148 - cancel.setOnAction(new CloseDialogHandler(dialogStage, null));
2.149 - dialogStage.centerOnScreen();
2.150 - dialogStage.showAndWait();
2.151 - return res[0] ? line.getText() : null;
2.152 - }
2.153 - });
2.154 - root.setCenter(view);
2.155 + attachHandlers(view, newStage);
2.156 + bp.setCenter(view);
2.157 final Worker<Void> w = view.getEngine().getLoadWorker();
2.158 w.stateProperty().addListener(new ChangeListener<Worker.State>() {
2.159 private String previous;
2.160 @@ -362,6 +300,101 @@
2.161 return view;
2.162 }
2.163
2.164 + private static void attachHandlers(final WebView view, final Stage owner) {
2.165 + view.getEngine().setOnAlert(new EventHandler<WebEvent<String>>() {
2.166 + @Override
2.167 + public void handle(WebEvent<String> t) {
2.168 + final Stage dialogStage = new Stage();
2.169 + dialogStage.initModality(Modality.WINDOW_MODAL);
2.170 + dialogStage.initOwner(owner);
2.171 + ResourceBundle r = ResourceBundle.getBundle("org/netbeans/html/boot/fx/Bundle"); // NOI18N
2.172 + dialogStage.setTitle(r.getString("AlertTitle")); // NOI18N
2.173 + final Button button = new Button(r.getString("AlertCloseButton")); // NOI18N
2.174 + final Text text = new Text(t.getData());
2.175 + VBox box = new VBox();
2.176 + box.setAlignment(Pos.CENTER);
2.177 + box.setSpacing(10);
2.178 + box.setPadding(new Insets(10));
2.179 + box.getChildren().addAll(text, button);
2.180 + dialogStage.setScene(new Scene(box));
2.181 + button.setCancelButton(true);
2.182 + button.setOnAction(new CloseDialogHandler(dialogStage, null));
2.183 + dialogStage.centerOnScreen();
2.184 + dialogStage.showAndWait();
2.185 + }
2.186 + });
2.187 + view.getEngine().setConfirmHandler(new Callback<String, Boolean>() {
2.188 + @Override
2.189 + public Boolean call(String question) {
2.190 + final Stage dialogStage = new Stage();
2.191 + dialogStage.initModality(Modality.WINDOW_MODAL);
2.192 + dialogStage.initOwner(owner);
2.193 + ResourceBundle r = ResourceBundle.getBundle("org/netbeans/html/boot/fx/Bundle"); // NOI18N
2.194 + dialogStage.setTitle(r.getString("ConfirmTitle")); // NOI18N
2.195 + final Button ok = new Button(r.getString("ConfirmOKButton")); // NOI18N
2.196 + final Button cancel = new Button(r.getString("ConfirmCancelButton")); // NOI18N
2.197 + final Text text = new Text(question);
2.198 + final Insets ins = new Insets(10);
2.199 + final VBox box = new VBox();
2.200 + box.setAlignment(Pos.CENTER);
2.201 + box.setSpacing(10);
2.202 + box.setPadding(ins);
2.203 + final HBox buttons = new HBox(10);
2.204 + buttons.getChildren().addAll(ok, cancel);
2.205 + buttons.setAlignment(Pos.CENTER);
2.206 + buttons.setPadding(ins);
2.207 + box.getChildren().addAll(text, buttons);
2.208 + dialogStage.setScene(new Scene(box));
2.209 + ok.setCancelButton(false);
2.210 +
2.211 + final boolean[] res = new boolean[1];
2.212 + ok.setOnAction(new CloseDialogHandler(dialogStage, res));
2.213 + cancel.setCancelButton(true);
2.214 + cancel.setOnAction(new CloseDialogHandler(dialogStage, null));
2.215 + dialogStage.centerOnScreen();
2.216 + dialogStage.showAndWait();
2.217 + return res[0];
2.218 + }
2.219 + });
2.220 + view.getEngine().setPromptHandler(new Callback<PromptData, String>() {
2.221 + @Override
2.222 + public String call(PromptData prompt) {
2.223 + final Stage dialogStage = new Stage();
2.224 + dialogStage.initModality(Modality.WINDOW_MODAL);
2.225 + dialogStage.initOwner(owner);
2.226 + ResourceBundle r = ResourceBundle.getBundle("org/netbeans/html/boot/fx/Bundle"); // NOI18N
2.227 + dialogStage.setTitle(r.getString("PromptTitle")); // NOI18N
2.228 + final Button ok = new Button(r.getString("PromptOKButton")); // NOI18N
2.229 + final Button cancel = new Button(r.getString("PromptCancelButton")); // NOI18N
2.230 + final Text text = new Text(prompt.getMessage());
2.231 + final TextField line = new TextField();
2.232 + if (prompt.getDefaultValue() != null) {
2.233 + line.setText(prompt.getDefaultValue());
2.234 + }
2.235 + final Insets ins = new Insets(10);
2.236 + final VBox box = new VBox();
2.237 + box.setAlignment(Pos.CENTER);
2.238 + box.setSpacing(10);
2.239 + box.setPadding(ins);
2.240 + final HBox buttons = new HBox(10);
2.241 + buttons.getChildren().addAll(ok, cancel);
2.242 + buttons.setAlignment(Pos.CENTER);
2.243 + buttons.setPadding(ins);
2.244 + box.getChildren().addAll(text, line, buttons);
2.245 + dialogStage.setScene(new Scene(box));
2.246 + ok.setCancelButton(false);
2.247 +
2.248 + final boolean[] res = new boolean[1];
2.249 + ok.setOnAction(new CloseDialogHandler(dialogStage, res));
2.250 + cancel.setCancelButton(true);
2.251 + cancel.setOnAction(new CloseDialogHandler(dialogStage, null));
2.252 + dialogStage.centerOnScreen();
2.253 + dialogStage.showAndWait();
2.254 + return res[0] ? line.getText() : null;
2.255 + }
2.256 + });
2.257 + }
2.258 +
2.259 static void waitFinished() {
2.260 for (;;) {
2.261 try {
3.1 --- a/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersOnResourceTest.java Sun Oct 04 14:55:01 2015 +0200
3.2 +++ b/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersOnResourceTest.java Sun Oct 11 07:24:32 2015 +0200
3.3 @@ -71,7 +71,15 @@
3.4 new Thread("initFX") {
3.5 @Override
3.6 public void run() {
3.7 - App.launch(App.class);
3.8 + if (Platform.isFxApplicationThread()) {
3.9 + new App().start(new Stage());
3.10 + } else {
3.11 + try {
3.12 + App.launch(App.class);
3.13 + } catch (IllegalStateException ex) {
3.14 + Platform.runLater(this);
3.15 + }
3.16 + }
3.17 }
3.18 }.start();
3.19 App.CDL.await();
3.20 @@ -182,7 +190,7 @@
3.21 }
3.22
3.23 @Override
3.24 - public void start(Stage stage) throws Exception {
3.25 + public void start(Stage stage) {
3.26 pane= new BorderPane();
3.27 Scene scene = new Scene(pane, 800, 600);
3.28 stage.setScene(scene);
4.1 --- a/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersTest.java Sun Oct 04 14:55:01 2015 +0200
4.2 +++ b/boot-fx/src/test/java/net/java/html/boot/fx/FXBrowsersTest.java Sun Oct 11 07:24:32 2015 +0200
4.3 @@ -68,7 +68,15 @@
4.4 new Thread("initFX") {
4.5 @Override
4.6 public void run() {
4.7 - App.launch(App.class);
4.8 + if (Platform.isFxApplicationThread()) {
4.9 + new App().start(new Stage());
4.10 + } else {
4.11 + try {
4.12 + App.launch(App.class);
4.13 + } catch (IllegalStateException ex) {
4.14 + Platform.runLater(this);
4.15 + }
4.16 + }
4.17 }
4.18 }.start();
4.19 App.CDL.await();
4.20 @@ -122,7 +130,7 @@
4.21 @Override
4.22 public void run() {
4.23 assertTrue(Platform.isFxApplicationThread());
4.24 - three[0] = App.getV1().getEngine().executeScript("window.cnt");
4.25 + three[0] = App.getV1().getEngine().executeScript("window.cntBrwsr");
4.26 finish.countDown();
4.27 }
4.28 });
4.29 @@ -173,8 +181,8 @@
4.30 private static native Object window();
4.31
4.32 @JavaScriptBody(args = {}, body = ""
4.33 - + "if (window.cnt) return ++window.cnt;"
4.34 - + "return window.cnt = 1;"
4.35 + + "if (window.cntBrwsr) return ++window.cntBrwsr;"
4.36 + + "return window.cntBrwsr = 1;"
4.37 )
4.38 private static native int increment();
4.39 }
4.40 @@ -198,7 +206,7 @@
4.41 }
4.42
4.43 @Override
4.44 - public void start(Stage stage) throws Exception {
4.45 + public void start(Stage stage) {
4.46 pane= new BorderPane();
4.47 Scene scene = new Scene(pane, 800, 600);
4.48 stage.setScene(scene);