JAL-3026 JLabel for alignment properties in jalview-js
[jalview.git] / src / jalview / gui / AlignFrame.java
index e10ff4a..7525f47 100644 (file)
@@ -45,6 +45,7 @@ import jalview.commands.RemoveGapColCommand;
 import jalview.commands.RemoveGapsCommand;
 import jalview.commands.SlideSequencesCommand;
 import jalview.commands.TrimRegionCommand;
+import jalview.datamodel.AlignExportSettingBeanI;
 import jalview.datamodel.AlignedCodonFrame;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentAnnotation;
@@ -54,7 +55,6 @@ import jalview.datamodel.AlignmentOrder;
 import jalview.datamodel.AlignmentView;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.HiddenColumns;
-import jalview.datamodel.HiddenSequences;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SeqCigar;
 import jalview.datamodel.Sequence;
@@ -81,12 +81,14 @@ import jalview.io.JnetAnnotationMaker;
 import jalview.io.NewickFile;
 import jalview.io.ScoreMatrixFile;
 import jalview.io.TCoffeeScoreFile;
+import jalview.io.vcf.VCFLoader;
 import jalview.jbgui.GAlignFrame;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemes;
 import jalview.schemes.ResidueColourScheme;
 import jalview.schemes.TCoffeeColourScheme;
 import jalview.util.MessageManager;
+import jalview.util.dialogrunner.RunResponse;
 import jalview.viewmodel.AlignmentViewport;
 import jalview.viewmodel.ViewportRanges;
 import jalview.ws.DBRefFetcher;
@@ -97,6 +99,7 @@ import jalview.ws.jws2.jabaws2.Jws2Instance;
 import jalview.ws.seqfetcher.DbSourceProxy;
 
 import java.awt.BorderLayout;
+import java.awt.Color;
 import java.awt.Component;
 import java.awt.Rectangle;
 import java.awt.Toolkit;
@@ -121,6 +124,7 @@ import java.awt.event.MouseEvent;
 import java.awt.print.PageFormat;
 import java.awt.print.PrinterJob;
 import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 import java.io.File;
 import java.io.FileWriter;
 import java.io.PrintWriter;
@@ -134,12 +138,17 @@ import java.util.List;
 import java.util.Vector;
 
 import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JComponent;
 import javax.swing.JEditorPane;
+import javax.swing.JFileChooser;
 import javax.swing.JInternalFrame;
+import javax.swing.JLabel;
 import javax.swing.JLayeredPane;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
+import javax.swing.JPanel;
 import javax.swing.JScrollPane;
+import javax.swing.JTextPane;
 import javax.swing.SwingUtilities;
 
 /**
@@ -149,7 +158,8 @@ import javax.swing.SwingUtilities;
  * @version $Revision$
  */
 public class AlignFrame extends GAlignFrame implements DropTargetListener,
-        IProgressIndicator, AlignViewControllerGuiI, ColourChangeListener
+        IProgressIndicator, AlignViewControllerGuiI, ColourChangeListener,
+        PropertyChangeListener
 {
 
   public static final int DEFAULT_WIDTH = 700;
@@ -177,6 +187,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    */
   String fileName = null;
 
+  File fileObject;
+
   /**
    * Creates a new AlignFrame object with specific width and height.
    * 
@@ -323,6 +335,34 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     init();
   }
 
+  @Override
+  public void propertyChange(PropertyChangeEvent evt)
+  {
+    Desktop.getDesktop().propertyChange(evt);
+  }
+
+  /**
+   * BH 2018
+   * 
+   * @return true if we have any features
+   */
+  @Override
+  protected boolean haveAlignmentFeatures()
+  {
+    AlignmentI alignment = getViewport().getAlignment();
+
+    for (int i = 0; i < alignment.getHeight(); i++)
+    {
+      SequenceI seq = alignment.getSequenceAt(i);
+      for (String group : seq.getFeatures().getFeatureGroups(true))
+      {
+        if (group != null)
+          return true;
+      }
+    }
+    return false;
+  }
+
   /**
    * initalise the alignframe from the underlying viewport data and the
    * configurations
@@ -377,7 +417,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     if (Desktop.desktop != null)
     {
       this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
-      addServiceListeners();
+      /**
+       * BH 2018 ignore service listeners
+       * 
+       * @j2sNative
+       * 
+       */
+      {
+        addServiceListeners();
+      }
       setGUINucleotide();
     }
 
