Merge branch 'develop' into features/JAL-653_gffalignments features/JAL-653_gffalignments
authorJim Procter <jprocter@issues.jalview.org>
Wed, 17 Jun 2015 15:35:29 +0000 (16:35 +0100)
committerJim Procter <jprocter@issues.jalview.org>
Wed, 17 Jun 2015 15:35:29 +0000 (16:35 +0100)
update for incoming changes and finessing against JAL-1641

1  2 
src/jalview/appletgui/AlignFrame.java
src/jalview/datamodel/Sequence.java
src/jalview/gui/AlignFrame.java
src/jalview/io/AppletFormatAdapter.java
src/jalview/io/FileLoader.java

   */
  package jalview.appletgui;
  
 -import java.awt.BorderLayout;
 -import java.awt.Canvas;
 -import java.awt.CheckboxMenuItem;
 -import java.awt.Color;
 -import java.awt.Font;
 -import java.awt.FontMetrics;
 -import java.awt.Frame;
 -import java.awt.Graphics;
 -import java.awt.Label;
 -import java.awt.Menu;
 -import java.awt.MenuBar;
 -import java.awt.MenuItem;
 -import java.awt.event.ActionEvent;
 -import java.awt.event.ActionListener;
 -import java.awt.event.FocusEvent;
 -import java.awt.event.FocusListener;
 -import java.awt.event.ItemEvent;
 -import java.awt.event.ItemListener;
 -import java.awt.event.KeyEvent;
 -import java.awt.event.KeyListener;
 -import java.awt.event.WindowAdapter;
 -import java.awt.event.WindowEvent;
 -import java.io.IOException;
 -import java.net.URL;
 -import java.net.URLEncoder;
 -import java.util.Arrays;
 -import java.util.Deque;
 -import java.util.HashMap;
 -import java.util.Hashtable;
 -import java.util.List;
 -import java.util.Map;
 -import java.util.StringTokenizer;
 -import java.util.Vector;
 -
  import jalview.analysis.AlignmentSorter;
  import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
  import jalview.api.AlignViewControllerGuiI;
  import jalview.api.AlignViewControllerI;
  import jalview.api.AlignViewportI;
  import jalview.api.FeatureRenderer;
 +import jalview.api.FeatureSettingsControllerI;
  import jalview.api.SequenceStructureBinding;
  import jalview.bin.JalviewLite;
  import jalview.commands.CommandI;
@@@ -72,40 -105,6 +72,40 @@@ import jalview.util.MappingUtils
  import jalview.util.MessageManager;
  import jalview.viewmodel.AlignmentViewport;
  
 +import java.awt.BorderLayout;
 +import java.awt.Canvas;
 +import java.awt.CheckboxMenuItem;
 +import java.awt.Color;
 +import java.awt.Font;
 +import java.awt.FontMetrics;
 +import java.awt.Frame;
 +import java.awt.Graphics;
 +import java.awt.Label;
 +import java.awt.Menu;
 +import java.awt.MenuBar;
 +import java.awt.MenuItem;
 +import java.awt.event.ActionEvent;
 +import java.awt.event.ActionListener;
 +import java.awt.event.FocusEvent;
 +import java.awt.event.FocusListener;
 +import java.awt.event.ItemEvent;
 +import java.awt.event.ItemListener;
 +import java.awt.event.KeyEvent;
 +import java.awt.event.KeyListener;
 +import java.awt.event.WindowAdapter;
 +import java.awt.event.WindowEvent;
 +import java.io.IOException;
 +import java.net.URL;
 +import java.net.URLEncoder;
 +import java.util.Arrays;
 +import java.util.Deque;
 +import java.util.HashMap;
 +import java.util.Hashtable;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.StringTokenizer;
 +import java.util.Vector;
 +
  public class AlignFrame extends EmbmenuFrame implements ActionListener,
          ItemListener, KeyListener, AlignViewControllerGuiI
  {
    public AlignFrame(AlignmentI al, JalviewLite applet,
            String title, boolean embedded, boolean addToDisplay)
    {
+     this(al, null, null, applet, title, embedded, addToDisplay);
+   }
+   public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
+           ColumnSelection columnSelection, JalviewLite applet,
+           String title, boolean embedded)
+   {
+     this(al, hiddenSeqs, columnSelection, applet, title, embedded, true);
+   }
+   public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
+           ColumnSelection columnSelection, JalviewLite applet,
+           String title, boolean embedded, boolean addToDisplay)
+   {
      if (applet != null)
      {
        jalviewServletURL = applet.getParameter("APPLICATION_URL");
        }
      }
      viewport = new AlignViewport(al, applet);
