Merge branch 'develop' into task/JAL-4001_migrate_googleanalytics_to_GA4
authorBen Soares <b.soares@dundee.ac.uk>
Thu, 8 Jun 2023 07:16:06 +0000 (08:16 +0100)
committerBen Soares <b.soares@dundee.ac.uk>
Thu, 8 Jun 2023 07:16:06 +0000 (08:16 +0100)
18 files changed:
help/help/html/features/clarguments-reference.html
src/jalview/bin/Commands.java
src/jalview/bin/Jalview.java
src/jalview/bin/argparser/Arg.java
src/jalview/bin/argparser/ArgParser.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/AppJmol.java
src/jalview/gui/Desktop.java
src/jalview/gui/ImageExporter.java
src/jalview/gui/PCAPanel.java
src/jalview/gui/TreePanel.java
src/jalview/io/HTMLOutput.java
src/jalview/io/exceptions/ImageOutputException.java [new file with mode: 0644]
src/jalview/jbgui/GAlignFrame.java
src/jalview/workers/AlignCalcManager.java
test/jalview/bin/CommandsTest.java
test/jalview/bin/CommandsTest2.java

index 0221a67..dd0bd52 100644 (file)
     </tr>
 
     <tr valign="top">
-    <td><code>&#8209;&#8209;title&nbsp;<em>"string""</em></code></td>
+    <td><code>&#8209;&#8209;title&nbsp;<em>"string"</em></code></td>
     <td>Specifies the title for the open alignment window as <em>string</em>.</td>
     <td></td>
     <td align="center">&#x2713;</td>
 
     <tr valign="top">
     <td><code>&#8209;&#8209;colour&nbsp;<em>name</em></code></td>
-    <td>Applies the colour scheme <em>name</em> to the open alignment window.  Valid values for <em>name</em> are:
+    <td>Applies the colour scheme <em>name</em> to the open alignment window.  Valid values for <em>name</em> include:
     <br/>
     <code>clustal</code>,
     <br/>
     <code>t-coffee-scores</code>,
     <br/>
     <code>sequence-id</code>.
+    <br/>
+    <br/>
+    Names of user defined schemes will also work, and jalview colour scheme specifications like:
+    <br/>
+       <code>&#8209;&#8209;colour "D,E=red; K,R,H=0022FF; C,c=yellow"</code>
     <td></td>
     <td align="center">&#x2713;</td>
     </tr>
index 30fdc30..bcf231e 100644 (file)
@@ -44,6 +44,9 @@ import jalview.io.FileLoader;
 import jalview.io.HtmlSvgOutput;
 import jalview.io.IdentifyFile;
 import jalview.io.NewickFile;
+import jalview.io.exceptions.ImageOutputException;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ColourSchemeProperty;
 import jalview.structure.StructureImportSettings.TFType;
 import jalview.structure.StructureSelectionManager;
 import jalview.util.FileUtils;
@@ -100,6 +103,16 @@ public class Commands
         theseArgsWereParsed &= processLinked(id);
         processGroovyScript(id);
         boolean processLinkedOkay = theseArgsWereParsed;
+        
+        // wait around until alignFrame isn't busy
+        AlignFrame af=afMap.get(id);
+        while (af!=null && af.getViewport().isCalcInProgress())
+        {
+          try {
+            Thread.sleep(25);
+          } catch (Exception q) {};
+        }
+        
         theseArgsWereParsed &= processImages(id);
         if (processLinkedOkay)
           theseArgsWereParsed &= processOutput(id);
@@ -107,7 +120,7 @@ public class Commands
         // close ap
         if (avm.getBoolean(Arg.CLOSE))
         {
-          AlignFrame af = afMap.get(id);
+          af = afMap.get(id);
           if (af != null)
           {
             af.closeMenuItem_actionPerformed(true);
@@ -249,7 +262,15 @@ public class Commands
                   Arg.COLOUR, sv, null, "DEFAULT_COLOUR_PROT", "");
           if ("" != colour)
           {
-            af.changeColour_actionPerformed(colour);
+            ColourSchemeI cs = ColourSchemeProperty.getColourScheme(
+                    af.getViewport(), af.getViewport().getAlignment(), colour);
+            
+            if (cs==null && !"None".equals(colour))
+            {
+              Console.warn("Couldn't parse '"+colour+"' as a colourscheme.");
+            } else {
+              af.changeColour(cs);
+            }
             Jalview.testoutput(argParser, Arg.COLOUR, "zappo", colour);
           }
 
@@ -608,8 +629,15 @@ public class Commands
               if (sview instanceof AppJmol)
               {
                 AppJmol jmol = (AppJmol) sview;
-                jmol.makePDBImage(structureImageFile, imageType, renderer,
+                try { 
+                  jmol.makePDBImage(structureImageFile, imageType, renderer,
                         userBis);
+                }
+                catch (ImageOutputException ioexc)
+                {
+                  Console.warn("Unexpected error whilst exporting image to "+structureImageFile,ioexc);
+                }
+
               }
               break;
             default:
@@ -717,7 +745,7 @@ public class Commands
         Cache.setProperty("EXPORT_EMBBED_BIOJSON", "false");
 
         Console.info("Writing " + file);
-
+        try {
         switch (type)
         {
 
@@ -738,6 +766,7 @@ public class Commands
           break;
 
         case "biojs":
+          Console.debug("Creating BioJS MSA Viwer HTML file: " + fileName);
           try
           {
             BioJsHTMLOutput.refreshVersionInfo(
@@ -748,17 +777,16 @@ public class Commands
           }
           BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
           bjs.exportHTML(fileName);
-          Console.debug("Creating BioJS MSA Viwer HTML file: " + fileName);
           break;
 
         case "eps":
-          af.createEPS(file, name);
           Console.debug("Creating EPS file: " + fileName);
+          af.createEPS(file, name);
           break;
 
         case "imagemap":
-          af.createImageMap(file, name);
           Console.debug("Creating ImageMap file: " + fileName);
+          af.createImageMap(file, name);
           break;
 
         default:
@@ -766,6 +794,9 @@ public class Commands
                   + "' not known. Ignoring");
           break;
         }
+        } catch (Exception ioex) {
+          Console.warn("Unexpected error during export",ioex);
+        }
       }
     }
     return true;
