package edu.mbl.jif.job;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import foxtrot.Job;
import foxtrot.Worker;
import javax.swing.JLabel;
import net.miginfocom.swing.MigLayout;
/**
* An example of how to use progress indication with Foxtrot. The main advantage is that there is no
* more need to create a separate thread for the progressive operation, but just use the Foxtrot
* API. And, of course, with Foxtrot the GUI can be interrupted in any moment.
*
* @version $Revision: 260 $
*/
public class JobMonitorPanel extends JPanel {
private JButton button;
JLabel descriptionLabel;
private JProgressBar bar;
private boolean running;
private boolean taskInterrupted;
private boolean indeterminate;
private Job theJobToRun;
public void setTheJobToRun(Job theJobToRun, String jobDescription) {
this.theJobToRun = theJobToRun;
descriptionLabel.setText(jobDescription);
button.setEnabled(true);
}
public JobMonitorPanel() {
// MigLayout ml = new MigLayout("",
// "[pref!][grow,fill]",
// "[]15[]");
MigLayout ml = new MigLayout("","","[]15[]");
setLayout(ml);
//setLayout(new MigLayout("", "[grow]", "[grow]"));
button = new JButton("Run Task !");
button.setSize(85, 32);
button.setAlignmentX(CENTER_ALIGNMENT);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (running) {
onCancelClicked();
} else {
onRunClicked();
}
}
});
button.setEnabled(false);
descriptionLabel = new JLabel("- - -");
bar = new JProgressBar();
bar.setStringPainted(true);
add(descriptionLabel, "width 200:null:null, span, wrap para");
add(button, "center, wrap");
add(bar, "center, grow");
//add(p);
}
void setIndeterminate(boolean b) {
indeterminate = b;
}
private void onRunClicked() {
if (theJobToRun == null) {
return;
}
// We are running
running = true;
// We just started, set the task as not interrupted, to
// clear any eventual previous status
setTaskInterrupted(false);
// We will execute a long operation, change the text signaling
// that the user can interrupt the operation
button.setText("Cancel");
// getData() will block until the heavy operation is finished
// and the AWT-Swing events will be dequeued and processed
bar.setString("running...");
if (indeterminate) {
bar.setIndeterminate(true);
}
boolean successfullyCompleted = runTheJob();
if (indeterminate) {
bar.setIndeterminate(false);
}
if (successfullyCompleted) {
bar.setString("done.");
} else {
bar.setString("Cancelled.");
}
// Restore the button's text
button.setText("Run Task !");
// We're not running anymore
running = false;
button.setEnabled(false);
// If was interrupted we get back a null list
}
private void onCancelClicked() {
// Here if we want to interrupt the Task
setTaskInterrupted(true);
}
private boolean runTheJob() {
if (theJobToRun == null) {
return false;
}
return (Boolean) Worker.post(theJobToRun);
}
public void update(final int index, final int max, final String string) {
// This method is called by the Foxtrot Worker thread, but I want to
// update the GUI, so I use SwingUtilities.invokeLater, as the Task
// is not finished yet.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
bar.setMaximum(max);
bar.setValue(index);
bar.setString(string);
}
});
}
public synchronized boolean isTaskInterrupted() {
// Called from the Foxtrot Worker Thread.
// Must be synchronized, since the variable taskInterrupted is accessed from 2 threads.
// While it is easier just to change the variable value without synchronizing, it is possible
// that the Foxtrot worker thread doesn't see the change (it may cache the value of the variable
// in a registry).
return taskInterrupted;
}
private synchronized void setTaskInterrupted(boolean value) {
// Called from the AWT Event Dispatch Thread.
// See comments above on why it must be synchronized.
taskInterrupted = value;
}
}