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