index 6952cfb..675a758 100755 (executable)
@@ -91,6 +91,7 @@ import jalview.io.FileLoader;
 import jalview.io.HtmlSvgOutput;
 import jalview.io.IdentifyFile;
 import jalview.io.NewickFile;
+import jalview.io.exceptions.ImageOutputException;
 import jalview.io.gff.SequenceOntologyFactory;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemeProperty;
@@ -1005,9 +1006,7 @@ public class Jalview
             ex.printStackTrace(System.err);
           }
         }
-        // TODO - load PDB structure(s) to alignment JAL-629
-        // (associate with identical sequence in alignment, or a specified
-        // sequence)
+        
         if (groovyscript != null)
         {
           // Execute the groovy script after we've done all the rendering stuff
@@ -1021,100 +1020,109 @@ public class Jalview
         String imageName = "unnamed.png";
         while (aparser.getSize() > 1)
         {
-          String outputFormat = aparser.nextValue();
-          file = aparser.nextValue();
-
-          if (outputFormat.equalsIgnoreCase("png"))
-          {
-            af.createPNG(new File(file));
-            imageName = (new File(file)).getName();
-            System.out.println("Creating PNG image: " + file);
-            continue;
-          }
-          else if (outputFormat.equalsIgnoreCase("svg"))
-          {
-            File imageFile = new File(file);
-            imageName = imageFile.getName();
-            af.createSVG(imageFile);
-            System.out.println("Creating SVG image: " + file);
-            continue;
-          }
-          else if (outputFormat.equalsIgnoreCase("html"))
+          try
           {
-            File imageFile = new File(file);
-            imageName = imageFile.getName();
-            HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
-            htmlSVG.exportHTML(file);
+            String outputFormat = aparser.nextValue();
+            file = aparser.nextValue();
 
-            System.out.println("Creating HTML image: " + file);
-            continue;
-          }
-          else if (outputFormat.equalsIgnoreCase("biojsmsa"))
-          {
-            if (file == null)
+            if (outputFormat.equalsIgnoreCase("png"))
             {
-              System.err.println("The output html file must not be null");
-              return;
+              System.out.println("Creating PNG image: " + file);
+              af.createPNG(new File(file));
+              imageName = (new File(file)).getName();
+              continue;
             }
-            try
+            else if (outputFormat.equalsIgnoreCase("svg"))
             {
-              BioJsHTMLOutput.refreshVersionInfo(
-                      BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
-            } catch (URISyntaxException e)
+              System.out.println("Creating SVG image: " + file);
+              File imageFile = new File(file);
+              imageName = imageFile.getName();
+              af.createSVG(imageFile);
+              continue;
+            }
+            else if (outputFormat.equalsIgnoreCase("html"))
             {
-              e.printStackTrace();
+              File imageFile = new File(file);
+              imageName = imageFile.getName();
+              HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
+
+              System.out.println("Creating HTML image: " + file);
+              htmlSVG.exportHTML(file);
+              continue;
             }
-            BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
-            bjs.exportHTML(file);
-            System.out
-                    .println("Creating BioJS MSA Viwer HTML file: " + file);
-            continue;
-          }
-          else if (outputFormat.equalsIgnoreCase("imgMap"))
-          {
-            af.createImageMap(new File(file), imageName);
-            System.out.println("Creating image map: " + file);
-            continue;
-          }
-          else if (outputFormat.equalsIgnoreCase("eps"))
-          {
-            File outputFile = new File(file);
-            System.out.println(
-                    "Creating EPS file: " + outputFile.getAbsolutePath());
-            af.createEPS(outputFile);
-            continue;
-          }
-          FileFormatI outFormat = null;
-          try
-          {
-            outFormat = FileFormats.getInstance().forName(outputFormat);
-          } catch (Exception formatP)
-          {
-            System.out.println("Couldn't parse " + outFormat
-                    + " as a valid Jalview format string.");
-          }
-          if (outFormat != null)
-          {
-            if (!outFormat.isWritable())
+            else if (outputFormat.equalsIgnoreCase("biojsmsa"))
+            {
+              if (file == null)
+              {
+                System.err.println("The output html file must not be null");
+                return;
+              }
+              try
+              {
+                BioJsHTMLOutput.refreshVersionInfo(
+                        BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
+              } catch (URISyntaxException e)
+              {
+                e.printStackTrace();
+              }
+              BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
+              System.out.println(
+                      "Creating BioJS MSA Viwer HTML file: " + file);
+              bjs.exportHTML(file);
+              continue;
+            }
+            else if (outputFormat.equalsIgnoreCase("imgMap"))
             {
+              System.out.println("Creating image map: " + file);
+              af.createImageMap(new File(file), imageName);
+              continue;
+            }
+            else if (outputFormat.equalsIgnoreCase("eps"))
+            {
+              File outputFile = new File(file);
               System.out.println(
-                      "This version of Jalview does not support alignment export as "
-                              + outputFormat);
+                      "Creating EPS file: " + outputFile.getAbsolutePath());
+              af.createEPS(outputFile);
+              continue;
+            }
+
+            FileFormatI outFormat = null;
+            try
+            {
+              outFormat = FileFormats.getInstance().forName(outputFormat);
+            } catch (Exception formatP)
+            {
+              System.out.println("Couldn't parse " + outFormat
+                      + " as a valid Jalview format string.");
             }
-            else
+            if (outFormat != null)
             {
-              af.saveAlignment(file, outFormat);
-              if (af.isSaveAlignmentSuccessful())
+              if (!outFormat.isWritable())
               {
-                System.out.println("Written alignment in "
-                        + outFormat.getName() + " format to " + file);
+                System.out.println(
+                        "This version of Jalview does not support alignment export as "
+                                + outputFormat);
               }
               else
               {
-                System.out.println("Error writing file " + file + " in "
-                        + outFormat.getName() + " format!!");
+                af.saveAlignment(file, outFormat);
+                if (af.isSaveAlignmentSuccessful())
+                {
+                  System.out.println("Written alignment in "
+                          + outFormat.getName() + " format to " + file);
+                }
+                else
+                {
+                  System.out.println("Error writing file " + file + " in "
+                          + outFormat.getName() + " format!!");
+                }
               }
             }
+          } catch (ImageOutputException ioexc)
+          {
+            System.out.println(
+                    "Unexpected error whilst exporting image to " + file);
+            ioexc.printStackTrace();
           }
 
         }
@@ -1799,8 +1807,14 @@ public class Jalview
     }
   }
 
