JAL-3048 JalviewJS compliant use of LineartOptions dialog
[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.datamodel.AlignExportSettingsAdapter;
25 import jalview.datamodel.AlignmentExportData;
26 import jalview.exceptions.NoFileSelectedException;
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   public String getOutputFile() throws NoFileSelectedException
191   {
192     String selectedFile = null;
193     if (pIndicator != null && !isHeadless())
194     {
195       pIndicator.setProgressBar(MessageManager.formatMessage(
196               "status.waiting_for_user_to_select_output_file", "HTML"),
197               pSessionId);
198     }
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       jalview.bin.Cache.setProperty("LAST_DIRECTORY",
214               jvFileChooser.getSelectedFile().getParent());
215       selectedFile = jvFileChooser.getSelectedFile().getPath();
216     }
217     else
218     {
219       throw new NoFileSelectedException("No file was selected.");
220     }
221     return selectedFile;
222   }
223
224   protected void setProgressMessage(String message)
225   {
226     if (pIndicator != null && !isHeadless())
227     {
228       pIndicator.setProgressBar(message, pSessionId);
229     }
230     else
231     {
232       System.out.println(message);
233     }
234   }
235
236   /**
237    * Answers true if HTML export is invoke in headless mode or false otherwise
238    * 
239    * @return
240    */
241   protected boolean isHeadless()
242   {
243     return System.getProperty("java.awt.headless") != null
244             && System.getProperty("java.awt.headless").equals("true");
245   }
246
247   /**
248    * This method provides implementation of consistent behaviour which should
249    * occur before a HTML file export. It MUST be called at the start of the
250    * exportHTML() method implementation.
251    */
252   protected void exportStarted()
253   {
254     pSessionId = System.currentTimeMillis();
255   }
256
257   /**
258    * This method provides implementation of consistent behaviour which should
259    * occur after a HTML file export. It MUST be called at the end of the
260    * exportHTML() method implementation.
261    */
262   protected void exportCompleted()
263   {
264     if (isLaunchInBrowserAfterExport() && !isHeadless())
265     {
266       try
267       {
268         jalview.util.BrowserLauncher
269                 .openURL("file:///" + getExportedFile());
270       } catch (IOException e)
271       {
272         e.printStackTrace();
273       }
274     }
275   }
276
277   /**
278    * if this answers true then BioJSON data will be embedded to the exported
279    * HTML file otherwise it won't be embedded.
280    * 
281    * @return
282    */
283   public abstract boolean isEmbedData();
284
285   /**
286    * if this answers true then the generated HTML file is opened for viewing in
287    * a browser after its generation otherwise it won't be opened in a browser
288    * 
289    * @return
290    */
291   public abstract boolean isLaunchInBrowserAfterExport();
292
293   /**
294    * handle to the generated HTML file
295    * 
296    * @return
297    */
298   public abstract File getExportedFile();
299
300   /**
301    * This is the main method to handle the HTML generation.
302    * 
303    * @param outputFile
304    *          the file path of the generated HTML
305    */
306   public abstract void exportHTML(String outputFile);
307 }