Change the Html export to utilize svg
[jalview.git] / src / jalview / io / HtmlSvgOutput.java
diff --git a/src/jalview/io/HtmlSvgOutput.java b/src/jalview/io/HtmlSvgOutput.java
new file mode 100644 (file)
index 0000000..4643858
--- /dev/null
@@ -0,0 +1,264 @@
+package jalview.io;
+
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignViewport;
+import jalview.gui.AlignmentPanel;
+import jalview.gui.AnnotationPanel;
+import jalview.gui.FeatureRenderer;
+import jalview.gui.HTMLOptions;
+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;
+
+  AnnotationPanel annotationPanel;
+
+  public HtmlSvgOutput(AlignmentPanel ap)
+  {
+
+      this.av = ap.av;
+      this.ap = ap;
+      this.annotationPanel = ap.getAnnotationPanel();
+    generateHtmlSvgOutput();
+  }
+
+  public void generateHtmlSvgOutput()
+  {
+    File file = null;
+    try
+    {
+      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();
+      }
+
+      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)
+        {
+          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);
+      FileOutputStream out = new FileOutputStream(file);
+
+      String titleSvgData = g1.getSVGDocument();
+      String alignSvgData = g2.getSVGDocument();
+      String htmlData = getHtml(titleSvgData, alignSvgData);
+
+      out.write(htmlData.getBytes());
+      out.flush();
+      out.close();
+
+      jalview.util.BrowserLauncher.openURL("file:///" + file);
+    } catch (Exception e)
+    {
+      e.printStackTrace();
+    }
+  }
+  
+  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)
+  {
+    StringBuilder htmlSvg = new StringBuilder();
+    htmlSvg.append("<html><style type=\"text/css\">" + "div.title {"
+            + "height: 100%;" + "width: 9%;" + "float: left;" + "}"
+            + "div.align {" + "height: 100%;" + "width: 91%;"
+            + "overflow: scroll;" + "float: right;" + "}" + "</style>"
+            + "<div style=\"width:100%; height:100%; overflow: hidden\">"
+            + "<div class=\"title\">");
+    htmlSvg.append(titleSvg);
+    htmlSvg.append("</div><div class=\"align\">").append(alignmentSvg);
+    htmlSvg.append("</div>");
+    return htmlSvg.toString();
+  }
+}