/*
 * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javafx.application;

import java.security.AccessController;
import java.security.PrivilegedAction;

Class that is extended to define an optional preloader for a JavaFX Application. An application may contain a preloader that is used to improve the application loading experience.

A preloader is a small application that is started before the main application to customize the startup experience. The preloader:

  • gets notification of progress of loading application resources
  • gets notification of errors
  • gets notification of application initialization and startup
  • decides when application should become visible

The default preloader is shown on top of the application Stage, which is not visible until the preloader is visible. The preloader need to hide itself to make the application visible. Good practice is to do this no earlier than right before application.start() is called, as otherwise application itself is not visible.

The preloader may also cooperate with the application to achieve advanced visual effects or share data (e.g. to implement login screen). The preloader gets a reference to the application and may pull data it needs for cooperation from the application if the application implements an interface that the preloader knows about and relies upon. Generally it is not recommended to design preloaders in such a way that an application would call them directly, as this will result in bad user experience if the application is signed and the preloader is not.

If the application does not specify a preloader, then the default preloader is used. Default preloader appearance can be customized (set of parameters is TBD).

Custom preloader implementations should follow these rules:

  1. a custom preloader class should extend Preloader
  2. classes needed for preloader need to be packaged in the separate jar.

Applications may also send custom notification to the preloader using the notifyPreloader method. This way a preloader may also show application initialization progress.

Note that preloaders are subject to the same rules as other JavaFX applications including FX threading rules. In particular, the class constructor and init() method will be called on a non-FX thread and start() will be executed on the FX application thread. This also means that the application constructor/init() will run concurrently with preloader start().

Callbacks on preloader notification will be delivered on the FX application thread.

Shutdown (including when stop() is called) is TBD.

Since:JavaFX 2.0
/** * Class that is extended to define an optional preloader for a * JavaFX Application. * An application may contain a preloader that is used * to improve the application loading experience. * * <p> * A preloader is a small application that is started * before the main application to customize the startup experience. * The preloader: * </p> * <ul> * <li>gets notification of progress of loading application resources</li> * <li>gets notification of errors</li> * <li>gets notification of application initialization and startup</li> * <li>decides when application should become visible</li> * </ul> * * <p> * The default preloader is shown on top of the application Stage, which is not * visible until the preloader is visible. The preloader need to hide itself * to make the application visible. Good practice is to do this no earlier than * right before application.start() is called, as otherwise application itself * is not visible. * </p> * * <p> * The preloader may also cooperate with the application to achieve advanced * visual effects or share data (e.g. to implement login screen). * The preloader gets a reference to the application and may pull data it * needs for cooperation from the application if the application implements * an interface that the preloader knows about and relies upon. Generally it * is not recommended to design preloaders in such a way that an application * would call them directly, as this will result in bad user experience if * the application is signed and the preloader is not. * </p> * * <p> * If the application does not specify a preloader, then the default preloader * is used. Default preloader appearance can be customized * (set of parameters is TBD). * </p> * * <p> * Custom preloader implementations should follow these rules: * </p> * <ol> * <li>a custom preloader class should extend Preloader</li> * <li>classes needed for preloader need to be packaged in the separate jar.</li> * </ol> * * <p> * Applications may also send custom notification to the preloader using the * {@link #notifyPreloader notifyPreloader} method. This way a preloader may * also show application initialization progress. * </p> * * <p> * Note that preloaders are subject to the same rules as other JavaFX * applications including FX threading rules. In particular, the class * constructor and init() method will be called on a non-FX thread and start() * will be executed on the FX application thread. * This also means that the application constructor/init() will run concurrently * with preloader start(). * </p> * * <p> * Callbacks on preloader notification will be delivered on the FX * application thread. * </p> * * <p> * Shutdown (including when stop() is called) is TBD. * </p> * @since JavaFX 2.0 */
public abstract class Preloader extends Application { // Too bad this isn't already available in a Java core class private static final String lineSeparator; static { String prop = AccessController.doPrivileged((PrivilegedAction<String>) () -> System.getProperty("line.separator")); lineSeparator = prop != null ? prop : "\n"; }
Indicates download progress. This method is called by the FX runtime to indicate progress while application resources are being loaded. It will not be called to deliver a ProgressNotification sent to notifyPreloader.

The implementation of this method provided by the Preloader class does nothing.

Params:
  • info – the progress notification
/** * Indicates download progress. * This method is called by the FX runtime to indicate progress while * application resources are being loaded. It will not be called to deliver * a ProgressNotification sent to {@link #notifyPreloader notifyPreloader}. * * <p> * The implementation of this method provided by the Preloader class * does nothing. * </p> * * @param info the progress notification */
public void handleProgressNotification(ProgressNotification info) { }
Indicates a change in application state. This method is called by the FX runtime as part of the application life-cycle.

The implementation of this method provided by the Preloader class does nothing.

Params:
  • info – the state change notification
/** * Indicates a change in application state. * This method is called by the FX runtime as part of the * application life-cycle. * * <p> * The implementation of this method provided by the Preloader class * does nothing. * </p> * * @param info the state change notification */
public void handleStateChangeNotification(StateChangeNotification info) { }
Indicates an application-generated notification. This method is called by the FX runtime to deliver a notification sent via notifyPreloader.

Applications should not call this method directly, but should use notifyPreloader instead to avoid mixed code dialog issues.

The implementation of this method provided by the Preloader class does nothing.

Params:
  • info – the application-generated notification
/** * Indicates an application-generated notification. * This method is called by the FX runtime to deliver a notification sent * via {@link #notifyPreloader notifyPreloader}. * * <p> * Applications should not call this method directly, but should use * {@link #notifyPreloader notifyPreloader} instead to avoid mixed code dialog issues. * </p> * * <p> * The implementation of this method provided by the Preloader class * does nothing. * </p> * * @param info the application-generated notification */
public void handleApplicationNotification(PreloaderNotification info) { }
Called when an error occurs.

The implementation of this method provided by the Preloader class returns false, indicating that the default error handler should show the message to the user.

Params:
  • info – the error notification describing the cause of this error
Returns:true if error was shown to the user by preloader and no additional visualization is needed; otherwise, false.
/** * Called when an error occurs. * * <p> * The implementation of this method provided by the Preloader class * returns false, indicating that the default error handler should * show the message to the user. * </p> * * @param info the error notification describing the cause of this error * * @return true if error was shown to the user by preloader and no * additional visualization is needed; otherwise, false. */
public boolean handleErrorNotification(ErrorNotification info) { return false; } // /** // * Called when security or other system modal dialog is shown or hidden // * (such as proxy auth dialog). // * // * <p> // * The implementation of this method provided by the Preloader class // * does nothing. // * </p> // * // * @param info the UI notification // */ // public void handleUINotification(UINotification info) { // // TODO RT-19601: not used for now pending completion of JRE work //// System.err.println("Preloader: handleUINotification = " + info); // } // ------------------------------------------------------------------------
Marker interface for all Preloader notification.
Since:JavaFX 2.0
/** * Marker interface for all Preloader notification. * @since JavaFX 2.0 */
public static interface PreloaderNotification { }
Preloader notification that reports an error. This is delivered to preloader in case of problem with application startup.
Since:JavaFX 2.0
/** * Preloader notification that reports an error. * This is delivered to preloader in case of problem with application startup. * @since JavaFX 2.0 */
public static class ErrorNotification implements PreloaderNotification { private String location; private String details = ""; private Throwable cause;
Constructs an error notification.
Params:
  • location – the URL associated with an error (if any); may be null
  • details – a string describing the error; must be non-null
  • cause – the cause of the error; may be null
/** * Constructs an error notification. * * @param location the URL associated with an error (if any); may be null * @param details a string describing the error; must be non-null * @param cause the cause of the error; may be null */
public ErrorNotification(String location, String details, Throwable cause) { if (details == null) throw new NullPointerException(); this.location = location; this.details = details; this.cause = cause; }
Retrieves the URL associated with this error, if any. For example, if there is a download or singing check error, this will be the URL of the jar file that has the problem. It may be null.
Returns:the location, or null
/** * Retrieves the URL associated with this error, if any. * For example, if there is a download or singing check error, this * will be the URL of the jar file that has the problem. * It may be null. * * @return the location, or null */
public String getLocation() { return location; }
Retrieves the description of the error. It may be the empty string, but is always non-null.
Returns:the description of the error
/** * Retrieves the description of the error. * It may be the empty string, but is always non-null. * * @return the description of the error */
public String getDetails() { return details; }
Retrieves the Exception or Error associated with this error notification, if any. It may be null.
Returns:the cause of the error, or null
/** * Retrieves the Exception or Error associated with this error * notification, if any. It may be null. * * @return the cause of the error, or null */
public Throwable getCause() { return cause; }
Returns a string representation of this ErrorNotification object.
Returns:a string representation of this ErrorNotification object.
/** * Returns a string representation of this {@code ErrorNotification} object. * @return a string representation of this {@code ErrorNotification} object. */
@Override public String toString() { StringBuilder str = new StringBuilder("Preloader.ErrorNotification: "); str.append(details); if (cause != null) { str.append(lineSeparator).append("Caused by: ").append(cause.toString()); } if (location != null) { str.append(lineSeparator).append("Location: ").append(location); } return str.toString(); } }
Preloader notification that reports progress. This is typically used to report progress while downloading and initializing the application.
Since:JavaFX 2.0
/** * Preloader notification that reports progress. This is typically used to * report progress while downloading and initializing the application. * @since JavaFX 2.0 */
public static class ProgressNotification implements PreloaderNotification { private final double progress; private final String details;
Constructs a progress notification.
Params:
  • progress – a value indicating the progress. A negative value for progress indicates that the progress is indeterminate. A value between 0 and 1 indicates the amount of progress. Any value greater than 1 is interpreted as 1.
/** * Constructs a progress notification. * * @param progress a value indicating the progress. * A negative value for progress indicates that the progress is * indeterminate. A value between 0 and 1 indicates the amount * of progress. Any value greater than 1 is interpreted as 1. */
public ProgressNotification(double progress) { this(progress, ""); } // NOTE: We could consider exposing details in the future, but currently // have no plan to do so. This method is private for now.
Constructs a progress notification.
Params:
  • progress – a value indicating the progress. A negative value for progress indicates that the progress is indeterminate. A value between 0 and 1 indicates the amount of progress. Any value greater than 1 is interpreted as 1.
  • details – the details of this notification
/** * Constructs a progress notification. * * @param progress a value indicating the progress. * A negative value for progress indicates that the progress is * indeterminate. A value between 0 and 1 indicates the amount * of progress. Any value greater than 1 is interpreted as 1. * * @param details the details of this notification */
private ProgressNotification(double progress, String details) { this.progress = progress; this.details = details; }
Retrieves the progress for this notification. Progress is in the range of 0 to 1, or is negative for indeterminate progress.
Returns:the progress
/** * Retrieves the progress for this notification. Progress is in the * range of 0 to 1, or is negative for indeterminate progress. * * @return the progress */
public double getProgress() { return progress; }
Retrieves the details of the progress notification
Returns:the details of this notification
/** * Retrieves the details of the progress notification * * @return the details of this notification */
private String getDetails() { return details; } }
A notification that signals a change in the application state. A state change notification is sent to a preloader immediately prior to loading the application class (and constructing an instance), calling the application init method, or calling the application start method.
Since:JavaFX 2.0
/** * A notification that signals a change in the application state. * A state change notification is sent to a preloader immediately prior * to loading * the application class (and constructing an instance), calling the * application init method, or calling the application start method. * @since JavaFX 2.0 */
public static class StateChangeNotification implements PreloaderNotification {
Enum that defines the type of change associated with this notification
Since:JavaFX 2.0
/** * Enum that defines the type of change associated with this notification * @since JavaFX 2.0 */
public enum Type {
Indicates that the application class is about to be loaded and constructed.
/** * Indicates that the application class is about to be loaded and * constructed. */
BEFORE_LOAD,
Indicates that the application's init method is about to be called.
/** * Indicates that the application's init method is about to be called. */
BEFORE_INIT,
Indicates that the application's start method is about to be called.
/** * Indicates that the application's start method is about to be called. */
BEFORE_START } private final Type notificationType; private final Application application;
Constructs a StateChangeNotification of the specified type.
Params:
  • notificationType – the type of this notification.
/** * Constructs a StateChangeNotification of the specified type. * * @param notificationType the type of this notification. */
public StateChangeNotification(Type notificationType){ this.notificationType = notificationType; this.application = null; }
Constructs an StateChangeNotification of the specified type for the specified application.
Params:
  • notificationType – the type of this notification.
  • application – the application instance associated with this notification.
/** * Constructs an StateChangeNotification of the specified type for the * specified application. * * @param notificationType the type of this notification. * @param application the application instance associated with this * notification. */
public StateChangeNotification(Type notificationType, Application application) { this.notificationType = notificationType; this.application = application; }
Returns the type of notification.
Returns:one of: BEFORE_LOAD, BEFORE_INIT, BEFORE_START
/** * Returns the type of notification. * * @return one of: BEFORE_LOAD, BEFORE_INIT, BEFORE_START */
public Type getType() { return notificationType; }
Returns the Application instance associated with this notification. This is null for a BEFORE_LOAD notification and non-null for other notification types.
Returns:the Application instance or null.
/** * Returns the Application instance associated with this notification. * This is null for a BEFORE_LOAD notification and non-null for other * notification types. * * @return the Application instance or null. */
public Application getApplication() { return application; } } // /** // * Used to signal about global modal dialogs to be shown that block // * application launch. In particular proxy and security dialogs // */ // public static class UINotification implements PreloaderNotification { // //TODO RT-19601: implementation pending JRE work // } }