-  /*
-   * testoutput for string values
+  /******************************
+   * 
+   * TEST OUTPUT METHODS
+   * 
+   ******************************/
+  /**
+   * method for reporting string values parsed/processed during tests
+   * 
    */
   protected static void testoutput(ArgParser ap, Arg a, String s1,
           String s2)
@@ -1824,6 +1838,10 @@ public class Jalview
     testoutput(true, a, s1, s2);
   }
 
+  /**
+   * method for reporting string values parsed/processed during tests
+   */
+
   protected static void testoutput(BootstrapArgs bsa, Arg a, String s1,
           String s2)
   {
@@ -1848,6 +1866,9 @@ public class Jalview
     testoutput(true, a, s1, s2);
   }
 
+  /**
+   * report value set for string values parsed/processed during tests
+   */
   private static void testoutput(boolean yes, Arg a, String s1, String s2)
   {
     if (yes && ((s1 == null && s2 == null)
index f7588cb..2f25978 100644 (file)
@@ -84,7 +84,7 @@ public enum Arg
           "Specifies the title for the open alignment window as string.",
           Opt.STRING, Opt.LINKED),
   COLOUR(Type.OPENING, "color", // being a bit soft on the Americans!
-          "Applies the colour scheme to the open alignment window. Valid values are:\n"
+          "Applies the colour scheme to the open alignment window. Valid values include:\n"
                   + "clustal,\n" + "blosum62,\n" + "pc-identity,\n"
                   + "zappo,\n" + "taylor,\n" + "gecos-flower,\n"
                   + "gecos-blossom,\n" + "gecos-sunset,\n"
@@ -93,7 +93,11 @@ public enum Arg
                   + "turn-propensity,\n" + "buried-index,\n"
                   + "nucleotide,\n" + "nucleotide-ambiguity,\n"
                   + "purine-pyrimidine,\n" + "rna-helices,\n"
-                  + "t-coffee-scores,\n" + "sequence-id.",
+                  + "t-coffee-scores,\n" + "sequence-id.\n"
+                  +"\n"
+                  + "Names of user defined colourschemes will also work,\n"
+                 +"and jalview colourscheme specifications like\n"
+                  +"--colour=\"D,E=red; K,R,H=0022FF; C,c=yellow\"",
           Opt.STRING, Opt.LINKED, Opt.ALLOWALL),
   FEATURES(Type.OPENING, "Add a feature file or URL to the open alignment.",
           Opt.STRING, Opt.LINKED, Opt.MULTI, Opt.ALLOWSUBSTITUTIONS),
index 1558065..907b1fa 100644 (file)
@@ -52,77 +52,111 @@ public class ArgParser
 
   protected static final String NEGATESTRING = "no";
 
-  // the default linked id prefix used for no id (not even square braces)
+  /**
+   * the default linked id prefix used for no id (ie when not even square braces
+   * are provided)
+   */
   protected static final String DEFAULTLINKEDIDPREFIX = "JALVIEW:";
 
-  // the linkedId string used to match all linkedIds seen so far
+  /**
+   * the linkedId string used to match all linkedIds seen so far
+   */
   protected static final String MATCHALLLINKEDIDS = "*";
 
-  // the linkedId string used to match all of the last --open'ed linkedIds
+  /**
+   * the linkedId string used to match all of the last --open'ed linkedIds
+   */
   protected static final String MATCHOPENEDLINKEDIDS = "open*";
 
-  // the counter added to the default linked id prefix
+  /**
+   * the counter added to the default linked id prefix
+   */
   private int defaultLinkedIdCounter = 0;
 
-  // the substitution string used to use the defaultLinkedIdCounter
+  /**
+   * the substitution string used to use the defaultLinkedIdCounter
+   */
   private static final String DEFAULTLINKEDIDCOUNTER = "{}";
 
-  // the counter added to the default linked id prefix. NOW using
-  // linkedIdAutoCounter
-  // private int openLinkedIdCounter = 0;
-
-  // the linked id prefix used for --open files. NOW the same as DEFAULT
+  /**
+   * the linked id prefix used for --open files. NOW the same as DEFAULT
+   */
   protected static final String OPENLINKEDIDPREFIX = DEFAULTLINKEDIDPREFIX;
 
-  // the counter used for {n} substitutions
+  /**
+   * the counter used for {n} substitutions
+   */
   private int linkedIdAutoCounter = 0;
 
-  // the linked id substitution string used to increment the idCounter (and use
-  // the incremented value)
+  /**
+   * the linked id substitution string used to increment the idCounter (and use
+   * the incremented value)
+   */
   private static final String INCREMENTLINKEDIDAUTOCOUNTER = "{++n}";
 
-  // the linked id substitution string used to use the idCounter
+  /**
+   * the linked id substitution string used to use the idCounter
+   */
   private static final String LINKEDIDAUTOCOUNTER = "{n}";
 
-  // the linked id substitution string used to use the filename extension of
-  // --append
-  // or --open
+  /**
+   * the linked id substitution string used to use the filename extension of
+   * --append or --open
+   */
   private static final String LINKEDIDEXTENSION = "{extension}";
 
-  // the linked id substitution string used to use the base filename of --append
-  // or --open
+  /**
+   * the linked id substitution string used to use the base filename of --append
+   */
+  /** or --open */
   private static final String LINKEDIDBASENAME = "{basename}";
 
-  // the linked id substitution string used to use the dir path of --append
-  // or --open
+  /**
+   * the linked id substitution string used to use the dir path of --append or
+   * --open
+   */
   private static final String LINKEDIDDIRNAME = "{dirname}";
 
-  // the current argfile
+  /**
+   * the current argfile
+   */
   private String argFile = null;
 
-  // the linked id substitution string used to use the dir path of the latest
-  // --argfile name
+  /**
+   * the linked id substitution string used to use the dir path of the latest
+   */
+  /** --argfile name */
   private static final String ARGFILEBASENAME = "{argfilebasename}";
 
-  // the linked id substitution string used to use the dir path of the latest
-  // --argfile name
+  /**
+   * the linked id substitution string used to use the dir path of the latest
+   * --argfile name
+   */
   private static final String ARGFILEDIRNAME = "{argfiledirname}";
 
-  // flag to say whether {n} subtitutions in output filenames should be made.
-  // Turn on and off with --substitutions and --nosubstitutions
-  // Start with it on
+  /**
+   * flag to say whether {n} subtitutions in output filenames should be made.
+   * Turn on and off with --substitutions and --nosubstitutions Start with it on
+   */
   private boolean substitutions = true;
 
-  // flag to say whether the default linkedId is the current default linked id
-  // or ALL linkedIds
+  /**
+   * flag to say whether the default linkedId is the current default linked id
+   *
+   * or ALL linkedIds
+   */
   private boolean allLinkedIds = false;
 
-  // flag to say whether the default linkedId is the current default linked id
-  // or OPENED linkedIds
+  /**
+   * flag to say whether the default linkedId is the current default linked id
+   * or OPENED linkedIds
+   */
   private boolean openedLinkedIds = false;
 
-  // flag to say whether the structure arguments should be applied to all
-  // structures with this linked id
+  /**
+   * flag to say whether the structure arguments should be applied to all
+   * structures with this linked id
+   */
   private boolean allStructures = false;
 
   protected static final Map<String, Arg> argMap;
@@ -925,15 +959,19 @@ public class ArgParser
     FIRST, BEFORE, AFTER
   }
 
-  // get from following Arg of type a or subval of same name (lowercase)
+  /**
+   * get from following Arg of type a or subval of same name (lowercase)
+   */
   public static String getValueFromSubValOrArg(ArgValuesMap avm,
           ArgValue av, Arg a, SubVals sv)
   {
     return getFromSubValArgOrPref(avm, av, a, sv, null, null, null);
   }
 
-  // get from following Arg of type a or subval key or preference pref or
-  // default def
+  /**
+   * get from following Arg of type a or subval key or preference pref or
+   * default def
+   */
   public static String getFromSubValArgOrPref(ArgValuesMap avm, ArgValue av,
           Arg a, SubVals sv, String key, String pref, String def)
   {
@@ -941,8 +979,10 @@ public class ArgParser
             def);
   }
 