+     if (hiddenSeqs != null && hiddenSeqs.length > 0)
+     {
+       viewport.hideSequence(hiddenSeqs);
+       viewport.setHasHiddenRows(true);
+     }
+     if (columnSelection != null)
+     {
+       viewport.setColumnSelection(columnSelection);
+     }
      alignPanel = new AlignmentPanel(this, viewport);
      avc = new jalview.controller.AlignViewController(this, viewport,
              alignPanel);
      jalview.bin.JalviewLite.addFrame(frame, MessageManager.formatMessage(
              "label.alignment_output_command", new Object[]
              { e.getActionCommand() }), 600, 500);
-     cap.setText(new AppletFormatAdapter().formatSequences(
+     FeatureRenderer fr = this.alignPanel.cloneFeatureRenderer();
+     viewport.setFeatureRenderer(fr);
+     viewport.setIncludeHiddenRegion(false);
+     cap.setText(new AppletFormatAdapter(viewport).formatSequences(
              e.getActionCommand(), viewport.getAlignment(),
              viewport.getShowJVSuffix()));
    }
    {
      this.splitFrame = sf;
    }
++
 +    // may not need this
 +  @Override
 +  public void setShowSeqFeatures(boolean b)
 +  {
 +    // showSeqFeatures.setSelected(b);
 +    viewport.setShowSequenceFeatures(b);
 +
 +  }
 +
 +  @Override
 +  public void setMenusForViewport()
 +  {
 +    // setMenusFromViewport(viewport);
 +
 +  }
 +  @Override
 +  public void refreshFeatureUI(boolean enableIfNecessary)
 +  {
 +    if (enableIfNecessary)
 +    {
 +      sequenceFeatures.setState(true);
 +      alignPanel.av.setShowSequenceFeatures(true);
 +    }
 +  }
 +
 +  @Override
 +  public FeatureSettingsControllerI getFeatureSettingsUI()
 +  {
 +    return alignPanel.av.featureSettings;
 +  }
 +
  }
