49 * starts out empty and gradually becomes filled in as the task progresses.
50 * In addition, the progress bar can display a textual representation of this
51 * percentage.
52 * <p>
53 * {@code JProgressBar} uses a {@code BoundedRangeModel} as its data model,
54 * with the {@code value} property representing the "current" state of the task,
55 * and the {@code minimum} and {@code maximum} properties representing the
56 * beginning and end points, respectively.
57 * <p>
58 * To indicate that a task of unknown length is executing,
59 * you can put a progress bar into indeterminate mode.
60 * While the bar is in indeterminate mode,
61 * it animates constantly to show that work is occurring.
62 * As soon as you can determine the task's length and amount of progress,
63 * you should update the progress bar's value
64 * and switch it back to determinate mode.
65 *
66 * <p>
67 *
68 * Here is an example of creating a progress bar,
69 * where <code>task</code> is an object (representing some piece of work)
70 * which returns information about the progress of the task:
71 *
72 *<pre>
73 *progressBar = new JProgressBar(0, task.getLengthOfTask());
74 *progressBar.setValue(0);
75 *progressBar.setStringPainted(true);
76 *</pre>
77 *
78 * Here is an example of querying the current state of the task, and using
79 * the returned value to update the progress bar:
80 *
81 *<pre>
82 *progressBar.setValue(task.getCurrent());
83 *</pre>
84 *
85 * Here is an example of putting a progress bar into
86 * indeterminate mode,
87 * and then switching back to determinate mode
88 * once the length of the task is known:
89 *
98 *</pre>
99 *
100 * <p>
101 *
102 * For complete examples and further documentation see
103 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/progress.html" target="_top">How to Monitor Progress</a>,
104 * a section in <em>The Java Tutorial.</em>
105 *
106 * <p>
107 * <strong>Warning:</strong> Swing is not thread safe. For more
108 * information see <a
109 * href="package-summary.html#threading">Swing's Threading
110 * Policy</a>.
111 * <p>
112 * <strong>Warning:</strong>
113 * Serialized objects of this class will not be compatible with
114 * future Swing releases. The current serialization support is
115 * appropriate for short term storage or RMI between applications running
116 * the same version of Swing. As of 1.4, support for long term storage
117 * of all JavaBeans™
118 * has been added to the <code>java.beans</code> package.
119 * Please see {@link java.beans.XMLEncoder}.
120 *
121 * @see javax.swing.plaf.basic.BasicProgressBarUI
122 * @see javax.swing.BoundedRangeModel
123 * @see javax.swing.SwingWorker
124 *
125 * @beaninfo
126 * attribute: isContainer false
127 * description: A component that displays an integer value.
128 *
129 * @author Michael C. Albers
130 * @author Kathy Walrath
131 * @since 1.2
132 */
133 @SuppressWarnings("serial") // Same-version serialization only
134 public class JProgressBar extends JComponent implements SwingConstants, Accessible
135 {
136 /**
137 * @see #getUIClassID
138 */
139 private static final String uiClassID = "ProgressBarUI";
140
141 /**
142 * Whether the progress bar is horizontal or vertical.
143 * The default is <code>HORIZONTAL</code>.
144 *
145 * @see #setOrientation
146 */
147 protected int orientation;
148
149 /**
150 * Whether to display a border around the progress bar.
151 * The default is <code>true</code>.
152 *
153 * @see #setBorderPainted
154 */
155 protected boolean paintBorder;
156
157 /**
158 * The object that holds the data for the progress bar.
159 *
160 * @see #setModel
161 */
162 protected BoundedRangeModel model;
163
164 /**
165 * An optional string that can be displayed on the progress bar.
166 * The default is <code>null</code>. Setting this to a non-<code>null</code>
167 * value does not imply that the string will be displayed.
168 * To display the string, {@code paintString} must be {@code true}.
169 *
170 * @see #setString
171 * @see #setStringPainted
172 */
173 protected String progressString;
174
175 /**
176 * Whether to display a string of text on the progress bar.
177 * The default is <code>false</code>.
178 * Setting this to <code>true</code> causes a textual
179 * display of the progress to be rendered on the progress bar. If
180 * the <code>progressString</code> is <code>null</code>,
181 * the percentage of completion is displayed on the progress bar.
182 * Otherwise, the <code>progressString</code> is
183 * rendered on the progress bar.
184 *
185 * @see #setStringPainted
186 * @see #setString
187 */
188 protected boolean paintString;
189
190 /**
191 * The default minimum for a progress bar is 0.
192 */
193 private static final int defaultMinimum = 0;
194 /**
195 * The default maximum for a progress bar is 100.
196 */
197 private static final int defaultMaximum = 100;
198 /**
199 * The default orientation for a progress bar is <code>HORIZONTAL</code>.
200 */
201 private static final int defaultOrientation = HORIZONTAL;
202
203 /**
204 * Only one <code>ChangeEvent</code> is needed per instance since the
205 * event's only interesting property is the immutable source, which
206 * is the progress bar.
207 * The event is lazily created the first time that an
208 * event notification is fired.
209 *
210 * @see #fireStateChanged
211 */
212 protected transient ChangeEvent changeEvent = null;
213
214 /**
215 * Listens for change events sent by the progress bar's model,
216 * redispatching them
217 * to change-event listeners registered upon
218 * this progress bar.
219 *
220 * @see #createChangeListener
221 */
222 protected ChangeListener changeListener = null;
223
224 /**
225 * Format used when displaying percent complete.
226 */
227 private transient Format format;
228
229 /**
230 * Whether the progress bar is indeterminate (<code>true</code>) or
231 * normal (<code>false</code>); the default is <code>false</code>.
232 *
233 * @see #setIndeterminate
234 * @since 1.4
235 */
236 private boolean indeterminate;
237
238
239 /**
240 * Creates a horizontal progress bar
241 * that displays a border but no progress string.
242 * The initial and minimum values are 0,
243 * and the maximum is 100.
244 *
245 * @see #setOrientation
246 * @see #setBorderPainted
247 * @see #setStringPainted
248 * @see #setString
249 * @see #setIndeterminate
250 */
251 public JProgressBar()
266 * @throws IllegalArgumentException if {@code orient} is an illegal value
267 *
268 * @see #setOrientation
269 * @see #setBorderPainted
270 * @see #setStringPainted
271 * @see #setString
272 * @see #setIndeterminate
273 */
274 public JProgressBar(int orient)
275 {
276 this(orient, defaultMinimum, defaultMaximum);
277 }
278
279
280 /**
281 * Creates a horizontal progress bar
282 * with the specified minimum and maximum.
283 * Sets the initial value of the progress bar to the specified minimum.
284 * By default, a border is painted but a progress string is not.
285 * <p>
286 * The <code>BoundedRangeModel</code> that holds the progress bar's data
287 * handles any issues that may arise from improperly setting the
288 * minimum, initial, and maximum values on the progress bar.
289 * See the {@code BoundedRangeModel} documentation for details.
290 *
291 * @param min the minimum value of the progress bar
292 * @param max the maximum value of the progress bar
293 *
294 * @see BoundedRangeModel
295 * @see #setOrientation
296 * @see #setBorderPainted
297 * @see #setStringPainted
298 * @see #setString
299 * @see #setIndeterminate
300 */
301 public JProgressBar(int min, int max)
302 {
303 this(defaultOrientation, min, max);
304 }
305
306
307 /**
308 * Creates a progress bar using the specified orientation,
309 * minimum, and maximum.
310 * By default, a border is painted but a progress string is not.
311 * Sets the initial value of the progress bar to the specified minimum.
312 * <p>
313 * The <code>BoundedRangeModel</code> that holds the progress bar's data
314 * handles any issues that may arise from improperly setting the
315 * minimum, initial, and maximum values on the progress bar.
316 * See the {@code BoundedRangeModel} documentation for details.
317 *
318 * @param orient the desired orientation of the progress bar
319 * @param min the minimum value of the progress bar
320 * @param max the maximum value of the progress bar
321 * @throws IllegalArgumentException if {@code orient} is an illegal value
322 *
323 * @see BoundedRangeModel
324 * @see #setOrientation
325 * @see #setBorderPainted
326 * @see #setStringPainted
327 * @see #setString
328 * @see #setIndeterminate
329 */
330 public JProgressBar(int orient, int min, int max)
331 {
332 // Creating the model this way is a bit simplistic, but
333 // I believe that it is the most common usage of this
359 */
360 public JProgressBar(BoundedRangeModel newModel)
361 {
362 setModel(newModel);
363 updateUI();
364
365 setOrientation(defaultOrientation); // see setOrientation()
366 setBorderPainted(true); // see setBorderPainted()
367 setStringPainted(false); // see setStringPainted
368 setString(null); // see getString
369 setIndeterminate(false); // see setIndeterminate
370 }
371
372
373 /**
374 * Returns {@code SwingConstants.VERTICAL} or
375 * {@code SwingConstants.HORIZONTAL}, depending on the orientation
376 * of the progress bar. The default orientation is
377 * {@code SwingConstants.HORIZONTAL}.
378 *
379 * @return <code>HORIZONTAL</code> or <code>VERTICAL</code>
380 * @see #setOrientation
381 */
382 public int getOrientation() {
383 return orientation;
384 }
385
386
387 /**
388 * Sets the progress bar's orientation to <code>newOrientation</code>,
389 * which must be {@code SwingConstants.VERTICAL} or
390 * {@code SwingConstants.HORIZONTAL}. The default orientation
391 * is {@code SwingConstants.HORIZONTAL}.
392 *
393 * @param newOrientation <code>HORIZONTAL</code> or <code>VERTICAL</code>
394 * @exception IllegalArgumentException if <code>newOrientation</code>
395 * is an illegal value
396 * @see #getOrientation
397 *
398 * @beaninfo
399 * preferred: true
400 * bound: true
401 * attribute: visualUpdate true
402 * description: Set the progress bar's orientation.
403 */
404 public void setOrientation(int newOrientation) {
405 if (orientation != newOrientation) {
406 switch (newOrientation) {
407 case VERTICAL:
408 case HORIZONTAL:
409 int oldOrientation = orientation;
410 orientation = newOrientation;
411 firePropertyChange("orientation", oldOrientation, newOrientation);
412 if (accessibleContext != null) {
413 accessibleContext.firePropertyChange(
414 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
415 ((oldOrientation == VERTICAL)
416 ? AccessibleState.VERTICAL
417 : AccessibleState.HORIZONTAL),
418 ((orientation == VERTICAL)
419 ? AccessibleState.VERTICAL
420 : AccessibleState.HORIZONTAL));
421 }
422 break;
423 default:
424 throw new IllegalArgumentException(newOrientation +
425 " is not a legal orientation");
426 }
427 revalidate();
428 }
429 }
430
431
432 /**
433 * Returns the value of the <code>stringPainted</code> property.
434 *
435 * @return the value of the <code>stringPainted</code> property
436 * @see #setStringPainted
437 * @see #setString
438 */
439 public boolean isStringPainted() {
440 return paintString;
441 }
442
443
444 /**
445 * Sets the value of the <code>stringPainted</code> property,
446 * which determines whether the progress bar
447 * should render a progress string.
448 * The default is <code>false</code>, meaning
449 * no string is painted.
450 * Some look and feels might not support progress strings
451 * or might support them only when the progress bar is in determinate mode.
452 *
453 * @param b <code>true</code> if the progress bar should render a string
454 * @see #isStringPainted
455 * @see #setString
456 * @beaninfo
457 * bound: true
458 * attribute: visualUpdate true
459 * description: Whether the progress bar should render a string.
460 */
461 public void setStringPainted(boolean b) {
462 //PENDING: specify that string not painted when in indeterminate mode?
463 // or just leave that to the L&F?
464 boolean oldValue = paintString;
465 paintString = b;
466 firePropertyChange("stringPainted", oldValue, paintString);
467 if (paintString != oldValue) {
468 revalidate();
469 repaint();
470 }
471 }
472
473
477 * the value returned from {@code getPercentComplete}. An example
478 * would be the "42%". You can change this by calling {@code setString}.
479 *
480 * @return the value of the progress string, or a simple percentage string
481 * if the progress string is {@code null}
482 * @see #setString
483 */
484 public String getString(){
485 if (progressString != null) {
486 return progressString;
487 } else {
488 if (format == null) {
489 format = NumberFormat.getPercentInstance();
490 }
491 return format.format(new Double(getPercentComplete()));
492 }
493 }
494
495 /**
496 * Sets the value of the progress string. By default,
497 * this string is <code>null</code>, implying the built-in behavior of
498 * using a simple percent string.
499 * If you have provided a custom progress string and want to revert to
500 * the built-in behavior, set the string back to <code>null</code>.
501 * <p>
502 * The progress string is painted only if
503 * the <code>isStringPainted</code> method returns <code>true</code>.
504 *
505 * @param s the value of the progress string
506 * @see #getString
507 * @see #setStringPainted
508 * @see #isStringPainted
509 * @beaninfo
510 * bound: true
511 * attribute: visualUpdate true
512 * description: Specifies the progress string to paint
513 */
514 public void setString(String s){
515 String oldValue = progressString;
516 progressString = s;
517 firePropertyChange("string", oldValue, progressString);
518 if (progressString == null || oldValue == null || !progressString.equals(oldValue)) {
519 repaint();
520 }
521 }
522
523 /**
524 * Returns the percent complete for the progress bar.
525 * Note that this number is between 0.0 and 1.0.
526 *
527 * @return the percent complete for this progress bar
528 */
529 public double getPercentComplete() {
530 long span = model.getMaximum() - model.getMinimum();
531 double currentValue = model.getValue();
532 double pc = (currentValue - model.getMinimum()) / span;
533 return pc;
534 }
535
536 /**
537 * Returns the <code>borderPainted</code> property.
538 *
539 * @return the value of the <code>borderPainted</code> property
540 * @see #setBorderPainted
541 * @beaninfo
542 * description: Does the progress bar paint its border
543 */
544 public boolean isBorderPainted() {
545 return paintBorder;
546 }
547
548 /**
549 * Sets the <code>borderPainted</code> property, which is
550 * <code>true</code> if the progress bar should paint its border.
551 * The default value for this property is <code>true</code>.
552 * Some look and feels might not implement painted borders;
553 * they will ignore this property.
554 *
555 * @param b <code>true</code> if the progress bar
556 * should paint its border;
557 * otherwise, <code>false</code>
558 * @see #isBorderPainted
559 * @beaninfo
560 * bound: true
561 * attribute: visualUpdate true
562 * description: Whether the progress bar should paint its border.
563 */
564 public void setBorderPainted(boolean b) {
565 boolean oldValue = paintBorder;
566 paintBorder = b;
567 firePropertyChange("borderPainted", oldValue, paintBorder);
568 if (paintBorder != oldValue) {
569 repaint();
570 }
571 }
572
573 /**
574 * Paints the progress bar's border if the <code>borderPainted</code>
575 * property is <code>true</code>.
576 *
577 * @param g the <code>Graphics</code> context within which to paint the border
578 * @see #paint
579 * @see #setBorder
580 * @see #isBorderPainted
581 * @see #setBorderPainted
582 */
583 protected void paintBorder(Graphics g) {
584 if (isBorderPainted()) {
585 super.paintBorder(g);
586 }
587 }
588
589
590 /**
591 * Returns the look-and-feel object that renders this component.
592 *
593 * @return the <code>ProgressBarUI</code> object that renders this component
594 */
595 public ProgressBarUI getUI() {
596 return (ProgressBarUI)ui;
597 }
598
599 /**
600 * Sets the look-and-feel object that renders this component.
601 *
602 * @param ui a <code>ProgressBarUI</code> object
603 * @see UIDefaults#getUI
604 * @beaninfo
605 * bound: true
606 * hidden: true
607 * attribute: visualUpdate true
608 * description: The UI object that implements the Component's LookAndFeel.
609 */
610 public void setUI(ProgressBarUI ui) {
611 super.setUI(ui);
612 }
613
614
615 /**
616 * Resets the UI property to a value from the current look and feel.
617 *
618 * @see JComponent#updateUI
619 */
620 public void updateUI() {
621 setUI((ProgressBarUI)UIManager.getUI(this));
622 }
629 * @see JComponent#getUIClassID
630 * @see UIDefaults#getUI
631 * @beaninfo
632 * expert: true
633 * description: A string that specifies the name of the look-and-feel class.
634 */
635 public String getUIClassID() {
636 return uiClassID;
637 }
638
639
640 /* We pass each Change event to the listeners with the
641 * the progress bar as the event source.
642 * <p>
643 * <strong>Warning:</strong>
644 * Serialized objects of this class will not be compatible with
645 * future Swing releases. The current serialization support is
646 * appropriate for short term storage or RMI between applications running
647 * the same version of Swing. As of 1.4, support for long term storage
648 * of all JavaBeans™
649 * has been added to the <code>java.beans</code> package.
650 * Please see {@link java.beans.XMLEncoder}.
651 */
652 @SuppressWarnings("serial") // Same-version serialization only
653 private class ModelListener implements ChangeListener, Serializable {
654 public void stateChanged(ChangeEvent e) {
655 fireStateChanged();
656 }
657 }
658
659 /**
660 * Subclasses that want to handle change events
661 * from the model differently
662 * can override this to return
663 * an instance of a custom <code>ChangeListener</code> implementation.
664 * The default {@code ChangeListener} simply calls the
665 * {@code fireStateChanged} method to forward {@code ChangeEvent}s
666 * to the {@code ChangeListener}s that have been added directly to the
667 * progress bar.
668 *
669 * @return the instance of a custom {@code ChangeListener} implementation.
670 * @see #changeListener
671 * @see #fireStateChanged
672 * @see javax.swing.event.ChangeListener
673 * @see javax.swing.BoundedRangeModel
674 */
675 protected ChangeListener createChangeListener() {
676 return new ModelListener();
677 }
678
679 /**
680 * Adds the specified <code>ChangeListener</code> to the progress bar.
681 *
682 * @param l the <code>ChangeListener</code> to add
683 */
684 public void addChangeListener(ChangeListener l) {
685 listenerList.add(ChangeListener.class, l);
686 }
687
688 /**
689 * Removes a <code>ChangeListener</code> from the progress bar.
690 *
691 * @param l the <code>ChangeListener</code> to remove
692 */
693 public void removeChangeListener(ChangeListener l) {
694 listenerList.remove(ChangeListener.class, l);
695 }
696
697 /**
698 * Returns an array of all the <code>ChangeListener</code>s added
699 * to this progress bar with <code>addChangeListener</code>.
700 *
701 * @return all of the <code>ChangeListener</code>s added or an empty
702 * array if no listeners have been added
703 * @since 1.4
704 */
705 public ChangeListener[] getChangeListeners() {
706 return listenerList.getListeners(ChangeListener.class);
707 }
708
709 /**
710 * Send a {@code ChangeEvent}, whose source is this {@code JProgressBar}, to
711 * all {@code ChangeListener}s that have registered interest in
712 * {@code ChangeEvent}s.
713 * This method is called each time a {@code ChangeEvent} is received from
714 * the model.
715 * <p>
716 *
717 * The event instance is created if necessary, and stored in
718 * {@code changeEvent}.
719 *
720 * @see #addChangeListener
721 * @see EventListenerList
722 */
723 protected void fireStateChanged() {
724 // Guaranteed to return a non-null array
725 Object[] listeners = listenerList.getListenerList();
726 // Process the listeners last to first, notifying
727 // those that are interested in this event
728 for (int i = listeners.length-2; i>=0; i-=2) {
729 if (listeners[i]==ChangeListener.class) {
730 // Lazily create the event:
731 if (changeEvent == null)
732 changeEvent = new ChangeEvent(this);
733 ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
734 }
735 }
736 }
737
738 /**
739 * Returns the data model used by this progress bar.
740 *
741 * @return the <code>BoundedRangeModel</code> currently in use
742 * @see #setModel
743 * @see BoundedRangeModel
744 */
745 public BoundedRangeModel getModel() {
746 return model;
747 }
748
749 /**
750 * Sets the data model used by the <code>JProgressBar</code>.
751 * Note that the {@code BoundedRangeModel}'s {@code extent} is not used,
752 * and is set to {@code 0}.
753 *
754 * @param newModel the <code>BoundedRangeModel</code> to use
755 *
756 * @beaninfo
757 * expert: true
758 * description: The data model used by the JProgressBar.
759 */
760 public void setModel(BoundedRangeModel newModel) {
761 // PENDING(???) setting the same model to multiple bars is broken; listeners
762 BoundedRangeModel oldModel = getModel();
763
764 if (newModel != oldModel) {
765 if (oldModel != null) {
766 oldModel.removeChangeListener(changeListener);
767 changeListener = null;
768 }
769
770 model = newModel;
771
772 if (newModel != null) {
773 changeListener = createChangeListener();
774 newModel.addChangeListener(changeListener);
778 accessibleContext.firePropertyChange(
779 AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
780 (oldModel== null
781 ? null : Integer.valueOf(oldModel.getValue())),
782 (newModel== null
783 ? null : Integer.valueOf(newModel.getValue())));
784 }
785
786 if (model != null) {
787 model.setExtent(0);
788 }
789 repaint();
790 }
791 }
792
793
794 /* All of the model methods are implemented by delegation. */
795
796 /**
797 * Returns the progress bar's current {@code value}
798 * from the <code>BoundedRangeModel</code>.
799 * The value is always between the
800 * minimum and maximum values, inclusive.
801 *
802 * @return the current value of the progress bar
803 * @see #setValue
804 * @see BoundedRangeModel#getValue
805 */
806 public int getValue() { return getModel().getValue(); }
807
808 /**
809 * Returns the progress bar's {@code minimum} value
810 * from the <code>BoundedRangeModel</code>.
811 *
812 * @return the progress bar's minimum value
813 * @see #setMinimum
814 * @see BoundedRangeModel#getMinimum
815 */
816 public int getMinimum() { return getModel().getMinimum(); }
817
818 /**
819 * Returns the progress bar's {@code maximum} value
820 * from the <code>BoundedRangeModel</code>.
821 *
822 * @return the progress bar's maximum value
823 * @see #setMaximum
824 * @see BoundedRangeModel#getMaximum
825 */
826 public int getMaximum() { return getModel().getMaximum(); }
827
828 /**
829 * Sets the progress bar's current value to {@code n}. This method
830 * forwards the new value to the model.
831 * <p>
832 * The data model (an instance of {@code BoundedRangeModel})
833 * handles any mathematical
834 * issues arising from assigning faulty values. See the
835 * {@code BoundedRangeModel} documentation for details.
836 * <p>
837 * If the new value is different from the previous value,
838 * all change listeners are notified.
839 *
840 * @param n the new value
843 * @see BoundedRangeModel#setValue
844 * @beaninfo
845 * preferred: true
846 * description: The progress bar's current value.
847 */
848 public void setValue(int n) {
849 BoundedRangeModel brm = getModel();
850 int oldValue = brm.getValue();
851 brm.setValue(n);
852
853 if (accessibleContext != null) {
854 accessibleContext.firePropertyChange(
855 AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
856 Integer.valueOf(oldValue),
857 Integer.valueOf(brm.getValue()));
858 }
859 }
860
861 /**
862 * Sets the progress bar's minimum value
863 * (stored in the progress bar's data model) to <code>n</code>.
864 * <p>
865 * The data model (a <code>BoundedRangeModel</code> instance)
866 * handles any mathematical
867 * issues arising from assigning faulty values.
868 * See the {@code BoundedRangeModel} documentation for details.
869 * <p>
870 * If the minimum value is different from the previous minimum,
871 * all change listeners are notified.
872 *
873 * @param n the new minimum
874 * @see #getMinimum
875 * @see #addChangeListener
876 * @see BoundedRangeModel#setMinimum
877 * @beaninfo
878 * preferred: true
879 * description: The progress bar's minimum value.
880 */
881 public void setMinimum(int n) { getModel().setMinimum(n); }
882
883 /**
884 * Sets the progress bar's maximum value
885 * (stored in the progress bar's data model) to <code>n</code>.
886 * <p>
887 * The underlying <code>BoundedRangeModel</code> handles any mathematical
888 * issues arising from assigning faulty values.
889 * See the {@code BoundedRangeModel} documentation for details.
890 * <p>
891 * If the maximum value is different from the previous maximum,
892 * all change listeners are notified.
893 *
894 * @param n the new maximum
895 * @see #getMaximum
896 * @see #addChangeListener
897 * @see BoundedRangeModel#setMaximum
898 * @beaninfo
899 * preferred: true
900 * description: The progress bar's maximum value.
901 */
902 public void setMaximum(int n) { getModel().setMaximum(n); }
903
904 /**
905 * Sets the <code>indeterminate</code> property of the progress bar,
906 * which determines whether the progress bar is in determinate
907 * or indeterminate mode.
908 * An indeterminate progress bar continuously displays animation
909 * indicating that an operation of unknown length is occurring.
910 * By default, this property is <code>false</code>.
911 * Some look and feels might not support indeterminate progress bars;
912 * they will ignore this property.
913 *
914 * <p>
915 *
916 * See
917 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/progress.html" target="_top">How to Monitor Progress</a>
918 * for examples of using indeterminate progress bars.
919 *
920 * @param newValue <code>true</code> if the progress bar
921 * should change to indeterminate mode;
922 * <code>false</code> if it should revert to normal.
923 *
924 * @see #isIndeterminate
925 * @see javax.swing.plaf.basic.BasicProgressBarUI
926 *
927 * @since 1.4
928 *
929 * @beaninfo
930 * bound: true
931 * attribute: visualUpdate true
932 * description: Set whether the progress bar is indeterminate (true)
933 * or normal (false).
934 */
935 public void setIndeterminate(boolean newValue) {
936 boolean oldValue = indeterminate;
937 indeterminate = newValue;
938 firePropertyChange("indeterminate", oldValue, indeterminate);
939 }
940
941 /**
942 * Returns the value of the <code>indeterminate</code> property.
943 *
944 * @return the value of the <code>indeterminate</code> property
945 * @see #setIndeterminate
946 *
947 * @since 1.4
948 *
949 * @beaninfo
950 * description: Is the progress bar indeterminate (true)
951 * or normal (false)?
952 */
953 public boolean isIndeterminate() {
954 return indeterminate;
955 }
956
957
958 /**
959 * See readObject() and writeObject() in JComponent for more
960 * information about serialization in Swing.
961 */
962 private void writeObject(ObjectOutputStream s) throws IOException {
963 s.defaultWriteObject();
964 if (getUIClassID().equals(uiClassID)) {
965 byte count = JComponent.getWriteObjCounter(this);
966 JComponent.setWriteObjCounter(this, --count);
967 if (count == 0 && ui != null) {
968 ui.installUI(this);
969 }
970 }
971 }
972
973
974 /**
975 * Returns a string representation of this <code>JProgressBar</code>.
976 * This method is intended to be used only for debugging purposes. The
977 * content and format of the returned string may vary between
978 * implementations. The returned string may be empty but may not
979 * be <code>null</code>.
980 *
981 * @return a string representation of this <code>JProgressBar</code>
982 */
983 protected String paramString() {
984 String orientationString = (orientation == HORIZONTAL ?
985 "HORIZONTAL" : "VERTICAL");
986 String paintBorderString = (paintBorder ?
987 "true" : "false");
988 String progressStringString = (progressString != null ?
989 progressString : "");
990 String paintStringString = (paintString ?
991 "true" : "false");
992 String indeterminateString = (indeterminate ?
993 "true" : "false");
994
995 return super.paramString() +
996 ",orientation=" + orientationString +
997 ",paintBorder=" + paintBorderString +
998 ",paintString=" + paintStringString +
999 ",progressString=" + progressStringString +
1000 ",indeterminateString=" + indeterminateString;
1001 }
1002
1003 /////////////////
1004 // Accessibility support
1005 ////////////////
1006
1007 /**
1008 * Gets the <code>AccessibleContext</code> associated with this
1009 * <code>JProgressBar</code>. For progress bars, the
1010 * <code>AccessibleContext</code> takes the form of an
1011 * <code>AccessibleJProgressBar</code>.
1012 * A new <code>AccessibleJProgressBar</code> instance is created if necessary.
1013 *
1014 * @return an <code>AccessibleJProgressBar</code> that serves as the
1015 * <code>AccessibleContext</code> of this <code>JProgressBar</code>
1016 * @beaninfo
1017 * expert: true
1018 * description: The AccessibleContext associated with this ProgressBar.
1019 */
1020 public AccessibleContext getAccessibleContext() {
1021 if (accessibleContext == null) {
1022 accessibleContext = new AccessibleJProgressBar();
1023 }
1024 return accessibleContext;
1025 }
1026
1027 /**
1028 * This class implements accessibility support for the
1029 * <code>JProgressBar</code> class. It provides an implementation of the
1030 * Java Accessibility API appropriate to progress bar user-interface
1031 * elements.
1032 * <p>
1033 * <strong>Warning:</strong>
1034 * Serialized objects of this class will not be compatible with
1035 * future Swing releases. The current serialization support is
1036 * appropriate for short term storage or RMI between applications running
1037 * the same version of Swing. As of 1.4, support for long term storage
1038 * of all JavaBeans™
1039 * has been added to the <code>java.beans</code> package.
1040 * Please see {@link java.beans.XMLEncoder}.
1041 */
1042 @SuppressWarnings("serial") // Same-version serialization only
1043 protected class AccessibleJProgressBar extends AccessibleJComponent
1044 implements AccessibleValue {
1045
1046 /**
1047 * Gets the state set of this object.
1048 *
1049 * @return an instance of AccessibleState containing the current state
1050 * of the object
1051 * @see AccessibleState
1052 */
1053 public AccessibleStateSet getAccessibleStateSet() {
1054 AccessibleStateSet states = super.getAccessibleStateSet();
1055 if (getModel().getValueIsAdjusting()) {
1056 states.add(AccessibleState.BUSY);
1057 }
1058 if (getOrientation() == VERTICAL) {
1059 states.add(AccessibleState.VERTICAL);
1060 } else {
1061 states.add(AccessibleState.HORIZONTAL);
1062 }
1063 return states;
1064 }
1065
1066 /**
1067 * Gets the role of this object.
1068 *
1069 * @return an instance of AccessibleRole describing the role of the
1070 * object
1071 */
1072 public AccessibleRole getAccessibleRole() {
1073 return AccessibleRole.PROGRESS_BAR;
1074 }
1075
1076 /**
1077 * Gets the <code>AccessibleValue</code> associated with this object. In the
1078 * implementation of the Java Accessibility API for this class,
1079 * returns this object, which is responsible for implementing the
1080 * <code>AccessibleValue</code> interface on behalf of itself.
1081 *
1082 * @return this object
1083 */
1084 public AccessibleValue getAccessibleValue() {
1085 return this;
1086 }
1087
1088 /**
1089 * Gets the accessible value of this object.
1090 *
1091 * @return the current value of this object
1092 */
1093 public Number getCurrentAccessibleValue() {
1094 return Integer.valueOf(getValue());
1095 }
1096
1097 /**
1098 * Sets the value of this object as a <code>Number</code>.
1099 *
1100 * @return <code>true</code> if the value was set
1101 */
1102 public boolean setCurrentAccessibleValue(Number n) {
1103 // TIGER- 4422535
1104 if (n == null) {
1105 return false;
1106 }
1107 setValue(n.intValue());
1108 return true;
1109 }
1110
1111 /**
1112 * Gets the minimum accessible value of this object.
1113 *
1114 * @return the minimum value of this object
1115 */
1116 public Number getMinimumAccessibleValue() {
1117 return Integer.valueOf(getMinimum());
1118 }
1119
1120 /**
|
49 * starts out empty and gradually becomes filled in as the task progresses.
50 * In addition, the progress bar can display a textual representation of this
51 * percentage.
52 * <p>
53 * {@code JProgressBar} uses a {@code BoundedRangeModel} as its data model,
54 * with the {@code value} property representing the "current" state of the task,
55 * and the {@code minimum} and {@code maximum} properties representing the
56 * beginning and end points, respectively.
57 * <p>
58 * To indicate that a task of unknown length is executing,
59 * you can put a progress bar into indeterminate mode.
60 * While the bar is in indeterminate mode,
61 * it animates constantly to show that work is occurring.
62 * As soon as you can determine the task's length and amount of progress,
63 * you should update the progress bar's value
64 * and switch it back to determinate mode.
65 *
66 * <p>
67 *
68 * Here is an example of creating a progress bar,
69 * where {@code task} is an object (representing some piece of work)
70 * which returns information about the progress of the task:
71 *
72 *<pre>
73 *progressBar = new JProgressBar(0, task.getLengthOfTask());
74 *progressBar.setValue(0);
75 *progressBar.setStringPainted(true);
76 *</pre>
77 *
78 * Here is an example of querying the current state of the task, and using
79 * the returned value to update the progress bar:
80 *
81 *<pre>
82 *progressBar.setValue(task.getCurrent());
83 *</pre>
84 *
85 * Here is an example of putting a progress bar into
86 * indeterminate mode,
87 * and then switching back to determinate mode
88 * once the length of the task is known:
89 *
98 *</pre>
99 *
100 * <p>
101 *
102 * For complete examples and further documentation see
103 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/progress.html" target="_top">How to Monitor Progress</a>,
104 * a section in <em>The Java Tutorial.</em>
105 *
106 * <p>
107 * <strong>Warning:</strong> Swing is not thread safe. For more
108 * information see <a
109 * href="package-summary.html#threading">Swing's Threading
110 * Policy</a>.
111 * <p>
112 * <strong>Warning:</strong>
113 * Serialized objects of this class will not be compatible with
114 * future Swing releases. The current serialization support is
115 * appropriate for short term storage or RMI between applications running
116 * the same version of Swing. As of 1.4, support for long term storage
117 * of all JavaBeans™
118 * has been added to the {@code java.beans} package.
119 * Please see {@link java.beans.XMLEncoder}.
120 *
121 * @see javax.swing.plaf.basic.BasicProgressBarUI
122 * @see javax.swing.BoundedRangeModel
123 * @see javax.swing.SwingWorker
124 *
125 * @beaninfo
126 * attribute: isContainer false
127 * description: A component that displays an integer value.
128 *
129 * @author Michael C. Albers
130 * @author Kathy Walrath
131 * @since 1.2
132 */
133 @SuppressWarnings("serial") // Same-version serialization only
134 public class JProgressBar extends JComponent implements SwingConstants, Accessible
135 {
136 /**
137 * @see #getUIClassID
138 */
139 private static final String uiClassID = "ProgressBarUI";
140
141 /**
142 * Whether the progress bar is horizontal or vertical.
143 * The default is {@code HORIZONTAL}.
144 *
145 * @see #setOrientation
146 */
147 protected int orientation;
148
149 /**
150 * Whether to display a border around the progress bar.
151 * The default is {@code true}.
152 *
153 * @see #setBorderPainted
154 */
155 protected boolean paintBorder;
156
157 /**
158 * The object that holds the data for the progress bar.
159 *
160 * @see #setModel
161 */
162 protected BoundedRangeModel model;
163
164 /**
165 * An optional string that can be displayed on the progress bar.
166 * The default is {@code null}. Setting this to a non-{@code null}
167 * value does not imply that the string will be displayed.
168 * To display the string, {@code paintString} must be {@code true}.
169 *
170 * @see #setString
171 * @see #setStringPainted
172 */
173 protected String progressString;
174
175 /**
176 * Whether to display a string of text on the progress bar.
177 * The default is {@code false}.
178 * Setting this to {@code true} causes a textual
179 * display of the progress to be rendered on the progress bar. If
180 * the {@code progressString} is {@code null},
181 * the percentage of completion is displayed on the progress bar.
182 * Otherwise, the {@code progressString} is
183 * rendered on the progress bar.
184 *
185 * @see #setStringPainted
186 * @see #setString
187 */
188 protected boolean paintString;
189
190 /**
191 * The default minimum for a progress bar is 0.
192 */
193 private static final int defaultMinimum = 0;
194 /**
195 * The default maximum for a progress bar is 100.
196 */
197 private static final int defaultMaximum = 100;
198 /**
199 * The default orientation for a progress bar is {@code HORIZONTAL}.
200 */
201 private static final int defaultOrientation = HORIZONTAL;
202
203 /**
204 * Only one {@code ChangeEvent} is needed per instance since the
205 * event's only interesting property is the immutable source, which
206 * is the progress bar.
207 * The event is lazily created the first time that an
208 * event notification is fired.
209 *
210 * @see #fireStateChanged
211 */
212 protected transient ChangeEvent changeEvent = null;
213
214 /**
215 * Listens for change events sent by the progress bar's model,
216 * redispatching them
217 * to change-event listeners registered upon
218 * this progress bar.
219 *
220 * @see #createChangeListener
221 */
222 protected ChangeListener changeListener = null;
223
224 /**
225 * Format used when displaying percent complete.
226 */
227 private transient Format format;
228
229 /**
230 * Whether the progress bar is indeterminate ({@code true}) or
231 * normal ({@code false}); the default is {@code false}.
232 *
233 * @see #setIndeterminate
234 * @since 1.4
235 */
236 private boolean indeterminate;
237
238
239 /**
240 * Creates a horizontal progress bar
241 * that displays a border but no progress string.
242 * The initial and minimum values are 0,
243 * and the maximum is 100.
244 *
245 * @see #setOrientation
246 * @see #setBorderPainted
247 * @see #setStringPainted
248 * @see #setString
249 * @see #setIndeterminate
250 */
251 public JProgressBar()
266 * @throws IllegalArgumentException if {@code orient} is an illegal value
267 *
268 * @see #setOrientation
269 * @see #setBorderPainted
270 * @see #setStringPainted
271 * @see #setString
272 * @see #setIndeterminate
273 */
274 public JProgressBar(int orient)
275 {
276 this(orient, defaultMinimum, defaultMaximum);
277 }
278
279
280 /**
281 * Creates a horizontal progress bar
282 * with the specified minimum and maximum.
283 * Sets the initial value of the progress bar to the specified minimum.
284 * By default, a border is painted but a progress string is not.
285 * <p>
286 * The {@code BoundedRangeModel} that holds the progress bar's data
287 * handles any issues that may arise from improperly setting the
288 * minimum, initial, and maximum values on the progress bar.
289 * See the {@code BoundedRangeModel} documentation for details.
290 *
291 * @param min the minimum value of the progress bar
292 * @param max the maximum value of the progress bar
293 *
294 * @see BoundedRangeModel
295 * @see #setOrientation
296 * @see #setBorderPainted
297 * @see #setStringPainted
298 * @see #setString
299 * @see #setIndeterminate
300 */
301 public JProgressBar(int min, int max)
302 {
303 this(defaultOrientation, min, max);
304 }
305
306
307 /**
308 * Creates a progress bar using the specified orientation,
309 * minimum, and maximum.
310 * By default, a border is painted but a progress string is not.
311 * Sets the initial value of the progress bar to the specified minimum.
312 * <p>
313 * The {@code BoundedRangeModel} that holds the progress bar's data
314 * handles any issues that may arise from improperly setting the
315 * minimum, initial, and maximum values on the progress bar.
316 * See the {@code BoundedRangeModel} documentation for details.
317 *
318 * @param orient the desired orientation of the progress bar
319 * @param min the minimum value of the progress bar
320 * @param max the maximum value of the progress bar
321 * @throws IllegalArgumentException if {@code orient} is an illegal value
322 *
323 * @see BoundedRangeModel
324 * @see #setOrientation
325 * @see #setBorderPainted
326 * @see #setStringPainted
327 * @see #setString
328 * @see #setIndeterminate
329 */
330 public JProgressBar(int orient, int min, int max)
331 {
332 // Creating the model this way is a bit simplistic, but
333 // I believe that it is the most common usage of this
359 */
360 public JProgressBar(BoundedRangeModel newModel)
361 {
362 setModel(newModel);
363 updateUI();
364
365 setOrientation(defaultOrientation); // see setOrientation()
366 setBorderPainted(true); // see setBorderPainted()
367 setStringPainted(false); // see setStringPainted
368 setString(null); // see getString
369 setIndeterminate(false); // see setIndeterminate
370 }
371
372
373 /**
374 * Returns {@code SwingConstants.VERTICAL} or
375 * {@code SwingConstants.HORIZONTAL}, depending on the orientation
376 * of the progress bar. The default orientation is
377 * {@code SwingConstants.HORIZONTAL}.
378 *
379 * @return {@code HORIZONTAL} or {@code VERTICAL}
380 * @see #setOrientation
381 */
382 public int getOrientation() {
383 return orientation;
384 }
385
386
387 /**
388 * Sets the progress bar's orientation to {@code newOrientation},
389 * which must be {@code SwingConstants.VERTICAL} or
390 * {@code SwingConstants.HORIZONTAL}. The default orientation
391 * is {@code SwingConstants.HORIZONTAL}.
392 *
393 * @param newOrientation {@code HORIZONTAL} or {@code VERTICAL}
394 * @exception IllegalArgumentException if {@code newOrientation}
395 * is an illegal value
396 * @see #getOrientation
397 *
398 * @beaninfo
399 * preferred: true
400 * bound: true
401 * attribute: visualUpdate true
402 * description: Set the progress bar's orientation.
403 */
404 public void setOrientation(int newOrientation) {
405 if (orientation != newOrientation) {
406 switch (newOrientation) {
407 case VERTICAL:
408 case HORIZONTAL:
409 int oldOrientation = orientation;
410 orientation = newOrientation;
411 firePropertyChange("orientation", oldOrientation, newOrientation);
412 if (accessibleContext != null) {
413 accessibleContext.firePropertyChange(
414 AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
415 ((oldOrientation == VERTICAL)
416 ? AccessibleState.VERTICAL
417 : AccessibleState.HORIZONTAL),
418 ((orientation == VERTICAL)
419 ? AccessibleState.VERTICAL
420 : AccessibleState.HORIZONTAL));
421 }
422 break;
423 default:
424 throw new IllegalArgumentException(newOrientation +
425 " is not a legal orientation");
426 }
427 revalidate();
428 }
429 }
430
431
432 /**
433 * Returns the value of the {@code stringPainted} property.
434 *
435 * @return the value of the {@code stringPainted} property
436 * @see #setStringPainted
437 * @see #setString
438 */
439 public boolean isStringPainted() {
440 return paintString;
441 }
442
443
444 /**
445 * Sets the value of the {@code stringPainted} property,
446 * which determines whether the progress bar
447 * should render a progress string.
448 * The default is {@code false}, meaning
449 * no string is painted.
450 * Some look and feels might not support progress strings
451 * or might support them only when the progress bar is in determinate mode.
452 *
453 * @param b {@code true} if the progress bar should render a string
454 * @see #isStringPainted
455 * @see #setString
456 * @beaninfo
457 * bound: true
458 * attribute: visualUpdate true
459 * description: Whether the progress bar should render a string.
460 */
461 public void setStringPainted(boolean b) {
462 //PENDING: specify that string not painted when in indeterminate mode?
463 // or just leave that to the L&F?
464 boolean oldValue = paintString;
465 paintString = b;
466 firePropertyChange("stringPainted", oldValue, paintString);
467 if (paintString != oldValue) {
468 revalidate();
469 repaint();
470 }
471 }
472
473
477 * the value returned from {@code getPercentComplete}. An example
478 * would be the "42%". You can change this by calling {@code setString}.
479 *
480 * @return the value of the progress string, or a simple percentage string
481 * if the progress string is {@code null}
482 * @see #setString
483 */
484 public String getString(){
485 if (progressString != null) {
486 return progressString;
487 } else {
488 if (format == null) {
489 format = NumberFormat.getPercentInstance();
490 }
491 return format.format(new Double(getPercentComplete()));
492 }
493 }
494
495 /**
496 * Sets the value of the progress string. By default,
497 * this string is {@code null}, implying the built-in behavior of
498 * using a simple percent string.
499 * If you have provided a custom progress string and want to revert to
500 * the built-in behavior, set the string back to {@code null}.
501 * <p>
502 * The progress string is painted only if
503 * the {@code isStringPainted} method returns {@code true}.
504 *
505 * @param s the value of the progress string
506 * @see #getString
507 * @see #setStringPainted
508 * @see #isStringPainted
509 * @beaninfo
510 * bound: true
511 * attribute: visualUpdate true
512 * description: Specifies the progress string to paint
513 */
514 public void setString(String s){
515 String oldValue = progressString;
516 progressString = s;
517 firePropertyChange("string", oldValue, progressString);
518 if (progressString == null || oldValue == null || !progressString.equals(oldValue)) {
519 repaint();
520 }
521 }
522
523 /**
524 * Returns the percent complete for the progress bar.
525 * Note that this number is between 0.0 and 1.0.
526 *
527 * @return the percent complete for this progress bar
528 */
529 public double getPercentComplete() {
530 long span = model.getMaximum() - model.getMinimum();
531 double currentValue = model.getValue();
532 double pc = (currentValue - model.getMinimum()) / span;
533 return pc;
534 }
535
536 /**
537 * Returns the {@code borderPainted} property.
538 *
539 * @return the value of the {@code borderPainted} property
540 * @see #setBorderPainted
541 * @beaninfo
542 * description: Does the progress bar paint its border
543 */
544 public boolean isBorderPainted() {
545 return paintBorder;
546 }
547
548 /**
549 * Sets the {@code borderPainted} property, which is
550 * {@code true} if the progress bar should paint its border.
551 * The default value for this property is {@code true}.
552 * Some look and feels might not implement painted borders;
553 * they will ignore this property.
554 *
555 * @param b {@code true} if the progress bar
556 * should paint its border;
557 * otherwise, {@code false}
558 * @see #isBorderPainted
559 * @beaninfo
560 * bound: true
561 * attribute: visualUpdate true
562 * description: Whether the progress bar should paint its border.
563 */
564 public void setBorderPainted(boolean b) {
565 boolean oldValue = paintBorder;
566 paintBorder = b;
567 firePropertyChange("borderPainted", oldValue, paintBorder);
568 if (paintBorder != oldValue) {
569 repaint();
570 }
571 }
572
573 /**
574 * Paints the progress bar's border if the {@code borderPainted}
575 * property is {@code true}.
576 *
577 * @param g the {@code Graphics} context within which to paint the border
578 * @see #paint
579 * @see #setBorder
580 * @see #isBorderPainted
581 * @see #setBorderPainted
582 */
583 protected void paintBorder(Graphics g) {
584 if (isBorderPainted()) {
585 super.paintBorder(g);
586 }
587 }
588
589
590 /**
591 * Returns the look-and-feel object that renders this component.
592 *
593 * @return the {@code ProgressBarUI} object that renders this component
594 */
595 public ProgressBarUI getUI() {
596 return (ProgressBarUI)ui;
597 }
598
599 /**
600 * Sets the look-and-feel object that renders this component.
601 *
602 * @param ui a {@code ProgressBarUI} object
603 * @see UIDefaults#getUI
604 * @beaninfo
605 * bound: true
606 * hidden: true
607 * attribute: visualUpdate true
608 * description: The UI object that implements the Component's LookAndFeel.
609 */
610 public void setUI(ProgressBarUI ui) {
611 super.setUI(ui);
612 }
613
614
615 /**
616 * Resets the UI property to a value from the current look and feel.
617 *
618 * @see JComponent#updateUI
619 */
620 public void updateUI() {
621 setUI((ProgressBarUI)UIManager.getUI(this));
622 }
629 * @see JComponent#getUIClassID
630 * @see UIDefaults#getUI
631 * @beaninfo
632 * expert: true
633 * description: A string that specifies the name of the look-and-feel class.
634 */
635 public String getUIClassID() {
636 return uiClassID;
637 }
638
639
640 /* We pass each Change event to the listeners with the
641 * the progress bar as the event source.
642 * <p>
643 * <strong>Warning:</strong>
644 * Serialized objects of this class will not be compatible with
645 * future Swing releases. The current serialization support is
646 * appropriate for short term storage or RMI between applications running
647 * the same version of Swing. As of 1.4, support for long term storage
648 * of all JavaBeans™
649 * has been added to the {@code java.beans} package.
650 * Please see {@link java.beans.XMLEncoder}.
651 */
652 @SuppressWarnings("serial") // Same-version serialization only
653 private class ModelListener implements ChangeListener, Serializable {
654 public void stateChanged(ChangeEvent e) {
655 fireStateChanged();
656 }
657 }
658
659 /**
660 * Subclasses that want to handle change events
661 * from the model differently
662 * can override this to return
663 * an instance of a custom {@code ChangeListener} implementation.
664 * The default {@code ChangeListener} simply calls the
665 * {@code fireStateChanged} method to forward {@code ChangeEvent}s
666 * to the {@code ChangeListener}s that have been added directly to the
667 * progress bar.
668 *
669 * @return the instance of a custom {@code ChangeListener} implementation.
670 * @see #changeListener
671 * @see #fireStateChanged
672 * @see javax.swing.event.ChangeListener
673 * @see javax.swing.BoundedRangeModel
674 */
675 protected ChangeListener createChangeListener() {
676 return new ModelListener();
677 }
678
679 /**
680 * Adds the specified {@code ChangeListener} to the progress bar.
681 *
682 * @param l the {@code ChangeListener} to add
683 */
684 public void addChangeListener(ChangeListener l) {
685 listenerList.add(ChangeListener.class, l);
686 }
687
688 /**
689 * Removes a {@code ChangeListener} from the progress bar.
690 *
691 * @param l the {@code ChangeListener} to remove
692 */
693 public void removeChangeListener(ChangeListener l) {
694 listenerList.remove(ChangeListener.class, l);
695 }
696
697 /**
698 * Returns an array of all the {@code ChangeListener}s added
699 * to this progress bar with {@code addChangeListener}.
700 *
701 * @return all of the {@code ChangeListener}s added or an empty
702 * array if no listeners have been added
703 * @since 1.4
704 */
705 public ChangeListener[] getChangeListeners() {
706 return listenerList.getListeners(ChangeListener.class);
707 }
708
709 /**
710 * Send a {@code ChangeEvent}, whose source is this {@code JProgressBar}, to
711 * all {@code ChangeListener}s that have registered interest in
712 * {@code ChangeEvent}s.
713 * This method is called each time a {@code ChangeEvent} is received from
714 * the model.
715 * <p>
716 *
717 * The event instance is created if necessary, and stored in
718 * {@code changeEvent}.
719 *
720 * @see #addChangeListener
721 * @see EventListenerList
722 */
723 protected void fireStateChanged() {
724 // Guaranteed to return a non-null array
725 Object[] listeners = listenerList.getListenerList();
726 // Process the listeners last to first, notifying
727 // those that are interested in this event
728 for (int i = listeners.length-2; i>=0; i-=2) {
729 if (listeners[i]==ChangeListener.class) {
730 // Lazily create the event:
731 if (changeEvent == null)
732 changeEvent = new ChangeEvent(this);
733 ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
734 }
735 }
736 }
737
738 /**
739 * Returns the data model used by this progress bar.
740 *
741 * @return the {@code BoundedRangeModel} currently in use
742 * @see #setModel
743 * @see BoundedRangeModel
744 */
745 public BoundedRangeModel getModel() {
746 return model;
747 }
748
749 /**
750 * Sets the data model used by the {@code JProgressBar}.
751 * Note that the {@code BoundedRangeModel}'s {@code extent} is not used,
752 * and is set to {@code 0}.
753 *
754 * @param newModel the {@code BoundedRangeModel} to use
755 *
756 * @beaninfo
757 * expert: true
758 * description: The data model used by the JProgressBar.
759 */
760 public void setModel(BoundedRangeModel newModel) {
761 // PENDING(???) setting the same model to multiple bars is broken; listeners
762 BoundedRangeModel oldModel = getModel();
763
764 if (newModel != oldModel) {
765 if (oldModel != null) {
766 oldModel.removeChangeListener(changeListener);
767 changeListener = null;
768 }
769
770 model = newModel;
771
772 if (newModel != null) {
773 changeListener = createChangeListener();
774 newModel.addChangeListener(changeListener);
778 accessibleContext.firePropertyChange(
779 AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
780 (oldModel== null
781 ? null : Integer.valueOf(oldModel.getValue())),
782 (newModel== null
783 ? null : Integer.valueOf(newModel.getValue())));
784 }
785
786 if (model != null) {
787 model.setExtent(0);
788 }
789 repaint();
790 }
791 }
792
793
794 /* All of the model methods are implemented by delegation. */
795
796 /**
797 * Returns the progress bar's current {@code value}
798 * from the {@code BoundedRangeModel}.
799 * The value is always between the
800 * minimum and maximum values, inclusive.
801 *
802 * @return the current value of the progress bar
803 * @see #setValue
804 * @see BoundedRangeModel#getValue
805 */
806 public int getValue() { return getModel().getValue(); }
807
808 /**
809 * Returns the progress bar's {@code minimum} value
810 * from the {@code BoundedRangeModel}.
811 *
812 * @return the progress bar's minimum value
813 * @see #setMinimum
814 * @see BoundedRangeModel#getMinimum
815 */
816 public int getMinimum() { return getModel().getMinimum(); }
817
818 /**
819 * Returns the progress bar's {@code maximum} value
820 * from the {@code BoundedRangeModel}.
821 *
822 * @return the progress bar's maximum value
823 * @see #setMaximum
824 * @see BoundedRangeModel#getMaximum
825 */
826 public int getMaximum() { return getModel().getMaximum(); }
827
828 /**
829 * Sets the progress bar's current value to {@code n}. This method
830 * forwards the new value to the model.
831 * <p>
832 * The data model (an instance of {@code BoundedRangeModel})
833 * handles any mathematical
834 * issues arising from assigning faulty values. See the
835 * {@code BoundedRangeModel} documentation for details.
836 * <p>
837 * If the new value is different from the previous value,
838 * all change listeners are notified.
839 *
840 * @param n the new value
843 * @see BoundedRangeModel#setValue
844 * @beaninfo
845 * preferred: true
846 * description: The progress bar's current value.
847 */
848 public void setValue(int n) {
849 BoundedRangeModel brm = getModel();
850 int oldValue = brm.getValue();
851 brm.setValue(n);
852
853 if (accessibleContext != null) {
854 accessibleContext.firePropertyChange(
855 AccessibleContext.ACCESSIBLE_VALUE_PROPERTY,
856 Integer.valueOf(oldValue),
857 Integer.valueOf(brm.getValue()));
858 }
859 }
860
861 /**
862 * Sets the progress bar's minimum value
863 * (stored in the progress bar's data model) to {@code n}.
864 * <p>
865 * The data model (a {@code BoundedRangeModel} instance)
866 * handles any mathematical
867 * issues arising from assigning faulty values.
868 * See the {@code BoundedRangeModel} documentation for details.
869 * <p>
870 * If the minimum value is different from the previous minimum,
871 * all change listeners are notified.
872 *
873 * @param n the new minimum
874 * @see #getMinimum
875 * @see #addChangeListener
876 * @see BoundedRangeModel#setMinimum
877 * @beaninfo
878 * preferred: true
879 * description: The progress bar's minimum value.
880 */
881 public void setMinimum(int n) { getModel().setMinimum(n); }
882
883 /**
884 * Sets the progress bar's maximum value
885 * (stored in the progress bar's data model) to {@code n}.
886 * <p>
887 * The underlying {@code BoundedRangeModel} handles any mathematical
888 * issues arising from assigning faulty values.
889 * See the {@code BoundedRangeModel} documentation for details.
890 * <p>
891 * If the maximum value is different from the previous maximum,
892 * all change listeners are notified.
893 *
894 * @param n the new maximum
895 * @see #getMaximum
896 * @see #addChangeListener
897 * @see BoundedRangeModel#setMaximum
898 * @beaninfo
899 * preferred: true
900 * description: The progress bar's maximum value.
901 */
902 public void setMaximum(int n) { getModel().setMaximum(n); }
903
904 /**
905 * Sets the {@code indeterminate} property of the progress bar,
906 * which determines whether the progress bar is in determinate
907 * or indeterminate mode.
908 * An indeterminate progress bar continuously displays animation
909 * indicating that an operation of unknown length is occurring.
910 * By default, this property is {@code false}.
911 * Some look and feels might not support indeterminate progress bars;
912 * they will ignore this property.
913 *
914 * <p>
915 *
916 * See
917 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/progress.html" target="_top">How to Monitor Progress</a>
918 * for examples of using indeterminate progress bars.
919 *
920 * @param newValue {@code true} if the progress bar
921 * should change to indeterminate mode;
922 * {@code false} if it should revert to normal.
923 *
924 * @see #isIndeterminate
925 * @see javax.swing.plaf.basic.BasicProgressBarUI
926 *
927 * @since 1.4
928 *
929 * @beaninfo
930 * bound: true
931 * attribute: visualUpdate true
932 * description: Set whether the progress bar is indeterminate (true)
933 * or normal (false).
934 */
935 public void setIndeterminate(boolean newValue) {
936 boolean oldValue = indeterminate;
937 indeterminate = newValue;
938 firePropertyChange("indeterminate", oldValue, indeterminate);
939 }
940
941 /**
942 * Returns the value of the {@code indeterminate} property.
943 *
944 * @return the value of the {@code indeterminate} property
945 * @see #setIndeterminate
946 *
947 * @since 1.4
948 *
949 * @beaninfo
950 * description: Is the progress bar indeterminate (true)
951 * or normal (false)?
952 */
953 public boolean isIndeterminate() {
954 return indeterminate;
955 }
956
957
958 /**
959 * See readObject() and writeObject() in JComponent for more
960 * information about serialization in Swing.
961 */
962 private void writeObject(ObjectOutputStream s) throws IOException {
963 s.defaultWriteObject();
964 if (getUIClassID().equals(uiClassID)) {
965 byte count = JComponent.getWriteObjCounter(this);
966 JComponent.setWriteObjCounter(this, --count);
967 if (count == 0 && ui != null) {
968 ui.installUI(this);
969 }
970 }
971 }
972
973
974 /**
975 * Returns a string representation of this {@code JProgressBar}.
976 * This method is intended to be used only for debugging purposes. The
977 * content and format of the returned string may vary between
978 * implementations. The returned string may be empty but may not
979 * be {@code null}.
980 *
981 * @return a string representation of this {@code JProgressBar}
982 */
983 protected String paramString() {
984 String orientationString = (orientation == HORIZONTAL ?
985 "HORIZONTAL" : "VERTICAL");
986 String paintBorderString = (paintBorder ?
987 "true" : "false");
988 String progressStringString = (progressString != null ?
989 progressString : "");
990 String paintStringString = (paintString ?
991 "true" : "false");
992 String indeterminateString = (indeterminate ?
993 "true" : "false");
994
995 return super.paramString() +
996 ",orientation=" + orientationString +
997 ",paintBorder=" + paintBorderString +
998 ",paintString=" + paintStringString +
999 ",progressString=" + progressStringString +
1000 ",indeterminateString=" + indeterminateString;
1001 }
1002
1003 /////////////////
1004 // Accessibility support
1005 ////////////////
1006
1007 /**
1008 * Gets the {@code AccessibleContext} associated with this
1009 * {@code JProgressBar}. For progress bars, the
1010 * {@code AccessibleContext} takes the form of an
1011 * {@code AccessibleJProgressBar}.
1012 * A new {@code AccessibleJProgressBar} instance is created if necessary.
1013 *
1014 * @return an {@code AccessibleJProgressBar} that serves as the
1015 * {@code AccessibleContext} of this {@code JProgressBar}
1016 * @beaninfo
1017 * expert: true
1018 * description: The AccessibleContext associated with this ProgressBar.
1019 */
1020 public AccessibleContext getAccessibleContext() {
1021 if (accessibleContext == null) {
1022 accessibleContext = new AccessibleJProgressBar();
1023 }
1024 return accessibleContext;
1025 }
1026
1027 /**
1028 * This class implements accessibility support for the
1029 * {@code JProgressBar} class. It provides an implementation of the
1030 * Java Accessibility API appropriate to progress bar user-interface
1031 * elements.
1032 * <p>
1033 * <strong>Warning:</strong>
1034 * Serialized objects of this class will not be compatible with
1035 * future Swing releases. The current serialization support is
1036 * appropriate for short term storage or RMI between applications running
1037 * the same version of Swing. As of 1.4, support for long term storage
1038 * of all JavaBeans™
1039 * has been added to the {@code java.beans} package.
1040 * Please see {@link java.beans.XMLEncoder}.
1041 */
1042 @SuppressWarnings("serial") // Same-version serialization only
1043 protected class AccessibleJProgressBar extends AccessibleJComponent
1044 implements AccessibleValue {
1045
1046 /**
1047 * Gets the state set of this object.
1048 *
1049 * @return an instance of AccessibleState containing the current state
1050 * of the object
1051 * @see AccessibleState
1052 */
1053 public AccessibleStateSet getAccessibleStateSet() {
1054 AccessibleStateSet states = super.getAccessibleStateSet();
1055 if (getModel().getValueIsAdjusting()) {
1056 states.add(AccessibleState.BUSY);
1057 }
1058 if (getOrientation() == VERTICAL) {
1059 states.add(AccessibleState.VERTICAL);
1060 } else {
1061 states.add(AccessibleState.HORIZONTAL);
1062 }
1063 return states;
1064 }
1065
1066 /**
1067 * Gets the role of this object.
1068 *
1069 * @return an instance of AccessibleRole describing the role of the
1070 * object
1071 */
1072 public AccessibleRole getAccessibleRole() {
1073 return AccessibleRole.PROGRESS_BAR;
1074 }
1075
1076 /**
1077 * Gets the {@code AccessibleValue} associated with this object. In the
1078 * implementation of the Java Accessibility API for this class,
1079 * returns this object, which is responsible for implementing the
1080 * {@code AccessibleValue} interface on behalf of itself.
1081 *
1082 * @return this object
1083 */
1084 public AccessibleValue getAccessibleValue() {
1085 return this;
1086 }
1087
1088 /**
1089 * Gets the accessible value of this object.
1090 *
1091 * @return the current value of this object
1092 */
1093 public Number getCurrentAccessibleValue() {
1094 return Integer.valueOf(getValue());
1095 }
1096
1097 /**
1098 * Sets the value of this object as a {@code Number}.
1099 *
1100 * @return {@code true} if the value was set
1101 */
1102 public boolean setCurrentAccessibleValue(Number n) {
1103 // TIGER- 4422535
1104 if (n == null) {
1105 return false;
1106 }
1107 setValue(n.intValue());
1108 return true;
1109 }
1110
1111 /**
1112 * Gets the minimum accessible value of this object.
1113 *
1114 * @return the minimum value of this object
1115 */
1116 public Number getMinimumAccessibleValue() {
1117 return Integer.valueOf(getMinimum());
1118 }
1119
1120 /**
|