-  // get from following(AFTER), first occurence of (FIRST) or previous (BEFORE)
-  // Arg of type a or subval key or preference pref or default def
+  /**
+   * get from following(AFTER), first occurence of (FIRST) or previous (BEFORE)
+   * Arg of type a or subval key or preference pref or default def
+   */
   public static String getFromSubValArgOrPref(ArgValuesMap avm, Arg a,
           Position pos, ArgValue av, SubVals sv, String key, String pref,
           String def)
@@ -1071,7 +1111,9 @@ public class ArgParser
 
   // the following methods look for the "*" linkedId and add the argvalue to all
   // linkedId ArgValues if it does.
-  // This version inserts the subvals sv into all created values
+  /**
+   * This version inserts the subvals sv into all created values
+   */
   private void addValue(String linkedId, Type type, ArgValues avs,
           SubVals sv, String v, int argIndex, boolean doSubs)
   {
@@ -1119,21 +1161,32 @@ public class ArgParser
             doSubs);
   }
 
-  /*
+  /**
    * The following operations look for the "*" and "open*" linkedIds and add the
-   * argvalue to all appropriate linkedId ArgValues if it does.
-   * If subvals are supplied, they are inserted into all new set values.
+   * argvalue to all appropriate linkedId ArgValues if it does. If subvals are
+   * supplied, they are inserted into all new set values.
    * 
-   * @param op The ArgParser.Op operation
-   * @param linkedId The String linkedId from the ArgValuesMap
-   * @param type The Arg.Type to attach to this ArgValue
-   * @param avs The ArgValues for this linkedId
-   * @param sv Use these SubVals on the ArgValue
-   * @param merge Merge the SubVals with any existing on the value.  False will replace unless sv is null
-   * @param v The value of the ArgValue (may contain subvals).
-   * @param b The boolean value of the ArgValue.
-   * @param argIndex The argIndex for the ArgValue.
-   * @param doSubs Whether to perform substitutions on the subvals and value.
+   * @param op
+   *          The ArgParser.Op operation
+   * @param linkedId
+   *          The String linkedId from the ArgValuesMap
+   * @param type
+   *          The Arg.Type to attach to this ArgValue
+   * @param avs
+   *          The ArgValues for this linkedId
+   * @param sv
+   *          Use these SubVals on the ArgValue
+   * @param merge
+   *          Merge the SubVals with any existing on the value. False will
+   *          replace unless sv is null
+   * @param v
+   *          The value of the ArgValue (may contain subvals).
+   * @param b
+   *          The boolean value of the ArgValue.
+   * @param argIndex
+   *          The argIndex for the ArgValue.
+   * @param doSubs
+   *          Whether to perform substitutions on the subvals and value.
    */
   private void argValueOperation(Op op, String linkedId, Type type,
           ArgValues avs, SubVals sv, boolean merge, String v, boolean b,
index 77c0238..ab705c2 100644 (file)
@@ -140,6 +140,7 @@ import jalview.io.JnetAnnotationMaker;
 import jalview.io.NewickFile;
 import jalview.io.ScoreMatrixFile;
 import jalview.io.TCoffeeScoreFile;
+import jalview.io.exceptions.ImageOutputException;
 import jalview.io.vcf.VCFLoader;
 import jalview.jbgui.GAlignFrame;
 import jalview.project.Jalview2XML;
@@ -1455,34 +1456,74 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   protected void htmlMenuItem_actionPerformed(ActionEvent e)
   {
     HtmlSvgOutput htmlSVG = new HtmlSvgOutput(alignPanel);
-    htmlSVG.exportHTML(null);
+    try {
+      htmlSVG.exportHTML(null);
+    } catch (ImageOutputException x) {
+      // report problem to console and raise dialog
+    }
   }
 
   @Override
   public void bioJSMenuItem_actionPerformed(ActionEvent e)
   {
     BioJsHTMLOutput bjs = new BioJsHTMLOutput(alignPanel);
+    try {
     bjs.exportHTML(null);
+  } catch (ImageOutputException x) {
+    // report problem to console and raise dialog
+  }
   }
 
   public void createImageMap(File file, String image)
   {
+    try {
     alignPanel.makePNGImageMap(file, image);
+    } catch (ImageOutputException x) {
+      // report problem to console and raise dialog
+    }
   }
 
+  @Override
+  public void createPNG_actionPerformed(ActionEvent e) {
+    try{
+      createPNG(null);
+    } catch (ImageOutputException ioex)
+    {
+      // raise dialog, and report via console
+    }
+  }
+  @Override
+  public void createEPS_actionPerformed(ActionEvent e) {
+    try{
+      createEPS(null);
+    } catch (ImageOutputException ioex)
+    {
+      // raise dialog, and report via console
+    }
+    
+  }
+  @Override
+  public void createSVG_actionPerformed(ActionEvent e) {
+    try{
+      createSVG(null);
+    } catch (ImageOutputException ioex)
+    {
+      // raise dialog, and report via console
+    }
+    
+  }
   /**
    * Creates a PNG image of the alignment and writes it to the given file. If
    * the file is null, the user is prompted to choose a file.
    * 
    * @param f
    */
-  @Override
-  public void createPNG(File f)
+  public void createPNG(File f) throws ImageOutputException
   {
     createPNG(f, null, BitmapImageSizing.nullBitmapImageSizing());
   }
 
-  public void createPNG(File f, String renderer, BitmapImageSizing userBis)
+  public void createPNG(File f, String renderer, BitmapImageSizing userBis) throws ImageOutputException
   {
     alignPanel.makeAlignmentImage(TYPE.PNG, f, renderer, userBis);
   }
@@ -1493,13 +1534,12 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    * 
    * @param f
    */
-  @Override
-  public void createEPS(File f)
+  public void createEPS(File f)  throws ImageOutputException
   {
     createEPS(f, null);
   }
 
-  public void createEPS(File f, String renderer)
+  public void createEPS(File f, String renderer) throws ImageOutputException
   {
     alignPanel.makeAlignmentImage(TYPE.EPS, f, renderer);
   }
@@ -1510,13 +1550,12 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    * 
    * @param f
    */
-  @Override
-  public void createSVG(File f)
+  public void createSVG(File f)  throws ImageOutputException
   {
     createSVG(f, null);
   }
 
-  public void createSVG(File f, String renderer)
+  public void createSVG(File f, String renderer) throws ImageOutputException
   {
     alignPanel.makeAlignmentImage(TYPE.SVG, f, renderer);
   }
index 7befa20..3dfb510 100644 (file)
@@ -58,6 +58,7 @@ import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.gui.ImageExporter.ImageWriterI;
 import jalview.io.HTMLOutput;
+import jalview.io.exceptions.ImageOutputException;
 import jalview.jbgui.GAlignmentPanel;
 import jalview.math.AlignmentDimension;
 import jalview.schemes.ResidueProperties;
@@ -1174,7 +1175,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
     return (w > 0 ? w : calculateIdWidth().width);
   }
 
