JAL-3048 JalviewJS compliant use of LineartOptions dialog
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 20 Jul 2018 10:04:19 +0000 (11:04 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 20 Jul 2018 10:04:19 +0000 (11:04 +0100)
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/LineartOptions.java
src/jalview/gui/TreePanel.java
src/jalview/io/HTMLOutput.java
src/jalview/io/HtmlSvgOutput.java
src/jalview/jbgui/GTreePanel.java
src/jalview/util/ImageMaker.java

index e1d4800..6e46781 100644 (file)
@@ -1279,9 +1279,16 @@ public class AlignmentPanel extends GAlignmentPanel implements
     return idwidth.intValue() + 4;
   }
 
-  void makeAlignmentImage(jalview.util.ImageMaker.TYPE type, File file)
+  /**
+   * Builds an image of the alignment of the specified type (EPS/PNG/SVG) and
+   * writes it to the specified file
+   * 
+   * @param type
+   * @param file
+   */
+  void makeAlignmentImage(ImageMaker.TYPE type, File file)
   {
-    int boarderBottomOffset = 5;
+    int borderBottomOffset = 5;
     long pSessionId = System.currentTimeMillis();
     headless = (System.getProperty("java.awt.headless") != null
             && System.getProperty("java.awt.headless").equals("true"));
@@ -1297,64 +1304,39 @@ public class AlignmentPanel extends GAlignmentPanel implements
     try
     {
       AlignmentDimension aDimension = getAlignmentDimension();
-      try
+      String imageAction = "Create " + type.getName()
+              + " image from alignment";
+      String imageTitle = alignFrame.getTitle();
+
+      ImageMaker im = new ImageMaker(this, type, imageAction,
+              aDimension.getWidth(),
+              aDimension.getHeight() + borderBottomOffset, file, imageTitle,
+              alignFrame, pSessionId, headless);
+      Graphics graphics = im.getGraphics();
+      if (graphics != null)
       {
-        ImageMaker im;
-        final String imageAction, imageTitle;
-        if (type == ImageMaker.TYPE.PNG)
-        {
-          imageAction = "Create PNG image from alignment";
-          imageTitle = null;
-        }
-        else if (type == ImageMaker.TYPE.EPS)
-        {
-          imageAction = "Create EPS file from alignment";
-          imageTitle = alignFrame.getTitle();
-        }
-        else
-        {
-          imageAction = "Create SVG file from alignment";
-          imageTitle = alignFrame.getTitle();
-        }
-
-        im = new ImageMaker(this, type, imageAction, aDimension.getWidth(),
-                aDimension.getHeight() + boarderBottomOffset, file,
-                imageTitle, alignFrame, pSessionId, headless);
-        Graphics graphics = im.getGraphics();
         if (av.getWrapAlignment())
         {
-          if (graphics != null)
-          {
-            printWrappedAlignment(aDimension.getWidth(),
-                    aDimension.getHeight() + boarderBottomOffset, 0,
-                    graphics);
-            im.writeImage();
-          }
+          printWrappedAlignment(aDimension.getWidth(),
+                  aDimension.getHeight() + borderBottomOffset, 0, graphics);
         }
         else
         {
-          if (graphics != null)
-          {
-            printUnwrapped(aDimension.getWidth(), aDimension.getHeight(), 0,
-                    graphics, graphics);
-            im.writeImage();
-          }
+          printUnwrapped(aDimension.getWidth(), aDimension.getHeight(), 0,
+                  graphics, graphics);
         }
-
-      } catch (OutOfMemoryError err)
-      {
-        // Be noisy here.
-        System.out.println("########################\n" + "OUT OF MEMORY "
-                + file + "\n" + "########################");
-        new OOMWarning("Creating Image for " + file, err);
-        // System.out.println("Create IMAGE: " + err);
-      } catch (Exception ex)
-      {
-        ex.printStackTrace();
+        im.writeImage();
       }
-    } finally
+    } catch (OutOfMemoryError err)
     {
-
+      // Be noisy here.
+      System.out.println("########################\n" + "OUT OF MEMORY "
+              + file + "\n" + "########################");
+      new OOMWarning("Creating Image for " + file, err);
+      // System.out.println("Create IMAGE: " + err);
+    } catch (Exception ex)
+    {
+      ex.printStackTrace();
     }
   }
 
index 1fded80..1dd030b 100644 (file)
@@ -22,18 +22,17 @@ package jalview.gui;
 
 import jalview.bin.Cache;
 import jalview.util.MessageManager;
+import jalview.util.dialogrunner.RunResponse;
 
-import java.awt.BorderLayout;
+import java.awt.FlowLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.swing.BorderFactory;
 import javax.swing.ButtonGroup;
-import javax.swing.JButton;
 import javax.swing.JCheckBox;
-import javax.swing.JDialog;
 import javax.swing.JLabel;
-import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JRadioButton;
 