@@ -496,6 +544,17 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   }
 
   /**
+   * JavaScript will have this, maybe others. More dependable than a file name
+   * and maintains a reference to the actual bytes loaded.
+   * 
+   * @param file
+   */
+  public void setFileObject(File file)
+  {
+    this.fileObject = file;
+  }
+
+  /**
    * Add a KeyListener with handlers for various KeyPressed and KeyReleased
    * events
    */
@@ -839,6 +898,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     AlignmentI al = getViewport().getAlignment();
     boolean nucleotide = al.isNucleotide();
 
+    loadVcf.setVisible(nucleotide);
     showTranslation.setVisible(nucleotide);
     showReverse.setVisible(nucleotide);
     showReverseComplement.setVisible(nucleotide);
@@ -1033,11 +1093,23 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         Rectangle bounds = this.getBounds();
 
         FileLoader loader = new FileLoader();
-        DataSourceType protocol = fileName.startsWith("http:")
-                ? DataSourceType.URL
-                : DataSourceType.FILE;
-        AlignFrame newframe = loader.LoadFileWaitTillLoaded(fileName,
-                protocol, currentFileFormat);
+
+        AlignFrame newframe = null;
+
+        if (fileObject == null)
+        {
+
+          DataSourceType protocol = (fileName.startsWith("http:")
+                  ? DataSourceType.URL
+                  : DataSourceType.FILE);
+          newframe = loader.LoadFileWaitTillLoaded(fileName, protocol,
+                  currentFileFormat);
+        }
+        else
+        {
+          newframe = loader.LoadFileWaitTillLoaded(fileObject,
+                  DataSourceType.FILE, currentFileFormat);
+        }
 
         newframe.setBounds(bounds);
         if (featureSettings != null && featureSettings.isShowing())
@@ -1101,47 +1173,82 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   {
     String format = currentFileFormat == null ? null
             : currentFileFormat.getName();
-    JalviewFileChooser chooser = JalviewFileChooser
+    final JalviewFileChooser chooser = JalviewFileChooser
             .forWrite(Cache.getProperty("LAST_DIRECTORY"), format);
-
+    final AlignFrame us = this;
     chooser.setFileView(new JalviewFileView());
     chooser.setDialogTitle(
             MessageManager.getString("label.save_alignment_to_file"));
     chooser.setToolTipText(MessageManager.getString("action.save"));
 
-    int value = chooser.showSaveDialog(this);
-
-    if (value == JalviewFileChooser.APPROVE_OPTION)
+    chooser.response(new RunResponse(JalviewFileChooser.APPROVE_OPTION)
     {
-      currentFileFormat = chooser.getSelectedFormat();
-      while (currentFileFormat == null)
+      @Override
+      public void run()
       {
-        JvOptionPane.showInternalMessageDialog(Desktop.desktop,
-                MessageManager.getString(
-                        "label.select_file_format_before_saving"),
-                MessageManager.getString("label.file_format_not_specified"),
-                JvOptionPane.WARNING_MESSAGE);
         currentFileFormat = chooser.getSelectedFormat();
-        value = chooser.showSaveDialog(this);
-        if (value != JalviewFileChooser.APPROVE_OPTION)
+        while (currentFileFormat == null)
         {
-          return;
+          JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                  MessageManager.getString(
+                          "label.select_file_format_before_saving"),
+                  MessageManager
+                          .getString("label.file_format_not_specified"),
+                  JvOptionPane.WARNING_MESSAGE);
+          currentFileFormat = chooser.getSelectedFormat();
+          chooser.showSaveDialog(us);
         }
+
+        fileName = chooser.getSelectedFile().getPath();
+
+        Cache.setProperty("DEFAULT_FILE_FORMAT",
+                currentFileFormat.getName());
+
+        Cache.setProperty("LAST_DIRECTORY", fileName);
+        saveAlignment(fileName, currentFileFormat);
       }
+    }).showSaveDialog(this);
+  }
 