-  void makeAlignmentImage(ImageMaker.TYPE type, File file, String renderer)
+  void makeAlignmentImage(ImageMaker.TYPE type, File file, String renderer) throws ImageOutputException
   {
     makeAlignmentImage(type, file, renderer,
             BitmapImageSizing.nullBitmapImageSizing());
@@ -1190,7 +1191,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
    * @param bitmapscale
    */
   void makeAlignmentImage(ImageMaker.TYPE type, File file, String renderer,
-          BitmapImageSizing userBis)
+          BitmapImageSizing userBis) throws ImageOutputException
   {
     final int borderBottomOffset = 5;
 
@@ -1265,7 +1266,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
 
   }
 
-  public void makePNGImageMap(File imgMapFile, String imageName)
+  public void makePNGImageMap(File imgMapFile, String imageName) throws ImageOutputException
   {
     // /////ONLY WORKS WITH NON WRAPPED ALIGNMENTS
     // ////////////////////////////////////////////
@@ -1390,7 +1391,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
 
       } catch (Exception ex)
       {
-        ex.printStackTrace();
+        throw new ImageOutputException("couldn't write ImageMap due to unexpected error",ex);
       }
     } // /////////END OF IMAGE MAP
 
index b7bac37..1758b5b 100644 (file)
@@ -46,6 +46,7 @@ import jalview.datamodel.StructureViewerModel;
 import jalview.datamodel.StructureViewerModel.StructureData;
 import jalview.gui.ImageExporter.ImageWriterI;
 import jalview.gui.StructureViewer.ViewerType;