@@@ -37,7 -37,7 +37,7 @@@ import jalview.util.StringUtils
   * @author $author$
   * @version $Revision$
   */
 -public class Sequence implements SequenceI
 +public class Sequence extends ASequence implements SequenceI
  {
    SequenceI datasetSequence;
  
@@@ -59,6 -59,7 +59,7 @@@
  
    RNA rna;
  
    /**
     * This annotation is displayed below the alignment but the positions are tied
     * to the residues of this sequence
     */
    public Sequence(String name, String sequence, int start, int end)
    {
 -    this.name = name;
 -    this.sequence = sequence.toCharArray();
 -    this.start = start;
 -    this.end = end;
 -    parseId();
 -    checkValidRange();
 +    initSeqAndName(name, sequence.toCharArray(), start, end);
    }
  
    public Sequence(String name, char[] sequence, int start, int end)
    {
 -    this.name = name;
 -    this.sequence = sequence;
 -    this.start = start;
 -    this.end = end;
 +    initSeqAndName(name, sequence, start, end);
 +  }
 +
 +  /**
 +   * Stage 1 constructor - assign name, sequence, and set start and end fields.
 +   * start and end are updated values from name2 if it ends with /start-end
 +   * 
 +   * @param name2
 +   * @param sequence2
 +   * @param start2
 +   * @param end2
 +   */
 +  protected void initSeqAndName(String name2, char[] sequence2, int start2,
 +          int end2)
 +  {
 +    this.name = name2;
 +    this.sequence = sequence2;
 +    this.start = start2;
 +    this.end = end2;
      parseId();
      checkValidRange();
    }
     */
    public Sequence(SequenceI seq, AlignmentAnnotation[] alAnnotation)
    {
 -    this(seq.getName(), seq.getSequence(), seq.getStart(), seq.getEnd());
 +    initSeqFrom(seq, alAnnotation);
 +
 +  }
 +
 +  protected void initSeqFrom(SequenceI seq,
 +          AlignmentAnnotation[] alAnnotation)
 +  {
 +    initSeqAndName(seq.getName(), seq.getSequence(), seq.getStart(),
 +            seq.getEnd());
      description = seq.getDescription();
      if (seq.getSequenceFeatures() != null)
      {
      return result;
    }
  
  }
   */
  package jalview.gui;
  
+ import java.awt.BorderLayout;
+ import java.awt.Component;
+ import java.awt.Rectangle;
+ import java.awt.Toolkit;
+ import java.awt.datatransfer.Clipboard;
+ import java.awt.datatransfer.DataFlavor;
+ import java.awt.datatransfer.StringSelection;
+ import java.awt.datatransfer.Transferable;
+ import java.awt.dnd.DnDConstants;
+ import java.awt.dnd.DropTargetDragEvent;
+ import java.awt.dnd.DropTargetDropEvent;
+ import java.awt.dnd.DropTargetEvent;
+ import java.awt.dnd.DropTargetListener;
+ import java.awt.event.ActionEvent;
+ import java.awt.event.ActionListener;
+ import java.awt.event.ItemEvent;
+ import java.awt.event.ItemListener;
+ import java.awt.event.KeyAdapter;
+ import java.awt.event.KeyEvent;
+ import java.awt.event.MouseAdapter;
+ import java.awt.event.MouseEvent;
+ import java.awt.print.PageFormat;
+ import java.awt.print.PrinterJob;
+ import java.beans.PropertyChangeEvent;
+ import java.io.File;
+ import java.net.URL;
+ import java.util.ArrayList;
+ import java.util.Arrays;
+ import java.util.Deque;
+ import java.util.Enumeration;
+ import java.util.Hashtable;
+ import java.util.List;
+ import java.util.Set;
+ import java.util.Vector;
+ import javax.swing.JCheckBoxMenuItem;
+ import javax.swing.JEditorPane;
+ import javax.swing.JInternalFrame;
+ import javax.swing.JLayeredPane;
+ import javax.swing.JMenu;
+ import javax.swing.JMenuItem;
+ import javax.swing.JOptionPane;
+ import javax.swing.JRadioButtonMenuItem;
+ import javax.swing.JScrollPane;
+ import javax.swing.SwingUtilities;
  import jalview.analysis.AAFrequency;
  import jalview.analysis.AlignmentSorter;
  import jalview.analysis.AlignmentUtils;
@@@ -32,7 -78,6 +78,7 @@@ import jalview.api.AlignViewControllerG
  import jalview.api.AlignViewControllerI;
  import jalview.api.AlignViewportI;
  import jalview.api.AlignmentViewPanel;
 +import jalview.api.FeatureSettingsControllerI;
  import jalview.api.SplitContainerI;
  import jalview.api.ViewStyleI;
  import jalview.api.analysis.ScoreModelI;
@@@ -52,6 -97,7 +98,7 @@@ import jalview.datamodel.AlignmentI
  import jalview.datamodel.AlignmentOrder;
  import jalview.datamodel.AlignmentView;
  import jalview.datamodel.ColumnSelection;
+ import jalview.datamodel.HiddenSequences;
  import jalview.datamodel.PDBEntry;
  import jalview.datamodel.SeqCigar;
  import jalview.datamodel.Sequence;
@@@ -61,6 -107,7 +108,6 @@@ import jalview.gui.ViewSelectionMenu.Vi
  import jalview.io.AlignmentProperties;
  import jalview.io.AnnotationFile;
  import jalview.io.BioJsHTMLOutput;
 -import jalview.io.FeaturesFile;
  import jalview.io.FileLoader;
  import jalview.io.FormatAdapter;
  import jalview.io.HtmlSvgOutput;
@@@ -97,52 -144,6 +144,6 @@@ import jalview.ws.jws2.Jws2Discoverer
  import jalview.ws.jws2.jabaws2.Jws2Instance;
  import jalview.ws.seqfetcher.DbSourceProxy;
  
- import java.awt.BorderLayout;
- import java.awt.Component;
- import java.awt.Rectangle;
- import java.awt.Toolkit;
- import java.awt.datatransfer.Clipboard;
- import java.awt.datatransfer.DataFlavor;
- import java.awt.datatransfer.StringSelection;
- import java.awt.datatransfer.Transferable;
- import java.awt.dnd.DnDConstants;
- import java.awt.dnd.DropTargetDragEvent;
- import java.awt.dnd.DropTargetDropEvent;
- import java.awt.dnd.DropTargetEvent;
- import java.awt.dnd.DropTargetListener;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.awt.event.ItemEvent;
- import java.awt.event.ItemListener;
- import java.awt.event.KeyAdapter;
- import java.awt.event.KeyEvent;
- import java.awt.event.MouseAdapter;
- import java.awt.event.MouseEvent;
- import java.awt.print.PageFormat;
- import java.awt.print.PrinterJob;
- import java.beans.PropertyChangeEvent;
- import java.io.File;
- import java.net.URL;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Deque;
- import java.util.Enumeration;
- import java.util.Hashtable;
- import java.util.List;
- import java.util.Set;
- import java.util.Vector;
- import javax.swing.JCheckBoxMenuItem;
- import javax.swing.JEditorPane;
- import javax.swing.JInternalFrame;
- import javax.swing.JLayeredPane;
- import javax.swing.JMenu;
- import javax.swing.JMenuItem;
- import javax.swing.JOptionPane;
- import javax.swing.JRadioButtonMenuItem;
- import javax.swing.JScrollPane;
- import javax.swing.SwingUtilities;
  /**
   * DOCUMENT ME!
   * 
@@@ -239,6 -240,7 +240,7 @@@ public class AlignFrame extends GAlignF
      this(al, hiddenColumns, width, height, null);
    }
  
    /**
     * Create alignment frame for al with hiddenColumns, a specific width and
     * height, and specific sequenceId
      init();
    }
  
+   public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
+           ColumnSelection hiddenColumns, int width, int height)
+   {
+     setSize(width, height);
+     if (al.getDataset() == null)
+     {
+       al.setDataset(null);
+     }
+     viewport = new AlignViewport(al, hiddenColumns);
+     if (hiddenSeqs != null && hiddenSeqs.length > 0)
+     {
+       viewport.hideSequence(hiddenSeqs);
+       viewport.setHasHiddenRows(true);
+     }
+     alignPanel = new AlignmentPanel(this, viewport);
+     addAlignmentPanel(alignPanel, true);
+     init();
+   }
    /**
     * Make a new AlignFrame from existing alignmentPanels
     * 
                  .lastIndexOf(java.io.File.separatorChar) + 1);
        }
  
-       /*
-        * First save any linked Chimera session.
-        */
-       Desktop.instance.saveChimeraSessions(file);
        success = new Jalview2XML().saveAlignment(this, file, shortName);
  
        statusBar.setText(MessageManager.formatMessage(
          return false;
        }
  
-       String[] omitHidden = null;
-       if (viewport.hasHiddenColumns())
-       {
-         int reply = JOptionPane
-                 .showInternalConfirmDialog(
-                         Desktop.desktop,
-                         MessageManager
-                                 .getString("label.alignment_contains_hidden_columns"),
-                         MessageManager
-                                 .getString("action.save_omit_hidden_columns"),
-                         JOptionPane.YES_NO_OPTION,
-                         JOptionPane.QUESTION_MESSAGE);
-         if (reply == JOptionPane.YES_OPTION)
-         {
-           omitHidden = viewport.getViewAsString(false);
-         }
-       }
-       FeatureRenderer fr = new FeatureRenderer(this.alignPanel);
-       viewport.setFeatureRenderer(fr);
+       ExportData exportData = getAlignmentForExport();
        FormatAdapter f = new FormatAdapter(viewport);
        String output = f.formatSequences(format,
-               viewport.getAlignment(), // class cast exceptions will
+               exportData.getAlignment(), // class cast exceptions will
                // occur in the distant future
-               omitHidden, f.getCacheSuffixDefault(format),
+               exportData.getOmitHidden(), exportData.getStartEndPostions(),
+               f.getCacheSuffixDefault(format),
                viewport.getColumnSelection());
  
        if (output == null)
      return success;
    }
  
    private void warningMessage(String warning, String title)
    {
      if (new jalview.util.Platform().isHeadless())
    @Override
    protected void outputText_actionPerformed(ActionEvent e)
    {
+     ExportData exportData = getAlignmentForExport();
+     CutAndPasteTransfer cap = new CutAndPasteTransfer();
+     cap.setForInput(null);
+     try
+     {
+       cap.setText(new FormatAdapter(viewport).formatSequences(
+               e.getActionCommand(),
+  exportData.getAlignment(),
+               exportData.getOmitHidden(), exportData.getStartEndPostions(),
+               viewport.getColumnSelection()));
+       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();
+     }
+   }
+   public ExportData getAlignmentForExport()
+   {
+     AlignmentI alignmentToExport = null;
      String[] omitHidden = null;
+     int[] alignmentStartEnd = new int[2];
      FeatureRenderer fr = new FeatureRenderer(this.alignPanel);
      viewport.setFeatureRenderer(fr);
-     if (viewport.hasHiddenColumns())
+     HiddenSequences hiddenSeqs = viewport.getAlignment()
+             .getHiddenSequences();
+     alignmentToExport = viewport.getAlignment();
+     alignmentStartEnd = new int[]
+     { 0, alignmentToExport.getWidth() - 1 };
+     if (viewport.hasHiddenColumns() || hiddenSeqs.getSize() > 0)
      {
        int reply = JOptionPane
                .showInternalConfirmDialog(
  
        if (reply == JOptionPane.YES_OPTION)
        {
+         // export only visible region
          omitHidden = viewport.getViewAsString(false);
+         alignmentToExport = viewport.getAlignment();
+         alignmentStartEnd = getStartEnd(alignmentStartEnd, viewport
+                 .getColumnSelection().getHiddenColumns());
+         viewport.setIncludeHiddenRegion(false);
+       }
+       else
+       {
+         // export all region including visible
+         alignmentToExport = hiddenSeqs.getFullAlignment();
+         viewport.setIncludeHiddenRegion(true);
        }
      }
  
-     CutAndPasteTransfer cap = new CutAndPasteTransfer();
-     cap.setForInput(null);
+     return new ExportData(alignmentToExport, omitHidden, alignmentStartEnd);
+   }
  
-     try
+   private static int[] getStartEnd(int[] aligmentStartEnd,
+           List<int[]> hiddenCols)
+   {
+     int startPos = aligmentStartEnd[0];
+     int endPos = aligmentStartEnd[1];
+     int[] lowestRange = new int[2];
+     int[] higestRange = new int[2];
+     for (int[] hiddenCol : hiddenCols)
      {
-       cap.setText(new FormatAdapter(viewport).formatSequences(
-               e.getActionCommand(),
-               viewport.getAlignment(), omitHidden,
-               viewport.getColumnSelection()));
-       Desktop.addInternalFrame(cap, MessageManager.formatMessage(
-               "label.alignment_output_command", new Object[]
-               { e.getActionCommand() }), 600, 500);
-     } catch (OutOfMemoryError oom)
+       // System.out.println("comparing : " + hiddenCol[0] + "-" + hiddenCol[1]);
+       lowestRange = (hiddenCol[0] <= startPos) ? hiddenCol : lowestRange;
+       higestRange = (hiddenCol[1] >= endPos) ? hiddenCol : higestRange;
+     }
+     // System.out.println("min : " + lowestRange[0] + "-" + lowestRange[1]);
+     // System.out.println("max : " + higestRange[0] + "-" + higestRange[1]);
+     if (lowestRange[0] == 0 && lowestRange[1] == 0)
      {
-       new OOMWarning("Outputting alignment as " + e.getActionCommand(), oom);
-       cap.dispose();
+       startPos = aligmentStartEnd[0];
+     }
+     else
+     {
+       startPos = lowestRange[1] + 1;
      }
  
+     if (higestRange[0] == 0 && higestRange[1] == 0)
+     {
+       endPos = aligmentStartEnd[1];
+     }
+     else
+     {
+       endPos = higestRange[0];
+     }
+     // System.out.println("Export range : " + minPos + " - " + maxPos);
+     return new int[]
+     { startPos, endPos };
+   }
+   public static void main(String[] args)
+   {
+     ArrayList<int[]> hiddenCols = new ArrayList<int[]>();
+     hiddenCols.add(new int[]
+     { 0, 4 });
+     hiddenCols.add(new int[]
+     { 6, 9 });
+     hiddenCols.add(new int[]
+     { 11, 12 });
+     hiddenCols.add(new int[]
+     { 33, 33 });
+     hiddenCols.add(new int[]
+     { 45, 50 });
+     int[] x = getStartEnd(new int[]
+     { 0, 50 }, hiddenCols);
+     // System.out.println("Export range : " + x[0] + " - " + x[1]);
    }
  
    /**
      }
  
      String output = new FormatAdapter().formatSequences("Fasta", seqs,
-             omitHidden);
+             omitHidden, null);
  
      StringSelection ss = new StringSelection(output);
  
    public FeatureSettings featureSettings;
  
    @Override
 +  public FeatureSettingsControllerI getFeatureSettingsUI()
 +  {
 +    return featureSettings;
 +  }
 +
 +  @Override
    public void featureSettings_actionPerformed(ActionEvent e)
    {
      if (featureSettings != null)
     *          contents or path to retrieve file
     * @param type
     *          access mode of file (see jalview.io.AlignFile)
 -   * @return true if features file was parsed corectly.
 +   * @return true if features file was parsed correctly.
     */
    public boolean parseFeaturesFile(String file, String type)
    {
 -    boolean featuresFile = false;
 -    try
 -    {
 -      featuresFile = new FeaturesFile(file, type).parse(viewport
 -              .getAlignment().getDataset(), alignPanel.getSeqPanel().seqCanvas
 -              .getFeatureRenderer().getFeatureColours(), false,
 -              jalview.bin.Cache.getDefault("RELAXEDSEQIDMATCHING", false));
 -    } catch (Exception ex)
 -    {
 -      ex.printStackTrace();
 -    }
 +    return avc.parseFeaturesFile(file, type,
 +            jalview.bin.Cache.getDefault("RELAXEDSEQIDMATCHING", false));
 +    
 +  }
  
 -    if (featuresFile)
 +  @Override
 +  public void refreshFeatureUI(boolean enableIfNecessary)
 +  {
 +    // note - currently this is only still here rather than in the controller
 +    // because of the featureSettings hard reference that is yet to be
 +    // abstracted
 +    if (enableIfNecessary)
      {
        viewport.setShowSequenceFeatures(true);
        showSeqFeatures.setSelected(true);
 -      if (alignPanel.getSeqPanel().seqCanvas.fr != null)
 -      {
 -        // update the min/max ranges where necessary
 -        alignPanel.getSeqPanel().seqCanvas.fr.findAllFeatures(true);
 -      }
 -      if (featureSettings != null)
 -      {
 -        featureSettings.setTableData();
 -      }
 -      alignPanel.paintAlignment(true);
      }
  
 -    return featuresFile;
 -  }
  
 +  }
    @Override
    public void dragEnter(DropTargetDragEvent evt)
    {
        sf.setComplementVisible(this, show);
      }
    }
