GNU Classpath (0.20) | |
Frames | No Frames |
1: /* ProgressMonitor.java -- 2: Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: package javax.swing; 39: 40: import java.awt.Component; 41: import java.awt.event.ActionListener; 42: import java.awt.event.ActionEvent; 43: 44: /** 45: * <p>Using this class you can easily monitor tasks where you cannot 46: * estimate the duration exactly.</p> 47: * 48: * <p>A ProgressMonitor instance waits until the first time setProgress 49: * is called. When <code>millisToDecideToPopup</code> time elapsed the 50: * instance estimates the duration until the whole operation is completed. 51: * If this duration exceeds <code>millisToPopup</code> a non-modal dialog 52: * with a message and a progress bar is shown.</p> 53: * 54: * <p>The value of <code>millisToDecideToPopup</code> defaults to 55: * <code>500</code> and <code>millisToPopup</code> to 56: * <code>2000</code>.</p> 57: * 58: * @author Andrew Selkirk 59: * @author Robert Schuster (robertschuster@fsfe.org) 60: * @since 1.2 61: * @status updated to 1.2 62: */ 63: public class ProgressMonitor 64: { 65: /** 66: * parentComponent 67: */ 68: Component component; 69: 70: /** 71: * note 72: */ 73: String note; 74: 75: /** 76: * message 77: */ 78: Object message; 79: 80: /** 81: * millisToDecideToPopup 82: */ 83: int millisToDecideToPopup = 500; 84: 85: /** 86: * millisToPopup 87: */ 88: int millisToPopup = 2000; 89: 90: int min, max, progress; 91: 92: JProgressBar progressBar; 93: 94: JLabel noteLabel; 95: 96: JDialog progressDialog; 97: 98: Timer timer; 99: 100: boolean canceled; 101: 102: /** 103: * Constructor ProgressMonitor 104: * @param component The parent component of the progress dialog or <code>null</code>. 105: * @param message A constant message object which works in the way it does in <code>JOptionPane</code>. 106: * @param note A string message which can be changed while the operation goes on. 107: * @param minimum The minimum value for the operation (start value). 108: * @param maximum The maximum value for the operation (end value). 109: */ 110: public ProgressMonitor(Component component, Object message, 111: String note, int minimum, int maximum) 112: { 113: 114: // Set data. 115: this.component = component; 116: this.message = message; 117: this.note = note; 118: 119: min = minimum; 120: max = maximum; 121: } 122: 123: /** 124: * <p>Hides the dialog and stops any measurements.</p> 125: * 126: * <p>Has no effect when <code>setProgress</code> is not at least 127: * called once.</p> 128: */ 129: public void close() 130: { 131: if ( progressDialog != null ) 132: { 133: progressDialog.setVisible(false); 134: } 135: 136: if ( timer != null ) 137: { 138: timer.stop(); 139: timer = null; 140: } 141: } 142: 143: /** 144: * <p>Updates the progress value.</p> 145: * 146: * <p>When called for the first time this initializes a timer 147: * which decides after <code>millisToDecideToPopup</code> time 148: * whether to show a progress dialog or not.</p> 149: * 150: * <p>If the progress value equals or exceeds the maximum 151: * value the progress dialog is closed automatically.</p> 152: * 153: * @param progress New progress value. 154: */ 155: public void setProgress(int progress) 156: { 157: this.progress = progress; 158: 159: // Initializes and starts a timer with a task 160: // which measures the duration and displays 161: // a progress dialog if neccessary. 162: if ( timer == null && progressDialog == null ) 163: { 164: timer = new Timer(25, null); 165: timer.addActionListener(new TimerListener()); 166: timer.start(); 167: } 168: 169: // Cancels timer and hides progress dialog if the 170: // maximum value is reached. 171: if ( progressBar != null && this.progress >= progressBar.getMaximum() ) 172: { 173: // The reason for using progressBar.getMaximum() instead of max is that 174: // we want to prevent that changes to the value have any effect after the 175: // progress dialog is visible (This is how the JDK behaves.). 176: close(); 177: } 178: 179: } 180: 181: /** Returns the minimum or start value of the operation. 182: * 183: * @returns Minimum or start value of the operation. 184: */ 185: public int getMinimum() 186: { 187: return min; 188: } 189: 190: /** 191: * <p>Use this method to set the minimum or start value of 192: * your operation.</p> 193: * 194: * <p>For typical application like copy operation this will be 195: * zero.</p> 196: * 197: * <p>Keep in mind that changing this value after the progress 198: * dialog is made visible has no effect upon the progress bar.</p> 199: * 200: * @param minimum The new minimum value. 201: */ 202: public void setMinimum(int minimum) 203: { 204: min = minimum; 205: } 206: 207: /** 208: * Return the maximum or end value of your operation. 209: * 210: * @returns Maximum or end value. 211: */ 212: public int getMaximum() 213: { 214: return max; 215: } 216: 217: /** 218: * <p>Sets the maximum or end value of the operation to the 219: * given integer.</p> 220: * 221: * @param maximum 222: */ 223: public void setMaximum(int maximum) 224: { 225: max = maximum; 226: } 227: 228: /** 229: * Returns whether the user canceled the operation. 230: * 231: * @returns Whether the operation was canceled. 232: */ 233: public boolean isCanceled() 234: { 235: // The value is predefined to false 236: // and changes only when the user clicks 237: // the cancel button in the progress dialog. 238: return canceled; 239: } 240: 241: /** 242: * Returns the amount of milliseconds to wait 243: * until the ProgressMonitor should decide whether 244: * a progress dialog is to be shown or not. 245: * 246: * @returns The duration in milliseconds. 247: */ 248: public int getMillisToDecideToPopup() 249: { 250: return millisToDecideToPopup; 251: } 252: 253: /** 254: * Sets the amount of milliseconds to wait until the 255: * ProgressMonitor should decide whether a progress dialog 256: * is to be shown or not. 257: * 258: * <p>This method has no effect when the progress dialog 259: * is already visible.</p> 260: * 261: * @param time The duration in milliseconds. 262: */ 263: public void setMillisToDecideToPopup(int time) 264: { 265: millisToDecideToPopup = time; 266: } 267: 268: /** 269: * getMillisToPopup 270: * @returns int 271: */ 272: public int getMillisToPopup() 273: { 274: return millisToPopup; 275: } 276: 277: /** 278: * setMillisToPopup 279: * @param time TODO 280: */ 281: public void setMillisToPopup(int time) 282: { 283: millisToPopup = time; 284: } 285: 286: /** 287: * Returns a message which is shown in the progress dialog. 288: * 289: * @returns The changeable message visible in the progress dialog. 290: */ 291: public String getNote() 292: { 293: return note; 294: } 295: 296: /** 297: * <p>Set the message shown in the progess dialog.</p> 298: * 299: * <p>Changing the note while the progress dialog is visible 300: * is possible.</p> 301: * 302: * @param note A message shown in the progress dialog. 303: */ 304: public void setNote(String note) 305: { 306: if ( noteLabel != null ) 307: { 308: noteLabel.setText(note); 309: } 310: else 311: { 312: this.note = note; 313: } 314: } 315: 316: /** Internal method that creates the progress dialog. 317: */ 318: void createDialog() 319: { 320: // If there is no note we suppress the generation of the 321: // label. 322: Object[] tmp = (note == null) ? 323: new Object[] 324: { 325: message, 326: progressBar = new JProgressBar(min, max) 327: } 328: : 329: new Object[] 330: { 331: message, 332: noteLabel = new JLabel(note), 333: progressBar = new JProgressBar(min, max) 334: }; 335: 336: JOptionPane pane = new JOptionPane(tmp, JOptionPane.INFORMATION_MESSAGE); 337: 338: // FIXME: Internationalize the button 339: JButton cancelButton = new JButton("Cancel"); 340: cancelButton.addActionListener(new ActionListener() 341: { 342: public void actionPerformed(ActionEvent ae) 343: { 344: canceled = true; 345: } 346: }); 347: 348: pane.setOptions(new Object[] { cancelButton }); 349: 350: // FIXME: Internationalize the title 351: progressDialog = pane.createDialog(component, "Progress ..."); 352: progressDialog.setModal(false); 353: progressDialog.setResizable(true); 354: 355: progressDialog.pack(); 356: progressDialog.setVisible(true); 357: 358: } 359: 360: /** An ActionListener implementation which does the measurements 361: * and estimations of the ProgressMonitor. 362: */ 363: class TimerListener implements ActionListener 364: { 365: long timestamp; 366: 367: int lastProgress; 368: 369: boolean first = true; 370: 371: TimerListener() 372: { 373: timestamp = System.currentTimeMillis(); 374: } 375: 376: public void actionPerformed(ActionEvent ae) 377: { 378: long now = System.currentTimeMillis(); 379: 380: if ( first ) 381: { 382: if (( now - timestamp ) > millisToDecideToPopup ) 383: { 384: first = false; 385: long expected = ( now - timestamp ) * ( max - min ) / ( progress - min ); 386: 387: if ( expected > millisToPopup ) 388: { 389: createDialog(); 390: } 391: } 392: else 393: { 394: // We have not waited long enough to make a decision, 395: // so return and try again when the timer is invoked. 396: return; 397: } 398: } 399: else if ( progressDialog != null ) 400: { 401: // The progress dialog is being displayed. We now calculate 402: // whether setting the progress bar to the current progress 403: // value would result in a visual difference. 404: int delta = progress - progressBar.getValue(); 405: 406: if ( ( delta * progressBar.getWidth() / (max - min) ) > 0 ) 407: { 408: // At least one pixel would change. 409: progressBar.setValue(progress); 410: } 411: } 412: else 413: { 414: // No dialog necessary 415: timer.stop(); 416: timer = null; 417: } 418: 419: timestamp = now; 420: } 421: } 422: 423: }
GNU Classpath (0.20) |