@@ -43,7 +42,7 @@ import javax.swing.JRadioButton;
  */
 public class LineartOptions extends JPanel
 {
-  JDialog dialog;
+  JvOptionPane dialog;
 
   public boolean cancelled = false;
 
@@ -53,16 +52,31 @@ public class LineartOptions extends JPanel
 
   JCheckBox askAgainCB = new JCheckBox();
 
+  AtomicBoolean asText;
+
+  private String dialogTitle;
+
   /**
-   * Constructor
+   * Constructor that passes in an initial choice of Text or Lineart, as a
+   * mutable boolean object. User action in the dialog should update this
+   * object, and the <em>same</em> object should be used in any action handler
+   * set by calling <code>setResponseAction</code>.
    * 
    * @param preferencesKey
    *          the key under which the choice is saved as a user preference, if
    *          'Don't ask me again' is selected
    * @param formatType
+   *          image type e.g. EPS, SVG
+   * @param textOption
+   *          true to select Text, false for Lineart
    */
-  public LineartOptions(String preferencesKey, String formatType)
+  public LineartOptions(String preferencesKey, String formatType,
+          AtomicBoolean textOption)
   {
+    this.asText = textOption;
+    dialogTitle = MessageManager.formatMessage(
+            "label.select_character_style_title", formatType);
+
     try
     {
       jbInit(preferencesKey, formatType);
@@ -71,109 +85,110 @@ public class LineartOptions extends JPanel
       ex.printStackTrace();
     }
 
-    JOptionPane pane = new JOptionPane(null, JvOptionPane.DEFAULT_OPTION,
-            JvOptionPane.DEFAULT_OPTION, null, new Object[]
-            { this });
+    dialog = JvOptionPane.newOptionDialog(Desktop.desktop);
+  }
 
-    String theTitle = MessageManager.formatMessage(
-            "label.select_character_style_title", formatType);
-    dialog = pane.createDialog(Desktop.desktop, theTitle);
-    dialog.setVisible(true);
+  /**
+   * Registers a Runnable action to be performed for a particular user response
+   * in the dialog
+   * 
+   * @param action
+   */
+  public void setResponseAction(RunResponse action)
+  {
+    dialog.response(action);
+  }
+
+  /**
+   * Shows the dialog, and performs any registered actions depending on the user
+   * choices
+   */
+  public void showDialog()
+  {
+    Object[] options = new Object[] { MessageManager.getString("action.ok"),
+        MessageManager.getString("action.cancel") };
+    dialog.showInternalDialog(this, dialogTitle,
+            JvOptionPane.OK_CANCEL_OPTION, JvOptionPane.PLAIN_MESSAGE, null,
+            options, MessageManager.getString("action.ok"));
   }
 
+  /**
+   * Initialises the panel layout
+   * 
+   * @param preferencesKey
+   * @param formatType
+   * @throws Exception
+   */
   private void jbInit(String preferencesKey, String formatType)
           throws Exception
   {
+    /*
+     * radio buttons for Text or Lineart - selection updates the value
+     * of field 'asText' so it is correct when used in the confirm action
+     */
     lineartRB = new JRadioButton(MessageManager.getString("label.lineart"));
     lineartRB.setFont(JvSwingUtils.getLabelFont());
-    JRadioButton text = new JRadioButton(
-            MessageManager.getString("action.text"));
-    text.setFont(JvSwingUtils.getLabelFont());
-    text.setSelected(true);
-
-    ButtonGroup bg = new ButtonGroup();
-    bg.add(lineartRB);
-    bg.add(text);
-
-    askAgainCB.setFont(JvSwingUtils.getLabelFont());
-    askAgainCB.setText(MessageManager.getString("label.dont_ask_me_again"));
-    JButton ok = new JButton(MessageManager.getString("action.ok"));
-    ok.addActionListener(new ActionListener()
+    lineartRB.setSelected(!asText.get());
+    lineartRB.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        ok_actionPerformed(preferencesKey);
+        asText.set(!lineartRB.isSelected());
       }
     });
-    JButton cancel = new JButton(MessageManager.getString("action.cancel"));
-    cancel.addActionListener(new ActionListener()
+
+    JRadioButton textRB = new JRadioButton(
+            MessageManager.getString("action.text"));
+    textRB.setFont(JvSwingUtils.getLabelFont());
+    textRB.setSelected(asText.get());
+    textRB.addActionListener(new ActionListener()
     {
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        cancel_actionPerformed(e);
+        asText.set(textRB.isSelected());
       }
     });
