/*******************************************************************************
* Copyright (c) 2012 Arapiki Solutions Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* "Peter Smith <psmith@arapiki.com>" - initial API and
* implementation and/or initial documentation
*******************************************************************************/
package com.buildml.eclipse.utils;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
/**
* A general purpose dialog box for reporting information, warnings and errors to the
* end user.
*
* @author "Peter Smith <psmith@arapiki.com>"
*/
public class AlertDialog extends TitleAreaDialog {
/*=====================================================================================*
* FIELDS/TYPES
*=====================================================================================*/
/** Maximum size of a dialog box is 1/MAX_DIALOG_RATIO of the screen height/width */
private static final int MAX_DIALOG_RATIO = 2;
/** The title of the dialog box */
private String title;
/** The detailed message to display */
private String message;
/** The severity level */
private int severity;
/** Should the dialog box provide a "cancel" choice? */
private boolean allowCancel;
/*=====================================================================================*
* CONSTRUCTORS
*=====================================================================================*/
/**
* Create a new AlertDialog. This method is private, so can only be invoked by
* the static class methods (displayInfoDialog, displayErrorDialog, etc).
* @param title The title to display in the dialog box.
* @param message The detailed message to display in the dialog box.
* @param severity The severity level (e.g. IMessageProvider.ERROR).
* @param allowCancel Should the dialog provide a "cancel" option?
*/
private AlertDialog(String title, String message, int severity, boolean allowCancel) {
super(Display.getDefault().getActiveShell());
this.title = title;
this.message = message;
this.severity = severity;
this.allowCancel = allowCancel;
/* set the title image to say "BuildML" */
Image iconImage = EclipsePartUtils.getImage("images/buildml_logo_dialog.gif");
if (iconImage != null) {
setTitleImage(iconImage);
}
}
/*=====================================================================================*
* PUBLIC METHODS
*=====================================================================================*/
/**
* Display an informational dialog box in the context of the current shell. Both
* a general message and an explanatory reason will be display. Given that there's
* only an "OK" button, there's no return code needed.
* @param title The general informational message to be displayed.
* @param message The detailed reason for the event.
*/
public static void displayInfoDialog(String title, String message) {
openDialog(title, message, IMessageProvider.INFORMATION, false);
}
/*-------------------------------------------------------------------------------------*/
/**
* Display an warning dialog box in the context of the current shell. Both
* a general message and an explanatory reason will be display. Given that there's
* only an "OK" button, there's no return code needed.
* @param title The general informational message to be displayed.
* @param message The detailed reason for the event.
*/
public static void displayWarningDialog(String title, String message) {
openDialog(title, message, IMessageProvider.WARNING, false);
}
/*-------------------------------------------------------------------------------------*/
/**
* Display an error dialog box in the context of the current shell. Both
* a general message and an explanatory reason will be display. Given that there's
* only an "OK" button, there's no return code needed.
* @param title The general error message to be displayed.
* @param message The detailed reason for the event.
*/
public static void displayErrorDialog(final String title, final String message) {
openDialog(title, message, IMessageProvider.ERROR, false);
}
/*-------------------------------------------------------------------------------------*/
/**
* Display an question dialog box in the context of the current shell. The user will
* be expected to click on OK or CANCEL to answer the question.
* @param message The question to be displayed.
* @return The answer to the question (IDialogConstants.OK_ID or IDialogConstants.CANCEL_ID).
*/
public static int displayOKCancelDialog(final String message) {
return openDialog("Question...", message, IMessageProvider.INFORMATION, true);
}
/*=====================================================================================*
* PROTECTED METHODS
*=====================================================================================*/
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
*/
@Override
protected Control createDialogArea(Composite parent) {
/* set the dialog's title, or default to "Alert" */
setHelpAvailable(false);
if (title == null) {
title = "Alert";
}
setMessage(title, severity);
/* create and format the top-level composite of this dialog */
Composite composite = (Composite) super.createDialogArea(parent);
composite.setLayout(new GridLayout());
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
composite.setLayoutData(gd);
ScrolledComposite sc = new ScrolledComposite(composite, SWT.V_SCROLL | SWT.H_SCROLL);
sc.setLayout(new GridLayout());
sc.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
/* create a label for the message, and centre it */
if (message != null) {
Label label = new Label(sc, SWT.WRAP);
label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
label.setText(message);
sc.setContent(label);
label.setSize(label.computeSize(SWT.DEFAULT, SWT.DEFAULT));
}
return parent;
}
/*-------------------------------------------------------------------------------------*/
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.Dialog#createButton(org.eclipse.swt.widgets.Composite,
* int, java.lang.String, boolean)
*/
@Override
protected Button createButton(Composite parent, int id, String label,
boolean defaultButton) {
/*
* Ignore the CANCEL button (if not needed), but display the OK button.
*/
if (!allowCancel && (id == IDialogConstants.CANCEL_ID)) {
return null;
} else {
return super.createButton(parent, id, label, defaultButton);
}
}
/*-------------------------------------------------------------------------------------*/
/**
* When the dialog box is created (based on the size of all the child widgets - particularly
* the label), make sure that it never takes up too much of the screen, otherwise it loses
* the feeling of being a Dialog.
*/
@Override
protected Point getInitialSize() {
Point initialSize = super.getInitialSize();
int screenWidth = EclipsePartUtils.getScreenWidth();
int screenHeight = EclipsePartUtils.getScreenHeight();
if (initialSize.x > (screenWidth / MAX_DIALOG_RATIO)) {
initialSize.x = screenWidth / MAX_DIALOG_RATIO;
}
if (initialSize.y > (screenHeight / MAX_DIALOG_RATIO)) {
initialSize.y = screenHeight / MAX_DIALOG_RATIO;
}
return initialSize;
}
/*=====================================================================================*
* PRIVATE METHODS
*=====================================================================================*/
/**
* Create and open a dialog box, using the UI thread. This allows non-UI code to
* raise an error.
*
* @param title The title to display in the dialog box.
* @param message The detailed message to display in the dialog box.
* @param severity The severity level (e.g. IMessageProvider.ERROR).
* @param allowCancel Should the dialog provide a "cancel" option?
* @return The dialog status (typically IDialogConstants.OK_ID or
* IDialogConstants.CANCEL_ID).
*/
private static int openDialog(
final String title, final String message, final int severity,
final boolean allowCancel) {
/* for returning the dialog code (OK/Cancel/etc) from the UI thread */
final Integer retCode[] = new Integer[1];
/* Open the dialog in the UI thread, blocking until the user presses "OK" */
Display.getDefault().syncExec(new Runnable() {
public void run() {
AlertDialog dialog = new AlertDialog(title, message, severity, allowCancel);
dialog.setBlockOnOpen(true);
dialog.open();
/* return response back to our calling thread */
retCode[0] = dialog.getReturnCode();
}
});
/* status code? (OK, Cancel, etc) */
return retCode[0];
}
/*-------------------------------------------------------------------------------------*/
}