package org.gudy.azureus2.ui.swt.progress; /** * A simple listener interface used to pass a <code>ProgressReport</code> to a listener from a <code>ProgressReporter</code> * @author knguyen * */ public interface IProgressReporterListener extends IProgressReportConstants { /** * When an event is detected this callback method will be called so listeners can take appropriate action such as updating a UI element * <p> * Currently there are 2 return types recognized: * <ul> * <li><code>RETVAL_OK</code> - Indicates the given <code>ProgressReport</code> has been consumed successfully</li> * <li><code>RETVAL_OK_TO_DISPOSE</code> - Indicates that this listener is no longer interested in any subsequent reports</li> * </ul> * </p> * * The return value of <code>RETVAL_OK_TO_DISPOSE</code> is a hint to the caller that it is now * safe to remove this listener from the caller's list of listeners. This pattern allows the caller * to perform clean up operations associated with this listener, and allows the listener to initiate * its own removal from within an event loop. * * <p> A typical life cycle of an event listener is create listener, register listener, then remove listener. * To accomplish all three steps we would need a reference to the listeners at all time as can be seen in this sample: </p> * * * <pre> * ProgressReporter reporter = new ProgressReporter("I'm a reporter"); * * // Create a concrete listener since we need to remove it later for clean up * IProgressReporterListener listener = new IProgressReporterListener() { * public int report(ProgressReport progressReport) { * // Do some work here * return RETVAL_OK; * } * }; * * // Add the listener * reporter.addListener(listener); * * // Do some more work * * // Then for clean up remove the listener * if ([some condition] == true) { * reporter.removeListener(listener); * } * * </pre> * * * Sometime it is more convenient to remove a listener from within the call to .report() but a direct * attempt at removal of this listener may result in modification conflict since most likely this method is being * called from within an iterator loop which does not allow concurrent modifications. * * To address this limitation we make use of the <code>RETVAL_OK_TO_DISPOSE</code> as a return code which will * allow the caller to perform the clean up as in this modification of the example above: * * <pre> * ... * * final IProgressReporterListener listener = new IProgressReporterListener() { * public int report(ProgressReport progressReport) { * * // Do some work here * * // This would throw a ConcurrentModificationException * reporter.removeListener(listener); * * // This would work * if ([some condition] == true) { * return RETVAL_OK_TO_DISPOSE; * } * * return RETVAL_OK; * } * }; * </pre> * * <p>If the decision to remove a listener is based on the information contained in the given <code>ProgressReport</code> * we can implement a much simpler listener as an inner class like so:</p> * <pre> * * ProgressReporter reporter = new ProgressReporter("I'm a reporter"); * * // Creates an anonymous inner class using RETVAL_OK_TO_DISPOSE to initiate clean up * reporter.addListener(new IProgressReporterListener() { * public int report(ProgressReport progressReport) { * * // Do some work * * if ([some condition] == true) { * return RETVAL_OK_TO_DISPOSE; * } * return RETVAL_OK; * * }} * ); * * * </pre> * * @param progressReport * @return */ public int report(IProgressReport progressReport); }