Merge branch 'develop' into feature/JAL-3187linkedFeatures
[jalview.git] / getdown / src / getdown / launcher / src / main / java / com / threerings / getdown / launcher / Getdown.java
index 539b47e..01bf370 100644 (file)
@@ -9,6 +9,7 @@ import java.awt.BorderLayout;
 import java.awt.Container;
 import java.awt.Dimension;
 import java.awt.EventQueue;
+import java.awt.Graphics;
 import java.awt.GraphicsEnvironment;
 import java.awt.Image;
 import java.awt.event.ActionEvent;
@@ -32,6 +33,7 @@ import javax.swing.AbstractAction;
 import javax.swing.JButton;
 import javax.swing.JFrame;
 import javax.swing.JLayeredPane;
+import javax.swing.JPanel;
 
 import com.samskivert.swing.util.SwingUtil;
 import com.threerings.getdown.data.*;
@@ -229,6 +231,9 @@ public abstract class Getdown extends Thread
         Config config = _app.init(true);
         if (preloads) doPredownloads(_app.getResources());
         _ifc = new Application.UpdateInterface(config);
+        if (_status != null) {
+          _status.setAppbase(_app.getAppbase());
+        }
     }
 
     /**
@@ -497,6 +502,19 @@ public abstract class Getdown extends Thread
             throw new IOException("m.java_download_failed");
         }
 
+        // on Windows, if the local JVM is in use, we will not be able to replace it with an
+        // updated JVM; we detect this by attempting to rename the java.dll to its same name, which
+        // will fail on Windows for in use files; hackery!
+        File javaLocalDir = new File(_app.getAppDir(), LaunchUtil.LOCAL_JAVA_DIR+File.separator);
+        File javaDll = new File(javaLocalDir, "bin" + File.separator + "java.dll");
+        if (javaDll.exists()) {
+            if (!javaDll.renameTo(javaDll)) {
+                log.info("Cannot update local Java VM as it is in use.");
+                return;
+            }
+            log.info("Can update local Java VM as it is not in use.");
+        }
+
         reportTrackingEvent("jvm_start", -1);
 
         updateStatus("m.downloading_java");
@@ -555,7 +573,7 @@ public abstract class Getdown extends Thread
             // show the patch notes button, if applicable
             if (!StringUtil.isBlank(_ifc.patchNotesUrl)) {
                 createInterfaceAsync(false);
-                EventQueue.invokeLater(new Runnable() {
+                EQinvoke(new Runnable() {
                     public void run () {
                         _patchNotes.setVisible(true);
                     }
@@ -687,7 +705,7 @@ public abstract class Getdown extends Thread
                 } else {
                     proc = _app.createProcess(false);
                 }
-
+                
                 // close standard in to avoid choking standard out of the launched process
                 proc.getInputStream().close();
                 // close standard out, since we're not going to write to anything to it anyway
@@ -716,6 +734,9 @@ public abstract class Getdown extends Thread
                 }
             }
 
+            //_container.setVisible(true);
+            //_container.validate();
+
             // if we have a UI open and we haven't been around for at least 5 seconds (the default
             // for min_show_seconds), don't stick a fork in ourselves straight away but give our
             // lovely user a chance to see what we're doing
@@ -748,9 +769,10 @@ public abstract class Getdown extends Thread
         if (_silent || (_container != null && !reinit)) {
             return;
         }
-
-        EventQueue.invokeLater(new Runnable() {
+        
+        EQinvoke (new Runnable() {
             public void run () {
+               
                 if (_container == null || reinit) {
                     if (_container == null) {
                         _container = createContainer();
@@ -759,6 +781,49 @@ public abstract class Getdown extends Thread
                     }
                     configureContainer();
                     _layers = new JLayeredPane();
+                    
+                    
+                    
+                    // added in the instant display of a splashscreen
+                    try {
+                      readConfig(false);
+                      Graphics g = _container.getGraphics();
+                      BufferedImage iBgImage = loadImage(_ifc.instantBackgroundImage);
+                      boolean ibg = true;
+                      if (iBgImage == null) {
+                         iBgImage = loadImage(_ifc.backgroundImage);
+                         ibg = false;
+                      }
+                      if (iBgImage != null) {
+                                                 final BufferedImage bgImage = iBgImage;
+                                                 int bwidth = bgImage.getWidth();
+                                                 int bheight = bgImage.getHeight();
+                                                 
+                                                 log.info("Displaying instant background image", ibg?"instant_background_image":"background_image");
+
+                                                 instantSplashPane = new JPanel() {
+                                                       @Override
+                                                       protected void paintComponent(Graphics g)
+                                                       {
+                                                         super.paintComponent(g);
+                                                         // attempt to draw a background image...
+                                                         if (bgImage != null) {
+                                                               g.drawImage(bgImage, 0, 0, this);
+                                                         }
+                                                       }
+                                                 };
+
+                                                 instantSplashPane.setSize(bwidth,bheight);
+                                                 instantSplashPane.setPreferredSize(new Dimension(bwidth,bheight));
+
+                                                 _layers.add(instantSplashPane, Integer.valueOf(1));
+                                                 
+                                                 _container.setPreferredSize(new Dimension(bwidth,bheight));
+                      }
+                    } catch (Exception e) {
+                      log.warning("Failed to set instant background image", "ibg", _ifc.instantBackgroundImage);
+                    }
+                    
                     _container.add(_layers, BorderLayout.CENTER);
                     _patchNotes = new JButton(new AbstractAction(_msgs.getString("m.patch_notes")) {
                         @Override public void actionPerformed (ActionEvent event) {
@@ -768,12 +833,14 @@ public abstract class Getdown extends Thread
                     _patchNotes.setFont(StatusPanel.FONT);
                     _layers.add(_patchNotes);
                     _status = new StatusPanel(_msgs);
-                    _layers.add(_status);
+                    setStatusAsync("m.initialising", 0, -1L, true);
+                    //_layers.add(_status, Integer.valueOf(2));
                     initInterface();
                 }
                 showContainer();
             }
         });
+        
     }
 
     /**
@@ -790,6 +857,7 @@ public abstract class Getdown extends Thread
         _status.init(_ifc, _background, getProgressImage());
         Dimension size = _status.getPreferredSize();
         _status.setSize(size);
+        //_status.updateStatusLabel();
         _layers.setPreferredSize(size);
 
         _patchNotes.setBounds(_ifc.patchNotes.x, _ifc.patchNotes.y,
@@ -804,13 +872,12 @@ public abstract class Getdown extends Thread
 
     protected RotatingBackgrounds getBackground ()
     {
-        if (_ifc.rotatingBackgrounds != null) {
+        if (_ifc.rotatingBackgrounds != null && _ifc.rotatingBackgrounds.size() > 0) {
             if (_ifc.backgroundImage != null) {
                 log.warning("ui.background_image and ui.rotating_background were both specified. " +
                             "The background image is being used.");
             }
-            return new RotatingBackgrounds(loadImage(_ifc.backgroundImage));
-            //return new RotatingBackgrounds(_ifc.rotatingBackgrounds, _ifc.errorBackground, Getdown.this);
+            return new RotatingBackgrounds(_ifc.rotatingBackgrounds, _ifc.errorBackground, Getdown.this);
         } else if (_ifc.backgroundImage != null) {
             return new RotatingBackgrounds(loadImage(_ifc.backgroundImage));
         } else {
@@ -891,9 +958,10 @@ public abstract class Getdown extends Thread
             createInterfaceAsync(false);
         }
 
-        EventQueue.invokeLater(new Runnable() {
+        EQinvoke(new Runnable() {
             public void run () {
-                if (_status == null) {
+
+               if (_status == null) {
                     if (message != null) {
                         log.info("Dropping status '" + message + "'.");
                     }
@@ -906,9 +974,19 @@ public abstract class Getdown extends Thread
                     _status.setProgress(0, -1L);
                 } else if (percent >= 0) {
                     _status.setProgress(percent, remaining);
+                } else {
+                       //_status.setStatus("m.initialising", false);
                 }
+                
             }
         });
+        
+        if (_status != null && ! _addedStatusLayer) {
+               _layers.add(_status, Integer.valueOf(2));
+               _addedStatusLayer = true;
+               initInterface();
+        }
+        
     }
 
     protected void reportTrackingEvent (String event, int progress)
@@ -1037,30 +1115,59 @@ public abstract class Getdown extends Thread
             setStatusAsync(null, stepToGlobalPercent(percent), -1L, false);
         }
     };
-
+    
+    // Asynchronous or synchronous progress updates
+    protected void EQinvoke(Runnable r) {
+      
+      try {
+        readConfig(false);
+      } catch (Exception e) {
+        log.warning("Could't read config when invoking GUI action", "Exception", e.getMessage());
+      }
+      if (_ifc != null && (_shownContainer?_ifc.progressSyncAfterShown:_ifc.progressSync)) {
+        try {
+          EventQueue.invokeAndWait(r);
+          //r.run();
+        } catch (Exception e) {
+          log.warning("Tried to invokeAndWait but couldn't. Going to invokeLater instead", "Exception", e.getMessage());
+          EventQueue.invokeLater(r);
+        }
+      } else {
+        EventQueue.invokeLater(r);
+        //r.run();
+      }
+      
+      //try { Thread.sleep(500); } catch (Exception e) {}
+      
+    }
+    
     protected Application _app;
     protected Application.UpdateInterface _ifc = new Application.UpdateInterface(Config.EMPTY);
 
     protected ResourceBundle _msgs;
     protected Container _container;
     protected JLayeredPane _layers;
+    protected JPanel instantSplashPane;
     protected StatusPanel _status;
     protected JButton _patchNotes;
     protected AbortPanel _abort;
     protected RotatingBackgrounds _background;
 
+    protected boolean _addedStatusLayer;
     protected boolean _dead;
     protected boolean _silent;
     protected boolean _launchInSilent;
     protected boolean _noUpdate;
     protected long _startup;
-
     protected Set<Resource> _toInstallResources;
     protected boolean _readyToInstall;
 
     protected boolean _enableTracking = true;
     protected int _reportedProgress = 0;
 
+    protected boolean _shownContainer;
+
     /** Number of minutes to wait after startup before beginning any real heavy lifting. */
     protected int _delay;