Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
HTMLOutput | 41 | 64 | 28 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ The Jalview Authors | |
4 | * | |
5 | * This file is part of Jalview. | |
6 | * | |
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. | |
11 | * | |
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. | |
16 | * | |
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. | |
20 | */ | |
21 | package jalview.io; | |
22 | ||
23 | import java.io.BufferedReader; | |
24 | import java.io.File; | |
25 | import java.io.IOException; | |
26 | import java.io.InputStreamReader; | |
27 | import java.net.URL; | |
28 | import java.util.Objects; | |
29 | ||
30 | import jalview.api.AlignExportSettingsI; | |
31 | import jalview.bin.Cache; | |
32 | import jalview.bin.Jalview; | |
33 | import jalview.datamodel.AlignExportSettingsAdapter; | |
34 | import jalview.datamodel.AlignmentExportData; | |
35 | import jalview.gui.AlignmentPanel; | |
36 | import jalview.gui.IProgressIndicator; | |
37 | import jalview.io.exceptions.ImageOutputException; | |
38 | import jalview.util.HttpUtils; | |
39 | import jalview.util.MessageManager; | |
40 | ||
41 | public abstract class HTMLOutput implements Runnable | |
42 | { | |
43 | protected AlignmentPanel ap; | |
44 | ||
45 | /* | |
46 | * key for progress or status messages | |
47 | */ | |
48 | protected long pSessionId; | |
49 | ||
50 | /* | |
51 | * (optional) place to write progress messages to | |
52 | */ | |
53 | protected IProgressIndicator pIndicator; | |
54 | ||
55 | protected File generatedFile; | |
56 | ||
57 | String _bioJson = null; | |
58 | ||
59 | private String description; | |
60 | ||
61 | /** | |
62 | * Constructor given an alignment panel (which should not be null) | |
63 | * | |
64 | * @param ap | |
65 | * @param desc | |
66 | */ | |
67 | 2 | public HTMLOutput(AlignmentPanel ap, String desc) |
68 | { | |
69 | 2 | this.ap = ap; |
70 | 2 | this.pIndicator = ap.alignFrame; |
71 | 2 | this.description = desc; |
72 | 2 | this.pSessionId = System.currentTimeMillis(); |
73 | } | |
74 | ||
75 | /** | |
76 | * Gets the BioJSON data as a string, with lazy evaluation (first time called | |
77 | * only). If the output format is configured not to embed BioJSON, returns | |
78 | * null. | |
79 | * | |
80 | * @return | |
81 | */ | |
82 | 2 | public String getBioJSONData() |
83 | { | |
84 | 2 | if (!isEmbedData()) |
85 | { | |
86 | 1 | return null; |
87 | } | |
88 | 1 | if (_bioJson == null) |
89 | { | |
90 | 1 | AlignExportSettingsI options = new AlignExportSettingsAdapter(true); |
91 | 1 | AlignmentExportData exportData = ap.getAlignViewport() |
92 | .getAlignExportData(options); | |
93 | 1 | _bioJson = new FormatAdapter(ap, options).formatSequences( |
94 | FileFormat.Json, exportData.getAlignment(), | |
95 | exportData.getOmitHidden(), exportData.getStartEndPostions(), | |
96 | ap.getAlignViewport().getAlignment().getHiddenColumns()); | |
97 | } | |
98 | ||
99 | 1 | return _bioJson; |
100 | } | |
101 | ||
102 | /** | |
103 | * Read a template file content as string | |
104 | * | |
105 | * @param file | |
106 | * - the file to be read | |
107 | * @return File content as String | |
108 | * @throws IOException | |
109 | */ | |
110 | 2 | public static String readFileAsString(File file) throws IOException |
111 | { | |
112 | 2 | InputStreamReader isReader = null; |
113 | 2 | BufferedReader buffReader = null; |
114 | 2 | StringBuilder sb = new StringBuilder(); |
115 | 2 | Objects.requireNonNull(file, "File must not be null!"); |
116 | 2 | @SuppressWarnings("deprecation") |
117 | URL url = file.toURL(); | |
118 | 2 | if (url != null) |
119 | { | |
120 | 2 | try |
121 | { | |
122 | 2 | isReader = new InputStreamReader(HttpUtils.openStream(url)); |
123 | 2 | buffReader = new BufferedReader(isReader); |
124 | 2 | String line; |
125 | 2 | String lineSeparator = System.getProperty("line.separator"); |
126 | ? | while ((line = buffReader.readLine()) != null) |
127 | { | |
128 | 9979 | sb.append(line).append(lineSeparator); |
129 | } | |
130 | ||
131 | } catch (Exception ex) | |
132 | { | |
133 | 0 | ex.printStackTrace(); |
134 | } finally | |
135 | { | |
136 | 2 | if (isReader != null) |
137 | { | |
138 | 2 | isReader.close(); |
139 | } | |
140 | ||
141 | 2 | if (buffReader != null) |
142 | { | |
143 | 2 | buffReader.close(); |
144 | } | |
145 | } | |
146 | } | |
147 | 2 | return sb.toString(); |
148 | } | |
149 | ||
150 | 0 | public static String getImageMapHTML() |
151 | { | |
152 | 0 | return new String("<html>\n" + "<head>\n" |
153 | + "<script language=\"JavaScript\">\n" | |
154 | + "var ns4 = document.layers;\n" | |
155 | + "var ns6 = document.getElementById && !document.all;\n" | |
156 | + "var ie4 = document.all;\n" + "offsetX = 0;\n" | |
157 | + "offsetY = 20;\n" + "var toolTipSTYLE=\"\";\n" | |
158 | + "function initToolTips()\n" + "{\n" + " if(ns4||ns6||ie4)\n" | |
159 | + " {\n" | |
160 | + " if(ns4) toolTipSTYLE = document.toolTipLayer;\n" | |
161 | + " else if(ns6) toolTipSTYLE = document.getElementById(\"toolTipLayer\").style;\n" | |
162 | + " else if(ie4) toolTipSTYLE = document.all.toolTipLayer.style;\n" | |
163 | + " if(ns4) document.captureEvents(Event.MOUSEMOVE);\n" | |
164 | + " else\n" + " {\n" | |
165 | + " toolTipSTYLE.visibility = \"visible\";\n" | |
166 | + " toolTipSTYLE.display = \"none\";\n" + " }\n" | |
167 | + " document.onmousemove = moveToMouseLoc;\n" + " }\n" | |
168 | + "}\n" + "function toolTip(msg, fg, bg)\n" + "{\n" | |
169 | + " if(toolTip.arguments.length < 1) // hide\n" + " {\n" | |
170 | + " if(ns4) toolTipSTYLE.visibility = \"hidden\";\n" | |
171 | + " else toolTipSTYLE.display = \"none\";\n" + " }\n" | |
172 | + " else // show\n" + " {\n" | |
173 | + " if(!fg) fg = \"#555555\";\n" | |
174 | + " if(!bg) bg = \"#FFFFFF\";\n" + " var content =\n" | |
175 | + " '<table border=\"0\" cellspacing=\"0\" cellpadding=\"1\" bgcolor=\"' + fg + '\"><td>' +\n" | |
176 | + " '<table border=\"0\" cellspacing=\"0\" cellpadding=\"1\" bgcolor=\"' + bg + \n" | |
177 | + " '\"><td align=\"center\"><font face=\"sans-serif\" color=\"' + fg +\n" | |
178 | + " '\" size=\"-2\"> ' + msg +\n" | |
179 | + " ' </font></td></table></td></table>';\n" | |
180 | + " if(ns4)\n" + " {\n" | |
181 | + " toolTipSTYLE.document.write(content);\n" | |
182 | + " toolTipSTYLE.document.close();\n" | |
183 | + " toolTipSTYLE.visibility = \"visible\";\n" + " }\n" | |
184 | + " if(ns6)\n" + " {\n" | |
185 | + " document.getElementById(\"toolTipLayer\").innerHTML = content;\n" | |
186 | + " toolTipSTYLE.display='block'\n" + " }\n" | |
187 | + " if(ie4)\n" + " {\n" | |
188 | + " document.all(\"toolTipLayer\").innerHTML=content;\n" | |
189 | + " toolTipSTYLE.display='block'\n" + " }\n" + " }\n" | |
190 | + "}\n" + "function moveToMouseLoc(e)\n" + "{\n" | |
191 | + " if(ns4||ns6)\n" + " {\n" + " x = e.pageX;\n" | |
192 | + " y = e.pageY;\n" + " }\n" + " else\n" + " {\n" | |
193 | + " x = event.x + document.body.scrollLeft;\n" | |
194 | + " y = event.y + document.body.scrollTop;\n" + " }\n" | |
195 | + " toolTipSTYLE.left = x + offsetX;\n" | |
196 | + " toolTipSTYLE.top = y + offsetY;\n" + " return true;\n" | |
197 | + "}\n" + "</script>\n" + "</head>\n" + "<body>\n" | |
198 | + "<div id=\"toolTipLayer\" style=\"position:absolute; visibility: hidden\"></div>\n" | |
199 | + "<script language=\"JavaScript\"><!--\n" | |
200 | + "initToolTips(); //--></script>\n"); | |
201 | ||
202 | } | |
203 | ||
204 | /** | |
205 | * Prompts the user to choose an output file and returns the file path, or | |
206 | * null on Cancel | |
207 | * | |
208 | * @return | |
209 | */ | |
210 | 0 | public String getOutputFile() |
211 | { | |
212 | 0 | String selectedFile = null; |
213 | ||
214 | // TODO: JAL-3048 generate html rendered view (requires SvgGraphics and/or | |
215 | // Jalview HTML rendering system- probably not required for Jalview-JS) | |
216 | 0 | JalviewFileChooser jvFileChooser = new JalviewFileChooser("html", |
217 | "HTML files"); | |
218 | 0 | jvFileChooser.setFileView(new JalviewFileView()); |
219 | ||
220 | 0 | jvFileChooser |
221 | .setDialogTitle(MessageManager.getString("label.save_as_html")); | |
222 | 0 | jvFileChooser.setToolTipText(MessageManager.getString("action.save")); |
223 | ||
224 | 0 | int fileChooserOpt = jvFileChooser.showSaveDialog(null); |
225 | 0 | if (fileChooserOpt == JalviewFileChooser.APPROVE_OPTION) |
226 | { | |
227 | 0 | Cache.setProperty("LAST_DIRECTORY", |
228 | jvFileChooser.getSelectedFile().getParent()); | |
229 | 0 | selectedFile = jvFileChooser.getSelectedFile().getPath(); |
230 | } | |
231 | ||
232 | 0 | return selectedFile; |
233 | } | |
234 | ||
235 | 4 | protected void setProgressMessage(String message) |
236 | { | |
237 | 4 | if (pIndicator != null && !isHeadless()) |
238 | { | |
239 | 0 | pIndicator.setProgressBar(message, pSessionId); |
240 | } | |
241 | else | |
242 | { | |
243 | 4 | jalview.bin.Console.outPrintln(message); |
244 | } | |
245 | } | |
246 | ||
247 | /** | |
248 | * Answers true if HTML export is invoke in headless mode or false otherwise | |
249 | * | |
250 | * @return | |
251 | */ | |
252 | 7 | protected boolean isHeadless() |
253 | { | |
254 | 7 | return System.getProperty("java.awt.headless") != null |
255 | && System.getProperty("java.awt.headless").equals("true"); | |
256 | } | |
257 | ||
258 | /** | |
259 | * This method provides implementation of consistent behaviour which should | |
260 | * occur after a HTML file export. It MUST be called at the end of the | |
261 | * exportHTML() method implementation. | |
262 | */ | |
263 | 2 | protected void exportCompleted() |
264 | { | |
265 | 2 | if (isLaunchInBrowserAfterExport() && !isHeadless()) |
266 | { | |
267 | /* | |
268 | try | |
269 | { | |
270 | */ | |
271 | 0 | jalview.util.BrowserLauncher.openURL("file:///" + getExportedFile()); |
272 | /* | |
273 | } catch (IOException e) | |
274 | { | |
275 | e.printStackTrace(); | |
276 | } | |
277 | */ | |
278 | } | |
279 | } | |
280 | ||
281 | /** | |
282 | * if this answers true then BioJSON data will be embedded to the exported | |
283 | * HTML file otherwise it won't be embedded. | |
284 | * | |
285 | * @return | |
286 | */ | |
287 | public abstract boolean isEmbedData(); | |
288 | ||
289 | /** | |
290 | * if this answers true then the generated HTML file is opened for viewing in | |
291 | * a browser after its generation otherwise it won't be opened in a browser | |
292 | * | |
293 | * @return | |
294 | */ | |
295 | public abstract boolean isLaunchInBrowserAfterExport(); | |
296 | ||
297 | /** | |
298 | * handle to the generated HTML file | |
299 | * | |
300 | * @return | |
301 | */ | |
302 | 0 | public File getExportedFile() |
303 | { | |
304 | 0 | return generatedFile; |
305 | } | |
306 | ||
307 | 1 | public void exportHTML(String outputFile) throws ImageOutputException |
308 | { | |
309 | 1 | exportHTML(outputFile, null); |
310 | } | |
311 | ||
312 | 2 | public void exportHTML(String outputFile, String renderer) |
313 | throws ImageOutputException | |
314 | { | |
315 | 2 | setProgressMessage(MessageManager.formatMessage( |
316 | "status.exporting_alignment_as_x_file", getDescription())); | |
317 | 2 | try |
318 | { | |
319 | 2 | if (outputFile == null) |
320 | { | |
321 | /* | |
322 | * prompt for output file | |
323 | */ | |
324 | 0 | outputFile = getOutputFile(); |
325 | 0 | if (outputFile == null) |
326 | { | |
327 | 0 | setProgressMessage(MessageManager.formatMessage( |
328 | "status.cancelled_image_export_operation", | |
329 | getDescription())); | |
330 | 0 | return; |
331 | } | |
332 | } | |
333 | 2 | generatedFile = new File(outputFile); |
334 | } catch (Exception e) | |
335 | { | |
336 | 0 | setProgressMessage(MessageManager |
337 | .formatMessage("info.error_creating_file", getDescription())); | |
338 | 0 | e.printStackTrace(); |
339 | 0 | return; |
340 | } | |
341 | 2 | if (Jalview.isHeadlessMode()) |
342 | { | |
343 | 2 | this.run(renderer); |
344 | } | |
345 | else | |
346 | { | |
347 | 0 | new Thread(this).start(); |
348 | } | |
349 | ||
350 | } | |
351 | ||
352 | /** | |
353 | * Answers a short description of the image format suitable for display in | |
354 | * messages | |
355 | * | |
356 | * @return | |
357 | */ | |
358 | 4 | protected final String getDescription() |
359 | { | |
360 | 4 | return description; |
361 | } | |
362 | ||
363 | // used to pass an option such as render to run | |
364 | public abstract void run(String string) throws ImageOutputException; | |
365 | } |