-    JLabel jLabel1 = new JLabel(MessageManager.formatMessage(
+
+    ButtonGroup bg = new ButtonGroup();
+    bg.add(lineartRB);
+    bg.add(textRB);
+
+    askAgainCB.setFont(JvSwingUtils.getLabelFont());
+    askAgainCB.setText(MessageManager.getString("label.dont_ask_me_again"));
+
+    JLabel prompt = new JLabel(MessageManager.formatMessage(
             "label.select_character_rendering_style", formatType));
-    jLabel1.setFont(JvSwingUtils.getLabelFont());
-
-    this.setLayout(new BorderLayout());
-    JPanel jPanel3 = new JPanel();
-    jPanel3.setBorder(BorderFactory.createEtchedBorder());
-    JPanel optionsPanel = new JPanel();
-    optionsPanel.add(text);
-    optionsPanel.add(lineartRB);
-    optionsPanel.add(askAgainCB);
-    JPanel okCancelPanel = new JPanel();
-    okCancelPanel.add(ok);
-    okCancelPanel.add(cancel);
-    jPanel3.add(jLabel1);
-    jPanel3.add(optionsPanel);
-    this.add(jPanel3, BorderLayout.CENTER);
-    this.add(okCancelPanel, BorderLayout.SOUTH);
+    prompt.setFont(JvSwingUtils.getLabelFont());
+
+    this.setLayout(new FlowLayout(FlowLayout.LEFT));
+    setBorder(BorderFactory.createEtchedBorder());
+    add(prompt);
+    add(textRB);
+    add(lineartRB);
+    add(askAgainCB);
   }
 
   /**
-   * Action on OK is to save the selected option as the <code>value</code> field
-   * and close the dialog. If "Don't ask me again" is selected, it is also saved
-   * as user preference, otherwise the existing user preference (if any) is
-   * removed.
+   * If "Don't ask me again" is selected, saves the selected option as the user
+   * preference, otherwise removes the existing user preference (if any) is
+   * removed
    * 
    * @param preferencesKey
    */
-  protected void ok_actionPerformed(String preferencesKey)
+  protected void updatePreference(String preferencesKey)
   {
-    if (lineartRB.isSelected())
-    {
-      value = "Lineart";
-    }
-    else
-    {
-      value = "Text";
-    }
+    value = lineartRB.isSelected() ? "Lineart" : "Text";
 
-    if (!askAgainCB.isSelected())
+    if (askAgainCB.isSelected())
     {
-      Cache.applicationProperties.remove(preferencesKey);
+      Cache.setProperty(preferencesKey, value);
     }
     else
     {
-      Cache.setProperty(preferencesKey, value);
+      Cache.applicationProperties.remove(preferencesKey);
     }
-    dialog.setVisible(false);
-  }
-
-  /**
-   * Action on Cancel is to hide the dialog
-   * 
-   * @param e
-   */
-  protected void cancel_actionPerformed(ActionEvent e)
-  {
-    cancelled = true;
-    dialog.setVisible(false);
   }
 
   /**
@@ -183,6 +198,7 @@ public class LineartOptions extends JPanel
    */
   public String getValue()
   {
+    // todo remove
     return value;
   }
 }
index eb2397c..fefa77f 100755 (executable)
@@ -47,6 +47,7 @@ import jalview.io.NewickFile;
 import jalview.jbgui.GTreePanel;
 import jalview.util.ImageMaker;
 import jalview.util.MessageManager;
+import jalview.util.dialogrunner.RunResponse;
 import jalview.viewmodel.AlignmentViewport;
 
 import java.awt.Font;
@@ -56,13 +57,16 @@ import java.awt.event.ActionListener;
 import java.awt.image.BufferedImage;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
+import java.io.File;
 import java.io.FileOutputStream;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.imageio.ImageIO;
 import javax.swing.ButtonGroup;
 import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
 import javax.swing.JRadioButtonMenuItem;
 import javax.swing.event.InternalFrameAdapter;
 import javax.swing.event.InternalFrameEvent;
@@ -658,77 +662,65 @@ public class TreePanel extends GTreePanel
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
+   * Outputs the Tree in EPS format. The user is prompted for the file to save
+   * to, and (unless a preference is already set) for the choice of Text or
+   * Lineart for character rendering.
    */
   @Override
