/* * Copyright (c) 2008, SQL Power Group Inc. * * This file is part of SQL Power Library. * * SQL Power Library 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 3 of the License, or * (at your option) any later version. * * SQL Power 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package ca.sqlpower.swingui; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JLabel; import javax.swing.JProgressBar; import javax.swing.ProgressMonitor; import javax.swing.Timer; import org.apache.log4j.Logger; import ca.sqlpower.util.Monitorable; /** * This class updates a JProgressBar based on the progress of a given Monitorable * object. It places itself as the ActionListener within a Timer object, and uses * it to periodically update the progress bar. The ProgressWatcher also allows you to * set whether or not */ public class ProgressWatcher implements ActionListener { private JProgressBar bar = null; private boolean hideProgressBarWhenFinished = false; private ProgressMonitor pm = null; private Monitorable monitorable = null; private JLabel label = null; private boolean hideLabelWhenFinished = false; private Timer timer; private static final Logger logger = Logger.getLogger(ProgressWatcher.class); /** * This runnable can be set to some operation that is to be performed when * the progress bar has completed successfully. */ private Runnable finishedAction; /** * Create a ProgressWatcher with the given progress bar and Monitorable. * It will leave the progress bar label blank. The label and progress bar will * remain visible after the monitorable is finished by default. * <p> * The progress bar will not start up at this point. You should either use the static method * {@link #watchProgress(JProgressBar, Monitorable)} or call the {@link #start()} * method after calling the constructor to start the progress bar monitor. * * @param bar The JProgressBar that is tracking the progress of the monitorable * @param monitorable The monitorable object that the ProgressWatcher monitors */ public ProgressWatcher(JProgressBar bar, Monitorable monitorable) { this (bar,monitorable,null); } /** * Create a ProgressWatcher with the given progress bar and Monitorable, and * set the progress bar label to the given JLabel. The label and progress * bar will remain visible after the monitorable is finished by default. * <p> * The progress bar will not start up at this point. You should either use * the static method * {@link #watchProgress(JProgressBar, Monitorable, JLabel))} instead of * invoking this constructor directly, or call the {@link #start()} method * after calling the constructor to start the progress bar monitor. * * @param bar * The JProgressBar that is tracking the progress of the * monitorable * @param monitorable * The monitorable object that the ProgressWatcher monitors * @param label * The label you want to display on the progress bar */ public ProgressWatcher(JProgressBar bar, Monitorable monitorable, JLabel label) { this.bar = bar; this.monitorable = monitorable; this.label = label; } /** * Create a ProgressWatcher with the given ProgressMonitor and Monitorable. * <p> * The progress monitor will not start receiving updates until you call call * the {@link #start()}. As an alternative to this constructor, you can use * the static method {@link #watchProgress(ProgressMonitor, Monitorable)} * which creates a ProgressWatcher instance and starts it. * * @param pm * The Swing ProgressMonitor that should track the progress of * the monitorable * @param monitorable * The monitorable object that the ProgressWatcher monitors */ public ProgressWatcher(ProgressMonitor pm, Monitorable monitorable) { this.pm = pm; this.monitorable = monitorable; } /** * Start the progress bar watcher to update the progress bar based * on the progress of the given monitorable object. The progress bar * is set to update every 50 ms. */ public void start() { timer = new Timer(50, this); timer.start(); } /** * Creates a ProgressWatcher with the given JProgressBar and Monitorable using the * {@link #ProgressWatcher(JProgressBar, Monitorable)} constructor and starts it immediately. * <p> * Also, the progress bar and label will remain visible once the monitorable is finished. * If you prefer to have the progress bar and label to be hidden after the monitorable is finished, * then use the {@link #ProgressWatcher(JProgressBar, Monitorable)} constructor, followed by * {@link #setHideLabelWhenFinished(boolean)} and/or {@link #setHideProgressBarWhenFinished(boolean)} * method calls to hide the label and/or progress bar after the Monitorable is finished, and then * call {@link #start()} to start the ProgressWatcher. * * @param bar The JProgressBar that will be used to track the progress of the Monitorable object * @param monitorable The Monitorable object that will be monitored to update the progress bar */ public static void watchProgress(JProgressBar bar, Monitorable monitorable) { ProgressWatcher watcher = new ProgressWatcher(bar, monitorable); watcher.start(); } /** * Creates a ProgressWatcher with the given JProgressBar, Monitorable, and JLabel using the * {@link #ProgressWatcher(JProgressBar, Monitorable, JLabel)} constructor and starts it immediately. * * Also, the progress bar and label will remain visible once the monitorable is finished. * If you prefer to have the progress bar and label to be hidden after the monitorable is finished, * then use the {@link #ProgressWatcher(JProgressBar, Monitorable, JLabel)} constructor, followed by * {@link #setHideLabelWhenFinished(boolean)} and/or {@link #setHideProgressBarWhenFinished(boolean)} * method calls to hide the label and/or progress bar after the Monitorable is finished, and then * call {@link #start()} to start the ProgressWatcher. * * @param bar The JProgressBar that will be used to track the progress of the Monitorable object * @param monitorable The Monitorable object that will be monitored to update the progress bar * @param label The label that will be displayed next to the progress bar */ public static void watchProgress(JProgressBar bar, Monitorable monitorable, JLabel label) { ProgressWatcher watcher = new ProgressWatcher(bar, monitorable, label); watcher.start(); } /** * Creates a ProgressWatcher with the given ProgressMonitor and Monitorable * using the {@link #ProgressWatcher(ProgressMonitor, Monitorable)} * constructor and starts it immediately. * * @param pm * The Swing ProgressMonitor that should track the progress of * the given Monitorable object. * @param monitorable * The Monitorable object that will be monitored to update the * progress monitor. */ public static void watchProgress(ProgressMonitor pm, Monitorable monitorable) { ProgressWatcher watcher = new ProgressWatcher(pm, monitorable); watcher.start(); } /** * The method that is run when the timer thread notifies the ProgressWatcher. It * updates the progress bar based on the status of the monitorable object. When the monitorable * is finished, it will hide the progress bar if {@link #hideProgressBarWhenFinished} is set to * true and it will hide the label if {@link #hideLabelWhenFinished} is set to true. */ public void actionPerformed(ActionEvent evt) { // update the progress bar logger.debug("updating progress bar..."); //$NON-NLS-1$ Integer jobSize = monitorable.getJobSize(); if (bar != null) { if (monitorable.hasStarted()) { if (jobSize == null) { bar.setIndeterminate(true); } else { bar.setIndeterminate(false); bar.setMaximum(jobSize.intValue()); bar.setValue(monitorable.getProgress()); } bar.setVisible(true); } if (monitorable.isFinished() && hideProgressBarWhenFinished){ bar.setVisible(false); } } if (label != null) { label.setVisible(true); label.setText(monitorable.getMessage()); } if (pm != null) { // using ProgressMonitor if (monitorable.hasStarted()) { monitorable.setCancelled(pm.isCanceled()); if (jobSize != null) { pm.setMaximum(jobSize.intValue()); } pm.setProgress(monitorable.getProgress()); logger.debug("progress: " + monitorable.getProgress()); //$NON-NLS-1$ pm.setNote(monitorable.getMessage()); } } logger.debug("monitorable.isFinished():" + monitorable.isFinished()); //$NON-NLS-1$ if (monitorable.isFinished()) { if (label != null && hideLabelWhenFinished) { label.setText(""); //$NON-NLS-1$ } if (bar != null) { bar.setValue(0); bar.setIndeterminate(false); } if (pm != null) { logger.debug("pm done, max was: " + pm.getMaximum()); //$NON-NLS-1$ pm.close(); } logger.debug("trying to stop timer thread..."); //$NON-NLS-1$ timer.stop(); logger.debug("did the timer thread stop???"); //$NON-NLS-1$ if (finishedAction != null) { finishedAction.run(); } } } /** * Returns true if the progress bar will be hidden once the monitorable is finished. * Otherwise returns false, in that case the progress bar will remain and the value set to 0 * when finished. The default value is false. */ public boolean isHideProgressBarWhenFinished() { return hideProgressBarWhenFinished; } /** * Set if the progress bar will be hidden once the monitorable is finished. * The default value is false. */ public void setHideProgressBarWhenFinished(boolean hideProgressBarWhenFinished) { this.hideProgressBarWhenFinished = hideProgressBarWhenFinished; } /** * Returns true if the label will be hidden once the monitorable is finished. * Otherwise returns false, in that case the label will remain when finished. * The default value is false. */ public boolean isHideLabelWhenFinished() { return hideLabelWhenFinished; } /** * Set if the label will be hidden once the monitorable is finished. * The default value is false. */ public void setHideLabelWhenFinished(boolean hideLabelWhenFinished) { this.hideLabelWhenFinished = hideLabelWhenFinished; } public void setFinishedAction(Runnable finishedAction) { this.finishedAction = finishedAction; } }