JAL-3048 inlined 1-line methods, small refactor of ImageMaker.TYPE
[jalview.git] / src / jalview / util / ImageMaker.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.util;
22
23 import jalview.bin.Cache;
24 import jalview.bin.Jalview;
25 import jalview.gui.IProgressIndicator;
26 import jalview.gui.LineartOptions;
27 import jalview.io.JalviewFileChooser;
28
29 import java.awt.Component;
30 import java.awt.Graphics;
31 import java.awt.Graphics2D;
32 import java.awt.RenderingHints;
33 import java.awt.image.BufferedImage;
34 import java.io.File;
35 import java.io.FileOutputStream;
36
37 import javax.imageio.ImageIO;
38
39 import org.jfree.graphics2d.svg.SVGGraphics2D;
40 import org.jfree.graphics2d.svg.SVGHints;
41 import org.jibble.epsgraphics.EpsGraphics2D;
42
43 public class ImageMaker
44 {
45   public static final String SVG_DESCRIPTION = "Scalable Vector Graphics";
46
47   public static final String SVG_EXTENSION = "svg";
48
49   public static final String EPS_DESCRIPTION = "Encapsulated Postscript";
50
51   public static final String EPS_EXTENSION = "eps";
52
53   public static final String PNG_EXTENSION = "png";
54
55   public static final String PNG_DESCRIPTION = "Portable  network graphics";
56
57   public static final String HTML_EXTENSION = "html";
58
59   public static final String HTML_DESCRIPTION = "Hypertext Markup Language";
60
61   EpsGraphics2D pg;
62
63   SVGGraphics2D g2;
64
65   Graphics graphics;
66
67   FileOutputStream out;
68
69   BufferedImage bi;
70
71   TYPE type;
72
73   private IProgressIndicator pIndicator;
74
75   private long pSessionId;
76
77   private boolean headless;
78
79   public enum TYPE
80   {
81     EPS("EPS", MessageManager.getString("label.eps_file"), EPS_EXTENSION,
82             EPS_DESCRIPTION),
83     PNG("PNG", MessageManager.getString("label.png_image"), PNG_EXTENSION,
84             PNG_DESCRIPTION),
85     SVG("SVG", "SVG", SVG_EXTENSION, SVG_DESCRIPTION);
86
87     public final String name;
88
89     public final String label;
90
91     public final String extension;
92
93     public final String description;
94
95     TYPE(String name, String label, String ext, String desc)
96     {
97       this.name = name;
98       this.label = label;
99       this.extension = ext;
100       this.description = desc;
101     }
102
103     public String getName()
104     {
105       return name;
106     }
107
108     public JalviewFileChooser getChooser()
109     {
110       return new JalviewFileChooser(extension, description);
111     }
112
113     public String getLabel()
114     {
115       return label;
116     }
117
118   }
119
120   /**
121    * Constructor builds the image and writes it to file. If the supplied file
122    * name is null, the user is prompted for the output file.
123    * 
124    * @param parent
125    * @param type
126    * @param title
127    * @param width
128    * @param height
129    * @param file
130    * @param fileTitle
131    * @param pIndicator
132    * @param pSessionId
133    * @param headless
134    */
135   public ImageMaker(Component parent, TYPE type, String title, int width,
136           int height, File file, String fileTitle,
137           IProgressIndicator pIndicator, long pSessionId, boolean headless)
138   {
139     this.pIndicator = pIndicator;
140     this.type = type;
141     this.pSessionId = pSessionId;
142     this.headless = headless;
143     if (file == null && !Jalview.isHeadlessMode())
144     {
145       setProgressMessage(MessageManager.formatMessage(
146               "status.waiting_for_user_to_select_output_file", type.name));
147       JalviewFileChooser chooser;
148       chooser = type.getChooser();
149       chooser.setFileView(new jalview.io.JalviewFileView());
150       chooser.setDialogTitle(title);
151       chooser.setToolTipText(MessageManager.getString("action.save"));
152       int value = chooser.showSaveDialog(parent);
153
154       if (value == JalviewFileChooser.APPROVE_OPTION)
155       {
156         Cache.setProperty("LAST_DIRECTORY",
157                 chooser.getSelectedFile().getParent());
158         file = chooser.getSelectedFile();
159       }
160       else
161       {
162         setProgressMessage(MessageManager.formatMessage(
163                 "status.cancelled_image_export_operation", type.name));
164       }
165     }
166     // TODO JAL-3048 refactor to method called by constructor or callback
167     if (file != null)
168     {
169       try
170       {
171         out = new FileOutputStream(file);
172         setProgressMessage(null);
173         setProgressMessage(MessageManager.formatMessage(
174                 "status.exporting_alignment_as_x_file", type.getName()));
175         if (type == TYPE.SVG)
176         {
177           setupSVG(width, height, fileTitle);
178         }
179         else if (type == TYPE.EPS)
180         {
181           setupEPS(width, height, fileTitle);
182         }
183         else if (type == TYPE.PNG)
184         {
185           setupPNG(width, height);
186         }
187
188       } catch (Exception ex)
189       {
190         System.out.println("Error creating " + type.getName() + " file.");
191
192         setProgressMessage(MessageManager
193                 .formatMessage("info.error_creating_file", type.getName()));
194       }
195     }
196   }
197
198   public Graphics getGraphics()
199   {
200     return graphics;
201   }
202
203   public void writeImage()
204   {
205     try
206     {
207       switch (type)
208       {
209       case EPS:
210         pg.flush();
211         pg.close();
212         break;
213       case SVG:
214         String svgData = ((SVGGraphics2D) getGraphics()).getSVGDocument();
215         out.write(svgData.getBytes());
216         out.flush();
217         out.close();
218         break;
219       case PNG:
220         ImageIO.write(bi, PNG_EXTENSION, out);
221         out.flush();
222         out.close();
223         break;
224       }
225     } catch (Exception ex)
226     {
227       ex.printStackTrace();
228     }
229   }
230
231   void setupEPS(int width, int height, String title)
232   {
233     boolean accurateText = true;
234
235     String renderStyle = Cache.getDefault("EPS_RENDERING",
236             "Prompt each time");
237
238     // If we need to prompt, and if the GUI is visible then
239     // Prompt for EPS rendering style
240     if (renderStyle.equalsIgnoreCase("Prompt each time")
241             && !(System.getProperty("java.awt.headless") != null && System
242                     .getProperty("java.awt.headless").equals("true")))
243     {
244       LineartOptions eps = new LineartOptions("EPS_RENDERING", "EPS");
245       renderStyle = eps.getValue();
246
247       if (renderStyle == null || eps.cancelled)
248       {
249         setProgressMessage(MessageManager.formatMessage(
250                 "status.cancelled_image_export_operation", "EPS"));
251         return;
252       }
253     }
254
255     if (renderStyle.equalsIgnoreCase("text"))
256     {
257       accurateText = false;
258     }
259
260     try
261     {
262       pg = new EpsGraphics2D(title, out, 0, 0, width, height);
263       Graphics2D ig2 = pg;
264       ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
265               RenderingHints.VALUE_ANTIALIAS_ON);
266
267       pg.setAccurateTextMode(accurateText);
268
269       graphics = pg;
270       setProgressMessage(MessageManager
271               .formatMessage("status.export_complete", type.getName()));
272     } catch (Exception ex)
273     {
274       System.err.println("Error writing PNG: " + ex.toString());
275     }
276   }
277
278   void setupPNG(int width, int height)
279   {
280     bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
281     graphics = bi.getGraphics();
282     Graphics2D ig2 = (Graphics2D) graphics;
283     ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
284             RenderingHints.VALUE_ANTIALIAS_ON);
285     setProgressMessage(MessageManager
286             .formatMessage("status.export_complete", type.getName()));
287
288   }
289
290   void setupSVG(int width, int height, String title)
291   {
292
293     g2 = new SVGGraphics2D(width, height);
294     Graphics2D ig2 = g2;
295
296     String renderStyle = jalview.bin.Cache.getDefault("SVG_RENDERING",
297             "Prompt each time");
298
299     // If we need to prompt, and if the GUI is visible then
300     // Prompt for EPS rendering style
301     if (renderStyle.equalsIgnoreCase("Prompt each time")
302             && !(System.getProperty("java.awt.headless") != null && System
303                     .getProperty("java.awt.headless").equals("true")))
304     {
305       LineartOptions svgOption = new LineartOptions("SVG_RENDERING", "SVG");
306       renderStyle = svgOption.getValue();
307
308       if (renderStyle == null || svgOption.cancelled)
309       {
310         setProgressMessage(MessageManager.formatMessage(
311                 "status.cancelled_image_export_operation", "SVG"));
312         return;
313       }
314     }
315
316     if (renderStyle.equalsIgnoreCase("Lineart"))
317     {
318       ig2.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
319               SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
320     }
321
322     setProgressMessage(MessageManager
323             .formatMessage("status.export_complete", type.getName()));
324     graphics = g2;
325   }
326
327   static JalviewFileChooser getPNGChooser()
328   {
329     if (Jalview.isHeadlessMode())
330     {
331       return null;
332     }
333     return new JalviewFileChooser(PNG_EXTENSION, PNG_DESCRIPTION);
334   }
335
336   static JalviewFileChooser getEPSChooser()
337   {
338     if (Jalview.isHeadlessMode())
339     {
340       return null;
341     }
342     return new JalviewFileChooser(EPS_EXTENSION, EPS_DESCRIPTION);
343   }
344
345   private void setProgressMessage(String message)
346   {
347     if (pIndicator != null && !headless)
348     {
349       pIndicator.setProgressBar(message, pSessionId);
350     }
351   }
352
353   static JalviewFileChooser getSVGChooser()
354   {
355     if (Jalview.isHeadlessMode())
356     {
357       return null;
358     }
359     return new JalviewFileChooser(SVG_EXTENSION, SVG_DESCRIPTION);
360   }
361 }