Hi, this patch implements the ProgressMonitor. I'll send a demo application to the associated bug report[0].
2005-09-15 Robert Schuster <[EMAIL PROTECTED]> * javax/swing/ProgressMonitor: Implemented the former stubbed class and added documentation. (close): Implemented and added documentation. (setProgress): Dito. (isCanceled): Dito. (setMinimum): Added documentation. (getMinimum): Dito. (setMaximum): Dito. (getMaximum): Dito. (setNote): Dito. (getMillisToDecideToPopup): Dito. (setMillisToDecideToPopup): Dito. (getMillisToPopup): Dito. (setMillisToPopup): Dito. (getNote): Dito. [0] - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=23850 cu Robert
Index: javax/swing/ProgressMonitor.java =================================================================== RCS file: /cvsroot/classpath/classpath/javax/swing/ProgressMonitor.java,v retrieving revision 1.4 diff -u -r1.4 ProgressMonitor.java --- javax/swing/ProgressMonitor.java 13 Sep 2005 09:17:21 -0000 1.4 +++ javax/swing/ProgressMonitor.java 15 Sep 2005 17:59:38 -0000 @@ -1,5 +1,5 @@ /* ProgressMonitor.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,56 +38,74 @@ package javax.swing; import java.awt.Component; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; /** - * ProgressMonitor - * @author Andrew Selkirk - * @version 1.0 + * <p>Using this class you can easily monitor tasks where you cannot + * estimate the duration exactly.</p> + * + * <p>A ProgressMonitor instance waits until the first time setProgress + * is called. When <code>millisToDecideToPopup</code> time elapsed the + * instance estimates the duration until the whole operation is completed. + * If this duration exceeds <code>millisToPopup</code> a non-modal dialog + * with a message and a progress bar is shown.</p> + * + * <p>The value of <code>millisToDecideToPopup</code> defaults to + * <code>500</code> and <code>millisToPopup</code> to + * <code>2000</code>.</p> + * + * @author Andrew Selkirk + * @author Robert Schuster ([EMAIL PROTECTED]) + * @since 1.2 + * @status updated to 1.2 */ public class ProgressMonitor { /** * parentComponent */ - private Component component; + Component component; /** * note */ - private String note; + String note; /** * message */ - private Object message; + Object message; /** * millisToDecideToPopup */ - private int millisToDecideToPopup; + int millisToDecideToPopup = 500; /** * millisToPopup */ - private int millisToPopup; + int millisToPopup = 2000; - /** - * min - */ - private int minimum; + int min, max, progress; - /** - * max - */ - private int maximum; + JProgressBar progressBar; + + JLabel noteLabel; + + JDialog progressDialog; + + Timer timer; + + boolean canceled; /** * Constructor ProgressMonitor - * @param component TODO - * @param message TODO - * @param note TODO - * @param minimum TODO - * @param maximum TODO + * @param component The parent component of the progress dialog or <code>null</code>. + * @param message A constant message object which works in the way it does in <code>JOptionPane</code>. + * @param note A string message which can be changed while the operation goes on. + * @param minimum The minimum value for the operation (start value). + * @param maximum The maximum value for the operation (end value). */ public ProgressMonitor(Component component, Object message, String note, int minimum, int maximum) @@ -97,93 +115,154 @@ this.component = component; this.message = message; this.note = note; - this.minimum = minimum; - this.maximum = maximum; - // TODO + min = minimum; + max = maximum; } /** - * close + * <p>Hides the dialog and stops any measurements.</p> + * + * <p>Has no effect when <code>setProgress</code> is not at least + * called once.</p> */ public void close() { - // TODO + if ( progressDialog != null ) + { + progressDialog.setVisible(false); + } + + if ( timer != null ) + { + timer.stop(); + timer = null; + } } /** - * setProgress - * @param progress TODO + * <p>Updates the progress value.</p> + * + * <p>When called for the first time this initializes a timer + * which decides after <code>millisToDecideToPopup</code> time + * whether to show a progress dialog or not.</p> + * + * <p>If the progress value equals or exceeds the maximum + * value the progress dialog is closed automatically.</p> + * + * @param progress New progress value. */ public void setProgress(int progress) { - // TODO + this.progress = progress; + + // Initializes and starts a timer with a task + // which measures the duration and displays + // a progress dialog if neccessary. + if ( timer == null && progressDialog == null ) + { + timer = new Timer(25, null); + timer.addActionListener(new TimerListener()); + timer.start(); + } + + // Cancels timer and hides progress dialog if the + // maximum value is reached. + if ( progressBar != null && this.progress >= progressBar.getMaximum() ) + { + // The reason for using progressBar.getMaximum() instead of max is that + // we want to prevent that changes to the value have any effect after the + // progress dialog is visible (This is how the JDK behaves.). + close(); + } + } - /** - * getMinimum - * @returns int + /** Returns the minimum or start value of the operation. + * + * @returns Minimum or start value of the operation. */ public int getMinimum() { - return minimum; // TODO + return min; } /** - * setMinimum - * @param minimum TODO + * <p>Use this method to set the minimum or start value of + * your operation.</p> + * + * <p>For typical application like copy operation this will be + * zero.</p> + * + * <p>Keep in mind that changing this value after the progress + * dialog is made visible has no effect upon the progress bar.</p> + * + * @param minimum The new minimum value. */ public void setMinimum(int minimum) { - this.minimum = minimum; - // TODO + min = minimum; } /** - * getMaximum - * @returns int + * Return the maximum or end value of your operation. + * + * @returns Maximum or end value. */ public int getMaximum() { - return maximum; // TODO + return max; } /** - * setMaximum - * @param maximum TODO + * <p>Sets the maximum or end value of the operation to the + * given integer.</p> + * + * @param maximum */ public void setMaximum(int maximum) { - this.maximum = maximum; - // TODO + max = maximum; } /** - * isCanceled - * @returns boolean + * Returns whether the user canceled the operation. + * + * @returns Whether the operation was canceled. */ public boolean isCanceled() { - return false; // TODO + // The value is predefined to false + // and changes only when the user clicks + // the cancel button in the progress dialog. + return canceled; } /** - * getMillisToDecideToPopup - * @returns int + * Returns the amount of milliseconds to wait + * until the ProgressMonitor should decide whether + * a progress dialog is to be shown or not. + * + * @returns The duration in milliseconds. */ public int getMillisToDecideToPopup() { - return millisToDecideToPopup; // TODO + return millisToDecideToPopup; } /** - * setMillisToDecideToPopup - * @param time TODO + * Sets the amount of milliseconds to wait until the + * ProgressMonitor should decide whether a progress dialog + * is to be shown or not. + * + * <p>This method has no effect when the progress dialog + * is already visible.</p> + * + * @param time The duration in milliseconds. */ public void setMillisToDecideToPopup(int time) { millisToDecideToPopup = time; - // TODO } /** @@ -192,7 +271,7 @@ */ public int getMillisToPopup() { - return millisToPopup; // TODO + return millisToPopup; } /** @@ -202,26 +281,134 @@ public void setMillisToPopup(int time) { millisToPopup = time; - // TODO } /** - * getNote - * @returns String + * Returns a message which is shown in the progress dialog. + * + * @returns The changeable message visible in the progress dialog. */ public String getNote() { - return note; // TODO + return note; } /** - * setNote - * @param note TODO + * <p>Set the message shown in the progess dialog.</p> + * + * <p>Changing the note while the progress dialog is visible + * is possible.</p> + * + * @param note A message shown in the progress dialog. */ public void setNote(String note) { - this.note = note; - // TODO + if ( noteLabel != null ) + { + noteLabel.setText(note); + } + else + { + this.note = note; + } + } + + /** Internal method that creates the progress dialog. + */ + void createDialog() + { + Object[] tmp = new Object[] + { + message, + noteLabel = new JLabel(note), + progressBar = new JProgressBar(min, max) + }; + + JOptionPane pane = new JOptionPane(tmp, JOptionPane.INFORMATION_MESSAGE); + + // FIXME: Internationalize the button + JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent ae) + { + canceled = true; + } + }); + + pane.setOptions(new Object[] { cancelButton }); + + // FIXME: Internationalize the title + progressDialog = pane.createDialog(component, "Progress ..."); + progressDialog.setModal(false); + progressDialog.setResizable(true); + + progressDialog.pack(); + progressDialog.setVisible(true); + + } + + /** An ActionListener implementation which does the measurements + * and estimations of the ProgressMonitor. + */ + class TimerListener implements ActionListener + { + long timestamp; + + int lastProgress; + + boolean first = true; + + TimerListener() + { + timestamp = System.currentTimeMillis(); + } + + public void actionPerformed(ActionEvent ae) + { + long now = System.currentTimeMillis(); + + if ( first ) + { + if (( now - timestamp ) > millisToDecideToPopup ) + { + first = false; + long expected = ( now - timestamp ) * ( max - min ) / ( progress - min ); + + if ( expected > millisToPopup ) + { + createDialog(); + } + } + else + { + // We have not waited long enough to make a decision, + // so return and try again when the timer is invoked. + return; + } + } + else if ( progressDialog != null ) + { + // The progress dialog is being displayed. We now calculate + // whether setting the progress bar to the current progress + // value would result in a visual difference. + int delta = progress - progressBar.getValue(); + + if ( ( delta * progressBar.getWidth() / (max - min) ) > 0 ) + { + // At least one pixel would change. + progressBar.setValue(progress); + } + } + else + { + // No dialog necessary + timer.stop(); + timer = null; + } + + timestamp = now; + } } }
_______________________________________________ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches