1 /* 2 * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javafx.application; 27 28 import java.security.AccessController; 29 import java.security.PrivilegedAction; 30 import java.util.List; 31 import java.util.Map; 32 33 import javafx.application.Preloader.PreloaderNotification; 34 import javafx.scene.Scene; 35 import javafx.stage.Stage; 36 37 import com.sun.javafx.application.LauncherImpl; 38 import com.sun.javafx.application.ParametersImpl; 39 import com.sun.javafx.application.PlatformImpl; 40 import com.sun.javafx.css.StyleManager; 41 42 /** 43 * Application class from which JavaFX applications extend. 44 * 45 * <p><b>Life-cycle</b></p> 46 * <p> 47 * The entry point for JavaFX applications is the Application class. The 48 * JavaFX runtime does the following, in order, whenever an application is 49 * launched: 50 * </p> 51 * <ol> 52 * <li>Constructs an instance of the specified Application class</li> 53 * <li>Calls the {@link #init} method</li> 54 * <li>Calls the {@link #start} method</li> 55 * <li>Waits for the application to finish, which happens when either of 56 * the following occur: 57 * <ul> 58 * <li>the application calls {@link Platform#exit}</li> 59 * <li>the last window has been closed and the {@code implicitExit} 60 * attribute on {@code Platform} is true</li> 61 * </ul></li> 62 * <li>Calls the {@link #stop} method</li> 63 * </ol> 64 * <p>Note that the {@code start} method is abstract and must be overridden. 65 * The {@code init} and {@code stop} methods have concrete implementations 66 * that do nothing.</p> 67 * 68 * <p>Calling {@link Platform#exit} is the preferred way to explicitly terminate 69 * a JavaFX Application. Directly calling {@link System#exit} is 70 * an acceptable alternative, but doesn't allow the Application {@link #stop} 71 * method to run. 72 * </p> 73 * 74 * <p>A JavaFX Application should not attempt to use JavaFX after the 75 * FX toolkit has terminated or from a ShutdownHook, that is, after the 76 * {@link #stop} method returns or {@link System#exit} is called. 77 * </p> 78 * 79 * <p><b>Parameters</b></p> 80 * <p> 81 * Application parameters are available by calling the {@link #getParameters} 82 * method from the {@link #init} method, or any time after the {@code init} 83 * method has been called. 84 * </p> 85 * 86 * <p><b>Threading</b></p> 87 * <p> 88 * JavaFX creates an application thread for running the application start 89 * method, processing input events, and running animation timelines. Creation 90 * of JavaFX {@link Scene} and {@link Stage} objects as well as modification of 91 * scene graph operations to <em>live</em> objects (those objects already 92 * attached to a scene) must be done on the JavaFX application thread. 93 * </p> 94 * 95 * <p> 96 * The Java launcher loads and initializes the specified Application class 97 * on the JavaFX Application Thread. If there is no main method in the 98 * Application class, or if the main method calls Application.launch(), then 99 * an instance of the Application is then constructed on the JavaFX Application 100 * Thread. 101 * </p> 102 * 103 * <p> 104 * The {@code init} method is called on the launcher thread, not on the 105 * JavaFX Application Thread. 106 * This means that an application must not construct a {@link Scene} 107 * or a {@link Stage} in the {@code init} method. 108 * An application may construct other JavaFX objects in the {@code init} 109 * method. 110 * </p> 111 * 112 * <p> 113 * All the unhandled exceptions on the JavaFX application thread that occur during 114 * event dispatching, running animation timelines, or any other code, are forwarded 115 * to the thread's {@link java.lang.Thread.UncaughtExceptionHandler uncaught 116 * exception handler}. 117 * </p> 118 * 119 * <p><b>Example</b></p> 120 * <p>The following example will illustrate a simple JavaFX application.</p> 121 * <pre><code> 122 import javafx.application.Application; 123 import javafx.scene.Group; 124 import javafx.scene.Scene; 125 import javafx.scene.shape.Circle; 126 import javafx.stage.Stage; 127 128 public class MyApp extends Application { 129 public void start(Stage stage) { 130 Circle circ = new Circle(40, 40, 30); 131 Group root = new Group(circ); 132 Scene scene = new Scene(root, 400, 300); 133 134 stage.setTitle("My JavaFX Application"); 135 stage.setScene(scene); 136 stage.show(); 137 } 138 } 139 * </code></pre> 140 * 141 * <p>The above example will produce the following:</p> 142 * <p><img src="doc-files/Application.png"/></p> 143 * @since JavaFX 2.0 144 */ 145 public abstract class Application { 146 /** 147 * Constant for user agent stylesheet for the "Caspian" theme. Caspian 148 * is the theme that shipped as default in JavaFX 2.x. 149 * @since JavaFX 8.0 150 */ 151 public static final String STYLESHEET_CASPIAN = "CASPIAN"; 152 /** 153 * Constant for user agent stylesheet for the "Modena" theme. Modena 154 * is the default theme for JavaFX 8.x. 155 * @since JavaFX 8.0 156 */ 157 public static final String STYLESHEET_MODENA = "MODENA"; 158 159 /** 160 * Launch a standalone application. This method is typically called 161 * from the main method(). It must not be called more than once or an 162 * exception will be thrown. 163 * 164 * <p> 165 * The launch method does not return until the application has exited, 166 * either via a call to Platform.exit or all of the application windows 167 * have been closed. 168 * 169 * <p> 170 * Typical usage is: 171 * <ul> 172 * <pre> 173 * public static void main(String[] args) { 174 * Application.launch(MyApp.class, args); 175 * } 176 * </pre> 177 * </ul> 178 * where <code>MyApp</code> is a subclass of Application. 179 * 180 * @param appClass the application class that is constructed and executed 181 * by the launcher. 182 * @param args the command line arguments passed to the application. 183 * An application may get these parameters using the 184 * {@link #getParameters()} method. 185 * 186 * @throws IllegalStateException if this method is called more than once. 187 * @throws IllegalArgumentException if <code>appClass</code> is not a 188 * subclass of <code>Application</code>. 189 */ 190 public static void launch(Class<? extends Application> appClass, String... args) { 191 LauncherImpl.launchApplication(appClass, args); 192 } 193 194 /** 195 * Launch a standalone application. This method is typically called 196 * from the main method(). It must not be called more than once or an 197 * exception will be thrown. 198 * This is equivalent to launch(TheClass.class, args) where TheClass is the 199 * immediately enclosing class of the method that called launch. It must 200 * be a subclass of Application or a RuntimeException will be thrown. 201 * 202 * <p> 203 * The launch method does not return until the application has exited, 204 * either via a call to Platform.exit or all of the application windows 205 * have been closed. 206 * 207 * <p> 208 * Typical usage is: 209 * <ul> 210 * <pre> 211 * public static void main(String[] args) { 212 * Application.launch(args); 213 * } 214 * </pre> 215 * </ul> 216 * 217 * @param args the command line arguments passed to the application. 218 * An application may get these parameters using the 219 * {@link #getParameters()} method. 220 * 221 * @throws IllegalStateException if this method is called more than once. 222 */ 223 public static void launch(String... args) { 224 // Figure out the right class to call 225 StackTraceElement[] cause = Thread.currentThread().getStackTrace(); 226 227 boolean foundThisMethod = false; 228 String callingClassName = null; 229 for (StackTraceElement se : cause) { 230 // Skip entries until we get to the entry for this class 231 String className = se.getClassName(); 232 String methodName = se.getMethodName(); 233 if (foundThisMethod) { 234 callingClassName = className; 235 break; 236 } else if (Application.class.getName().equals(className) 237 && "launch".equals(methodName)) { 238 239 foundThisMethod = true; 240 } 241 } 242 243 if (callingClassName == null) { 244 throw new RuntimeException("Error: unable to determine Application class"); 245 } 246 247 try { 248 Class theClass = Class.forName(callingClassName, false, 249 Thread.currentThread().getContextClassLoader()); 250 if (Application.class.isAssignableFrom(theClass)) { 251 Class<? extends Application> appClass = theClass; 252 LauncherImpl.launchApplication(appClass, args); 253 } else { 254 throw new RuntimeException("Error: " + theClass 255 + " is not a subclass of javafx.application.Application"); 256 } 257 } catch (RuntimeException ex) { 258 throw ex; 259 } catch (Exception ex) { 260 throw new RuntimeException(ex); 261 } 262 } 263 264 /** 265 * Constructs a new {@code Application} instance. 266 */ 267 public Application() { 268 } 269 270 /** 271 * The application initialization method. This method is called immediately 272 * after the Application class is loaded and constructed. An application may 273 * override this method to perform initialization prior to the actual starting 274 * of the application. 275 * 276 * <p> 277 * The implementation of this method provided by the Application class does nothing. 278 * </p> 279 * 280 * <p> 281 * NOTE: This method is not called on the JavaFX Application Thread. An 282 * application must not construct a Scene or a Stage in this 283 * method. 284 * An application may construct other JavaFX objects in this method. 285 * </p> 286 */ 287 public void init() throws Exception { 288 } 289 290 /** 291 * The main entry point for all JavaFX applications. 292 * The start method is called after the init method has returned, 293 * and after the system is ready for the application to begin running. 294 * 295 * <p> 296 * NOTE: This method is called on the JavaFX Application Thread. 297 * </p> 298 * 299 * @param primaryStage the primary stage for this application, onto which 300 * the application scene can be set. The primary stage will be embedded in 301 * the browser if the application was launched as an applet. 302 * Applications may create other stages, if needed, but they will not be 303 * primary stages and will not be embedded in the browser. 304 */ 305 public abstract void start(Stage primaryStage) throws Exception; 306 307 /** 308 * This method is called when the application should stop, and provides a 309 * convenient place to prepare for application exit and destroy resources. 310 * 311 * <p> 312 * The implementation of this method provided by the Application class does nothing. 313 * </p> 314 * 315 * <p> 316 * NOTE: This method is called on the JavaFX Application Thread. 317 * </p> 318 */ 319 public void stop() throws Exception { 320 } 321 322 private HostServices hostServices = null; 323 324 /** 325 * Gets the HostServices provider for this application. This provides 326 * the ability to get the code base and document base for this application, 327 * and to access the enclosing web page. 328 * 329 * @return the HostServices provider 330 */ 331 public final HostServices getHostServices() { 332 synchronized (this) { 333 if (hostServices == null) { 334 hostServices = new HostServices(this); 335 } 336 return hostServices; 337 } 338 } 339 340 /** 341 * Retrieves the parameters for this Application, including any arguments 342 * passed on the command line and any parameters specified in a JNLP file 343 * for an applet or WebStart application. 344 * 345 * <p> 346 * NOTE: this method should not be called from the Application constructor, 347 * as it will return null. It may be called in the init() method or any 348 * time after that. 349 * </p> 350 * 351 * @return the parameters for this Application, or null if called from the 352 * constructor. 353 */ 354 public final Parameters getParameters() { 355 return ParametersImpl.getParameters(this); 356 } 357 358 /** 359 * Notifies the preloader with an application-generated notification. 360 * Application code calls this method with a PreloaderNotification that is 361 * delivered to the 362 * {@link Preloader#handleApplicationNotification 363 * Preloader.handleApplicationNotification} method. 364 * This is primarily useful for cases where an application wants the 365 * preloader to show progress during a long application initialization 366 * step. 367 * 368 * <p> 369 * NOTE: the notification will be delivered only to the preloader's 370 * handleApplicationNotification() method; this means, for example, that 371 * if this method is called with a ProgressNotification, that notification 372 * will not be delivered to the {@link Preloader#handleProgressNotification 373 * Preloader.handleProgressNotification} 374 * method. 375 * </p> 376 * 377 * @param info the application-generated preloader notification 378 */ 379 public final void notifyPreloader(PreloaderNotification info) { 380 LauncherImpl.notifyPreloader(this, info); 381 } 382 383 /** 384 * Encapsulates the set of parameters for an application. This includes 385 * arguments passed on the command line, unnamed parameters specified 386 * in a JNLP file, and <name,value> pairs specified in a JNLP file. 387 * 388 * <p> 389 * Note that the application and the preloader both get the same set 390 * of parameters for a given run of an application. 391 * </p> 392 * @since JavaFX 2.0 393 */ 394 public static abstract class Parameters { 395 396 /** 397 * Constructs a new {@code Parameters} instance. 398 */ 399 public Parameters() { 400 } 401 402 /** 403 * Retrieves a read-only list of the raw arguments. This list 404 * may be empty, but is never null. In the case of a standalone 405 * application, it is the ordered list of arguments specified on the 406 * command line. In the case of an applet or WebStart application, 407 * it includes unnamed parameters as well as named parameters. For 408 * named parameters, each <name,value> pair is represented as 409 * a single argument of the form: "--name=value". 410 * 411 * @return a read-only list of raw application arguments 412 */ 413 public abstract List<String> getRaw(); 414 415 /** 416 * Retrieves a read-only list of the unnamed parameters. This list 417 * may be empty, but is never null. The named parameters, that is 418 * the parameters that are represented as <name,value> pairs, are 419 * filtered out. 420 * 421 * @return a read-only list of unnamed parameters. 422 */ 423 public abstract List<String> getUnnamed(); 424 425 /** 426 * Retrieves a read-only map of the named parameters. It may be 427 * empty, but is never null. 428 * Named parameters include those <name,value> pairs explicitly 429 * specified in a JNLP file. It also includes any command line 430 * arguments of the form: "--name=value". 431 * 432 * @return a read-only map of named parameters. 433 */ 434 public abstract Map<String, String> getNamed(); 435 436 } 437 438 private static String userAgentStylesheet = null; 439 440 /** 441 * Get the user agent stylesheet used by the whole application. This is 442 * used to provide default styling for all ui controls and other nodes. 443 * A value of null means the platform default stylesheet is being used. 444 * <p> 445 * NOTE: This method must be called on the JavaFX Application Thread. 446 * </p> 447 * 448 * @return The URL to the stylesheet as a String. 449 * @since JavaFX 8.0 450 */ 451 public static String getUserAgentStylesheet() { 452 return userAgentStylesheet; 453 } 454 455 /** 456 * Set the user agent stylesheet used by the whole application. This is used 457 * to provide default styling for all ui controls and other nodes. Each 458 * release of JavaFX may have a new default value for this so if you need 459 * to guarantee consistency you will need to call this method and choose 460 * what default you would like for your application. A value of null will 461 * restore the platform default stylesheet. This property can also be set 462 * on the command line with {@code -Djavafx.userAgentStylesheetUrl=[URL]} 463 * Setting it on the command line overrides anything set using this method 464 * in code. 465 * <p> 466 * NOTE: This method must be called on the JavaFX Application Thread. 467 * </p> 468 * 469 * 470 * @param url The URL to the stylesheet as a String. 471 * @since JavaFX 8.0 472 */ 473 public static void setUserAgentStylesheet(String url) { 474 userAgentStylesheet = url; 475 if (url == null) { 476 PlatformImpl.setDefaultPlatformUserAgentStylesheet(); 477 } else { 478 PlatformImpl.setPlatformUserAgentStylesheet(url); 479 } 480 } 481 }