/* * $Id$ * * Copyright (c) 2008-2010 by Joel Uckelman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation. * * 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, copies are available * at http://www.opensource.org. */ package VASSAL.tools.swing; import java.awt.Dimension; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.event.EventListenerList; import net.miginfocom.swing.MigLayout; import VASSAL.i18n.Resources; /** * A cancellable progress dialog. * * @since 3.1.0 * @author Joel Uckelman */ public class ProgressDialog extends JDialog { private static final long serialVersionUID = 1L; protected final JLabel label; protected final JProgressBar progbar; protected final JButton cancel; protected final EventListenerList listeners = new EventListenerList(); /** * Creates a progress dialog. * * @param parent the parent frame * @param title the dialog title * @param text the text beneath the progress bar */ public ProgressDialog(Frame parent, String title, String text) { super(parent, title, true); // set up the components label = new JLabel(text); // Font f = label.getFont(); // label.setFont(f.deriveFont(f.getSize2D()*4f/3f)); // label.setFont(f.deriveFont(14f)); progbar = new JProgressBar(0, 100); progbar.setStringPainted(true); progbar.setValue(0); // AUGH! This is retarded that we can't set a default font size... // f = progbar.getFont(); // progbar.setFont(f.deriveFont(14f)); cancel = new JButton(Resources.getString(Resources.CANCEL)); // f = cancel.getFont(); // cancel.setFont(f.deriveFont(14f)); // forward clicks on the close decoration to cancellation listeners addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { fireCancelledEvent(new ActionEvent( ProgressDialog.this, ActionEvent.ACTION_PERFORMED, "cancel" )); } }); // forward clicks on the close button to the cancellation listeners cancel.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { fireCancelledEvent(e); } }); // create the layout final JPanel panel = new JPanel(new MigLayout( "insets dialog, fill", "", "unrelated:push[]related[]unrelated:push[]")); // NB: It's necessary to set the minimum width for the label, // otherwise if the label text is set to a string which is too long, // the label will overflow the container instead of showing ellipses. panel.add(progbar, "growx, wrap"); panel.add(label, "wmin 0, pad 0 0 2pt 0, wrap unrel:push"); panel.add(cancel, "tag cancel"); add(panel); // pack to find the minimum height pack(); // set minimum size setMinimumSize(new Dimension(300, getHeight())); // pack again to ensure that we respect the minimum size pack(); } protected void fireCancelledEvent(ActionEvent e) { final Object[] larr = listeners.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event. for (int i = larr.length-2; i >= 0; i -= 2) { if (larr[i] == ActionListener.class) { ((ActionListener) larr[i+1]).actionPerformed(e); } } } /** * Gets the text label shown beneath the progress bar. * * @return the text label */ public String getLabel() { return label.getText(); } /** * Sets the text label shown beneath the progress bar. * * @param text the text label */ public void setLabel(String text) { label.setText(text); } /** * Gets whether the progress bar is indeterminate. * * @return whether the progress bar is indeterminate */ public boolean isIndeterminate() { return progbar.isIndeterminate(); } /** * Sets whether the progress bar should be indeterminate. * * @param indet whether the progress bar should beindeterminate */ public void setIndeterminate(boolean indet) { progbar.setIndeterminate(indet); } /** * Gets the percentage displayed by the progress bar. * * @return the percentage completed */ public int getProgress() { return progbar.getValue(); } /** * Sets the percentage for the progress bar. * * @param percent the percentage completed */ public void setProgress(int percent) { progbar.setValue(percent); } /** * Gets whether the progress bar contains a progress string. * * @return whether the progress bar contains a progress string */ public boolean isStringPainted() { return progbar.isStringPainted(); } /** * Sets whether the progress bar should contain a progress string. * * @param painted whether the progress bar should contain a progress string */ public void setStringPainted(boolean painted) { progbar.setStringPainted(painted); } /** * Adds a cancellation listener. * * @param l the action listener */ public void addActionListener(ActionListener l) { listeners.add(ActionListener.class, l); } /** * Removes cancellation listener. * * @param l the action listener */ public void removeActionListener(ActionListener l) { listeners.remove(ActionListener.class, l); } /** * Gets the list of cancellation listeners. * * @return the action listeners */ public ActionListener[] getActionListeners() { return listeners.getListeners(ActionListener.class); } /** * Creates a progress dialog on the EDT. * * This is a convenience method to be used when a non-EDT thread needs to * create a progress dialog in order to attach listeners to it. * * @param parent the parent frame * @param title the dialog title * @param text the text beneath the progress bar */ public static ProgressDialog createOnEDT(final Frame parent, final String title, final String text) { final Future<ProgressDialog> f = EDT.submit(new Callable<ProgressDialog>() { public ProgressDialog call() { return new ProgressDialog(parent, title, text); } }); try { return f.get(); } catch (CancellationException e) { // this should never happen throw new IllegalStateException(e); } catch (InterruptedException e) { // this should never happen throw new IllegalStateException(e); } catch (ExecutionException e) { throw new RuntimeException(e); } } }