### Eclipse Workspace Patch 1.0 #P org.eclipse.ui.workbench Index: Eclipse UI/org/eclipse/ui/statushandlers/AbstractStatusHandler.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/statushandlers/AbstractStatusHandler.java,v retrieving revision 1.9 diff -u -r1.9 AbstractStatusHandler.java --- Eclipse UI/org/eclipse/ui/statushandlers/AbstractStatusHandler.java 15 May 2007 12:38:58 -0000 1.9 +++ Eclipse UI/org/eclipse/ui/statushandlers/AbstractStatusHandler.java 13 Jan 2009 12:03:57 -0000 @@ -136,4 +136,22 @@ public void setId(String id) { this.id = id; } + + /** + * This methods indicates if the status handler supports specific kind of + * notification. If some kind of notification is supported, then + * {@link StatusManager#fireNotification(int, StatusAdapter[])} has to be + * called when particular event occurs. Only known notification types should + * be accepted, whereas unkown types should be always rejected, because it + * is possible that more types will be introduced over time. + * + * @param type + * - a notification type that should be checked. + * @return true if particular event notification is supported, false + * otherwise + * @since 3.5 + */ + public boolean supportsNotification(int type){ + return false; + } } Index: Eclipse UI/org/eclipse/ui/statushandlers/WorkbenchStatusDialogManager.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/statushandlers/WorkbenchStatusDialogManager.java,v retrieving revision 1.25 diff -u -r1.25 WorkbenchStatusDialogManager.java --- Eclipse UI/org/eclipse/ui/statushandlers/WorkbenchStatusDialogManager.java 15 Dec 2008 08:46:35 -0000 1.25 +++ Eclipse UI/org/eclipse/ui/statushandlers/WorkbenchStatusDialogManager.java 13 Jan 2009 12:03:57 -0000 @@ -95,6 +95,7 @@ import org.eclipse.ui.internal.statushandlers.DefaultDetailsArea; import org.eclipse.ui.internal.statushandlers.StackTraceSupportArea; import org.eclipse.ui.progress.IProgressConstants; +import org.eclipse.ui.statushandlers.StatusManager.INotificationType; import com.ibm.icu.text.DateFormat; @@ -1227,6 +1228,9 @@ modals.put(statusAdapter, new Boolean(modal)); // Delay prompting if the status adapter property is set if (shouldPrompt(statusAdapter)) { + StatusManager.getManager() + .fireNotification(INotificationType.HANDLED, + new StatusAdapter[] {}); if (dialog == null) { dialog = new InternalDialog(getParentShell(), WorkbenchStatusDialogManager.this, shouldBeModal()); @@ -1242,6 +1246,9 @@ } } else { + StatusManager.getManager().fireNotification( + INotificationType.HANDLED, + new StatusAdapter[] { statusAdapter }); if (statusAdapter .getProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY) != null) { statusAdapter.setProperty( Index: Eclipse UI/org/eclipse/ui/statushandlers/WorkbenchErrorHandler.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/statushandlers/WorkbenchErrorHandler.java,v retrieving revision 1.27 diff -u -r1.27 WorkbenchErrorHandler.java --- Eclipse UI/org/eclipse/ui/statushandlers/WorkbenchErrorHandler.java 22 Dec 2008 10:35:49 -0000 1.27 +++ Eclipse UI/org/eclipse/ui/statushandlers/WorkbenchErrorHandler.java 13 Jan 2009 12:03:57 -0000 @@ -18,6 +18,7 @@ import org.eclipse.ui.PlatformUI; import org.eclipse.ui.application.WorkbenchAdvisor; import org.eclipse.ui.internal.WorkbenchPlugin; +import org.eclipse.ui.statushandlers.StatusManager.INotificationType; /** * This is a default workbench error handler. @@ -27,6 +28,16 @@ */ public class WorkbenchErrorHandler extends AbstractStatusHandler { + /* (non-Javadoc) + * @see org.eclipse.ui.statushandlers.AbstractStatusHandler#supportsNotification(int) + */ + public boolean supportsNotification(int type) { + if (type == INotificationType.HANDLED) { + return true; + } + return super.supportsNotification(type); + } + private WorkbenchStatusDialogManager statusDialogManager; /* Index: Eclipse UI/org/eclipse/ui/statushandlers/StatusManager.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/statushandlers/StatusManager.java,v retrieving revision 1.26 diff -u -r1.26 StatusManager.java --- Eclipse UI/org/eclipse/ui/statushandlers/StatusManager.java 22 Sep 2008 10:03:50 -0000 1.26 +++ Eclipse UI/org/eclipse/ui/statushandlers/StatusManager.java 13 Jan 2009 12:03:57 -0000 @@ -17,6 +17,7 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.ILogListener; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.Dialog; @@ -25,8 +26,6 @@ import org.eclipse.ui.internal.WorkbenchErrorHandlerProxy; import org.eclipse.ui.internal.WorkbenchPlugin; import org.eclipse.ui.internal.misc.StatusUtil; -import org.eclipse.ui.internal.progress.FinishedJobs; -import org.eclipse.ui.internal.progress.StatusAdapterHelper; import org.eclipse.ui.internal.statushandlers.StatusHandlerRegistry; import org.eclipse.ui.progress.IProgressConstants; @@ -110,10 +109,12 @@ private static StatusManager MANAGER; - private AbstractStatusHandler workbenchHandler; + private AbstractStatusHandler statusHandler; private List loggedStatuses = new ArrayList(); + private ListenerList listeners = new ListenerList(); + /** * Returns StatusManager singleton instance. * @@ -130,17 +131,21 @@ Platform.addLogListener(new StatusManagerLogListener()); } - /** - * @return the workbench status handler - */ - private AbstractStatusHandler getWorkbenchHandler() { - if (workbenchHandler == null) { - workbenchHandler = new WorkbenchErrorHandlerProxy(); + private AbstractStatusHandler getStatusHandler(){ + if(statusHandler == null && StatusHandlerRegistry.getDefault() + .getDefaultHandlerDescriptor() != null){ + try { + statusHandler = StatusHandlerRegistry.getDefault() + .getDefaultHandlerDescriptor().getStatusHandler(); + } catch (CoreException ex) { + logError("Errors during the default handler creating", ex); //$NON-NLS-1$ + } } - - return workbenchHandler; + if(statusHandler == null){ + statusHandler = new WorkbenchErrorHandlerProxy(); + } + return statusHandler; } - /** * Handles the given status adapter due to the style. Because the facility * depends on Workbench, this method will log the status, if Workbench isn't @@ -180,42 +185,17 @@ return; } - // tries to handle the problem with default (product) handler - if (StatusHandlerRegistry.getDefault() - .getDefaultHandlerDescriptor() != null) { - try { - StatusHandlerRegistry.getDefault() - .getDefaultHandlerDescriptor().getStatusHandler() - .handle(statusAdapter, style); - // if statuses are shown, all finished jobs with error will - // be removed, - // we should remove it from the status manager, when error - // icon - // will be part of handlers not ProgressAnimationItem - if (((style & StatusManager.SHOW) == StatusManager.SHOW || (style & StatusManager.BLOCK) == StatusManager.BLOCK) - && statusAdapter - .getProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY) != Boolean.TRUE) { - FinishedJobs.getInstance().removeErrorJobs(); - StatusAdapterHelper.getInstance().clear(); - } - return; - } catch (CoreException ex) { - logError("Errors during the default handler creating", ex); //$NON-NLS-1$ - } - } - // delegates the problem to workbench handler - getWorkbenchHandler().handle(statusAdapter, style); - - // if statuses are shown, all finished jobs with error will be - // removed, - // we should remove it from the status manager, when error icon - // will be part of handlers not ProgressAnimationItem - if (((style & StatusManager.SHOW) == StatusManager.SHOW || (style & StatusManager.BLOCK) == StatusManager.BLOCK) - && statusAdapter - .getProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY) != Boolean.TRUE) { - FinishedJobs.getInstance().removeErrorJobs(); + getStatusHandler().handle(statusAdapter, style); + + // if attached status handler is not able to notify StatusManager + // about particular event, use the default policy and fake the + // notification + if (!getStatusHandler().supportsNotification( + INotificationType.HANDLED)) { + generateFakeNotification(statusAdapter, style); } + } catch (Throwable ex) { // The used status handler failed logError(statusAdapter.getStatus()); @@ -329,4 +309,101 @@ } } } + + /** + * This method should be called by custom status handlers when an event + * occurs. This method will have no effect if statushandler does not declare + * that particular event type is supported. + * + * @param type + * - type of the event. + * @param adapters + * - array of affected {@link StatusAdapter}s. + * @see IStatusAdapterConstants + * @since 3.5 + */ + public void fireNotification(int type, StatusAdapter[] adapters){ + if(getStatusHandler().supportsNotification(type)){ + doFireNotification(type, adapters); + } + } + + private void doFireNotification(int type, StatusAdapter[] adapters) { + Object[] oListeners = listeners.getListeners(); + for (int i = 0; i < oListeners.length; i++) { + if (oListeners[i] instanceof INotificationListener) { + ((INotificationListener) oListeners[i]) + .statusManagerNotified(type, adapters); + } + } + } + + private void generateFakeNotification(StatusAdapter statusAdapter, int style) { + if (((style & StatusManager.SHOW) == StatusManager.SHOW || (style & StatusManager.BLOCK) == StatusManager.BLOCK) + && statusAdapter + .getProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY) != Boolean.TRUE) { + doFireNotification(INotificationType.HANDLED, + new StatusAdapter[] { statusAdapter }); + } + } + + /** + * Adds a listener to the StatusManager. + * + * @param listener + * - a listener to be added. + * @since 3.5 + */ + public void addListener(INotificationListener listener) { + this.listeners.add(listener); + } + + /** + * Removes a listener from StatusManager. + * + * @param listener + * - a listener to be removed. + * @since 3.5 + */ + public void removeListener(INotificationListener listener){ + this.listeners.remove(listener); + } + + /** + * This interface allows for listening to status handling framework changes. + * Currently it is possible to be notified when: + * + * @since 3.5 + * + */ + public interface INotificationListener{ + /** + * + * @param type + * - a type of notification. + * @param adapters + * - affected {@link StatusAdapter}s + */ + public void statusManagerNotified(int type, StatusAdapter[] adapters); + } + + /** + * This interface declares types of notification. + * + * @since 3.5 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + * + */ + public interface INotificationType { + + /** + * This type notifications are used when a particular + * {@link StatusAdapter} was handled. + */ + public static final int HANDLED = 0x01; + + } } Index: Eclipse UI/org/eclipse/ui/internal/WorkbenchErrorHandlerProxy.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchErrorHandlerProxy.java,v retrieving revision 1.8 diff -u -r1.8 WorkbenchErrorHandlerProxy.java --- Eclipse UI/org/eclipse/ui/internal/WorkbenchErrorHandlerProxy.java 16 Mar 2007 18:00:31 -0000 1.8 +++ Eclipse UI/org/eclipse/ui/internal/WorkbenchErrorHandlerProxy.java 13 Jan 2009 12:03:56 -0000 @@ -36,4 +36,13 @@ Workbench.getInstance().getAdvisor().getWorkbenchErrorHandler().handle( statusAdapter, style); } + + /* (non-Javadoc) + * @see org.eclipse.ui.statushandlers.AbstractStatusHandler#supportsNotification(int) + */ + public boolean supportsNotification(int type) { + return Workbench.getInstance().getAdvisor().getWorkbenchErrorHandler() + .supportsNotification(type); + } + } Index: Eclipse UI/org/eclipse/ui/internal/progress/ProgressManager.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/progress/ProgressManager.java,v retrieving revision 1.139 diff -u -r1.139 ProgressManager.java --- Eclipse UI/org/eclipse/ui/internal/progress/ProgressManager.java 29 Apr 2008 07:09:16 -0000 1.139 +++ Eclipse UI/org/eclipse/ui/internal/progress/ProgressManager.java 13 Jan 2009 12:03:57 -0000 @@ -67,6 +67,7 @@ import org.eclipse.ui.progress.WorkbenchJob; import org.eclipse.ui.statushandlers.StatusAdapter; import org.eclipse.ui.statushandlers.StatusManager; +import org.eclipse.ui.statushandlers.StatusManager.INotificationType; /** * JobProgressManager provides the progress monitor to the job manager and @@ -370,6 +371,16 @@ } catch (MalformedURLException e) { ProgressManagerUtil.logException(e); } + StatusManager.getManager().addListener(new StatusManager.INotificationListener(){ + + public void statusManagerNotified(int type, StatusAdapter[] adapters) { + if(type == INotificationType.HANDLED){ + FinishedJobs.getInstance().removeErrorJobs(); + StatusAdapterHelper.getInstance().clear(); + } + } + + }); } /** #P org.eclipse.ui.tests Index: Eclipse UI Tests/org/eclipse/ui/tests/statushandlers/StatusHandlingConfigurationTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/statushandlers/StatusHandlingConfigurationTest.java,v retrieving revision 1.1 diff -u -r1.1 StatusHandlingConfigurationTest.java --- Eclipse UI Tests/org/eclipse/ui/tests/statushandlers/StatusHandlingConfigurationTest.java 3 Dec 2008 11:25:24 -0000 1.1 +++ Eclipse UI Tests/org/eclipse/ui/tests/statushandlers/StatusHandlingConfigurationTest.java 13 Jan 2009 12:03:58 -0000 @@ -13,9 +13,11 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; +import org.eclipse.ui.progress.IProgressConstants; import org.eclipse.ui.statushandlers.AbstractStatusHandler; import org.eclipse.ui.statushandlers.StatusAdapter; import org.eclipse.ui.statushandlers.StatusManager; +import org.eclipse.ui.statushandlers.StatusManager.INotificationType; import junit.framework.TestCase; @@ -38,4 +40,23 @@ StatusManager.getManager().handle(adapter); assertEquals(true, called[0]); } + + public void testDefaultNotification(){ + final StatusAdapter adapter = new StatusAdapter(new Status(IStatus.ERROR,"fakeplugin","testmessage")); + adapter.setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE); + final StatusAdapter adapter2 = new StatusAdapter(new Status(IStatus.ERROR,"fakeplugin2","testmessage2")); + final boolean[] called = new boolean[]{false}; + StatusManager.getManager().addListener(new StatusManager.INotificationListener(){ + public void statusManagerNotified(int type, + StatusAdapter[] adapters) { + if (type == INotificationType.HANDLED) + called[0] = true; + } + }); + StatusManager.getManager().handle(adapter, StatusManager.SHOW); + assertEquals(false, called[0]); + StatusManager.getManager().handle(adapter2, StatusManager.SHOW); + assertEquals(true, called[0]); + + } }