JAL-1605 merge commit
authorCharles Ofoegbu <tcnofoegbu@dundee.ac.uk>
Fri, 5 Dec 2014 12:45:11 +0000 (12:45 +0000)
committerCharles Ofoegbu <tcnofoegbu@dundee.ac.uk>
Fri, 5 Dec 2014 12:45:11 +0000 (12:45 +0000)
1  2 
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/AnnotationExporter.java
src/jalview/gui/ChimeraViewFrame.java
src/jalview/gui/FeatureRenderer.java
src/jalview/gui/FeatureSettings.java
src/jalview/gui/Jalview2XML.java
src/jalview/gui/Jalview2XML_V1.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/SeqPanel.java

@@@ -30,7 -30,6 +30,7 @@@ import jalview.analysis.ParseProperties
  import jalview.analysis.SequenceIdMatcher;
  import jalview.api.AlignViewControllerGuiI;
  import jalview.api.AlignViewControllerI;
 +import jalview.api.AlignmentViewPanel;
  import jalview.api.analysis.ScoreModelI;
  import jalview.bin.Cache;
  import jalview.commands.CommandI;
@@@ -55,11 -54,10 +55,11 @@@ import jalview.datamodel.SequenceGroup
  import jalview.datamodel.SequenceI;
  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.HTMLOutput;
+ import jalview.io.HtmlSvgOutput;
  import jalview.io.IdentifyFile;
  import jalview.io.JalviewFileChooser;
  import jalview.io.JalviewFileView;
@@@ -117,7 -115,6 +117,7 @@@ import java.beans.PropertyChangeEvent
  import java.io.File;
  import java.net.URL;
  import java.util.ArrayList;
 +import java.util.Arrays;
  import java.util.Enumeration;
  import java.util.Hashtable;
  import java.util.List;
@@@ -382,7 -379,7 +382,7 @@@ public class AlignFrame extends GAlignF
                          .getKeyCode() <= KeyEvent.VK_NUMPAD9))
                  && Character.isDigit(evt.getKeyChar()))
          {
-           alignPanel.seqPanel.numberPressed(evt.getKeyChar());
+           alignPanel.getSeqPanel().numberPressed(evt.getKeyChar());
          }
  
          switch (evt.getKeyCode())
            }
            if (viewport.cursorMode)
            {
-             alignPanel.seqPanel.moveCursor(0, 1);
+             alignPanel.getSeqPanel().moveCursor(0, 1);
            }
            break;
  
            }
            if (viewport.cursorMode)
            {
-             alignPanel.seqPanel.moveCursor(0, -1);
+             alignPanel.getSeqPanel().moveCursor(0, -1);
            }
  
            break;
          case KeyEvent.VK_LEFT:
            if (evt.isAltDown() || !viewport.cursorMode)
            {
-             slideSequences(false, alignPanel.seqPanel.getKeyboardNo1());
+             slideSequences(false, alignPanel.getSeqPanel().getKeyboardNo1());
            }
            else
            {
-             alignPanel.seqPanel.moveCursor(-1, 0);
+             alignPanel.getSeqPanel().moveCursor(-1, 0);
            }
  
            break;
          case KeyEvent.VK_RIGHT:
            if (evt.isAltDown() || !viewport.cursorMode)
            {
-             slideSequences(true, alignPanel.seqPanel.getKeyboardNo1());
+             slideSequences(true, alignPanel.getSeqPanel().getKeyboardNo1());
            }
            else
            {
-             alignPanel.seqPanel.moveCursor(1, 0);
+             alignPanel.getSeqPanel().moveCursor(1, 0);
            }
            break;
  
          case KeyEvent.VK_SPACE:
            if (viewport.cursorMode)
            {
-             alignPanel.seqPanel.insertGapAtCursor(evt.isControlDown()
+             alignPanel.getSeqPanel().insertGapAtCursor(evt.isControlDown()
                      || evt.isShiftDown() || evt.isAltDown());
            }
            break;
            }
            else
            {
-             alignPanel.seqPanel.deleteGapAtCursor(evt.isControlDown()
+             alignPanel.getSeqPanel().deleteGapAtCursor(evt.isControlDown()
                      || evt.isShiftDown() || evt.isAltDown());
            }
  
          case KeyEvent.VK_S:
            if (viewport.cursorMode)
            {
-             alignPanel.seqPanel.setCursorRow();
+             alignPanel.getSeqPanel().setCursorRow();
            }
            break;
          case KeyEvent.VK_C:
            if (viewport.cursorMode && !evt.isControlDown())
            {
-             alignPanel.seqPanel.setCursorColumn();
+             alignPanel.getSeqPanel().setCursorColumn();
            }
            break;
          case KeyEvent.VK_P:
            if (viewport.cursorMode)
            {
-             alignPanel.seqPanel.setCursorPosition();
+             alignPanel.getSeqPanel().setCursorPosition();
            }
            break;
  
          case KeyEvent.VK_COMMA:
            if (viewport.cursorMode)
            {
-             alignPanel.seqPanel.setCursorRowAndColumn();
+             alignPanel.getSeqPanel().setCursorRowAndColumn();
            }
            break;
  
          case KeyEvent.VK_Q:
            if (viewport.cursorMode)
            {
-             alignPanel.seqPanel.setSelectionAreaAtCursor(true);
+             alignPanel.getSeqPanel().setSelectionAreaAtCursor(true);
            }
            break;
          case KeyEvent.VK_M:
            if (viewport.cursorMode)
            {
-             alignPanel.seqPanel.setSelectionAreaAtCursor(false);
+             alignPanel.getSeqPanel().setSelectionAreaAtCursor(false);
            }
            break;
  
                    { (viewport.cursorMode ? "on" : "off") }));
            if (viewport.cursorMode)
            {
-             alignPanel.seqPanel.seqCanvas.cursorX = viewport.startRes;
-             alignPanel.seqPanel.seqCanvas.cursorY = viewport.startSeq;
+             alignPanel.getSeqPanel().seqCanvas.cursorX = viewport.startRes;
+             alignPanel.getSeqPanel().seqCanvas.cursorY = viewport.startSeq;
            }
-           alignPanel.seqPanel.seqCanvas.repaint();
+           alignPanel.getSeqPanel().seqCanvas.repaint();
            break;
  
          case KeyEvent.VK_F1:
      abovePIDThreshold.setSelected(av.getAbovePIDThreshold());
      conservationMenuItem.setSelected(av.getConservationSelected());
      seqLimits.setSelected(av.getShowJVSuffix());
-     idRightAlign.setSelected(av.rightAlignIds);
+     idRightAlign.setSelected(av.isRightAlignIds());
      centreColumnLabelsMenuItem.setState(av.centreColumnLabels);
      renderGapsMenuItem.setSelected(av.renderGaps);
      wrapMenuItem.setSelected(av.wrapAlignment);
      scaleAbove.setVisible(av.wrapAlignment);
      scaleLeft.setVisible(av.wrapAlignment);
      scaleRight.setVisible(av.wrapAlignment);
