org.eclipse.jface.dialogs.MessageDialogWithToggle Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Patrik Suzzi - Bug 490700
* David Weister - Bug 511626
*******************************************************************************/
package org.eclipse.jface.dialogs;
import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter;
import java.util.LinkedHashMap;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
/**
*
* A message dialog which also allows the user to adjust a toggle setting. If a
* preference store is provided and the user selects the toggle, then the user's
* answer (yes/ok or no) will be persisted in the store. If no store is
* provided, then this information can be queried after the dialog closes.
*
*
* This type of dialog should be used whenever you want to user to be able to
* avoid being prompted in the future. It is strongly
* recommended that a cancel option be provided, so that the user has the option
* of making the decision at a later point in time. The semantic for a cancel
* button should be to cancel the operation (if it has not yet started), or stop
* the operation (if it has already started).
*
*
* It is the responsibility of the developer to provide a mechanism for the user
* to change this preference at some later point in time (e.g., through a
* preference page).
*
*
* @since 3.0
*/
public class MessageDialogWithToggle extends MessageDialog {
/**
* The value of the preference when the user has asked that the answer to
* the question always be "okay" or "yes".
*/
public static final String ALWAYS = "always"; //$NON-NLS-1$
/**
* The value of the preference when the user has asked that the answer to
* the question always be "no".
*/
public static final String NEVER = "never"; //$NON-NLS-1$
/**
* The value of the preference when the user wishes to prompted for an
* answer every time the question is to be asked.
*/
public static final String PROMPT = "prompt"; //$NON-NLS-1$
/**
* Convenience method to open a simple dialog as specified by the kind
flag,
* with a "don't show again' toggle.
*
* @param kind
* the kind of dialog to open, one of {@link #ERROR},
* {@link #INFORMATION}, {@link #QUESTION}, {@link #WARNING},
* {@link #CONFIRM}, or {#QUESTION_WITH_CANCEL}.
* @param parent
* the parent shell of the dialog, or null
if none
* @param title
* the dialog's title, or null
if none
* @param message
* the message
* @param toggleMessage
* the message for the toggle control, or null
for
* the default message
* @param toggleState
* the initial state for the toggle
* @param store
* the IPreference store in which the user's preference should be
* persisted; null
if you don't want it persisted
* automatically.
* @param key
* the key to use when persisting the user's preference;
* null
if you don't want it persisted.
* @param style
* {@link SWT#NONE} for a default dialog, or {@link SWT#SHEET} for
* a dialog with sheet behavior
* @return the dialog, after being closed by the user, which the client can
* only call getReturnCode()
or
* getToggleState()
* @since 3.5
*/
public static MessageDialogWithToggle open(int kind, Shell parent, String title,
String message, String toggleMessage, boolean toggleState,
IPreferenceStore store, String key, int style) {
MessageDialogWithToggle dialog = new MessageDialogWithToggle(parent,
title, null, // accept the default window icon
message, kind, getButtonLabels(kind), 0,
toggleMessage, toggleState);
style &= SWT.SHEET;
dialog.setShellStyle(dialog.getShellStyle() | style);
dialog.prefStore = store;
dialog.prefKey = key;
dialog.open();
return dialog;
}
/**
* Convenience method to open a simple dialog as specified by the
* kind
flag, with a "don't show again' toggle.
*
* This method accepts a LinkedHashMap<String, Integer> to set custom
* button labels (String) and custom button IDs (Integer) as return codes for
* those buttons.
*
* Use this method if you need to override the default labels and IDs.
*
* @param kind the kind of dialog to open, one of {@link #ERROR},
* {@link #INFORMATION}, {@link #QUESTION},
* {@link #WARNING}, {@link #CONFIRM}, or
* {#QUESTION_WITH_CANCEL}.
* @param parent the parent shell of the dialog, or
* null
if none
* @param title the dialog's title, or null
if none
* @param message the message
* @param toggleMessage the message for the toggle control, or
* null
for the default message
* @param toggleState the initial state for the toggle
* @param store the IPreference store in which the user's
* preference should be persisted; null
* if you don't want it persisted automatically.
* @param key the key to use when persisting the user's
* preference; null
if you don't want it
* persisted.
* @param style {@link SWT#NONE} for a default dialog, or
* {@link SWT#SHEET} for a dialog with sheet behavior
* @param buttonLabelToIdMap map with button labels and ids to define custom
* labels and their corresponding ids
* @return the dialog, after being closed by the user, which the client can only
* call getReturnCode()
or getToggleState()
* @since 3.13
*/
public static MessageDialogWithToggle open(int kind, Shell parent, String title, String message,
String toggleMessage, boolean toggleState, IPreferenceStore store, String key, int style,
LinkedHashMap buttonLabelToIdMap) {
// use null as image to accept the default window icon
MessageDialogWithToggle dialog = new MessageDialogWithToggle(parent, title, null, message, kind,
buttonLabelToIdMap, 0, toggleMessage, toggleState);
style &= SWT.SHEET;
dialog.setShellStyle(dialog.getShellStyle() | style);
dialog.prefStore = store;
dialog.prefKey = key;
dialog.open();
return dialog;
}
/**
* Convenience method to open a standard error dialog.
*
* @param parent
* the parent shell of the dialog, or null
if none
* @param title
* the dialog's title, or null
if none
* @param message
* the message
* @param toggleMessage
* the message for the toggle control, or null
for
* the default message
* @param toggleState
* the initial state for the toggle
* @param store
* the IPreference store in which the user's preference should be
* persisted; null
if you don't want it persisted
* automatically.
* @param key
* the key to use when persisting the user's preference;
* null
if you don't want it persisted.
* @return the dialog, after being closed by the user, which the client can
* only call getReturnCode()
or
* getToggleState()
*/
public static MessageDialogWithToggle openError(Shell parent, String title,
String message, String toggleMessage, boolean toggleState,
IPreferenceStore store, String key) {
return open(ERROR, parent, title, message, toggleMessage, toggleState, store, key, SWT.NONE);
}
/**
* Convenience method to open a standard information dialog.
*
* @param parent
* the parent shell of the dialog, or null
if none
* @param title
* the dialog's title, or null
if none
* @param message
* the message
* @param toggleMessage
* the message for the toggle control, or null
for
* the default message
* @param toggleState
* the initial state for the toggle
* @param store
* the IPreference store in which the user's preference should be
* persisted; null
if you don't want it persisted
* automatically.
* @param key
* the key to use when persisting the user's preference;
* null
if you don't want it persisted.
*
* @return the dialog, after being closed by the user, which the client can
* only call getReturnCode()
or
* getToggleState()
*/
public static MessageDialogWithToggle openInformation(Shell parent,
String title, String message, String toggleMessage,
boolean toggleState, IPreferenceStore store, String key) {
return open(INFORMATION, parent, title, message, toggleMessage, toggleState, store, key, SWT.NONE);
}
/**
* Convenience method to open a simple confirm (OK/Cancel) dialog.
*
* @param parent
* the parent shell of the dialog, or null
if none
* @param title
* the dialog's title, or null
if none
* @param message
* the message
* @param toggleMessage
* the message for the toggle control, or null
for
* the default message
* @param toggleState
* the initial state for the toggle
* @param store
* the IPreference store in which the user's preference should be
* persisted; null
if you don't want it persisted
* automatically.
* @param key
* the key to use when persisting the user's preference;
* null
if you don't want it persisted.
* @return the dialog, after being closed by the user, which the client can
* only call getReturnCode()
or
* getToggleState()
*/
public static MessageDialogWithToggle openOkCancelConfirm(Shell parent,
String title, String message, String toggleMessage,
boolean toggleState, IPreferenceStore store, String key) {
return open(CONFIRM, parent, title, message, toggleMessage, toggleState, store, key, SWT.NONE);
}
/**
* Convenience method to open a standard warning dialog.
*
* @param parent
* the parent shell of the dialog, or null
if none
* @param title
* the dialog's title, or null
if none
* @param message
* the message
* @param toggleMessage
* the message for the toggle control, or null
for
* the default message
* @param toggleState
* the initial state for the toggle
* @param store
* the IPreference store in which the user's preference should be
* persisted; null
if you don't want it persisted
* automatically.
* @param key
* the key to use when persisting the user's preference;
* null
if you don't want it persisted.
* @return the dialog, after being closed by the user, which the client can
* only call getReturnCode()
or
* getToggleState()
*/
public static MessageDialogWithToggle openWarning(Shell parent,
String title, String message, String toggleMessage,
boolean toggleState, IPreferenceStore store, String key) {
return open(WARNING, parent, title, message, toggleMessage, toggleState, store, key, SWT.NONE);
}
/**
* Convenience method to open a simple question Yes/No/Cancel dialog.
*
* @param parent
* the parent shell of the dialog, or null
if none
* @param title
* the dialog's title, or null
if none
* @param message
* the message
* @param toggleMessage
* the message for the toggle control, or null
for
* the default message
* @param toggleState
* the initial state for the toggle
* @param store
* the IPreference store in which the user's preference should be
* persisted; null
if you don't want it persisted
* automatically.
* @param key
* the key to use when persisting the user's preference;
* null
if you don't want it persisted.
* @return the dialog, after being closed by the user, which the client can
* only call getReturnCode()
or
* getToggleState()
*/
public static MessageDialogWithToggle openYesNoCancelQuestion(Shell parent,
String title, String message, String toggleMessage,
boolean toggleState, IPreferenceStore store, String key) {
return open(QUESTION_WITH_CANCEL, parent, title, message, toggleMessage, toggleState, store, key, SWT.NONE);
}
/**
* Convenience method to open a simple Yes/No question dialog.
*
* @param parent
* the parent shell of the dialog, or null
if none
* @param title
* the dialog's title, or null
if none
* @param message
* the message
* @param toggleMessage
* the message for the toggle control, or null
for
* the default message
* @param toggleState
* the initial state for the toggle
* @param store
* the IPreference store in which the user's preference should be
* persisted; null
if you don't want it persisted
* automatically.
* @param key
* the key to use when persisting the user's preference;
* null
if you don't want it persisted.
*
* @return the dialog, after being closed by the user, which the client can
* only call getReturnCode()
or
* getToggleState()
*/
public static MessageDialogWithToggle openYesNoQuestion(Shell parent,
String title, String message, String toggleMessage,
boolean toggleState, IPreferenceStore store, String key) {
return open(QUESTION, parent, title, message, toggleMessage, toggleState, store, key, SWT.NONE);
}
/**
* The key at which the toggle state should be stored within the
* preferences. This value may be null
, which indicates that
* no preference should be updated automatically. It is then the
* responsibility of the user of this API to use the information from the
* toggle. Note: a prefStore
is also needed.
*/
private String prefKey = null;
/**
* The preference store which will be affected by the toggle button. This
* value may be null
, which indicates that no preference
* should be updated automatically. It is then the responsibility of the
* user of this API to use the information from the toggle. Note: a
* prefKey
is also needed.
*/
private IPreferenceStore prefStore = null;
/**
* The toggle button (widget). This value is null
until the
* dialog is created.
*/
private Button toggleButton = null;
/**
* The message displayed to the user, with the toggle button. This is the
* text besides the toggle. If it is null
, this means that
* the default text for the toggle should be used.
*/
private String toggleMessage;
/**
* The initial selected state of the toggle.
*/
private boolean toggleState;
/**
* The mapping for custom buttons and ids
*
* Allows clients to override the default label and id mapping
*/
private LinkedHashMap buttonLabelToIdMap;
/**
* Creates a message dialog with a toggle. See the superclass constructor
* for info on the other parameters.
*
* @param parentShell
* the parent shell
* @param dialogTitle
* the dialog title, or null
if none
* @param image
* the dialog title image, or null
if none
* @param message
* the dialog message
* @param dialogImageType
* one of the following values:
*
* MessageDialog.NONE
for a dialog with no
* image
* MessageDialog.ERROR
for a dialog with an
* error image
* MessageDialog.INFORMATION
for a dialog
* with an information image
* MessageDialog.QUESTION
for a dialog with a
* question image
* MessageDialog.WARNING
for a dialog with a
* warning image
*
* @param dialogButtonLabels
* an array of labels for the buttons in the button bar
* @param defaultIndex
* the index in the button label array of the default button
* @param toggleMessage
* the message for the toggle control, or null
for
* the default message
* @param toggleState
* the initial state for the toggle
*/
public MessageDialogWithToggle(Shell parentShell, String dialogTitle,
Image image, String message, int dialogImageType,
String[] dialogButtonLabels, int defaultIndex,
String toggleMessage, boolean toggleState) {
super(parentShell, dialogTitle, image, message, dialogImageType, defaultIndex, dialogButtonLabels);
this.toggleMessage = toggleMessage;
this.toggleState = toggleState;
setButtonLabels(dialogButtonLabels);
}
/**
* Creates a message dialog with a toggle. See the superclass constructor for
* info on the other parameters.
*
* This constructor accepts a LinkedHashMap<String, Integer> to set custom
* button labels (String) and custom button IDs (Integer) as return codes for
* those buttons.
*
* Use this constructor if you need to override the default labels and IDs.
*
* @param parentShell the parent shell
* @param dialogTitle the dialog title, or null
if none
* @param image the dialog title image, or null
if
* none
* @param message the dialog message
* @param dialogImageType one of the following values:
*
* MessageDialog.NONE
for a dialog
* with no image
* MessageDialog.ERROR
for a dialog
* with an error image
* MessageDialog.INFORMATION
for a
* dialog with an information image
* MessageDialog.QUESTION
for a
* dialog with a question image
* MessageDialog.WARNING
for a dialog
* with a warning image
*
* @param buttonLabelToIdMap map with button labels and IDs to define custom
* labels and their corresponding IDs
* @param defaultIndex the index of the default button in the button label
* and ID map related to the insertion order of the
* elements
* @param toggleMessage the message for the toggle control, or
* null
for the default message
* @param toggleState the initial state for the toggle
* @since 3.13
*/
public MessageDialogWithToggle(Shell parentShell, String dialogTitle, Image image, String message,
int dialogImageType, LinkedHashMap buttonLabelToIdMap, int defaultIndex,
String toggleMessage,
boolean toggleState) {
super(parentShell, dialogTitle, image, message, dialogImageType, defaultIndex,
buttonLabelToIdMap.keySet().toArray(new String[buttonLabelToIdMap.size()]));
this.toggleMessage = toggleMessage;
this.toggleState = toggleState;
this.buttonLabelToIdMap = buttonLabelToIdMap;
}
/**
* @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int)
*/
@Override
protected void buttonPressed(int buttonId) {
super.buttonPressed(buttonId);
if (buttonId != IDialogConstants.CANCEL_ID && toggleState
&& prefStore != null && prefKey != null) {
switch (buttonId) {
case IDialogConstants.YES_ID:
case IDialogConstants.YES_TO_ALL_ID:
case IDialogConstants.PROCEED_ID:
case IDialogConstants.OK_ID:
prefStore.setValue(prefKey, ALWAYS);
break;
case IDialogConstants.NO_ID:
case IDialogConstants.NO_TO_ALL_ID:
prefStore.setValue(prefKey, NEVER);
break;
}
}
}
/**
* @see Dialog#createButtonBar(Composite)
*/
@Override
protected void createButtonsForButtonBar(Composite parent) {
final String[] buttonLabels = getButtonLabels();
final Button[] buttons = new Button[buttonLabels.length];
final int defaultButtonIndex = getDefaultButtonIndex();
int suggestedId = IDialogConstants.INTERNAL_ID;
for (int i = 0; i < buttonLabels.length; i++) {
String label = buttonLabels[i];
// get the JFace button ID that matches the label, or use the specified
// id if there is no match.
int id = mapButtonLabelToButtonID(label, suggestedId);
// if the suggested id was used, increment the default for next use
if (id == suggestedId) {
suggestedId++;
}
Button button = createButton(parent, id, label,
defaultButtonIndex == i);
buttons[i] = button;
}
setButtons(buttons);
}
/**
* @see Dialog#createDialogArea(Composite)
*/
@Override
protected Control createDialogArea(Composite parent) {
Composite dialogAreaComposite = (Composite) super
.createDialogArea(parent);
setToggleButton(createToggleButton(dialogAreaComposite));
return dialogAreaComposite;
}
/**
* Creates a toggle button without any text or state. The text and state
* will be created by createDialogArea
.
*
* @param parent
* The composite in which the toggle button should be placed;
* must not be null
.
* @return The added toggle button; never null
.
*/
protected Button createToggleButton(Composite parent) {
final Button button = new Button(parent, SWT.CHECK | SWT.LEFT);
GridData data = new GridData(SWT.NONE);
data.horizontalSpan = 2;
button.setLayoutData(data);
button.setFont(parent.getFont());
button.addSelectionListener(widgetSelectedAdapter(e -> toggleState = button.getSelection()));
return button;
}
/**
* Returns the toggle button.
*
* @return the toggle button
*/
protected Button getToggleButton() {
return toggleButton;
}
/**
* An accessor for the current preference store for this dialog.
*
* @return The preference store; this value may be null
if no
* preference is being used.
*/
public IPreferenceStore getPrefStore() {
return prefStore;
}
/**
* An accessor for the current key of the toggle preference.
*
* @return The preference key; this value may be null
if no
* preference is being used.
*/
public String getPrefKey() {
return prefKey;
}
/**
* Returns the toggle state. This can be called even after the dialog is
* closed.
*
* @return true
if the toggle button is checked,
* false
if not
*/
public boolean getToggleState() {
return toggleState;
}
/**
* A mutator for the key of the preference to be modified by the toggle
* button.
*
* @param prefKey
* The prefKey to set. If this value is null
,
* then no preference will be modified.
*/
public void setPrefKey(String prefKey) {
this.prefKey = prefKey;
}
/**
* A mutator for the preference store to be modified by the toggle button.
*
* @param prefStore
* The prefStore to set. If this value is null
,
* then no preference will be modified.
*/
public void setPrefStore(IPreferenceStore prefStore) {
this.prefStore = prefStore;
}
/**
* A mutator for the button providing the toggle option. If the button
* exists, then it will automatically get the text set to the current toggle
* message, and its selection state set to the current selection state.
*
* @param button
* The button to use; must not be null
.
*/
protected void setToggleButton(Button button) {
if (button == null) {
throw new NullPointerException(
"A message dialog with toggle may not have a null toggle button.");} //$NON-NLS-1$
if (!button.isDisposed()) {
final String text;
if (toggleMessage == null) {
text = JFaceResources
.getString("MessageDialogWithToggle.defaultToggleMessage"); //$NON-NLS-1$
} else {
text = toggleMessage;
}
button.setText(text);
button.setSelection(toggleState);
}
this.toggleButton = button;
}
/**
* A mutator for the text on the toggle button. The button will
* automatically get updated with the new text, if it exists.
*
* @param message
* The new text of the toggle button; if it is null
,
* then used the default toggle message.
*/
protected void setToggleMessage(String message) {
this.toggleMessage = message;
if ((toggleButton != null) && (!toggleButton.isDisposed())) {
final String text;
if (toggleMessage == null) {
text = JFaceResources
.getString("MessageDialogWithToggle.defaultToggleMessage"); //$NON-NLS-1$
} else {
text = toggleMessage;
}
toggleButton.setText(text);
}
}
/**
* A mutator for the state of the toggle button. This method will update the
* button, if it exists.
*
* @param toggleState
* The desired state of the toggle button (true
* means the toggle should be selected).
*/
public void setToggleState(boolean toggleState) {
this.toggleState = toggleState;
// Update the button, if it exists.
if ((toggleButton != null) && (!toggleButton.isDisposed())) {
toggleButton.setSelection(toggleState);
}
}
/**
* Attempt to find a standard JFace button id that matches the specified
* button label. If a {@literal LinkedHashMap} with custom button
* labels and custom button ids was set, this method first searches the Map
* to find the button id that matches the specific button label. If no match
* can be found at all, use the default id provided.
*
* @param buttonLabel
* the button label whose id is sought
* @param defaultId
* the id to use for the button if there is no custom or standard
* id
* @return the id for the specified button label
*/
private int mapButtonLabelToButtonID(String buttonLabel, int defaultId) {
if (buttonLabelToIdMap != null && buttonLabelToIdMap.containsKey(buttonLabel)) {
return buttonLabelToIdMap.get(buttonLabel).intValue();
}
// The following hard-coded mapping of labels to ID is unfortunately
// API and cannot be changed.
if (IDialogConstants.OK_LABEL.equals(buttonLabel)) {
return IDialogConstants.OK_ID;
}
if (IDialogConstants.YES_LABEL.equals(buttonLabel)) {
return IDialogConstants.YES_ID;
}
if (IDialogConstants.NO_LABEL.equals(buttonLabel)) {
return IDialogConstants.NO_ID;
}
if (IDialogConstants.CANCEL_LABEL.equals(buttonLabel)) {
return IDialogConstants.CANCEL_ID;
}
if (IDialogConstants.YES_TO_ALL_LABEL.equals(buttonLabel)) {
return IDialogConstants.YES_TO_ALL_ID;
}
if (IDialogConstants.SKIP_LABEL.equals(buttonLabel)) {
return IDialogConstants.SKIP_ID;
}
if (IDialogConstants.STOP_LABEL.equals(buttonLabel)) {
return IDialogConstants.STOP_ID;
}
if (IDialogConstants.ABORT_LABEL.equals(buttonLabel)) {
return IDialogConstants.ABORT_ID;
}
if (IDialogConstants.RETRY_LABEL.equals(buttonLabel)) {
return IDialogConstants.RETRY_ID;
}
if (IDialogConstants.IGNORE_LABEL.equals(buttonLabel)) {
return IDialogConstants.IGNORE_ID;
}
if (IDialogConstants.PROCEED_LABEL.equals(buttonLabel)) {
return IDialogConstants.PROCEED_ID;
}
if (IDialogConstants.OPEN_LABEL.equals(buttonLabel)) {
return IDialogConstants.OPEN_ID;
}
if (IDialogConstants.CLOSE_LABEL.equals(buttonLabel)) {
return IDialogConstants.CLOSE_ID;
}
if (IDialogConstants.BACK_LABEL.equals(buttonLabel)) {
return IDialogConstants.BACK_ID;
}
if (IDialogConstants.NEXT_LABEL.equals(buttonLabel)) {
return IDialogConstants.NEXT_ID;
}
if (IDialogConstants.FINISH_LABEL.equals(buttonLabel)) {
return IDialogConstants.FINISH_ID;
}
if (IDialogConstants.HELP_LABEL.equals(buttonLabel)) {
return IDialogConstants.HELP_ID;
}
if (IDialogConstants.NO_TO_ALL_LABEL.equals(buttonLabel)) {
return IDialogConstants.NO_TO_ALL_ID;
}
if (IDialogConstants.SHOW_DETAILS_LABEL.equals(buttonLabel)) {
return IDialogConstants.DETAILS_ID;
}
if (IDialogConstants.HIDE_DETAILS_LABEL.equals(buttonLabel)) {
return IDialogConstants.DETAILS_ID;
}
// No XXX_LABEL in IDialogConstants for these. Unlikely
// they would be used in a message dialog though.
// public int SELECT_ALL_ID = 18;
// public int DESELECT_ALL_ID = 19;
// public int SELECT_TYPES_ID = 20;
return defaultId;
}
}