-      fileName = chooser.getSelectedFile().getPath();
+  private boolean lastSaveSuccessful = false;
 
-      Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat.getName());
+  private FileFormatI lastFormatSaved;
 
-      Cache.setProperty("LAST_DIRECTORY", fileName);
-      saveAlignment(fileName, currentFileFormat);
+  private String lastFilenameSaved;
+
+  /**
+   * Raise a dialog or status message for the last call to saveAlignment.
+   *
+   * @return true if last call to saveAlignment(file, format) was successful.
+   */
+  public boolean isSaveAlignmentSuccessful()
+  {
+
+    if (!lastSaveSuccessful)
+    {
+      JvOptionPane.showInternalMessageDialog(this, MessageManager
+              .formatMessage("label.couldnt_save_file", new Object[]
+              { lastFilenameSaved }),
+              MessageManager.getString("label.error_saving_file"),
+              JvOptionPane.WARNING_MESSAGE);
     }
+    else
+    {
+
+      statusBar.setText(MessageManager.formatMessage(
+              "label.successfully_saved_to_file_in_format", new Object[]
+              { lastFilenameSaved, lastFormatSaved }));
+
+    }
+    return lastSaveSuccessful;
   }
 
-  public boolean saveAlignment(String file, FileFormatI format)
+  public void saveAlignment(String file, FileFormatI format)
   {
-    boolean success = true;
-
+    lastSaveSuccessful = false;
+    lastFilenameSaved = file;
+    lastFormatSaved = format;
+    AlignFrame us = this;
     if (FileFormat.Jalview.equals(format))
     {
       String shortName = title;
@@ -1152,81 +1259,66 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                 shortName.lastIndexOf(java.io.File.separatorChar) + 1);
       }
 
-      success = new Jalview2XML().saveAlignment(this, file, shortName);
-
-      statusBar.setText(MessageManager.formatMessage(
-              "label.successfully_saved_to_file_in_format", new Object[]
-              { fileName, format }));
-
+      lastSaveSuccessful = new Jalview2XML().saveAlignment(this, file,
+              shortName);
     }
     else
     {
-      AlignmentExportData exportData = getAlignmentForExport(format,
-              viewport, null);
-      if (exportData.getSettings().isCancelled())
-      {
-        return false;
-      }
-      FormatAdapter f = new FormatAdapter(alignPanel,
-              exportData.getSettings());
-      String output = f.formatSequences(format, exportData.getAlignment(), // class
-                                                                           // cast
-                                                                           // exceptions
-                                                                           // will
-              // occur in the distant future
-              exportData.getOmitHidden(), exportData.getStartEndPostions(),
-              f.getCacheSuffixDefault(format),
-              viewport.getAlignment().getHiddenColumns());
-
-      if (output == null)
-      {
-        success = false;
-      }
-      else
+      AlignExportSettingI settings = getAlignmentForExport(format,
+              alignPanel, null);
+      settings.addActionListener(new ActionListener()
       {
-        try
-        {
-          PrintWriter out = new PrintWriter(new FileWriter(file));
-
-          out.print(output);
-          out.close();
-          this.setTitle(file);
-          statusBar.setText(MessageManager.formatMessage(
-                  "label.successfully_saved_to_file_in_format", new Object[]
-                  { fileName, format.getName() }));
-        } catch (Exception ex)
+        @Override
+        public void actionPerformed(ActionEvent e)
         {
-          success = false;
-          ex.printStackTrace();
-        }
-      }
-    }
-
-    if (!success)
-    {
-      JvOptionPane.showInternalMessageDialog(this, MessageManager
-              .formatMessage("label.couldnt_save_file", new Object[]
-              { fileName }),
-              MessageManager.getString("label.error_saving_file"),
-              JvOptionPane.WARNING_MESSAGE);
-    }
 
-    return success;
-  }
-
-  private void warningMessage(String warning, String title)
-  {
-    if (new jalview.util.Platform().isHeadless())
-    {
-      System.err.println("Warning: " + title + "\nWarning: " + warning);
+          if (settings.isCancelled())
+          {
+            lastSaveSuccessful = false;
+            return;
+          }
+          AlignmentExportData exportData = settings.getAlignExportData();
+          FormatAdapter f = new FormatAdapter(alignPanel,
+                  exportData.getSettings());
+          String output = f.formatSequences(format,
+                  exportData.getAlignment(), // class
+                                             // cast
+                                             // exceptions
+                                             // will
+                  // occur in the distant future
+                  exportData.getOmitHidden(),
+                  exportData.getStartEndPostions(),
+                  f.getCacheSuffixDefault(format),
+                  viewport.getAlignment().getHiddenColumns());
+
+          if (output == null)
+          {
+            lastSaveSuccessful = false;
+          }
+          else
+          {
+            try
+            {
+              PrintWriter out = new PrintWriter(new FileWriter(file));
+
+              out.print(output);
+              out.close();
+              us.setTitle(file);
+              statusBar.setText(MessageManager.formatMessage(
+                      "label.successfully_saved_to_file_in_format",
+                      new Object[]
+                      { fileName, format.getName() }));
+            } catch (Exception ex)
+            {
+              lastSaveSuccessful = false;
+              ex.printStackTrace();
+            }
+          }
+        }
+      });
 
