From a22d5c37079494737fa1cbf7c99e6ad5f86daf82 Mon Sep 17 00:00:00 2001 From: Charlie Groves Date: Fri, 12 Oct 2007 18:46:40 +0000 Subject: [PATCH] Allow more than one background image to be specified, and if there are multiple, rotate through them as things are downloaded. --- .../threerings/getdown/data/Application.java | 8 +- .../threerings/getdown/launcher/Getdown.java | 25 +++-- .../getdown/launcher/GetdownApplet.java | 55 ++++++----- .../getdown/launcher/ImageLoader.java | 9 ++ .../getdown/launcher/RotatingBackgrounds.java | 98 +++++++++++++++++++ .../getdown/launcher/StatusPanel.java | 25 ++--- 6 files changed, 174 insertions(+), 46 deletions(-) create mode 100644 src/java/com/threerings/getdown/launcher/ImageLoader.java create mode 100644 src/java/com/threerings/getdown/launcher/RotatingBackgrounds.java diff --git a/src/java/com/threerings/getdown/data/Application.java b/src/java/com/threerings/getdown/data/Application.java index 72968a6..123dc33 100644 --- a/src/java/com/threerings/getdown/data/Application.java +++ b/src/java/com/threerings/getdown/data/Application.java @@ -66,6 +66,7 @@ import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.IOUtils; import com.threerings.getdown.Log; +import com.threerings.getdown.launcher.RotatingBackgrounds; import com.threerings.getdown.util.ConfigUtil; import com.threerings.getdown.util.FileUtil; import com.threerings.getdown.util.LaunchUtil; @@ -97,7 +98,10 @@ public class Application /** The human readable name of this application. */ public String name; - /** The path (relative to the appdir) to the background image. */ + /** Background image specifiers for {@link RotatingBackgrounds}. */ + public String[] rotatingBackgrounds; + + /** The path (relative to the appdir) to a single background image. */ public String backgroundImage; /** The path (relative to the appdir) to the progress bar image. */ @@ -575,7 +579,7 @@ public class Application ui.backgroundImage = (String)cdata.get("ui.background"); } ui.progressImage = (String)cdata.get("ui.progress_image"); - + ui.rotatingBackgrounds = ConfigUtil.getMultiValue(cdata, "ui.rotating_background"); _dockIconPath = (String)cdata.get("ui.mac_dock_icon"); if (_dockIconPath == null) { _dockIconPath = "../desktop.icns"; // use a sensible default diff --git a/src/java/com/threerings/getdown/launcher/Getdown.java b/src/java/com/threerings/getdown/launcher/Getdown.java index 9727678..2ea275e 100644 --- a/src/java/com/threerings/getdown/launcher/Getdown.java +++ b/src/java/com/threerings/getdown/launcher/Getdown.java @@ -71,7 +71,7 @@ import com.threerings.getdown.util.ProgressObserver; * Manages the main control for the Getdown application updater and deployment system. */ public abstract class Getdown extends Thread - implements Application.StatusDisplay + implements Application.StatusDisplay, ImageLoader { public static void main (String[] args) { @@ -717,23 +717,35 @@ public abstract class Getdown extends Thread } EventQueue.invokeLater(new Runnable() { + public void run () { if (_status == null) { _container = createContainer(); _status = new StatusPanel(_msgs); _container.add(_status, BorderLayout.CENTER); + _background = getBackground(); } - _status.init(_ifc, getBackgroundImage(), getProgressImage()); + _status.init(_ifc, _background, getProgressImage()); showContainer(); } }); } - protected Image getBackgroundImage () + protected RotatingBackgrounds getBackground () { - return loadImage(_ifc.backgroundImage); + if (_ifc.rotatingBackgrounds != null) { + if (_ifc.backgroundImage != null) { + Log.warning("ui.background_image and ui.rotating_background were " + + " both specified. The rotating images are being used."); + } + return new RotatingBackgrounds(_ifc.rotatingBackgrounds, Getdown.this); + } else if (_ifc.backgroundImage != null) { + return new RotatingBackgrounds(loadImage(_ifc.backgroundImage)); + } else { + return new RotatingBackgrounds(); + } } - + protected Image getProgressImage () { return loadImage(_ifc.progressImage); @@ -805,7 +817,7 @@ public abstract class Getdown extends Thread * we will look to see if we can find a localized version by sticking a * _ in front of the "." in the filename. */ - protected BufferedImage loadImage (String path) + public BufferedImage loadImage (String path) { String localeStr = Locale.getDefault().getLanguage(); @@ -926,6 +938,7 @@ public abstract class Getdown extends Thread protected Container _container; protected StatusPanel _status; protected AbortPanel _abort; + protected RotatingBackgrounds _background; protected boolean _dead; protected boolean _silent; diff --git a/src/java/com/threerings/getdown/launcher/GetdownApplet.java b/src/java/com/threerings/getdown/launcher/GetdownApplet.java index ceb68dd..18ba847 100644 --- a/src/java/com/threerings/getdown/launcher/GetdownApplet.java +++ b/src/java/com/threerings/getdown/launcher/GetdownApplet.java @@ -22,19 +22,18 @@ package com.threerings.getdown.launcher; import java.awt.Container; import java.awt.Image; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.net.MalformedURLException; import java.net.URL; import javax.swing.JApplet; import javax.swing.JPanel; -import java.io.IOException; -import java.io.FileOutputStream; -import java.io.File; -import java.io.PrintStream; - import com.samskivert.util.RunAnywhere; import com.samskivert.util.StringUtil; - import com.threerings.getdown.Log; /** @@ -42,6 +41,7 @@ import com.threerings.getdown.Log; * given privileges). */ public class GetdownApplet extends JApplet + implements ImageLoader { @Override // documentation inherited public void init () @@ -50,16 +50,22 @@ public class GetdownApplet extends JApplet // signer String appbase = getParameter("appbase"); String appname = getParameter("appname"); - String imgpath = getParameter("bgimage"); + String imgpath = getParameter("bgimage");; if (appbase == null) { appbase = ""; } if (appname == null) { appname = ""; } - if (imgpath == null) { - imgpath = ""; + final RotatingBackgrounds bgimages; + if(imgpath == null) { + bgimages = new RotatingBackgrounds(); + } else if(imgpath.contains(",")) { + bgimages = new RotatingBackgrounds(imgpath.split(","), this); + } else { + bgimages = new RotatingBackgrounds(loadImage(imgpath)); } + Log.info("App Base: " + appbase); Log.info("App Name: " + appname); @@ -68,16 +74,6 @@ public class GetdownApplet extends JApplet try { appdir = initGetdown(appbase, appname, imgpath); - // if a background image was specified, grabbit - try { - if (!StringUtil.isBlank(imgpath)) { - _bgimage = getImage(new URL(getDocumentBase(), imgpath)); - } - } catch (Exception e) { - Log.info("Failed to load background image [path=" + imgpath + "]."); - Log.logStackTrace(e); - } - // record a few things for posterity Log.info("------------------ VM Info ------------------"); Log.info("-- OS Name: " + System.getProperty("os.name")); @@ -103,6 +99,9 @@ public class GetdownApplet extends JApplet getContentPane().removeAll(); return getContentPane(); } + protected RotatingBackgrounds getBackground () { + return bgimages; + } protected void showContainer () { ((JPanel)getContentPane()).revalidate(); } @@ -115,10 +114,6 @@ public class GetdownApplet extends JApplet protected JApplet getApplet () { return GetdownApplet.this; } - protected Image getBackgroundImage () { - return _bgimage == null ? - super.getBackgroundImage() : _bgimage; - } protected void exit (int exitCode) { // don't exit as we're in an applet } @@ -132,6 +127,17 @@ public class GetdownApplet extends JApplet } } + public Image loadImage (String path) + { + try { + return getImage(new URL(getDocumentBase(), path)); + } catch (MalformedURLException e) { + Log.warning("Failed to load background image [path=" + path + "]."); + Log.logStackTrace(e); + return null; + } + } + @Override // documentation inherited public void start () { @@ -257,9 +263,6 @@ public class GetdownApplet extends JApplet /** Handles all the actual getting down. */ protected Getdown _getdown; - /** A background image drawn to make things look purdy. */ - protected Image _bgimage; - /** An error encountered during initialization. */ protected String _errmsg; } diff --git a/src/java/com/threerings/getdown/launcher/ImageLoader.java b/src/java/com/threerings/getdown/launcher/ImageLoader.java new file mode 100644 index 0000000..72e3fe5 --- /dev/null +++ b/src/java/com/threerings/getdown/launcher/ImageLoader.java @@ -0,0 +1,9 @@ +package com.threerings.getdown.launcher; + +import java.awt.Image; + +public interface ImageLoader +{ + + public Image loadImage (String path); +} diff --git a/src/java/com/threerings/getdown/launcher/RotatingBackgrounds.java b/src/java/com/threerings/getdown/launcher/RotatingBackgrounds.java new file mode 100644 index 0000000..33994b4 --- /dev/null +++ b/src/java/com/threerings/getdown/launcher/RotatingBackgrounds.java @@ -0,0 +1,98 @@ +package com.threerings.getdown.launcher; + +import java.awt.Image; + +import com.threerings.getdown.Log; + +public class RotatingBackgrounds +{ + + /** + * Creates a placeholder if there are no images. Just returns null from getImage every time. + */ + public RotatingBackgrounds () + { + makeEmpty(); + } + + /** Creates a single image background. */ + public RotatingBackgrounds (Image background) + { + percentages = new int[] { 0 }; + minDisplayTime = new int[] { 0 }; + images = new Image[] { background }; + } + + /** + * Create a sequence of images to be rotated through from backgrounds. + * + * Each String in backgrounds should be the path to the image, a semicolon, and the minimum + * amount of time to display the image in seconds. Each image will be active for an equal + * percentage of the download process, unless one hasn't been active for its minimum display + * time when the next should be shown. In that case, it's left up until its been there for its + * minimum display time and then the next one gets to come up. + */ + public RotatingBackgrounds (String[] backgrounds, ImageLoader loader) + { + percentages = new int[backgrounds.length]; + minDisplayTime = new int[backgrounds.length]; + images = new Image[backgrounds.length]; + for (int ii = 0; ii < backgrounds.length; ii++) { + String[] pieces = backgrounds[ii].split(";"); + if (pieces.length != 2) { + Log.warning("Unable to parse background image '" + backgrounds[ii] + "'"); + makeEmpty(); + return; + } + images[ii] = loader.loadImage(pieces[0]); + try { + minDisplayTime[ii] = Integer.parseInt(pieces[1]); + } catch (NumberFormatException e) { + Log.warning("Unable to parse background image display time '" + + backgrounds[ii] + "'"); + makeEmpty(); + return; + } + percentages[ii] = (int)((ii/(float)backgrounds.length) * 100); + } + } + + /** + * @return the image to display at the given progress or null if there aren't any. + */ + public Image getImage (int progress) + { + if (images.length == 0) { + return null; + } + long now = System.currentTimeMillis(); + if (current != images.length - 1 + && (current == -1 || (progress >= percentages[current + 1] && + (now - currentDisplayStart) / 1000 > minDisplayTime[current]))) { + current++; + currentDisplayStart = now; + } + return images[current]; + } + + protected void makeEmpty () + { + percentages = new int[] {}; + minDisplayTime = new int[] {}; + images = new Image[] {}; + } + + /** Time at which the currently displayed image was first displayed in millis. */ + protected long currentDisplayStart; + + /** The index of the currently displayed image or -1 if we haven't displayed any. */ + protected int current = -1; + + protected Image[] images; + + /** Percentage at which each image should be displayed. */ + protected int[] percentages; + + /** Time to show each image in seconds. */ + protected int[] minDisplayTime; +} diff --git a/src/java/com/threerings/getdown/launcher/StatusPanel.java b/src/java/com/threerings/getdown/launcher/StatusPanel.java index 1dd8bc9..ebd03bb 100644 --- a/src/java/com/threerings/getdown/launcher/StatusPanel.java +++ b/src/java/com/threerings/getdown/launcher/StatusPanel.java @@ -22,23 +22,21 @@ package com.threerings.getdown.launcher; import java.awt.Dimension; import java.awt.Font; -import java.awt.Graphics2D; import java.awt.Graphics; +import java.awt.Graphics2D; import java.awt.Image; import java.awt.Rectangle; - -import javax.swing.JComponent; - import java.text.MessageFormat; import java.util.MissingResourceException; import java.util.ResourceBundle; +import javax.swing.JComponent; + import com.samskivert.swing.Label; import com.samskivert.swing.util.SwingUtil; import com.samskivert.text.MessageUtil; import com.samskivert.util.StringUtil; import com.samskivert.util.Throttle; - import com.threerings.getdown.Log; import com.threerings.getdown.data.Application.UpdateInterface; @@ -52,16 +50,17 @@ public class StatusPanel extends JComponent _msgs = msgs; } - public void init (UpdateInterface ifc, Image bgimg, Image barimg) + public void init (UpdateInterface ifc, RotatingBackgrounds bg, Image barimg) { _ifc = ifc; - _bgimg = bgimg; - if (bgimg == null) { + _bg = bg; + Image img = _bg.getImage(_progress); + if (img == null) { Rectangle bounds = ifc.progress.union(ifc.status); bounds.grow(5, 5); _psize = bounds.getSize(); } else { - _psize = new Dimension(bgimg.getWidth(null), bgimg.getHeight(null)); + _psize = new Dimension(img.getWidth(null), img.getHeight(null)); } _barimg = barimg; } @@ -132,8 +131,9 @@ public class StatusPanel extends JComponent super.paintComponent(g); Graphics2D gfx = (Graphics2D)g; - if (_bgimg != null) { - gfx.drawImage(_bgimg, 0, 0, null); + Image img = _bg.getImage(_progress); + if (img != null) { + gfx.drawImage(img, 0, 0, null); } else { gfx.setColor(getBackground()); gfx.fillRect(0, 0, getWidth(), getHeight()); @@ -256,7 +256,8 @@ public class StatusPanel extends JComponent } } - protected Image _bgimg, _barimg; + protected Image _barimg; + protected RotatingBackgrounds _bg; protected Dimension _psize; protected ResourceBundle _msgs;