Beginnings of an interface to display download and patching status.
This commit is contained in:
@@ -1,8 +1,10 @@
|
|||||||
//
|
//
|
||||||
// $Id: Application.java,v 1.5 2004/07/06 09:46:35 mdb Exp $
|
// $Id: Application.java,v 1.6 2004/07/07 08:42:40 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.getdown.data;
|
package com.threerings.getdown.data;
|
||||||
|
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@@ -42,6 +44,23 @@ public class Application
|
|||||||
/** The name of our target version file. */
|
/** The name of our target version file. */
|
||||||
public static final String VERSION_FILE = "version.txt";
|
public static final String VERSION_FILE = "version.txt";
|
||||||
|
|
||||||
|
/** Used to communicate information about the UI displayed when
|
||||||
|
* updating the application. */
|
||||||
|
public static class UpdateInterface
|
||||||
|
{
|
||||||
|
/** The human readable name of this application. */
|
||||||
|
public String name;
|
||||||
|
|
||||||
|
/** The dimensions of the progress bar. */
|
||||||
|
public Rectangle progress;
|
||||||
|
|
||||||
|
/** The dimensions of the status display. */
|
||||||
|
public Rectangle status;
|
||||||
|
|
||||||
|
/** The path (relative to the appdir) to the background image. */
|
||||||
|
public String background;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an application instance which records the location of the
|
* Creates an application instance which records the location of the
|
||||||
* <code>getdown.txt</code> configuration file from the supplied
|
* <code>getdown.txt</code> configuration file from the supplied
|
||||||
@@ -91,10 +110,13 @@ public class Application
|
|||||||
* discovered later, the caller can use the application base to
|
* discovered later, the caller can use the application base to
|
||||||
* download a new <code>config.txt</code> file and try again.
|
* download a new <code>config.txt</code> file and try again.
|
||||||
*
|
*
|
||||||
|
* @return a configured UpdateInterface instance that will be used to
|
||||||
|
* configure the update UI.
|
||||||
|
*
|
||||||
* @exception IOException thrown if there is an error reading the file
|
* @exception IOException thrown if there is an error reading the file
|
||||||
* or an error encountered during its parsing.
|
* or an error encountered during its parsing.
|
||||||
*/
|
*/
|
||||||
public void init ()
|
public UpdateInterface init ()
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
// parse our configuration file
|
// parse our configuration file
|
||||||
@@ -194,6 +216,15 @@ public class Application
|
|||||||
_appargs.add(appargs[ii]);
|
_appargs.add(appargs[ii]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parse and return our application config
|
||||||
|
UpdateInterface ui = new UpdateInterface();
|
||||||
|
ui.name = (String)cdata.get("ui.name");
|
||||||
|
ui.progress = parseRect(
|
||||||
|
"ui.progress", (String)cdata.get("ui.progress"));
|
||||||
|
ui.status = parseRect("ui.progress", (String)cdata.get("ui.status"));
|
||||||
|
ui.background = (String)cdata.get("ui.background");
|
||||||
|
return ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -362,6 +393,8 @@ public class Application
|
|||||||
StreamUtil.close(fin);
|
StreamUtil.close(fin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// next parse any custom user interface information
|
||||||
|
|
||||||
// finally let the caller know if we need an update
|
// finally let the caller know if we need an update
|
||||||
return _version != _targetVersion;
|
return _version != _targetVersion;
|
||||||
}
|
}
|
||||||
@@ -469,6 +502,21 @@ public class Application
|
|||||||
return new Resource(path, getRemoteURL(path), getLocalPath(path));
|
return new Resource(path, getRemoteURL(path), getLocalPath(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Used to parse rectangle specifications from the config file. */
|
||||||
|
protected Rectangle parseRect (String name, String value)
|
||||||
|
{
|
||||||
|
if (!StringUtil.blank(value)) {
|
||||||
|
int[] v = StringUtil.parseIntArray(value);
|
||||||
|
if (v != null && v.length == 4) {
|
||||||
|
return new Rectangle(v[0], v[1], v[2], v[3]);
|
||||||
|
} else {
|
||||||
|
Log.warning("Ignoring invalid '" + name + "' config '" +
|
||||||
|
value + "'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
protected File _appdir;
|
protected File _appdir;
|
||||||
protected File _config;
|
protected File _config;
|
||||||
protected Digest _digest;
|
protected Digest _digest;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: Downloader.java,v 1.1 2004/07/06 05:13:36 mdb Exp $
|
// $Id: Downloader.java,v 1.2 2004/07/07 08:42:40 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.getdown.launcher;
|
package com.threerings.getdown.launcher;
|
||||||
|
|
||||||
@@ -260,5 +260,5 @@ public class Downloader extends Thread
|
|||||||
|
|
||||||
/** The delay in milliseconds between notifying progress observers of
|
/** The delay in milliseconds between notifying progress observers of
|
||||||
* file download progress. */
|
* file download progress. */
|
||||||
protected static final long UPDATE_DELAY = 2500L;
|
protected static final long UPDATE_DELAY = 500L;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
//
|
//
|
||||||
// $Id: Getdown.java,v 1.4 2004/07/06 05:13:36 mdb Exp $
|
// $Id: Getdown.java,v 1.5 2004/07/07 08:42:40 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.getdown.launcher;
|
package com.threerings.getdown.launcher;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -12,6 +19,9 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.apache.commons.io.TeeOutputStream;
|
import org.apache.commons.io.TeeOutputStream;
|
||||||
|
|
||||||
|
import com.samskivert.swing.util.SwingUtil;
|
||||||
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
import com.threerings.getdown.Log;
|
import com.threerings.getdown.Log;
|
||||||
import com.threerings.getdown.data.Application;
|
import com.threerings.getdown.data.Application;
|
||||||
import com.threerings.getdown.data.Resource;
|
import com.threerings.getdown.data.Resource;
|
||||||
@@ -31,10 +41,11 @@ public class Getdown
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
for (int ii = 0; ii < MAX_LOOPS; ii++) {
|
for (int ii = 0; ii < MAX_LOOPS; ii++) {
|
||||||
_app.init();
|
_ifc = _app.init();
|
||||||
|
|
||||||
if (_app.verifyMetadata()) {
|
if (_app.verifyMetadata()) {
|
||||||
Log.info("Application requires update.");
|
Log.info("Application requires update.");
|
||||||
|
update();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log.info("Metadata verified.");
|
Log.info("Metadata verified.");
|
||||||
@@ -63,7 +74,6 @@ public class Getdown
|
|||||||
*/
|
*/
|
||||||
protected void update ()
|
protected void update ()
|
||||||
{
|
{
|
||||||
Log.info("We're needin' an update Cap'n!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,15 +84,20 @@ public class Getdown
|
|||||||
{
|
{
|
||||||
final Object lock = new Object();
|
final Object lock = new Object();
|
||||||
|
|
||||||
|
// create our user interface
|
||||||
|
createInterface();
|
||||||
|
|
||||||
// create a downloader to download our resources
|
// create a downloader to download our resources
|
||||||
Downloader.Observer obs = new Downloader.Observer() {
|
Downloader.Observer obs = new Downloader.Observer() {
|
||||||
public void resolvingDownloads () {
|
public void resolvingDownloads () {
|
||||||
Log.info("Resolving downloads...");
|
Log.info("Resolving downloads...");
|
||||||
|
_status.setStatus("Resolving downloads...");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void downloadProgress (int percent, long remaining) {
|
public void downloadProgress (int percent, long remaining) {
|
||||||
Log.info("Download progress " + percent + "% " +
|
_status.setStatus("Download progress " + percent + "%, " +
|
||||||
remaining + "s remaining.");
|
remaining + " seconds remaining.");
|
||||||
|
_status.setProgress(percent);
|
||||||
if (percent == 100) {
|
if (percent == 100) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
lock.notify();
|
lock.notify();
|
||||||
@@ -91,6 +106,7 @@ public class Getdown
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void downloadFailed (Resource rsrc, Exception e) {
|
public void downloadFailed (Resource rsrc, Exception e) {
|
||||||
|
_status.setStatus("Download failed: " + e.getMessage());
|
||||||
Log.warning("Download failed [rsrc=" + rsrc + "].");
|
Log.warning("Download failed [rsrc=" + rsrc + "].");
|
||||||
Log.logStackTrace(e);
|
Log.logStackTrace(e);
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
@@ -117,14 +133,55 @@ public class Getdown
|
|||||||
*/
|
*/
|
||||||
protected void launch ()
|
protected void launch ()
|
||||||
{
|
{
|
||||||
Log.info("All systems go!");
|
if (_status != null) {
|
||||||
|
_status.setStatus("Launching...");
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Process proc = _app.createProcess();
|
Process proc = _app.createProcess();
|
||||||
|
System.exit(0);
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
Log.logStackTrace(ioe);
|
Log.logStackTrace(ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates our user interface, which we avoid doing unless we actually
|
||||||
|
* have to update something.
|
||||||
|
*/
|
||||||
|
protected void createInterface ()
|
||||||
|
{
|
||||||
|
if (_frame != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle ppos = (_ifc.progress == null) ? DEFAULT_PPOS : _ifc.progress;
|
||||||
|
Rectangle spos = (_ifc.status == null) ? DEFAULT_STATUS : _ifc.status;
|
||||||
|
Rectangle bounds = ppos.union(spos);
|
||||||
|
bounds.grow(5, 5);
|
||||||
|
|
||||||
|
// if we have a background image, load it up
|
||||||
|
BufferedImage bgimg = null;
|
||||||
|
if (!StringUtil.blank(_ifc.background)) {
|
||||||
|
File bgpath = _app.getLocalPath(_ifc.background);
|
||||||
|
try {
|
||||||
|
bgimg = ImageIO.read(bgpath);
|
||||||
|
bounds.setRect(0, 0, bgimg.getWidth(), bgimg.getHeight());
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
Log.warning("Failed to read UI background [path=" + bgpath +
|
||||||
|
", error=" + ioe + "].");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create our user interface, and display it
|
||||||
|
_frame = new JFrame(StringUtil.blank(_ifc.name) ? "" : _ifc.name);
|
||||||
|
_status = new StatusPanel(bounds, bgimg, ppos, spos);
|
||||||
|
_frame.getContentPane().add(_status, BorderLayout.CENTER);
|
||||||
|
_frame.pack();
|
||||||
|
SwingUtil.centerWindow(_frame);
|
||||||
|
_frame.show();
|
||||||
|
}
|
||||||
|
|
||||||
public static void main (String[] args)
|
public static void main (String[] args)
|
||||||
{
|
{
|
||||||
// ensure the proper parameters are passed
|
// ensure the proper parameters are passed
|
||||||
@@ -161,6 +218,15 @@ public class Getdown
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Application _app;
|
protected Application _app;
|
||||||
|
protected Application.UpdateInterface _ifc;
|
||||||
|
|
||||||
|
protected JFrame _frame;
|
||||||
|
protected StatusPanel _status;
|
||||||
|
|
||||||
protected static final int MAX_LOOPS = 5;
|
protected static final int MAX_LOOPS = 5;
|
||||||
|
|
||||||
|
protected static final Rectangle DEFAULT_PPOS =
|
||||||
|
new Rectangle(0, 0, 300, 15);
|
||||||
|
protected static final Rectangle DEFAULT_STATUS =
|
||||||
|
new Rectangle(0, 20, 300, 200);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
//
|
||||||
|
// $Id: StatusPanel.java,v 1.1 2004/07/07 08:42:40 mdb Exp $
|
||||||
|
|
||||||
|
package com.threerings.getdown.launcher;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
|
||||||
|
import com.samskivert.swing.Label;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays download and patching status.
|
||||||
|
*/
|
||||||
|
public class StatusPanel extends JComponent
|
||||||
|
{
|
||||||
|
public StatusPanel (Rectangle bounds, BufferedImage bgimg,
|
||||||
|
Rectangle ppos, Rectangle spos)
|
||||||
|
{
|
||||||
|
_bgimg = bgimg;
|
||||||
|
_psize = new Dimension(bounds.width, bounds.height);
|
||||||
|
_ppos = ppos;
|
||||||
|
_spos = spos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjusts the progress display to the specified percentage.
|
||||||
|
*/
|
||||||
|
public void setProgress (int percent)
|
||||||
|
{
|
||||||
|
_progress = percent;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the specified status string.
|
||||||
|
*/
|
||||||
|
public void setStatus (String status)
|
||||||
|
{
|
||||||
|
_newlab = new Label(status, Color.white, null);
|
||||||
|
_newlab.setTargetWidth(_spos.width);
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public void paintComponent (Graphics g)
|
||||||
|
{
|
||||||
|
super.paintComponent(g);
|
||||||
|
Graphics2D gfx = (Graphics2D)g;
|
||||||
|
|
||||||
|
// if we have a new label; lay it out
|
||||||
|
if (_newlab != null) {
|
||||||
|
_newlab.layout(gfx);
|
||||||
|
_label = _newlab;
|
||||||
|
_newlab = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_bgimg != null) {
|
||||||
|
gfx.drawImage(_bgimg, 0, 0, null);
|
||||||
|
} else {
|
||||||
|
gfx.fillRect(0, 0, getWidth(), getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx.setColor(Color.blue);
|
||||||
|
gfx.fillRect(_ppos.x, _ppos.y, _progress * _ppos.width / 100,
|
||||||
|
_ppos.height);
|
||||||
|
|
||||||
|
gfx.setColor(Color.white);
|
||||||
|
gfx.draw(_ppos);
|
||||||
|
|
||||||
|
if (_label != null) {
|
||||||
|
_label.render(gfx, _spos.x, _spos.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited
|
||||||
|
public Dimension getPreferredSize ()
|
||||||
|
{
|
||||||
|
return _psize;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BufferedImage _bgimg;
|
||||||
|
protected Dimension _psize;
|
||||||
|
protected Rectangle _ppos, _spos;
|
||||||
|
|
||||||
|
protected int _progress = 0;
|
||||||
|
protected Label _label, _newlab;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user