+import jalview.io.exceptions.ImageOutputException;
 import jalview.structure.StructureCommand;
 import jalview.structures.models.AAStructureBindingModel;
 import jalview.util.BrowserLauncher;
@@ -426,12 +427,16 @@ public class AppJmol extends StructureViewerBase
   @Override
   public void makePDBImage(ImageMaker.TYPE type)
   {
+    try {
     makePDBImage(null, type, null,
             BitmapImageSizing.nullBitmapImageSizing());
+    } catch (ImageOutputException ioex) {
+      Console.error("Unexpected error whilst writing "+type.toString(),ioex);
+    }
   }
 
   public void makePDBImage(File file, ImageMaker.TYPE type, String renderer,
-          BitmapImageSizing userBis)
+          BitmapImageSizing userBis) throws ImageOutputException
   {
     int width = getWidth();
     int height = getHeight();
@@ -469,7 +474,9 @@ public class AppJmol extends StructureViewerBase
             .toLowerCase(Locale.ROOT);
     ImageExporter exporter = new ImageExporter(writer,
             getProgressIndicator(), type, getTitle());
+    
     exporter.doExport(file, this, width, height, view, renderer, userBis);
+    
   }
 
   @Override
index 44bf61e..cfc56b2 100644 (file)
@@ -121,6 +121,7 @@ import jalview.io.FormatAdapter;
 import jalview.io.IdentifyFile;
 import jalview.io.JalviewFileChooser;
 import jalview.io.JalviewFileView;
+import jalview.io.exceptions.ImageOutputException;
 import jalview.jbgui.GSplitFrame;
 import jalview.jbgui.GStructureViewer;
 import jalview.project.Jalview2XML;
@@ -3158,7 +3159,11 @@ public class Desktop extends jalview.jbgui.GDesktop
     String title = "View of desktop";
     ImageExporter exporter = new ImageExporter(writer, null, TYPE.EPS,
             title);
-    exporter.doExport(of, this, width, height, title);
+    try {
+      exporter.doExport(of, this, width, height, title);
+    } catch (ImageOutputException ioex) {
+      jalview.bin.Console.error("Unexpected error whilst writing Jalview desktop snapshot as EPS",ioex);
+    }
   }
 
   /**
@@ -3598,4 +3603,17 @@ public class Desktop extends jalview.jbgui.GDesktop
       jalview.bin.Console.debug(Cache.getStackTraceString(e));
     }
   }
+
+  /**
+   * closes the current instance window, disposes and forgets about it.
+   */
+  public static void closeDesktop()
+  {
+    if (Desktop.instance != null) {
+      Desktop.instance.closeAll_actionPerformed(null);
+      Desktop.instance.setVisible(false);
+      Desktop.instance.dispose();
+      Desktop.instance = null;
+    }
+  }
 }
index 32704d6..f337b39 100644 (file)
@@ -29,6 +29,7 @@ import jalview.bin.Cache;
 import jalview.bin.Jalview;
 import jalview.io.JalviewFileChooser;
 import jalview.io.JalviewFileView;
