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