2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
23 import java.awt.Component;
24 import java.awt.Graphics;
26 import java.util.concurrent.atomic.AtomicBoolean;
28 import jalview.bin.Cache;
29 import jalview.bin.Jalview;
30 import jalview.io.JalviewFileChooser;
31 import jalview.io.JalviewFileView;
32 import jalview.io.exceptions.ImageOutputException;
33 import jalview.util.ImageMaker;
34 import jalview.util.ImageMaker.TYPE;
35 import jalview.util.MessageManager;
36 import jalview.util.Platform;
37 import jalview.util.imagemaker.BitmapImageSizing;
40 * A class that marshals steps in exporting a view in image graphics format
42 * <li>prompts the user for the output file, if not already specified</li>
43 * <li>prompts the user for Text or Lineart character rendering, if
45 * <li>instantiates an ImageMaker to create the appropriate Graphics output
46 * context for the image format</li>
47 * <li>invokes a callback to do the work of writing to the graphics</li>
53 public class ImageExporter
55 // todo move interface to jalview.api? or replace with lambda?
57 * An interface for the callback that can be run to write the image on to the
58 * graphics object. The callback should throw any exceptions arising so they
59 * can be reported by this class.
61 public interface ImageWriterI
63 void exportImage(Graphics g) throws Exception;
66 private IProgressIndicator messageBoard;
68 private ImageWriterI imageWriter;
75 * Constructor given a callback handler to write graphics data, an (optional)
76 * target for status messages, image type and (optional) title for output file
83 public ImageExporter(ImageWriterI writer, IProgressIndicator statusBar,
84 TYPE type, String fileTitle)
86 this.imageWriter = writer;
87 this.messageBoard = statusBar;
88 this.imageType = type;
89 this.title = fileTitle;
93 * Prompts the user for output file and Text/Lineart options as required,
94 * configures a Graphics context for output, and makes a callback to the
95 * client code to perform the image output
98 * output file (if null, user is prompted to choose)
100 * parent component for any dialogs shown
104 * what the image is of e.g. Tree, Alignment
106 public void doExport(File file, Component parent, int width, int height,
107 String imageSource) throws ImageOutputException
109 doExport(file, parent, width, height, imageSource, null,
110 BitmapImageSizing.nullBitmapImageSizing());
113 public void doExport(File file, Component parent, int width, int height,
114 String imageSource, String renderer, BitmapImageSizing userBis) throws ImageOutputException
116 final long messageId = System.currentTimeMillis();
118 MessageManager.formatMessage(
119 "status.exporting_alignment_as_x_file", imageType),
123 * prompt user for output file if not provided
125 if (file == null && !Jalview.isHeadlessMode())
127 JalviewFileChooser chooser = imageType.getFileChooser();
128 chooser.setFileView(new JalviewFileView());
129 MessageManager.formatMessage("label.create_image_of",
130 imageType.getName(), imageSource);
131 String title = "Create " + imageType.getName()
132 + " image from alignment";
133 chooser.setDialogTitle(title);
134 chooser.setToolTipText(MessageManager.getString("action.save"));
135 int value = chooser.showSaveDialog(parent);
136 if (value != JalviewFileChooser.APPROVE_OPTION)
138 String msg = MessageManager.formatMessage(
139 "status.cancelled_image_export_operation", imageType.name);
140 setStatus(msg, messageId);
143 Cache.setProperty("LAST_DIRECTORY",
144 chooser.getSelectedFile().getParent());
145 file = chooser.getSelectedFile();
149 * Prompt for Text or Lineart (EPS/SVG) unless a preference is already set
150 * for this as EPS_RENDERING / SVG_RENDERING
151 * Always set to Text for JalviewJS as Lineart (glyph fonts) not available
153 String renderStyle = renderer == null
154 ? Cache.getDefault(imageType.getName() + "_RENDERING",
155 LineartOptions.PROMPT_EACH_TIME)
159 renderStyle = "Text";
161 AtomicBoolean textSelected = new AtomicBoolean(
162 !"Lineart".equals(renderStyle));
163 if ((imageType == TYPE.EPS || imageType == TYPE.SVG)
164 && LineartOptions.PROMPT_EACH_TIME.equals(renderStyle)
165 && !Jalview.isHeadlessMode())
167 final File chosenFile = file;
168 Runnable okAction = () -> {
169 exportImage(chosenFile, !textSelected.get(), width, height,
172 LineartOptions epsOption = new LineartOptions(TYPE.EPS.getName(),
174 epsOption.setResponseAction(1, () -> {
175 setStatus(MessageManager.formatMessage(
176 "status.cancelled_image_export_operation",
177 imageType.getName()), messageId);
179 epsOption.setResponseAction(0, okAction);
180 epsOption.showDialog();
181 /* no code here - JalviewJS cannot execute it */
186 * character rendering not required, or preference already set
187 * - just do the export
189 exportImage(file, !textSelected.get(), width, height, messageId,
195 * Constructs a suitable graphics context and passes it to the callback
196 * handler for the image to be written. Shows status messages for export in
197 * progress, complete, or failed as appropriate.
205 protected void exportImage(File chosenFile, boolean asLineart, int width,
206 int height, long messageId, BitmapImageSizing userBis)
208 String type = imageType.getName();
212 // MessageManager.formatMessage(
213 // "status.exporting_alignment_as_x_file", type),
215 ImageMaker im = new ImageMaker(imageType, width, height, chosenFile,
216 title, asLineart, userBis);
217 imageWriter.exportImage(im.getGraphics());
220 MessageManager.formatMessage("status.export_complete", type),
222 } catch (Exception e)
224 jalview.bin.Console.error(String.format("Error creating %s file: %s", type,
226 setStatus(MessageManager.formatMessage("info.error_creating_file",
232 * Asks the callback to show a status message with given id
237 void setStatus(String msg, long id)
239 if (messageBoard != null && !Jalview.isHeadlessMode())
241 messageBoard.setProgressBar(msg, id);