+import jalview.io.exceptions.ImageOutputException;
 import jalview.util.ImageMaker;
 import jalview.util.ImageMaker.TYPE;
 import jalview.util.MessageManager;
@@ -103,14 +104,14 @@ public class ImageExporter
    *          what the image is of e.g. Tree, Alignment
    */
   public void doExport(File file, Component parent, int width, int height,
-          String imageSource)
+          String imageSource) throws ImageOutputException
   {
     doExport(file, parent, width, height, imageSource, null,
             BitmapImageSizing.nullBitmapImageSizing());
   }
 
   public void doExport(File file, Component parent, int width, int height,
-          String imageSource, String renderer, BitmapImageSizing userBis)
+          String imageSource, String renderer, BitmapImageSizing userBis) throws ImageOutputException
   {
     final long messageId = System.currentTimeMillis();
     setStatus(
@@ -220,8 +221,8 @@ public class ImageExporter
               messageId);
     } catch (Exception e)
     {
-      System.out.println(String.format("Error creating %s file: %s", type,
-              e.toString()));
+      jalview.bin.Console.error(String.format("Error creating %s file: %s", type,
+              e.toString()),e);
       setStatus(MessageManager.formatMessage("info.error_creating_file",
               type), messageId);
     }
index 26db8c3..211c370 100644 (file)
@@ -49,6 +49,7 @@ import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.SequenceI;
 import jalview.gui.ImageExporter.ImageWriterI;
 import jalview.gui.JalviewColourChooser.ColourChooserListener;
+import jalview.io.exceptions.ImageOutputException;
 import jalview.jbgui.GPCAPanel;
 import jalview.math.RotatableMatrix.Axis;
 import jalview.util.ImageMaker;
@@ -438,7 +439,11 @@ public class PCAPanel extends GPCAPanel
     };
     String pca = MessageManager.getString("label.pca");
     ImageExporter exporter = new ImageExporter(writer, null, type, pca);
-    exporter.doExport(null, this, width, height, pca);
+    try {
+      exporter.doExport(null, this, width, height, pca);
+    } catch (ImageOutputException ioex) {
+      Console.error("Unexpected error whilst writing "+type.toString(),ioex);
+    }
   }
 
   @Override
index 4737235..5ccd68d 100755 (executable)
@@ -69,6 +69,7 @@ import jalview.gui.ImageExporter.ImageWriterI;
 import jalview.io.JalviewFileChooser;
 import jalview.io.JalviewFileView;
 import jalview.io.NewickFile;
+import jalview.io.exceptions.ImageOutputException;
 import jalview.jbgui.GTreePanel;
 import jalview.util.ImageMaker.TYPE;
 import jalview.util.MessageManager;
@@ -757,8 +758,12 @@ public class TreePanel extends GTreePanel
     String tree = MessageManager.getString("label.tree");
     ImageExporter exporter = new ImageExporter(writer, null, imageFormat,
             tree);
+    try {
     exporter.doExport(null, this, width, height,
             tree.toLowerCase(Locale.ROOT));
+    } catch (ImageOutputException ioex) {
+      Console.error("Unexpected error whilst writing "+imageFormat.toString(),ioex);
+    }
   }
 
   /**
index ed80eb9..d659e2a 100644 (file)
@@ -34,6 +34,7 @@ import jalview.datamodel.AlignExportSettingsAdapter;
 import jalview.datamodel.AlignmentExportData;
 import jalview.gui.AlignmentPanel;
 import jalview.gui.IProgressIndicator;
+import jalview.io.exceptions.ImageOutputException;
 import jalview.util.MessageManager;
 
 public abstract class HTMLOutput implements Runnable
@@ -302,12 +303,12 @@ public abstract class HTMLOutput implements Runnable
     return generatedFile;
   }
 
-  public void exportHTML(String outputFile)
+  public void exportHTML(String outputFile) throws ImageOutputException
   {
     exportHTML(outputFile, null);
   }
 
-  public void exportHTML(String outputFile, String renderer)
+  public void exportHTML(String outputFile, String renderer) throws ImageOutputException
   {
     setProgressMessage(MessageManager.formatMessage(
             "status.exporting_alignment_as_x_file", getDescription()));
@@ -358,5 +359,5 @@ public abstract class HTMLOutput implements Runnable
   }
 
   // used to pass an option such as render to run
-  public abstract void run(String string);
+  public abstract void run(String string) throws ImageOutputException;
 }
\ No newline at end of file
diff --git a/src/jalview/io/exceptions/ImageOutputException.java b/src/jalview/io/exceptions/ImageOutputException.java
new file mode 100644 (file)
index 0000000..bf06494
--- /dev/null
@@ -0,0 +1,36 @@
+package jalview.io.exceptions;
+
+/**
+ * wrapper for passing error messages and exceptions back to UI when image io goes wrong
+ * @author jprocter
+ *
+ */
+public class ImageOutputException extends Exception
+{
+
+  public ImageOutputException()
+  {
+  }
+
+  public ImageOutputException(String message)
+  {
+    super(message);
+  }
+
+  public ImageOutputException(Throwable cause)
+  {
+    super(cause);
+  }
+
+  public ImageOutputException(String message, Throwable cause)
+  {
+    super(message, cause);
+  }
+
+  public ImageOutputException(String message, Throwable cause,
+          boolean enableSuppression, boolean writableStackTrace)
+  {
+    super(message, cause, enableSuppression, writableStackTrace);
+  }
+
+}
index f6ab8c9..c0cdfee 100755 (executable)
@@ -57,6 +57,7 @@ import jalview.bin.Cache;
 import jalview.gui.JvSwingUtils;
 import jalview.gui.Preferences;
 import jalview.io.FileFormats;
