001: package org.swingml.task.monitoring;
002:
003: import java.awt.*;
004: import java.awt.event.*;
005: import java.util.*;
006: import java.util.List;
007:
008: import javax.swing.*;
009:
010: import org.swingml.task.*;
011:
012: /**
013: * A dialog that shows progress of tasks using JProgressBars. Allows the user to
014: * 'hide' the window by providing a "Run in Background" button.
015: *
016: * @author CrossLogic
017: */
018: public class TaskMonitorDialog implements TaskReporter, ITaskMonitor {
019:
020: /**
021: * Executes when the user clicks the "Hide" button.
022: */
023: private class HideListener implements ActionListener {
024:
025: HideListener() {
026: }
027:
028: public void actionPerformed(ActionEvent e) {
029: if (tasks != null && tasks.size() > 0) {
030: setHiddenByUser(true);
031: } else {
032: hide();
033: }
034: }
035: }
036:
037: private static TaskMonitorDialog instance = null;
038:
039: public static TaskMonitorDialog getInstance() {
040: if (instance == null) {
041: instance = new TaskMonitorDialog();
042: }
043: return instance;
044: }
045:
046: private JDialog dialog;
047: private boolean hiddenByUser = false;
048: private JButton hide;
049: private Map labels = new HashMap();
050: private JLabel name;
051: private JPanel progressBarArea;
052: private Map progressBars = new HashMap();
053:
054: private List tasks;
055:
056: private TaskMonitorDialog() {
057: super ();
058: dialog = new JDialog();
059: dialog.setModal(true);
060: dialog.setVisible(false);
061: buildContentPanel();
062: }
063:
064: private void addLabel(ITask task, JLabel label) {
065: labels.put(task, label);
066: }
067:
068: private void addProgressBar(ITask task, JProgressBar bar) {
069: progressBars.put(task, bar);
070: }
071:
072: public void beginReporting() {
073: show(false);
074: }
075:
076: public void beginTask(ITask task) {
077: show(false);
078: }
079:
080: private void buildContentPanel() {
081: // Build panel area
082: JPanel contentArea = new JPanel();
083: contentArea.setLayout(new BorderLayout());
084: dialog.setContentPane(contentArea);
085:
086: // Build progress area (West)
087: JPanel progressArea = new JPanel(new BorderLayout());
088: JPanel titleArea = new JPanel(new BorderLayout());
089: titleArea.add(new JLabel("Executing: "), BorderLayout.WEST);
090: setNameLabel(new JLabel(""));
091: titleArea.add(getNameLabel(), BorderLayout.CENTER);
092: progressArea.add(titleArea, BorderLayout.NORTH);
093: progressBarArea = new JPanel(new SpringLayout());
094: JScrollPane scrollPane = new JScrollPane(progressBarArea,
095: JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
096: JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
097: progressArea.add(scrollPane, BorderLayout.CENTER);
098: contentArea.add(progressArea, BorderLayout.CENTER);
099:
100: // build Hide button (South)
101: hide = new JButton("Run in Background");
102: hide.addActionListener(new HideListener());
103: JPanel buttonBar = new JPanel(new BorderLayout());
104: buttonBar.add(hide, BorderLayout.EAST);
105: contentArea.add(buttonBar, BorderLayout.SOUTH);
106:
107: dialog.setModal(true);
108: dialog.setSize(new Dimension(380, 180));
109: dialog.setResizable(false);
110: }
111:
112: private void compactProgressBarArea() {
113: if (getTasks().size() > 0) {
114: SpringUtilities.makeCompactGrid(progressBarArea, getTasks()
115: .size(), 2, // rows,
116: // cols
117: 6, 6, // initX, initY
118: 6, 6); // xPad, yPad
119: } else {
120: progressBarArea.removeAll();
121: }
122: }
123:
124: public void complete() {
125: hide();
126: }
127:
128: public void endTask(ITask task) {
129: if (getTasks().remove(task)) {
130: // remove from panel
131: JProgressBar bar = getProgressBar(task);
132: JLabel label = getLabel(task);
133: bar.setEnabled(false);
134: label.setEnabled(false);
135: progressBarArea.remove(bar);
136: progressBarArea.remove(label);
137: compactProgressBarArea();
138:
139: // take care of progressbar and label
140: removeProgressBar(task);
141: removeLabel(task);
142:
143: if (getTasks().size() == 0) {
144: setHiddenByUser(false);
145: hide();
146: }
147: }
148: }
149:
150: /**
151: * Get the label for the given task.
152: *
153: * @param task
154: * @return
155: */
156: public JLabel getLabel(ITask task) {
157: JLabel result = null;
158: if (labels.containsKey(task)) {
159: result = (JLabel) labels.get(task);
160: }
161: return result;
162: }
163:
164: private JLabel getNameLabel() {
165: return name;
166: }
167:
168: /**
169: * Get the progressbar for the given task.
170: *
171: * @param task
172: * @return
173: */
174: public JProgressBar getProgressBar(ITask task) {
175: JProgressBar result = null;
176: if (progressBars.containsKey(task)) {
177: result = (JProgressBar) progressBars.get(task);
178: }
179: return result;
180: }
181:
182: private List getTasks() {
183: if (tasks == null) {
184: tasks = new ArrayList();
185: }
186: return tasks;
187: }
188:
189: public void hide() {
190: dialog.setVisible(false);
191: }
192:
193: public boolean isHiddenByUser() {
194: return hiddenByUser;
195: }
196:
197: public boolean isVisible() {
198: return dialog.isVisible();
199: }
200:
201: public void prepare(ITask aTask) {
202: if (!getTasks().contains(aTask)) {
203: getTasks().add(aTask);
204: dialog.setTitle(aTask.getName());
205:
206: // add this dialog as a listener for progress
207: aTask.addTaskMonitor(this );
208:
209: // Set the task name label text
210: getNameLabel().setText(aTask.getName());
211:
212: // Add ProgressBar and Label for this new task.
213: JLabel aLabel = new JLabel("");
214: progressBarArea.add(aLabel);
215: JProgressBar aBar = new JProgressBar();
216: int steps = aTask.getSteps();
217: if (steps < 1) {
218: aBar.setMaximum(0);
219: aBar.setIndeterminate(true);
220: } else {
221: aBar.setMaximum(steps);
222: aBar.setIndeterminate(false);
223: }
224: progressBarArea.add(aBar);
225:
226: compactProgressBarArea();
227:
228: // set as current
229: addProgressBar(aTask, aBar);
230: addLabel(aTask, aLabel);
231: }
232:
233: if (!isHiddenByUser()) {
234: show(false);
235: }
236: }
237:
238: public void progressMade(ITask task) {
239: progressMade(task, 1);
240: }
241:
242: public void progressMade(ITask task, int ticks) {
243: int totalTicks = getProgressBar(task).getValue();
244: totalTicks += ticks;
245: getProgressBar(task).setValue(totalTicks);
246: }
247:
248: public void progressMade(ITask task, int ticks, String aMessage) {
249: progressMade(task, ticks);
250: setMessage(task, aMessage);
251: }
252:
253: public void progressMade(ITask task, String aMessage) {
254: progressMade(task, 1);
255: setMessage(task, aMessage);
256: }
257:
258: /**
259: * Remove the label registered for the given task.
260: *
261: * @param task
262: */
263: private void removeLabel(ITask task) {
264: if (task != null && labels.containsKey(task)) {
265: labels.remove(task);
266: }
267: }
268:
269: /**
270: * Remove the JProgressBar registered for the given task.
271: *
272: * @param task
273: */
274: private void removeProgressBar(ITask task) {
275: if (task != null && progressBars.containsKey(task)) {
276: progressBars.remove(task);
277: }
278: }
279:
280: public void setHiddenByUser(boolean b) {
281: hiddenByUser = b;
282: if (hiddenByUser) {
283: hide();
284: }
285: }
286:
287: public void setMessage(ITask task, String aMessage) {
288: if (aMessage == null) {
289: aMessage = "";
290: }
291: getLabel(task).setText(aMessage);
292: }
293:
294: private void setNameLabel(JLabel aLabel) {
295: this .name = aLabel;
296: }
297:
298: public void show(final boolean showImmediately) {
299: Runnable runner = new Runnable() {
300:
301: public void run() {
302: // set location
303: int height = dialog.getGraphicsConfiguration()
304: .getDevice().getDisplayMode().getHeight();
305: int width = dialog.getGraphicsConfiguration()
306: .getDevice().getDisplayMode().getWidth();
307: int x = (width / 2) - (dialog.getWidth() / 2);
308: int y = (height / 2) - (dialog.getHeight() / 2);
309: dialog.setLocation(x, y);
310:
311: dialog.setVisible(!isHiddenByUser());
312: }
313: };
314: if (showImmediately) {
315: setHiddenByUser(false);
316: runner.run();
317: } else {
318: SwingUtilities.invokeLater(runner);
319: }
320:
321: }
322: }
|