Merge branch 'JAL-1130' into develop
authorjprocter <jprocter@compbio.dundee.ac.uk>
Fri, 21 Sep 2012 16:26:54 +0000 (17:26 +0100)
committerjprocter <jprocter@compbio.dundee.ac.uk>
Fri, 21 Sep 2012 16:26:54 +0000 (17:26 +0100)
15 files changed:
build.xml
help/html/Jalview_Logo.png [new file with mode: 0644]
help/html/index.html
help/html/whatsNew.html
resources/images/Jalview_Logo.png [new file with mode: 0644]
resources/images/Jalview_Logo_small.png [new file with mode: 0644]
resources/images/logo_v2.jpeg [new file with mode: 0644]
resources/images/logo_v2_big.jpg [new file with mode: 0644]
resources/images/logo_v2_square.jpg [new file with mode: 0644]
src/jalview/gui/Desktop.java
src/jalview/gui/SplashScreen.java
src/jalview/gui/WebserviceInfo.java
src/jalview/jbgui/GWebserviceInfo.java
src/jalview/ws/AWSThread.java
src/jalview/ws/jws2/MsaWSThread.java

index 6e3a2f2..ee0542d 100755 (executable)
--- a/build.xml
+++ b/build.xml
                                <homepage href="http://www.jalview.org" />
                                <description>Jalview Multiple Alignment Editor</description>
                                <description kind="short">Jalview</description>
-                               <icon href="logo_big.gif" />
-                               <offline_allowed />
+                               <icon href="JalviewLogo_big.png" />
+                               <offline_allowed/>
                        </information>
                        <resources>
                                <j2se version="${j2sev}" initial_heap_size="10M"  />
                                <homepage href="http://www.jalview.org" />
                                <description>Jalview Multiple Alignment Editor</description>
                                <description kind="short">Jalview</description>
-                               <icon href="logo_big.gif" />
+                               <icon href="JalviewLogo_big.png" />
                                <offline_allowed />
                        </information>
                        <resources>
                                <homepage href="http://www.jalview.org" />
                                <description>Jalview Multiple Alignment Editor</description>
                                <description kind="short">Jalview</description>
-                               <icon href="logo_big.gif" />
+                               <icon href="JalviewLogo_big.png" />
                                <offline_allowed />
                        </information>
                        <resources>
diff --git a/help/html/Jalview_Logo.png b/help/html/Jalview_Logo.png
new file mode 100644 (file)
index 0000000..06429d9
Binary files /dev/null and b/help/html/Jalview_Logo.png differ
index cfa8cb3..c89bbc2 100755 (executable)
@@ -19,7 +19,7 @@
 <head><title>Jalview Documentation</title></head>
 
 <body>
-<IMG src="align.jpg"><font size="4">
+<IMG src="Jalview_Logo.png"><font size="4">
 <br><br>
 <strong>Jalview Documentation</strong></font>
 <br><br>
index f623685..7f1637c 100755 (executable)
                <strong>What's new ?</strong>
        </p>
        <p>
-               The Jalview 2.8 release features (tbc)
-               <br /> For full
-               details see the <a href="releases.html#Jalview2.7.1">Jalview 2.7.1
-                       release history</a>.
+       Jalview 2.8 includes a brand new logo, which you'll see in file browsers, splash screens, and also on the new look Jalview site.
        </p>
        <p>
-               <strong>Highlights in Jalview Desktop Version 2.7.1</strong>
+               In addition to our new look, Jalview 2.8 includes a number of new
+               features.. some of which have been in development since July 2010. The
+               highlights are below, and - as usual, for a comprehensive list, take a
+               look at the <a href="releases.html#Jalview2.8">Jalview 2.8 Release
+                       Notes</a>.
+       </p>
+       <p>
+               <strong>Highlights in Jalview Desktop Version 2.8</strong>
        </p>
        <ul>
 