+import jalview.io.exceptions.ImageOutputException;
 import jalview.schemes.ResidueColourScheme;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
@@ -1081,7 +1082,7 @@ public class GAlignFrame extends JInternalFrame
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        createPNG(null);
+        createPNG_actionPerformed(e);
       }
     });
     createPNG.setActionCommand(
@@ -1113,7 +1114,7 @@ public class GAlignFrame extends JInternalFrame
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        createEPS(null);
+        createEPS_actionPerformed(e);
       }
     });
 
@@ -1123,7 +1124,7 @@ public class GAlignFrame extends JInternalFrame
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        createSVG(null);
+        createSVG_actionPerformed(e);
       }
     });
 
@@ -1975,6 +1976,24 @@ public class GAlignFrame extends JInternalFrame
     // selectMenu.add(listenToViewSelections);
   }
 
+  protected void createPNG_actionPerformed(ActionEvent object)
+  {
+    // TODO Auto-generated method stub
+    
+  }
+
+  protected void createEPS_actionPerformed(ActionEvent object)
+  {
+    // TODO Auto-generated method stub
+    
+  }
+
+  protected void createSVG_actionPerformed(ActionEvent object)
+  {
+    // TODO Auto-generated method stub
+    
+  }
+
   protected void copyHighlightedColumns_actionPerformed(
           ActionEvent actionEvent)
   {
@@ -2468,9 +2487,6 @@ public class GAlignFrame extends JInternalFrame
   {
   }
 
-  public void createPNG(java.io.File f)
-  {
-  }
 
   protected void font_actionPerformed(ActionEvent e)
   {
@@ -2485,14 +2501,6 @@ public class GAlignFrame extends JInternalFrame
 
   }
 
-  public void createEPS(java.io.File f)
-  {
-  }
-
-  public void createSVG(java.io.File f)
-  {
-
-  }
 
   protected void loadTreeMenuItem_actionPerformed(ActionEvent e)
   {
index 08ef3a2..d81db8c 100644 (file)
@@ -200,11 +200,20 @@ public class AlignCalcManager implements AlignCalcManagerI
   @Override
   public boolean isWorking()
   {
+    boolean working=false;
     synchronized (inProgress)
     {
       // System.err.println("isWorking "+hashCode());
-      return inProgress.size() > 0;
+      working |= inProgress.size() > 0;
     }
+    synchronized (updating)
+    {
+      for (List<AlignCalcWorkerI> workers : updating.values())
+      {
+        working |= workers.size() > 0;
+      }
+    }
+    return working;
   }
 
   @Override
index b4c927b..61892df 100644 (file)
@@ -49,8 +49,15 @@ public class CommandsTest
   @AfterMethod(alwaysRun = true)
   public void tearDown()
   {
-    if (Desktop.instance != null)
-      Desktop.instance.closeAll_actionPerformed(null);
+    Desktop.closeDesktop();
+  }
+  
+  public static void callJalviewMain(String[] args) {
+    if (Jalview.getInstance()!=null) {
+      Jalview.getInstance().doMain(args);
+    } else {
+      Jalview.main(args);
+    }
   }
 
   /* --setprops is currently disabled so this test won't work
@@ -71,7 +78,7 @@ public class CommandsTest
           int numFrames, String[] sequences)
   {
     String[] args = (cmdLine + " --gui").split("\\s+");
-    Jalview.main(args);
+    callJalviewMain(args);
     Commands cmds = Jalview.getInstance().getCommands();
     Assert.assertNotNull(cmds);
     Assert.assertEquals(cmds.commandArgsProvided(), cmdArgs,
@@ -111,7 +118,7 @@ public class CommandsTest
   {
     cleanupFiles(filenames);
     String[] args = (cmdLine + " --gui").split("\\s+");
-    Jalview.main(args);
+    callJalviewMain(args);
     Commands cmds = Jalview.getInstance().getCommands();
     Assert.assertNotNull(cmds);
     File lastFile = null;
@@ -139,7 +146,7 @@ public class CommandsTest
   {
     cleanupFiles(filenames);
     String[] args = (cmdLine + " --gui").split("\\s+");
-    Jalview.main(args);
+    callJalviewMain(args);
     Commands cmds = Jalview.getInstance().getCommands();
     Assert.assertNotNull(cmds);
     File lastFile = null;
@@ -297,7 +304,7 @@ public class CommandsTest
           String[] nonfilenames)
   {
     String[] args = (cmdLine + " --gui").split("\\s+");
-    Jalview.main(args);
+    callJalviewMain(args);
     Commands cmds = Jalview.getInstance().getCommands();
     Assert.assertNotNull(cmds);
     for (String filename : filenames)
index 0a47700..0c2071a 100644 (file)
@@ -51,8 +51,7 @@ public class CommandsTest2
   @AfterMethod(alwaysRun = true)
   public void tearDown()
   {
-    if (Desktop.instance != null)
-      Desktop.instance.closeAll_actionPerformed(null);
+    Desktop.closeDesktop();
   }
 
   @Test(
@@ -65,7 +64,7 @@ public class CommandsTest2
   {
     String[] args = cmdLine.split("\\s+");
 
-    Jalview.main(args);
+    CommandsTest.callJalviewMain(args);
     try
     {
       // sleep for slow build server to open annotations and viewer windows