blob: dcee79b3ac79f5aa79dcb1fb2e062807732fc195 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.progress;
import java.util.ArrayList;
import java.util.Collection;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
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.List;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
/**
* The ErrorNotificationDialog is is the dialog that comes up when an error has
* occured.
*/
public class ErrorNotificationDialog extends Dialog {
TableViewer errorViewer;
Button clearButton;
List detailsList;
private Clipboard clipboard;
private ErrorInfo selectedError = null;
/**
* Reserve room for this many details list items.
*/
private static final int DETAILS_LIST_ITEM_COUNT = 7;
/**
* The nesting indent.
*/
private static final String NESTING_INDENT = " "; //$NON-NLS-1$
/**
* Create a new instance of the receiver.
*
* @param parentShell
*/
public ErrorNotificationDialog(Shell parentShell) {
super(parentShell == null
? ProgressManagerUtil.getDefaultParent()
: parentShell);
setBlockOnOpen(false);
setShellStyle(SWT.CLOSE | SWT.MODELESS | SWT.BORDER | SWT.TITLE
| SWT.RESIZE);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
*/
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText(ProgressMessages
.getString("ErrorNotificationDialog.ErrorNotificationTitle")); //$NON-NLS-1$
newShell.addDisposeListener(new DisposeListener() {
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
*/
public void widgetDisposed(DisposeEvent e) {
getManager().clearDialog();
}
});
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.window.Window#getShellStyle()
*/
protected int getShellStyle() {
return super.getShellStyle() | SWT.MIN;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
*/
protected Control createDialogArea(Composite parent) {
initializeDialogUnits(parent);
Composite topArea = (Composite) super.createDialogArea(parent);
errorViewer = new TableViewer(topArea, SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL | SWT.BORDER);
errorViewer.setSorter(getViewerSorter());
errorViewer.getControl().addMouseListener(new MouseAdapter() {
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.events.MouseAdapter#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
*/
public void mouseDoubleClick(MouseEvent e) {
openErrorDialog();
}
});
errorViewer
.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
clearButton.setEnabled(!errorViewer.getSelection()
.isEmpty());
setDetailsContents();
}
});
Control control = errorViewer.getControl();
GridData data = new GridData(GridData.FILL_BOTH
| GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL);
data.widthHint = convertWidthInCharsToPixels(60);
data.heightHint = convertHeightInCharsToPixels(10);
control.setLayoutData(data);
initContentProvider();
initLabelProvider();
applyDialogFont(parent);
createDetailsList(topArea);
return topArea;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
*/
protected void createButtonsForButtonBar(Composite parent) {
clearButton = createButton(
parent,
IDialogConstants.CLIENT_ID + 2,
ProgressMessages
.getString("ErrorNotificationDialog.ClearButtonTitle"), false); //$NON-NLS-1$
clearButton.setEnabled(false);
clearButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
ISelection rawSelection = errorViewer.getSelection();
if (rawSelection != null
&& rawSelection instanceof IStructuredSelection) {
IStructuredSelection selection = (IStructuredSelection) rawSelection;
getManager().removeErrors(selection.toList());
}
refresh();
}
});
Button button = createButton(parent, IDialogConstants.CLOSE_ID,
IDialogConstants.CLOSE_LABEL, true);
button.addSelectionListener(new SelectionListener() {
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent e) {
close();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent e) {
close();
}
});
}
/**
* Return a viewer sorter for looking at the jobs.
*
* @return
*/
private ViewerSorter getViewerSorter() {
return new ViewerSorter() {
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ViewerSorter#compare(org.eclipse.jface.viewers.Viewer,
* java.lang.Object, java.lang.Object)
*/
public int compare(Viewer testViewer, Object e1, Object e2) {
return ((Comparable) e1).compareTo(e2);
}
};
}
/**
* Sets the content provider for the viewer.
*/
protected void initContentProvider() {
IContentProvider provider = new IStructuredContentProvider() {
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IContentProvider#dispose()
*/
public void dispose() {
//Nothing of interest here
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
*/
public Object[] getElements(Object inputElement) {
return getManager().getErrors().toArray();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
* java.lang.Object, java.lang.Object)
*/
public void inputChanged(Viewer viewer, Object oldInput,
Object newInput) {
if (newInput != null)
refresh();
}
};
errorViewer.setContentProvider(provider);
errorViewer.setInput(getManager());
}
/**
* Get the notificationManager that this is being created for.
*
* @return
*/
private ErrorNotificationManager getManager() {
return ProgressManager.getInstance().errorManager;
}
/**
* Refresh the contents of the viewer.
*/
void refresh() {
errorViewer.refresh();
}
private void initLabelProvider() {
ITableLabelProvider provider = new ITableLabelProvider() {
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)
*/
public void addListener(ILabelProviderListener listener) {
//Do nothing
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
*/
public void dispose() {
//Do nothing
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object,
* int)
*/
public Image getColumnImage(Object element, int columnIndex) {
return JFaceResources.getImageRegistry().get(
ErrorNotificationManager.ERROR_JOB_KEY);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object,
* int)
*/
public String getColumnText(Object element, int columnIndex) {
return ((ErrorInfo) element).getDisplayString();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object,
* java.lang.String)
*/
public boolean isLabelProperty(Object element, String property) {
return false;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)
*/
public void removeListener(ILabelProviderListener listener) {
//Do nothing
}
};
errorViewer.setLabelProvider(provider);
}
/**
* Open the error dialog on the current selection.
*/
private void openErrorDialog() {
ErrorInfo element = getSingleSelection();
if (element == null)
return;
ErrorDialog.openError(getShell(), element.getDisplayString(), null,
element.getErrorStatus());
}
/**
* Get the single selection. Return null if the selection is not just one
* element.
*
* @return ErrorInfo or <code>null</code>.
*/
private ErrorInfo getSingleSelection() {
ISelection rawSelection = errorViewer.getSelection();
if (rawSelection != null
&& rawSelection instanceof IStructuredSelection) {
IStructuredSelection selection = (IStructuredSelection) rawSelection;
if (selection.size() == 1)
return (ErrorInfo) selection.getFirstElement();
}
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.dialogs.Dialog#close()
*/
public boolean close() {
getManager().clearAllErrors();
Rectangle shellPosition = getShell().getBounds();
boolean result = super.close();
ProgressManagerUtil.animateDown(shellPosition);
return result;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.dialogs.Dialog#initializeBounds()
*/
protected void initializeBounds() {
super.initializeBounds();
Rectangle shellPosition = getShell().getBounds();
ProgressManagerUtil.animateUp(shellPosition);
}
/**
* Create this dialog's drop-down list component.
*
* @param detailsParent
* the parent composite
*/
private void createDetailsList(Composite detailsParent) {
// create the list
detailsList = new List(detailsParent, SWT.BORDER | SWT.H_SCROLL
| SWT.V_SCROLL | SWT.MULTI);
GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL
| GridData.GRAB_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL
| GridData.GRAB_VERTICAL);
data.heightHint = detailsList.getItemHeight() * DETAILS_LIST_ITEM_COUNT;
data.horizontalSpan = 2;
detailsList.setLayoutData(data);
Menu copyMenu = new Menu(detailsList);
MenuItem copyItem = new MenuItem(copyMenu, SWT.NONE);
copyItem.addSelectionListener(new SelectionListener() {
/*
* @see SelectionListener.widgetSelected (SelectionEvent)
*/
public void widgetSelected(SelectionEvent e) {
copyToClipboard();
}
/*
* @see SelectionListener.widgetDefaultSelected(SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent e) {
copyToClipboard();
}
});
copyItem.setText(JFaceResources.getString("copy")); //$NON-NLS-1$
detailsList.setMenu(copyMenu);
}
/**
* Set the contents of the details list to be the status from the selected
* error.
*/
private void setDetailsContents() {
Collection statusList = new ArrayList();
ErrorInfo info = getSingleSelection();
if (info != null) {
selectedError = info;
statusList.add(selectedError.getErrorStatus().getMessage());
if (selectedError.getErrorStatus().getException() != null) {
Throwable exception = selectedError.getErrorStatus()
.getException();
statusList.add(exception.toString());
StackTraceElement[] elements = exception.getStackTrace();
for (int i = 0; i < elements.length; i++) {
statusList.add(elements[i].toString());
}
}
IStatus[] statuses = (selectedError.getErrorStatus().getChildren());
for (int i = 0; i < statuses.length; i++) {
statusList.add(NESTING_INDENT + statuses[i].getMessage());
}
}
String[] items = new String[statusList.size()];
statusList.toArray(items);
detailsList.setItems(items);
}
/**
* Copy the contents of the statuses to the clipboard.
*/
private void copyToClipboard() {
if (selectedError == null)
return;
if (clipboard != null)
clipboard.dispose();
StringBuffer statusBuffer = new StringBuffer();
populateCopyBuffer(selectedError.getErrorStatus(), statusBuffer, 0);
clipboard = new Clipboard(detailsList.getDisplay());
clipboard.setContents(new Object[]{statusBuffer.toString()},
new Transfer[]{TextTransfer.getInstance()});
}
/**
* Put the details of the status of the error onto the stream.
*
* @param buildingStatus
* @param buffer
* @param nesting
*/
private void populateCopyBuffer(IStatus buildingStatus,
StringBuffer buffer, int nesting) {
for (int i = 0; i < nesting; i++) {
buffer.append(NESTING_INDENT); //$NON-NLS-1$
}
buffer.append(buildingStatus.getMessage());
if (buildingStatus.getException() != null) {
Throwable exception = buildingStatus.getException();
buffer.append("\n"); //$NON-NLS-1$
buffer.append(exception.toString());
StackTraceElement[] elements = exception.getStackTrace();
for (int i = 0; i < elements.length; i++) {
buffer.append("\n"); //$NON-NLS-1$
buffer.append(elements[i].toString());
}
}
buffer.append("\n"); //$NON-NLS-1$
IStatus[] children = buildingStatus.getChildren();
for (int i = 0; i < children.length; i++) {
populateCopyBuffer(children[i], buffer, nesting + 1);
}
}
}