Showing the changes to java/pkg/javax/swing/ProgressMonitor.java (1 of 18352 files). Show all
Unified · Split
| @@ -0,0 +1,1046 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. | ||
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | ||
| 4 | * | ||
| 5 | * This code is free software; you can redistribute it and/or modify it | ||
| 6 | * under the terms of the GNU General Public License version 2 only, as | ||
| 7 | * published by the Free Software Foundation. Oracle designates this | ||
| 8 | * particular file as subject to the "Classpath" exception as provided | ||
| 9 | * by Oracle in the LICENSE file that accompanied this code. | ||
| 10 | * | ||
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
| 14 | * version 2 for more details (a copy is included in the LICENSE file that | ||
| 15 | * accompanied this code). | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License version | ||
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, | ||
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 20 | * | ||
| 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | ||
| 22 | * or visit www.oracle.com if you need additional information or have any | ||
| 23 | * questions. | ||
| 24 | */ | ||
| 25 | |||
| 26 | |||
| 27 | |||
| 28 | package javax.swing; | ||
| 29 | |||
| 30 | |||
| 31 | |||
| 32 | import java.io.*; | ||
| 33 | import java.awt.BorderLayout; | ||
| 34 | import java.awt.Frame; | ||
| 35 | import java.awt.Dialog; | ||
| 36 | import java.awt.Window; | ||
| 37 | import java.awt.Component; | ||
| 38 | import java.awt.Container; | ||
| 39 | import java.beans.PropertyChangeEvent; | ||
| 40 | import java.beans.PropertyChangeListener; | ||
| 41 | import java.awt.event.WindowListener; | ||
| 42 | import java.awt.event.WindowAdapter; | ||
| 43 | import java.awt.event.WindowEvent; | ||
| 44 | |||
| 45 | import java.awt.IllegalComponentStateException; | ||
| 46 | import java.awt.Point; | ||
| 47 | import java.awt.Rectangle; | ||
| 48 | import java.text.*; | ||
| 49 | import java.util.Locale; | ||
| 50 | import javax.accessibility.*; | ||
| 51 | import javax.swing.event.*; | ||
| 52 | import javax.swing.text.*; | ||
| 53 | |||
| 54 | |||
| 55 | /** A class to monitor the progress of some operation. If it looks | ||
| 56 | * like the operation will take a while, a progress dialog will be popped up. | ||
| 57 | * When the ProgressMonitor is created it is given a numeric range and a | ||
| 58 | * descriptive string. As the operation progresses, call the setProgress method | ||
| 59 | * to indicate how far along the [min,max] range the operation is. | ||
| 60 | * Initially, there is no ProgressDialog. After the first millisToDecideToPopup | ||
| 61 | * milliseconds (default 500) the progress monitor will predict how long | ||
| 62 | * the operation will take. If it is longer than millisToPopup (default 2000, | ||
| 63 | * 2 seconds) a ProgressDialog will be popped up. | ||
| 64 | * <p> | ||
| 65 | * From time to time, when the Dialog box is visible, the progress bar will | ||
| 66 | * be updated when setProgress is called. setProgress won't always update | ||
| 67 | * the progress bar, it will only be done if the amount of progress is | ||
| 68 | * visibly significant. | ||
| 69 | * | ||
| 70 | * <p> | ||
| 71 | * | ||
| 72 | * For further documentation and examples see | ||
| 73 | * <a | ||
| 74 | href="http://java.sun.com/docs/books/tutorial/uiswing/components/progress.html">How to Monitor Progress</a>, | ||
| 75 | * a section in <em>The Java Tutorial.</em> | ||
| 76 | * | ||
| 77 | * @see ProgressMonitorInputStream | ||
| 78 | * @author James Gosling | ||
| 79 | * @author Lynn Monsanto (accessibility) | ||
| 80 | */ | ||
| 81 | public class ProgressMonitor implements Accessible | ||
| 82 | { | ||
| 83 | private ProgressMonitor root; | ||
| 84 | private JDialog dialog; | ||
| 85 | private JOptionPane pane; | ||
| 86 | private JProgressBar myBar; | ||
| 87 | private JLabel noteLabel; | ||
| 88 | private Component parentComponent; | ||
| 89 | private String note; | ||
| 90 | private Object[] cancelOption = null; | ||
| 91 | private Object message; | ||
| 92 | private long T0; | ||
| 93 | private int millisToDecideToPopup = 500; | ||
| 94 | private int millisToPopup = 2000; | ||
| 95 | private int min; | ||
| 96 | private int max; | ||
| 97 | |||
| 98 | |||
| 99 | /** | ||
| 100 | * Constructs a graphic object that shows progress, typically by filling | ||
| 101 | * in a rectangular bar as the process nears completion. | ||
| 102 | * | ||
| 103 | * @param parentComponent the parent component for the dialog box | ||
| 104 | * @param message a descriptive message that will be shown | ||
| 105 | * to the user to indicate what operation is being monitored. | ||
| 106 | * This does not change as the operation progresses. | ||
| 107 | * See the message parameters to methods in | ||
| 108 | * {@link JOptionPane#message} | ||
| 109 | * for the range of values. | ||
| 110 | * @param note a short note describing the state of the | ||
| 111 | * operation. As the operation progresses, you can call | ||
| 112 | * setNote to change the note displayed. This is used, | ||
| 113 | * for example, in operations that iterate through a | ||
| 114 | * list of files to show the name of the file being processes. | ||
| 115 | * If note is initially null, there will be no note line | ||
| 116 | * in the dialog box and setNote will be ineffective | ||
| 117 | * @param min the lower bound of the range | ||
| 118 | * @param max the upper bound of the range | ||
| 119 | * @see JDialog | ||
| 120 | * @see JOptionPane | ||
| 121 | */ | ||
| 122 | public ProgressMonitor(Component parentComponent, | ||
| 123 | Object message, | ||
| 124 | String note, | ||
| 125 | int min, | ||
| 126 | int max) { | ||
| 127 | this(parentComponent, message, note, min, max, null); | ||
| 128 | } | ||
| 129 | |||
| 130 | |||
| 131 | private ProgressMonitor(Component parentComponent, | ||
| 132 | Object message, | ||
| 133 | String note, | ||
| 134 | int min, | ||
| 135 | int max, | ||
| 136 | ProgressMonitor group) { | ||
| 137 | this.min = min; | ||
| 138 | this.max = max; | ||
| 139 | this.parentComponent = parentComponent; | ||
| 140 | |||
| 141 | cancelOption = new Object[1]; | ||
| 142 | cancelOption[0] = UIManager.getString("OptionPane.cancelButtonText"); | ||
| 143 | |||
| 144 | this.message = message; | ||
| 145 | this.note = note; | ||
| 146 | if (group != null) { | ||
| 147 | root = (group.root != null) ? group.root : group; | ||
| 148 | T0 = root.T0; | ||
| 149 | dialog = root.dialog; | ||
| 150 | } | ||
| 151 | else { | ||
| 152 | T0 = System.currentTimeMillis(); | ||
| 153 | } | ||
| 154 | } | ||
| 155 | |||
| 156 | |||
| 157 | private class ProgressOptionPane extends JOptionPane | ||
| 158 | { | ||
| 159 | ProgressOptionPane(Object messageList) { | ||
| 160 | super(messageList, | ||
| 161 | JOptionPane.INFORMATION_MESSAGE, | ||
| 162 | JOptionPane.DEFAULT_OPTION, | ||
| 163 | null, | ||
| 164 | ProgressMonitor.this.cancelOption, | ||
| 165 | null); | ||
| 166 | } | ||
| 167 | |||
| 168 | |||
| 169 | public int getMaxCharactersPerLineCount() { | ||
| 170 | return 60; | ||
| 171 | } | ||
| 172 | |||
| 173 | |||
| 174 | // Equivalent to JOptionPane.createDialog, | ||
| 175 | // but create a modeless dialog. | ||
| 176 | // This is necessary because the Solaris implementation doesn't | ||
| 177 | // support Dialog.setModal yet. | ||
| 178 | public JDialog createDialog(Component parentComponent, String title) { | ||
| 179 | final JDialog dialog; | ||
| 180 | |||
| 181 | Window window = JOptionPane.getWindowForComponent(parentComponent); | ||
| 182 | if (window instanceof Frame) { | ||
| 183 | dialog = new JDialog((Frame)window, title, false); | ||
| 184 | } else { | ||
| 185 | dialog = new JDialog((Dialog)window, title, false); | ||
| 186 | } | ||
| 187 | if (window instanceof SwingUtilities.SharedOwnerFrame) { | ||
| 188 | WindowListener ownerShutdownListener = | ||
| 189 | SwingUtilities.getSharedOwnerFrameShutdownListener(); | ||
| 190 | dialog.addWindowListener(ownerShutdownListener); | ||
| 191 | } | ||
| 192 | Container contentPane = dialog.getContentPane(); | ||
| 193 | |||
| 194 | contentPane.setLayout(new BorderLayout()); | ||
| 195 | contentPane.add(this, BorderLayout.CENTER); | ||
| 196 | dialog.pack(); | ||
| 197 | dialog.setLocationRelativeTo(parentComponent); | ||
| 198 | dialog.addWindowListener(new WindowAdapter() { | ||
| 199 | boolean gotFocus = false; | ||
| 200 | |||
| 201 | public void windowClosing(WindowEvent we) { | ||
| 202 | setValue(cancelOption[0]); | ||
| 203 | } | ||
| 204 | |||
| 205 | public void windowActivated(WindowEvent we) { | ||
| 206 | // Once window gets focus, set initial focus | ||
| 207 | if (!gotFocus) { | ||
| 208 | selectInitialValue(); | ||
| 209 | gotFocus = true; | ||
| 210 | } | ||
| 211 | } | ||
| 212 | }); | ||
| 213 | |||
| 214 | addPropertyChangeListener(new PropertyChangeListener() { | ||
| 215 | public void propertyChange(PropertyChangeEvent event) { | ||
| 216 | if(dialog.isVisible() && | ||
| 217 | event.getSource() == ProgressOptionPane.this && | ||
| 218 | (event.getPropertyName().equals(VALUE_PROPERTY) || | ||
| 219 | event.getPropertyName().equals(INPUT_VALUE_PROPERTY))){ | ||
| 220 | dialog.setVisible(false); | ||
| 221 | dialog.dispose(); | ||
| 222 | } | ||
| 223 | } | ||
| 224 | }); | ||
| 225 | |||
| 226 | return dialog; | ||
| 227 | } | ||
| 228 | |||
| 229 | ///////////////// | ||
| 230 | // Accessibility support for ProgressOptionPane | ||
| 231 | //////////////// | ||
| 232 | |||
| 233 | /** | ||
| 234 | * Gets the AccessibleContext for the ProgressOptionPane | ||
| 235 | * | ||
| 236 | * @return the AccessibleContext for the ProgressOptionPane | ||
| 237 | * @since 1.5 | ||
| 238 | */ | ||
| 239 | public AccessibleContext getAccessibleContext() { | ||
| 240 | return ProgressMonitor.this.getAccessibleContext(); | ||
| 241 | } | ||
| 242 | |||
| 243 | /* | ||
| 244 | * Returns the AccessibleJOptionPane | ||
| 245 | */ | ||
| 246 | private AccessibleContext getAccessibleJOptionPane() { | ||
| 247 | return super.getAccessibleContext(); | ||
| 248 | } | ||
| 249 | } | ||
| 250 | |||
| 251 | |||
| 252 | /** | ||
| 253 | * Indicate the progress of the operation being monitored. | ||
| 254 | * If the specified value is >= the maximum, the progress | ||
| 255 | * monitor is closed. | ||
| 256 | * @param nv an int specifying the current value, between the | ||
| 257 | * maximum and minimum specified for this component | ||
| 258 | * @see #setMinimum | ||
| 259 | * @see #setMaximum | ||
| 260 | * @see #close | ||
| 261 | */ | ||
| 262 | public void setProgress(int nv) { | ||
| 263 | if (nv >= max) { | ||
| 264 | close(); | ||
| 265 | } | ||
| 266 | else { | ||
| 267 | if (myBar != null) { | ||
| 268 | myBar.setValue(nv); | ||
| 269 | } | ||
| 270 | else { | ||
| 271 | long T = System.currentTimeMillis(); | ||
| 272 | long dT = (int)(T-T0); | ||
| 273 | if (dT >= millisToDecideToPopup) { | ||
| 274 | int predictedCompletionTime; | ||
| 275 | if (nv > min) { | ||
| 276 | predictedCompletionTime = (int)(dT * | ||
| 277 | (max - min) / | ||
| 278 | (nv - min)); | ||
| 279 | } | ||
| 280 | else { | ||
| 281 | predictedCompletionTime = millisToPopup; | ||
| 282 | } | ||
| 283 | if (predictedCompletionTime >= millisToPopup) { | ||
| 284 | myBar = new JProgressBar(); | ||
| 285 | myBar.setMinimum(min); | ||
| 286 | myBar.setMaximum(max); | ||
| 287 | myBar.setValue(nv); | ||
| 288 | if (note != null) noteLabel = new JLabel(note); | ||
| 289 | pane = new ProgressOptionPane(new Object[] {message, | ||
| 290 | noteLabel, | ||
| 291 | myBar}); | ||
| 292 | dialog = pane.createDialog(parentComponent, | ||
| 293 | UIManager.getString( | ||
| 294 | "ProgressMonitor.progressText")); | ||
| 295 | dialog.show(); | ||
| 296 | } | ||
| 297 | } | ||
| 298 | } | ||
| 299 | } | ||
| 300 | } | ||
| 301 | |||
| 302 | |||
| 303 | /** | ||
| 304 | * Indicate that the operation is complete. This happens automatically | ||
| 305 | * when the value set by setProgress is >= max, but it may be called | ||
| 306 | * earlier if the operation ends early. | ||
| 307 | */ | ||
| 308 | public void close() { | ||
| 309 | if (dialog != null) { | ||
| 310 | dialog.setVisible(false); | ||
| 311 | dialog.dispose(); | ||
| 312 | dialog = null; | ||
| 313 | pane = null; | ||
| 314 | myBar = null; | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | |||
| 319 | /** | ||
| 320 | * Returns the minimum value -- the lower end of the progress value. | ||
| 321 | * | ||
| 322 | * @return an int representing the minimum value | ||
| 323 | * @see #setMinimum | ||
| 324 | */ | ||
| 325 | public int getMinimum() { | ||
| 326 | return min; | ||
| 327 | } | ||
| 328 | |||
| 329 | |||
| 330 | /** | ||
| 331 | * Specifies the minimum value. | ||
| 332 | * | ||
| 333 | * @param m an int specifying the minimum value | ||
| 334 | * @see #getMinimum | ||
| 335 | */ | ||
| 336 | public void setMinimum(int m) { | ||
| 337 | if (myBar != null) { | ||
| 338 | myBar.setMinimum(m); | ||
| 339 | } | ||
| 340 | min = m; | ||
| 341 | } | ||
| 342 | |||
| 343 | |||
| 344 | /** | ||
| 345 | * Returns the maximum value -- the higher end of the progress value. | ||
| 346 | * | ||
| 347 | * @return an int representing the maximum value | ||
| 348 | * @see #setMaximum | ||
| 349 | */ | ||
| 350 | public int getMaximum() { | ||
| 351 | return max; | ||
| 352 | } | ||
| 353 | |||
| 354 | |||
| 355 | /** | ||
| 356 | * Specifies the maximum value. | ||
| 357 | * | ||
| 358 | * @param m an int specifying the maximum value | ||
| 359 | * @see #getMaximum | ||
| 360 | */ | ||
| 361 | public void setMaximum(int m) { | ||
| 362 | if (myBar != null) { | ||
| 363 | myBar.setMaximum(m); | ||
| 364 | } | ||
| 365 | max = m; | ||
| 366 | } | ||
| 367 | |||
| 368 | |||
| 369 | /** | ||
| 370 | * Returns true if the user hits the Cancel button in the progress dialog. | ||
| 371 | */ | ||
| 372 | public boolean isCanceled() { | ||
| 373 | if (pane == null) return false; | ||
| 374 | Object v = pane.getValue(); | ||
| 375 | return ((v != null) && | ||
| 376 | (cancelOption.length == 1) && | ||
| 377 | (v.equals(cancelOption[0]))); | ||
| 378 | } | ||
| 379 | |||
| 380 | |||
| 381 | /** | ||
| 382 | * Specifies the amount of time to wait before deciding whether or | ||
| 383 | * not to popup a progress monitor. | ||
| 384 | * | ||
| 385 | * @param millisToDecideToPopup an int specifying the time to wait, | ||
| 386 | * in milliseconds | ||
| 387 | * @see #getMillisToDecideToPopup | ||
| 388 | */ | ||
| 389 | public void setMillisToDecideToPopup(int millisToDecideToPopup) { | ||
| 390 | this.millisToDecideToPopup = millisToDecideToPopup; | ||
| 391 | } | ||
| 392 | |||
| 393 | |||
| 394 | /** | ||
| 395 | * Returns the amount of time this object waits before deciding whether | ||
| 396 | * or not to popup a progress monitor. | ||
| 397 | * | ||
| 398 | * @see #setMillisToDecideToPopup | ||
| 399 | */ | ||
| 400 | public int getMillisToDecideToPopup() { | ||
| 401 | return millisToDecideToPopup; | ||
| 402 | } | ||
| 403 | |||
| 404 | |||
| 405 | /** | ||
| 406 | * Specifies the amount of time it will take for the popup to appear. | ||
| 407 | * (If the predicted time remaining is less than this time, the popup | ||
| 408 | * won't be displayed.) | ||
| 409 | * | ||
| 410 | * @param millisToPopup an int specifying the time in milliseconds | ||
| 411 | * @see #getMillisToPopup | ||
| 412 | */ | ||
| 413 | public void setMillisToPopup(int millisToPopup) { | ||
| 414 | this.millisToPopup = millisToPopup; | ||
| 415 | } | ||
| 416 | |||
| 417 | |||
| 418 | /** | ||
| 419 | * Returns the amount of time it will take for the popup to appear. | ||
| 420 | * | ||
| 421 | * @see #setMillisToPopup | ||
| 422 | */ | ||
| 423 | public int getMillisToPopup() { | ||
| 424 | return millisToPopup; | ||
| 425 | } | ||
| 426 | |||
| 427 | |||
| 428 | /** | ||
| 429 | * Specifies the additional note that is displayed along with the | ||
| 430 | * progress message. Used, for example, to show which file the | ||
| 431 | * is currently being copied during a multiple-file copy. | ||
| 432 | * | ||
| 433 | * @param note a String specifying the note to display | ||
| 434 | * @see #getNote | ||
| 435 | */ | ||
| 436 | public void setNote(String note) { | ||
| 437 | this.note = note; | ||
| 438 | if (noteLabel != null) { | ||
| 439 | noteLabel.setText(note); | ||
| 440 | } | ||
| 441 | } | ||
| 442 | |||
| 443 | |||
| 444 | /** | ||
| 445 | * Specifies the additional note that is displayed along with the | ||
| 446 | * progress message. | ||
| 447 | * | ||
| 448 | * @return a String specifying the note to display | ||
| 449 | * @see #setNote | ||
| 450 | */ | ||
| 451 | public String getNote() { | ||
| 452 | return note; | ||
| 453 | } | ||
| 454 | |||
| 455 | ///////////////// | ||
| 456 | // Accessibility support | ||
| 457 | //////////////// | ||
| 458 | |||
| 459 | /** | ||
| 460 | * The <code>AccessibleContext</code> for the <code>ProgressMonitor</code> | ||
| 461 | * @since 1.5 | ||
| 462 | */ | ||
| 463 | protected AccessibleContext accessibleContext = null; | ||
| 464 | |||
| 465 | private AccessibleContext accessibleJOptionPane = null; | ||
| 466 | |||
| 467 | /** | ||
| 468 | * Gets the <code>AccessibleContext</code> for the | ||
| 469 | * <code>ProgressMonitor</code> | ||
| 470 | * | ||
| 471 | * @return the <code>AccessibleContext</code> for the | ||
| 472 | * <code>ProgressMonitor</code> | ||
| 473 | * @since 1.5 | ||
| 474 | */ | ||
| 475 | public AccessibleContext getAccessibleContext() { | ||
| 476 | if (accessibleContext == null) { | ||
| 477 | accessibleContext = new AccessibleProgressMonitor(); | ||
| 478 | } | ||
| 479 | if (pane != null && accessibleJOptionPane == null) { | ||
| 480 | // Notify the AccessibleProgressMonitor that the | ||
| 481 | // ProgressOptionPane was created. It is necessary | ||
| 482 | // to poll for ProgressOptionPane creation because | ||
| 483 | // the ProgressMonitor does not have a Component | ||
| 484 | // to add a listener to until the ProgressOptionPane | ||
| 485 | // is created. | ||
| 486 | if (accessibleContext instanceof AccessibleProgressMonitor) { | ||
| 487 | ((AccessibleProgressMonitor)accessibleContext).optionPaneCreated(); | ||
| 488 | } | ||
| 489 | } | ||
| 490 | return accessibleContext; | ||
| 491 | } | ||
| 492 | |||
| 493 | /** | ||
| 494 | * <code>AccessibleProgressMonitor</code> implements accessibility | ||
| 495 | * support for the <code>ProgressMonitor</code> class. | ||
| 496 | * @since 1.5 | ||
| 497 | */ | ||
| 498 | protected class AccessibleProgressMonitor extends AccessibleContext | ||
| 499 | implements AccessibleText, ChangeListener, PropertyChangeListener { | ||
| 500 | |||
| 501 | /* | ||
| 502 | * The accessibility hierarchy for ProgressMonitor is a flattened | ||
| 503 | * version of the ProgressOptionPane component hierarchy. | ||
| 504 | * | ||
| 505 | * The ProgressOptionPane component hierarchy is: | ||
| 506 | * JDialog | ||
| 507 | * ProgressOptionPane | ||
| 508 | * JPanel | ||
| 509 | * JPanel | ||
| 510 | * JLabel | ||
| 511 | * JLabel | ||
| 512 | * JProgressBar | ||
| 513 | * | ||
| 514 | * The AccessibleProgessMonitor accessibility hierarchy is: | ||
| 515 | * AccessibleJDialog | ||
| 516 | * AccessibleProgressMonitor | ||
| 517 | * AccessibleJLabel | ||
| 518 | * AccessibleJLabel | ||
| 519 | * AccessibleJProgressBar | ||
| 520 | * | ||
| 521 | * The abstraction presented to assitive technologies by | ||
| 522 | * the AccessibleProgressMonitor is that a dialog contains a | ||
| 523 | * progress monitor with three children: a message, a note | ||
| 524 | * label and a progress bar. | ||
| 525 | */ | ||
| 526 | |||
| 527 | private Object oldModelValue; | ||
| 528 | |||
| 529 | /** | ||
| 530 | * AccessibleProgressMonitor constructor | ||
| 531 | */ | ||
| 532 | protected AccessibleProgressMonitor() { | ||
| 533 | } | ||
| 534 | |||
| 535 | /* | ||
| 536 | * Initializes the AccessibleContext now that the ProgressOptionPane | ||
| 537 | * has been created. Because the ProgressMonitor is not a Component | ||
| 538 | * implementing the Accessible interface, an AccessibleContext | ||
| 539 | * must be synthesized from the ProgressOptionPane and its children. | ||
| 540 | * | ||
| 541 | * For other AWT and Swing classes, the inner class that implements | ||
| 542 | * accessibility for the class extends the inner class that implements | ||
| 543 | * implements accessibility for the super class. AccessibleProgressMonitor | ||
| 544 | * cannot extend AccessibleJOptionPane and must therefore delegate calls | ||
| 545 | * to the AccessibleJOptionPane. | ||
| 546 | */ | ||
| 547 | private void optionPaneCreated() { | ||
| 548 | accessibleJOptionPane = | ||
| 549 | ((ProgressOptionPane)pane).getAccessibleJOptionPane(); | ||
| 550 | |||
| 551 | // add a listener for progress bar ChangeEvents | ||
| 552 | if (myBar != null) { | ||
| 553 | myBar.addChangeListener(this); | ||
| 554 | } | ||
| 555 | |||
| 556 | // add a listener for note label PropertyChangeEvents | ||
| 557 | if (noteLabel != null) { | ||
| 558 | noteLabel.addPropertyChangeListener(this); | ||
| 559 | } | ||
| 560 | } | ||
| 561 | |||
| 562 | /** | ||
| 563 | * Invoked when the target of the listener has changed its state. | ||
| 564 | * | ||
| 565 | * @param e a <code>ChangeEvent</code> object. Must not be null. | ||
| 566 | * @throws NullPointerException if the parameter is null. | ||
| 567 | */ | ||
| 568 | public void stateChanged(ChangeEvent e) { | ||
| 569 | if (e == null) { | ||
| 570 | return; | ||
| 571 | } | ||
| 572 | if (myBar != null) { | ||
| 573 | // the progress bar value changed | ||
| 574 | Object newModelValue = myBar.getValue(); | ||
| 575 | firePropertyChange(ACCESSIBLE_VALUE_PROPERTY, | ||
| 576 | oldModelValue, | ||
| 577 | newModelValue); | ||
| 578 | oldModelValue = newModelValue; | ||
| 579 | } | ||
| 580 | } | ||
| 581 | |||
| 582 | /** | ||
| 583 | * This method gets called when a bound property is changed. | ||
| 584 | * | ||
| 585 | * @param e A <code>PropertyChangeEvent</code> object describing | ||
| 586 | * the event source and the property that has changed. Must not be null. | ||
| 587 | * @throws NullPointerException if the parameter is null. | ||
| 588 | */ | ||
| 589 | public void propertyChange(PropertyChangeEvent e) { | ||
| 590 | if (e.getSource() == noteLabel && e.getPropertyName() == "text") { | ||
| 591 | // the note label text changed | ||
| 592 | firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, 0); | ||
| 593 | } | ||
| 594 | } | ||
| 595 | |||
| 596 | /* ===== Begin AccessileContext ===== */ | ||
| 597 | |||
| 598 | /** | ||
| 599 | * Gets the accessibleName property of this object. The accessibleName | ||
| 600 | * property of an object is a localized String that designates the purpose | ||
| 601 | * of the object. For example, the accessibleName property of a label | ||
| 602 | * or button might be the text of the label or button itself. In the | ||
| 603 | * case of an object that doesn't display its name, the accessibleName | ||
| 604 | * should still be set. For example, in the case of a text field used | ||
| 605 | * to enter the name of a city, the accessibleName for the en_US locale | ||
| 606 | * could be 'city.' | ||
| 607 | * | ||
| 608 | * @return the localized name of the object; null if this | ||
| 609 | * object does not have a name | ||
| 610 | * | ||
| 611 | * @see #setAccessibleName | ||
| 612 | */ | ||
| 613 | public String getAccessibleName() { | ||
| 614 | if (accessibleName != null) { // defined in AccessibleContext | ||
| 615 | return accessibleName; | ||
| 616 | } else if (accessibleJOptionPane != null) { | ||
| 617 | // delegate to the AccessibleJOptionPane | ||
| 618 | return accessibleJOptionPane.getAccessibleName(); | ||
| 619 | } | ||
| 620 | return null; | ||
| 621 | } | ||
| 622 | |||
| 623 | /** | ||
| 624 | * Gets the accessibleDescription property of this object. The | ||
| 625 | * accessibleDescription property of this object is a short localized | ||
| 626 | * phrase describing the purpose of the object. For example, in the | ||
| 627 | * case of a 'Cancel' button, the accessibleDescription could be | ||
| 628 | * 'Ignore changes and close dialog box.' | ||
| 629 | * | ||
| 630 | * @return the localized description of the object; null if | ||
| 631 | * this object does not have a description | ||
| 632 | * | ||
| 633 | * @see #setAccessibleDescription | ||
| 634 | */ | ||
| 635 | public String getAccessibleDescription() { | ||
| 636 | if (accessibleDescription != null) { // defined in AccessibleContext | ||
| 637 | return accessibleDescription; | ||
| 638 | } else if (accessibleJOptionPane != null) { | ||
| 639 | // delegate to the AccessibleJOptionPane | ||
| 640 | return accessibleJOptionPane.getAccessibleDescription(); | ||
| 641 | } | ||
| 642 | return null; | ||
| 643 | } | ||
| 644 | |||
| 645 | /** | ||
| 646 | * Gets the role of this object. The role of the object is the generic | ||
| 647 | * purpose or use of the class of this object. For example, the role | ||
| 648 | * of a push button is AccessibleRole.PUSH_BUTTON. The roles in | ||
| 649 | * AccessibleRole are provided so component developers can pick from | ||
| 650 | * a set of predefined roles. This enables assistive technologies to | ||
| 651 | * provide a consistent interface to various tweaked subclasses of | ||
| 652 | * components (e.g., use AccessibleRole.PUSH_BUTTON for all components | ||
| 653 | * that act like a push button) as well as distinguish between sublasses | ||
| 654 | * that behave differently (e.g., AccessibleRole.CHECK_BOX for check boxes | ||
| 655 | * and AccessibleRole.RADIO_BUTTON for radio buttons). | ||
| 656 | * <p>Note that the AccessibleRole class is also extensible, so | ||
| 657 | * custom component developers can define their own AccessibleRole's | ||
| 658 | * if the set of predefined roles is inadequate. | ||
| 659 | * | ||
| 660 | * @return an instance of AccessibleRole describing the role of the object | ||
| 661 | * @see AccessibleRole | ||
| 662 | */ | ||
| 663 | public AccessibleRole getAccessibleRole() { | ||
| 664 | return AccessibleRole.PROGRESS_MONITOR; | ||
| 665 | } | ||
| 666 | |||
| 667 | /** | ||
| 668 | * Gets the state set of this object. The AccessibleStateSet of an object | ||
| 669 | * is composed of a set of unique AccessibleStates. A change in the | ||
| 670 | * AccessibleStateSet of an object will cause a PropertyChangeEvent to | ||
| 671 | * be fired for the ACCESSIBLE_STATE_PROPERTY property. | ||
| 672 | * | ||
| 673 | * @return an instance of AccessibleStateSet containing the | ||
| 674 | * current state set of the object | ||
| 675 | * @see AccessibleStateSet | ||
| 676 | * @see AccessibleState | ||
| 677 | * @see #addPropertyChangeListener | ||
| 678 | */ | ||
| 679 | public AccessibleStateSet getAccessibleStateSet() { | ||
| 680 | if (accessibleJOptionPane != null) { | ||
| 681 | // delegate to the AccessibleJOptionPane | ||
| 682 | return accessibleJOptionPane.getAccessibleStateSet(); | ||
| 683 | } | ||
| 684 | return null; | ||
| 685 | } | ||
| 686 | |||
| 687 | /** | ||
| 688 | * Gets the Accessible parent of this object. | ||
| 689 | * | ||
| 690 | * @return the Accessible parent of this object; null if this | ||
| 691 | * object does not have an Accessible parent | ||
| 692 | */ | ||
| 693 | public Accessible getAccessibleParent() { | ||
| 694 | return dialog; | ||
| 695 | } | ||
| 696 | |||
| 697 | /* | ||
| 698 | * Returns the parent AccessibleContext | ||
| 699 | */ | ||
| 700 | private AccessibleContext getParentAccessibleContext() { | ||
| 701 | if (dialog != null) { | ||
| 702 | return dialog.getAccessibleContext(); | ||
| 703 | } | ||
| 704 | return null; | ||
| 705 | } | ||
| 706 | |||
| 707 | /** | ||
| 708 | * Gets the 0-based index of this object in its accessible parent. | ||
| 709 | * | ||
| 710 | * @return the 0-based index of this object in its parent; -1 if this | ||
| 711 | * object does not have an accessible parent. | ||
| 712 | * | ||
| 713 | * @see #getAccessibleParent | ||
| 714 | * @see #getAccessibleChildrenCount | ||
| 715 | * @see #getAccessibleChild | ||
| 716 | */ | ||
| 717 | public int getAccessibleIndexInParent() { | ||
| 718 | if (accessibleJOptionPane != null) { | ||
| 719 | // delegate to the AccessibleJOptionPane | ||
| 720 | return accessibleJOptionPane.getAccessibleIndexInParent(); | ||
| 721 | } | ||
| 722 | return -1; | ||
| 723 | } | ||
| 724 | |||
| 725 | /** | ||
| 726 | * Returns the number of accessible children of the object. | ||
| 727 | * | ||
| 728 | * @return the number of accessible children of the object. | ||
| 729 | */ | ||
| 730 | public int getAccessibleChildrenCount() { | ||
| 731 | // return the number of children in the JPanel containing | ||
| 732 | // the message, note label and progress bar | ||
| 733 | AccessibleContext ac = getPanelAccessibleContext(); | ||
| 734 | if (ac != null) { | ||
| 735 | return ac.getAccessibleChildrenCount(); | ||
| 736 | } | ||
| 737 | return 0; | ||
| 738 | } | ||
| 739 | |||
| 740 | /** | ||
| 741 | * Returns the specified Accessible child of the object. The Accessible | ||
| 742 | * children of an Accessible object are zero-based, so the first child | ||
| 743 | * of an Accessible child is at index 0, the second child is at index 1, | ||
| 744 | * and so on. | ||
| 745 | * | ||
| 746 | * @param i zero-based index of child | ||
| 747 | * @return the Accessible child of the object | ||
| 748 | * @see #getAccessibleChildrenCount | ||
| 749 | */ | ||
| 750 | public Accessible getAccessibleChild(int i) { | ||
| 751 | // return a child in the JPanel containing the message, note label | ||
| 752 | // and progress bar | ||
| 753 | AccessibleContext ac = getPanelAccessibleContext(); | ||
| 754 | if (ac != null) { | ||
| 755 | return ac.getAccessibleChild(i); | ||
| 756 | } | ||
| 757 | return null; | ||
| 758 | } | ||
| 759 | |||
| 760 | /* | ||
| 761 | * Returns the AccessibleContext for the JPanel containing the | ||
| 762 | * message, note label and progress bar | ||
| 763 | */ | ||
| 764 | private AccessibleContext getPanelAccessibleContext() { | ||
| 765 | if (myBar != null) { | ||
| 766 | Component c = myBar.getParent(); | ||
| 767 | if (c instanceof Accessible) { | ||
| 768 | return c.getAccessibleContext(); | ||
| 769 | } | ||
| 770 | } | ||
| 771 | return null; | ||
| 772 | } | ||
| 773 | |||
| 774 | /** | ||
| 775 | * Gets the locale of the component. If the component does not have a | ||
| 776 | * locale, then the locale of its parent is returned. | ||
| 777 | * | ||
| 778 | * @return this component's locale. If this component does not have | ||
| 779 | * a locale, the locale of its parent is returned. | ||
| 780 | * | ||
| 781 | * @exception IllegalComponentStateException | ||
| 782 | * If the Component does not have its own locale and has not yet been | ||
| 783 | * added to a containment hierarchy such that the locale can be | ||
| 784 | * determined from the containing parent. | ||
| 785 | */ | ||
| 786 | public Locale getLocale() throws IllegalComponentStateException { | ||
| 787 | if (accessibleJOptionPane != null) { | ||
| 788 | // delegate to the AccessibleJOptionPane | ||
| 789 | return accessibleJOptionPane.getLocale(); | ||
| 790 | } | ||
| 791 | return null; | ||
| 792 | } | ||
| 793 | |||
| 794 | /* ===== end AccessibleContext ===== */ | ||
| 795 | |||
| 796 | /** | ||
| 797 | * Gets the AccessibleComponent associated with this object that has a | ||
| 798 | * graphical representation. | ||
| 799 | * | ||
| 800 | * @return AccessibleComponent if supported by object; else return null | ||
| 801 | * @see AccessibleComponent | ||
| 802 | */ | ||
| 803 | public AccessibleComponent getAccessibleComponent() { | ||
| 804 | if (accessibleJOptionPane != null) { | ||
| 805 | // delegate to the AccessibleJOptionPane | ||
| 806 | return accessibleJOptionPane.getAccessibleComponent(); | ||
| 807 | } | ||
| 808 | return null; | ||
| 809 | } | ||
| 810 | |||
| 811 | /** | ||
| 812 | * Gets the AccessibleValue associated with this object that supports a | ||
| 813 | * Numerical value. | ||
| 814 | * | ||
| 815 | * @return AccessibleValue if supported by object; else return null | ||
| 816 | * @see AccessibleValue | ||
| 817 | */ | ||
| 818 | public AccessibleValue getAccessibleValue() { | ||
| 819 | if (myBar != null) { | ||
| 820 | // delegate to the AccessibleJProgressBar | ||
| 821 | return myBar.getAccessibleContext().getAccessibleValue(); | ||
| 822 | } | ||
| 823 | return null; | ||
| 824 | } | ||
| 825 | |||
| 826 | /** | ||
| 827 | * Gets the AccessibleText associated with this object presenting | ||
| 828 | * text on the display. | ||
| 829 | * | ||
| 830 | * @return AccessibleText if supported by object; else return null | ||
| 831 | * @see AccessibleText | ||
| 832 | */ | ||
| 833 | public AccessibleText getAccessibleText() { | ||
| 834 | if (getNoteLabelAccessibleText() != null) { | ||
| 835 | return this; | ||
| 836 | } | ||
| 837 | return null; | ||
| 838 | } | ||
| 839 | |||
| 840 | /* | ||
| 841 | * Returns the note label AccessibleText | ||
| 842 | */ | ||
| 843 | private AccessibleText getNoteLabelAccessibleText() { | ||
| 844 | if (noteLabel != null) { | ||
| 845 | // AccessibleJLabel implements AccessibleText if the | ||
| 846 | // JLabel contains HTML text | ||
| 847 | return noteLabel.getAccessibleContext().getAccessibleText(); | ||
| 848 | } | ||
| 849 | return null; | ||
| 850 | } | ||
| 851 | |||
| 852 | /* ===== Begin AccessibleText impl ===== */ | ||
| 853 | |||
| 854 | /** | ||
| 855 | * Given a point in local coordinates, return the zero-based index | ||
| 856 | * of the character under that Point. If the point is invalid, | ||
| 857 | * this method returns -1. | ||
| 858 | * | ||
| 859 | * @param p the Point in local coordinates | ||
| 860 | * @return the zero-based index of the character under Point p; if | ||
| 861 | * Point is invalid return -1. | ||
| 862 | */ | ||
| 863 | public int getIndexAtPoint(Point p) { | ||
| 864 | AccessibleText at = getNoteLabelAccessibleText(); | ||
| 865 | if (at != null && sameWindowAncestor(pane, noteLabel)) { | ||
| 866 | // convert point from the option pane bounds | ||
| 867 | // to the note label bounds. | ||
| 868 | Point noteLabelPoint = SwingUtilities.convertPoint(pane, | ||
| 869 | p, | ||
| 870 | noteLabel); | ||
| 871 | if (noteLabelPoint != null) { | ||
| 872 | return at.getIndexAtPoint(noteLabelPoint); | ||
| 873 | } | ||
| 874 | } | ||
| 875 | return -1; | ||
| 876 | } | ||
| 877 | |||
| 878 | /** | ||
| 879 | * Determines the bounding box of the character at the given | ||
| 880 | * index into the string. The bounds are returned in local | ||
| 881 | * coordinates. If the index is invalid an empty rectangle is returned. | ||
| 882 | * | ||
| 883 | * @param i the index into the String | ||
| 884 | * @return the screen coordinates of the character's bounding box, | ||
| 885 | * if index is invalid return an empty rectangle. | ||
| 886 | */ | ||
| 887 | public Rectangle getCharacterBounds(int i) { | ||
| 888 | AccessibleText at = getNoteLabelAccessibleText(); | ||
| 889 | if (at != null && sameWindowAncestor(pane, noteLabel)) { | ||
| 890 | // return rectangle in the option pane bounds | ||
| 891 | Rectangle noteLabelRect = at.getCharacterBounds(i); | ||
| 892 | if (noteLabelRect != null) { | ||
| 893 | return SwingUtilities.convertRectangle(noteLabel, | ||
| 894 | noteLabelRect, | ||
| 895 | pane); | ||
| 896 | } | ||
| 897 | } | ||
| 898 | return null; | ||
| 899 | } | ||
| 900 | |||
| 901 | /* | ||
| 902 | * Returns whether source and destination components have the | ||
| 903 | * same window ancestor | ||
| 904 | */ | ||
| 905 | private boolean sameWindowAncestor(Component src, Component dest) { | ||
| 906 | if (src == null || dest == null) { | ||
| 907 | return false; | ||
| 908 | } | ||
| 909 | return SwingUtilities.getWindowAncestor(src) == | ||
| 910 | SwingUtilities.getWindowAncestor(dest); | ||
| 911 | } | ||
| 912 | |||
| 913 | /** | ||
| 914 | * Returns the number of characters (valid indicies) | ||
| 915 | * | ||
| 916 | * @return the number of characters | ||
| 917 | */ | ||
| 918 | public int getCharCount() { | ||
| 919 | AccessibleText at = getNoteLabelAccessibleText(); | ||
| 920 | if (at != null) { // JLabel contains HTML text | ||
| 921 | return at.getCharCount(); | ||
| 922 | } | ||
| 923 | return -1; | ||
| 924 | } | ||
| 925 | |||
| 926 | /** | ||
| 927 | * Returns the zero-based offset of the caret. | ||
| 928 | * | ||
| 929 | * Note: That to the right of the caret will have the same index | ||
| 930 | * value as the offset (the caret is between two characters). | ||
| 931 | * @return the zero-based offset of the caret. | ||
| 932 | */ | ||
| 933 | public int getCaretPosition() { | ||
| 934 | AccessibleText at = getNoteLabelAccessibleText(); | ||
| 935 | if (at != null) { // JLabel contains HTML text | ||
| 936 | return at.getCaretPosition(); | ||
| 937 | } | ||
| 938 | return -1; | ||
| 939 | } | ||
| 940 | |||
| 941 | /** | ||
| 942 | * Returns the String at a given index. | ||
| 943 | * | ||
| 944 | * @param part the CHARACTER, WORD, or SENTENCE to retrieve | ||
| 945 | * @param index an index within the text | ||
| 946 | * @return the letter, word, or sentence | ||
| 947 | */ | ||
| 948 | public String getAtIndex(int part, int index) { | ||
| 949 | AccessibleText at = getNoteLabelAccessibleText(); | ||
| 950 | if (at != null) { // JLabel contains HTML text | ||
| 951 | return at.getAtIndex(part, index); | ||
| 952 | } | ||
| 953 | return null; | ||
| 954 | } | ||
| 955 | |||
| 956 | /** | ||
| 957 | * Returns the String after a given index. | ||
| 958 | * | ||
| 959 | * @param part the CHARACTER, WORD, or SENTENCE to retrieve | ||
| 960 | * @param index an index within the text | ||
| 961 | * @return the letter, word, or sentence | ||
| 962 | */ | ||
| 963 | public String getAfterIndex(int part, int index) { | ||
| 964 | AccessibleText at = getNoteLabelAccessibleText(); | ||
| 965 | if (at != null) { // JLabel contains HTML text | ||
| 966 | return at.getAfterIndex(part, index); | ||
| 967 | } | ||
| 968 | return null; | ||
| 969 | } | ||
| 970 | |||
| 971 | /** | ||
| 972 | * Returns the String before a given index. | ||
| 973 | * | ||
| 974 | * @param part the CHARACTER, WORD, or SENTENCE to retrieve | ||
| 975 | * @param index an index within the text | ||
| 976 | * @return the letter, word, or sentence | ||
| 977 | */ | ||
| 978 | public String getBeforeIndex(int part, int index) { | ||
| 979 | AccessibleText at = getNoteLabelAccessibleText(); | ||
| 980 | if (at != null) { // JLabel contains HTML text | ||
| 981 | return at.getBeforeIndex(part, index); | ||
| 982 | } | ||
| 983 | return null; | ||
| 984 | } | ||
| 985 | |||
| 986 | /** | ||
| 987 | * Returns the AttributeSet for a given character at a given index | ||
| 988 | * | ||
| 989 | * @param i the zero-based index into the text | ||
| 990 | * @return the AttributeSet of the character | ||
| 991 | */ | ||
| 992 | public AttributeSet getCharacterAttribute(int i) { | ||
| 993 | AccessibleText at = getNoteLabelAccessibleText(); | ||
| 994 | if (at != null) { // JLabel contains HTML text | ||
| 995 | return at.getCharacterAttribute(i); | ||
| 996 | } | ||
| 997 | return null; | ||
| 998 | } | ||
| 999 | |||
| 1000 | /** | ||
| 1001 | * Returns the start offset within the selected text. | ||
| 1002 | * If there is no selection, but there is | ||
| 1003 | * a caret, the start and end offsets will be the same. | ||
| 1004 | * | ||
| 1005 | * @return the index into the text of the start of the selection | ||
| 1006 | */ | ||
| 1007 | public int getSelectionStart() { | ||
| 1008 | AccessibleText at = getNoteLabelAccessibleText(); | ||
| 1009 | if (at != null) { // JLabel contains HTML text | ||
| 1010 | return at.getSelectionStart(); | ||
| 1011 | } | ||
| 1012 | return -1; | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | /** | ||
| 1016 | * Returns the end offset within the selected text. | ||
| 1017 | * If there is no selection, but there is | ||
| 1018 | * a caret, the start and end offsets will be the same. | ||
| 1019 | * | ||
| 1020 | * @return the index into teh text of the end of the selection | ||
| 1021 | */ | ||
| 1022 | public int getSelectionEnd() { | ||
| 1023 | AccessibleText at = getNoteLabelAccessibleText(); | ||
| 1024 | if (at != null) { // JLabel contains HTML text | ||
| 1025 | return at.getSelectionEnd(); | ||
| 1026 | } | ||
| 1027 | return -1; | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | /** | ||
| 1031 | * Returns the portion of the text that is selected. | ||
| 1032 | * | ||
| 1033 | * @return the String portion of the text that is selected | ||
| 1034 | */ | ||
| 1035 | public String getSelectedText() { | ||
| 1036 | AccessibleText at = getNoteLabelAccessibleText(); | ||
| 1037 | if (at != null) { // JLabel contains HTML text | ||
| 1038 | return at.getSelectedText(); | ||
| 1039 | } | ||
| 1040 | return null; | ||
| 1041 | } | ||
| 1042 | /* ===== End AccessibleText impl ===== */ | ||
| 1043 | } | ||
| 1044 | // inner class AccessibleProgressMonitor | ||
| 1045 | |||
| 1046 | } | ||