/* class JProgressBar * * Copyright (C) 2001, 2002, 2003 R M Pitman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package charvax.swing; import charva.awt.Dimension; import charva.awt.Insets; import charva.awt.Point; import charva.awt.Toolkit; import charva.awt.event.KeyEvent; /** * A component that displays an integer value within a bounded interval. * A progress bar is typically used to indicate the progress of some task * by displaying a percentage of completion and possibly a textual display * of this percentage. */ public class JProgressBar extends JComponent { /** Creates a horizontal progress bar that displays a border * but no progress string. */ public JProgressBar() { } /** Creates a progress bar with the specified minimum and * maximum values. */ public JProgressBar(int min_, int max_) { _minimum = min_; _maximum = max_; } /** Set the progress bar's minimum value. */ public void setMinimum(int min_) { _minimum = min_; if (_maximum <= _minimum) _maximum = _minimum + 1; if (_value < _minimum) _value = _minimum; } /** Set the progress bar's value. */ public void setValue(int value_) { if (value_ < _minimum) _value = _minimum; else _value = value_; /* If this component is already displayed, generate a PaintEvent * and post it onto the queue. */ repaint(); } /** Set the progress bar's maximum value. */ public void setMaximum(int max_) { _maximum = max_; if (_minimum > _maximum) _minimum = _maximum - 1; if (_value > _maximum) _value = _maximum; } /** * Set the size of the component on the screen. */ public void setSize(Dimension size_) { _width = size_.width; if (_width < 3) { throw new IllegalArgumentException( "length of progress bar must be at least 3"); } } /** Get the screen size of the progress bar. */ public Dimension getSize() { return new Dimension(this.getWidth(), this.getHeight()); } public int getWidth() { Insets insets = super.getInsets(); return _width + insets.left + insets.right; } public int getHeight() { Insets insets = super.getInsets(); return 1 + insets.top + insets.bottom; } public void draw(Toolkit toolkit) { // Draw the border if it exists super.draw(toolkit); /* Get the absolute origin of this component. */ Point origin = getLocationOnScreen(); Insets insets = super.getInsets(); origin.translate(insets.left, insets.top); int colorpair = getCursesColor(); int offset = ((_value - _minimum) * _width) / _maximum; if ( ! isIndeterminate()) { for (int i=0; i< offset; i++) { toolkit.setCursor(origin.addOffset(i, 0)); toolkit.addChar(' ', Toolkit.A_REVERSE, colorpair); } for (int k=offset; k<_width; k++) { toolkit.setCursor(origin.addOffset(k,0)); toolkit.addChar(Toolkit.ACS_CKBOARD, 0, colorpair); } } else { for (int i=0; i< _width; i++) { toolkit.setCursor(origin.addOffset(i, 0)); toolkit.addChar(' ', 0, colorpair); } toolkit.setCursor(origin.addOffset(offset, 0)); toolkit.addChar(' ', Toolkit.A_REVERSE, colorpair); } // Display the progress string if required if (isStringPainted()) { offset = (getSize().width - _string.length()) / 2; toolkit.setCursor(origin.addOffset(offset, 0)); toolkit.addString(_string, 0, colorpair); } } /** This component will not receive focus when Tab or Shift-Tab is pressed. */ public boolean isFocusTraversable() { return false; } /** The JProgressBar class ignores key events. A JProgressBar should never * have input focus anyway. */ public void processKeyEvent(KeyEvent ke_) { } /** * The JProgressBar component never gets the keyboard input focus. */ public void requestFocus() {} public void debug(int level_) { for (int i=0; i<level_; i++) System.err.print(" "); System.err.println("JProgressBar origin=" + _origin + " size=" + getSize() + " value=" + _value + " minimum=" + _minimum + " maximum=" + _maximum); } public Dimension minimumSize() { return getSize(); } public int getMinimum() { return _minimum; } public int getValue() { return _value; } public int getMaximum() { return _maximum; } /** Returns the value of the _stringPainted property */ public boolean isStringPainted() { return _stringPainted; } /** Set the value of the _stringPainted property */ public void setStringPainted(boolean stringPainted_) { _stringPainted = stringPainted_; } /** Sets the value of the progress string */ public void setString(String string_) { _string = string_; repaint(); } public void setIndeterminate(boolean newval) { if (newval == _indeterminate) return; // no change in state. _indeterminate = newval; if ( newval) { setMinimum(0); setMaximum(100); _indeterminateThread = new IndeterminateThread(); _indeterminateThread.start(); } else { if (_indeterminateThread != null && _indeterminateThread.isAlive()) { _indeterminateThread.interrupt(); } } } public boolean isIndeterminate() { return _indeterminate; } /** Returns the value of the progress string */ public String getString() { return _string; } public void finalize() { if (_indeterminateThread != null && _indeterminateThread.isAlive()) { _indeterminateThread.interrupt(); } } /** A nonstatic inner class that updates the progress bar * once per second when the progress bar is in "indeterminate" mode. */ private class IndeterminateThread extends Thread { /** Constructor */ private IndeterminateThread() { } /** * Twice per second, wake up and update the progress bar. Note that * since this thread is not the event-dispatching thread, we cannot * manipulate the screen components directly; instead, we must * call the static method "invokeLater()" of the EventQueue class, * which will cause the event-dispatching thread to update the progress * bar. * See "Core Java, Volume II" by Horstmann and Cornell, chapter 1; * Also see * http://java.sun.com/docs/books/tutorial/uiswing/overview/threads.html */ public void run() { try { while (true) { this.adjust(); Thread.sleep(500L); SwingUtilities.invokeLater(new Runnable() { public void run() { JProgressBar.this.setValue(_percent); } }); } } catch (InterruptedException e) { return; } } /** Adjust the percent-completed so that the indicator moves right * and left continuously. */ private void adjust() { if (_right) { if (_percent < 96) _percent += 4; else { _right = false; } } else { if (_percent > 0) _percent -= 4; else { _right = true; } } } boolean _right = true; int _percent = 0; } //******************************************************************** // INSTANCE VARIABLES protected int _minimum = 0; protected int _value = 0; protected int _maximum = 100; protected boolean _stringPainted = false; protected String _string = ""; /** The length of this component on the screen. */ protected int _width = 50; // default size protected boolean _indeterminate; protected Thread _indeterminateThread; }