+      settings.doShowSettings();
     }
-    else
-    {
-      JvOptionPane.showInternalMessageDialog(this, warning, title,
-              JvOptionPane.WARNING_MESSAGE);
-    }
-    return;
   }
 
   /**
@@ -1240,75 +1332,50 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   {
     FileFormatI fileFormat = FileFormats.getInstance()
             .forName(e.getActionCommand());
-    AlignmentExportData exportData = getAlignmentForExport(fileFormat,
-            viewport, null);
-    if (exportData.getSettings().isCancelled())
-    {
-      return;
-    }
-    CutAndPasteTransfer cap = new CutAndPasteTransfer();
-    cap.setForInput(null);
-    try
+    AlignExportSettingI settings = getAlignmentForExport(fileFormat,
+            alignPanel, null);
+    settings.addActionListener(new ActionListener()
     {
-      FileFormatI format = fileFormat;
-      cap.setText(new FormatAdapter(alignPanel, exportData.getSettings())
-              .formatSequences(format, exportData.getAlignment(),
-                      exportData.getOmitHidden(),
-                      exportData.getStartEndPostions(),
-                      viewport.getAlignment().getHiddenColumns()));
-      Desktop.addInternalFrame(cap, MessageManager
-              .formatMessage("label.alignment_output_command", new Object[]
-              { e.getActionCommand() }), 600, 500);
-    } catch (OutOfMemoryError oom)
-    {
-      new OOMWarning("Outputting alignment as " + e.getActionCommand(),
-              oom);
-      cap.dispose();
-    }
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        if (settings.isCancelled())
+        {
+          return;
+        }
+        AlignmentExportData exportData = settings.getAlignExportData();
+        CutAndPasteTransfer cap = new CutAndPasteTransfer();
+        cap.setForInput(null);
+        try
+        {
+          FileFormatI format = fileFormat;
+          cap.setText(new FormatAdapter(alignPanel, settings)
+                  .formatSequences(format, exportData.getAlignment(),
+                          exportData.getOmitHidden(),
+                          exportData.getStartEndPostions(),
+                          viewport.getAlignment().getHiddenColumns()));
+          Desktop.addInternalFrame(cap, MessageManager.formatMessage(
+                  "label.alignment_output_command", new Object[]
+                  { fileFormat.getName() }), 600, 500);
+        } catch (OutOfMemoryError oom)
+        {
+          new OOMWarning("Outputting alignment as " + fileFormat.getName(),
+                  oom);
+          cap.dispose();
+        }
+        // TODO Auto-generated method stub
 
+      }
+    });
+    settings.doShowSettings();
   }
 
-  public static AlignmentExportData getAlignmentForExport(
-          FileFormatI format, AlignViewportI viewport,
-          AlignExportSettingI exportSettings)
+  public static AlignExportSettingI getAlignmentForExport(
+          FileFormatI format, AlignmentPanel alignPanel,
+          AlignExportSettingBeanI exportSettings)
   {
-    AlignmentI alignmentToExport = null;
-    AlignExportSettingI settings = exportSettings;
-    String[] omitHidden = null;
-
-    HiddenSequences hiddenSeqs = viewport.getAlignment()
-            .getHiddenSequences();
-
-    alignmentToExport = viewport.getAlignment();
-
-    boolean hasHiddenSeqs = hiddenSeqs.getSize() > 0;
-    if (settings == null)
-    {
-      settings = new AlignExportSettings(hasHiddenSeqs,
-              viewport.hasHiddenColumns(), format);
-    }
-    // settings.isExportAnnotations();
 
-    if (viewport.hasHiddenColumns() && !settings.isExportHiddenColumns())
-    {
-      omitHidden = viewport.getViewAsString(false,
-              settings.isExportHiddenSequences());
-    }
-
-    int[] alignmentStartEnd = new int[2];
-    if (hasHiddenSeqs && settings.isExportHiddenSequences())
-    {
-      alignmentToExport = hiddenSeqs.getFullAlignment();
-    }
-    else
-    {
-      alignmentToExport = viewport.getAlignment();
-    }
-    alignmentStartEnd = viewport.getAlignment().getHiddenColumns()
-            .getVisibleStartAndEndIndex(alignmentToExport.getWidth());
-    AlignmentExportData ed = new AlignmentExportData(alignmentToExport,
-            omitHidden, alignmentStartEnd, settings);
-    return ed;
+    return new AlignExportSettings(alignPanel, format, exportSettings);
   }
 
   /**
@@ -1390,36 +1457,39 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   public void exportFeatures_actionPerformed(ActionEvent e)
   {
-    new AnnotationExporter().exportFeatures(alignPanel);
+    new AnnotationExporter(alignPanel).exportFeatures();
   }
 
   @Override
   public void exportAnnotations_actionPerformed(ActionEvent e)
   {
-    new AnnotationExporter().exportAnnotations(alignPanel);
+    new AnnotationExporter(alignPanel).exportAnnotations();
   }
 
   @Override
   public void associatedData_actionPerformed(ActionEvent e)
   {
-    // Pick the tree file
-    JalviewFileChooser chooser = new JalviewFileChooser(
+    final JalviewFileChooser chooser = new JalviewFileChooser(
             jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
     chooser.setFileView(new JalviewFileView());
     chooser.setDialogTitle(
             MessageManager.getString("label.load_jalview_annotations"));
     chooser.setToolTipText(
             MessageManager.getString("label.load_jalview_annotations"));
+    chooser.response(new RunResponse(JalviewFileChooser.APPROVE_OPTION)
+    {
 
-    int value = chooser.showOpenDialog(null);
+      @Override
+      public void run()
+      {
+        String choice = chooser.getSelectedFile().getPath();
+        jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
+        loadJalviewDataFile(chooser.getSelectedFile(), null, null, null);
+      }
 
-    if (value == JalviewFileChooser.APPROVE_OPTION)
-    {
-      String choice = chooser.getSelectedFile().getPath();
-      jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
-      loadJalviewDataFile(choice, null, null, null);
-    }
+    });
 
+    chooser.openDialog(this);
   }
 
   /**
@@ -1826,7 +1896,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   protected void copy_actionPerformed(ActionEvent e)
   {
-    System.gc();
     if (viewport.getSelectionGroup() == null)
     {
       return;
@@ -1862,23 +1931,17 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       return;
     }
 
-    ArrayList<int[]> hiddenColumns = null;
+    HiddenColumns hiddenColumns = null;
     if (viewport.hasHiddenColumns())
     {
-      hiddenColumns = new ArrayList<>();
       int hiddenOffset = viewport.getSelectionGroup().getStartRes();
       int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
-      ArrayList<int[]> hiddenRegions = viewport.getAlignment()
-              .getHiddenColumns().getHiddenColumnsCopy();
-      for (int[] region : hiddenRegions)
-      {
-        if (region[0] >= hiddenOffset && region[1] <= hiddenCutoff)
-        {
-          hiddenColumns
-                  .add(new int[]
-                  { region[0] - hiddenOffset, region[1] - hiddenOffset });
-        }
-      }
+
+      // create new HiddenColumns object with copy of hidden regions
+      // between startRes and endRes, offset by startRes
+      hiddenColumns = new HiddenColumns(
+              viewport.getAlignment().getHiddenColumns(), hiddenOffset,
+              hiddenCutoff, hiddenOffset);
     }
 
     Desktop.jalviewClipboard = new Object[] { seqs,
@@ -2207,11 +2270,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         if (Desktop.jalviewClipboard != null
                 && Desktop.jalviewClipboard[2] != null)
         {
-          List<int[]> hc = (List<int[]>) Desktop.jalviewClipboard[2];
-          for (int[] region : hc)
-          {
-            af.viewport.hideColumns(region[0], region[1]);
-          }
+          HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
+          af.viewport.setHiddenColumns(hc);
         }
 
         // >>>This is a fix for the moment, until a better solution is
@@ -2266,11 +2326,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       if (Desktop.jalviewClipboard != null
               && Desktop.jalviewClipboard[2] != null)
       {
-        List<int[]> hc = (List<int[]>) Desktop.jalviewClipboard[2];
-        for (int region[] : hc)
-        {
-          af.viewport.hideColumns(region[0], region[1]);
-        }
+        HiddenColumns hc = (HiddenColumns) Desktop.jalviewClipboard[2];
+        af.viewport.setHiddenColumns(hc);
       }
 
       // >>>This is a fix for the moment, until a better solution is
@@ -3222,15 +3279,37 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   @Override
   public void alignmentProperties()
   {
-    JEditorPane editPane = new JEditorPane("text/html", "");
-    editPane.setEditable(false);
+    JComponent pane;
     StringBuffer contents = new AlignmentProperties(viewport.getAlignment())
+
             .formatAsHtml();
-    editPane.setText(
-            MessageManager.formatMessage("label.html_content", new Object[]
-            { contents.toString() }));
+    String content = MessageManager.formatMessage("label.html_content",
+            new Object[]
+            { contents.toString() });
+    contents = null;
+
+    if (/** @j2sNative true || */
+    false)
+    {
+      JLabel textLabel = new JLabel();
+      textLabel.setText(content);
+      textLabel.setBackground(Color.WHITE);
+      
+      pane = new JPanel(new BorderLayout());
+      ((JPanel) pane).setOpaque(true);
+      ((JPanel) pane).add(textLabel, BorderLayout.CENTER);
+    }
+    else
+    {
+      JEditorPane editPane = new JEditorPane("text/html", "");
+      editPane.setEditable(false);
+      editPane.setText(content);
+      pane = editPane;
+    }
+
     JInternalFrame frame = new JInternalFrame();
