/**
* Copyright 2014 SAP AG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spotter.eclipse.ui.util;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.statushandlers.StatusManager;
import org.spotter.eclipse.ui.Activator;
/**
* An utility class for showing different kinds of message dialogs in the
* DynamicSpotter UI.
* <p>
* The methods to display dialogs are thread-access safe regarding the problem
* that only the UI thread is allowed to access and manipulate SWT components.
* </p>
*
* @author Denis Knoepfle
*
*/
public final class DialogUtils {
private DialogUtils() {
}
/**
* Class used only privately to retrieve a confirmation return value from a
* runnable which gets executed by a Display.syncExec().
*/
private static final class ConfirmationRunnable implements Runnable {
private boolean confirm;
private String title;
private String message;
private ConfirmationRunnable(String title, String message) {
this.title = title;
this.message = message;
}
@Override
public void run() {
confirm = MessageDialog.openConfirm(getShell(), title, message);
}
}
public static final String DEFAULT_DLG_TITLE = "DynamicSpotter";
/**
* Returns the message string with the appended cause. If cause was
* <code>null</code> or empty the message is returned unchanged.
*
* @param message
* The message to append to.
* @param cause
* The cause to append. May be <code>null</code>.
* @return the message appended by the cause
*/
public static String appendCause(String message, String cause) {
return appendCause(message, cause, false);
}
/**
* Returns the message string with the appended cause. If cause was
* <code>null</code> or empty the message is returned unchanged.
*
* @param message
* The message to append to.
* @param cause
* The cause to append. May be <code>null</code>.
* @param insertBlankLine
* <code>true</code> to insert a blank line before the cause.
* @return the message appended by the cause
*/
public static String appendCause(String message, String cause, boolean insertBlankLine) {
if (cause == null || cause.isEmpty()) {
return message;
}
String blank = insertBlankLine ? "\n\n" : " ";
String formattedCause = blank + "Cause: " + cause;
return message.concat(formattedCause);
}
/**
* Returns the display of the workbench. Can be called from any thread.
*
* @return The display of the workbench.
*/
public static Display getDisplay() {
return PlatformUI.getWorkbench().getDisplay();
}
/**
* Returns the shell of the active window in the workbench. Must be called
* from the UI thread, otherwise returns <code>null</code>.
*
* @return The active shell or <code>null</code> if none available.
*/
public static Shell getShell() {
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
return window != null ? window.getShell() : null;
}
private static void handleStatus(final IStatus status) {
if (isUIThread()) {
StatusManager.getManager().handle(status, StatusManager.SHOW | StatusManager.BLOCK);
} else {
getDisplay().syncExec(new Runnable() {
@Override
public void run() {
StatusManager.getManager().handle(status, StatusManager.SHOW | StatusManager.BLOCK);
}
});
}
}
/**
* Returns <code>true</code> if currently operating on the UI thread.
*
* @return <code>true</code> if currently operating on the UI thread
*/
private static boolean isUIThread() {
return Thread.currentThread() == getDisplay().getThread();
}
/**
* Opens asynchronously an information dialog with the given message and a
* default title. It is ensured that the dialog is opened on the UI thread.
*
* @param message
* The message of the dialog
*/
public static void openAsyncInformation(final String message) {
openInformation(DEFAULT_DLG_TITLE, message);
}
/**
* Opens asynchronously an information dialog with the given title and
* message. It is ensured that the dialog is opened on the UI thread.
*
* @param title
* The title of the dialog
* @param message
* The message of the dialog
*/
public static void openAsyncInformation(final String title, final String message) {
getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
MessageDialog.openInformation(getShell(), title, message);
}
});
}
/**
* Opens asynchronously a warning dialog with the given message and a
* default title. It is ensured that the dialog is opened on the UI thread.
*
* @param message
* The message of the dialog
*/
public static void openAsyncWarning(final String message) {
openAsyncWarning(DEFAULT_DLG_TITLE, message);
}
/**
* Opens asynchronously a warning dialog with the given title and message.
* It is ensured that the dialog is opened on the UI thread.
*
* @param title
* The title of the dialog
* @param message
* The message of the dialog
*/
public static void openAsyncWarning(final String title, final String message) {
getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
MessageDialog.openWarning(getShell(), title, message);
}
});
}
/**
* Opens a confirmation dialog with the given message and a default title.
* It is ensured that the dialog is opened on the UI thread.
*
* @param message
* The message of the dialog
* @return <code>true</code> if the user presses the OK button,
* <code>false</code> otherwise
*/
public static boolean openConfirm(final String message) {
return openConfirm(DEFAULT_DLG_TITLE, message);
}
/**
* Opens a confirmation dialog with the given title and message. It is
* ensured that the dialog is opened on the UI thread.
*
* @param title
* The title of the dialog
* @param message
* The message of the dialog
* @return <code>true</code> if the user presses the OK button,
* <code>false</code> otherwise
*/
public static boolean openConfirm(final String title, final String message) {
if (isUIThread()) {
return MessageDialog.openConfirm(getShell(), title, message);
} else {
ConfirmationRunnable runnable = new ConfirmationRunnable(title, message);
getDisplay().syncExec(runnable);
return runnable.confirm;
}
}
/**
* Opens an error dialog with the given message and a default title. It is
* ensured that the dialog is opened on the UI thread.
*
* @param message
* The message of the dialog
*/
public static void openError(final String message) {
openError(DEFAULT_DLG_TITLE, message);
}
/**
* Opens an error dialog with the given title and message. It is ensured
* that the dialog is opened on the UI thread.
*
* @param title
* The title of the dialog
* @param message
* The message of the dialog
*/
public static void openError(final String title, final String message) {
if (isUIThread()) {
MessageDialog.openError(getShell(), title, message);
} else {
getDisplay().syncExec(new Runnable() {
@Override
public void run() {
MessageDialog.openError(getShell(), title, message);
}
});
}
}
/**
* Handles an error described by the given message using the
* {@link StatusManager}. The method is safe to be called from a thread
* which is not the UI thread.
*
* @param message
* the message of the error
* @param exception
* a low-level exception to be appended, or null if not
* applicable
*/
public static void handleError(final String message, final Throwable exception) {
IStatus status = new Status(Status.ERROR, Activator.PLUGIN_ID, message, exception);
handleStatus(status);
}
/**
* Opens an information dialog with the given message and a default title.
* It is ensured that the dialog is opened on the UI thread.
*
* @param message
* The message of the dialog
*/
public static void openInformation(final String message) {
openInformation(DEFAULT_DLG_TITLE, message);
}
/**
* Opens an information dialog with the given title and message. It is
* ensured that the dialog is opened on the UI thread.
*
* @param title
* The title of the dialog
* @param message
* The message of the dialog
*/
public static void openInformation(final String title, final String message) {
if (isUIThread()) {
MessageDialog.openInformation(getShell(), title, message);
} else {
getDisplay().syncExec(new Runnable() {
@Override
public void run() {
MessageDialog.openInformation(getShell(), title, message);
}
});
}
}
/**
* Opens a warning dialog with the given message and a default title. It is
* ensured that the dialog is opened on the UI thread.
*
* @param message
* The message of the dialog
*/
public static void openWarning(final String message) {
openWarning(DEFAULT_DLG_TITLE, message);
}
/**
* Opens a warning dialog with the given title and message. It is ensured
* that the dialog is opened on the UI thread.
*
* @param title
* The title of the dialog
* @param message
* The message of the dialog
*/
public static void openWarning(final String title, final String message) {
if (isUIThread()) {
MessageDialog.openWarning(getShell(), title, message);
} else {
getDisplay().syncExec(new Runnable() {
@Override
public void run() {
MessageDialog.openWarning(getShell(), title, message);
}
});
}
}
}