JAL-629 Add --renderer arg/subval for vector output and fixed annotation renderer...
authorBen Soares <b.soares@dundee.ac.uk>
Tue, 2 May 2023 11:29:55 +0000 (12:29 +0100)
committerBen Soares <b.soares@dundee.ac.uk>
Tue, 2 May 2023 11:29:55 +0000 (12:29 +0100)
12 files changed:
src/jalview/bin/Commands.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/AnnotationPanel.java
src/jalview/gui/ImageExporter.java
src/jalview/gui/LineartOptions.java
src/jalview/gui/Preferences.java
src/jalview/io/BioJsHTMLOutput.java
src/jalview/io/HTMLOutput.java
src/jalview/io/HtmlSvgOutput.java

index f33202d..90eb45c 100644 (file)
@@ -2,6 +2,7 @@ package jalview.bin;
 
 import java.io.File;
 import java.io.IOException;
+import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -31,6 +32,7 @@ import jalview.gui.StructureChooser;
 import jalview.gui.StructureViewer;
 import jalview.gui.StructureViewer.ViewerType;
 import jalview.io.AppletFormatAdapter;
+import jalview.io.BioJsHTMLOutput;
 import jalview.io.DataSourceType;
 import jalview.io.FileFormat;
 import jalview.io.FileFormatException;