-  public void epsTree_actionPerformed(ActionEvent e)
+  public void epsTree_actionPerformed()
   {
-    boolean accurateText = true;
-
-    String renderStyle = jalview.bin.Cache.getDefault("EPS_RENDERING",
-            "Prompt each time");
-
-    // If we need to prompt, and if the GUI is visible then
-    // Prompt for EPS rendering style
-    if (renderStyle.equalsIgnoreCase("Prompt each time")
-            && !(System.getProperty("java.awt.headless") != null && System
-                    .getProperty("java.awt.headless").equals("true")))
-    {
-      LineartOptions eps = new LineartOptions("EPS_RENDERING", "EPS");
-      renderStyle = eps.getValue();
-
-      if (renderStyle == null || eps.cancelled)
-      {
-        return;
-      }
+    JalviewFileChooser chooser = new JalviewFileChooser(
+            ImageMaker.EPS_EXTENSION, ImageMaker.EPS_EXTENSION);
+    chooser.setFileView(new JalviewFileView());
+    chooser.setDialogTitle(
+            MessageManager.getString("label.create_eps_from_tree"));
+    chooser.setToolTipText(MessageManager.getString("action.save"));
 
-    }
+    int value = chooser.showSaveDialog(this);
 
-    if (renderStyle.equalsIgnoreCase("text"))
+    if (value != JalviewFileChooser.APPROVE_OPTION)
     {
-      accurateText = false;
+      return;
     }
+    File outFile = chooser.getSelectedFile();
+    Cache.setProperty("LAST_DIRECTORY", outFile.getParent());
 
-    int width = treeCanvas.getWidth();
-    int height = treeCanvas.getHeight();
+    String renderStyle = Cache.getDefault("EPS_RENDERING",
+            "Prompt each time");
+    AtomicBoolean textOption = new AtomicBoolean(
+            !"Lineart".equals(renderStyle));
 
-    try
+    /*
+     * configure the export action to run on OK in the dialog
+     */
+    RunResponse okAction = new RunResponse(JOptionPane.OK_OPTION)
     {
-      // TODO: JAL-3048 not needed for Jalview-JS - Requires EpsGraphics2D dependency
-      JalviewFileChooser chooser = new JalviewFileChooser(
-              ImageMaker.EPS_EXTENSION, ImageMaker.EPS_EXTENSION);
-      chooser.setFileView(new JalviewFileView());
-      chooser.setDialogTitle(
-              MessageManager.getString("label.create_eps_from_tree"));
-      chooser.setToolTipText(MessageManager.getString("action.save"));
-
-      int value = chooser.showSaveDialog(this);
-
-      if (value != JalviewFileChooser.APPROVE_OPTION)
+      @Override
+      public void run()
       {
-        return;
+        writeEpsFile(outFile, textOption.get());
       }
+    };
 
-      Cache.setProperty("LAST_DIRECTORY",
-              chooser.getSelectedFile().getParent());
-
-      FileOutputStream out = new FileOutputStream(
-              chooser.getSelectedFile());
-      EpsGraphics2D pg = new EpsGraphics2D("Tree", out, 0, 0, width,
-              height);
-
-      pg.setAccurateTextMode(accurateText);
-
-      treeCanvas.draw(pg, width, height);
-
-      pg.flush();
-      pg.close();
-    } catch (Exception ex)
+    /*
+     * Prompt for character rendering style if preference is not set
+     */
+    if (renderStyle.equalsIgnoreCase("Prompt each time")
+            && !(System.getProperty("java.awt.headless") != null && System
+                    .getProperty("java.awt.headless").equals("true")))
     {
-      ex.printStackTrace();
+      LineartOptions eps = new LineartOptions("EPS_RENDERING", "EPS",
+              textOption);
+      eps.setResponseAction(okAction);
+      eps.showDialog();
+      /* no code here - JalviewJS won't execute it */
+    }
+    else
+    {
+      /*
+       * if preference set, just run the export action
+       */
+      writeEpsFile(outFile, textOption.get());
     }
   }
 
@@ -741,7 +733,6 @@ public class TreePanel extends GTreePanel
   @Override
   public void pngTree_actionPerformed(ActionEvent e)
   {
-    // TODO: JAL-3048 image export supported in JalviewJS ?
     int width = treeCanvas.getWidth();
     int height = treeCanvas.getHeight();
 
@@ -886,4 +877,34 @@ public class TreePanel extends GTreePanel
             treecalcnm, smn);
     return ttl;
   }
+
+  /**
+   * Builds an EPS image and writes it to the specified file.
+   * 
+   * @param outFile
+   * @param textOption
+   *          true for Text character rendering, false for Lineart
+   */
+  protected void writeEpsFile(File outFile, boolean textOption)
+  {
+    try
+    {
+      int width = treeCanvas.getWidth();
+      int height = treeCanvas.getHeight();
+
+      FileOutputStream out = new FileOutputStream(
+              outFile);
+      EpsGraphics2D pg = new EpsGraphics2D("Tree", out, 0, 0, width,
+              height);
+      pg.setAccurateTextMode(!textOption);
+      treeCanvas.draw(pg, width, height);
+
+      pg.flush();
+      pg.close();
+    } catch (Exception ex)
+    {
+      System.err.println("Error writing tree as EPS");
+      ex.printStackTrace();
+    }
+  }
 }
index 3a7b441..86da67a 100644 (file)
  */
 package jalview.io;
 
-import jalview.api.AlignExportSettingI;
-import jalview.datamodel.AlignExportSettingBeanI;
+import jalview.api.AlignExportSettingsI;
+import jalview.datamodel.AlignExportSettingsAdapter;
 import jalview.datamodel.AlignmentExportData;
 import jalview.exceptions.NoFileSelectedException;
 import jalview.gui.AlignmentPanel;
 import jalview.gui.IProgressIndicator;
 import jalview.util.MessageManager;
 
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
@@ -47,93 +45,44 @@ public abstract class HTMLOutput implements Runnable
 
   protected File generatedFile;
 
+  String _bioJson = null;
+
+  /**
+   * Constructor given an alignment panel (which should not be null)
+   * 
+   * @param ap
+   */
   public HTMLOutput(AlignmentPanel ap)
   {
-    if (ap != null)
-    {
-      this.ap = ap;
-      this.pIndicator = ap.alignFrame;
-    }
+    this.ap = ap;
+    this.pIndicator = ap.alignFrame;
   }
 