diff --git a/resources/images/Jalview_Logo.png b/resources/images/Jalview_Logo.png
new file mode 100644 (file)
index 0000000..06429d9
Binary files /dev/null and b/resources/images/Jalview_Logo.png differ
diff --git a/resources/images/Jalview_Logo_small.png b/resources/images/Jalview_Logo_small.png
new file mode 100644 (file)
index 0000000..a0384da
Binary files /dev/null and b/resources/images/Jalview_Logo_small.png differ
diff --git a/resources/images/logo_v2.jpeg b/resources/images/logo_v2.jpeg
new file mode 100644 (file)
index 0000000..a37600c
Binary files /dev/null and b/resources/images/logo_v2.jpeg differ
diff --git a/resources/images/logo_v2_big.jpg b/resources/images/logo_v2_big.jpg
new file mode 100644 (file)
index 0000000..74615a4
Binary files /dev/null and b/resources/images/logo_v2_big.jpg differ
diff --git a/resources/images/logo_v2_square.jpg b/resources/images/logo_v2_square.jpg
new file mode 100644 (file)
index 0000000..3fff428
Binary files /dev/null and b/resources/images/logo_v2_square.jpg differ
index 5388605..d6ab3ae 100644 (file)
@@ -80,8 +80,10 @@ import javax.swing.JPanel;
 import javax.swing.JPopupMenu;
 import javax.swing.JProgressBar;
 import javax.swing.SwingUtilities;
+import javax.swing.event.HyperlinkEvent;
 import javax.swing.event.MenuEvent;
 import javax.swing.event.MenuListener;