+   public class ExportData
+   {
+     private AlignmentI alignment;
+     private String[] omitHidden;
+     private int[] startEnd;
+     public ExportData(AlignmentI align, String[] ommit, int[] startEnd)
+     {
+       this.alignment = align;
+       this.omitHidden = ommit;
+       this.startEnd = startEnd;
+     }
+     public AlignmentI getAlignment()
+     {
+       return alignment;
+     }
+     public void setAlignment(AlignmentI alignment)
+     {
+       this.alignment = alignment;
+     }
+     public String[] getOmitHidden()
+     {
+       return omitHidden;
+     }
+     public void setOmitHidden(String[] omitHidden)
+     {
+       this.omitHidden = omitHidden;
+     }
+     public int[] getStartEndPostions()
+     {
+       return startEnd;
+     }
+     public void setStartEndPostions(int[] startEnd)
+     {
+       this.startEnd = startEnd;
+     }
+   }
  }
  
  class PrintThread extends Thread
   */
  package jalview.io;
  
+ import java.io.File;
+ import java.io.InputStream;
+ import java.util.List;
  import jalview.api.AlignViewportI;
  import jalview.datamodel.Alignment;
  import jalview.datamodel.AlignmentAnnotation;
@@@ -28,10 -32,6 +32,6 @@@ import jalview.datamodel.AlignmentView
  import jalview.datamodel.SequenceGroup;
  import jalview.util.MessageManager;
  