-    frame.getContentPane().add(new JScrollPane(editPane));
+
+    frame.getContentPane().add(new JScrollPane(pane));
 
     Desktop.addInternalFrame(frame, MessageManager
             .formatMessage("label.alignment_properties", new Object[]
@@ -3271,6 +3350,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                 alignPanel.setOverviewPanel(null);
               };
             });
+    if (getKeyListeners().length > 0)
+    {
+      frame.addKeyListener(getKeyListeners()[0]);
+    }
 
     alignPanel.setOverviewPanel(overview);
   }
@@ -3886,33 +3969,38 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     chooser.setToolTipText(
             MessageManager.getString("label.load_tree_file"));
 
-    int value = chooser.showOpenDialog(null);
-
-    if (value == JalviewFileChooser.APPROVE_OPTION)
+    chooser.response(new jalview.util.dialogrunner.RunResponse(
+            JalviewFileChooser.APPROVE_OPTION)
     {
-      String filePath = chooser.getSelectedFile().getPath();
-      Cache.setProperty("LAST_DIRECTORY", filePath);
-      NewickFile fin = null;
-      try
-      {
-        fin = new NewickFile(filePath, DataSourceType.FILE);
-        viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
-      } catch (Exception ex)
-      {
-        JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
-                MessageManager.getString("label.problem_reading_tree_file"),
-                JvOptionPane.WARNING_MESSAGE);
-        ex.printStackTrace();
-      }
-      if (fin != null && fin.hasWarningMessage())
+      @Override
+      public void run()
       {
-        JvOptionPane.showMessageDialog(Desktop.desktop,
-                fin.getWarningMessage(),
-                MessageManager
-                        .getString("label.possible_problem_with_tree_file"),
-                JvOptionPane.WARNING_MESSAGE);
+        String filePath = chooser.getSelectedFile().getPath();
+        Cache.setProperty("LAST_DIRECTORY", filePath);
+        NewickFile fin = null;
+        try
+        {
+          fin = new NewickFile(new FileParse(chooser.getSelectedFile(),
+                  DataSourceType.FILE));
+          viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
+        } catch (Exception ex)
+        {
+          JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
+                  MessageManager
+                          .getString("label.problem_reading_tree_file"),
+                  JvOptionPane.WARNING_MESSAGE);
+          ex.printStackTrace();
+        }
+        if (fin != null && fin.hasWarningMessage())
+        {
+          JvOptionPane.showMessageDialog(Desktop.desktop,
+                  fin.getWarningMessage(),
+                  MessageManager.getString(
+                          "label.possible_problem_with_tree_file"),
+                  JvOptionPane.WARNING_MESSAGE);
+        }
       }
