3 import jalview.api.AlignExportSettingI;
4 import jalview.api.FeatureRenderer;
5 import jalview.datamodel.AlignmentExportData;
6 import jalview.datamodel.SequenceI;
7 import jalview.gui.AlignViewport;
8 import jalview.gui.AlignmentPanel;
9 import jalview.gui.HTMLOptions;
10 import jalview.math.AlignmentDimension;
11 import jalview.util.MessageManager;
13 import java.awt.Color;
14 import java.awt.FontMetrics;
15 import java.awt.Graphics;
16 import java.awt.print.Printable;
17 import java.awt.print.PrinterException;
19 import java.io.FileOutputStream;
21 import org.jfree.graphics2d.svg.SVGGraphics2D;
22 import org.jfree.graphics2d.svg.SVGHints;
24 public class HtmlSvgOutput
32 public HtmlSvgOutput(File file, AlignmentPanel ap)
36 fr = ap.cloneFeatureRenderer();
37 generateHtmlSvgOutput(file);
40 public void generateHtmlSvgOutput(File file)
47 JalviewFileChooser chooser = getHTMLChooser();
48 chooser.setFileView(new jalview.io.JalviewFileView());
49 chooser.setDialogTitle(ap.alignFrame.getTitle());
50 chooser.setToolTipText(MessageManager.getString("action.save"));
51 int value = chooser.showSaveDialog(ap.alignFrame);
53 if (value == jalview.io.JalviewFileChooser.APPROVE_OPTION)
55 jalview.bin.Cache.setProperty("LAST_DIRECTORY", chooser
56 .getSelectedFile().getParent());
57 file = chooser.getSelectedFile();
61 AlignmentDimension aDimension = ap.getAlignmentDimension();
62 SVGGraphics2D g1 = new SVGGraphics2D(aDimension.getWidth(),
63 aDimension.getHeight());
64 SVGGraphics2D g2 = new SVGGraphics2D(aDimension.getWidth(),
65 aDimension.getHeight());
67 String renderStyle = jalview.bin.Cache.getDefault("HTML_RENDERING",
70 // If we need to prompt, and if the GUI is visible then
71 // Prompt for rendering style
72 if (renderStyle.equalsIgnoreCase("Prompt each time")
73 && !(System.getProperty("java.awt.headless") != null && System
74 .getProperty("java.awt.headless").equals("true")))
76 HTMLOptions svgOption = new HTMLOptions();
77 renderStyle = svgOption.getValue();
79 if (renderStyle == null || svgOption.cancelled)
85 if (renderStyle.equalsIgnoreCase("lineart"))
87 g1.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
88 SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
89 g2.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
90 SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
92 printUnwrapped(aDimension.getWidth(), aDimension.getHeight(), 0, g1,
95 String titleSvgData = g1.getSVGDocument();
96 String alignSvgData = g2.getSVGDocument();
97 String jsonData = null;
98 boolean isEmbbedBioJSON = Boolean.valueOf(jalview.bin.Cache
99 .getDefault("EXPORT_EMBBED_BIOJSON", "true"));
102 AlignExportSettingI exportSettings = new AlignExportSettingI(){
104 public boolean isExportHiddenSequences()
110 public boolean isExportHiddenColumns()
116 public boolean isExportAnnotations()
122 public boolean isExportFeatures()
128 public boolean isExportGroups()
134 public boolean isCancelled()
140 AlignmentExportData exportData = jalview.gui.AlignFrame
141 .getAlignmentForExport(JSONFile.FILE_DESC, av,
143 jsonData = new FormatAdapter(ap, exportData.getSettings())
144 .formatSequences(JSONFile.FILE_DESC, exportData
145 .getAlignment(), exportData.getOmitHidden(),
146 exportData.getStartEndPostions(),
147 av.getColumnSelection());
149 String htmlData = getHtml(titleSvgData, alignSvgData, jsonData);
150 FileOutputStream out = new FileOutputStream(file);
151 out.write(htmlData.getBytes());
154 if (!(System.getProperty("java.awt.headless") != null && System
155 .getProperty("java.awt.headless").equals("true")))
157 jalview.util.BrowserLauncher.openURL("file:///" + file);
159 } catch (Exception e)
165 static JalviewFileChooser getHTMLChooser()
167 return new jalview.io.JalviewFileChooser(
168 jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
169 { "html" }, new String[]
170 { "Hypertext Markup Language" }, "Hypertext Markup Language");
173 public int printUnwrapped(int pwidth, int pheight, int pi, Graphics... pg)
174 throws PrinterException
176 int idWidth = ap.getVisibleIdWidth(false);
177 FontMetrics fm = ap.getFontMetrics(av.getFont());
178 int scaleHeight = av.getCharHeight() + fm.getDescent();
180 pg[0].setColor(Color.white);
181 pg[0].fillRect(0, 0, pwidth, pheight);
182 pg[0].setFont(av.getFont());
184 // //////////////////////////////////
185 // / How many sequences and residues can we fit on a printable page?
186 int totalRes = (pwidth - idWidth) / av.getCharWidth();
187 int totalSeq = (pheight - scaleHeight) / av.getCharHeight() - 1;
188 int pagesWide = (av.getAlignment().getWidth() / totalRes) + 1;
190 // ///////////////////////////
191 // / Only print these sequences and residues on this page
194 // ///////////////////////////
195 // / Only print these sequences and residues on this page
198 // ///////////////////////////
199 // / Only print these sequences and residues on this page
202 // ///////////////////////////
203 // / Only print these sequences and residues on this page
205 startRes = (pi % pagesWide) * totalRes;
206 endRes = (startRes + totalRes) - 1;
208 if (endRes > (av.getAlignment().getWidth() - 1))
210 endRes = av.getAlignment().getWidth() - 1;
212 startSeq = (pi / pagesWide) * totalSeq;
213 endSeq = startSeq + totalSeq;
214 if (endSeq > av.getAlignment().getHeight())
216 endSeq = av.getAlignment().getHeight();
218 int pagesHigh = ((av.getAlignment().getHeight() / totalSeq) + 1)
220 if (av.isShowAnnotation())
222 pagesHigh += ap.getAnnotationPanel().adjustPanelHeight() + 3;
224 pagesHigh /= pheight;
225 if (pi >= (pagesWide * pagesHigh))
227 return Printable.NO_SUCH_PAGE;
231 pg[1].translate(0, 0);
232 ap.getScalePanel().drawScale(pg[1], startRes, endRes, pwidth - idWidth,
234 pg[1].translate(-idWidth, scaleHeight);
238 Color currentColor = null;
239 Color currentTextColor = null;
240 pg[0].translate(0, scaleHeight);
241 pg[0].setFont(ap.getIdPanel().getIdCanvas().getIdfont());
243 for (int i = startSeq; i < endSeq; i++)
245 seq = av.getAlignment().getSequenceAt(i);
246 if ((av.getSelectionGroup() != null)
247 && av.getSelectionGroup().getSequences(null).contains(seq))
249 currentColor = Color.gray;
250 currentTextColor = Color.black;
254 currentColor = av.getSequenceColour(seq);
255 currentTextColor = Color.black;
257 pg[0].setColor(currentColor);
258 pg[0].fillRect(0, (i - startSeq) * av.getCharHeight(), idWidth,
260 pg[0].setColor(currentTextColor);
262 if (av.isRightAlignIds())
264 fm = pg[0].getFontMetrics();
266 - fm.stringWidth(seq.getDisplayId(av.getShowJVSuffix()))
270 seq.getDisplayId(av.getShowJVSuffix()),
272 (((i - startSeq) * av.getCharHeight()) + av.getCharHeight())
273 - (av.getCharHeight() / 5));
275 pg[0].setFont(av.getFont());
276 pg[0].translate(idWidth, 0);
278 // draw main sequence panel
279 pg[1].translate(idWidth, 0);
280 ap.getSeqPanel().seqCanvas.drawPanel(pg[1], startRes, endRes, startSeq,
282 if (av.isShowAnnotation() && (endSeq == av.getAlignment().getHeight()))
284 // draw annotation label - need to offset for current scroll position
285 int offset = -ap.getAlabels().getScrollOffset();
286 pg[0].translate(0, offset);
287 pg[0].translate(-idWidth - 3,
288 (endSeq - startSeq) * av.getCharHeight() + 3);
289 ap.getAlabels().drawComponent(pg[0], idWidth);
290 pg[0].translate(idWidth + 3, 0);
291 pg[0].translate(0, -offset);
293 // draw annotation - need to offset for current scroll position
294 pg[1].translate(0, offset);
295 pg[1].translate(-idWidth - 3,
296 (endSeq - startSeq) * av.getCharHeight() + 3);
297 pg[1].translate(idWidth + 3, 0);
298 ap.getAnnotationPanel().renderer.drawComponent(
299 ap.getAnnotationPanel(), av, pg[1], -1, startRes, endRes + 1);
300 pg[1].translate(0, -offset);
303 return Printable.PAGE_EXISTS;
306 private String getHtml(String titleSvg, String alignmentSvg,
309 StringBuilder htmlSvg = new StringBuilder();
310 htmlSvg.append("<html>\n");
311 if (jsonData != null)
313 htmlSvg.append("<button onclick=\"javascipt:openJalviewUsingCurrentUrl();\">Launch in Jalview</button>");
314 htmlSvg.append("<input type=\"hidden\" name=\"seqData\" id=\"seqData\" value='"
317 htmlSvg.append("\n<style type=\"text/css\"> "
318 + "div.parent{ width:100%;<!-- overflow: auto; -->}\n"
319 + "div.titlex{ width:11%; float: left; }\n"
320 + "div.align{ width:89%; float: right; }\n"
321 + ".sub-category-container {overflow-y: scroll; overflow-x: hidden; width: 100%; height: 100%;}\n"
322 + "object {pointer-events: none;}"
324 htmlSvg.append("<div>");
326 "<div class=\"titlex\">");
328 "<div class=\"sub-category-container\"> ")
331 .append("</div>\n\n<!-- ========================================================================================== -->\n\n");
333 "<div class=\"align\" >");
335 "<div class=\"sub-category-container\"> <div style=\"overflow-x: scroll;\">")
336 .append(alignmentSvg)
337 .append("</div></div>")
339 htmlSvg.append("</div>");
341 htmlSvg.append("<script language=\"JavaScript\" type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js\"></script>\n"
342 + "<script language=\"JavaScript\" type=\"text/javascript\" src=\"//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js\"></script>\n"
344 + "var subCatContainer = $(\".sub-category-container\");\n"
345 + "subCatContainer.scroll(\nfunction() {\n"
346 + "subCatContainer.scrollTop($(this).scrollTop());\n});\n");
348 htmlSvg.append("</script>\n");
350 // javascript for launching file in Jalview
352 htmlSvg.append("<script language=\"JavaScript\">\n");
353 htmlSvg.append("function openJalviewUsingCurrentUrl(){\n");
354 htmlSvg.append(" var json = JSON.parse(document.getElementById(\"seqData\").value);\n");
355 htmlSvg.append(" var jalviewVersion = json['appSettings'].version;\n");
356 htmlSvg.append(" var url = json['appSettings'].webStartUrl;\n");
357 htmlSvg.append(" var myForm = document.createElement(\"form\");\n\n");
358 htmlSvg.append(" var heap = document.createElement(\"input\");\n");
359 htmlSvg.append(" heap.setAttribute(\"name\", \"jvm-max-heap\") ;\n");
360 htmlSvg.append(" heap.setAttribute(\"value\", \"2G\");\n\n");
361 htmlSvg.append(" var target = document.createElement(\"input\");\n");
362 htmlSvg.append(" target.setAttribute(\"name\", \"open\");\n");
363 htmlSvg.append(" target.setAttribute(\"value\", document.URL);\n\n");
364 htmlSvg.append(" var jvVersion = document.createElement(\"input\");\n");
365 htmlSvg.append(" jvVersion.setAttribute(\"name\", \"version\") ;\n");
366 htmlSvg.append(" jvVersion.setAttribute(\"value\", jalviewVersion);\n\n");
367 htmlSvg.append(" myForm.action = url;\n");
368 htmlSvg.append(" myForm.appendChild(heap);\n");
369 htmlSvg.append(" myForm.appendChild(target);\n");
370 htmlSvg.append(" myForm.appendChild(jvVersion);\n");
371 htmlSvg.append(" document.body.appendChild(myForm);\n");
372 htmlSvg.append(" myForm.submit() ;\n");
373 htmlSvg.append(" document.body.removeChild(myForm);\n");
374 htmlSvg.append("}\n");
375 htmlSvg.append("</script>\n");
376 htmlSvg.append("</hmtl>");
377 return htmlSvg.toString();