-  String _bioJson=null;
+  /**
+   * Gets the BioJSON data as a string, with lazy evaluation (first time called
+   * only). If the output format is configured not to embed BioJSON, returns
+   * null.
+   * 
+   * @return
+   */
   public String getBioJSONData()
   {
-    if (_bioJson==null) {
-      getBioJSONData(null);
-    }
-    return _bioJson;
-  }
-
-  public void getBioJSONData(AlignExportSettingBeanI exportSettings)
-  {
     if (!isEmbedData())
     {
-      return;
+      return null;
     }
-    if (exportSettings == null)
+    if (_bioJson == null)
     {
-      exportSettings = new AlignExportSettingBeanI()
-      {
-        @Override
-        public boolean isExportHiddenSequences()
-        {
-          return true;
-        }
-
-        @Override
-        public boolean isExportHiddenColumns()
-        {
-          return true;
-        }
-
-        @Override
-        public boolean isExportAnnotations()
-        {
-          return true;
-        }
-
-        @Override
-        public boolean isExportFeatures()
-        {
-          return true;
-        }
-
-        @Override
-        public boolean isExportGroups()
-        {
-          return true;
-        }
-
-        @Override
-        public boolean isCancelled()
-        {
-          return false;
-        }
-        
-      };
+      AlignExportSettingsI options = new AlignExportSettingsAdapter(true);
+      AlignmentExportData exportData = ap.getAlignViewport()
+              .getAlignExportData(options);
+      _bioJson = new FormatAdapter(ap, options).formatSequences(
+              FileFormat.Json, exportData.getAlignment(),
+              exportData.getOmitHidden(), exportData.getStartEndPostions(),
+              ap.getAlignViewport().getAlignment().getHiddenColumns());
     }
-    AlignExportSettingI exportDataSettings = jalview.gui.AlignFrame
-            .getAlignmentForExport(FileFormat.Json, ap,
-                    exportSettings);
-    exportDataSettings.addActionListener(new ActionListener()
-    {
-      
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        AlignmentExportData exportData = exportDataSettings.getAlignExportData();
-        _bioJson = new FormatAdapter(ap, exportData.getSettings())
-                .formatSequences(FileFormat.Json, exportData.getAlignment(),
-                        exportData.getOmitHidden(),
-                        exportData.getStartEndPostions(), ap.getAlignViewport()
-                                .getAlignment().getHiddenColumns());
-        
-      }
-    
-      
-    });
-    exportDataSettings.doShowSettings();
+
+    return _bioJson;
   }
 
   /**
index a184185..30c40a9 100644 (file)
  */
 package jalview.io;
 
+import jalview.bin.Cache;
 import jalview.exceptions.NoFileSelectedException;
 import jalview.gui.AlignmentPanel;
 import jalview.gui.LineartOptions;
 import jalview.gui.OOMWarning;
 import jalview.math.AlignmentDimension;
 import jalview.util.MessageManager;
+import jalview.util.dialogrunner.RunResponse;
 
 import java.awt.Graphics;
 import java.awt.print.PrinterException;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.swing.JOptionPane;
 
 import org.jfree.graphics2d.svg.SVGGraphics2D;
 import org.jfree.graphics2d.svg.SVGHints;
@@ -84,7 +89,7 @@ public class HtmlSvgOutput extends HTMLOutput
     return ap.printWrappedAlignment(pwidth, pheight, pi, pg[0]);
   }
 
-  private String getHtml(String titleSvg, String alignmentSvg,
+  String getHtml(String titleSvg, String alignmentSvg,
           String jsonData, boolean wrapped)
   {
     StringBuilder htmlSvg = new StringBuilder();
@@ -238,36 +243,87 @@ public class HtmlSvgOutput extends HTMLOutput
       setProgressMessage(null);
       setProgressMessage(MessageManager.formatMessage(
               "status.exporting_alignment_as_x_file", "HTML"));
-      AlignmentDimension aDimension = ap.getAlignmentDimension();
-      SVGGraphics2D idPanelGraphics = new SVGGraphics2D(
-              aDimension.getWidth(), aDimension.getHeight());
-      SVGGraphics2D alignPanelGraphics = new SVGGraphics2D(
-              aDimension.getWidth(), aDimension.getHeight());
 
-      String renderStyle = jalview.bin.Cache.getDefault("HTML_RENDERING",
+      String renderStyle = Cache.getDefault("HTML_RENDERING",
               "Prompt each time");
+      AtomicBoolean textOption = new AtomicBoolean(
+              !"Lineart".equals(renderStyle));
+
+      /*
+       * configure the action to run on OK in the dialog
+       */
+      RunResponse okAction = new RunResponse(JOptionPane.OK_OPTION)
+      {
+        @Override
+        public void run()
+        {
+          doOutput(textOption.get());
+        }
+      };
 
-      // If we need to prompt, and if the GUI is visible then
-      // Prompt for rendering style
+      /*
+       * Prompt for character rendering style if preference is not set
+       */
       if (renderStyle.equalsIgnoreCase("Prompt each time") && !isHeadless())
       {
         LineartOptions svgOption = new LineartOptions("HTML_RENDERING",
-                "HTML");
-        renderStyle = svgOption.getValue();
-
-        if (renderStyle == null || svgOption.cancelled)
+                "HTML", textOption);
+        svgOption.setResponseAction(new RunResponse(JOptionPane.NO_OPTION)
         {
-          setProgressMessage(MessageManager.formatMessage(
-                  "status.cancelled_image_export_operation", "HTML"));
-          return;
-        }
+          @Override
+          public void run()
+          {
+            setProgressMessage(MessageManager.formatMessage(
+                    "status.cancelled_image_export_operation", "HTML"));
+          }
+        });
+        svgOption.setResponseAction(okAction);
+        svgOption.showDialog();
+        /* no code here - JalviewJS cannot execute it */
+      }
+      else
+      {
+        /*
+         * else (if preference set) just do the export action
+         */
+        doOutput(textOption.get());
       }
+    } catch (OutOfMemoryError err)
+    {
+      System.out.println("########################\n" + "OUT OF MEMORY "
+              + generatedFile + "\n" + "########################");
+      new OOMWarning("Creating Image for " + generatedFile, err);
+    } catch (Exception e)
+    {
+      e.printStackTrace();
+      setProgressMessage(MessageManager
+              .formatMessage("info.error_creating_file", "HTML"));
+    }
+  }
 