- import java.io.File;
- import java.io.InputStream;
- import java.util.List;
  /**
   * A low level class for alignment and feature IO with alignment formatting
   * methods used by both applet and application for generating flat alignment
@@@ -82,7 -82,7 +82,7 @@@ public class AppletFormatAdapte
     */
    public static final String[] READABLE_FORMATS = new String[]
    { "BLC", "CLUSTAL", "FASTA", "MSF", "PileUp", "PIR", "PFAM", "STH",
 -      "PDB", "JnetFile", "RNAML", PhylipFile.FILE_DESC, JSONFile.FILE_DESC,
 +      "PDB", "JnetFile", "RNAML", PhylipFile.FILE_DESC, JSONFile.FILE_DESC, IdentifyFile.GFF3File,
        "HTML" };
  
    /**
@@@ -92,7 -92,6 +92,7 @@@
    public static final String[] READABLE_EXTENSIONS = new String[]
    { "fa, fasta, mfa, fastq", "aln", "pfam", "msf", "pir", "blc", "amsa",
        "sto,stk", "xml,rnaml", PhylipFile.FILE_EXT, JSONFile.FILE_EXT,
 +      ".gff2,gff3",
        "jar,jvp", HtmlFile.FILE_EXT };
  
    /**
     */
    public static final String[] READABLE_FNAMES = new String[]
    { "Fasta", "Clustal", "PFAM", "MSF", "PIR", "BLC", "AMSA", "Stockholm",
 -      "RNAML", PhylipFile.FILE_DESC, JSONFile.FILE_DESC, "Jalview",
 +      "RNAML", PhylipFile.FILE_DESC, JSONFile.FILE_DESC, IdentifyFile.GFF3File, "Jalview",
        HtmlFile.FILE_DESC };
  
    /**
          {
            al.addGroup(sg);
          }
          return al;
        }
        else if (format.equals(HtmlFile.FILE_DESC))
        {
          alignFile = new RnamlFile(inFile, type);
        }
 +      else if (format.equals(IdentifyFile.GFF3File))
 +      {
 +        alignFile = new Gff3File(inFile, type);
 +      }
  
        al = new Alignment(alignFile.getSeqsAsArray());
  
        {
          alignFile = new PhylipFile(source);
        }
 +      else if (format.equals(IdentifyFile.GFF3File))
 +      {
 +        alignFile = new Gff3File(inFile, type);
 +      }
        else if (format.equals(JSONFile.FILE_DESC))
        {
          alignFile = new JSONFile(source);
-         // ((JSONFile) afile).setViewport(viewport);
          al = new Alignment(alignFile.getSeqsAsArray());
          alignFile.addAnnotations(al);
          alignFile.addSeqGroups(al);
   */
  package jalview.io;
  
