From 08fece8cdf7aeee3893e1c63fc94c01ce517e3dd Mon Sep 17 00:00:00 2001 From: Ben Soares Date: Tue, 2 May 2023 12:29:55 +0100 Subject: [PATCH] JAL-629 Add --renderer arg/subval for vector output and fixed annotation renderer code --- src/jalview/bin/Commands.java | 57 +++++++++++++++++------------ src/jalview/bin/argparser/Arg.java | 8 +++-- src/jalview/bin/argparser/ArgParser.java | 20 ++++++----- src/jalview/gui/AlignFrame.java | 21 +++++++++-- src/jalview/gui/AlignmentPanel.java | 58 +++++++++++++++--------------- src/jalview/gui/AnnotationPanel.java | 24 +++++++++---- src/jalview/gui/ImageExporter.java | 13 +++++-- src/jalview/gui/LineartOptions.java | 2 +- src/jalview/gui/Preferences.java | 2 +- src/jalview/io/BioJsHTMLOutput.java | 20 +++++++---- src/jalview/io/HTMLOutput.java | 10 +++++- src/jalview/io/HtmlSvgOutput.java | 18 +++++++--- 12 files changed, 164 insertions(+), 89 deletions(-) diff --git a/src/jalview/bin/Commands.java b/src/jalview/bin/Commands.java index f33202d..90eb45c 100644 --- a/src/jalview/bin/Commands.java +++ b/src/jalview/bin/Commands.java @@ -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 + "'"); } } } diff --git a/src/jalview/bin/argparser/Arg.java b/src/jalview/bin/argparser/Arg.java index 6c3e6ae..ca6cc77 100644 --- a/src/jalview/bin/argparser/Arg.java +++ b/src/jalview/bin/argparser/Arg.java @@ -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); diff --git a/src/jalview/bin/argparser/ArgParser.java b/src/jalview/bin/argparser/ArgParser.java index 415e065..f1781fc 100644 --- a/src/jalview/bin/argparser/ArgParser.java +++ b/src/jalview/bin/argparser/ArgParser.java @@ -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 diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index 5fdaabb..6b46041 100644 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -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 diff --git a/src/jalview/gui/AlignmentPanel.java b/src/jalview/gui/AlignmentPanel.java index 2d057bb..3b0597a 100644 --- a/src/jalview/gui/AlignmentPanel.java +++ b/src/jalview/gui/AlignmentPanel.java @@ -20,30 +20,6 @@ */ 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); } /** diff --git a/src/jalview/gui/AnnotationPanel.java b/src/jalview/gui/AnnotationPanel.java index eeda585..f1a8af7 100755 --- a/src/jalview/gui/AnnotationPanel.java +++ b/src/jalview/gui/AnnotationPanel.java @@ -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; } diff --git a/src/jalview/gui/ImageExporter.java b/src/jalview/gui/ImageExporter.java index d849ba2..657601e 100644 --- a/src/jalview/gui/ImageExporter.java +++ b/src/jalview/gui/ImageExporter.java @@ -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"; diff --git a/src/jalview/gui/LineartOptions.java b/src/jalview/gui/LineartOptions.java index 8a530ac..ff4ff6a 100644 --- a/src/jalview/gui/LineartOptions.java +++ b/src/jalview/gui/LineartOptions.java @@ -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; diff --git a/src/jalview/gui/Preferences.java b/src/jalview/gui/Preferences.java index 493deee..35fdf6a 100755 --- a/src/jalview/gui/Preferences.java +++ b/src/jalview/gui/Preferences.java @@ -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"); diff --git a/src/jalview/io/BioJsHTMLOutput.java b/src/jalview/io/BioJsHTMLOutput.java index c88d8eb..6779892 100644 --- a/src/jalview/io/BioJsHTMLOutput.java +++ b/src/jalview/io/BioJsHTMLOutput.java @@ -20,13 +20,6 @@ */ 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(); + } + } diff --git a/src/jalview/io/HTMLOutput.java b/src/jalview/io/HTMLOutput.java index 2745420..ed80eb9 100644 --- a/src/jalview/io/HTMLOutput.java +++ b/src/jalview/io/HTMLOutput.java @@ -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 diff --git a/src/jalview/io/HtmlSvgOutput.java b/src/jalview/io/HtmlSvgOutput.java index 9fb3720..c5ce35b 100644 --- a/src/jalview/io/HtmlSvgOutput.java +++ b/src/jalview/io/HtmlSvgOutput.java @@ -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, () -> { -- 1.7.10.2