-     annotationPanelMenuItem.setState(av.showAnnotation);
+     annotationPanelMenuItem.setState(av.isShowAnnotation());
      /*
       * Show/hide annotations only enabled if annotation panel is shown
       */
  
    public FeatureRenderer getFeatureRenderer()
    {
-     return alignPanel.seqPanel.seqCanvas.getFeatureRenderer();
+     return alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer();
    }
  
    @Override
    @Override
    protected void htmlMenuItem_actionPerformed(ActionEvent e)
    {
-     new HTMLOutput(alignPanel,
-             alignPanel.seqPanel.seqCanvas.getSequenceRenderer(),
-             alignPanel.seqPanel.seqCanvas.getFeatureRenderer());
+     // new HTMLOutput(alignPanel,
+     // alignPanel.getSeqPanel().seqCanvas.getSequenceRenderer(),
+     // alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer());
+     new HtmlSvgOutput(alignPanel);
    }
  
 +  @Override
 +  public void bioJSMenuItem_actionPerformed(ActionEvent e)
 +  {
 +    new BioJsHTMLOutput(alignPanel,
-             alignPanel.seqPanel.seqCanvas.getFeatureRenderer());
++            alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer());
 +  }
    public void createImageMap(File file, String image)
    {
      alignPanel.makePNGImageMap(file, image);
    public void exportAnnotations_actionPerformed(ActionEvent e)
    {
      new AnnotationExporter().exportAnnotations(alignPanel,
-             viewport.showAnnotation ? viewport.getAlignment()
+             viewport.isShowAnnotation() ? viewport.getAlignment()
                      .getAlignmentAnnotation() : null, viewport
                      .getAlignment().getGroups(), ((Alignment) viewport
                      .getAlignment()).alignmentProperties);
      if (viewport.cursorMode)
      {
        sg.add(viewport.getAlignment().getSequenceAt(
-               alignPanel.seqPanel.seqCanvas.cursorY));
+               alignPanel.getSeqPanel().seqCanvas.cursorY));
      }
      else if (viewport.getSelectionGroup() != null
              && viewport.getSelectionGroup().getSize() != viewport
      {
        if (viewport.cursorMode)
        {
-         alignPanel.seqPanel.moveCursor(size, 0);
+         alignPanel.getSeqPanel().moveCursor(size, 0);
        }
        else
        {
      {
        if (viewport.cursorMode)
        {
-         alignPanel.seqPanel.moveCursor(-size, 0);
+         alignPanel.getSeqPanel().moveCursor(-size, 0);
        }
        else
        {
  
          // >>>This is a fix for the moment, until a better solution is
          // found!!<<<
-         af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer()
+         af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
                  .transferSettings(
-                         alignPanel.seqPanel.seqCanvas.getFeatureRenderer());
+                         alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer());
  
          // TODO: maintain provenance of an alignment, rather than just make the
          // title a concatenation of operations.
  
        // >>>This is a fix for the moment, until a better solution is
        // found!!<<<
-       af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer()
+       af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
                .transferSettings(
-                       alignPanel.seqPanel.seqCanvas.getFeatureRenderer());
+                       alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer());
  
        // TODO: maintain provenance of an alignment, rather than just make the
        // title a concatenation of operations.
    {
      if (viewport.cursorMode)
      {
-       alignPanel.seqPanel.keyboardNo1 = null;
-       alignPanel.seqPanel.keyboardNo2 = null;
+       alignPanel.getSeqPanel().keyboardNo1 = null;
+       alignPanel.getSeqPanel().keyboardNo2 = null;
      }
      viewport.setSelectionGroup(null);
      viewport.getColumnSelection().clear();
      viewport.setSelectionGroup(null);
-     alignPanel.seqPanel.seqCanvas.highlightSearchResults(null);
-     alignPanel.idPanel.idCanvas.searchResults = null;
+     alignPanel.getSeqPanel().seqCanvas.highlightSearchResults(null);
+     alignPanel.getIdPanel().getIdCanvas().searchResults = null;
      alignPanel.paintAlignment(true);
      PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
      viewport.sendSelection();
    {
      viewport.setShowJVSuffix(seqLimits.isSelected());
  
-     alignPanel.idPanel.idCanvas.setPreferredSize(alignPanel
+     alignPanel.getIdPanel().getIdCanvas().setPreferredSize(alignPanel
              .calculateIdWidth());
      alignPanel.paintAlignment(true);
    }
    @Override
    public void idRightAlign_actionPerformed(ActionEvent e)
    {
-     viewport.rightAlignIds = idRightAlign.isSelected();
+     viewport.setRightAlignIds(idRightAlign.isSelected());
      alignPanel.paintAlignment(true);
    }
  
      if (viewport.followHighlight = this.followHighlightMenuItem.getState())
      {
        alignPanel.scrollToPosition(
-               alignPanel.seqPanel.seqCanvas.searchResults, false);
+               alignPanel.getSeqPanel().seqCanvas.searchResults, false);
      }
    }
  
      else if (viewport.getSelectionGroup() != null
              && viewport.getSelectionGroup().getSize() == 1)
      {
 -      int option = JOptionPane
 -              .showConfirmDialog(
 -this,
 -                      "More than one sequece group selection is required for this Job, click \n'Cancel' to edit your selection or 'Ok' to submit the entire sequence.",
 -                      "Invalid selection",
 -                      JOptionPane.OK_CANCEL_OPTION);
 +      int option = JOptionPane.showConfirmDialog(this,
 +              MessageManager.getString("warn.oneseq_msainput_selection"),
 +              MessageManager.getString("label.invalid_selection"),
 +              JOptionPane.OK_CANCEL_OPTION);
        if (option == JOptionPane.OK_OPTION)
        {
          msa = viewport.getAlignmentView(false);
        }
      }
      else
      {
 -      /*
 -       * Vector seqs = viewport.getAlignment().getSequences();
 -       * 
 -       * if (seqs.size() > 1) { msa = new SequenceI[seqs.size()];
 -       * 
 -       * for (int i = 0; i < seqs.size(); i++) { msa[i] = (SequenceI)
 -       * seqs.elementAt(i); } }
 -       */
        msa = viewport.getAlignmentView(false);
      }
      return msa;
      try
      {
        featuresFile = new FeaturesFile(file, type).parse(viewport
-               .getAlignment().getDataset(), alignPanel.seqPanel.seqCanvas
+               .getAlignment().getDataset(), alignPanel.getSeqPanel().seqCanvas
                .getFeatureRenderer().featureColours, false,
                jalview.bin.Cache.getDefault("RELAXEDSEQIDMATCHING", false));
      } catch (Exception ex)
      {
        viewport.showSequenceFeatures = true;
        showSeqFeatures.setSelected(true);
-       if (alignPanel.seqPanel.seqCanvas.fr != null)
+       if (alignPanel.getSeqPanel().seqCanvas.fr != null)
        {
          // update the min/max ranges where necessary
-         alignPanel.seqPanel.seqCanvas.fr.findAllFeatures(true);
+         alignPanel.getSeqPanel().seqCanvas.fr.findAllFeatures(true);
        }
        if (featureSettings != null)
        {
              .setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
      alignPanel.paintAlignment(true);
    }
 +
 +  /**
 +   * 
 +   * @return alignment panels in this alignemnt frame
 +   */
 +  public List<AlignmentViewPanel> getAlignPanels()
 +  {
 +    return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
 +  }
  }
  
  class PrintThread extends Thread
@@@ -97,7 -97,7 +97,7 @@@ public class AlignViewport extends Alig
  
    boolean showSequenceFeatures = false;
  
-   boolean showAnnotation = true;
+   private boolean showAnnotation = true;
  
    SequenceAnnotationOrder sortAnnotationsBy = null;
  
     * Keys are the feature types which are currently visible. Note: Values are
     * not used!
     */
 -  Hashtable featuresDisplayed = null;
 +  private Hashtable featuresDisplayed = null;
  
    boolean antiAlias = false;
  
  
    Color textColour2 = Color.white;
  
-   boolean rightAlignIds = false;
+   private boolean rightAlignIds = false;
  
    /**
     * Creates a new AlignViewport object.
      antiAlias = Cache.getDefault("ANTI_ALIAS", false);
  
      showJVSuffix = Cache.getDefault("SHOW_JVSUFFIX", true);
-     showAnnotation = Cache.getDefault("SHOW_ANNOTATIONS", true);
+     setShowAnnotation(Cache.getDefault("SHOW_ANNOTATIONS", true));
  
-     rightAlignIds = Cache.getDefault("RIGHT_ALIGN_IDS", false);
+     setRightAlignIds(Cache.getDefault("RIGHT_ALIGN_IDS", false));
      centreColumnLabels = Cache.getDefault("CENTRE_COLUMN_LABELS", false);
      autoCalculateConsensus = Cache.getDefault("AUTO_CALC_CONSENSUS", true);
  
     */
    public boolean getShowAnnotation()
    {
-     return showAnnotation;
+     return isShowAnnotation();
    }
  
    /**
      }
    }
  
 +
 +  public Hashtable getFeaturesDisplayed()
 +  {
 +    return featuresDisplayed;
 +  }
 +
 +  public void setFeaturesDisplayed(Hashtable featuresDisplayed)
 +  {
 +    this.featuresDisplayed = featuresDisplayed;
 +  }
    protected SequenceAnnotationOrder getSortAnnotationsBy()
    {
      return sortAnnotationsBy;
    {
      this.showAutocalculatedAbove = showAutocalculatedAbove;
    }
+   public boolean isShowAnnotation()
+   {
+     return showAnnotation;
+   }
+   public boolean isRightAlignIds()
+   {
+     return rightAlignIds;
+   }
+   public void setRightAlignIds(boolean rightAlignIds)
+   {
+     this.rightAlignIds = rightAlignIds;
+   }
  }
@@@ -29,6 -29,7 +29,7 @@@ import jalview.datamodel.SequenceFeatur
  import jalview.datamodel.SequenceGroup;
  import jalview.datamodel.SequenceI;
  import jalview.jbgui.GAlignmentPanel;
+ import jalview.math.AlignmentDimension;
  import jalview.schemes.ResidueProperties;
  import jalview.structure.StructureSelectionManager;
  import jalview.util.MessageManager;
@@@ -66,20 -67,21 +67,21 @@@ public class AlignmentPanel extends GAl
  
    OverviewPanel overviewPanel;
  
-   SeqPanel seqPanel;
+   private SeqPanel seqPanel;
  
-   IdPanel idPanel;
+   private IdPanel idPanel;
  
+   private boolean headless;
    IdwidthAdjuster idwidthAdjuster;
  
    /** DOCUMENT ME!! */
    public AlignFrame alignFrame;
  
-   ScalePanel scalePanel;
+   private ScalePanel scalePanel;
  
-   AnnotationPanel annotationPanel;
+   private AnnotationPanel annotationPanel;
  
-   AnnotationLabels alabels;
+   private AnnotationLabels alabels;
  
    // this value is set false when selection area being dragged
    boolean fastPaint = true;
    {
      alignFrame = af;
      this.av = av;
-     seqPanel = new SeqPanel(av, this);
-     idPanel = new IdPanel(av, this);
+     setSeqPanel(new SeqPanel(av, this));
+     setIdPanel(new IdPanel(av, this));
  
-     scalePanel = new ScalePanel(av, this);
+     setScalePanel(new ScalePanel(av, this));
  
-     idPanelHolder.add(idPanel, BorderLayout.CENTER);
+     idPanelHolder.add(getIdPanel(), BorderLayout.CENTER);
      idwidthAdjuster = new IdwidthAdjuster(this);
      idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);
  
-     annotationPanel = new AnnotationPanel(this);
-     alabels = new AnnotationLabels(this);
+     setAnnotationPanel(new AnnotationPanel(this));
+     setAlabels(new AnnotationLabels(this));
  
-     annotationScroller.setViewportView(annotationPanel);
-     annotationSpaceFillerHolder.add(alabels, BorderLayout.CENTER);
+     annotationScroller.setViewportView(getAnnotationPanel());
+     annotationSpaceFillerHolder.add(getAlabels(), BorderLayout.CENTER);
  
-     scalePanelHolder.add(scalePanel, BorderLayout.CENTER);
-     seqPanelHolder.add(seqPanel, BorderLayout.CENTER);
+     scalePanelHolder.add(getScalePanel(), BorderLayout.CENTER);
+     seqPanelHolder.add(getSeqPanel(), BorderLayout.CENTER);
  
      setScrollValues(0, 0);
  
      idSpaceFillerPanel1.setPreferredSize(new Dimension(10, av.charHeight
              + fm.getDescent()));
  
-     idPanel.idCanvas.gg = null;
-     seqPanel.seqCanvas.img = null;
-     annotationPanel.adjustPanelHeight();
+     getIdPanel().getIdCanvas().gg = null;
+     getSeqPanel().seqCanvas.img = null;
+     getAnnotationPanel().adjustPanelHeight();
  
      Dimension d = calculateIdWidth();
      d.setSize(d.width + 4, d.height);
-     idPanel.idCanvas.setPreferredSize(d);
+     getIdPanel().getIdCanvas().setPreferredSize(d);
      hscrollFillerPanel.setPreferredSize(d);
  
      if (overviewPanel != null)
  
      if (al.getAlignmentAnnotation() != null)
      {
-       fm = c.getFontMetrics(alabels.getFont());
+       fm = c.getFontMetrics(getAlabels().getFont());
  
        while (i < al.getAlignmentAnnotation().length)
        {
    public void highlightSearchResults(SearchResults results)
    {
      scrollToPosition(results);
-     seqPanel.seqCanvas.highlightSearchResults(results);
+     getSeqPanel().seqCanvas.highlightSearchResults(results);
    }
  
    /**
  
    void scrollToWrappedVisible(int res)
    {
-     int cwidth = seqPanel.seqCanvas
-             .getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());
+     int cwidth = getSeqPanel().seqCanvas
+             .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
      if (res < av.getStartRes() || res >= (av.getStartRes() + cwidth))
      {
        vscroll.setValue((res / cwidth));
     */
    protected void validateAnnotationDimensions(boolean adjustPanelHeight)
    {
-     int height = annotationPanel.adjustPanelHeight();
+     int height = getAnnotationPanel().adjustPanelHeight();
  
      int theight = av.getCharHeight()
              * (av.getAlignment().getHeight() + (!av.hasHiddenRows() ? 0
        annotationScroller.setVisible(false);
        annotationSpaceFillerHolder.setVisible(false);
      }
-     else if (av.showAnnotation)
+     else if (av.isShowAnnotation())
      {
        annotationScroller.setVisible(true);
        annotationSpaceFillerHolder.setVisible(true);
        width = av.getColumnSelection().findColumnPosition(width);
      }
  
-     av.setEndRes((x + (seqPanel.seqCanvas.getWidth() / av.charWidth)) - 1);
+     av.setEndRes((x + (getSeqPanel().seqCanvas.getWidth() / av.charWidth)) - 1);
  
-     hextent = seqPanel.seqCanvas.getWidth() / av.charWidth;
-     vextent = seqPanel.seqCanvas.getHeight() / av.charHeight;
+     hextent = getSeqPanel().seqCanvas.getWidth() / av.charWidth;
+     vextent = getSeqPanel().seqCanvas.getHeight() / av.charHeight;
  
      if (hextent > width)
      {
      {
        int x = hscroll.getValue();
        av.setStartRes(x);
-       av.setEndRes((x + (seqPanel.seqCanvas.getWidth() / av.getCharWidth())) - 1);
+       av.setEndRes((x + (getSeqPanel().seqCanvas.getWidth() / av.getCharWidth())) - 1);
      }
  
      if (evt.getSource() == vscroll)
        {
          if (offy > -1)
          {
-           int rowSize = seqPanel.seqCanvas
-                   .getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());
+           int rowSize = getSeqPanel().seqCanvas
+                   .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
            av.setStartRes(offy * rowSize);
            av.setEndRes((offy + 1) * rowSize);
          }
        {
          av.setStartSeq(offy);
          av.setEndSeq(offy
-                 + (seqPanel.seqCanvas.getHeight() / av.getCharHeight()));
+                 + (getSeqPanel().seqCanvas.getHeight() / av.getCharHeight()));
        }
      }
  
  
        if (scrollX != 0 || scrollY != 0)
        {
-         idPanel.idCanvas.fastPaint(scrollY);
-         seqPanel.seqCanvas.fastPaint(scrollX, scrollY);
-         scalePanel.repaint();
+         getIdPanel().getIdCanvas().fastPaint(scrollY);
+         getSeqPanel().seqCanvas.fastPaint(scrollX, scrollY);
+         getScalePanel().repaint();
  
          if (av.getShowAnnotation() && scrollX != 0)
          {
-           annotationPanel.fastPaint(scrollX);
+           getAnnotationPanel().fastPaint(scrollX);
          }
        }
      }
    {
      invalidate();
  
-     Dimension d = idPanel.idCanvas.getPreferredSize();
+     Dimension d = getIdPanel().getIdCanvas().getPreferredSize();
      idPanelHolder.setPreferredSize(d);
      hscrollFillerPanel.setPreferredSize(new Dimension(d.width, 12));
      validate();
          maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
        }
  
-       int canvasWidth = seqPanel.seqCanvas
-               .getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());
+       int canvasWidth = getSeqPanel().seqCanvas
+               .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
        if (canvasWidth > 0)
        {
          int max = maxwidth
-                 / seqPanel.seqCanvas
-                         .getWrappedCanvasWidth(seqPanel.seqCanvas
+                 / getSeqPanel().seqCanvas
+                         .getWrappedCanvasWidth(getSeqPanel().seqCanvas
                                  .getWidth()) + 1;
          vscroll.setMaximum(max);
          vscroll.setUnitIncrement(1);
      int pagesHigh = ((av.getAlignment().getHeight() / totalSeq) + 1)
              * pheight;
  
-     if (av.showAnnotation)
+     if (av.isShowAnnotation())
      {
-       pagesHigh += annotationPanel.adjustPanelHeight() + 3;
+       pagesHigh += getAnnotationPanel().adjustPanelHeight() + 3;
      }
  
      pagesHigh /= pheight;
  
      // draw Scale
      pg.translate(idWidth, 0);
-     scalePanel.drawScale(pg, startRes, endRes, pwidth - idWidth,
+     getScalePanel().drawScale(pg, startRes, endRes, pwidth - idWidth,
              scaleHeight);
      pg.translate(-idWidth, scaleHeight);
  
      Color currentColor = null;
      Color currentTextColor = null;
  
-     pg.setFont(idPanel.idCanvas.idfont);
+     pg.setFont(getIdPanel().getIdCanvas().getIdfont());
  
      SequenceI seq;
      for (int i = startSeq; i < endSeq; i++)
        pg.setColor(currentTextColor);
  
        int xPos = 0;
-       if (av.rightAlignIds)
+       if (av.isRightAlignIds())
        {
          fm = pg.getFontMetrics();
          xPos = idWidth
  
      // draw main sequence panel
      pg.translate(idWidth, 0);
-     seqPanel.seqCanvas.drawPanel(pg, startRes, endRes, startSeq, endSeq, 0);
+     getSeqPanel().seqCanvas.drawPanel(pg, startRes, endRes, startSeq, endSeq, 0);
  
-     if (av.showAnnotation && (endSeq == av.getAlignment().getHeight()))
+     if (av.isShowAnnotation() && (endSeq == av.getAlignment().getHeight()))
      {
        // draw annotation - need to offset for current scroll position
-       int offset = -alabels.scrollOffset;
+       int offset = -getAlabels().getScrollOffset();
        pg.translate(0, offset);
        pg.translate(-idWidth - 3, (endSeq - startSeq) * av.charHeight + 3);
-       alabels.drawComponent(pg, idWidth);
+       getAlabels().drawComponent(pg, idWidth);
        pg.translate(idWidth + 3, 0);
-       annotationPanel.renderer.drawComponent(annotationPanel, av,
+       getAnnotationPanel().renderer.drawComponent(getAnnotationPanel(), av,
                pg, -1, startRes, endRes + 1);
        pg.translate(0, -offset);
      }
  
      int annotationHeight = 0;
      AnnotationLabels labels = null;
-     if (av.showAnnotation)
+     if (av.isShowAnnotation())
      {
-       annotationHeight = annotationPanel.adjustPanelHeight();
+       annotationHeight = getAnnotationPanel().adjustPanelHeight();
        labels = new AnnotationLabels(av);
      }
  
        maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
      }
  
-     int resWidth = seqPanel.seqCanvas.getWrappedCanvasWidth(pwidth
+     int resWidth = getSeqPanel().seqCanvas.getWrappedCanvasWidth(pwidth
              - idWidth);
  
      int totalHeight = cHeight * (maxwidth / resWidth + 1);
      {
        for (int i = 0; i < av.getAlignment().getHeight(); i++)
        {
-         pg.setFont(idPanel.idCanvas.idfont);
+         pg.setFont(getIdPanel().getIdCanvas().getIdfont());
          SequenceI s = av.getAlignment().getSequenceAt(i);
          String string = s.getDisplayId(av.getShowJVSuffix());
          int xPos = 0;
-         if (av.rightAlignIds)
+         if (av.isRightAlignIds())
          {
            FontMetrics fm = pg.getFontMetrics();
            xPos = idWidth - fm.stringWidth(string) - 4;
  
      pg.translate(idWidth, 0);
  
-     seqPanel.seqCanvas.drawWrappedPanel(pg, pwidth - idWidth, totalHeight,
+     getSeqPanel().seqCanvas.drawWrappedPanel(pg, pwidth - idWidth, totalHeight,
              0);
  
      if ((pi * pheight) < totalHeight)
     * 
     * @return
     */
-   int getVisibleIdWidth()
+   public int getVisibleIdWidth()
    {
      return getVisibleIdWidth(true);
    }
     *          be returned
     * @return
     */
-   int getVisibleIdWidth(boolean onscreen)
+   public int getVisibleIdWidth(boolean onscreen)
    {
      // see if rendering offscreen - check preferences and calc width accordingly
      if (!onscreen && Cache.getDefault("FIGURE_AUTOIDWIDTH", false))
      if (onscreen
              || (idwidth = Cache.getIntegerProperty("FIGURE_FIXEDIDWIDTH")) == null)
      {
-       return (idPanel.getWidth() > 0 ? idPanel.getWidth()
+       return (getIdPanel().getWidth() > 0 ? getIdPanel().getWidth()
                : calculateIdWidth().width + 4);
      }
      return idwidth.intValue() + 4;
    void makeAlignmentImage(jalview.util.ImageMaker.TYPE type, File file)
    {
      long progress = System.currentTimeMillis();
-     boolean headless = (System.getProperty("java.awt.headless") != null && System
+     headless = (System.getProperty("java.awt.headless") != null && System
              .getProperty("java.awt.headless").equals("true"));
      if (alignFrame != null && !headless)
      {
      }
      try
      {
-       int maxwidth = av.getAlignment().getWidth();
-       if (av.hasHiddenColumns())
-       {
-         maxwidth = av.getColumnSelection().findColumnPosition(maxwidth);
-       }
-       int height = ((av.getAlignment().getHeight() + 1) * av.charHeight)
-               + scalePanel.getHeight();
-       int width = getVisibleIdWidth(false) + (maxwidth * av.charWidth);
-       if (av.getWrapAlignment())
-       {
-         height = getWrappedHeight();
-         if (headless)
-         {
-           // need to obtain default alignment width and then add in any
-           // additional allowance for id margin
-           // this duplicates the calculation in getWrappedHeight but adjusts for
-           // offscreen idWith
-           width = alignFrame.getWidth() - vscroll.getPreferredSize().width
-                   - alignFrame.getInsets().left
-                   - alignFrame.getInsets().right - getVisibleIdWidth()
-                   + getVisibleIdWidth(false);
-         }
-         else
-         {
-           width = seqPanel.getWidth() + getVisibleIdWidth(false);
-         }
-       }
-       else if (av.getShowAnnotation())
-       {
-         height += annotationPanel.adjustPanelHeight() + 3;
-       }
+       AlignmentDimension aDimension = getAlignmentDimension();
        try
        {
          jalview.util.ImageMaker im;
          final String imageAction, imageTitle;
          if (type == jalview.util.ImageMaker.TYPE.PNG)
            imageTitle = alignFrame.getTitle();
          }
  
-         im = new jalview.util.ImageMaker(this, type, imageAction, width,
-                 height, file, imageTitle);
+         im = new jalview.util.ImageMaker(this, type, imageAction,
+                 aDimension.getWidth(), aDimension.getHeight(), file,
+                 imageTitle);
          if (av.getWrapAlignment())
          {
            if (im.getGraphics() != null)
            {
-             printWrappedAlignment(im.getGraphics(), width, height, 0);
+             printWrappedAlignment(im.getGraphics(), aDimension.getWidth(),
+                     aDimension.getHeight(), 0);
              im.writeImage();
            }
          }
          {
            if (im.getGraphics() != null)
            {
-             printUnwrapped(im.getGraphics(), width, height, 0);
+             printUnwrapped(im.getGraphics(), aDimension.getWidth(),
+                     aDimension.getHeight(), 0);
              im.writeImage();
            }
          }
      }
    }
  
+   public AlignmentDimension getAlignmentDimension()
+   {
+     int maxwidth = av.getAlignment().getWidth();
+     if (av.hasHiddenColumns())
+     {
+       maxwidth = av.getColumnSelection().findColumnPosition(maxwidth);
+     }
+     int height = ((av.getAlignment().getHeight() + 1) * av.charHeight)
+             + getScalePanel().getHeight();
+     int width = getVisibleIdWidth(false) + (maxwidth * av.charWidth);
+     if (av.getWrapAlignment())
+     {
+       height = getWrappedHeight();
+       if (headless)
+       {
+         // need to obtain default alignment width and then add in any
+         // additional allowance for id margin
+         // this duplicates the calculation in getWrappedHeight but adjusts for
+         // offscreen idWith
+         width = alignFrame.getWidth() - vscroll.getPreferredSize().width
+                 - alignFrame.getInsets().left
+                 - alignFrame.getInsets().right - getVisibleIdWidth()
+                 + getVisibleIdWidth(false);
+       }
+       else
+       {
+         width = getSeqPanel().getWidth() + getVisibleIdWidth(false);
+       }
+     }
+     else if (av.getShowAnnotation())
+     {
+       height += getAnnotationPanel().adjustPanelHeight() + 3;
+     }
+     return new AlignmentDimension(width, height);
+   }
    /**
     * DOCUMENT ME!
     */
  
    int getWrappedHeight()
    {
-     int seqPanelWidth = seqPanel.seqCanvas.getWidth();
+     int seqPanelWidth = getSeqPanel().seqCanvas.getWidth();
  
      if (System.getProperty("java.awt.headless") != null
              && System.getProperty("java.awt.headless").equals("true"))
                - alignFrame.getInsets().left - alignFrame.getInsets().right;
      }
  
-     int chunkWidth = seqPanel.seqCanvas
+     int chunkWidth = getSeqPanel().seqCanvas
              .getWrappedCanvasWidth(seqPanelWidth);
  
      int hgap = av.charHeight;
      }
  
      int annotationHeight = 0;
-     if (av.showAnnotation)
+     if (av.isShowAnnotation())
      {
-       annotationHeight = annotationPanel.adjustPanelHeight();
+       annotationHeight = getAnnotationPanel().adjustPanelHeight();
      }
  
      int cHeight = av.getAlignment().getHeight() * av.charHeight + hgap
     */
    public void closePanel()
    {
-     PaintRefresher.RemoveComponent(seqPanel.seqCanvas);
-     PaintRefresher.RemoveComponent(idPanel.idCanvas);
+     PaintRefresher.RemoveComponent(getSeqPanel().seqCanvas);
+     PaintRefresher.RemoveComponent(getIdPanel().getIdCanvas());
      PaintRefresher.RemoveComponent(this);
      if (av != null)
      {
        jalview.structure.StructureSelectionManager ssm = av
                .getStructureSelectionManager();
-       ssm.removeStructureViewerListener(seqPanel, null);
-       ssm.removeSelectionListener(seqPanel);
+       ssm.removeStructureViewerListener(getSeqPanel(), null);
+       ssm.removeSelectionListener(getSeqPanel());
        av.setAlignment(null);
        av = null;
      }
      return av.getAlignment();
    }
  
 -  /**
 -   * get the name for this view
 -   * 
 -   * @return
 -   */
 +
 +  @Override
    public String getViewName()
    {
      return av.viewName;
  
    public void updateFeatureRenderer(FeatureRenderer fr)
    {
-     fr.transferSettings(seqPanel.seqCanvas.getFeatureRenderer());
+     fr.transferSettings(getSeqPanel().seqCanvas.getFeatureRenderer());
    }
  
    public void updateFeatureRendererFrom(FeatureRenderer fr)
    {
-     if (seqPanel.seqCanvas.getFeatureRenderer() != null)
+     if (getSeqPanel().seqCanvas.getFeatureRenderer() != null)
      {
-       seqPanel.seqCanvas.getFeatureRenderer().transferSettings(fr);
+       getSeqPanel().seqCanvas.getFeatureRenderer().transferSettings(fr);
      }
    }
+   public ScalePanel getScalePanel()
+   {
+     return scalePanel;
+   }
+   public void setScalePanel(ScalePanel scalePanel)
+   {
+     this.scalePanel = scalePanel;
+   }
+   public SeqPanel getSeqPanel()
+   {
+     return seqPanel;
+   }
+   public void setSeqPanel(SeqPanel seqPanel)
+   {
+     this.seqPanel = seqPanel;
+   }
+   public AnnotationPanel getAnnotationPanel()
+   {
+     return annotationPanel;
+   }
+   public void setAnnotationPanel(AnnotationPanel annotationPanel)
+   {
+     this.annotationPanel = annotationPanel;
+   }
+   public AnnotationLabels getAlabels()
+   {
+     return alabels;
+   }
+   public void setAlabels(AnnotationLabels alabels)
+   {
+     this.alabels = alabels;
+   }
+   public IdPanel getIdPanel()
+   {
+     return idPanel;
+   }
+   public void setIdPanel(IdPanel idPanel)
+   {
+     this.idPanel = idPanel;
+   }
  }
   */
  package jalview.gui;
  
--import java.util.*;
++import jalview.datamodel.AlignmentAnnotation;
++import jalview.datamodel.SequenceGroup;
++import jalview.io.AnnotationFile;
++import jalview.io.FeaturesFile;
++import jalview.io.JalviewFileChooser;
++import jalview.io.JalviewFileView;
++import jalview.util.MessageManager;
++
++import java.awt.BorderLayout;
++import java.awt.Color;
++import java.awt.FlowLayout;
++import java.awt.event.ActionEvent;
++import java.awt.event.ActionListener;
++import java.util.Enumeration;
++import java.util.Hashtable;
  import java.util.List;
  
--import java.awt.*;
--import java.awt.event.*;
--import javax.swing.*;
--
--import jalview.datamodel.*;
--import jalview.io.*;
--import jalview.util.MessageManager;
++import javax.swing.BorderFactory;
++import javax.swing.ButtonGroup;
++import javax.swing.JButton;
++import javax.swing.JInternalFrame;
++import javax.swing.JLabel;
++import javax.swing.JLayeredPane;
++import javax.swing.JPanel;
++import javax.swing.JRadioButton;
++import javax.swing.SwingConstants;
  
  /**
   * 
@@@ -210,12 -210,12 +226,13 @@@ public class AnnotationExporter extend
    private Hashtable getDisplayedFeatureCols()
    {
      Hashtable fcols = new Hashtable();
 -    if (ap.av.featuresDisplayed == null)
 +    if (ap.av.getFeaturesDisplayed() == null)
      {
        return fcols;
      }
 -    Enumeration en = ap.av.featuresDisplayed.keys();
++
 +    Enumeration en = ap.av.getFeaturesDisplayed().keys();
-     FeatureRenderer fr = ap.seqPanel.seqCanvas.getFeatureRenderer(); // consider
+     FeatureRenderer fr = ap.getSeqPanel().seqCanvas.getFeatureRenderer(); // consider
                                                                       // higher
                                                                       // level
                                                                       // method ?
@@@ -244,9 -244,9 +244,9 @@@ public class ChimeraViewFrame extends G
          // TODO : Fix multiple seq to one chain issue here.
          ap.getStructureSelectionManager().setMapping(seq, chains,
                  alreadyMapped, AppletFormatAdapter.FILE);
-         if (ap.seqPanel.seqCanvas.fr != null)
+         if (ap.getSeqPanel().seqCanvas.fr != null)
          {
-           ap.seqPanel.seqCanvas.fr.featuresAdded();
+           ap.getSeqPanel().seqCanvas.fr.featuresAdded();
            ap.paintAlignment(true);
          }
  
      {
        if (progressBar != null)
        {
 -        progressBar.setProgressBar(
 -                MessageManager.getString("label.state_completed"), hdl);
 +        progressBar
 +                .setProgressBar(
 +                        pdbid
 +                                + " "
 +                                + MessageManager
 +                                        .getString("label.state_completed"),
 +                        hdl);
        }
      }
      /*
@@@ -84,10 -84,10 +84,10 @@@ public class FeatureRenderer implement
    {
      this.ap = ap;
      this.av = ap.av;
-     if (ap != null && ap.seqPanel != null && ap.seqPanel.seqCanvas != null
-             && ap.seqPanel.seqCanvas.fr != null)
+     if (ap != null && ap.getSeqPanel() != null && ap.getSeqPanel().seqCanvas != null
+             && ap.getSeqPanel().seqCanvas.fr != null)
      {
-       transferSettings(ap.seqPanel.seqCanvas.fr);
+       transferSettings(ap.getSeqPanel().seqCanvas.fr);
      }
    }
  
        // copy over the displayed feature settings
        if (fr.av != null)
        {
 -        if (fr.av.featuresDisplayed != null)
 +        if (fr.av.getFeaturesDisplayed() != null)
          {
            // update display settings
 -          if (av.featuresDisplayed == null)
 +          if (av.getFeaturesDisplayed() == null)
            {
 -            av.featuresDisplayed = new Hashtable(fr.av.featuresDisplayed);
 +            av.setFeaturesDisplayed(new Hashtable(fr.av.getFeaturesDisplayed()));
            }
            else
            {
 -            av.featuresDisplayed.clear();
 -            Enumeration en = fr.av.featuresDisplayed.keys();
 +            av.getFeaturesDisplayed().clear();
 +            Enumeration en = fr.av.getFeaturesDisplayed().keys();
              while (en.hasMoreElements())
              {
 -              av.featuresDisplayed.put(en.nextElement(), Boolean.TRUE);
 +              av.getFeaturesDisplayed().put(en.nextElement(), Boolean.TRUE);
              }
  
            }
        fm = g.getFontMetrics();
      }
  
 -    if (av.featuresDisplayed == null || renderOrder == null
 +    if (av.getFeaturesDisplayed() == null || renderOrder == null
              || newFeatureAdded)
      {
        findAllFeatures();
 -      if (av.featuresDisplayed.size() < 1)
 +      if (av.getFeaturesDisplayed().size() < 1)
        {
          return;
        }
      {
        type = renderOrder[renderIndex];
  
 -      if (type == null || !av.featuresDisplayed.containsKey(type))
 +      if (type == null || !av.getFeaturesDisplayed().containsKey(type))
        {
          continue;
        }
  
      findingFeatures = true;
  
 -    if (av.featuresDisplayed == null)
 +    if (av.getFeaturesDisplayed() == null)
      {
 -      av.featuresDisplayed = new Hashtable();
 +      av.setFeaturesDisplayed(new Hashtable());
      }
  
      allfeatures = new Vector();
        int index = 0;
        while (index < features.length)
        {
 -        if (!av.featuresDisplayed.containsKey(features[index].getType()))
 +        if (!av.getFeaturesDisplayed().containsKey(features[index].getType()))
          {
  
            if (featureGroups.containsKey(features[index].getType()))
              {
                // this is a new feature type on the alignment. Mark it for
                // display.
 -              av.featuresDisplayed.put(features[index].getType(),
 +              av.getFeaturesDisplayed().put(features[index].getType(),
                        new Integer(getColour(features[index].getType())
                                .getRGB()));
                setOrder(features[index].getType(), 0);
              highlight.addResult(sequences[0], features[index].getBegin(),
                      features[index].getEnd());
  
-             ap.seqPanel.seqCanvas.highlightSearchResults(highlight);
+             ap.getSeqPanel().seqCanvas.highlightSearchResults(highlight);
  
            }
            Object col = getFeatureStyle(name.getText());
          sf.description = lastDescriptionAdded;
  
          setColour(sf.type, fcol);
 -        av.featuresDisplayed.put(sf.type, getColour(sf.type));
 +        av.getFeaturesDisplayed().put(sf.type, getColour(sf.type));
  
          try
          {
            ffile.parseDescriptionHTML(features[i], false);
          }
  
 -        if (av.featuresDisplayed == null)
 +        if (av.getFeaturesDisplayed() == null)
          {
 -          av.featuresDisplayed = new Hashtable();
 +          av.setFeaturesDisplayed(new Hashtable());
          }
  
          if (lastFeatureGroupAdded != null)
            featureGroups.put(lastFeatureGroupAdded, new Boolean(true));
          }
          setColour(lastFeatureAdded, fcol);
 -        av.featuresDisplayed.put(lastFeatureAdded,
 +        av.getFeaturesDisplayed().put(lastFeatureAdded,
                  getColour(lastFeatureAdded));
  
          findAllFeatures(false);
    {
      if (visibleNew)
      {
 -      if (av.featuresDisplayed != null)
 +      if (av.getFeaturesDisplayed() != null)
        {
 -        av.featuresDisplayed.clear();
 +        av.getFeaturesDisplayed().clear();
        }
        else
        {
 -        av.featuresDisplayed = new Hashtable();
 +        av.setFeaturesDisplayed(new Hashtable());
        }
      }
      if (data == null)
          // interface object
          if (((Boolean) data[i][2]).booleanValue())
          {
 -          av.featuresDisplayed.put(type, new Integer(getColour(type)
 +          av.getFeaturesDisplayed().put(type, new Integer(getColour(type)
                    .getRGB()));
          }
  
@@@ -222,7 -222,7 +222,7 @@@ public class FeatureSettings extends JP
      dassourceBrowser = new DasSourceBrowser(this);
      dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
  
 -    if (af.getViewport().featuresDisplayed == null
 +    if (af.getViewport().getFeaturesDisplayed() == null
              || fr.renderOrder == null)
      {
        fr.findAllFeatures(true); // display everything!
        {
          fr.featureGroups.put(check.getText(),
                  new Boolean(check.isSelected()));
-         af.alignPanel.seqPanel.seqCanvas.repaint();
+         af.alignPanel.getSeqPanel().seqCanvas.repaint();
          if (af.alignPanel.overviewPanel != null)
          {
            af.alignPanel.overviewPanel.updateOverviewImage();
          data[dataIndex][0] = type;
          data[dataIndex][1] = fr.getFeatureStyle(type);
          data[dataIndex][2] = new Boolean(
 -                af.getViewport().featuresDisplayed.containsKey(type));
 +                af.getViewport().getFeaturesDisplayed().containsKey(type));
          dataIndex++;
          visibleChecks.removeElement(type);
        }
          System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
          for (int i = 0; i < typ.length; i++)
          {
 -          if (af.viewport.featuresDisplayed.get(typ[i]) == null)
 +          if (af.viewport.getFeaturesDisplayed().get(typ[i]) == null)
            {
              typ[i] = null;
            }
@@@ -498,7 -498,7 +498,7 @@@ public class Jalview2XM
      for (String dssids : dsses.keySet())
      {
        AlignFrame _af = dsses.get(dssids);
 -      String jfileName = MessageManager.formatMessage("label.dataset_for", new String[]{fileName,_af.getTitle()});
 +      String jfileName = fileName + " Dataset for " + _af.getTitle();
        if (!jfileName.endsWith(".xml"))
        {
          jfileName = jfileName + ".xml";
        view.setShowBoxes(av.getShowBoxes());
        view.setShowColourText(av.getColourText());
        view.setShowFullId(av.getShowJVSuffix());
-       view.setRightAlignIds(av.rightAlignIds);
+       view.setRightAlignIds(av.isRightAlignIds());
        view.setShowSequenceFeatures(av.showSequenceFeatures);
        view.setShowText(av.getShowText());
        view.setShowUnconserved(av.getShowUnconserved());
        view.setFollowHighlight(av.followHighlight);
        view.setFollowSelection(av.followSelection);
        view.setIgnoreGapsinConsensus(av.getIgnoreGapsConsensus());
 -      if (av.featuresDisplayed != null)
 +      if (av.getFeaturesDisplayed() != null)
        {
          jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
  
-         String[] renderOrder = ap.seqPanel.seqCanvas.getFeatureRenderer().renderOrder;
+         String[] renderOrder = ap.getSeqPanel().seqCanvas.getFeatureRenderer().renderOrder;
  
          Vector settingsAdded = new Vector();
          Object gstyle = null;
          {
            for (int ro = 0; ro < renderOrder.length; ro++)
            {
-             gstyle = ap.seqPanel.seqCanvas.getFeatureRenderer()
+             gstyle = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
                      .getFeatureStyle(renderOrder[ro]);
              Setting setting = new Setting();
              setting.setType(renderOrder[ro]);
              }
              else
              {
-               setting.setColour(ap.seqPanel.seqCanvas.getFeatureRenderer()
+               setting.setColour(ap.getSeqPanel().seqCanvas.getFeatureRenderer()
                        .getColour(renderOrder[ro]).getRGB());
              }
  
 -            setting.setDisplay(av.featuresDisplayed
 +            setting.setDisplay(av.getFeaturesDisplayed()
                      .containsKey(renderOrder[ro]));
-             float rorder = ap.seqPanel.seqCanvas.getFeatureRenderer()
+             float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
                      .getOrder(renderOrder[ro]);
              if (rorder > -1)
              {
          }
  
          // Make sure we save none displayed feature settings
-         Iterator en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureColours
+         Iterator en = ap.getSeqPanel().seqCanvas.getFeatureRenderer().featureColours
                  .keySet().iterator();
          while (en.hasNext())
          {
  
            Setting setting = new Setting();
            setting.setType(key);
-           setting.setColour(ap.seqPanel.seqCanvas.getFeatureRenderer()
+           setting.setColour(ap.getSeqPanel().seqCanvas.getFeatureRenderer()
                    .getColour(key).getRGB());
  
            setting.setDisplay(false);
-           float rorder = ap.seqPanel.seqCanvas.getFeatureRenderer()
+           float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
                    .getOrder(key);
            if (rorder > -1)
            {
            fs.addSetting(setting);
            settingsAdded.addElement(key);
          }
-         en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureGroups
+         en = ap.getSeqPanel().seqCanvas.getFeatureRenderer().featureGroups
                  .keySet().iterator();
          Vector groupsAdded = new Vector();
          while (en.hasNext())
            }
            Group g = new Group();
            g.setName(grp);
-           g.setDisplay(((Boolean) ap.seqPanel.seqCanvas
+           g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
                    .getFeatureRenderer().featureGroups.get(grp))
                    .booleanValue());
            fs.addGroup(g);
            }
  
            ae.setPosition(a);
 -          if (aa[i].annotations[a].secondaryStructure != ' '
 -                  && aa[i].annotations[a].secondaryStructure != '\0')
 +          if (aa[i].annotations[a].secondaryStructure > ' ')
            {
              ae.setSecondaryStructure(aa[i].annotations[a].secondaryStructure
                      + "");
      }
      else
      {
 -      recoverDatasetFor(vamsasSet, al);
 +      // recover dataset - passing on flag indicating if this a 'viewless'
 +      // sequence set (a.k.a. a stored dataset for the project)
 +      recoverDatasetFor(vamsasSet, al, object.getJalviewModelSequence()
 +              .getViewportCount() == 0);
      }
      // ///////////////////////////////
  
  
      af.viewport.setConservationSelected(view.getConservationSelected());
      af.viewport.setShowJVSuffix(view.getShowFullId());
-     af.viewport.rightAlignIds = view.getRightAlignIds();
+     af.viewport.setRightAlignIds(view.getRightAlignIds());
      af.viewport.setFont(new java.awt.Font(view.getFontName(), view
              .getFontStyle(), view.getFontSize()));
      af.alignPanel.fontChanged();
      // recover featre settings
      if (jms.getFeatureSettings() != null)
      {
 -      af.viewport.featuresDisplayed = new Hashtable();
 +      af.viewport.setFeaturesDisplayed(new Hashtable());
        String[] renderOrder = new String[jms.getFeatureSettings()
                .getSettingCount()];
        for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
              gc.setColourByLabel(setting.getColourByLabel());
            }
            // and put in the feature colour table.
-           af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
+           af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer().setColour(
                    setting.getType(), gc);
          }
          else
          {
-           af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
+           af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer().setColour(
                    setting.getType(),
                    new java.awt.Color(setting.getColour()));
          }
          renderOrder[fs] = setting.getType();
          if (setting.hasOrder())
          {
-           af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
+           af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer().setOrder(
                    setting.getType(), setting.getOrder());
          }
          else
          {
-           af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
+           af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer().setOrder(
                    setting.getType(),
                    fs / jms.getFeatureSettings().getSettingCount());
          }
          if (setting.getDisplay())
          {
 -          af.viewport.featuresDisplayed.put(setting.getType(), new Integer(
 +          af.viewport.getFeaturesDisplayed().put(setting.getType(), new Integer(
                    setting.getColour()));
          }
        }
-       af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().renderOrder = renderOrder;
+       af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer().renderOrder = renderOrder;
        Hashtable fgtable;
-       af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().featureGroups = fgtable = new Hashtable();
+       af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer().featureGroups = fgtable = new Hashtable();
        for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
        {
          Group grp = jms.getFeatureSettings().getGroup(gs);
      }
    }
  
 -  private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al)
 +  private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al,
 +          boolean ignoreUnrefed)
    {
      jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId());
      Vector dseqs = null;
      for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++)
      {
        Sequence vamsasSeq = vamsasSet.getSequence(i);
 -      ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs);
 +      ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed);
      }
      // create a new dataset
      if (ds == null)
     *          vector to add new dataset sequence to
     */
    private void ensureJalviewDatasetSequence(Sequence vamsasSeq,
 -          AlignmentI ds, Vector dseqs)
 +          AlignmentI ds, Vector dseqs, boolean ignoreUnrefed)
    {
      // JBP TODO: Check this is called for AlCodonFrames to support recovery of
      // xRef Codon Maps
      {
        dsq = sq.getDatasetSequence();
      }
 -
 +    if (sq == null && ignoreUnrefed)
 +    {
 +      return;
 +    }
      String sqid = vamsasSeq.getDsseqid();
      if (dsq == null)
      {
@@@ -415,25 -415,25 +415,25 @@@ public class Jalview2XML_V
  
      if (jms.getFeatureSettings() != null)
      {
 -      af.viewport.featuresDisplayed = new Hashtable();
 +      af.viewport.setFeaturesDisplayed(new Hashtable());
        String[] renderOrder = new String[jms.getFeatureSettings()
                .getSettingCount()];
        for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
        {
          Setting setting = jms.getFeatureSettings().getSetting(fs);
  
-         af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
+         af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer().setColour(
                  setting.getType(), new java.awt.Color(setting.getColour()));
  
          renderOrder[fs] = setting.getType();
  
          if (setting.getDisplay())
          {
 -          af.viewport.featuresDisplayed.put(setting.getType(), new Integer(
 +          af.viewport.getFeaturesDisplayed().put(setting.getType(), new Integer(
                    setting.getColour()));
          }
        }
-       af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().renderOrder = renderOrder;
+       af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer().renderOrder = renderOrder;
      }
  
      af.setMenusFromViewport(af.viewport);
@@@ -27,7 -27,6 +27,7 @@@ import jalview.commands.ChangeCaseComma
  import jalview.commands.EditCommand;
  import jalview.commands.EditCommand.Action;
  import jalview.datamodel.AlignmentAnnotation;
 +import jalview.datamodel.AlignmentI;
  import jalview.datamodel.Annotation;
  import jalview.datamodel.DBRefEntry;
  import jalview.datamodel.PDBEntry;
@@@ -1766,13 -1765,12 +1766,13 @@@ public class PopupMenu extends JPopupMe
  
    /**
     * Check for any annotations on the underlying dataset sequences (for the
 -   * current selection group) which are not on the alignment annotations for the
 -   * sequence. If any are found, enable the option to add them to the alignment.
 -   * The criteria for 'on the alignment' is finding an alignment annotation on
 -   * the sequence, that matches on calcId and label. A tooltip is also
 -   * constructed that displays the source (calcId) and type (label) of the
 -   * annotations that can be added.
 +   * current selection group) which are not 'on the alignment'.If any are found,
 +   * enable the option to add them to the alignment. The criteria for 'on the
 +   * alignment' is finding an alignment annotation on the alignment, matched on
 +   * calcId, label and sequenceRef.
 +   * 
 +   * A tooltip is also constructed that displays the source (calcId) and type
 +   * (label) of the annotations that can be added.
     * 
     * @param menuItem
     * @param forSequences
      /*
       * For each sequence selected in the alignment, make a list of any
       * annotations on the underlying dataset sequence which are not already on
 -     * the sequence in the alignment.
 +     * the alignment.
       * 
       * Build a map of { alignmentSequence, <List of annotations to add> }
       */
 +    AlignmentI al = this.ap.av.getAlignment();
      final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<SequenceI, List<AlignmentAnnotation>>();
      for (SequenceI seq : forSequences)
      {
        for (AlignmentAnnotation dsann : datasetAnnotations)
        {
          /*
 -         * If the sequence has no annotation that matches this one, then add
 -         * this one to the results list.
 +         * Find matching annotations on the alignment.
           */
 -        if (seq.getAlignmentAnnotations(dsann.getCalcId(), dsann.label)
 -                .isEmpty())
 +        final Iterable<AlignmentAnnotation> matchedAlignmentAnnotations = al
 +                .findAnnotations(seq, dsann.getCalcId(),
 +                        dsann.label);
 +        if (!matchedAlignmentAnnotations.iterator().hasNext())
          {
            result.add(dsann);
            tipEntries.put(dsann.getCalcId(), dsann.label);
          }
          copyAnn.restrict(startRes, endRes);
  
 -        // add to the sequence (sets copyAnn.datasetSequence)
 -        seq.addAlignmentAnnotation(copyAnn);
 +        /*
 +         * Add to the sequence (sets copyAnn.datasetSequence), unless the
 +         * original annotation is already on the sequence.
 +         */
 +        if (!seq.hasAnnotation(ann))
 +        {
 +          seq.addAlignmentAnnotation(copyAnn);
 +        }
          // adjust for gaps
          copyAnn.adjustForAlignment();
          // add to the alignment and set visible
                        true,
                        true,
                        false,
-                       (ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr.minmax
+                       (ap.getSeqPanel().seqCanvas.fr != null) ? ap.getSeqPanel().seqCanvas.fr.minmax
                                : null);
        contents.append("</p>");
      }
      System.arraycopy(features, 0, tfeatures, 0, rsize);
      features = tfeatures;
      seqs = rseqs;
-     if (ap.seqPanel.seqCanvas.getFeatureRenderer().amendFeatures(seqs,
+     if (ap.getSeqPanel().seqCanvas.getFeatureRenderer().amendFeatures(seqs,
              features, true, ap))
      {
        ap.alignFrame.setShowSeqFeatures(true);
@@@ -251,9 -251,8 +251,9 @@@ public class SeqPanel extends JPanel im
      {
        for (int i = 0; i < features.length; i++)
        {
 -        if (av.featuresDisplayed == null
 -                || !av.featuresDisplayed.containsKey(features[i].getType()))
 +        if (av.getFeaturesDisplayed() == null
 +                || !av.getFeaturesDisplayed().containsKey(
 +                        features[i].getType()))
          {
            continue;
          }
                sequence.getDatasetSequence(),
                rpos = sequence.findPosition(res));
        seqARep.appendFeatures(tooltipText, rpos, features,
-               this.ap.seqPanel.seqCanvas.fr.minmax);
+               this.ap.getSeqPanel().seqCanvas.fr.minmax);
      }
      if (tooltipText.length() == 6) // <html></html>
      {