+ import jalview.api.ComplexAlignFile;
  import jalview.datamodel.AlignmentI;
+ import jalview.datamodel.ColumnSelection;
  import jalview.datamodel.PDBEntry;
  import jalview.datamodel.SequenceI;
  import jalview.gui.AlignFrame;
  import jalview.gui.AlignViewport;
  import jalview.gui.Desktop;
  import jalview.gui.Jalview2XML;
+ import jalview.schemes.ColourSchemeI;
  import jalview.structure.StructureSelectionManager;
  import jalview.util.MessageManager;
  
@@@ -314,6 -317,7 +317,7 @@@ public class FileLoader implements Runn
  
          if ((al != null) && (al.getHeight() > 0))
          {
+           // construct and register dataset sequences
            for (SequenceI sq : al.getSequences())
            {
              while (sq.getDatasetSequence() != null)
              {
                for (PDBEntry pdbe : sq.getPDBId())
                {
+                 // register PDB entries with desktop's structure selection
+                 // manager
                  StructureSelectionManager.getStructureSelectionManager(
                          Desktop.instance).registerPDBEntry(pdbe);
                }
              }
            }
            if (viewport != null)
            {
+             // append to existing alignment
              viewport.addAlignment(al, title);
            }
            else
            {
-             alignFrame = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH,
-                     AlignFrame.DEFAULT_HEIGHT);
-             alignFrame.statusBar.setText(MessageManager.formatMessage(
-                     "label.successfully_loaded_file", new String[]
-                     { title }));
+             // otherwise construct the alignFrame
  
-             if (!protocol.equals(AppletFormatAdapter.PASTE))
-             {
-               alignFrame.setFileName(file, format);
-             }
-             if (source instanceof HtmlFile)
+             if (source instanceof ComplexAlignFile)
              {
-               ((HtmlFile) source).applySettingsToAlignFrame(alignFrame);
+               ColumnSelection colSel = ((ComplexAlignFile) source)
+                       .getColumnSelection();
+               SequenceI[] hiddenSeqs = ((ComplexAlignFile) source)
+                       .getHiddenSequences();
+               boolean showSeqFeatures = ((ComplexAlignFile) source)
+                       .isShowSeqFeatures();
+               ColourSchemeI cs = ((ComplexAlignFile) source)
+                       .getColourScheme();
+               alignFrame = new AlignFrame(al, hiddenSeqs, colSel,
+                       AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
+               alignFrame.getViewport().setShowSequenceFeatures(
+                       showSeqFeatures);
+               alignFrame.changeColour(cs);
              }
-             else if (source instanceof JSONFile)
+             else
              {
-               ((JSONFile) source).applySettingsToAlignFrame(alignFrame);
+               alignFrame = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH,
+                       AlignFrame.DEFAULT_HEIGHT);
              }
+           }
+           // add metadata and update ui
+           if (!protocol.equals(AppletFormatAdapter.PASTE))
+           {
+             alignFrame.setFileName(file, format);
+           }
  
