Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package javafx.application;
027
028import java.security.AccessController;
029import java.security.PrivilegedAction;
030import java.util.List;
031import java.util.Map;
032
033import javafx.application.Preloader.PreloaderNotification;
034import javafx.scene.Scene;
035import javafx.stage.Stage;
036
037import com.sun.javafx.application.LauncherImpl;
038import com.sun.javafx.application.ParametersImpl;
039import com.sun.javafx.application.PlatformImpl;
040import com.sun.javafx.css.StyleManager;
041
042/**
043 * Application class from which JavaFX applications extend.
044 *
045 * <p><b>Life-cycle</b></p>
046 * <p>
047 * The entry point for JavaFX applications is the Application class. The
048 * JavaFX runtime does the following, in order, whenever an application is
049 * launched:
050 * </p>
051 * <ol>
052 * <li>Constructs an instance of the specified Application class</li>
053 * <li>Calls the {@link #init} method</li>
054 * <li>Calls the {@link #start} method</li>
055 * <li>Waits for the application to finish, which happens when either of
056 * the following occur:
057 * <ul>
058 * <li>the application calls {@link Platform#exit}</li>
059 * <li>the last window has been closed and the {@code implicitExit}
060 * attribute on {@code Platform} is true</li>
061 * </ul></li>
062 * <li>Calls the {@link #stop} method</li>
063 * </ol>
064 * <p>Note that the {@code start} method is abstract and must be overridden.
065 * The {@code init} and {@code stop} methods have concrete implementations
066 * that do nothing.</p>
067 *
068 * <p><b>Parameters</b></p>
069 * <p>
070 * Application parameters are available by calling the {@link #getParameters}
071 * method from the {@link #init} method, or any time after the {@code init}
072 * method has been called.
073 * </p>
074 *
075 * <p><b>Threading</b></p>
076 * <p>
077 * JavaFX creates an application thread for running the application start
078 * method, processing input events, and running animation timelines. Creation
079 * of JavaFX {@link Scene} and {@link Stage} objects as well as modification of
080 * scene graph operations to <em>live</em> objects (those objects already
081 * attached to a scene) must be done on the JavaFX application thread.
082 * </p>
083 *
084 * <p>
085 * The Application constructor and {@code init} method are called on
086 * the launcher thread, not on the JavaFX Application Thread.
087 * This means that an application must not construct a {@link Scene}
088 * or a {@link Stage} in either the constructor or in the {@code init}
089 * method.
090 * An application may construct other JavaFX objects in the {@code init}
091 * method.
092 * </p>
093 *
094 * <p>
095 * All the unhandled exceptions on the JavaFX application thread that occur during
096 * event dispatching, running animation timelines, or any other code, are forwarded
097 * to the thread's {@link java.lang.Thread.UncaughtExceptionHandler uncaught
098 * exception handler}.
099 * </p>
100 *
101 * <p><b>Example</b></p>
102 * <p>The following example will illustrate a simple JavaFX application.</p>
103 * <pre><code>
104import javafx.application.Application;
105import javafx.scene.Group;
106import javafx.scene.Scene;
107import javafx.scene.shape.Circle;
108import javafx.stage.Stage;
109
110public class MyApp extends Application {
111    public void start(Stage stage) {
112        Circle circ = new Circle(40, 40, 30);
113        Group root = new Group(circ);
114        Scene scene = new Scene(root, 400, 300);
115
116        stage.setTitle("My JavaFX Application");
117        stage.setScene(scene);
118        stage.show();
119    }
120}
121 * </code></pre>
122 *
123 * <p>The above example will produce the following:</p>
124 * <p><img src="doc-files/Application.png"/></p>
125 */
126public abstract class Application {
127    /**
128     * Constant for user agent stylesheet for the "Caspian" theme. Caspian
129     * is the theme that shipped as default in JavaFX 2.x.
130     */
131    public static final String STYLESHEET_CASPIAN = "CASPIAN";
132    /**
133     * Constant for user agent stylesheet for the "Modena" theme. Modena
134     * is the default theme for JavaFX 8.x.
135     */
136    public static final String STYLESHEET_MODENA = "MODENA";
137
138    /**
139     * Launch a standalone application. This method is typically called
140     * from the main method(). It must not be called more than once or an
141     * exception will be thrown.
142     *
143     * <p>
144     * The launch method does not return until the application has exited,
145     * either via a call to Platform.exit or all of the application windows
146     * have been closed.
147     *
148     * <p>
149     * Typical usage is:
150     * <ul>
151     * <pre>
152     * public static void main(String[] args) {
153     *     Application.launch(MyApp.class, args);
154     * }
155     * </pre>
156     * </ul>
157     * where <code>MyApp</code> is a subclass of Application.
158     *
159     * @param appClass the application class that is constructed and executed
160     *        by the launcher.
161     * @param args the command line arguments passed to the application.
162     *             An application may get these parameters using the
163     *             {@link #getParameters()} method.
164     *
165     * @throws IllegalStateException if this method is called more than once.
166     * @throws IllegalArgumentException if <code>appClass</code> is not a
167     *         subclass of <code>Application</code>.
168     */
169    public static void launch(Class<? extends Application> appClass, String... args) {
170        LauncherImpl.launchApplication(appClass, args);
171    }
172
173    /**
174     * Launch a standalone application. This method is typically called
175     * from the main method(). It must not be called more than once or an
176     * exception will be thrown.
177     * This is equivalent to launch(TheClass.class, args) where TheClass is the
178     * immediately enclosing class of the method that called launch. It must
179     * be a subclass of Application or a RuntimeException will be thrown.
180     *
181     * <p>
182     * The launch method does not return until the application has exited,
183     * either via a call to Platform.exit or all of the application windows
184     * have been closed.
185     *
186     * <p>
187     * Typical usage is:
188     * <ul>
189     * <pre>
190     * public static void main(String[] args) {
191     *     Application.launch(args);
192     * }
193     * </pre>
194     * </ul>
195     *
196     * @param args the command line arguments passed to the application.
197     *             An application may get these parameters using the
198     *             {@link #getParameters()} method.
199     *
200     * @throws IllegalStateException if this method is called more than once.
201     */
202    public static void launch(String... args) {
203        // Figure out the right class to call
204        StackTraceElement[] cause = Thread.currentThread().getStackTrace();
205
206        boolean foundThisMethod = false;
207        String callingClassName = null;
208        for (StackTraceElement se : cause) {
209            // Skip entries until we get to the entry for this class
210            String className = se.getClassName();
211            String methodName = se.getMethodName();
212            if (foundThisMethod) {
213                callingClassName = className;
214                break;
215            } else if (Application.class.getName().equals(className)
216                    && "launch".equals(methodName)) {
217
218                foundThisMethod = true;
219            }
220        }
221
222        if (callingClassName == null) {
223            throw new RuntimeException("Error: unable to determine Application class");
224        }
225
226        try {
227            Class theClass = Class.forName(callingClassName, true,
228                               Thread.currentThread().getContextClassLoader());
229            if (Application.class.isAssignableFrom(theClass)) {
230                Class<? extends Application> appClass = theClass;
231                LauncherImpl.launchApplication(appClass, args);
232            } else {
233                throw new RuntimeException("Error: " + theClass
234                        + " is not a subclass of javafx.application.Application");
235            }
236        } catch (RuntimeException ex) {
237            throw ex;
238        } catch (Exception ex) {
239            throw new RuntimeException(ex);
240        }
241    }
242
243    /**
244     * The application initialization method. This method is called immediately
245     * after the Application class is loaded and constructed. An application may
246     * override this method to perform initialization prior to the actual starting
247     * of the application.
248     *
249     * <p>
250     * The implementation of this method provided by the Application class does nothing.
251     * </p>
252     *
253     * <p>
254     * NOTE: This method is not called on the JavaFX Application Thread. An
255     * application must not construct a Scene or a Stage in this
256     * method.
257     * An application may construct other JavaFX objects in this method.
258     * </p>
259     */
260    public void init() throws Exception {
261    }
262
263    /**
264     * The main entry point for all JavaFX applications.
265     * The start method is called after the init method has returned,
266     * and after the system is ready for the application to begin running.
267     *
268     * <p>
269     * NOTE: This method is called on the JavaFX Application Thread.
270     * </p>
271     *
272     * @param primaryStage the primary stage for this application, onto which
273     * the application scene can be set. The primary stage will be embedded in
274     * the browser if the application was launched as an applet.
275     * Applications may create other stages, if needed, but they will not be
276     * primary stages and will not be embedded in the browser.
277     */
278    public abstract void start(Stage primaryStage) throws Exception;
279
280    /**
281     * This method is called when the application should stop, and provides a
282     * convenient place to prepare for application exit and destroy resources.
283     *
284     * <p>
285     * The implementation of this method provided by the Application class does nothing.
286     * </p>
287     *
288     * <p>
289     * NOTE: This method is called on the JavaFX Application Thread.
290     * </p>
291     */
292    public void stop() throws Exception {
293    }
294
295    private HostServices hostServices = null;
296
297    /**
298     * Gets the HostServices provider for this application. This provides
299     * the ability to get the code base and document base for this application,
300     * and to access the enclosing web page.
301     *
302     * @return the HostServices provider
303     */
304    public final HostServices getHostServices() {
305        synchronized (this) {
306            if (hostServices == null) {
307                hostServices = new HostServices(this);
308            }
309            return hostServices;
310        }
311    }
312
313    /**
314     * Retrieves the parameters for this Application, including any arguments
315     * passed on the command line and any parameters specified in a JNLP file
316     * for an applet or WebStart application.
317     *
318     * <p>
319     * NOTE: this method should not be called from the Application constructor,
320     * as it will return null. It may be called in the init() method or any
321     * time after that.
322     * </p>
323     *
324     * @return the parameters for this Application, or null if called from the
325     * constructor.
326     */
327    public final Parameters getParameters() {
328        return ParametersImpl.getParameters(this);
329    }
330
331    /**
332     * Notifies the preloader with an application-generated notification.
333     * Application code calls this method with a PreloaderNotification that is
334     * delivered to the preloader's handleApplicationNotification() method.
335     * This is primarily useful for cases where an application wants the
336     * preloader to show progress during a long application initialization
337     * step.
338     *
339     * @param info the application-generated preloader notification
340     */
341    public final void notifyPreloader(PreloaderNotification info) {
342        LauncherImpl.notifyPreloader(this, info);
343    }
344
345    /**
346     * Encapsulates the set of parameters for an application. This includes
347     * arguments passed on the command line, unnamed parameters specified
348     * in a JNLP file, and &lt;name,value&gt; pairs specified in a JNLP file.
349     *
350     * <p>
351     * Note that the application and the preloader both get the same set
352     * of parameters for a given run of an application.
353     * </p>
354     */
355    public static abstract class Parameters {
356
357        /**
358         * Retrieves a read-only list of the raw arguments. This list
359         * may be empty, but is never null. In the case of a standalone
360         * application, it is the ordered list of arguments specified on the
361         * command line. In the case of an applet or WebStart application,
362         * it includes unnamed parameters as well as named parameters. For
363         * named parameters, each &lt;name,value&gt; pair is represented as
364         * a single argument of the form: "--name=value".
365         *
366         * @return a read-only list of raw application arguments
367         */
368        public abstract List<String> getRaw();
369
370        /**
371         * Retrieves a read-only list of the unnamed parameters. This list
372         * may be empty, but is never null. The named parameters, that is
373         * the parameters that are represented as &lt;name,value&gt; pairs, are
374         * filtered out.
375         *
376         * @return a read-only list of unnamed parameters.
377         */
378        public abstract List<String> getUnnamed();
379
380        /**
381         * Retrieves a read-only map of the named parameters. It may be
382         * empty, but is never null.
383         * Named parameters include those &lt;name,value&gt; pairs explicitly
384         * specified in a JNLP file. It also includes any command line
385         * arguments of the form: "--name=value".
386         *
387         * @return a read-only map of named parameters.
388         */
389        public abstract Map<String, String> getNamed();
390
391    }
392
393    private static String userAgentStylesheet = null;
394
395    /**
396     * Get the user agent stylesheet used by the whole application. This is
397     * used to provide default styling for all ui controls and other nodes.
398     * A value of null means the platform default stylesheet is being used.
399     * <p>
400     * NOTE: This method must be called on the JavaFX Application Thread.
401     * </p>
402     *
403     * @return The URL to the stylesheet as a String.
404     */
405    public static String getUserAgentStylesheet() {
406        return userAgentStylesheet;
407    }
408
409    /**
410     * Set the user agent stylesheet used by the whole application. This is used
411     * to provide default styling for all ui controls and other nodes. Each
412     * release of JavaFX may have a new default value for this so if you need
413     * to guarantee consistency you will need to call this method and choose
414     * what default you would like for your application. A value of null will
415     * restore the platform default stylesheet. This property can also be set
416     * on the command line with {@code -Djavafx.userAgentStylesheetUrl=[URL]}
417     * Setting it on the command line overrides anything set using this method
418     * in code.
419     * <p>
420     * NOTE: This method must be called on the JavaFX Application Thread.
421     * </p>
422     *
423     *
424     * @param url The URL to the stylesheet as a String.
425     */
426    public static void setUserAgentStylesheet(String url) {
427        userAgentStylesheet = url;
428        if (url == null) {
429            PlatformImpl.setDefaultPlatformUserAgentStylesheet();
430        } else {
431            PlatformImpl.setPlatformUserAgentStylesheet(url);
432        }
433    }
434}