/////////////////////////////////////////////////////////////////////////////
// Copyright (c) 1998, California Institute of Technology.
// ALL RIGHTS RESERVED. U.S. Government Sponsorship acknowledged.
//
// Please read the full copyright notice in the file COPYRIGHT
// in this directory.
//
// Author: Jake Hamby, NASA/Jet Propulsion Laboratory
// Jake.Hamby@jpl.nasa.gov
/////////////////////////////////////////////////////////////////////////////
package dods.util.geturl.gui;
import java.awt.*;
import java.awt.event.*;
import java.text.NumberFormat;
/** This class implements a simple status window to show DODS deserialize
* status. It shows the URL being retrieved, the number of bytes that
* have been read so far, the transfer rate in K/sec, and a Cancel button
* which can be used to abort the download.
*/
public class StatusWindow extends Frame implements dods.dap.StatusUI {
/** The Label showing the DODS URL being downloaded. */
private Label urlLabel;
/** The number of bytes downloaded so far. */
private int bytesRead;
/** The start time in milliseconds. */
private long startTime;
/** The last time the transfer rate was updated, in milliseconds. */
private long lastUpdateTime;
/** Has the cancel button been pushed by the user? */
private boolean cancelPushed;
/** The Label showing the number of bytes read */
private Label bytesReadLabel;
/** The Label showing the current transfer rate */
private Label transferRateLabel;
/** The cancel button. (NOTE: synchronize methods which access this!) */
private Button cancelButton;
/** The NumberFormat object used for writing floating point labels. */
NumberFormat nf = NumberFormat.getInstance();
/** Construct the status window to display download status for the
* given URL. */
public StatusWindow(String url) {
super("Status Window");
bytesRead = 0;
cancelPushed = false;
// set to a reasonable size
setSize(450, 150);
Label retrievingTag = new Label("Retrieving:");
urlLabel = new Label(url);
Label bytesReadTag = new Label("Bytes Read:");
bytesReadLabel = new Label(" ");
Label transferRateTag = new Label("Transfer Rate:");
transferRateLabel = new Label(" ");
cancelButton = new Button("Cancel Download");
GridBagLayout gbl = new GridBagLayout();
GridBagConstraints gbc = new GridBagConstraints();
setLayout(gbl);
gbc.anchor = GridBagConstraints.EAST;
gbc.gridwidth = 1;
gbl.setConstraints(retrievingTag, gbc);
add(retrievingTag);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbl.setConstraints(urlLabel, gbc);
add(urlLabel);
gbc.anchor = GridBagConstraints.EAST;
gbc.gridwidth = 1;
gbl.setConstraints(bytesReadTag, gbc);
add(bytesReadTag);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbl.setConstraints(bytesReadLabel, gbc);
add(bytesReadLabel);
gbc.anchor = GridBagConstraints.EAST;
gbc.gridwidth = 1;
gbl.setConstraints(transferRateTag, gbc);
add(transferRateTag);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbl.setConstraints(transferRateLabel, gbc);
add(transferRateLabel);
gbc.anchor = GridBagConstraints.CENTER;
gbl.setConstraints(cancelButton, gbc);
add(cancelButton);
// add action listener for cancel button
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
programCancel();
}
});
// set listener for window close
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
// first, cancel the download
programCancel();
// also, dispose the window in case the download has already cancelled
// due to an abnormal event, such as a SecurityException
dispose();
}
});
// start the download clock running
startTime = lastUpdateTime = System.currentTimeMillis();
// finally, show ourselves
show();
}
/** Add bytes to the total deserialize count. This is called by each
BaseType's deserialize() method to provide the user with feedback on the
number of bytes that have been transferred so far. If some future version
of DODS provides a correct Content-Length, then a sophisticated GUI could
use this information to estimate the time remaining to download. */
public void incrementByteCount(int bytes) {
bytesRead += bytes;
long currentTime = System.currentTimeMillis();
// update 5 times a second
if ((currentTime - lastUpdateTime) > 200) {
if (bytesRead > (1024*1024)) {
float MBread = (float)bytesRead / (1024*1024);
bytesReadLabel.setText(nf.format(MBread) + " MB");
} else if (bytesRead > 1024) {
float Kread = (float)bytesRead / 1024;
bytesReadLabel.setText(nf.format(Kread) + " K");
} else {
bytesReadLabel.setText(nf.format(bytesRead));
}
bytesReadLabel.repaint();
float bytesPerSecond = (float)bytesRead / (currentTime - startTime)
* 1000;
if (bytesPerSecond > (1024*1024)) {
float MBperSecond = bytesPerSecond / (1024*1024);
transferRateLabel.setText(nf.format(MBperSecond) + " MB/sec");
} else if (bytesPerSecond > 1024) {
float KperSecond = bytesPerSecond / 1024;
transferRateLabel.setText(nf.format(KperSecond) + " K/sec");
} else {
transferRateLabel.setText(nf.format(bytesPerSecond) + "bytes/sec");
}
transferRateLabel.repaint();
lastUpdateTime = currentTime;
}
}
/** User cancellation status. This returns true when the user has clicked
the cancel button of a GUI, or false if the download should proceed. This
is called at various cancellation points throughout the deserialize process
so that the download can be cancelled in an orderly fashion. */
public synchronized boolean userCancelled() {
// If the user has pushed cancel, then dispose of the window
if (cancelPushed)
dispose();
return cancelPushed;
}
/** Download finished notice. This is called when the download is finished
and disposes the status window. */
public void finished() {
dispose();
}
/** Allow the program to "press" the cancel button as well as the user. */
public synchronized void programCancel() {
cancelPushed = true;
}
}