-    }
+    }).openDialog(this);
   }
 
   public TreePanel showNewickTree(NewickFile nf, String treeTitle)
@@ -4258,7 +4346,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   protected void showProductsFor(final SequenceI[] sel, final boolean _odna,
           final String source)
   {
-    new Thread(CrossRefAction.showProductsFor(sel, _odna, source, this))
+    new Thread(CrossRefAction.getHandlerFor(sel, _odna, source, this))
             .start();
   }
 
@@ -4332,13 +4420,14 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    * Try to load a features file onto the alignment.
    * 
    * @param file
-   *          contents or path to retrieve file
+   *          contents or path to retrieve file or a File object
    * @param sourceType
    *          access mode of file (see jalview.io.AlignFile)
    * @return true if features file was parsed correctly.
    */
-  public boolean parseFeaturesFile(String file, DataSourceType sourceType)
+  public boolean parseFeaturesFile(Object file, DataSourceType sourceType)
   {
+    // BH 2018
     return avc.parseFeaturesFile(file, sourceType,
             Cache.getDefault("RELAXEDSEQIDMATCHING", false));
 
@@ -4385,8 +4474,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     // Java's Transferable for native dnd
     evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
     Transferable t = evt.getTransferable();
+
     final AlignFrame thisaf = this;
-    final List<String> files = new ArrayList<>();
+    final List<Object> files = new ArrayList<>();
     List<DataSourceType> protocols = new ArrayList<>();
 
     try
@@ -4414,20 +4504,25 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
              * Object[] { String,SequenceI}
              */
             ArrayList<Object[]> filesmatched = new ArrayList<>();
-            ArrayList<String> filesnotmatched = new ArrayList<>();
+            ArrayList<Object> filesnotmatched = new ArrayList<>();
             for (int i = 0; i < files.size(); i++)
             {
-              String file = files.get(i).toString();
+              // BH 2018
+              Object file = files.get(i);
+              String fileName = file.toString();
               String pdbfn = "";
-              DataSourceType protocol = FormatAdapter.checkProtocol(file);
+              DataSourceType protocol = (file instanceof File
+                      ? DataSourceType.FILE
+                      : FormatAdapter.checkProtocol(fileName));
               if (protocol == DataSourceType.FILE)
               {
-                File fl = new File(file);
+                File fl = (file instanceof File ? (File) file
+                        : new File(fileName));
                 pdbfn = fl.getName();
               }
               else if (protocol == DataSourceType.URL)
               {
-                URL url = new URL(file);
+                URL url = new URL(fileName);
                 pdbfn = url.getFile();
               }
               if (pdbfn.length() > 0)
@@ -4449,7 +4544,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                 }
                 if (mtch != null)
                 {
-                  FileFormatI type = null;
+                  FileFormatI type;
                   try
                   {
                     type = new IdentifyFile().identify(file, protocol);
@@ -4471,17 +4566,22 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
             int assocfiles = 0;
             if (filesmatched.size() > 0)
             {
-              if (Cache.getDefault("AUTOASSOCIATE_PDBANDSEQS", false)
-                      || JvOptionPane.showConfirmDialog(thisaf,
-                              MessageManager.formatMessage(
-                                      "label.automatically_associate_structure_files_with_sequences_same_name",
-                                      new Object[]
-                                      { Integer.valueOf(filesmatched.size())
-                                              .toString() }),
-                              MessageManager.getString(
-                                      "label.automatically_associate_structure_files_by_name"),
-                              JvOptionPane.YES_NO_OPTION) == JvOptionPane.YES_OPTION)
-
+              boolean autoAssociate = Cache
+                      .getDefault("AUTOASSOCIATE_PDBANDSEQS", false);
+              if (!autoAssociate)
+              {
+                String msg = MessageManager.formatMessage(
+                        "label.automatically_associate_structure_files_with_sequences_same_name",
+                        new Object[]
+                        { Integer.valueOf(filesmatched.size())
+                                .toString() });
+                String ttl = MessageManager.getString(
+                        "label.automatically_associate_structure_files_by_name");
+                int choice = JvOptionPane.showConfirmDialog(thisaf, msg,
+                        ttl, JvOptionPane.YES_NO_OPTION);
+                autoAssociate = choice == JvOptionPane.YES_OPTION;
+              }
+              if (autoAssociate)
               {
                 for (Object[] fm : filesmatched)
                 {
@@ -4507,6 +4607,16 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                   alignPanel.paintAlignment(true, false);
                 }
               }
+              else
+              {
+                /*
+                 * add declined structures as sequences
+                 */
+                for (Object[] o : filesmatched)
+                {
+                  filesnotmatched.add(o[0]);
+                }
+              }
             }
             if (filesnotmatched.size() > 0)
             {
@@ -4526,7 +4636,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
               {
                 return;
               }
-              for (String fn : filesnotmatched)
+              for (Object fn : filesnotmatched)
               {
                 loadJalviewDataFile(fn, null, null, null);
               }
@@ -4553,9 +4663,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    * @param file
    *          either a filename or a URL string.
    */
-  public void loadJalviewDataFile(String file, DataSourceType sourceType,
+  public void loadJalviewDataFile(Object file, DataSourceType sourceType,
           FileFormatI format, SequenceI assocSeq)
   {
+    // BH 2018 was String file
     try
     {
       if (sourceType == null)
@@ -4639,11 +4750,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
             new JnetAnnotationMaker();
             JnetAnnotationMaker.add_annotation(predictions,
                     viewport.getAlignment(), 0, false);
-            SequenceI repseq = viewport.getAlignment().getSequenceAt(0);
-            viewport.getAlignment().setSeqrep(repseq);
-            HiddenColumns cs = new HiddenColumns();
-            cs.hideInsertionsFor(repseq);
-            viewport.getAlignment().setHiddenColumns(cs);
+            viewport.getAlignment().setupJPredAlignment();
             isAnnotation = true;
           }
           // else if (IdentifyFile.FeaturesFile.equals(format))
@@ -5586,6 +5693,34 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       new CalculationChooser(AlignFrame.this);
     }
   }
+
+  @Override
+  protected void loadVcf_actionPerformed()
+  {
+    JalviewFileChooser chooser = new JalviewFileChooser(
+            Cache.getProperty("LAST_DIRECTORY"));
+    chooser.setFileView(new JalviewFileView());
+    chooser.setDialogTitle(MessageManager.getString("label.load_vcf_file"));
+    chooser.setToolTipText(MessageManager.getString("label.load_vcf_file"));
+    final AlignFrame us = this;
+    chooser.response(new RunResponse(JalviewFileChooser.APPROVE_OPTION)
+    {
+      @Override
+      public void run()
+      {
+
+        {
+          String choice = chooser.getSelectedFile().getPath();
+          Cache.setProperty("LAST_DIRECTORY", choice);
+          SequenceI[] seqs = viewport.getAlignment().getSequencesArray();
+          new VCFLoader(choice).loadVCF(seqs, us);
+        }
+
+      };
+    }).openDialog(null);
+
+  }
+
 }
 
 class PrintThread extends Thread