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.bin.Jalview;
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;
31 import java.awt.Graphics;
32 import java.awt.print.PrinterException;
34 import java.io.FileOutputStream;
35 import java.io.IOException;
36 import java.util.concurrent.atomic.AtomicBoolean;
38 import org.jfree.graphics2d.svg.SVGGraphics2D;
39 import org.jfree.graphics2d.svg.SVGHints;
41 public class HtmlSvgOutput extends HTMLOutput
43 public HtmlSvgOutput(AlignmentPanel ap)
48 public int printUnwrapped(int pwidth, int pheight, int pi,
49 Graphics idGraphics, Graphics alignmentGraphics)
50 throws PrinterException
52 return ap.printUnwrapped(pwidth, pheight, pi, idGraphics,
56 public int printWrapped(int pwidth, int pheight, int pi, Graphics... pg)
57 throws PrinterException
59 return ap.printWrappedAlignment(pwidth, pheight, pi, pg[0]);
62 String getHtml(String titleSvg, String alignmentSvg,
63 String jsonData, boolean wrapped)
65 StringBuilder htmlSvg = new StringBuilder();
66 htmlSvg.append("<html>\n");
70 "<button onclick=\"javascipt:openJalviewUsingCurrentUrl();\">Launch in Jalview</button> ");
72 "<input type=\"submit\" value=\"View raw BioJSON Data\" onclick=\"jQuery.facebox({ div:'#seqData' }); return false;\" />");
74 "<div style=\"display: none;\" name=\"seqData\" id=\"seqData\" >"
75 + jsonData + "</div>");
76 htmlSvg.append("<br/> ");
78 htmlSvg.append("\n<style type=\"text/css\"> "
79 + "div.parent{ width:100%;<!-- overflow: auto; -->}\n"
80 + "div.titlex{ width:11%; float: left; }\n"
81 + "div.align{ width:89%; float: right; }\n"
82 + "div.main-container{ border: 2px solid blue; border: 2px solid blue; width: 99%; min-height: 99%; }\n"
83 + ".sub-category-container {overflow-y: scroll; overflow-x: hidden; width: 100%; height: 100%;}\n"
84 + "object {pointer-events: none;}");
87 // facebox style sheet for displaying raw BioJSON data
89 "#facebox { position: absolute; top: 0; left: 0; z-index: 100; text-align: left; }\n"
90 + "#facebox .popup{ position:relative; border:3px solid rgba(0,0,0,0); -webkit-border-radius:5px;"
91 + "-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);"
92 + "box-shadow:0 0 18px rgba(0,0,0,0.4); }\n"
93 + "#facebox .content { display:table; width: 98%; padding: 10px; background: #fff; -webkit-border-radius:4px; -moz-border-radius:4px;"
94 + " border-radius:4px; }\n"
95 + "#facebox .content > p:first-child{ margin-top:0; }\n"
96 + "#facebox .content > p:last-child{ margin-bottom:0; }\n"
97 + "#facebox .close{ position:absolute; top:5px; right:5px; padding:2px; background:#fff; }\n"
98 + "#facebox .close img{ opacity:0.3; }\n"
99 + "#facebox .close:hover img{ opacity:1.0; }\n"
100 + "#facebox .loading { text-align: center; }\n"
101 + "#facebox .image { text-align: center;}\n"
102 + "#facebox img { border: 0; margin: 0; }\n"
103 + "#facebox_overlay { position: fixed; top: 0px; left: 0px; height:100%; width:100%; }\n"
104 + ".facebox_hide { z-index:-100; }\n"
105 + ".facebox_overlayBG { background-color: #000; z-index: 99; }");
107 htmlSvg.append("</style>");
110 htmlSvg.append("<div class=\"main-container\" \n>");
111 htmlSvg.append("<div class=\"titlex\">\n");
112 htmlSvg.append("<div class=\"sub-category-container\"> \n");
113 htmlSvg.append(titleSvg);
114 htmlSvg.append("</div>");
116 "</div>\n\n<!-- ========================================================================================== -->\n\n");
117 htmlSvg.append("<div class=\"align\" >");
119 "<div class=\"sub-category-container\"> <div style=\"overflow-x: scroll;\">")
120 .append(alignmentSvg).append("</div></div>").append("</div>");
121 htmlSvg.append("</div>");
124 "<script language=\"JavaScript\" type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js\"></script>\n"
125 + "<script language=\"JavaScript\" type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js\"></script>\n"
127 + "var subCatContainer = $(\".sub-category-container\");\n"
128 + "subCatContainer.scroll(\nfunction() {\n"
129 + "subCatContainer.scrollTop($(this).scrollTop());\n});\n");
131 htmlSvg.append("</script>\n");
135 htmlSvg.append("<div>\n").append(alignmentSvg).append("</div>");
137 "<script language=\"JavaScript\" type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js\"></script>\n"
138 + "<script language=\"JavaScript\" type=\"text/javascript\" src=\"http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js\"></script>\n");
141 // javascript for launching file in Jalview
142 htmlSvg.append("<script language=\"JavaScript\">\n");
143 htmlSvg.append("function openJalviewUsingCurrentUrl(){\n");
145 " var json = JSON.parse(document.getElementById(\"seqData\").innerHTML);\n");
147 " var jalviewVersion = json['appSettings'].version;\n");
148 htmlSvg.append(" var url = json['appSettings'].webStartUrl;\n");
150 " var myForm = document.createElement(\"form\");\n\n");
151 htmlSvg.append(" var heap = document.createElement(\"input\");\n");
152 htmlSvg.append(" heap.setAttribute(\"name\", \"jvm-max-heap\") ;\n");
153 htmlSvg.append(" heap.setAttribute(\"value\", \"2G\");\n\n");
154 htmlSvg.append(" var target = document.createElement(\"input\");\n");
155 htmlSvg.append(" target.setAttribute(\"name\", \"open\");\n");
156 htmlSvg.append(" target.setAttribute(\"value\", document.URL);\n\n");
158 " var jvVersion = document.createElement(\"input\");\n");
159 htmlSvg.append(" jvVersion.setAttribute(\"name\", \"version\") ;\n");
161 " jvVersion.setAttribute(\"value\", jalviewVersion);\n\n");
162 htmlSvg.append(" myForm.action = url;\n");
163 htmlSvg.append(" myForm.appendChild(heap);\n");
164 htmlSvg.append(" myForm.appendChild(target);\n");
165 htmlSvg.append(" myForm.appendChild(jvVersion);\n");
166 htmlSvg.append(" document.body.appendChild(myForm);\n");
167 htmlSvg.append(" myForm.submit() ;\n");
168 htmlSvg.append(" document.body.removeChild(myForm);\n");
169 htmlSvg.append("}\n");
171 if (jsonData != null)
173 // JQuery FaceBox for displaying raw BioJSON data");
174 File faceBoxJsFile = new File("examples/javascript/facebox-1.3.js");
177 htmlSvg.append(HTMLOutput.readFileAsString(faceBoxJsFile));
178 } catch (IOException e)
184 htmlSvg.append("</script>\n");
185 htmlSvg.append("</html>");
186 return htmlSvg.toString();
190 public boolean isEmbedData()
192 return Boolean.valueOf(
193 jalview.bin.Cache.getDefault("EXPORT_EMBBED_BIOJSON", "true"));
197 public boolean isLaunchInBrowserAfterExport()
207 String renderStyle = Cache.getDefault("HTML_RENDERING",
209 AtomicBoolean textOption = new AtomicBoolean(
210 !"Lineart".equals(renderStyle));
213 * configure the action to run on OK in the dialog
215 Runnable okAction = new Runnable()
220 doOutput(textOption.get());
225 * Prompt for character rendering style if preference is not set
227 if (renderStyle.equalsIgnoreCase("Prompt each time")
228 && !Jalview.isHeadlessMode())
230 LineartOptions svgOption = new LineartOptions("HTML", textOption);
231 svgOption.setResponseAction(1, new Runnable()
236 setProgressMessage(MessageManager.formatMessage(
237 "status.cancelled_image_export_operation",
241 svgOption.setResponseAction(0, okAction);
242 svgOption.showDialog();
243 /* no code here - JalviewJS cannot execute it */
248 * else (if preference set) just do the export action
250 doOutput(textOption.get());
252 } catch (OutOfMemoryError err)
254 System.out.println("########################\n" + "OUT OF MEMORY "
255 + generatedFile + "\n" + "########################");
256 new OOMWarning("Creating Image for " + generatedFile, err);
257 } catch (Exception e)
260 setProgressMessage(MessageManager
261 .formatMessage("info.error_creating_file", getDescription()));
266 * Builds and writes the image to the file specified by field
267 * <code>generatedFile</code>
269 * @param textCharacters
270 * true for Text character rendering, false for Lineart
272 protected void doOutput(boolean textCharacters)
276 AlignmentDimension aDimension = ap.getAlignmentDimension();
277 SVGGraphics2D idPanelGraphics = new SVGGraphics2D(
278 aDimension.getWidth(), aDimension.getHeight());
279 SVGGraphics2D alignPanelGraphics = new SVGGraphics2D(
280 aDimension.getWidth(), aDimension.getHeight());
281 if (!textCharacters) // Lineart selected
283 idPanelGraphics.setRenderingHint(
284 SVGHints.KEY_DRAW_STRING_TYPE,
285 SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
286 alignPanelGraphics.setRenderingHint(
287 SVGHints.KEY_DRAW_STRING_TYPE,
288 SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
290 if (ap.av.getWrapAlignment())
292 printWrapped(aDimension.getWidth(), aDimension.getHeight(), 0,
297 printUnwrapped(aDimension.getWidth(), aDimension.getHeight(),
298 0, idPanelGraphics, alignPanelGraphics);
301 String idPanelSvgData = idPanelGraphics.getSVGDocument();
302 String alignPanelSvgData = alignPanelGraphics.getSVGDocument();
303 String jsonData = getBioJSONData();
304 String htmlData = getHtml(idPanelSvgData, alignPanelSvgData,
305 jsonData, ap.av.getWrapAlignment());
306 FileOutputStream out = new FileOutputStream(generatedFile);
307 out.write(htmlData.getBytes());
310 setProgressMessage(MessageManager
311 .formatMessage("status.export_complete", getDescription()));
313 } catch (Exception e)
316 setProgressMessage(MessageManager
317 .formatMessage("info.error_creating_file", getDescription()));