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