@@ -87,14 +89,7 @@ public class Commands
       {
         ArgValuesMap avm = argParser.getLinkedArgs(id);
         theseArgsWereParsed = true;
-        if (id == null)
-        {
-          theseArgsWereParsed &= processUnlinked(id);
-        }
-        else
-        {
-          theseArgsWereParsed &= processLinked(id);
-        }
+        theseArgsWereParsed &= processLinked(id);
         theseArgsWereParsed &= processImages(id);
 
         // close ap
@@ -252,8 +247,8 @@ public class Commands
           af.getCurrentView().setWrapAlignment(wrap);
 
           // colour aligment?
-          String colour = ArgParser.getFromSubValArgOrPref(avm, Arg.COLOUR,
-                  sv, null, "DEFAULT_COLOUR_PROT", "");
+          String colour = ArgParser.getFromSubValArgOrPref(avm, av,
+                  Arg.COLOUR, sv, null, "DEFAULT_COLOUR_PROT", "");
 
           if ("" != colour)
           {
@@ -261,8 +256,8 @@ public class Commands
           }
 
           // change alignment frame title
-          String title = ArgParser.getFromSubValArgOrPref(avm, Arg.TITLE,
-                  sv, null, null, null);
+          String title = ArgParser.getFromSubValArgOrPref(avm, av,
+                  Arg.TITLE, sv, null, null, null);
           if (title != null)
             af.setTitle(title);
 
@@ -589,13 +584,14 @@ public class Commands
         String type = "png"; // default
         String fileName = subVal.getContent();
         File file = new File(fileName);
-        if (subVal.has("type"))
-        {
-          type = subVal.get("type");
-        }
-        else if (fileName != null)
+        String renderer = ArgParser.getValueFromSubValOrArg(avm, av,
+                Arg.RENDERER, subVal);
+        if (renderer == null)
+          renderer = "text";
+        type = ArgParser.getValueFromSubValOrArg(avm, av, Arg.TYPE, subVal);
+        if (type == null && fileName != null)
         {
-          for (String ext : new String[] { "svg", "png", "html" })
+          for (String ext : new String[] { "svg", "png", "html", "eps" })
           {
             if (fileName.toLowerCase(Locale.ROOT).endsWith("." + ext))
             {
@@ -609,19 +605,37 @@ public class Commands
 
         switch (type)
         {
+
         case "svg":
           Console.debug("Outputting type '" + type + "' to " + fileName);
-          af.createSVG(file);
+          af.createSVG(file, renderer);
           break;
+
         case "png":
           Console.debug("Outputting type '" + type + "' to " + fileName);
           af.createPNG(file);
           break;
+
         case "html":
           Console.debug("Outputting type '" + type + "' to " + fileName);
           HtmlSvgOutput htmlSVG = new HtmlSvgOutput(af.alignPanel);
-          htmlSVG.exportHTML(fileName);
+          htmlSVG.exportHTML(fileName, renderer);
+          break;
+
+        case "biojs":
+          try
+          {
+            BioJsHTMLOutput.refreshVersionInfo(
+                    BioJsHTMLOutput.BJS_TEMPLATES_LOCAL_DIRECTORY);
+          } catch (URISyntaxException e)
+          {
+            e.printStackTrace();
+          }
+          BioJsHTMLOutput bjs = new BioJsHTMLOutput(af.alignPanel);
+          bjs.exportHTML(fileName);
+          Console.debug("Creating BioJS MSA Viwer HTML file: " + fileName);
           break;
+
         default:
           Console.warn(Arg.IMAGE.argString() + " type '" + type
                   + "' not known. Ignoring");
@@ -677,9 +691,6 @@ public class Commands
             else
             {
               structfile = likelyStructure.getValue();
-              Console.debug(
-                      "##### Comparing closest previous structure argument '"
-                              + structfile + "'");
             }
           }
         }
index 6c3e6ae..ca6cc77 100644 (file)
@@ -13,9 +13,9 @@ public enum Arg
   COLOUR, FEATURES, GROOVY, GROUPS, HEADLESS, JABAWS, DISPLAY, GUI, NEWS,
   SORTBYTREE, USAGESTATS, APPEND, OPEN, PROPS, QUESTIONNAIRE, SETPROP, TREE,
   VDOC, VSESS, OUTPUT, SSANNOTATIONS, NOTEMPFAC, TEMPFAC, TITLE, PAEMATRIX,
-  WRAP, NOSTRUCTURE, STRUCTURE, STRUCTUREVIEWER, IMAGE, QUIT, CLOSE,
-  DEBUG("d"), QUIET("q"), ARGFILE, NEWFRAME, NPP("n++"), SUBSTITUTIONS,
-  INITSUBSTITUTIONS, NIL, SPLASH, SETARGFILE, UNSETARGFILE,
+  WRAP, NOSTRUCTURE, STRUCTURE, STRUCTUREVIEWER, IMAGE, TYPE, RENDERER,
+  QUIT, CLOSE, DEBUG("d"), QUIET("q"), ARGFILE, NEWFRAME, NPP("n++"),
+  SUBSTITUTIONS, INITSUBSTITUTIONS, NIL, SPLASH, SETARGFILE, UNSETARGFILE,
   WEBSERVICEDISCOVERY, ALLFRAMES;
 
   protected static enum Opt
@@ -114,6 +114,8 @@ public enum Arg
     WRAP.setOptions(Opt.BOOLEAN, Opt.LINKED);
     IMAGE.setOptions(Opt.STRING, Opt.LINKED, Opt.ALLOWSUBSTITUTIONS,
             Opt.ALLOWALL, Opt.REQUIREINPUT);
+    TYPE.setOptions(Opt.STRING, Opt.LINKED, Opt.ALLOWALL);
+    RENDERER.setOptions(Opt.STRING, Opt.LINKED, Opt.ALLOWALL);
     QUIT.setOptions(Opt.UNARY);
     CLOSE.setOptions(Opt.UNARY, Opt.LINKED, Opt.ALLOWALL);
     DEBUG.setOptions(Opt.BOOLEAN, Opt.BOOTSTRAP);
index 415e065..f1781fc 100644 (file)
@@ -773,19 +773,24 @@ public class ArgParser
     FIRST, BEFORE, AFTER
   }
 
-  public static String getValueFromSubValOrArg(ArgValuesMap avm, Arg a,
-          SubVals sv)
+  // 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, a, sv, null, null, null);
+    return getFromSubValArgOrPref(avm, av, a, sv, null, null, null);
   }
 
-  public static String getFromSubValArgOrPref(ArgValuesMap avm, Arg a,
-          SubVals sv, String key, String pref, String 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)
   {
-    return getFromSubValArgOrPref(avm, a, Position.FIRST, null, sv, key,
-            pref, def);
+    return getFromSubValArgOrPref(avm, a, Position.AFTER, av, sv, key, pref,
+            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)
@@ -796,7 +801,6 @@ public class ArgParser
       return sv.get(key);
     if (avm != null && avm.containsArg(a))
     {
-      String val = null;
       if (pos == Position.FIRST && avm.getValue(a) != null)
         return avm.getValue(a);
       else if (pos == Position.BEFORE
index 5fdaabb..6b46041 100644 (file)
@@ -1480,7 +1480,12 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   public void createPNG(File f)
   {
-    alignPanel.makeAlignmentImage(TYPE.PNG, f);
+    createPNG(f, null);
+  }
+
+  public void createPNG(File f, String renderer)
+  {
+    alignPanel.makeAlignmentImage(TYPE.PNG, f, renderer);
   }
 
   /**
@@ -1492,7 +1497,12 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   public void createEPS(File f)
   {
-    alignPanel.makeAlignmentImage(TYPE.EPS, f);
+    createEPS(f, null);
+  }
+
+  public void createEPS(File f, String renderer)
+  {
+    alignPanel.makeAlignmentImage(TYPE.EPS, f, renderer);
   }
 
   /**
@@ -1504,7 +1514,12 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   public void createSVG(File f)
   {
-    alignPanel.makeAlignmentImage(TYPE.SVG, f);
+    createSVG(f, null);
+  }
+
+  public void createSVG(File f, String renderer)
+  {
+    alignPanel.makeAlignmentImage(TYPE.SVG, f, renderer);
   }
 
   @Override
index 2d057bb..3b0597a 100644 (file)
  */
 package jalview.gui;
 
-import jalview.analysis.AnnotationSorter;
-import jalview.api.AlignViewportI;
-import jalview.api.AlignmentViewPanel;
-import jalview.bin.Cache;
-import jalview.bin.Console;
-import jalview.bin.Jalview;
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.HiddenColumns;
-import jalview.datamodel.SearchResultsI;
-import jalview.datamodel.SequenceFeature;
-import jalview.datamodel.SequenceGroup;
-import jalview.datamodel.SequenceI;
-import jalview.gui.ImageExporter.ImageWriterI;
-import jalview.io.HTMLOutput;
-import jalview.jbgui.GAlignmentPanel;
-import jalview.math.AlignmentDimension;
-import jalview.schemes.ResidueProperties;
-import jalview.structure.StructureSelectionManager;
-import jalview.util.Comparison;
-import jalview.util.ImageMaker;
-import jalview.util.MessageManager;
-import jalview.viewmodel.ViewportListenerI;
-import jalview.viewmodel.ViewportRanges;
-
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Container;
@@ -68,6 +44,30 @@ import java.util.List;
 
 import javax.swing.SwingUtilities;
 
+import jalview.analysis.AnnotationSorter;
+import jalview.api.AlignViewportI;
+import jalview.api.AlignmentViewPanel;
+import jalview.bin.Cache;
+import jalview.bin.Console;
+import jalview.bin.Jalview;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.SearchResultsI;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.gui.ImageExporter.ImageWriterI;
+import jalview.io.HTMLOutput;
+import jalview.jbgui.GAlignmentPanel;
+import jalview.math.AlignmentDimension;
+import jalview.schemes.ResidueProperties;
+import jalview.structure.StructureSelectionManager;
+import jalview.util.Comparison;
+import jalview.util.ImageMaker;
+import jalview.util.MessageManager;
+import jalview.viewmodel.ViewportListenerI;
+import jalview.viewmodel.ViewportRanges;
+
 /**
  * DOCUMENT ME!
  * 
@@ -229,8 +229,9 @@ public class AlignmentPanel extends GAlignmentPanel implements
     // set idCanvas bufferedImage to null
     // to prevent drawing old image
     FontMetrics fm = getFontMetrics(av.getFont());
-    
-    // update the flag controlling whether the grid is too small to render the font
+
+    // update the flag controlling whether the grid is too small to render the
+    // font
     av.validCharWidth = fm.charWidth('M') <= av.getCharWidth();
 
     scalePanelHolder.setPreferredSize(
@@ -1045,6 +1046,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
        */
       alignmentGraphics.translate(alignmentGraphicsOffset,
               alignmentDrawnHeight);
+      updateLayout();
       getAnnotationPanel().renderer.drawComponent(getAnnotationPanel(), av,
               alignmentGraphics, -1, startRes, endRes + 1);
     }
@@ -1178,7 +1180,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
    * @param type
    * @param file
    */
-  void makeAlignmentImage(ImageMaker.TYPE type, File file)
+  void makeAlignmentImage(ImageMaker.TYPE type, File file, String renderer)
   {
     final int borderBottomOffset = 5;
 
@@ -1208,7 +1210,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
     int imageWidth = aDimension.getWidth();
     int imageHeight = aDimension.getHeight() + borderBottomOffset;
     String of = MessageManager.getString("label.alignment");
-    exporter.doExport(file, this, imageWidth, imageHeight, of);
+    exporter.doExport(file, this, imageWidth, imageHeight, of, renderer);
   }
 
   /**
index eeda585..f1a8af7 100755 (executable)
@@ -605,7 +605,8 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
     }
     else
     {
-      // no row (or row that can be adjusted) was pressed. Simulate a ruler click
+      // no row (or row that can be adjusted) was pressed. Simulate a ruler
+      // click
       ap.getScalePanel().mousePressed(evt);
     }
   }
@@ -752,6 +753,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
     av.sendSelection();
     return true;
   }
+
   /**
    * Construct and display a context menu at the right-click position
    * 
@@ -1016,7 +1018,8 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
     }
     if (rowIndex[0] != toRowIndex[0])
     {
-      jalview.bin.Console.trace("Drag went to another row. needs to be clipped");
+      jalview.bin.Console
+              .trace("Drag went to another row. needs to be clipped");
     }
 
     // rectangular selection on matrix style annotation
@@ -1043,9 +1046,9 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
               rowIndex[1] - deltaY);
 
       // mark rectangular region formed by drag
-      jalview.bin.Console.trace("Matrix Selection from last(" + fromXc + ",["
-              + lastXci.cStart + "," + lastXci.cEnd + "]) to cur(" + toXc
-              + ",[" + cXci.cStart + "," + cXci.cEnd + "])");
+      jalview.bin.Console.trace("Matrix Selection from last(" + fromXc
+              + ",[" + lastXci.cStart + "," + lastXci.cEnd + "]) to cur("
+              + toXc + ",[" + cXci.cStart + "," + cXci.cEnd + "])");
       int fr, to;
       fr = Math.min(lastXci.cStart, lastXci.cEnd);
       to = Math.max(lastXci.cStart, lastXci.cEnd);
@@ -1404,8 +1407,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
         return;
       }
     }
-    imgWidth = (av.getRanges().getEndRes() - av.getRanges().getStartRes()
-            + 1) * av.getCharWidth();
+    updateFadedImageWidth();
     if (imgWidth < 1)
     {
       return;
@@ -1473,6 +1475,13 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
     g.drawImage(image, 0, 0, this);
   }
 
+  public void updateFadedImageWidth()
+  {
+    imgWidth = (av.getRanges().getEndRes() - av.getRanges().getStartRes()
+            + 1) * av.getCharWidth();
+
+  }
+
   /**
    * set true to enable redraw timing debug output on stderr
    */
@@ -1648,6 +1657,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
   @Override
   public int getFadedImageWidth()
   {
+    updateFadedImageWidth();
     return imgWidth;
   }
 
index d849ba2..657601e 100644 (file)
@@ -105,6 +105,12 @@ public class ImageExporter
   public void doExport(File file, Component parent, int width, int height,
           String imageSource)
   {
+    doExport(file, parent, width, height, imageSource, null);
+  }
+
+  public void doExport(File file, Component parent, int width, int height,
+          String imageSource, String renderer)
+  {
     final long messageId = System.currentTimeMillis();
     setStatus(
             MessageManager.formatMessage(
@@ -142,9 +148,10 @@ public class ImageExporter
      * for this as EPS_RENDERING / SVG_RENDERING
      * Always set to Text for JalviewJS as Lineart (glyph fonts) not available
      */
-    String renderStyle = Cache.getDefault(
-            imageType.getName() + "_RENDERING",
-            LineartOptions.PROMPT_EACH_TIME);
+    String renderStyle = renderer == null
+            ? Cache.getDefault(imageType.getName() + "_RENDERING",
+                    LineartOptions.PROMPT_EACH_TIME)
+            : renderer;
     if (Platform.isJS())
     {
       renderStyle = "Text";
index 8a530ac..ff4ff6a 100644 (file)
@@ -42,7 +42,7 @@ import jalview.util.MessageManager;
  */
 public class LineartOptions extends JPanel
 {
-  static final String PROMPT_EACH_TIME = "Prompt each time";
+  public static final String PROMPT_EACH_TIME = "Prompt each time";
 
   JvOptionPane dialog;
 
index 493deee..35fdf6a 100755 (executable)
@@ -188,7 +188,7 @@ public class Preferences extends GPreferences
 
   private OptionsParam promptEachTimeOpt = new OptionsParam(
           MessageManager.getString("label.prompt_each_time"),
-          "Prompt each time");
+          LineartOptions.PROMPT_EACH_TIME);
 
   private OptionsParam lineArtOpt = new OptionsParam(
           MessageManager.getString("label.lineart"), "Lineart");
index c88d8eb..6779892 100644 (file)
  */
 package jalview.io;
 
-import jalview.bin.Cache;
-import jalview.gui.AlignmentPanel;
-import jalview.gui.OOMWarning;
-import jalview.json.binding.biojs.BioJSReleasePojo;
-import jalview.json.binding.biojs.BioJSRepositoryPojo;
-import jalview.util.MessageManager;
-
 import java.io.BufferedInputStream;
 import java.io.BufferedReader;
 import java.io.File;
@@ -39,6 +32,13 @@ import java.net.URL;
 import java.util.Objects;
 import java.util.TreeMap;
 
+import jalview.bin.Cache;
+import jalview.gui.AlignmentPanel;
+import jalview.gui.OOMWarning;
+import jalview.json.binding.biojs.BioJSReleasePojo;
+import jalview.json.binding.biojs.BioJSRepositoryPojo;
+import jalview.util.MessageManager;
+
 public class BioJsHTMLOutput extends HTMLOutput
 {
   private static File currentBJSTemplateFile;
@@ -276,4 +276,10 @@ public class BioJsHTMLOutput extends HTMLOutput
 
   }
 
+  @Override
+  public void run(String s)
+  {
+    run();
+  }
+
 }
index 2745420..ed80eb9 100644 (file)
@@ -304,6 +304,11 @@ public abstract class HTMLOutput implements Runnable
 
   public void exportHTML(String outputFile)
   {
+    exportHTML(outputFile, null);
+  }
+
+  public void exportHTML(String outputFile, String renderer)
+  {
     setProgressMessage(MessageManager.formatMessage(
             "status.exporting_alignment_as_x_file", getDescription()));
     try
@@ -332,7 +337,7 @@ public abstract class HTMLOutput implements Runnable
     }
     if (Jalview.isHeadlessMode())
     {
-      this.run();
+      this.run(renderer);
     }
     else
     {
@@ -351,4 +356,7 @@ public abstract class HTMLOutput implements Runnable
   {
     return description;
   }
+
+  // used to pass an option such as render to run
+  public abstract void run(String string);
 }
\ No newline at end of file
index 9fb3720..c5ce35b 100644 (file)
@@ -25,6 +25,7 @@ import java.awt.print.PrinterException;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.util.Locale;
 import java.util.concurrent.Callable;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -202,12 +203,20 @@ public class HtmlSvgOutput extends HTMLOutput
   @Override
   public void run()
   {
+    run(null);
+  }
+
+  @Override
+  public void run(String renderer)
+  {
     try
     {
-      String renderStyle = Cache.getDefault("HTML_RENDERING",
-              "Prompt each time");
+      String renderStyle = renderer == null
+              ? Cache.getDefault("HTML_RENDERING",
+                      LineartOptions.PROMPT_EACH_TIME)
+              : renderer;
       AtomicBoolean textOption = new AtomicBoolean(
-              !"Lineart".equals(renderStyle));
+              !"lineart".equals(renderStyle.toLowerCase(Locale.ROOT)));
 
       /*
        * configure the action to run on OK in the dialog
@@ -220,7 +229,8 @@ public class HtmlSvgOutput extends HTMLOutput
       /*
        * Prompt for character rendering style if preference is not set
        */
-      if (renderStyle.equalsIgnoreCase("Prompt each time") && !isHeadless())
+      if (renderStyle.equalsIgnoreCase(LineartOptions.PROMPT_EACH_TIME)
+              && !isHeadless())
       {
         LineartOptions svgOption = new LineartOptions("HTML", textOption);
         svgOption.setResponseAction(1, () -> {