-      if (renderStyle.equalsIgnoreCase("Lineart"))
+  /**
+   * Builds and writes the image to the file specified by field
+   * <code>generatedFile</code>
+   * 
+   * @param textCharacters
+   *          true for Text character rendering, false for Lineart
+   */
+  protected void doOutput(boolean textCharacters)
+  {
+    try
+    {
+      AlignmentDimension aDimension = ap.getAlignmentDimension();
+      SVGGraphics2D idPanelGraphics = new SVGGraphics2D(
+              aDimension.getWidth(), aDimension.getHeight());
+      SVGGraphics2D alignPanelGraphics = new SVGGraphics2D(
+              aDimension.getWidth(), aDimension.getHeight());
+      if (!textCharacters) // Lineart selected
       {
-        idPanelGraphics.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
+        idPanelGraphics.setRenderingHint(
+                SVGHints.KEY_DRAW_STRING_TYPE,
                 SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
-        alignPanelGraphics.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
+        alignPanelGraphics.setRenderingHint(
+                SVGHints.KEY_DRAW_STRING_TYPE,
                 SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
       }
       if (ap.av.getWrapAlignment())
@@ -277,15 +333,15 @@ public class HtmlSvgOutput extends HTMLOutput
       }
       else
       {
-        printUnwrapped(aDimension.getWidth(), aDimension.getHeight(), 0,
-                idPanelGraphics, alignPanelGraphics);
+        printUnwrapped(aDimension.getWidth(), aDimension.getHeight(),
+                0, idPanelGraphics, alignPanelGraphics);
       }
 
       String idPanelSvgData = idPanelGraphics.getSVGDocument();
       String alignPanelSvgData = alignPanelGraphics.getSVGDocument();
       String jsonData = getBioJSONData();
-      String htmlData = getHtml(idPanelSvgData, alignPanelSvgData, jsonData,
-              ap.av.getWrapAlignment());
+      String htmlData = getHtml(idPanelSvgData, alignPanelSvgData,
+              jsonData, ap.av.getWrapAlignment());
       FileOutputStream out = new FileOutputStream(generatedFile);
       out.write(htmlData.getBytes());
       out.flush();
@@ -293,11 +349,6 @@ public class HtmlSvgOutput extends HTMLOutput
       setProgressMessage(MessageManager
               .formatMessage("status.export_complete", "HTML"));
       exportCompleted();
-    } catch (OutOfMemoryError err)
-    {
-      System.out.println("########################\n" + "OUT OF MEMORY "
-              + generatedFile + "\n" + "########################");
-      new OOMWarning("Creating Image for " + generatedFile, err);
     } catch (Exception e)
     {
       e.printStackTrace();
index c506fc6..916a98f 100755 (executable)
@@ -175,7 +175,7 @@ public class GTreePanel extends JInternalFrame
     {
       public void actionPerformed(ActionEvent e)
       {
-        epsTree_actionPerformed(e);
+        epsTree_actionPerformed();
       }
     });
     pngTree.setText("PNG");
@@ -259,7 +259,7 @@ public class GTreePanel extends JInternalFrame
   {
   }
 
-  public void epsTree_actionPerformed(ActionEvent e)
+  public void epsTree_actionPerformed()
   {
   }
 
index 493e210..64771c4 100755 (executable)
@@ -25,6 +25,7 @@ import jalview.bin.Jalview;
 import jalview.gui.IProgressIndicator;
 import jalview.gui.LineartOptions;
 import jalview.io.JalviewFileChooser;
+import jalview.util.dialogrunner.RunResponse;
 
 import java.awt.Component;
 import java.awt.Graphics;
@@ -33,8 +34,10 @@ import java.awt.RenderingHints;
 import java.awt.image.BufferedImage;
 import java.io.File;
 import java.io.FileOutputStream;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.imageio.ImageIO;
+import javax.swing.JOptionPane;
 
 import org.jfree.graphics2d.svg.SVGGraphics2D;
 import org.jfree.graphics2d.svg.SVGHints;
@@ -60,8 +63,6 @@ public class ImageMaker
 
   EpsGraphics2D pg;
 
-  SVGGraphics2D g2;
-
   Graphics graphics;
 
   FileOutputStream out;
@@ -105,7 +106,7 @@ public class ImageMaker
       return name;
     }
 
-    public JalviewFileChooser getChooser()
+    public JalviewFileChooser getFileChooser()
     {
       return new JalviewFileChooser(extension, description);
     }
@@ -144,8 +145,7 @@ public class ImageMaker
     {
       setProgressMessage(MessageManager.formatMessage(
               "status.waiting_for_user_to_select_output_file", type.name));
-      JalviewFileChooser chooser;
-      chooser = type.getChooser();
+      JalviewFileChooser chooser = type.getFileChooser();
       chooser.setFileView(new jalview.io.JalviewFileView());
       chooser.setDialogTitle(title);
       chooser.setToolTipText(MessageManager.getString("action.save"));
@@ -163,7 +163,7 @@ public class ImageMaker
                 "status.cancelled_image_export_operation", type.name));
       }
     }