+import javax.swing.event.HyperlinkEvent.EventType;
 
 /**
  * Jalview Desktop
@@ -1060,10 +1062,11 @@ public class Desktop extends jalview.jbgui.GDesktop implements
    */
   public void aboutMenuItem_actionPerformed(ActionEvent e)
   {
-    StringBuffer message = getAboutMessage(false);
-    JOptionPane.showInternalMessageDialog(Desktop.desktop,
-
-    message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
+//    StringBuffer message = getAboutMessage(false);
+//    JOptionPane.showInternalMessageDialog(Desktop.desktop,
+//
+//    message.toString(), "About Jalview", JOptionPane.INFORMATION_MESSAGE);
+    new Thread(new Runnable() { public void run() {new SplashScreen(true);}}).start();
   }
 
   public StringBuffer getAboutMessage(boolean shortv)
@@ -1072,7 +1075,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     message.append("<html>");
     if (shortv)
     {
-      message.append("<h1><strong>Jalview "
+      message.append("<h1><strong>Version: "
               + jalview.bin.Cache.getProperty("VERSION")
               + "</strong></h1><br>");
       message.append("<strong>Last Updated: <em>"
@@ -1083,7 +1086,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     else
     {
 
-      message.append("<strong>Jalview version "
+      message.append("<strong>Version "
               + jalview.bin.Cache.getProperty("VERSION")
               + "; last updated: "
               + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown"));
@@ -1107,7 +1110,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
         message.append("<div style=\"color: #FF0000;font-style: bold;\">");
       }
 
-      message.append("<br>!! Jalview version "
+      message.append("<br>!! Version "
               + jalview.bin.Cache.getDefault("LATEST_VERSION",
                       "..Checking..")
               + " is available for download from "
@@ -1124,7 +1127,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
                             "AUTHORNAMES",
                             "Jim Procter, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton")
             + "<br>Development managed by The Barton Group, University of Dundee, Scotland, UK.<br>"
-            + "<br>For help, see the FAQ at www.jalview.org and/or join the jalview-discuss@jalview.org mailing list"
+            + "<br>For help, see the FAQ at <a href=\"http://www.jalview.org\">www.jalview.org</a> and/or join the jalview-discuss@jalview.org mailing list"
             + "<br>If  you use Jalview, please cite:"
             + "<br>Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M. and Barton, G. J. (2009)"
             + "<br>Jalview Version 2 - a multiple sequence alignment editor and analysis workbench"
@@ -2574,5 +2577,33 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     return wsparamManager;
   }
 
+  /**
+   * static hyperlink handler proxy method for use by Jalview's internal windows 
+   * @param e
+   */
+  public static void hyperlinkUpdate(HyperlinkEvent e)
+  {
+    if (e.getEventType() == EventType.ACTIVATED)
+    {
+      String url=null;
+      try
+      {
+        url = e.getURL().toString();
+        Desktop.showUrl(url);
+      } catch (Exception x)
+      {
+        if (url!=null) { 
+          if (Cache.log!=null) { 
+            Cache.log.error("Couldn't handle string "+url+" as a URL.");
+          } else {
+            System.err.println("Couldn't handle string "+url+" as a URL.");
+          }
+        }
+        // ignore any exceptions due to dud links.
+      }
+
+    }    
+  }
+
 
 }
index 32c6aac..15914df 100755 (executable)
@@ -21,6 +21,8 @@ import java.awt.*;
 import java.awt.event.*;
 
 import javax.swing.*;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
 
 /**
  * DOCUMENT ME!
@@ -28,7 +30,7 @@ import javax.swing.*;
  * @author $author$
  * @version $Revision$
  */
-public class SplashScreen extends JPanel implements Runnable
+public class SplashScreen extends JPanel implements Runnable, HyperlinkListener
 {
   boolean visible = true;
 
@@ -49,18 +51,33 @@ public class SplashScreen extends JPanel implements Runnable
    */
   public SplashScreen()
   {
+    this(false);
+  }
+  private boolean interactiveDialog=false;
+  /**
+   * 
+   * @param interactive if true - an internal dialog is opened rather than a free-floating splash screen
+   */
+  public SplashScreen(boolean interactive)
+  {
+    this.interactiveDialog=interactive;
+    // show a splashscreen that will disapper
     Thread t = new Thread(this);
     t.start();
   }
 
+
   MouseAdapter closer = new MouseAdapter()
   {
     public void mousePressed(MouseEvent evt)
     {
       try
       {
-        visible = false;
-        closeSplash();
+        if (!interactiveDialog)
+        {
+          visible = false;
+          closeSplash();
+        }
       } catch (Exception ex)
       {
       }
@@ -76,7 +93,7 @@ public class SplashScreen extends JPanel implements Runnable
     addMouseListener(closer);
     try
     {
-      java.net.URL url = getClass().getResource("/images/logo.gif");
+      java.net.URL url = getClass().getResource("/images/Jalview_Logo.png");
 
       if (url != null)
       {
@@ -93,7 +110,7 @@ public class SplashScreen extends JPanel implements Runnable
 
     iframe = new JInternalFrame();
     iframe.setFrameIcon(null);
-    iframe.setClosable(false);
+    iframe.setClosable(interactiveDialog);
     this.setLayout(new BorderLayout());
     iframe.setContentPane(this);
     iframe.setLayer(JLayeredPane.PALETTE_LAYER);
@@ -101,7 +118,7 @@ public class SplashScreen extends JPanel implements Runnable
     Desktop.desktop.add(iframe);
     SplashImage splashimg = new SplashImage(image);
     iconimg.add(splashimg, BorderLayout.CENTER);
-    add(iconimg, BorderLayout.WEST);
+    add(iconimg, BorderLayout.NORTH);
     add(authlist, BorderLayout.CENTER);
     authlist.setEditable(false);
     authlist.addMouseListener(closer);
@@ -116,7 +133,7 @@ public class SplashScreen extends JPanel implements Runnable
   protected boolean refreshText()
   {
     String newtext = Desktop.instance.getAboutMessage(true).toString();
-    System.err.println("Text found: \n"+newtext+"\nEnd of newtext.");
+    //System.err.println("Text found: \n"+newtext+"\nEnd of newtext.");
     if (oldtext != newtext.length())
     {
       iframe.setVisible(false);
@@ -124,16 +141,17 @@ public class SplashScreen extends JPanel implements Runnable
       authlist=new JTextPane();
       authlist.setEditable(false);
       authlist.addMouseListener(closer);
+      authlist.addHyperlinkListener(this);
       authlist.setContentType("text/html");
       authlist.setText(newtext);
       authlist.setVisible(true);
       add(authlist, BorderLayout.CENTER);
-      iframe.pack();
-      iframe.setVisible(true);
       iframe.setBounds((int) ((Desktop.instance.getWidth() - 750) / 2),
               (int) ((Desktop.instance.getHeight() - 160) / 2), 750,
               iframe.getPreferredSize().height);
-      System.err.println("New preferred size: "+iframe.getPreferredSize().height);
+      //System.err.println("New preferred size: "+iframe.getPreferredSize().height);
+      iframe.validate();
+      iframe.setVisible(true);
 
       return true;
     }
@@ -151,21 +169,30 @@ public class SplashScreen extends JPanel implements Runnable
 
     while (visible)
     {
+      iframe.repaint();
       try
       {
         Thread.sleep(500);
       } catch (Exception ex)
       {
       }
-
-      if (((System.currentTimeMillis() / 1000) - startTime) > 5)
+      
+      if (!interactiveDialog && ((System.currentTimeMillis() / 1000) - startTime) > 5)
       {
         visible = false;
       }
 
       if (visible && refreshText())
       {
-          repaint();
+//          if (interactiveDialog) {
+            iframe.repaint();
+//          } else {
+//            iframe.repaint();
+//          };
+      }
+      if (interactiveDialog)
+      {
+        return;
       }
     }
 
@@ -206,7 +233,7 @@ public class SplashScreen extends JPanel implements Runnable
 
       if (image != null)
       {
-        g.drawImage(image, 4, (getHeight() - image.getHeight(this)) / 2,
+        g.drawImage(image, (getWidth() - image.getWidth(this)) / 2, (getHeight() - image.getHeight(this)) / 2,
                 this);
       }
     }
@@ -251,4 +278,10 @@ public class SplashScreen extends JPanel implements Runnable
      * += fontSize + 4); }
      */
   }
+  @Override
+  public void hyperlinkUpdate(HyperlinkEvent e)
+  {
+    Desktop.hyperlinkUpdate(e);
+    
+  }
 }
\ No newline at end of file
index 9f8a8a8..69fb44c 100755 (executable)
@@ -41,7 +41,7 @@ import jalview.ws.WSClientI;
  * @version $Revision$
  */
 public class WebserviceInfo extends GWebserviceInfo implements
-        HyperlinkListener
+        HyperlinkListener, IProgressIndicator
 {
 
   /** Job is Queued */
@@ -296,7 +296,7 @@ public class WebserviceInfo extends GWebserviceInfo implements
     this.title = title;
     setInfoText(info);
 
-    java.net.URL url = getClass().getResource("/images/logo.gif");
+    java.net.URL url = getClass().getResource("/images/Jalview_Logo_small.png");
     image = java.awt.Toolkit.getDefaultToolkit().createImage(url);
 
     MediaTracker mt = new MediaTracker(this);
@@ -799,9 +799,10 @@ public class WebserviceInfo extends GWebserviceInfo implements
 
       if (image != null)
       {
-        g.rotate(Math.toRadians(angle), 28, 28);
+        int x=image.getWidth(this)/2,y=image.getHeight(this)/2;
+        g.rotate(Math.toRadians(angle), 10+x, 10+y);
         g.drawImage(image, 10, 10, this);
-        g.rotate(-Math.toRadians(angle), 28, 28);
+        g.rotate(-Math.toRadians(angle), 10+x, 10+y);
       }
     }
 
@@ -822,21 +823,109 @@ public class WebserviceInfo extends GWebserviceInfo implements
 
   public void hyperlinkUpdate(HyperlinkEvent e)
   {
-    if (e.getEventType() == EventType.ACTIVATED)
+    Desktop.hyperlinkUpdate(e);
+  }
+
+  // methods for implementing IProgressIndicator
+  // need to refactor to a reusable stub class
+  Hashtable progressBars, progressBarHandlers;
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
+   */
+  @Override
+  public void setProgressBar(String message, long id)
+  {
+    if (progressBars == null)
     {
-      String url=null;
-      try
+      progressBars = new Hashtable();
+      progressBarHandlers = new Hashtable();
+    }
+
+    JPanel progressPanel;
+    Long lId = new Long(id);
+    GridLayout layout = (GridLayout) statusPanel.getLayout();
+    if (progressBars.get(lId) != null)
+    {
+      progressPanel = (JPanel) progressBars.get(new Long(id));
+      statusPanel.remove(progressPanel);
+      progressBars.remove(lId);
+      progressPanel = null;
+      if (message != null)
       {
-        url = e.getURL().toString();
-        Desktop.showUrl(url);
-      } catch (Exception x)
+        statusBar.setText(message);
+      }
+      if (progressBarHandlers.contains(lId))
       {
-        if (url!=null) { 
-          Cache.log.error("Couldn't handle string "+url+" as a URL.");
-        }
-        // ignore any exceptions due to dud links.
+        progressBarHandlers.remove(lId);
       }
+      layout.setRows(layout.getRows() - 1);
+    }
+    else
+    {
+      progressPanel = new JPanel(new BorderLayout(10, 5));
+
+      JProgressBar progressBar = new JProgressBar();
+      progressBar.setIndeterminate(true);
 
+      progressPanel.add(new JLabel(message), BorderLayout.WEST);
+      progressPanel.add(progressBar, BorderLayout.CENTER);
+
+      layout.setRows(layout.getRows() + 1);
+      statusPanel.add(progressPanel);
+
+      progressBars.put(lId, progressPanel);
+    }
+    // update GUI
+    // setMenusForViewport();
+    validate();
+  }
+
+  @Override
+  public void registerHandler(final long id,
+          final IProgressIndicatorHandler handler)
+  {
+    if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
+    {
+      throw new Error(
+              "call setProgressBar before registering the progress bar's handler.");
+    }
+    progressBarHandlers.put(new Long(id), handler);
+    final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
+    if (handler.canCancel())
+    {
+      JButton cancel = new JButton("Cancel");
+      final IProgressIndicator us = this;
+      cancel.addActionListener(new ActionListener()
+      {
+
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          handler.cancelActivity(id);
+          us.setProgressBar(
+                  "Cancelled "
+                          + ((JLabel) progressPanel.getComponent(0))
+                                  .getText(), id);
+        }
+      });
+      progressPanel.add(cancel, BorderLayout.EAST);
+    }
+  }
+
+  /**
+   *
+   * @return true if any progress bars are still active
+   */
+  @Override
+  public boolean operationInProgress()
+  {
+    if (progressBars != null && progressBars.size() > 0)
+    {
+      return true;
     }
+    return false;
   }
 }
index 5d6b6eb..00806ed 100755 (executable)
@@ -52,6 +52,9 @@ public class GWebserviceInfo extends JPanel
   public JButton mergeResults = new JButton();
 
   GridBagLayout gridBagLayout1 = new GridBagLayout();
+  
+  public JPanel statusPanel = new JPanel(new GridLayout());
+  public JLabel statusBar = new JLabel();
 
   /**
    * Creates a new GWebserviceInfo object.
@@ -110,6 +113,8 @@ public class GWebserviceInfo extends JPanel
     buttonPanel.add(cancel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
             GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(
                     19, 6, 16, 4), 0, 0));
+    this.add(statusPanel, java.awt.BorderLayout.SOUTH);
+    statusPanel.add(statusBar, null);
   }
 
   /**
index 7300462..eea756e 100644 (file)
@@ -163,30 +163,7 @@ public abstract class AWSThread extends Thread
         jstate.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
       }
       // Decide on overall state based on collected jobs[] states
-      if (jstate.running > 0)
-      {
-        wsInfo.setStatus(WebserviceInfo.STATE_RUNNING);
-      }
-      else if (jstate.queuing > 0)
-      {
-        wsInfo.setStatus(WebserviceInfo.STATE_QUEUING);
-      }
-      else
-      {
-        jobComplete = true;
-        if (jstate.finished > 0)
-        {
-          wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK);
-        }
-        else if (jstate.error > 0)
-        {
-          wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
-        }
-        else if (jstate.serror > 0)
-        {
-          wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
-        }
-      }
+      updateGlobalStatus(jstate);
       if (!jobComplete)
       {
         try
@@ -214,6 +191,34 @@ public abstract class AWSThread extends Thread
     }
   }
 
+  protected void updateGlobalStatus(JobStateSummary jstate)
+  {
+    if (jstate.running > 0)
+    {
+      wsInfo.setStatus(WebserviceInfo.STATE_RUNNING);
+    }
+    else if (jstate.queuing > 0)
+    {
+      wsInfo.setStatus(WebserviceInfo.STATE_QUEUING);
+    }
+    else
+    {
+      jobComplete = true;
+      if (jstate.finished > 0)
+      {
+        wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK);
+      }
+      else if (jstate.error > 0)
+      {
+        wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
+      }
+      else if (jstate.serror > 0)
+      {
+        wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
+      }
+    }
+  }
+
   public AWSThread()
   {
     super();
index 65873f2..6ef07c6 100644 (file)
@@ -516,7 +516,7 @@ class MsaWSThread extends AWS2Thread implements WSClientI
           try
           {
             boolean cancelledJob = server.cancelJob(jobs[job].getJobId());
-            if (cancelledJob || true)
+            if (true) // cancelledJob || true)
             {
               // CANCELLED_JOB
               // if the Jaba server indicates the job can't be cancelled, its
@@ -594,9 +594,12 @@ class MsaWSThread extends AWS2Thread implements WSClientI
               .pullExecStatistics(j.getJobId(), lastchunk);
       if (chunk != null)
       {
-        changed=chunk.getChunk().length()>0;
+        changed|=chunk.getChunk().length()>0;
         response.append(chunk.getChunk());
         lastchunk = chunk.getNextPosition();
+        try {
+          Thread.sleep(50);
+        } catch (InterruptedException x){};
       }
       ;
     } while (lastchunk >= 0 && j.getLastChunk() != lastchunk);
@@ -726,6 +729,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
 
   public void parseResult()
   {
+    long progbar=System.currentTimeMillis();
+    wsInfo.setProgressBar("Collecting job results.", progbar);
     int results = 0; // number of result sets received
     JobStateSummary finalState = new JobStateSummary();
     try
@@ -735,12 +740,16 @@ class MsaWSThread extends AWS2Thread implements WSClientI
         MsaWSJob msjob = ((MsaWSJob) jobs[j]);
         if (jobs[j].isFinished() && msjob.alignment == null)
         {
+          int nunchanged=3,nexcept=3;
           boolean jpchanged=false,jpex=false;
           do {
             try
             {
               jpchanged = updateJobProgress(msjob);
               jpex=false;
+              if (jpchanged) {
+                nexcept=3;
+              }
             } catch (Exception e)
             {
               
@@ -748,26 +757,24 @@ class MsaWSThread extends AWS2Thread implements WSClientI
                       .warn("Exception when retrieving remaining Job progress data for job "
                               + msjob.getJobId() + " on server " + WsUrl);
               e.printStackTrace();
-              if (jpex) {
-                // give up polling after two consecutive exceptions
-                jpchanged=false;
-              } else {
-                jpchanged=true;
-              }
+              nexcept--;
+              nunchanged=3;
               // set flag remember that we've had an exception.
               jpex=true;
+              jpchanged=false;
             }
-            if (jpchanged)
+            if (!jpchanged)
             {
               try
               {
-                Thread.sleep(jpex ? 400 : 200); // wait a bit longer if we experienced an exception.
+                Thread.sleep(jpex ? 2400 : 1200); // wait a bit longer if we experienced an exception.
               } catch (Exception ex)
               {
               }
               ;
-            }
-          } while (jpchanged);
+              nunchanged--;
+            } 
+          } while (nunchanged>0 && nexcept>0);
           
           if (Cache.log.isDebugEnabled())
           {
@@ -787,6 +794,9 @@ class MsaWSThread extends AWS2Thread implements WSClientI
             Cache.log
                     .debug("Results not available for finished job - marking as broken job.",
                             e);
+            msjob.jobProgress
+                    .append("\nResult not available. Probably due to invalid input or parameter settings. Server error message below:\n\n"
+                            + e.getLocalizedMessage());
             msjob.setjobStatus(JobStatus.FAILED);
           } catch (Exception e)
           {
@@ -843,9 +853,10 @@ class MsaWSThread extends AWS2Thread implements WSClientI
     }
     else
     {
-      wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
       wsInfo.setFinishedNoResults();
     }
+    updateGlobalStatus(finalState);
+    wsInfo.setProgressBar(null, progbar);
   }
 
   void displayResults(boolean newFrame)