| /******************************************************************************* |
| * Copyright (c) 2009, 2010 IBM Corporation and others. |
| * 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: |
| * IBM Corporation - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.ui.internal.statushandlers; |
| |
| import com.ibm.icu.text.DateFormat; |
| import java.net.URL; |
| import java.util.Collection; |
| import java.util.Date; |
| import java.util.Map; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.jface.resource.LocalResourceManager; |
| import org.eclipse.jface.resource.ResourceManager; |
| import org.eclipse.jface.viewers.ILabelDecorator; |
| import org.eclipse.jface.viewers.ILabelProviderListener; |
| import org.eclipse.jface.viewers.ITableLabelProvider; |
| import org.eclipse.jface.viewers.Viewer; |
| import org.eclipse.jface.viewers.ViewerComparator; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.ui.internal.WorkbenchMessages; |
| import org.eclipse.ui.internal.progress.ProgressManager; |
| import org.eclipse.ui.internal.progress.ProgressMessages; |
| import org.eclipse.ui.progress.IProgressConstants; |
| import org.eclipse.ui.statushandlers.IStatusAdapterConstants; |
| import org.eclipse.ui.statushandlers.StatusAdapter; |
| |
| |
| /** |
| * This is an utility class which is responsible for text and icon decorators in |
| * the StatusDialog. |
| * |
| * @since 3.6 |
| */ |
| public class LabelProviderWrapper extends ViewerComparator implements |
| ITableLabelProvider { |
| /** |
| * The default status label provider. |
| */ |
| private class DefaultLabelProvider implements ITableLabelProvider { |
| ResourceManager manager = new LocalResourceManager(JFaceResources |
| .getResources()); |
| |
| /* |
| * (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() { |
| manager.dispose(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java |
| * .lang.Object, int) |
| */ |
| public Image getColumnImage(Object element, int columnIndex) { |
| Image result = null; |
| if (element != null) { |
| StatusAdapter statusAdapter = ((StatusAdapter) element); |
| Job job = (Job) (statusAdapter.getAdapter(Job.class)); |
| if (job != null) { |
| result = getIcon(job); |
| } |
| } |
| // if somehow disposed image was received (should not happen) |
| if (result != null && result.isDisposed()) { |
| result = null; |
| } |
| return result; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java. |
| * lang.Object, int) |
| */ |
| public String getColumnText(Object element, int columnIndex) { |
| StatusAdapter statusAdapter = (StatusAdapter) element; |
| String text = WorkbenchMessages.WorkbenchStatusDialog_ProblemOccurred; |
| if (!isMulti()) { |
| Job job = (Job) (statusAdapter.getAdapter(Job.class)); |
| if (job != null) { |
| text = getPrimaryMessage(statusAdapter); |
| } else { |
| text = getSecondaryMessage(statusAdapter); |
| } |
| } else { |
| Job job = (Job) (statusAdapter.getAdapter(Job.class)); |
| if (job != null) { |
| text = job.getName(); |
| } else { |
| text = getPrimaryMessage(statusAdapter); |
| } |
| } |
| Long timestamp = (Long) statusAdapter |
| .getProperty(IStatusAdapterConstants.TIMESTAMP_PROPERTY); |
| |
| if (timestamp != null && isMulti()) { |
| String date = DateFormat.getDateTimeInstance(DateFormat.LONG, |
| DateFormat.LONG) |
| .format(new Date(timestamp.longValue())); |
| return NLS.bind(ProgressMessages.JobInfo_Error, (new Object[] { |
| text, date })); |
| } |
| return text; |
| } |
| |
| /* |
| * Get the icon for the job. |
| */ |
| private Image getIcon(Job job) { |
| if (job != null) { |
| Object property = job |
| .getProperty(IProgressConstants.ICON_PROPERTY); |
| |
| // Create an image from the job's icon property or family |
| if (property instanceof ImageDescriptor) { |
| return manager.createImage((ImageDescriptor) property); |
| } else if (property instanceof URL) { |
| return manager.createImage(ImageDescriptor |
| .createFromURL((URL) property)); |
| } else { |
| // Let the progress manager handle the resource management |
| return ProgressManager.getInstance().getIconFor(job); |
| } |
| } |
| return null; |
| } |
| |
| /* |
| * (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 |
| } |
| } |
| |
| private ITableLabelProvider labelProvider; |
| |
| /** |
| * This field stores the decorator which can override various texts produced |
| * by this class. |
| */ |
| private ILabelDecorator messageDecorator; |
| |
| private Map dialogState; |
| |
| /** |
| * @param dialogState |
| */ |
| public LabelProviderWrapper(Map dialogState) { |
| this.dialogState = dialogState; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang |
| * .Object, int) |
| */ |
| public Image getColumnImage(Object element, int columnIndex) { |
| return labelProvider.getColumnImage(element, columnIndex); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang |
| * .Object, int) |
| */ |
| public String getColumnText(Object element, int columnIndex) { |
| return getLabelProvider().getColumnText(element, columnIndex); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse. |
| * jface.viewers.ILabelProviderListener) |
| */ |
| public void addListener(ILabelProviderListener listener) { |
| getLabelProvider().addListener(listener); |
| } |
| |
| /** |
| * This method disposes the label provider if and only if the dialog is not |
| * changing its state. |
| * |
| * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose() |
| */ |
| public void dispose() { |
| boolean modalitySwitch = ((Boolean) dialogState.get(IStatusDialogConstants.MODALITY_SWITCH)) |
| .booleanValue(); |
| if (!modalitySwitch) { |
| getLabelProvider().dispose(); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang |
| * .Object, java.lang.String) |
| */ |
| public boolean isLabelProperty(Object element, String property) { |
| return getLabelProvider().isLabelProperty(element, property); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse |
| * .jface.viewers.ILabelProviderListener) |
| */ |
| public void removeListener(ILabelProviderListener listener) { |
| getLabelProvider().removeListener(listener); |
| } |
| |
| /** |
| * Gets {@link Image} associated with current {@link StatusAdapter} |
| * severity. |
| * |
| * @param statusAdapter |
| * |
| * @return {@link Image} associated with current {@link StatusAdapter} |
| * severity. |
| */ |
| public Image getImage(StatusAdapter statusAdapter) { |
| if (statusAdapter != null) { |
| int severity = statusAdapter.getStatus().getSeverity(); |
| switch (severity) { |
| case IStatus.OK: |
| case IStatus.INFO: |
| case IStatus.CANCEL: |
| return getSWTImage(SWT.ICON_INFORMATION); |
| case IStatus.WARNING: |
| return getSWTImage(SWT.ICON_WARNING); |
| default: /* IStatus.ERROR */ |
| return getSWTImage(SWT.ICON_ERROR); |
| } |
| } |
| // should not never happen but if we do not know what is going on, then |
| // return error image. |
| return getSWTImage(SWT.ICON_ERROR); |
| } |
| |
| /** |
| * Get an <code>Image</code> from the provide SWT image constant. |
| * |
| * @param imageID |
| * the SWT image constant |
| * @return image the image |
| */ |
| public Image getSWTImage(final int imageID) { |
| return Display.getCurrent().getSystemImage(imageID); |
| } |
| |
| /** |
| * This method computes the dialog main message. |
| * |
| * If there is only one reported status adapter, main message should be: |
| * <ul> |
| * <li>information about job that reported an error.</li> |
| * <li>primary message, if the statusAdapter was not reported by job</li> |
| * </ul> |
| * |
| * If there is more reported statusAdapters, main message should be: |
| * <ul> |
| * <li>primary message for job reported statusAdapters</li> |
| * <li>secondary message for statuses not reported by jobs</li> |
| * </ul> |
| * |
| * If nothing can be found, some general information should be displayed. |
| * |
| * @param statusAdapter |
| * A status adapter which is used as the base for computation. |
| * @return main message of the dialog. |
| * |
| * @see #getPrimaryMessage(StatusAdapter) |
| * @see #getSecondaryMessage(StatusAdapter) |
| */ |
| public String getMainMessage(StatusAdapter statusAdapter) { |
| if (!isMulti()) { |
| Job job = (Job) (statusAdapter.getAdapter(Job.class)); |
| // job |
| if (job != null) { |
| return NLS |
| .bind( |
| WorkbenchMessages.WorkbenchStatusDialog_ProblemOccurredInJob, |
| job.getName()); |
| } |
| // we are not handling job |
| return getPrimaryMessage(statusAdapter); |
| } |
| // we have a list. primary message or job name or on the list name (both |
| // with timestamp if available). |
| // we display secondary message or status |
| if (isMulti()) { |
| Job job = (Job) (statusAdapter.getAdapter(Job.class)); |
| // job |
| if (job != null) { |
| return getPrimaryMessage(statusAdapter); |
| } |
| |
| // plain status |
| return getSecondaryMessage(statusAdapter); |
| } |
| return WorkbenchMessages.WorkbenchStatusDialog_ProblemOccurred; |
| } |
| |
| /** |
| * Retrieves primary message from passed statusAdapter. Primary message |
| * should be (from the most important): |
| * <ul> |
| * <li>statusAdapter title</li> |
| * <li>IStatus message</li> |
| * <li>pointing to child statuses if IStatus has them.</li> |
| * <li>exception message</li> |
| * <li>exception class</li> |
| * <li>general message informing about error (no details at all)</li> |
| * </ul> |
| * |
| * @param statusAdapter |
| * an status adapter to retrieve primary message from |
| * @return String containing primary message |
| * |
| * @see #getMainMessage(StatusAdapter) |
| * @see #getSecondaryMessage(StatusAdapter) |
| */ |
| public String getPrimaryMessage(StatusAdapter statusAdapter) { |
| // if there was nonempty title set, display the title |
| Object property = statusAdapter |
| .getProperty(IStatusAdapterConstants.TITLE_PROPERTY); |
| if (property instanceof String) { |
| String header = (String) property; |
| if (header.trim().length() > 0) { |
| return decorate(header, statusAdapter); |
| } |
| } |
| // if there was message set in the status |
| IStatus status = statusAdapter.getStatus(); |
| if (status.getMessage() != null |
| && status.getMessage().trim().length() > 0) { |
| return decorate(status.getMessage(), statusAdapter); |
| } |
| |
| // if status has children |
| if (status.getChildren().length > 0) { |
| return WorkbenchMessages.WorkbenchStatusDialog_StatusWithChildren; |
| } |
| |
| // check the exception |
| Throwable t = status.getException(); |
| if (t != null) { |
| if (t.getMessage() != null && t.getMessage().trim().length() > 0) { |
| return decorate(t.getMessage(), statusAdapter); |
| } |
| return t.getClass().getName(); |
| } |
| return WorkbenchMessages.WorkbenchStatusDialog_ProblemOccurred; |
| } |
| |
| /** |
| * Retrieves secondary message from the passed statusAdapter. Secondary |
| * message is one level lower than primary. Secondary message should be |
| * (from the most important): |
| * <ul> |
| * <li>IStatus message</li> |
| * <li>pointing to child statuses if IStatus has them.</li> |
| * <li>exception message</li> |
| * <li>exception class</li> |
| * </ul> |
| * Secondary message should not be the same as primary one. If no secondary |
| * message can be extracted, details should be pointed. |
| * |
| * @param statusAdapter |
| * an status adapter to retrieve secondary message from |
| * @return String containing secondary message |
| * |
| * @see #getMainMessage(StatusAdapter) |
| * @see #getPrimaryMessage(StatusAdapter) |
| */ |
| public String getSecondaryMessage(StatusAdapter statusAdapter) { |
| String primary = getPrimaryMessage(statusAdapter); |
| // we can skip the title, it is always displayed as primary message |
| |
| // if there was message set in the status |
| IStatus status = statusAdapter.getStatus(); |
| String message = status.getMessage(); |
| String decoratedMessage = message == null ? null : decorate(message, |
| statusAdapter); |
| if (message != null && message.trim().length() > 0 |
| && !primary.equals(decoratedMessage)) { |
| /* we have not displayed it yet */ |
| return decoratedMessage; |
| } |
| // if status has children |
| if (status.getChildren().length > 0 |
| && !primary.equals(decoratedMessage)) { |
| return WorkbenchMessages.WorkbenchStatusDialog_StatusWithChildren; |
| } |
| |
| // check the exception |
| Throwable t = status.getException(); |
| if (t != null) { |
| if (t.getMessage() != null) { |
| String decoratedThrowable = decorate(t.getMessage(), |
| statusAdapter); |
| if (t.getMessage().trim().length() > 0 |
| && !primary.equals(decoratedThrowable)) { |
| return decoratedThrowable; |
| } |
| } |
| String throwableName = t.getClass().getName(); |
| if (!primary.equals(throwableName)) { |
| return throwableName; |
| } |
| } |
| return WorkbenchMessages.WorkbenchStatusDialog_SeeDetails; |
| } |
| |
| private String decorate(String string, StatusAdapter adapter) { |
| messageDecorator = (ILabelDecorator) dialogState |
| .get(IStatusDialogConstants.DECORATOR); |
| if (messageDecorator != null) { |
| string = messageDecorator.decorateText(string, adapter); |
| } |
| return string; |
| } |
| |
| private int compare(StatusAdapter s1, StatusAdapter s2) { |
| Long timestamp1 = ((Long) s1 |
| .getProperty(IStatusAdapterConstants.TIMESTAMP_PROPERTY)); |
| Long timestamp2 = ((Long) s2 |
| .getProperty(IStatusAdapterConstants.TIMESTAMP_PROPERTY)); |
| if (timestamp1 == null || timestamp2 == null |
| || (timestamp1.equals(timestamp2))) { |
| String text1 = getColumnText(s1, 0); |
| String text2 = getColumnText(s2, 0); |
| return text1.compareTo(text2); |
| } |
| |
| if (timestamp1.longValue() < timestamp2.longValue()) { |
| return -1; |
| } |
| if (timestamp1.longValue() > timestamp2.longValue()) { |
| return 1; |
| } |
| // should be never called |
| return 0; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface. |
| * viewers.Viewer, java.lang.Object, java.lang.Object) |
| */ |
| public int compare(Viewer testViewer, Object o1, Object o2) { |
| if (o1 instanceof StatusAdapter && o2 instanceof StatusAdapter) { |
| return compare((StatusAdapter) o1, (StatusAdapter) o2); |
| } |
| // should not happen |
| if (o1.hashCode() < o2.hashCode()) { |
| return -1; |
| } |
| if (o2.hashCode() > o2.hashCode()) { |
| return 1; |
| } |
| return 0; |
| } |
| |
| private boolean isMulti() { |
| return ((Collection) dialogState |
| .get(IStatusDialogConstants.STATUS_ADAPTERS)).size() > 1; |
| } |
| |
| /** |
| * @return Returns the labelProvider. |
| */ |
| public ITableLabelProvider getLabelProvider() { |
| ITableLabelProvider temp = (ITableLabelProvider) dialogState |
| .get(IStatusDialogConstants.CUSTOM_LABEL_PROVIDER); |
| if (temp != null) { |
| labelProvider = temp; |
| } |
| if (labelProvider == null) { |
| labelProvider = new DefaultLabelProvider(); |
| } |
| return labelProvider; |
| } |
| } |