-    // TODO JAL-3048 refactor to method called by constructor or callback
+
     if (file != null)
     {
       try
@@ -200,6 +200,11 @@ public class ImageMaker
     return graphics;
   }
 
+  /**
+   * For SVG or PNG, writes the generated graphics data to the file output
+   * stream. For EPS, flushes the output graphics (which is written to file as
+   * it is generated).
+   */
   public void writeImage()
   {
     try
@@ -228,53 +233,71 @@ public class ImageMaker
     }
   }
 
+  /**
+   * Generates an EPS image and writes it to the (previously set) output buffer.
+   * The user is first prompted for choice of Text or Lineart rendering, unless
+   * a preference for this has been set.
+   * 
+   * @param width
+   * @param height
+   * @param title
+   */
   void setupEPS(int width, int height, String title)
   {
-    boolean accurateText = true;
-
     String renderStyle = Cache.getDefault("EPS_RENDERING",
             "Prompt each time");
+    AtomicBoolean textOption = new AtomicBoolean(
+            !"Lineart".equals(renderStyle));
 
-    // If we need to prompt, and if the GUI is visible then
-    // Prompt for EPS rendering style
-    if (renderStyle.equalsIgnoreCase("Prompt each time")
-            && !(System.getProperty("java.awt.headless") != null && System
-                    .getProperty("java.awt.headless").equals("true")))
+    /*
+     * configure the action to run on OK in the dialog
+     */
+    RunResponse okAction = new RunResponse(JOptionPane.OK_OPTION)
     {
-      LineartOptions eps = new LineartOptions("EPS_RENDERING", "EPS");
-      renderStyle = eps.getValue();
-
-      if (renderStyle == null || eps.cancelled)
+      @Override
+      public void run()
       {
-        setProgressMessage(MessageManager.formatMessage(
-                "status.cancelled_image_export_operation", "EPS"));
-        return;
+        writeEPS(width, height, title, textOption.get());
       }
-    }
+    };
 
-    if (renderStyle.equalsIgnoreCase("text"))
+    /*
+     * Prompt for character rendering style if preference is not set
+     */
+    if (renderStyle.equalsIgnoreCase("Prompt each time")
+            && !(System.getProperty("java.awt.headless") != null && System
+                    .getProperty("java.awt.headless").equals("true")))
     {
-      accurateText = false;
+      LineartOptions epsOption = new LineartOptions("EPS_RENDERING",
+              TYPE.EPS.getName(), textOption);
+      epsOption.setResponseAction(new RunResponse(JOptionPane.NO_OPTION)
+      {
+        @Override
+        public void run()
+        {
+          setProgressMessage(MessageManager.formatMessage(
+                  "status.cancelled_image_export_operation", "EPS"));
+        }
+      });
+      epsOption.setResponseAction(okAction);
+      epsOption.showDialog();
+      /* no code here - JalviewJS cannot execute it */
     }
-
-    try
+    else
     {
-      pg = new EpsGraphics2D(title, out, 0, 0, width, height);
-      Graphics2D ig2 = pg;
-      ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
-              RenderingHints.VALUE_ANTIALIAS_ON);
-
-      pg.setAccurateTextMode(accurateText);
-
-      graphics = pg;
-      setProgressMessage(MessageManager
-              .formatMessage("status.export_complete", type.getName()));
-    } catch (Exception ex)
-    {
-      System.err.println("Error writing PNG: " + ex.toString());
+      /*
+       * else (if preference set) just do the export action
+       */
+      writeEPS(width, height, title, textOption.get());
     }
   }
 
+  /**
+   * Sets up a graphics object for the PNG image to be written on
+   * 
+   * @param width
+   * @param height
+   */
   void setupPNG(int width, int height)
   {
     bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
@@ -284,69 +307,123 @@ public class ImageMaker
             RenderingHints.VALUE_ANTIALIAS_ON);
     setProgressMessage(MessageManager
             .formatMessage("status.export_complete", type.getName()));
