/** *######################################################################### * * A component of the Gatherer application, part of the Greenstone digital * library suite from the New Zealand Digital Library Project at the * University of Waikato, New Zealand. * * Author: John Thompson, Greenstone Digital Library, University of Waikato * * Copyright (C) New Zealand Digital Library Project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *######################################################################## */ package org.greenstone.gatherer.gui; import javax.swing.*; import org.greenstone.gatherer.Dictionary; /** A progress bar that doesn't pack a sad when you feed it longs (such as the sizes of files) which get mangled into negative numbers. I know how it feels, as I often have negative progress. Also tries to be efficent when updating the JProgressBar, so only updates when the value actually changes, which become necessary when you move a large number of files with millions of bytes (where upon shifting a file of a thousand bytes would be pretty insignificant, maybe not even a percent, but would fire several progress updates). * @author John Thompson, Greenstone Digital Library, University of Waikato */ public class GProgressBar extends JProgressBar { private long cur_value = 0L; private long max_value = 0L; /** The previous percentage value. */ private int previous = -1; public GProgressBar() { super(0, 100); this.setComponentOrientation(Dictionary.getOrientation()); } public void addMaximum(long amount) { if (amount > 0) { max_value = max_value + amount; update(); } } public void addValue(long amount) { if (amount > 0) { cur_value = cur_value + amount; update(); } } public void clear() { previous = -1; update(); } public void reset() { cur_value = 0L; max_value = 0L; previous = -1; update(); } public void setIndeterminate(boolean indeterminate) { SwingUtilities.invokeLater(new SafeSetIndeterminateTask(indeterminate)); } public void setString(String label) { SwingUtilities.invokeLater(new SafeSetStringTask(label)); } public void setMaximum(int value) { max_value = value; update(); } public void setValue(int value) { cur_value = value; update(); } /** Only bother updating the progress bar if the percentage has changed. */ private void update() { int percentage = -1; if (cur_value == 0L || max_value == 0L) { percentage = 0; } else { long per_value = (cur_value * 100) / max_value; percentage = (int) per_value; if (percentage > 100) { percentage = 100; } } if (percentage != previous) { previous = percentage; setString(percentage + "%"); SwingUtilities.invokeLater(new SafeSetValueTask(percentage)); } } /** Internal class to call JProgressBar.setIndeterminate safely. */ private class SafeSetIndeterminateTask implements Runnable { private boolean indeterminate; public SafeSetIndeterminateTask(boolean indeterminate) { this.indeterminate = indeterminate; } public void run() { unsafeSetIndeterminate(indeterminate); } } /** This method is unsafe, -unless- it is called from the Event Queue (eg. from SafeSetIndeterminateTask). */ private void unsafeSetIndeterminate(boolean indeterminate) { super.setIndeterminate(indeterminate); } /** Internal class to call JProgressBar.setString safely. */ private class SafeSetStringTask implements Runnable { private String label; public SafeSetStringTask(String label) { this.label = label; } public void run() { unsafeSetString(label); } } /** This method is unsafe, -unless- it is called from the Event Queue (eg. from SafeSetStringTask). */ private void unsafeSetString(String label) { super.setString(label); } /** Internal class to call JProgressBar.setValue safely. */ private class SafeSetValueTask implements Runnable { private int value; public SafeSetValueTask(int value) { this.value = value; } public void run() { unsafeSetValue(value); } } /** This method is unsafe, -unless- it is called from the Event Queue (eg. from SafeSetValueTask). */ private void unsafeSetValue(int value) { super.setValue(value); } }