/* * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) * Copyright (C) $$Year-Rel$$ The Jalview Authors * * This file is part of Jalview. * * Jalview is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * Jalview is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Jalview. If not, see . * The Jalview Authors are detailed in the 'AUTHORS' file. */ package jalview.io; import jalview.api.AlignExportSettingI; import jalview.api.FeatureRenderer; import jalview.datamodel.AlignmentExportData; import jalview.datamodel.SequenceI; import jalview.gui.AlignViewport; import jalview.gui.AlignmentPanel; import jalview.gui.HTMLOptions; import jalview.gui.IProgressIndicator; import jalview.gui.OOMWarning; import jalview.math.AlignmentDimension; import jalview.util.MessageManager; import java.awt.Color; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.print.Printable; import java.awt.print.PrinterException; import java.io.File; import java.io.FileOutputStream; import org.jfree.graphics2d.svg.SVGGraphics2D; import org.jfree.graphics2d.svg.SVGHints; public class HtmlSvgOutput { AlignViewport av; FeatureRenderer fr; AlignmentPanel ap; private IProgressIndicator pIndicator; private long pSessionId; private boolean headless; public HtmlSvgOutput(File file, AlignmentPanel ap) { this.av = ap.av; this.ap = ap; fr = ap.cloneFeatureRenderer(); generateHtmlSvgOutput(file); } public void generateHtmlSvgOutput(File file) { pIndicator = ap.alignFrame; pSessionId = System.currentTimeMillis(); try { headless = (System.getProperty("java.awt.headless") != null && System .getProperty("java.awt.headless").equals("true")); if (file == null) { setProgressMessage(MessageManager.formatMessage( "status.waiting_for_user_to_select_output_file", "HTML")); JalviewFileChooser chooser = getHTMLChooser(); chooser.setFileView(new jalview.io.JalviewFileView()); chooser.setDialogTitle(ap.alignFrame.getTitle()); chooser.setToolTipText(MessageManager.getString("action.save")); int value = chooser.showSaveDialog(ap.alignFrame); if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION) { jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser .getSelectedFile().getParent()); file = chooser.getSelectedFile(); ap.alignFrame.repaint(); } else { setProgressMessage(MessageManager.formatMessage( "status.cancelled_image_export_operation", "HTML")); return; } } } catch (Exception e) { pIndicator.setProgressBar(MessageManager.formatMessage( "info.error_creating_file", "HTML"), pSessionId); e.printStackTrace(); return; } final File fileX = file; new Thread() { @Override public void run() { try { setProgressMessage(null); setProgressMessage(MessageManager.formatMessage( "status.exporting_alignment_as_x_file", "HTML")); AlignmentDimension aDimension = ap.getAlignmentDimension(); SVGGraphics2D g1 = new SVGGraphics2D(aDimension.getWidth(), aDimension.getHeight()); SVGGraphics2D g2 = new SVGGraphics2D(aDimension.getWidth(), aDimension.getHeight()); String renderStyle = jalview.bin.Cache.getDefault( "HTML_RENDERING", "Prompt each time"); // If we need to prompt, and if the GUI is visible then // Prompt for rendering style if (renderStyle.equalsIgnoreCase("Prompt each time") && !(System.getProperty("java.awt.headless") != null && System .getProperty("java.awt.headless").equals("true"))) { HTMLOptions svgOption = new HTMLOptions(); renderStyle = svgOption.getValue(); if (renderStyle == null || svgOption.cancelled) { setProgressMessage(MessageManager.formatMessage( "status.cancelled_image_export_operation", "HTML")); return; } } if (renderStyle.equalsIgnoreCase("Lineart")) { g1.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE, SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR); g2.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE, SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR); } printUnwrapped(aDimension.getWidth(), aDimension.getHeight(), 0, g1, g2); String titleSvgData = g1.getSVGDocument(); String alignSvgData = g2.getSVGDocument(); String jsonData = null; boolean isEmbbedBioJSON = Boolean.valueOf(jalview.bin.Cache .getDefault("EXPORT_EMBBED_BIOJSON", "true")); if (isEmbbedBioJSON) { AlignExportSettingI exportSettings = new AlignExportSettingI() { @Override public boolean isExportHiddenSequences() { return true; } @Override public boolean isExportHiddenColumns() { return true; } @Override public boolean isExportAnnotations() { return true; } @Override public boolean isExportFeatures() { return true; } @Override public boolean isExportGroups() { return true; } @Override public boolean isCancelled() { return false; } }; AlignmentExportData exportData = jalview.gui.AlignFrame .getAlignmentForExport(JSONFile.FILE_DESC, av, exportSettings); jsonData = new FormatAdapter(ap, exportData.getSettings()) .formatSequences(JSONFile.FILE_DESC, exportData.getAlignment(), exportData.getOmitHidden(), exportData.getStartEndPostions(), av.getColumnSelection()); } String htmlData = getHtml(titleSvgData, alignSvgData, jsonData); FileOutputStream out = new FileOutputStream(fileX); out.write(htmlData.getBytes()); out.flush(); out.close(); if (!(System.getProperty("java.awt.headless") != null && System .getProperty("java.awt.headless").equals("true"))) { jalview.util.BrowserLauncher.openURL("file:///" + fileX); } } catch (OutOfMemoryError err) { System.out.println("########################\n" + "OUT OF MEMORY " + fileX + "\n" + "########################"); new OOMWarning("Creating Image for " + fileX, err); } catch (Exception e) { e.printStackTrace(); pIndicator.setProgressBar(MessageManager.formatMessage( "info.error_creating_file", "HTML"), pSessionId); } setProgressMessage(MessageManager.formatMessage( "status.export_complete", "HTML")); } }.start(); } private void setProgressMessage(String message) { if (pIndicator != null && !headless) { pIndicator.setProgressBar(message, pSessionId); } else { System.out.println(message); } } static JalviewFileChooser getHTMLChooser() { return new jalview.io.JalviewFileChooser( jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[] { "html" }, new String[] { "Hypertext Markup Language" }, "Hypertext Markup Language"); } public int printUnwrapped(int pwidth, int pheight, int pi, Graphics... pg) throws PrinterException { int idWidth = ap.getVisibleIdWidth(false); FontMetrics fm = ap.getFontMetrics(av.getFont()); int scaleHeight = av.getCharHeight() + fm.getDescent(); pg[0].setColor(Color.white); pg[0].fillRect(0, 0, pwidth, pheight); pg[0].setFont(av.getFont()); // ////////////////////////////////// // / How many sequences and residues can we fit on a printable page? int totalRes = (pwidth - idWidth) / av.getCharWidth(); int totalSeq = (pheight - scaleHeight) / av.getCharHeight() - 1; int pagesWide = (av.getAlignment().getWidth() / totalRes) + 1; // /////////////////////////// // / Only print these sequences and residues on this page int startRes; // /////////////////////////// // / Only print these sequences and residues on this page int endRes; // /////////////////////////// // / Only print these sequences and residues on this page int startSeq; // /////////////////////////// // / Only print these sequences and residues on this page int endSeq; startRes = (pi % pagesWide) * totalRes; endRes = (startRes + totalRes) - 1; if (endRes > (av.getAlignment().getWidth() - 1)) { endRes = av.getAlignment().getWidth() - 1; } startSeq = (pi / pagesWide) * totalSeq; endSeq = startSeq + totalSeq; if (endSeq > av.getAlignment().getHeight()) { endSeq = av.getAlignment().getHeight(); } int pagesHigh = ((av.getAlignment().getHeight() / totalSeq) + 1) * pheight; if (av.isShowAnnotation()) { pagesHigh += ap.getAnnotationPanel().adjustPanelHeight() + 3; } pagesHigh /= pheight; if (pi >= (pagesWide * pagesHigh)) { return Printable.NO_SUCH_PAGE; } // draw Scale pg[1].translate(0, 0); ap.getScalePanel().drawScale(pg[1], startRes, endRes, pwidth - idWidth, scaleHeight); pg[1].translate(-idWidth, scaleHeight); // ////////////// // Draw the ids Color currentColor = null; Color currentTextColor = null; pg[0].translate(0, scaleHeight); pg[0].setFont(ap.getIdPanel().getIdCanvas().getIdfont()); SequenceI seq; for (int i = startSeq; i < endSeq; i++) { seq = av.getAlignment().getSequenceAt(i); if ((av.getSelectionGroup() != null) && av.getSelectionGroup().getSequences(null).contains(seq)) { currentColor = Color.gray; currentTextColor = Color.black; } else { currentColor = av.getSequenceColour(seq); currentTextColor = Color.black; } pg[0].setColor(currentColor); pg[0].fillRect(0, (i - startSeq) * av.getCharHeight(), idWidth, av.getCharHeight()); pg[0].setColor(currentTextColor); int xPos = 0; if (av.isRightAlignIds()) { fm = pg[0].getFontMetrics(); xPos = idWidth - fm.stringWidth(seq.getDisplayId(av.getShowJVSuffix())) - 4; } pg[0].drawString(seq.getDisplayId(av.getShowJVSuffix()), xPos, (((i - startSeq) * av.getCharHeight()) + av.getCharHeight()) - (av.getCharHeight() / 5)); } pg[0].setFont(av.getFont()); pg[0].translate(idWidth, 0); // draw main sequence panel pg[1].translate(idWidth, 0); ap.getSeqPanel().seqCanvas.drawPanel(pg[1], startRes, endRes, startSeq, endSeq, 0); if (av.isShowAnnotation() && (endSeq == av.getAlignment().getHeight())) { // draw annotation label - need to offset for current scroll position int offset = -ap.getAlabels().getScrollOffset(); pg[0].translate(0, offset); pg[0].translate(-idWidth - 3, (endSeq - startSeq) * av.getCharHeight() + 3); ap.getAlabels().drawComponent(pg[0], idWidth); pg[0].translate(idWidth + 3, 0); pg[0].translate(0, -offset); // draw annotation - need to offset for current scroll position pg[1].translate(0, offset); pg[1].translate(-idWidth - 3, (endSeq - startSeq) * av.getCharHeight() + 3); pg[1].translate(idWidth + 3, 0); ap.getAnnotationPanel().renderer.drawComponent( ap.getAnnotationPanel(), av, pg[1], -1, startRes, endRes + 1); pg[1].translate(0, -offset); } return Printable.PAGE_EXISTS; } private String getHtml(String titleSvg, String alignmentSvg, String jsonData) { StringBuilder htmlSvg = new StringBuilder(); htmlSvg.append("\n"); if (jsonData != null) { htmlSvg.append("  "); htmlSvg.append(""); htmlSvg.append("
" + jsonData + "
"); htmlSvg.append("
 "); } htmlSvg.append("\n"); htmlSvg.append("
"); htmlSvg.append("
\n"); htmlSvg.append("
\n"); htmlSvg.append(titleSvg); htmlSvg.append("
"); htmlSvg.append("
\n\n\n\n"); htmlSvg.append("
"); htmlSvg.append( "
") .append(alignmentSvg).append("
").append("
"); htmlSvg.append("
"); htmlSvg.append("\n" + "\n" + "\n"); // javascript for launching file in Jalview htmlSvg.append("\n"); htmlSvg.append(""); return htmlSvg.toString(); } }