-
   }
 
+  /**
+   * Sets up a graphics object for the SVG image to be written on. The user is
+   * first prompted for choice of Text or Lineart rendering, unless a preference
+   * for this has been set.
+   * 
+   * @param width
+   * @param height
+   * @param title
+   */
   void setupSVG(int width, int height, String title)
   {
-
-    g2 = new SVGGraphics2D(width, height);
-    Graphics2D ig2 = g2;
-
-    String renderStyle = jalview.bin.Cache.getDefault("SVG_RENDERING",
+    String renderStyle = Cache.getDefault("SVG_RENDERING",
             "Prompt each time");
+    AtomicBoolean textOption = new AtomicBoolean(
+            !"Lineart".equals(renderStyle));
 
-    // If we need to prompt, and if the GUI is visible then
-    // Prompt for EPS rendering style
+    /*
+     * configure the action to run on OK in the dialog
+     */
+    RunResponse okAction = new RunResponse(JOptionPane.OK_OPTION)
+    {
+      @Override
+      public void run()
+      {
+        setupSVG(width, height, textOption.get());
+      }
+    };
+
+    /*
+     * Prompt for character rendering style if preference is not set
+     */
     if (renderStyle.equalsIgnoreCase("Prompt each time")
             && !(System.getProperty("java.awt.headless") != null && System
                     .getProperty("java.awt.headless").equals("true")))
     {
-      LineartOptions svgOption = new LineartOptions("SVG_RENDERING", "SVG");
-      renderStyle = svgOption.getValue();
-
-      if (renderStyle == null || svgOption.cancelled)
+      LineartOptions svgOption = new LineartOptions("SVG_RENDERING",
+              TYPE.SVG.getName(), textOption);
+      svgOption.setResponseAction(new RunResponse(JOptionPane.NO_OPTION)
       {
-        setProgressMessage(MessageManager.formatMessage(
-                "status.cancelled_image_export_operation", "SVG"));
-        return;
-      }
+        @Override
+        public void run()
+        {
+          setProgressMessage(MessageManager.formatMessage(
+                  "status.cancelled_image_export_operation", "SVG"));
+        }
+      });
+      svgOption.setResponseAction(okAction);
+      svgOption.showDialog();
+      /* no code here - JalviewJS cannot execute it */
     }
-
-    if (renderStyle.equalsIgnoreCase("Lineart"))
+    else
     {
-      ig2.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
-              SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
+      /*
+       * else (if preference set) just do the export action
+       */
+      setupSVG(width, height, textOption.get());
     }
-
-    setProgressMessage(MessageManager
-            .formatMessage("status.export_complete", type.getName()));
-    graphics = g2;
   }
 
-  static JalviewFileChooser getPNGChooser()
+  void setProgressMessage(String message)
   {
-    if (Jalview.isHeadlessMode())
+    if (pIndicator != null && !headless)
     {
-      return null;
+      pIndicator.setProgressBar(message, pSessionId);
     }
-    return new JalviewFileChooser(PNG_EXTENSION, PNG_DESCRIPTION);
   }
 
-  static JalviewFileChooser getEPSChooser()
+  /**
+   * A helper method to configure the SVG output graphics, with choice of Text
+   * or Lineart character rendering
+   * 
+   * @param width
+   * @param height
+   * @param textOption
+   *          true for Text, false for Lineart
+   */
+  protected void setupSVG(int width, int height, boolean textOption)
   {
-    if (Jalview.isHeadlessMode())
+    SVGGraphics2D g2 = new SVGGraphics2D(width, height);
+    if (!textOption) // Lineart selected
     {
-      return null;
+      g2.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
+              SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
     }
-    return new JalviewFileChooser(EPS_EXTENSION, EPS_DESCRIPTION);
+    setProgressMessage(MessageManager
+            .formatMessage("status.export_complete", type.getName()));
+    graphics = g2;
   }
 
-  private void setProgressMessage(String message)
+  /**
+   * A helper method that sets up the EPS graphics output with user choice of
+   * Text or Lineart character rendering
+   * 
+   * @param width
+   * @param height
+   * @param title
+   * @param textOption
+   *          true for Text, false for Lineart
+   */
+  protected void writeEPS(int width, int height, String title,
+          boolean textOption)
   {
-    if (pIndicator != null && !headless)
+    try
     {
-      pIndicator.setProgressBar(message, pSessionId);
+      pg = new EpsGraphics2D(title, out, 0, 0, width, height);
+      Graphics2D ig2 = pg;
+      ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+              RenderingHints.VALUE_ANTIALIAS_ON);
+      pg.setAccurateTextMode(!textOption); // true = Lineart
+      graphics = pg;
+      setProgressMessage(MessageManager
+              .formatMessage("status.export_complete", type.getName()));
+    } catch (Exception ex)
+    {
+      System.err.println("Error writing PNG: " + ex.toString());
     }
   }