StatusPane.java
/**
* VStar: a statistical analysis tool for variable star data.
* Copyright (C) 2009 AAVSO (http://www.aavso.org/)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.aavso.tools.vstar.ui;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.border.BevelBorder;
import org.aavso.tools.vstar.ui.mediator.Mediator;
import org.aavso.tools.vstar.ui.mediator.NewStarType;
import org.aavso.tools.vstar.ui.mediator.message.NewStarMessage;
import org.aavso.tools.vstar.ui.mediator.message.ProgressInfo;
import org.aavso.tools.vstar.ui.mediator.message.StopRequestMessage;
import org.aavso.tools.vstar.ui.resources.ResourceAccessor;
import org.aavso.tools.vstar.util.locale.LocaleProps;
import org.aavso.tools.vstar.util.notification.Listener;
/**
* A status panel containing a text status message component and a status bar.
*
* The intention is that this should be added to the bottom of the GUI.
*
* This class will also listen to various events.
*/
@SuppressWarnings("serial")
public class StatusPane extends JPanel {
private Mediator mediator = Mediator.getInstance();
private JLabel statusLabel, xyLabel;
private JProgressBar progressBar;
private JButton stopButton;
/**
* Constructor.
*
* @param firstMsg
* The first message to be displayed in the status pane.
*/
public StatusPane(String firstMsg) {
super(true);
this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
statusLabel = new JLabel();
statusLabel.setHorizontalAlignment(JLabel.LEFT);
this.setMessage(firstMsg);
this.add(statusLabel);
this.add(Box.createHorizontalGlue());
this.progressBar = new JProgressBar();
this.add(progressBar);
this.add(Box.createHorizontalGlue());
xyLabel = new JLabel();
xyLabel.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 14));
// xyLabel.setBorder(BorderFactory.createEtchedBorder());
// this.add(xyLabel);
// this.add(Box.createHorizontalGlue());
Icon stopIcon = ResourceAccessor
.getIconResource("/nico/toolbarIcons/_24_/Stop2.png");
this.stopButton = new JButton(stopIcon);
this.stopButton.setToolTipText("Stop the current operation");
this.stopButton.setBorder(BorderFactory.createEmptyBorder());
this.stopButton.setEnabled(false);
this.stopButton.addActionListener(createStopButtonListener());
this.add(this.stopButton);
this.add(Box.createRigidArea(new Dimension(20, 10)));
this.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
mediator.getNewStarNotifier().addListener(createNewStarListener());
mediator.getProgressNotifier().addListener(createProgressListener());
}
// TODO: To prevent the progress bar from shifting, pad all messages
// to N length and make sure we are using a fixed width font (tracker).
// Or, use a different layout manager.
/**
* Set the status message to be displayed.
*
* @param msg
* The message to be displayed.
*/
public void setMessage(String msg) {
this.statusLabel.setText(" " + msg);
}
/**
* Set the XY message (intended to be JD/phase and magnitude).
*
* @param msg
* The message to be displayed.
*/
public void setXYMessage(String msg) {
this.xyLabel.setText(msg);
}
/**
* Set the minimum progress bar value.
*
* @param n
* The minimum value to set.
*/
public void setMinProgressValue(int n) {
this.progressBar.setMinimum(n);
assert (this.progressBar.getMinimum() <= this.progressBar.getMaximum());
}
/**
* Set the maximum progress bar value.
*
* @param n
* The maximum value to set.
*/
public void setMaxProgressValue(int n) {
this.progressBar.setMaximum(n);
assert (this.progressBar.getMaximum() >= this.progressBar.getMinimum());
}
/**
* Reset the progress bar to its minimum value.
*/
public void resetProgressBar() {
this.progressBar.setValue(this.progressBar.getMinimum());
}
/**
* Increment the progress bar by N.
*/
public void incrementProgressBar(int n) {
if (this.progressBar.getValue() + n <= this.progressBar.getMaximum()) {
this.progressBar.setValue(this.progressBar.getValue() + n);
}
}
/**
* Set the progress bar to its maximum value, i.e. complete the progress
* bar.
*/
public void completeProgressBar() {
this.progressBar.setValue(this.progressBar.getMaximum());
}
/**
* Set the progress bar to be in busy or indeterminate mode (or not) to
* indicate that some kind of work is being done.
*/
public void setIndeterminateMode(boolean status) {
this.progressBar.setIndeterminate(status);
}
/**
* Return a new star creation listener. TODO: instead of this, we could just
* write the status at end of new star task processing in mediator.
*/
private Listener<NewStarMessage> createNewStarListener() {
return new Listener<NewStarMessage>() {
// Update the status bar to say something about the fact that a
// new star has just been loaded.
public void update(NewStarMessage msg) {
if (msg.getNewStarType() == NewStarType.NEW_STAR_FROM_SIMPLE_FILE
|| msg.getNewStarType() == NewStarType.NEW_STAR_FROM_DOWNLOAD_FILE
|| msg.getNewStarType() == NewStarType.NEW_STAR_FROM_DATABASE) {
StringBuffer strBuf = new StringBuffer();
strBuf.append("'");
strBuf.append(msg.getStarInfo().getDesignation());
strBuf.append("' " + LocaleProps.get("LOADED"));
setMessage(strBuf.toString());
} else {
// Arbitrary data sources.
StringBuffer strBuf = new StringBuffer();
strBuf.append("'");
strBuf.append(msg.getStarInfo().getDesignation());
strBuf.append("' " + LocaleProps.get("LOADED"));
String str = strBuf.toString();
if (str.length() > 20) {
// We don't want to have a message that is so long (e.g.
// a URL) that it takes over the status pane!
str = "";
}
setMessage(str);
}
}
public boolean canBeRemoved() {
return false;
}
};
}
/**
* Return a progress listener.
*/
private Listener<ProgressInfo> createProgressListener() {
final StatusPane self = this;
return new Listener<ProgressInfo>() {
public void update(ProgressInfo info) {
self.setIndeterminateMode(false);
switch (info.getType()) {
case MIN_PROGRESS:
self.setMinProgressValue(info.getNum());
break;
case MAX_PROGRESS:
self.setMaxProgressValue(info.getNum());
break;
case START_PROGRESS:
// Ensure the main window now has focus so we see
// the progress bar and busy cursor as enabled.
// self.requestFocusInWindow(); // TODO: doesn't work;
// remove?
self.resetProgressBar();
self.setMessage("");
self.stopButton.setEnabled(true);
break;
case COMPLETE_PROGRESS:
self.completeProgressBar();
self.stopButton.setEnabled(false);
mediator.clearCurrentTask();
break;
case INCREMENT_PROGRESS:
// Ensure the main window now has focus so we see
// the progress bar and busy cursor as enabled.
// Except that it does not work here or above.
// self.requestFocusInWindow(); // TODO: remove?
self.incrementProgressBar(info.getNum());
break;
case CLEAR_PROGRESS:
self.progressBar.setValue(0);
break;
case BUSY_PROGRESS:
self.setIndeterminateMode(true);
break;
}
}
public boolean canBeRemoved() {
return false;
}
};
}
// Create an action listener to stop the current task,
// if one is in progress.
private ActionListener createStopButtonListener() {
return new ActionListener() {
public void actionPerformed(ActionEvent e) {
mediator.stopCurrentTask();
StopRequestMessage msg = new StopRequestMessage(this);
mediator.getStopRequestNotifier().notifyListeners(msg);
}
};
}
}