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