2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import jalview.bin.Cache;
24 import jalview.exceptions.NoFileSelectedException;
25 import jalview.gui.AlignmentPanel;
26 import jalview.gui.LineartOptions;
27 import jalview.gui.OOMWarning;
28 import jalview.math.AlignmentDimension;
29 import jalview.util.MessageManager;
30 import jalview.util.dialogrunner.RunResponse;
32 import java.awt.Graphics;
33 import java.awt.print.PrinterException;
35 import java.io.FileOutputStream;
36 import java.io.IOException;
37 import java.util.concurrent.atomic.AtomicBoolean;
39 import javax.swing.JOptionPane;
41 import org.jfree.graphics2d.svg.SVGGraphics2D;
42 import org.jfree.graphics2d.svg.SVGHints;
44 public class HtmlSvgOutput extends HTMLOutput
47 public HtmlSvgOutput(AlignmentPanel ap)
53 public void exportHTML(String outputFile)
58 if (outputFile == null)
60 outputFile = getOutputFile();
62 generatedFile = new File(outputFile);
63 } catch (NoFileSelectedException e)
65 setProgressMessage(MessageManager.formatMessage(
66 "status.cancelled_image_export_operation", "HTML"));
70 setProgressMessage(MessageManager
71 .formatMessage("info.error_creating_file", "HTML"));
75 new Thread(this).start();
78 public int printUnwrapped(int pwidth, int pheight, int pi,
79 Graphics idGraphics, Graphics alignmentGraphics)
80 throws PrinterException
82 return ap.printUnwrapped(pwidth, pheight, pi, idGraphics,
86 public int printWrapped(int pwidth, int pheight, int pi, Graphics... pg)
87 throws PrinterException
89 return ap.printWrappedAlignment(pwidth, pheight, pi, pg[0]);
92 String getHtml(String titleSvg, String alignmentSvg,
93 String jsonData, boolean wrapped)
95 StringBuilder htmlSvg = new StringBuilder();
96 htmlSvg.append("<html>\n");
100 "<button onclick=\"javascipt:openJalviewUsingCurrentUrl();\">Launch in Jalview</button> ");
102 "<input type=\"submit\" value=\"View raw BioJSON Data\" onclick=\"jQuery.facebox({ div:'#seqData' }); return false;\" />");
104 "<div style=\"display: none;\" name=\"seqData\" id=\"seqData\" >"
105 + jsonData + "</div>");
106 htmlSvg.append("<br/> ");
108 htmlSvg.append("\n<style type=\"text/css\"> "
109 + "div.parent{ width:100%;<!-- overflow: auto; -->}\n"
110 + "div.titlex{ width:11%; float: left; }\n"
111 + "div.align{ width:89%; float: right; }\n"
112 + "div.main-container{ border: 2px solid blue; border: 2px solid blue; width: 99%; min-height: 99%; }\n"
113 + ".sub-category-container {overflow-y: scroll; overflow-x: hidden; width: 100%; height: 100%;}\n"
114 + "object {pointer-events: none;}");
115 if (jsonData != null)
117 // facebox style sheet for displaying raw BioJSON data
119 "#facebox { position: absolute; top: 0; left: 0; z-index: 100; text-align: left; }\n"
120 + "#facebox .popup{ position:relative; border:3px solid rgba(0,0,0,0); -webkit-border-radius:5px;"
121 + "-moz-border-radius:5px; border-radius:5px; -webkit-box-shadow:0 0 18px rgba(0,0,0,0.4); -moz-box-shadow:0 0 18px rgba(0,0,0,0.4);"
122 + "box-shadow:0 0 18px rgba(0,0,0,0.4); }\n"
123 + "#facebox .content { display:table; width: 98%; padding: 10px; background: #fff; -webkit-border-radius:4px; -moz-border-radius:4px;"
124 + " border-radius:4px; }\n"
125 + "#facebox .content > p:first-child{ margin-top:0; }\n"
126 + "#facebox .content > p:last-child{ margin-bottom:0; }\n"
127 + "#facebox .close{ position:absolute; top:5px; right:5px; padding:2px; background:#fff; }\n"
128 + "#facebox .close img{ opacity:0.3; }\n"
129 + "#facebox .close:hover img{ opacity:1.0; }\n"
130 + "#facebox .loading { text-align: center; }\n"
131 + "#facebox .image { text-align: center;}\n"
132 + "#facebox img { border: 0; margin: 0; }\n"
133 + "#facebox_overlay { position: fixed; top: 0px; left: 0px; height:100%; width:100%; }\n"
134 + ".facebox_hide { z-index:-100; }\n"
135 + ".facebox_overlayBG { background-color: #000; z-index: 99; }");
137 htmlSvg.append("</style>");
140 htmlSvg.append("<div class=\"main-container\" \n>");
141 htmlSvg.append("<div class=\"titlex\">\n");
142 htmlSvg.append("<div class=\"sub-category-container\"> \n");
143 htmlSvg.append(titleSvg);
144 htmlSvg.append("</div>");
146 "</div>\n\n<!-- ========================================================================================== -->\n\n");
147 htmlSvg.append("<div class=\"align\" >");
149 "<div class=\"sub-category-container\"> <div style=\"overflow-x: scroll;\">")
150 .append(alignmentSvg).append("</div></div>").append("</div>");
151 htmlSvg.append("</div>");
154 "<script language=\"JavaScript\" type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js\"></script>\n"
155 + "<script language=\"JavaScript\" type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js\"></script>\n"
157 + "var subCatContainer = $(\".sub-category-container\");\n"
158 + "subCatContainer.scroll(\nfunction() {\n"
159 + "subCatContainer.scrollTop($(this).scrollTop());\n});\n");
161 htmlSvg.append("</script>\n");
165 htmlSvg.append("<div>\n").append(alignmentSvg).append("</div>");
167 "<script language=\"JavaScript\" type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js\"></script>\n"
168 + "<script language=\"JavaScript\" type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js\"></script>\n");
171 // javascript for launching file in Jalview
172 htmlSvg.append("<script language=\"JavaScript\">\n");
173 htmlSvg.append("function openJalviewUsingCurrentUrl(){\n");
175 " var json = JSON.parse(document.getElementById(\"seqData\").innerHTML);\n");
177 " var jalviewVersion = json['appSettings'].version;\n");
178 htmlSvg.append(" var url = json['appSettings'].webStartUrl;\n");
180 " var myForm = document.createElement(\"form\");\n\n");
181 htmlSvg.append(" var heap = document.createElement(\"input\");\n");
182 htmlSvg.append(" heap.setAttribute(\"name\", \"jvm-max-heap\") ;\n");
183 htmlSvg.append(" heap.setAttribute(\"value\", \"2G\");\n\n");
184 htmlSvg.append(" var target = document.createElement(\"input\");\n");
185 htmlSvg.append(" target.setAttribute(\"name\", \"open\");\n");
186 htmlSvg.append(" target.setAttribute(\"value\", document.URL);\n\n");
188 " var jvVersion = document.createElement(\"input\");\n");
189 htmlSvg.append(" jvVersion.setAttribute(\"name\", \"version\") ;\n");
191 " jvVersion.setAttribute(\"value\", jalviewVersion);\n\n");
192 htmlSvg.append(" myForm.action = url;\n");
193 htmlSvg.append(" myForm.appendChild(heap);\n");
194 htmlSvg.append(" myForm.appendChild(target);\n");
195 htmlSvg.append(" myForm.appendChild(jvVersion);\n");
196 htmlSvg.append(" document.body.appendChild(myForm);\n");
197 htmlSvg.append(" myForm.submit() ;\n");
198 htmlSvg.append(" document.body.removeChild(myForm);\n");
199 htmlSvg.append("}\n");
201 if (jsonData != null)
203 // JQuery FaceBox for displaying raw BioJSON data");
204 File faceBoxJsFile = new File("examples/javascript/facebox-1.3.js");
207 htmlSvg.append(HTMLOutput.readFileAsString(faceBoxJsFile));
208 } catch (IOException e)
214 htmlSvg.append("</script>\n");
215 htmlSvg.append("</html>");
216 return htmlSvg.toString();
220 public boolean isEmbedData()
222 return Boolean.valueOf(
223 jalview.bin.Cache.getDefault("EXPORT_EMBBED_BIOJSON", "true"));
227 public boolean isLaunchInBrowserAfterExport()
233 public File getExportedFile()
235 return generatedFile;
243 setProgressMessage(null);
244 setProgressMessage(MessageManager.formatMessage(
245 "status.exporting_alignment_as_x_file", "HTML"));
247 String renderStyle = Cache.getDefault("HTML_RENDERING",
249 AtomicBoolean textOption = new AtomicBoolean(
250 !"Lineart".equals(renderStyle));
253 * configure the action to run on OK in the dialog
255 RunResponse okAction = new RunResponse(JOptionPane.OK_OPTION)
260 doOutput(textOption.get());
265 * Prompt for character rendering style if preference is not set
267 if (renderStyle.equalsIgnoreCase("Prompt each time") && !isHeadless())
269 LineartOptions svgOption = new LineartOptions("HTML_RENDERING",
271 svgOption.setResponseAction(new RunResponse(JOptionPane.NO_OPTION)
276 setProgressMessage(MessageManager.formatMessage(
277 "status.cancelled_image_export_operation", "HTML"));
280 svgOption.setResponseAction(okAction);
281 svgOption.showDialog();
282 /* no code here - JalviewJS cannot execute it */
287 * else (if preference set) just do the export action
289 doOutput(textOption.get());
291 } catch (OutOfMemoryError err)
293 System.out.println("########################\n" + "OUT OF MEMORY "
294 + generatedFile + "\n" + "########################");
295 new OOMWarning("Creating Image for " + generatedFile, err);
296 } catch (Exception e)
299 setProgressMessage(MessageManager
300 .formatMessage("info.error_creating_file", "HTML"));
305 * Builds and writes the image to the file specified by field
306 * <code>generatedFile</code>
308 * @param textCharacters
309 * true for Text character rendering, false for Lineart
311 protected void doOutput(boolean textCharacters)
315 AlignmentDimension aDimension = ap.getAlignmentDimension();
316 SVGGraphics2D idPanelGraphics = new SVGGraphics2D(
317 aDimension.getWidth(), aDimension.getHeight());
318 SVGGraphics2D alignPanelGraphics = new SVGGraphics2D(
319 aDimension.getWidth(), aDimension.getHeight());
320 if (!textCharacters) // Lineart selected
322 idPanelGraphics.setRenderingHint(
323 SVGHints.KEY_DRAW_STRING_TYPE,
324 SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
325 alignPanelGraphics.setRenderingHint(
326 SVGHints.KEY_DRAW_STRING_TYPE,
327 SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
329 if (ap.av.getWrapAlignment())
331 printWrapped(aDimension.getWidth(), aDimension.getHeight(), 0,
336 printUnwrapped(aDimension.getWidth(), aDimension.getHeight(),
337 0, idPanelGraphics, alignPanelGraphics);
340 String idPanelSvgData = idPanelGraphics.getSVGDocument();
341 String alignPanelSvgData = alignPanelGraphics.getSVGDocument();
342 String jsonData = getBioJSONData();
343 String htmlData = getHtml(idPanelSvgData, alignPanelSvgData,
344 jsonData, ap.av.getWrapAlignment());
345 FileOutputStream out = new FileOutputStream(generatedFile);
346 out.write(htmlData.getBytes());
349 setProgressMessage(MessageManager
350 .formatMessage("status.export_complete", "HTML"));
352 } catch (Exception e)
355 setProgressMessage(MessageManager
356 .formatMessage("info.error_creating_file", "HTML"));