-             if (raiseGUI)
-             {
-               // add the window to the GUI
-               // note - this actually should happen regardless of raiseGUI
-               // status in Jalview 3
-               // TODO: define 'virtual desktop' for benefit of headless scripts
-               // that perform queries to find the 'current working alignment'
-               Desktop.addInternalFrame(alignFrame, title,
-                       AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
-             }
+           alignFrame.statusBar.setText(MessageManager.formatMessage(
+                   "label.successfully_loaded_file", new String[]
+                   { title }));
  
-             try
-             {
-               alignFrame.setMaximum(jalview.bin.Cache.getDefault(
-                       "SHOW_FULLSCREEN", false));
-             } catch (java.beans.PropertyVetoException ex)
-             {
-             }
+           if (raiseGUI)
+           {
+             // add the window to the GUI
+             // note - this actually should happen regardless of raiseGUI
+             // status in Jalview 3
+             // TODO: define 'virtual desktop' for benefit of headless scripts
+             // that perform queries to find the 'current working alignment'
+             Desktop.addInternalFrame(alignFrame, title,
+                     AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
+           }
+           try
+           {
+             alignFrame.setMaximum(jalview.bin.Cache.getDefault(
+                     "SHOW_FULLSCREEN", false));
+           } catch (java.beans.PropertyVetoException ex)
+           {
            }
          }
          else
  
            final String errorMessage = "Couldn't load file " + title + "\n"
                    + error;
 -          if (raiseGUI)
 +          // TODO: refactor FileLoader to be independent of Desktop / Applet GUI
 +          // bits ?
 +          if (raiseGUI && Desktop.desktop != null)
            {
              javax.swing.SwingUtilities.invokeLater(new Runnable()
              {