/* * Copyright (c) 2014, 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.scene.control; import java.lang.ref.WeakReference; import java.util.Optional; import com.sun.javafx.scene.control.skin.AccordionSkin; import com.sun.javafx.scene.control.skin.resources.ControlResources; import javafx.beans.InvalidationListener; import javafx.beans.NamedArg; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import javafx.scene.Node; import javafx.scene.image.Image; import javafx.scene.image.ImageView; /** * The Alert class subclasses the {@link Dialog} class, and provides support for a number * of pre-built dialog types that can be easily shown to users to prompt for a * response. Therefore, for many users, the Alert class is the most suited class * for their needs (as opposed to using {@link Dialog} directly). Alternatively, * users who want to prompt a user for text input or to make a choice from a list * of options would be better served by using {@link TextInputDialog} and * {@link ChoiceDialog}, respectively. * *
When creating an Alert instance, users must pass in an {@link AlertType} * enumeration value. It is by passing in this value that the Alert instance will * configure itself appropriately (by setting default values for many of the * {@link Dialog} properties, including {@link #titleProperty() title}, * {@link #headerTextProperty() header}, and {@link #graphicProperty() graphic}, * as well as the default {@link #getButtonTypes() buttons} that are expected in * a dialog of the given type. * *
To instantiate (but not yet show) an Alert, simply use code such as the following: * {@code Alert alert = new Alert(AlertType.CONFIRMATION, "Are you sure you want to format your system?");} * *
Once an Alert is instantiated, we must show it. More often than not, alerts * (and dialogs in general) are shown in a modal and blocking fashion. 'Modal' * means that the dialog prevents user interaction with the owning application * whilst it is showing, and 'blocking' means that code execution stops at the * point in which the dialog is shown. This means that you can show a dialog, * await the user response, and then continue running the code that directly * follows the show call, giving developers the ability to immediately deal with * the user input from the dialog (if relevant). * *
JavaFX dialogs are modal by default (you can change this via the * {@link #initModality(javafx.stage.Modality)} API). To specify whether you want * blocking or non-blocking dialogs, developers simply choose to call * {@link #showAndWait()} or {@link #show()} (respectively). By default most * developers should choose to use {@link #showAndWait()}, given the ease of * coding in these situations. Shown below is three code snippets, showing three * equally valid ways of showing the Alert dialog that was specified above: * *
Option 1: The 'traditional' approach *
{@code Optional* *result = alert.showAndWait(); * if (result.get() == ButtonType.OK) { * formatSystem(); * }}
Option 2: The traditional + Optional approach *
{@code alert.showAndWait().ifPresent(response -> { * if (response == ButtonType.OK) { * formatSystem(); * } * });}* *
Option 3: The fully lambda approach *
{@code alert.showAndWait() * .filter(response -> response == ButtonType.OK) * .ifPresent(response -> formatSystem()); * }* *
There is no better or worse option of the three listed above, so developers
* are encouraged to work to their own style preferences. The purpose of showing
* the above is to help introduce developers to the {@link Optional} API, which
* is new in Java 8 and may be foreign to many developers.
*
* @see Dialog
* @see AlertType
* @see TextInputDialog
* @see ChoiceDialog
* @since JavaFX 8u40
*/
public class Alert extends Dialog By passing in an AlertType, default values for the
* {@link #titleProperty() title}, {@link #headerTextProperty() headerText},
* and {@link #graphicProperty() graphic} properties are set, as well as the
* relevant {@link #getButtonTypes() buttons} being installed. Once the Alert
* is instantiated, developers are able to modify the values of the alert as
* desired.
*
* It is important to note that the one property that does not have a
* default value set, and which therefore the developer must set, is the
* {@link #contentTextProperty() content text} property (or alternatively,
* the developer may call {@code alert.getDialogPane().setContent(Node)} if
* they want a more complex alert). If the contentText (or content) properties
* are not set, there is no useful information presented to end users.
*/
public Alert(@NamedArg("AlertType") AlertType alertType) {
this(alertType, "");
}
/**
* Creates an alert with the given contentText and AlertType (refer to the
* {@link AlertType} documentation for clarification over which one is most
* appropriate).
*
* By passing in an AlertType, default values for the
* {@link #titleProperty() title}, {@link #headerTextProperty() headerText},
* and {@link #graphicProperty() graphic} properties are set, as well as the
* relevant {@link #getButtonTypes() buttons} being installed. Once the Alert
* is instantiated, developers are able to modify the values of the alert as
* desired.
*/
public Alert(@NamedArg("AlertType") AlertType alertType,
@NamedArg("contentText") String contentText) {
this(alertType, contentText, (ButtonType[])null);
}
/**
* Creates an alert with the given contentText, ButtonTypes, and AlertType
* (refer to the {@link AlertType} documentation for clarification over which
* one is most appropriate).
*
* By passing in a variable number of ButtonType arguments, the developer
* is directly overriding the default buttons that will be displayed in the
* dialog, replacing the pre-defined buttons with whatever is specified in the
* varargs array.
*
* By passing in an AlertType, default values for the
* {@link #titleProperty() title}, {@link #headerTextProperty() headerText},
* and {@link #graphicProperty() graphic} properties are set. Once the Alert
* is instantiated, developers are able to modify the values of the alert as
* desired.
*/
public Alert(@NamedArg("AlertType") AlertType alertType,
@NamedArg("contentText") String contentText,
ButtonType... buttons) {
super();
final DialogPane dialogPane = getDialogPane();
dialogPane.setContentText(contentText);
dialogPaneRef = new WeakReference<>(dialogPane);
hasCustomButtons = buttons != null && buttons.length > 0;
if (hasCustomButtons) {
for (ButtonType btnType : buttons) {
dialogPane.getButtonTypes().addAll(btnType);
}
}
setAlertType(alertType);
// listening to property changes on Dialog and DialogPane
dialogPaneProperty().addListener(o -> updateListeners());
titleProperty().addListener(titleListener);
updateListeners();
}
/**************************************************************************
*
* Properties
*
**************************************************************************/
/**
* When creating an Alert instance, users must pass in an {@link AlertType}
* enumeration value. It is by passing in this value that the Alert instance will
* configure itself appropriately (by setting default values for many of the
* {@link Dialog} properties, including {@link #titleProperty() title},
* {@link #headerTextProperty() header}, and {@link #graphicProperty() graphic},
* as well as the default {@link #getButtonTypes() buttons} that are expected in
* a dialog of the given type.
*/
// --- alertType
private final ObjectProperty Readers should refer to the {@link ButtonType} class documentation for more details,
* but at a high level, each ButtonType instance is converted to
* a Node (although most commonly a {@link Button}) via the (overridable)
* {@link DialogPane#createButton(ButtonType)} method on {@link DialogPane}.
*/
// --- buttonTypes
public final ObservableList