JAL-1355 (basic i18n support)
[jalview.git] / src / jalview / gui / AlignFrame.java
index 62fd29d..4c7ae80 100644 (file)
-/*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
- * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
- * 
- * This file is part of Jalview.
- * 
- * Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License 
- * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
- *  
- * Jalview is distributed in the hope that it will be useful, but 
- * WITHOUT ANY WARRANTY; without even the implied warranty 
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
- * PURPOSE.  See the GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
- */
-package jalview.gui;
-
-import jalview.analysis.AAFrequency;
-import jalview.analysis.AlignmentSorter;
-import jalview.analysis.Conservation;
-import jalview.analysis.CrossRef;
-import jalview.analysis.NJTree;
-import jalview.analysis.ParseProperties;
-import jalview.analysis.SequenceIdMatcher;
-import jalview.api.AlignViewControllerI;
-import jalview.bin.Cache;
-import jalview.commands.CommandI;
-import jalview.commands.EditCommand;
-import jalview.commands.OrderCommand;
-import jalview.commands.RemoveGapColCommand;
-import jalview.commands.RemoveGapsCommand;
-import jalview.commands.SlideSequencesCommand;
-import jalview.commands.TrimRegionCommand;
-import jalview.datamodel.AlignedCodonFrame;
-import jalview.datamodel.Alignment;
-import jalview.datamodel.AlignmentAnnotation;
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.AlignmentOrder;
-import jalview.datamodel.AlignmentView;
-import jalview.datamodel.ColumnSelection;
-import jalview.datamodel.PDBEntry;
-import jalview.datamodel.SeqCigar;
-import jalview.datamodel.Sequence;
-import jalview.datamodel.SequenceGroup;
-import jalview.datamodel.SequenceI;
-import jalview.io.AlignmentProperties;
-import jalview.io.AnnotationFile;
-import jalview.io.FeaturesFile;
-import jalview.io.FileLoader;
-import jalview.io.FormatAdapter;
-import jalview.io.HTMLOutput;
-import jalview.io.IdentifyFile;
-import jalview.io.JalviewFileChooser;
-import jalview.io.JalviewFileView;
-import jalview.io.JnetAnnotationMaker;
-import jalview.io.NewickFile;
-import jalview.io.TCoffeeScoreFile;
-import jalview.jbgui.GAlignFrame;
-import jalview.schemes.Blosum62ColourScheme;
-import jalview.schemes.BuriedColourScheme;
-import jalview.schemes.ClustalxColourScheme;
-import jalview.schemes.ColourSchemeI;
-import jalview.schemes.ColourSchemeProperty;
-import jalview.schemes.HelixColourScheme;
-import jalview.schemes.HydrophobicColourScheme;
-import jalview.schemes.NucleotideColourScheme;
-import jalview.schemes.PIDColourScheme;
-import jalview.schemes.PurinePyrimidineColourScheme;
-import jalview.schemes.RNAHelicesColourChooser;
-import jalview.schemes.ResidueProperties;
-import jalview.schemes.StrandColourScheme;
-import jalview.schemes.TCoffeeColourScheme;
-import jalview.schemes.TaylorColourScheme;
-import jalview.schemes.TurnColourScheme;
-import jalview.schemes.UserColourScheme;
-import jalview.schemes.ZappoColourScheme;
-import jalview.util.MessageManager;
-import jalview.ws.jws1.Discoverer;
-import jalview.ws.jws2.Jws2Discoverer;
-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.GridLayout;
-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.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.Enumeration;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Vector;
-
-import javax.swing.JButton;
-import javax.swing.JEditorPane;
-import javax.swing.JInternalFrame;
-import javax.swing.JLabel;
-import javax.swing.JLayeredPane;
-import javax.swing.JMenu;
-import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JProgressBar;
-import javax.swing.JRadioButtonMenuItem;
-import javax.swing.JScrollPane;
-import javax.swing.SwingUtilities;
-
-/**
- * DOCUMENT ME!
- * 
- * @author $author$
- * @version $Revision$
- */
-public class AlignFrame extends GAlignFrame implements DropTargetListener,
-        IProgressIndicator
-{
-
-  /** DOCUMENT ME!! */
-  public static final int DEFAULT_WIDTH = 700;
-
-  /** DOCUMENT ME!! */
-  public static final int DEFAULT_HEIGHT = 500;
-
-  public AlignmentPanel alignPanel;
-
-  AlignViewport viewport;
-  public AlignViewControllerI avc;
-
-  Vector alignPanels = new Vector();
-
-  /**
-   * Last format used to load or save alignments in this window
-   */
-  String currentFileFormat = null;
-
-  /**
-   * Current filename for this alignment
-   */
-  String fileName = null;
-
-  /**
-   * Creates a new AlignFrame object with specific width and height.
-   * 
-   * @param al
-   * @param width
-   * @param height
-   */
-  public AlignFrame(AlignmentI al, int width, int height)
-  {
-    this(al, null, width, height);
-  }
-
-  /**
-   * Creates a new AlignFrame object with specific width, height and
-   * sequenceSetId
-   * 
-   * @param al
-   * @param width
-   * @param height
-   * @param sequenceSetId
-   */
-  public AlignFrame(AlignmentI al, int width, int height,
-          String sequenceSetId)
-  {
-    this(al, null, width, height, sequenceSetId);
-  }
-
-  /**
-   * Creates a new AlignFrame object with specific width, height and
-   * sequenceSetId
-   * 
-   * @param al
-   * @param width
-   * @param height
-   * @param sequenceSetId
-   * @param viewId
-   */
-  public AlignFrame(AlignmentI al, int width, int height,
-          String sequenceSetId, String viewId)
-  {
-    this(al, null, width, height, sequenceSetId, viewId);
-  }
-
-  /**
-   * new alignment window with hidden columns
-   * 
-   * @param al
-   *          AlignmentI
-   * @param hiddenColumns
-   *          ColumnSelection or null
-   * @param width
-   *          Width of alignment frame
-   * @param height
-   *          height of frame.
-   */
-  public AlignFrame(AlignmentI al, ColumnSelection hiddenColumns,
-          int width, int height)
-  {
-    this(al, hiddenColumns, width, height, null);
-  }
-
-  /**
-   * Create alignment frame for al with hiddenColumns, a specific width and
-   * height, and specific sequenceId
-   * 
-   * @param al
-   * @param hiddenColumns
-   * @param width
-   * @param height
-   * @param sequenceSetId
-   *          (may be null)
-   */
-  public AlignFrame(AlignmentI al, ColumnSelection hiddenColumns,
-          int width, int height, String sequenceSetId)
-  {
-    this(al, hiddenColumns, width, height, sequenceSetId, null);
-  }
-
-  /**
-   * Create alignment frame for al with hiddenColumns, a specific width and
-   * height, and specific sequenceId
-   * 
-   * @param al
-   * @param hiddenColumns
-   * @param width
-   * @param height
-   * @param sequenceSetId
-   *          (may be null)
-   * @param viewId
-   *          (may be null)
-   */
-  public AlignFrame(AlignmentI al, ColumnSelection hiddenColumns,
-          int width, int height, String sequenceSetId, String viewId)
-  {
-    setSize(width, height);
-    viewport = new AlignViewport(al, hiddenColumns, sequenceSetId, viewId);
-
-    alignPanel = new AlignmentPanel(this, viewport);
-
-    if (al.getDataset() == null)
-    {
-      al.setDataset(null);
-    }
-
-    addAlignmentPanel(alignPanel, true);
-    init();
-  }
-
-  /**
-   * Make a new AlignFrame from exisiting alignmentPanels
-   * 
-   * @param ap
-   *          AlignmentPanel
-   * @param av
-   *          AlignViewport
-   */
-  public AlignFrame(AlignmentPanel ap)
-  {
-    viewport = ap.av;
-    alignPanel = ap;
-    addAlignmentPanel(ap, false);
-    init();
-  }
-
-  /**
-   * initalise the alignframe from the underlying viewport data and the
-   * configurations
-   */
-  void init()
-  {
-    avc = new jalview.controller.AlignViewController(viewport, alignPanel);
-    if (viewport.getAlignmentConservationAnnotation() == null)
-    {
-      BLOSUM62Colour.setEnabled(false);
-      conservationMenuItem.setEnabled(false);
-      modifyConservation.setEnabled(false);
-      // PIDColour.setEnabled(false);
-      // abovePIDThreshold.setEnabled(false);
-      // modifyPID.setEnabled(false);
-    }
-
-    String sortby = jalview.bin.Cache.getDefault("SORT_ALIGNMENT",
-            "No sort");
-
-    if (sortby.equals("Id"))
-    {
-      sortIDMenuItem_actionPerformed(null);
-    }
-    else if (sortby.equals("Pairwise Identity"))
-    {
-      sortPairwiseMenuItem_actionPerformed(null);
-    }
-
-    if (Desktop.desktop != null)
-    {
-      this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
-      addServiceListeners();
-      setGUINucleotide(viewport.getAlignment().isNucleotide());
-    }
-
-    setMenusFromViewport(viewport);
-    buildSortByAnnotationScoresMenu();
-    if (viewport.wrapAlignment)
-    {
-      wrapMenuItem_actionPerformed(null);
-    }
-
-    if (jalview.bin.Cache.getDefault("SHOW_OVERVIEW", false))
-    {
-      this.overviewMenuItem_actionPerformed(null);
-    }
-
-    addKeyListener();
-    
-  }
-
-  /**
-   * Change the filename and format for the alignment, and enable the 'reload'
-   * button functionality.
-   * 
-   * @param file
-   *          valid filename
-   * @param format
-   *          format of file
-   */
-  public void setFileName(String file, String format)
-  {
-    fileName = file;
-    currentFileFormat = format;
-    reload.setEnabled(true);
-  }
-
-  void addKeyListener()
-  {
-    addKeyListener(new KeyAdapter()
-    {
-      @Override
-      public void keyPressed(KeyEvent evt)
-      {
-        if (viewport.cursorMode
-                && ((evt.getKeyCode() >= KeyEvent.VK_0 && evt.getKeyCode() <= KeyEvent.VK_9) || (evt
-                        .getKeyCode() >= KeyEvent.VK_NUMPAD0 && evt
-                        .getKeyCode() <= KeyEvent.VK_NUMPAD9))
-                && Character.isDigit(evt.getKeyChar()))
-          alignPanel.seqPanel.numberPressed(evt.getKeyChar());
-
-        switch (evt.getKeyCode())
-        {
-
-        case 27: // escape key
-          deselectAllSequenceMenuItem_actionPerformed(null);
-
-          break;
-
-        case KeyEvent.VK_DOWN:
-          if (evt.isAltDown() || !viewport.cursorMode)
-            moveSelectedSequences(false);
-          if (viewport.cursorMode)
-            alignPanel.seqPanel.moveCursor(0, 1);
-          break;
-
-        case KeyEvent.VK_UP:
-          if (evt.isAltDown() || !viewport.cursorMode)
-            moveSelectedSequences(true);
-          if (viewport.cursorMode)
-            alignPanel.seqPanel.moveCursor(0, -1);
-
-          break;
-
-        case KeyEvent.VK_LEFT:
-          if (evt.isAltDown() || !viewport.cursorMode)
-            slideSequences(false, alignPanel.seqPanel.getKeyboardNo1());
-          else
-            alignPanel.seqPanel.moveCursor(-1, 0);
-
-          break;
-
-        case KeyEvent.VK_RIGHT:
-          if (evt.isAltDown() || !viewport.cursorMode)
-            slideSequences(true, alignPanel.seqPanel.getKeyboardNo1());
-          else
-            alignPanel.seqPanel.moveCursor(1, 0);
-          break;
-
-        case KeyEvent.VK_SPACE:
-          if (viewport.cursorMode)
-          {
-            alignPanel.seqPanel.insertGapAtCursor(evt.isControlDown()
-                    || evt.isShiftDown() || evt.isAltDown());
-          }
-          break;
-
-        // case KeyEvent.VK_A:
-        // if (viewport.cursorMode)
-        // {
-        // alignPanel.seqPanel.insertNucAtCursor(false,"A");
-        // //System.out.println("A");
-        // }
-        // break;
-        /*
-         * case KeyEvent.VK_CLOSE_BRACKET: if (viewport.cursorMode) {
-         * System.out.println("closing bracket"); } break;
-         */
-        case KeyEvent.VK_DELETE:
-        case KeyEvent.VK_BACK_SPACE:
-          if (!viewport.cursorMode)
-          {
-            cut_actionPerformed(null);
-          }
-          else
-          {
-            alignPanel.seqPanel.deleteGapAtCursor(evt.isControlDown()
-                    || evt.isShiftDown() || evt.isAltDown());
-          }
-
-          break;
-
-        case KeyEvent.VK_S:
-          if (viewport.cursorMode)
-          {
-            alignPanel.seqPanel.setCursorRow();
-          }
-          break;
-        case KeyEvent.VK_C:
-          if (viewport.cursorMode && !evt.isControlDown())
-          {
-            alignPanel.seqPanel.setCursorColumn();
-          }
-          break;
-        case KeyEvent.VK_P:
-          if (viewport.cursorMode)
-          {
-            alignPanel.seqPanel.setCursorPosition();
-          }
-          break;
-
-        case KeyEvent.VK_ENTER:
-        case KeyEvent.VK_COMMA:
-          if (viewport.cursorMode)
-          {
-            alignPanel.seqPanel.setCursorRowAndColumn();
-          }
-          break;
-
-        case KeyEvent.VK_Q:
-          if (viewport.cursorMode)
-          {
-            alignPanel.seqPanel.setSelectionAreaAtCursor(true);
-          }
-          break;
-        case KeyEvent.VK_M:
-          if (viewport.cursorMode)
-          {
-            alignPanel.seqPanel.setSelectionAreaAtCursor(false);
-          }
-          break;
-
-        case KeyEvent.VK_F2:
-          viewport.cursorMode = !viewport.cursorMode;
-          statusBar.setText(MessageManager.formatMessage("label.keyboard_editing_mode", new String[]{(viewport.cursorMode ? "on" : "off")}));
-          if (viewport.cursorMode)
-          {
-            alignPanel.seqPanel.seqCanvas.cursorX = viewport.startRes;
-            alignPanel.seqPanel.seqCanvas.cursorY = viewport.startSeq;
-          }
-          alignPanel.seqPanel.seqCanvas.repaint();
-          break;
-
-        case KeyEvent.VK_F1:
-          try
-          {
-            ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
-            java.net.URL url = javax.help.HelpSet.findHelpSet(cl,
-                    "help/help");
-            javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
-
-            javax.help.HelpBroker hb = hs.createHelpBroker();
-            hb.setCurrentID("home");
-            hb.setDisplayed(true);
-          } catch (Exception ex)
-          {
-            ex.printStackTrace();
-          }
-          break;
-        case KeyEvent.VK_H:
-        {
-          boolean toggleSeqs = !evt.isControlDown();
-          boolean toggleCols = !evt.isShiftDown();
-          toggleHiddenRegions(toggleSeqs, toggleCols);
-          break;
-        }
-        case KeyEvent.VK_PAGE_UP:
-          if (viewport.wrapAlignment)
-          {
-            alignPanel.scrollUp(true);
-          }
-          else
-          {
-            alignPanel.setScrollValues(viewport.startRes, viewport.startSeq
-                    - viewport.endSeq + viewport.startSeq);
-          }
-          break;
-        case KeyEvent.VK_PAGE_DOWN:
-          if (viewport.wrapAlignment)
-          {
-            alignPanel.scrollUp(false);
-          }
-          else
-          {
-            alignPanel.setScrollValues(viewport.startRes, viewport.startSeq
-                    + viewport.endSeq - viewport.startSeq);
-          }
-          break;
-        }
-      }
-
-      @Override
-      public void keyReleased(KeyEvent evt)
-      {
-        switch (evt.getKeyCode())
-        {
-        case KeyEvent.VK_LEFT:
-          if (evt.isAltDown() || !viewport.cursorMode)
-            viewport.firePropertyChange("alignment", null, viewport
-                    .getAlignment().getSequences());
-          break;
-
-        case KeyEvent.VK_RIGHT:
-          if (evt.isAltDown() || !viewport.cursorMode)
-            viewport.firePropertyChange("alignment", null, viewport
-                    .getAlignment().getSequences());
-          break;
-        }
-      }
-    });
-  }
-
-  public void addAlignmentPanel(final AlignmentPanel ap, boolean newPanel)
-  {
-    ap.alignFrame = this;
-    avc = new jalview.controller.AlignViewController(viewport, alignPanel);
-
-    alignPanels.addElement(ap);
-
-    PaintRefresher.Register(ap, ap.av.getSequenceSetId());
-
-    int aSize = alignPanels.size();
-
-    tabbedPane.setVisible(aSize > 1 || ap.av.viewName != null);
-
-    if (aSize == 1 && ap.av.viewName == null)
-    {
-      this.getContentPane().add(ap, BorderLayout.CENTER);
-    }
-    else
-    {
-      if (aSize == 2)
-      {
-        setInitialTabVisible();
-      }
-
-      expandViews.setEnabled(true);
-      gatherViews.setEnabled(true);
-      tabbedPane.addTab(ap.av.viewName, ap);
-
-      ap.setVisible(false);
-    }
-
-    if (newPanel)
-    {
-      if (ap.av.isPadGaps())
-      {
-        ap.av.getAlignment().padGaps();
-      }
-      ap.av.updateConservation(ap);
-      ap.av.updateConsensus(ap);
-      ap.av.updateStrucConsensus(ap);
-    }
-  }
-
-  public void setInitialTabVisible()
-  {
-    expandViews.setEnabled(true);
-    gatherViews.setEnabled(true);
-    tabbedPane.setVisible(true);
-    AlignmentPanel first = (AlignmentPanel) alignPanels.firstElement();
-    tabbedPane.addTab(first.av.viewName, first);
-    this.getContentPane().add(tabbedPane, BorderLayout.CENTER);
-  }
-
-  public AlignViewport getViewport()
-  {
-    return viewport;
-  }
-
-  /* Set up intrinsic listeners for dynamically generated GUI bits. */
-  private void addServiceListeners()
-  {
-    final java.beans.PropertyChangeListener thisListener;
-    Desktop.instance.addJalviewPropertyChangeListener("services",
-            thisListener = new java.beans.PropertyChangeListener()
-            {
-              @Override
-              public void propertyChange(PropertyChangeEvent evt)
-              {
-                // // System.out.println("Discoverer property change.");
-                // if (evt.getPropertyName().equals("services"))
-                {
-                  SwingUtilities.invokeLater(new Runnable()
-                  {
-
-                    @Override
-                    public void run()
-                    {
-                      System.err
-                              .println("Rebuild WS Menu for service change");
-                      BuildWebServiceMenu();
-                    }
-
-                  });
-                }
-              }
-            });
-    addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
-    {
-      @Override
-      public void internalFrameClosed(
-              javax.swing.event.InternalFrameEvent evt)
-      {
-        System.out.println("deregistering discoverer listener");
-        Desktop.instance.removeJalviewPropertyChangeListener("services",
-                thisListener);
-        closeMenuItem_actionPerformed(true);
-      };
-    });
-    // Finally, build the menu once to get current service state
-    new Thread(new Runnable()
-    {
-      @Override
-      public void run()
-      {
-        BuildWebServiceMenu();
-      }
-    }).start();
-  }
-
-  public void setGUINucleotide(boolean nucleotide)
-  {
-    showTranslation.setVisible(nucleotide);
-    conservationMenuItem.setEnabled(!nucleotide);
-    modifyConservation.setEnabled(!nucleotide);
-    showGroupConservation.setEnabled(!nucleotide);
-    rnahelicesColour.setEnabled(nucleotide);
-    purinePyrimidineColour.setEnabled(nucleotide);
-    // Remember AlignFrame always starts as protein
-    // if (!nucleotide)
-    // {
-    // showTr
-    // calculateMenu.remove(calculateMenu.getItemCount() - 2);
-    // }
-  }
-
-  /**
-   * set up menus for the currently viewport. This may be called after any
-   * operation that affects the data in the current view (selection changed,
-   * etc) to update the menus to reflect the new state.
-   */
-  public void setMenusForViewport()
-  {
-    setMenusFromViewport(viewport);
-  }
-
-  /**
-   * Need to call this method when tabs are selected for multiple views, or when
-   * loading from Jalview2XML.java
-   * 
-   * @param av
-   *          AlignViewport
-   */
-  void setMenusFromViewport(AlignViewport av)
-  {
-    padGapsMenuitem.setSelected(av.isPadGaps());
-    colourTextMenuItem.setSelected(av.showColourText);
-    abovePIDThreshold.setSelected(av.getAbovePIDThreshold());
-    conservationMenuItem.setSelected(av.getConservationSelected());
-    seqLimits.setSelected(av.getShowJVSuffix());
-    idRightAlign.setSelected(av.rightAlignIds);
-    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);
-    viewBoxesMenuItem.setSelected(av.showBoxes);
-    viewTextMenuItem.setSelected(av.showText);
-    showNonconservedMenuItem.setSelected(av.getShowUnconserved());
-    showGroupConsensus.setSelected(av.isShowGroupConsensus());
-    showGroupConservation.setSelected(av.isShowGroupConservation());
-    showConsensusHistogram.setSelected(av.isShowConsensusHistogram());
-    showSequenceLogo.setSelected(av.isShowSequenceLogo());
-    normaliseSequenceLogo.setSelected(av.isNormaliseSequenceLogo());
-
-    setColourSelected(ColourSchemeProperty.getColourName(av
-            .getGlobalColourScheme()));
-
-    showSeqFeatures.setSelected(av.showSequenceFeatures);
-    hiddenMarkers.setState(av.showHiddenMarkers);
-    applyToAllGroups.setState(av.getColourAppliesToAllGroups());
-    showNpFeatsMenuitem.setSelected(av.isShowNpFeats());
-    showDbRefsMenuitem.setSelected(av.isShowDbRefs());
-    autoCalculate.setSelected(av.autoCalculateConsensus);
-    sortByTree.setSelected(av.sortByTree);
-    listenToViewSelections.setSelected(av.followSelection);
-    rnahelicesColour.setEnabled(av.getAlignment().hasRNAStructure());
-    rnahelicesColour
-            .setSelected(av.getGlobalColourScheme() instanceof jalview.schemes.RNAHelicesColour);
-    setShowProductsEnabled();
-    updateEditMenuBar();
-  }
-
-  // methods for implementing IProgressIndicator
-  // need to refactor to a reusable stub class
-  Hashtable progressBars, progressBarHandlers;
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
-   */
-  @Override
-  public void setProgressBar(String message, long id)
-  {
-    if (progressBars == null)
-    {
-      progressBars = new Hashtable();
-      progressBarHandlers = new Hashtable();
-    }
-
-    JPanel progressPanel;
-    Long lId = new Long(id);
-    GridLayout layout = (GridLayout) statusPanel.getLayout();
-    if (progressBars.get(lId) != null)
-    {
-      progressPanel = (JPanel) progressBars.get(new Long(id));
-      statusPanel.remove(progressPanel);
-      progressBars.remove(lId);
-      progressPanel = null;
-      if (message != null)
-      {
-        statusBar.setText(message);
-      }
-      if (progressBarHandlers.contains(lId))
-      {
-        progressBarHandlers.remove(lId);
-      }
-      layout.setRows(layout.getRows() - 1);
-    }
-    else
-    {
-      progressPanel = new JPanel(new BorderLayout(10, 5));
-
-      JProgressBar progressBar = new JProgressBar();
-      progressBar.setIndeterminate(true);
-
-      progressPanel.add(new JLabel(message), BorderLayout.WEST);
-      progressPanel.add(progressBar, BorderLayout.CENTER);
-
-      layout.setRows(layout.getRows() + 1);
-      statusPanel.add(progressPanel);
-
-      progressBars.put(lId, progressPanel);
-    }
-    // update GUI
-    // setMenusForViewport();
-    validate();
-  }
-
-  @Override
-  public void registerHandler(final long id,
-          final IProgressIndicatorHandler handler)
-  {
-    if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
-    {
-      throw new Error(
-              "call setProgressBar before registering the progress bar's handler.");
-    }
-    progressBarHandlers.put(new Long(id), handler);
-    final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
-    if (handler.canCancel())
-    {
-      JButton cancel = new JButton(MessageManager.getString("action.cancel"));
-      final IProgressIndicator us = this;
-      cancel.addActionListener(new ActionListener()
-      {
-
-        @Override
-        public void actionPerformed(ActionEvent e)
-        {
-          handler.cancelActivity(id);
-          us.setProgressBar(
-                  "Cancelled "
-                          + ((JLabel) progressPanel.getComponent(0))
-                                  .getText(), id);
-        }
-      });
-      progressPanel.add(cancel, BorderLayout.EAST);
-    }
-  }
-
-  /**
-   * 
-   * @return true if any progress bars are still active
-   */
-  @Override
-  public boolean operationInProgress()
-  {
-    if (progressBars != null && progressBars.size() > 0)
-    {
-      return true;
-    }
-    return false;
-  }
-
-  /*
-   * Added so Castor Mapping file can obtain Jalview Version
-   */
-  public String getVersion()
-  {
-    return jalview.bin.Cache.getProperty("VERSION");
-  }
-
-  public FeatureRenderer getFeatureRenderer()
-  {
-    return alignPanel.seqPanel.seqCanvas.getFeatureRenderer();
-  }
-
-  @Override
-  public void fetchSequence_actionPerformed(ActionEvent e)
-  {
-    new SequenceFetcher(this);
-  }
-
-  @Override
-  public void addFromFile_actionPerformed(ActionEvent e)
-  {
-    Desktop.instance.inputLocalFileMenuItem_actionPerformed(viewport);
-  }
-
-  @Override
-  public void reload_actionPerformed(ActionEvent e)
-  {
-    if (fileName != null)
-    {
-      // TODO: JAL-1108 - ensure all associated frames are closed regardless of
-      // originating file's format
-      // TODO: work out how to recover feature settings for correct view(s) when
-      // file is reloaded.
-      if (currentFileFormat.equals("Jalview"))
-      {
-        JInternalFrame[] frames = Desktop.desktop.getAllFrames();
-        for (int i = 0; i < frames.length; i++)
-        {
-          if (frames[i] instanceof AlignFrame && frames[i] != this
-                  && ((AlignFrame) frames[i]).fileName != null
-                  && ((AlignFrame) frames[i]).fileName.equals(fileName))
-          {
-            try
-            {
-              frames[i].setSelected(true);
-              Desktop.instance.closeAssociatedWindows();
-            } catch (java.beans.PropertyVetoException ex)
-            {
-            }
-          }
-
-        }
-        Desktop.instance.closeAssociatedWindows();
-
-        FileLoader loader = new FileLoader();
-        String protocol = fileName.startsWith("http:") ? "URL" : "File";
-        loader.LoadFile(viewport, fileName, protocol, currentFileFormat);
-      }
-      else
-      {
-        Rectangle bounds = this.getBounds();
-
-        FileLoader loader = new FileLoader();
-        String protocol = fileName.startsWith("http:") ? "URL" : "File";
-        AlignFrame newframe = loader.LoadFileWaitTillLoaded(fileName,
-                protocol, currentFileFormat);
-
-        newframe.setBounds(bounds);
-        if (featureSettings != null && featureSettings.isShowing())
-        {
-          final Rectangle fspos = featureSettings.frame.getBounds();
-          // TODO: need a 'show feature settings' function that takes bounds -
-          // need to refactor Desktop.addFrame
-          newframe.featureSettings_actionPerformed(null);
-          final FeatureSettings nfs = newframe.featureSettings;
-          SwingUtilities.invokeLater(new Runnable()
-          {
-            @Override
-            public void run()
-            {
-              nfs.frame.setBounds(fspos);
-            }
-          });
-          this.featureSettings.close();
-          this.featureSettings = null;
-        }
-        this.closeMenuItem_actionPerformed(true);
-      }
-    }
-  }
-
-  @Override
-  public void addFromText_actionPerformed(ActionEvent e)
-  {
-    Desktop.instance.inputTextboxMenuItem_actionPerformed(viewport);
-  }
-
-  @Override
-  public void addFromURL_actionPerformed(ActionEvent e)
-  {
-    Desktop.instance.inputURLMenuItem_actionPerformed(viewport);
-  }
-
-  @Override
-  public void save_actionPerformed(ActionEvent e)
-  {
-    if (fileName == null
-            || (currentFileFormat == null || !jalview.io.FormatAdapter
-                    .isValidIOFormat(currentFileFormat, true))
-            || fileName.startsWith("http"))
-    {
-      saveAs_actionPerformed(null);
-    }
-    else
-    {
-      saveAlignment(fileName, currentFileFormat);
-    }
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void saveAs_actionPerformed(ActionEvent e)
-  {
-    JalviewFileChooser chooser = new JalviewFileChooser(
-            jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
-            jalview.io.AppletFormatAdapter.WRITABLE_EXTENSIONS,
-            jalview.io.AppletFormatAdapter.WRITABLE_FNAMES,
-            currentFileFormat, false);
-
-    chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle("Save Alignment to file");
-    chooser.setToolTipText("Save");
-
-    int value = chooser.showSaveDialog(this);
-
-    if (value == JalviewFileChooser.APPROVE_OPTION)
-    {
-      currentFileFormat = chooser.getSelectedFormat();
-      if (currentFileFormat == null)
-      {
-        JOptionPane.showInternalMessageDialog(Desktop.desktop,
-                MessageManager.getString("label.select_file_format_before_saving"),
-                MessageManager.getString("label.file_format_not_specified"), JOptionPane.WARNING_MESSAGE);
-        value = chooser.showSaveDialog(this);
-        return;
-      }
-
-      fileName = chooser.getSelectedFile().getPath();
-
-      jalview.bin.Cache.setProperty("DEFAULT_FILE_FORMAT",
-              currentFileFormat);
-
-      jalview.bin.Cache.setProperty("LAST_DIRECTORY", fileName);
-      if (currentFileFormat.indexOf(" ") > -1)
-      {
-        currentFileFormat = currentFileFormat.substring(0,
-                currentFileFormat.indexOf(" "));
-      }
-      saveAlignment(fileName, currentFileFormat);
-    }
-  }
-
-  public boolean saveAlignment(String file, String format)
-  {
-    boolean success = true;
-
-    if (format.equalsIgnoreCase("Jalview"))
-    {
-      String shortName = title;
-
-      if (shortName.indexOf(java.io.File.separatorChar) > -1)
-      {
-        shortName = shortName.substring(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 String[]{fileName, format}));
-
-
-    }
-    else
-    {
-      if (!jalview.io.AppletFormatAdapter.isValidFormat(format, true))
-      {
-        warningMessage("Cannot save file " + fileName + " using format "
-                + format, "Alignment output format not supported");
-        saveAs_actionPerformed(null);
-        // JBPNote need to have a raise_gui flag here
-        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);
-        }
-      }
-      FormatAdapter f = new FormatAdapter();
-      String output = f.formatSequences(format,
-              viewport.getAlignment(), // class cast exceptions will
-              // occur in the distant future
-              omitHidden, f.getCacheSuffixDefault(format),
-              viewport.getColumnSelection());
-
-      if (output == null)
-      {
-        success = false;
-      }
-      else
-      {
-        try
-        {
-          java.io.PrintWriter out = new java.io.PrintWriter(
-                  new java.io.FileWriter(file));
-
-          out.print(output);
-          out.close();
-          this.setTitle(file);
-          statusBar.setText(MessageManager.formatMessage("label.successfully_saved_to_file_in_format",new String[]{fileName, format}));
-        } catch (Exception ex)
-        {
-          success = false;
-          ex.printStackTrace();
-        }
-      }
-    }
-
-    if (!success)
-    {
-      JOptionPane.showInternalMessageDialog(this, MessageManager.formatMessage("label.couldnt_save_file", new String[]{fileName}),
-              MessageManager.getString("label.error_saving_file"), JOptionPane.WARNING_MESSAGE);
-    }
-
-    return success;
-  }
-
-  private void warningMessage(String warning, String title)
-  {
-    if (new jalview.util.Platform().isHeadless())
-    {
-      System.err.println("Warning: " + title + "\nWarning: " + warning);
-
-    }
-    else
-    {
-      JOptionPane.showInternalMessageDialog(this, warning, title,
-              JOptionPane.WARNING_MESSAGE);
-    }
-    return;
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void outputText_actionPerformed(ActionEvent e)
-  {
-    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);
-      }
-    }
-
-    CutAndPasteTransfer cap = new CutAndPasteTransfer();
-    cap.setForInput(null);
-
-    try
-    {
-      cap.setText(new FormatAdapter().formatSequences(e.getActionCommand(),
-              viewport.getAlignment(), omitHidden,
-              viewport.getColumnSelection()));
-      Desktop.addInternalFrame(cap,
-              "Alignment output - " + e.getActionCommand(), 600, 500);
-    } catch (OutOfMemoryError oom)
-    {
-      new OOMWarning("Outputting alignment as " + e.getActionCommand(), oom);
-      cap.dispose();
-    }
-
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void htmlMenuItem_actionPerformed(ActionEvent e)
-  {
-    new HTMLOutput(alignPanel,
-            alignPanel.seqPanel.seqCanvas.getSequenceRenderer(),
-            alignPanel.seqPanel.seqCanvas.getFeatureRenderer());
-  }
-
-  public void createImageMap(File file, String image)
-  {
-    alignPanel.makePNGImageMap(file, image);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void createPNG(File f)
-  {
-    alignPanel.makePNG(f);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void createEPS(File f)
-  {
-    alignPanel.makeEPS(f);
-  }
-
-  @Override
-  public void pageSetup_actionPerformed(ActionEvent e)
-  {
-    PrinterJob printJob = PrinterJob.getPrinterJob();
-    PrintThread.pf = printJob.pageDialog(printJob.defaultPage());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void printMenuItem_actionPerformed(ActionEvent e)
-  {
-    // Putting in a thread avoids Swing painting problems
-    PrintThread thread = new PrintThread(alignPanel);
-    thread.start();
-  }
-
-  @Override
-  public void exportFeatures_actionPerformed(ActionEvent e)
-  {
-    new AnnotationExporter().exportFeatures(alignPanel);
-  }
-
-  @Override
-  public void exportAnnotations_actionPerformed(ActionEvent e)
-  {
-    new AnnotationExporter().exportAnnotations(alignPanel,
-            viewport.showAnnotation ? viewport.getAlignment()
-                    .getAlignmentAnnotation() : null, viewport
-                    .getAlignment().getGroups(), ((Alignment) viewport
-                    .getAlignment()).alignmentProperties);
-  }
-
-  @Override
-  public void associatedData_actionPerformed(ActionEvent e)
-  {
-    // Pick the tree file
-    JalviewFileChooser chooser = new JalviewFileChooser(
-            jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
-    chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle("Load Jalview Annotations or Features File");
-    chooser.setToolTipText("Load Jalview Annotations / Features file");
-
-    int value = chooser.showOpenDialog(null);
-
-    if (value == JalviewFileChooser.APPROVE_OPTION)
-    {
-      String choice = chooser.getSelectedFile().getPath();
-      jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
-      loadJalviewDataFile(choice, null, null, null);
-    }
-
-  }
-
-  /**
-   * Close the current view or all views in the alignment frame. If the frame
-   * only contains one view then the alignment will be removed from memory.
-   * 
-   * @param closeAllTabs
-   */
-  @Override
-  public void closeMenuItem_actionPerformed(boolean closeAllTabs)
-  {
-    if (alignPanels != null && alignPanels.size() < 2)
-    {
-      closeAllTabs = true;
-    }
-
-    try
-    {
-      if (alignPanels != null)
-      {
-        if (closeAllTabs)
-        {
-          if (this.isClosed())
-          {
-            // really close all the windows - otherwise wait till
-            // setClosed(true) is called
-            for (int i = 0; i < alignPanels.size(); i++)
-            {
-              AlignmentPanel ap = (AlignmentPanel) alignPanels.elementAt(i);
-              ap.closePanel();
-            }
-          }
-        }
-        else
-        {
-          closeView(alignPanel);
-        }
-      }
-
-      if (closeAllTabs)
-      {
-        this.setClosed(true);
-      }
-    } catch (Exception ex)
-    {
-      ex.printStackTrace();
-    }
-  }
-
-  /**
-   * close alignPanel2 and shuffle tabs appropriately.
-   * 
-   * @param alignPanel2
-   */
-  public void closeView(AlignmentPanel alignPanel2)
-  {
-    int index = tabbedPane.getSelectedIndex();
-    int closedindex = tabbedPane.indexOfComponent(alignPanel2);
-    alignPanels.removeElement(alignPanel2);
-    // Unnecessary
-    // if (viewport == alignPanel2.av)
-    // {
-    // viewport = null;
-    // }
-    alignPanel2.closePanel();
-    alignPanel2 = null;
-
-    tabbedPane.removeTabAt(closedindex);
-    tabbedPane.validate();
-
-    if (index > closedindex || index == tabbedPane.getTabCount())
-    {
-      // modify currently selected tab index if necessary.
-      index--;
-    }
-
-    this.tabSelectionChanged(index);
-  }
-
-  /**
-   * DOCUMENT ME!
-   */
-  void updateEditMenuBar()
-  {
-
-    if (viewport.historyList.size() > 0)
-    {
-      undoMenuItem.setEnabled(true);
-      CommandI command = (CommandI) viewport.historyList.peek();
-      undoMenuItem.setText(MessageManager.formatMessage("label.undo_command", new String[]{command.getDescription()}));
-    }
-    else
-    {
-      undoMenuItem.setEnabled(false);
-      undoMenuItem.setText(MessageManager.getString("action.undo"));
-    }
-
-    if (viewport.redoList.size() > 0)
-    {
-      redoMenuItem.setEnabled(true);
-
-      CommandI command = (CommandI) viewport.redoList.peek();
-      redoMenuItem.setText(MessageManager.formatMessage("label.redo_command", new String[]{command.getDescription()}));
-    }
-    else
-    {
-      redoMenuItem.setEnabled(false);
-      redoMenuItem.setText(MessageManager.getString("action.redo"));
-    }
-  }
-
-  public void addHistoryItem(CommandI command)
-  {
-    if (command.getSize() > 0)
-    {
-      viewport.historyList.push(command);
-      viewport.redoList.clear();
-      updateEditMenuBar();
-      viewport.updateHiddenColumns();
-      // viewport.hasHiddenColumns = (viewport.getColumnSelection() != null
-      // && viewport.getColumnSelection().getHiddenColumns() != null &&
-      // viewport.getColumnSelection()
-      // .getHiddenColumns().size() > 0);
-    }
-  }
-
-  /**
-   * 
-   * @return alignment objects for all views
-   */
-  AlignmentI[] getViewAlignments()
-  {
-    if (alignPanels != null)
-    {
-      Enumeration e = alignPanels.elements();
-      AlignmentI[] als = new AlignmentI[alignPanels.size()];
-      for (int i = 0; e.hasMoreElements(); i++)
-      {
-        als[i] = ((AlignmentPanel) e.nextElement()).av.getAlignment();
-      }
-      return als;
-    }
-    if (viewport != null)
-    {
-      return new AlignmentI[]
-      { viewport.getAlignment() };
-    }
-    return null;
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void undoMenuItem_actionPerformed(ActionEvent e)
-  {
-    if (viewport.historyList.empty())
-      return;
-    CommandI command = (CommandI) viewport.historyList.pop();
-    viewport.redoList.push(command);
-    command.undoCommand(getViewAlignments());
-
-    AlignViewport originalSource = getOriginatingSource(command);
-    updateEditMenuBar();
-
-    if (originalSource != null)
-    {
-      if (originalSource != viewport)
-      {
-        Cache.log
-                .warn("Implementation worry: mismatch of viewport origin for undo");
-      }
-      originalSource.updateHiddenColumns();
-      // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
-      // null
-      // && viewport.getColumnSelection().getHiddenColumns() != null &&
-      // viewport.getColumnSelection()
-      // .getHiddenColumns().size() > 0);
-      originalSource.firePropertyChange("alignment", null, originalSource
-              .getAlignment().getSequences());
-    }
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void redoMenuItem_actionPerformed(ActionEvent e)
-  {
-    if (viewport.redoList.size() < 1)
-    {
-      return;
-    }
-
-    CommandI command = (CommandI) viewport.redoList.pop();
-    viewport.historyList.push(command);
-    command.doCommand(getViewAlignments());
-
-    AlignViewport originalSource = getOriginatingSource(command);
-    updateEditMenuBar();
-
-    if (originalSource != null)
-    {
-
-      if (originalSource != viewport)
-      {
-        Cache.log
-                .warn("Implementation worry: mismatch of viewport origin for redo");
-      }
-      originalSource.updateHiddenColumns();
-      // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=
-      // null
-      // && viewport.getColumnSelection().getHiddenColumns() != null &&
-      // viewport.getColumnSelection()
-      // .getHiddenColumns().size() > 0);
-      originalSource.firePropertyChange("alignment", null, originalSource
-              .getAlignment().getSequences());
-    }
-  }
-
-  AlignViewport getOriginatingSource(CommandI command)
-  {
-    AlignViewport originalSource = null;
-    // For sequence removal and addition, we need to fire
-    // the property change event FROM the viewport where the
-    // original alignment was altered
-    AlignmentI al = null;
-    if (command instanceof EditCommand)
-    {
-      EditCommand editCommand = (EditCommand) command;
-      al = editCommand.getAlignment();
-      Vector comps = (Vector) PaintRefresher.components.get(viewport
-              .getSequenceSetId());
-
-      for (int i = 0; i < comps.size(); i++)
-      {
-        if (comps.elementAt(i) instanceof AlignmentPanel)
-        {
-          if (al == ((AlignmentPanel) comps.elementAt(i)).av.getAlignment())
-          {
-            originalSource = ((AlignmentPanel) comps.elementAt(i)).av;
-            break;
-          }
-        }
-      }
-    }
-
-    if (originalSource == null)
-    {
-      // The original view is closed, we must validate
-      // the current view against the closed view first
-      if (al != null)
-      {
-        PaintRefresher.validateSequences(al, viewport.getAlignment());
-      }
-
-      originalSource = viewport;
-    }
-
-    return originalSource;
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param up
-   *          DOCUMENT ME!
-   */
-  public void moveSelectedSequences(boolean up)
-  {
-    SequenceGroup sg = viewport.getSelectionGroup();
-
-    if (sg == null)
-    {
-      return;
-    }
-    viewport.getAlignment().moveSelectedSequencesByOne(sg,
-            viewport.getHiddenRepSequences(), up);
-    alignPanel.paintAlignment(true);
-  }
-
-  synchronized void slideSequences(boolean right, int size)
-  {
-    List<SequenceI> sg = new Vector();
-    if (viewport.cursorMode)
-    {
-      sg.add(viewport.getAlignment().getSequenceAt(
-              alignPanel.seqPanel.seqCanvas.cursorY));
-    }
-    else if (viewport.getSelectionGroup() != null
-            && viewport.getSelectionGroup().getSize() != viewport
-                    .getAlignment().getHeight())
-    {
-      sg = viewport.getSelectionGroup().getSequences(
-              viewport.getHiddenRepSequences());
-    }
-
-    if (sg.size() < 1)
-    {
-      return;
-    }
-
-    Vector invertGroup = new Vector();
-
-    for (int i = 0; i < viewport.getAlignment().getHeight(); i++)
-    {
-      if (!sg.contains(viewport.getAlignment().getSequenceAt(i)))
-        invertGroup.add(viewport.getAlignment().getSequenceAt(i));
-    }
-
-    SequenceI[] seqs1 = sg.toArray(new SequenceI[0]);
-
-    SequenceI[] seqs2 = new SequenceI[invertGroup.size()];
-    for (int i = 0; i < invertGroup.size(); i++)
-      seqs2[i] = (SequenceI) invertGroup.elementAt(i);
-
-    SlideSequencesCommand ssc;
-    if (right)
-      ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1,
-              size, viewport.getGapCharacter());
-    else
-      ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2,
-              size, viewport.getGapCharacter());
-
-    int groupAdjustment = 0;
-    if (ssc.getGapsInsertedBegin() && right)
-    {
-      if (viewport.cursorMode)
-        alignPanel.seqPanel.moveCursor(size, 0);
-      else
-        groupAdjustment = size;
-    }
-    else if (!ssc.getGapsInsertedBegin() && !right)
-    {
-      if (viewport.cursorMode)
-        alignPanel.seqPanel.moveCursor(-size, 0);
-      else
-        groupAdjustment = -size;
-    }
-
-    if (groupAdjustment != 0)
-    {
-      viewport.getSelectionGroup().setStartRes(
-              viewport.getSelectionGroup().getStartRes() + groupAdjustment);
-      viewport.getSelectionGroup().setEndRes(
-              viewport.getSelectionGroup().getEndRes() + groupAdjustment);
-    }
-
-    boolean appendHistoryItem = false;
-    if (viewport.historyList != null && viewport.historyList.size() > 0
-            && viewport.historyList.peek() instanceof SlideSequencesCommand)
-    {
-      appendHistoryItem = ssc
-              .appendSlideCommand((SlideSequencesCommand) viewport.historyList
-                      .peek());
-    }
-
-    if (!appendHistoryItem)
-      addHistoryItem(ssc);
-
-    repaint();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void copy_actionPerformed(ActionEvent e)
-  {
-    System.gc();
-    if (viewport.getSelectionGroup() == null)
-    {
-      return;
-    }
-    // TODO: preserve the ordering of displayed alignment annotation in any
-    // internal paste (particularly sequence associated annotation)
-    SequenceI[] seqs = viewport.getSelectionAsNewSequence();
-    String[] omitHidden = null;
-
-    if (viewport.hasHiddenColumns())
-    {
-      omitHidden = viewport.getViewAsString(true);
-    }
-
-    String output = new FormatAdapter().formatSequences("Fasta", seqs,
-            omitHidden);
-
-    StringSelection ss = new StringSelection(output);
-
-    try
-    {
-      jalview.gui.Desktop.internalCopy = true;
-      // Its really worth setting the clipboard contents
-      // to empty before setting the large StringSelection!!
-      Toolkit.getDefaultToolkit().getSystemClipboard()
-              .setContents(new StringSelection(""), null);
-
-      Toolkit.getDefaultToolkit().getSystemClipboard()
-              .setContents(ss, Desktop.instance);
-    } catch (OutOfMemoryError er)
-    {
-      new OOMWarning("copying region", er);
-      return;
-    }
-
-    Vector hiddenColumns = null;
-    if (viewport.hasHiddenColumns())
-    {
-      hiddenColumns = new Vector();
-      int hiddenOffset = viewport.getSelectionGroup().getStartRes(), hiddenCutoff = viewport
-              .getSelectionGroup().getEndRes();
-      for (int i = 0; i < viewport.getColumnSelection().getHiddenColumns()
-              .size(); i++)
-      {
-        int[] region = (int[]) viewport.getColumnSelection()
-                .getHiddenColumns().elementAt(i);
-        if (region[0] >= hiddenOffset && region[1] <= hiddenCutoff)
-        {
-          hiddenColumns.addElement(new int[]
-          { region[0] - hiddenOffset, region[1] - hiddenOffset });
-        }
-      }
-    }
-
-    Desktop.jalviewClipboard = new Object[]
-    { seqs, viewport.getAlignment().getDataset(), hiddenColumns };
-    statusBar.setText(MessageManager.formatMessage("label.copied_sequences_to_clipboard", new String[]{Integer.valueOf(seqs.length).toString()}));
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void pasteNew_actionPerformed(ActionEvent e)
-  {
-    paste(true);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void pasteThis_actionPerformed(ActionEvent e)
-  {
-    paste(false);
-  }
-
-  /**
-   * Paste contents of Jalview clipboard
-   * 
-   * @param newAlignment
-   *          true to paste to a new alignment, otherwise add to this.
-   */
-  void paste(boolean newAlignment)
-  {
-    boolean externalPaste = true;
-    try
-    {
-      Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
-      Transferable contents = c.getContents(this);
-
-      if (contents == null)
-      {
-        return;
-      }
-
-      String str, format;
-      try
-      {
-        str = (String) contents.getTransferData(DataFlavor.stringFlavor);
-        if (str.length() < 1)
-        {
-          return;
-        }
-
-        format = new IdentifyFile().Identify(str, "Paste");
-
-      } catch (OutOfMemoryError er)
-      {
-        new OOMWarning("Out of memory pasting sequences!!", er);
-        return;
-      }
-
-      SequenceI[] sequences;
-      boolean annotationAdded = false;
-      AlignmentI alignment = null;
-
-      if (Desktop.jalviewClipboard != null)
-      {
-        // The clipboard was filled from within Jalview, we must use the
-        // sequences
-        // And dataset from the copied alignment
-        SequenceI[] newseq = (SequenceI[]) Desktop.jalviewClipboard[0];
-        // be doubly sure that we create *new* sequence objects.
-        sequences = new SequenceI[newseq.length];
-        for (int i = 0; i < newseq.length; i++)
-        {
-          sequences[i] = new Sequence(newseq[i]);
-        }
-        alignment = new Alignment(sequences);
-        externalPaste = false;
-      }
-      else
-      {
-        // parse the clipboard as an alignment.
-        alignment = new FormatAdapter().readFile(str, "Paste", format);
-        sequences = alignment.getSequencesArray();
-      }
-
-      int alwidth = 0;
-      ArrayList<Integer> newGraphGroups = new ArrayList<Integer>();
-      int fgroup = -1;
-
-      if (newAlignment)
-      {
-
-        if (Desktop.jalviewClipboard != null)
-        {
-          // dataset is inherited
-          alignment.setDataset((Alignment) Desktop.jalviewClipboard[1]);
-        }
-        else
-        {
-          // new dataset is constructed
-          alignment.setDataset(null);
-        }
-        alwidth = alignment.getWidth() + 1;
-      }
-      else
-      {
-        AlignmentI pastedal = alignment; // preserve pasted alignment object
-        // Add pasted sequences and dataset into existing alignment.
-        alignment = viewport.getAlignment();
-        alwidth = alignment.getWidth() + 1;
-        // decide if we need to import sequences from an existing dataset
-        boolean importDs = Desktop.jalviewClipboard != null
-                && Desktop.jalviewClipboard[1] != alignment.getDataset();
-        // importDs==true instructs us to copy over new dataset sequences from
-        // an existing alignment
-        Vector newDs = (importDs) ? new Vector() : null; // used to create
-        // minimum dataset set
-
-        for (int i = 0; i < sequences.length; i++)
-        {
-          if (importDs)
-          {
-            newDs.addElement(null);
-          }
-          SequenceI ds = sequences[i].getDatasetSequence(); // null for a simple
-          // paste
-          if (importDs && ds != null)
-          {
-            if (!newDs.contains(ds))
-            {
-              newDs.setElementAt(ds, i);
-              ds = new Sequence(ds);
-              // update with new dataset sequence
-              sequences[i].setDatasetSequence(ds);
-            }
-            else
-            {
-              ds = sequences[newDs.indexOf(ds)].getDatasetSequence();
-            }
-          }
-          else
-          {
-            // copy and derive new dataset sequence
-            sequences[i] = sequences[i].deriveSequence();
-            alignment.getDataset().addSequence(
-                    sequences[i].getDatasetSequence());
-            // TODO: avoid creation of duplicate dataset sequences with a
-            // 'contains' method using SequenceI.equals()/SequenceI.contains()
-          }
-          alignment.addSequence(sequences[i]); // merges dataset
-        }
-        if (newDs != null)
-        {
-          newDs.clear(); // tidy up
-        }
-        if (alignment.getAlignmentAnnotation() != null)
-        {
-          for (AlignmentAnnotation alan : alignment
-                  .getAlignmentAnnotation())
-          {
-            if (alan.graphGroup > fgroup)
-            {
-              fgroup = alan.graphGroup;
-            }
-          }
-        }
-        if (pastedal.getAlignmentAnnotation() != null)
-        {
-          // Add any annotation attached to alignment.
-          AlignmentAnnotation[] alann = pastedal.getAlignmentAnnotation();
-          for (int i = 0; i < alann.length; i++)
-          {
-            annotationAdded = true;
-            if (alann[i].sequenceRef == null && !alann[i].autoCalculated)
-            {
-              AlignmentAnnotation newann = new AlignmentAnnotation(alann[i]);
-              if (newann.graphGroup > -1)
-              {
-                if (newGraphGroups.size() <= newann.graphGroup
-                        || newGraphGroups.get(newann.graphGroup) == null)
-                {
-                  for (int q = newGraphGroups.size(); q <= newann.graphGroup; q++)
-                  {
-                    newGraphGroups.add(q, null);
-                  }
-                  newGraphGroups.set(newann.graphGroup, new Integer(
-                          ++fgroup));
-                }
-                newann.graphGroup = newGraphGroups.get(newann.graphGroup)
-                        .intValue();
-              }
-
-              newann.padAnnotation(alwidth);
-              alignment.addAnnotation(newann);
-            }
-          }
-        }
-      }
-      if (!newAlignment)
-      {
-        // /////
-        // ADD HISTORY ITEM
-        //
-        addHistoryItem(new EditCommand("Add sequences", EditCommand.PASTE,
-                sequences, 0, alignment.getWidth(), alignment));
-      }
-      // Add any annotations attached to sequences
-      for (int i = 0; i < sequences.length; i++)
-      {
-        if (sequences[i].getAnnotation() != null)
-        {
-          AlignmentAnnotation newann;
-          for (int a = 0; a < sequences[i].getAnnotation().length; a++)
-          {
-            annotationAdded = true;
-            newann = sequences[i].getAnnotation()[a];
-            newann.adjustForAlignment();
-            newann.padAnnotation(alwidth);
-            if (newann.graphGroup > -1)
-            {
-              if (newann.graphGroup > -1)
-              {
-                if (newGraphGroups.size() <= newann.graphGroup
-                        || newGraphGroups.get(newann.graphGroup) == null)
-                {
-                  for (int q = newGraphGroups.size(); q <= newann.graphGroup; q++)
-                  {
-                    newGraphGroups.add(q, null);
-                  }
-                  newGraphGroups.set(newann.graphGroup, new Integer(
-                          ++fgroup));
-                }
-                newann.graphGroup = newGraphGroups.get(newann.graphGroup)
-                        .intValue();
-              }
-            }
-            alignment.addAnnotation(sequences[i].getAnnotation()[a]); // annotation
-            // was
-            // duplicated
-            // earlier
-            alignment
-                    .setAnnotationIndex(sequences[i].getAnnotation()[a], a);
-          }
-        }
-      }
-      if (!newAlignment)
-      {
-
-        // propagate alignment changed.
-        viewport.setEndSeq(alignment.getHeight());
-        if (annotationAdded)
-        {
-          // Duplicate sequence annotation in all views.
-          AlignmentI[] alview = this.getViewAlignments();
-          for (int i = 0; i < sequences.length; i++)
-          {
-            AlignmentAnnotation sann[] = sequences[i].getAnnotation();
-            if (sann == null)
-              continue;
-            for (int avnum = 0; avnum < alview.length; avnum++)
-            {
-              if (alview[avnum] != alignment)
-              {
-                // duplicate in a view other than the one with input focus
-                int avwidth = alview[avnum].getWidth() + 1;
-                // this relies on sann being preserved after we
-                // modify the sequence's annotation array for each duplication
-                for (int a = 0; a < sann.length; a++)
-                {
-                  AlignmentAnnotation newann = new AlignmentAnnotation(
-                          sann[a]);
-                  sequences[i].addAlignmentAnnotation(newann);
-                  newann.padAnnotation(avwidth);
-                  alview[avnum].addAnnotation(newann); // annotation was
-                  // duplicated earlier
-                  // TODO JAL-1145 graphGroups are not updated for sequence
-                  // annotation added to several views. This may cause
-                  // strangeness
-                  alview[avnum].setAnnotationIndex(newann, a);
-                }
-              }
-            }
-          }
-          buildSortByAnnotationScoresMenu();
-        }
-        viewport.firePropertyChange("alignment", null,
-                alignment.getSequences());
-        if (alignPanels != null)
-        {
-          for (AlignmentPanel ap : ((Vector<AlignmentPanel>) alignPanels))
-          {
-            ap.validateAnnotationDimensions(false);
-          }
-        }
-        else
-        {
-          alignPanel.validateAnnotationDimensions(false);
-        }
-
-      }
-      else
-      {
-        AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
-                DEFAULT_HEIGHT);
-        String newtitle = new String("Copied sequences");
-
-        if (Desktop.jalviewClipboard != null
-                && Desktop.jalviewClipboard[2] != null)
-        {
-          Vector hc = (Vector) Desktop.jalviewClipboard[2];
-          for (int i = 0; i < hc.size(); i++)
-          {
-            int[] region = (int[]) hc.elementAt(i);
-            af.viewport.hideColumns(region[0], region[1]);
-          }
-        }
-
-        // >>>This is a fix for the moment, until a better solution is
-        // found!!<<<
-        af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer()
-                .transferSettings(
-                        alignPanel.seqPanel.seqCanvas.getFeatureRenderer());
-
-        // TODO: maintain provenance of an alignment, rather than just make the
-        // title a concatenation of operations.
-        if (!externalPaste)
-        {
-          if (title.startsWith("Copied sequences"))
-          {
-            newtitle = title;
-          }
-          else
-          {
-            newtitle = newtitle.concat("- from " + title);
-          }
-        }
-        else
-        {
-          newtitle = new String("Pasted sequences");
-        }
-
-        Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,
-                DEFAULT_HEIGHT);
-
-      }
-
-    } catch (Exception ex)
-    {
-      ex.printStackTrace();
-      System.out.println("Exception whilst pasting: " + ex);
-      // could be anything being pasted in here
-    }
-
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void cut_actionPerformed(ActionEvent e)
-  {
-    copy_actionPerformed(null);
-    delete_actionPerformed(null);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void delete_actionPerformed(ActionEvent evt)
-  {
-
-    SequenceGroup sg = viewport.getSelectionGroup();
-    if (sg == null)
-    {
-      return;
-    }
-
-    Vector seqs = new Vector();
-    SequenceI seq;
-    for (int i = 0; i < sg.getSize(); i++)
-    {
-      seq = sg.getSequenceAt(i);
-      seqs.addElement(seq);
-    }
-
-    // If the cut affects all sequences, remove highlighted columns
-    if (sg.getSize() == viewport.getAlignment().getHeight())
-    {
-      viewport.getColumnSelection().removeElements(sg.getStartRes(),
-              sg.getEndRes() + 1);
-    }
-
-    SequenceI[] cut = new SequenceI[seqs.size()];
-    for (int i = 0; i < seqs.size(); i++)
-    {
-      cut[i] = (SequenceI) seqs.elementAt(i);
-    }
-
-    /*
-     * //ADD HISTORY ITEM
-     */
-    addHistoryItem(new EditCommand("Cut Sequences", EditCommand.CUT, cut,
-            sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
-            viewport.getAlignment()));
-
-    viewport.setSelectionGroup(null);
-    viewport.sendSelection();
-    viewport.getAlignment().deleteGroup(sg);
-
-    viewport.firePropertyChange("alignment", null, viewport.getAlignment()
-            .getSequences());
-    if (viewport.getAlignment().getHeight() < 1)
-    {
-      try
-      {
-        this.setClosed(true);
-      } catch (Exception ex)
-      {
-      }
-    }
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void deleteGroups_actionPerformed(ActionEvent e)
-  {
-    if (avc.deleteGroups()) {
-      PaintRefresher.Refresh(this, viewport.getSequenceSetId());
-      alignPanel.updateAnnotation();
-      alignPanel.paintAlignment(true);
-    }
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
-  {
-    SequenceGroup sg = new SequenceGroup();
-
-    for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
-    {
-      sg.addSequence(viewport.getAlignment().getSequenceAt(i), false);
-    }
-
-    sg.setEndRes(viewport.getAlignment().getWidth() - 1);
-    viewport.setSelectionGroup(sg);
-    viewport.sendSelection();
-    alignPanel.paintAlignment(true);
-    PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
-  {
-    if (viewport.cursorMode)
-    {
-      alignPanel.seqPanel.keyboardNo1 = null;
-      alignPanel.seqPanel.keyboardNo2 = null;
-    }
-    viewport.setSelectionGroup(null);
-    viewport.getColumnSelection().clear();
-    viewport.setSelectionGroup(null);
-    alignPanel.seqPanel.seqCanvas.highlightSearchResults(null);
-    alignPanel.idPanel.idCanvas.searchResults = null;
-    alignPanel.paintAlignment(true);
-    PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
-    viewport.sendSelection();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
-  {
-    SequenceGroup sg = viewport.getSelectionGroup();
-
-    if (sg == null)
-    {
-      selectAllSequenceMenuItem_actionPerformed(null);
-
-      return;
-    }
-
-    for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
-    {
-      sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);
-    }
-
-    alignPanel.paintAlignment(true);
-    PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
-    viewport.sendSelection();
-  }
-
-  @Override
-  public void invertColSel_actionPerformed(ActionEvent e)
-  {
-    viewport.invertColumnSelection();
-    alignPanel.paintAlignment(true);
-    viewport.sendSelection();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
-  {
-    trimAlignment(true);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void remove2RightMenuItem_actionPerformed(ActionEvent e)
-  {
-    trimAlignment(false);
-  }
-
-  void trimAlignment(boolean trimLeft)
-  {
-    ColumnSelection colSel = viewport.getColumnSelection();
-    int column;
-
-    if (colSel.size() > 0)
-    {
-      if (trimLeft)
-      {
-        column = colSel.getMin();
-      }
-      else
-      {
-        column = colSel.getMax();
-      }
-
-      SequenceI[] seqs;
-      if (viewport.getSelectionGroup() != null)
-      {
-        seqs = viewport.getSelectionGroup().getSequencesAsArray(
-                viewport.getHiddenRepSequences());
-      }
-      else
-      {
-        seqs = viewport.getAlignment().getSequencesArray();
-      }
-
-      TrimRegionCommand trimRegion;
-      if (trimLeft)
-      {
-        trimRegion = new TrimRegionCommand("Remove Left",
-                TrimRegionCommand.TRIM_LEFT, seqs, column,
-                viewport.getAlignment(), viewport.getColumnSelection(),
-                viewport.getSelectionGroup());
-        viewport.setStartRes(0);
-      }
-      else
-      {
-        trimRegion = new TrimRegionCommand("Remove Right",
-                TrimRegionCommand.TRIM_RIGHT, seqs, column,
-                viewport.getAlignment(), viewport.getColumnSelection(),
-                viewport.getSelectionGroup());
-      }
-
-      statusBar.setText(MessageManager.formatMessage("label.removed_columns", new String[]{Integer.valueOf(trimRegion.getSize()).toString()}));
-
-      addHistoryItem(trimRegion);
-
-      for (SequenceGroup sg : viewport.getAlignment().getGroups())
-      {
-        if ((trimLeft && !sg.adjustForRemoveLeft(column))
-                || (!trimLeft && !sg.adjustForRemoveRight(column)))
-        {
-          viewport.getAlignment().deleteGroup(sg);
-        }
-      }
-
-      viewport.firePropertyChange("alignment", null, viewport
-              .getAlignment().getSequences());
-    }
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
-  {
-    int start = 0, end = viewport.getAlignment().getWidth() - 1;
-
-    SequenceI[] seqs;
-    if (viewport.getSelectionGroup() != null)
-    {
-      seqs = viewport.getSelectionGroup().getSequencesAsArray(
-              viewport.getHiddenRepSequences());
-      start = viewport.getSelectionGroup().getStartRes();
-      end = viewport.getSelectionGroup().getEndRes();
-    }
-    else
-    {
-      seqs = viewport.getAlignment().getSequencesArray();
-    }
-
-    RemoveGapColCommand removeGapCols = new RemoveGapColCommand(
-            "Remove Gapped Columns", seqs, start, end,
-            viewport.getAlignment());
-
-    addHistoryItem(removeGapCols);
-
-    statusBar.setText(MessageManager.formatMessage("label.removed_empty_columns", new String[]{Integer.valueOf(removeGapCols.getSize()).toString()}));
-
-    // This is to maintain viewport position on first residue
-    // of first sequence
-    SequenceI seq = viewport.getAlignment().getSequenceAt(0);
-    int startRes = seq.findPosition(viewport.startRes);
-    // ShiftList shifts;
-    // viewport.getAlignment().removeGaps(shifts=new ShiftList());
-    // edit.alColumnChanges=shifts.getInverse();
-    // if (viewport.hasHiddenColumns)
-    // viewport.getColumnSelection().compensateForEdits(shifts);
-    viewport.setStartRes(seq.findIndex(startRes) - 1);
-    viewport.firePropertyChange("alignment", null, viewport.getAlignment()
-            .getSequences());
-
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
-  {
-    int start = 0, end = viewport.getAlignment().getWidth() - 1;
-
-    SequenceI[] seqs;
-    if (viewport.getSelectionGroup() != null)
-    {
-      seqs = viewport.getSelectionGroup().getSequencesAsArray(
-              viewport.getHiddenRepSequences());
-      start = viewport.getSelectionGroup().getStartRes();
-      end = viewport.getSelectionGroup().getEndRes();
-    }
-    else
-    {
-      seqs = viewport.getAlignment().getSequencesArray();
-    }
-
-    // This is to maintain viewport position on first residue
-    // of first sequence
-    SequenceI seq = viewport.getAlignment().getSequenceAt(0);
-    int startRes = seq.findPosition(viewport.startRes);
-
-    addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,
-            viewport.getAlignment()));
-
-    viewport.setStartRes(seq.findIndex(startRes) - 1);
-
-    viewport.firePropertyChange("alignment", null, viewport.getAlignment()
-            .getSequences());
-
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void padGapsMenuitem_actionPerformed(ActionEvent e)
-  {
-    viewport.setPadGaps(padGapsMenuitem.isSelected());
-    viewport.firePropertyChange("alignment", null, viewport.getAlignment()
-            .getSequences());
-  }
-
-  // else
-  {
-    // if (justifySeqs>0)
-    {
-      // alignment.justify(justifySeqs!=RIGHT_JUSTIFY);
-    }
-  }
-
-  // }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void findMenuItem_actionPerformed(ActionEvent e)
-  {
-    new Finder();
-  }
-
-  @Override
-  public void newView_actionPerformed(ActionEvent e)
-  {
-    newView(true);
-  }
-
-  /**
-   * 
-   * @param copyAnnotation
-   *          if true then duplicate all annnotation, groups and settings
-   * @return new alignment panel, already displayed.
-   */
-  public AlignmentPanel newView(boolean copyAnnotation)
-  {
-    return newView(null, copyAnnotation);
-  }
-
-  /**
-   * 
-   * @param viewTitle
-   *          title of newly created view
-   * @return new alignment panel, already displayed.
-   */
-  public AlignmentPanel newView(String viewTitle)
-  {
-    return newView(viewTitle, true);
-  }
-
-  /**
-   * 
-   * @param viewTitle
-   *          title of newly created view
-   * @param copyAnnotation
-   *          if true then duplicate all annnotation, groups and settings
-   * @return new alignment panel, already displayed.
-   */
-  public AlignmentPanel newView(String viewTitle, boolean copyAnnotation)
-  {
-    AlignmentPanel newap = new Jalview2XML().copyAlignPanel(alignPanel,
-            true);
-    if (!copyAnnotation)
-    {
-      // just remove all the current annotation except for the automatic stuff
-      newap.av.getAlignment().deleteAllGroups();
-      for (AlignmentAnnotation alan : newap.av.getAlignment()
-              .getAlignmentAnnotation())
-      {
-        if (!alan.autoCalculated)
-        {
-          newap.av.getAlignment().deleteAnnotation(alan);
-        }
-        ;
-      }
-    }
-
-    newap.av.gatherViewsHere = false;
-
-    if (viewport.viewName == null)
-    {
-      viewport.viewName = "Original";
-    }
-
-    newap.av.historyList = viewport.historyList;
-    newap.av.redoList = viewport.redoList;
-
-    int index = Desktop.getViewCount(viewport.getSequenceSetId());
-    // make sure the new view has a unique name - this is essential for Jalview
-    // 2 archives
-    boolean addFirstIndex = false;
-    if (viewTitle == null || viewTitle.trim().length() == 0)
-    {
-      viewTitle = "View";
-      addFirstIndex = true;
-    }
-    else
-    {
-      index = 1;// we count from 1 if given a specific name
-    }
-    String newViewName = viewTitle + ((addFirstIndex) ? " " + index : "");
-    Vector comps = (Vector) PaintRefresher.components.get(viewport
-            .getSequenceSetId());
-    Vector existingNames = new Vector();
-    for (int i = 0; i < comps.size(); i++)
-    {
-      if (comps.elementAt(i) instanceof AlignmentPanel)
-      {
-        AlignmentPanel ap = (AlignmentPanel) comps.elementAt(i);
-        if (!existingNames.contains(ap.av.viewName))
-        {
-          existingNames.addElement(ap.av.viewName);
-        }
-      }
-    }
-
-    while (existingNames.contains(newViewName))
-    {
-      newViewName = viewTitle + " " + (++index);
-    }
-
-    newap.av.viewName = newViewName;
-
-    addAlignmentPanel(newap, true);
-    newap.alignmentChanged();
-    
-    if (alignPanels.size() == 2)
-    {
-      viewport.gatherViewsHere = true;
-    }
-    tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
-    return newap;
-  }
-
-  @Override
-  public void expandViews_actionPerformed(ActionEvent e)
-  {
-    Desktop.instance.explodeViews(this);
-  }
-
-  @Override
-  public void gatherViews_actionPerformed(ActionEvent e)
-  {
-    Desktop.instance.gatherViews(this);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void font_actionPerformed(ActionEvent e)
-  {
-    new FontChooser(alignPanel);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void seqLimit_actionPerformed(ActionEvent e)
-  {
-    viewport.setShowJVSuffix(seqLimits.isSelected());
-
-    alignPanel.idPanel.idCanvas.setPreferredSize(alignPanel
-            .calculateIdWidth());
-    alignPanel.paintAlignment(true);
-  }
-
-  @Override
-  public void idRightAlign_actionPerformed(ActionEvent e)
-  {
-    viewport.rightAlignIds = idRightAlign.isSelected();
-    alignPanel.paintAlignment(true);
-  }
-
-  @Override
-  public void centreColumnLabels_actionPerformed(ActionEvent e)
-  {
-    viewport.centreColumnLabels = centreColumnLabelsMenuItem.getState();
-    alignPanel.paintAlignment(true);
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see jalview.jbgui.GAlignFrame#followHighlight_actionPerformed()
-   */
-  @Override
-  protected void followHighlight_actionPerformed()
-  {
-    if (viewport.followHighlight = this.followHighlightMenuItem.getState())
-    {
-      alignPanel.scrollToPosition(
-              alignPanel.seqPanel.seqCanvas.searchResults, false);
-    }
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void colourTextMenuItem_actionPerformed(ActionEvent e)
-  {
-    viewport.setColourText(colourTextMenuItem.isSelected());
-    alignPanel.paintAlignment(true);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void wrapMenuItem_actionPerformed(ActionEvent e)
-  {
-    scaleAbove.setVisible(wrapMenuItem.isSelected());
-    scaleLeft.setVisible(wrapMenuItem.isSelected());
-    scaleRight.setVisible(wrapMenuItem.isSelected());
-    viewport.setWrapAlignment(wrapMenuItem.isSelected());
-    alignPanel.setWrapAlignment(wrapMenuItem.isSelected());
-  }
-
-  @Override
-  public void showAllSeqs_actionPerformed(ActionEvent e)
-  {
-    viewport.showAllHiddenSeqs();
-  }
-
-  @Override
-  public void showAllColumns_actionPerformed(ActionEvent e)
-  {
-    viewport.showAllHiddenColumns();
-    repaint();
-  }
-
-  @Override
-  public void hideSelSequences_actionPerformed(ActionEvent e)
-  {
-    viewport.hideAllSelectedSeqs();
-    alignPanel.paintAlignment(true);
-  }
-
-  /**
-   * called by key handler and the hide all/show all menu items
-   * 
-   * @param toggleSeqs
-   * @param toggleCols
-   */
-  private void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols)
-  {
-
-    boolean hide = false;
-    SequenceGroup sg = viewport.getSelectionGroup();
-    if (!toggleSeqs && !toggleCols)
-    {
-      // Hide everything by the current selection - this is a hack - we do the
-      // invert and then hide
-      // first check that there will be visible columns after the invert.
-      if ((viewport.getColumnSelection() != null
-              && viewport.getColumnSelection().getSelected() != null && viewport
-              .getColumnSelection().getSelected().size() > 0)
-              || (sg != null && sg.getSize() > 0 && sg.getStartRes() <= sg
-                      .getEndRes()))
-      {
-        // now invert the sequence set, if required - empty selection implies
-        // that no hiding is required.
-        if (sg != null)
-        {
-          invertSequenceMenuItem_actionPerformed(null);
-          sg = viewport.getSelectionGroup();
-          toggleSeqs = true;
-
-        }
-        viewport.expandColSelection(sg, true);
-        // finally invert the column selection and get the new sequence
-        // selection.
-        invertColSel_actionPerformed(null);
-        toggleCols = true;
-      }
-    }
-
-    if (toggleSeqs)
-    {
-      if (sg != null && sg.getSize() != viewport.getAlignment().getHeight())
-      {
-        hideSelSequences_actionPerformed(null);
-        hide = true;
-      }
-      else if (!(toggleCols && viewport.getColumnSelection().getSelected()
-              .size() > 0))
-      {
-        showAllSeqs_actionPerformed(null);
-      }
-    }
-
-    if (toggleCols)
-    {
-      if (viewport.getColumnSelection().getSelected().size() > 0)
-      {
-        hideSelColumns_actionPerformed(null);
-        if (!toggleSeqs)
-        {
-          viewport.setSelectionGroup(sg);
-        }
-      }
-      else if (!hide)
-      {
-        showAllColumns_actionPerformed(null);
-      }
-    }
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * jalview.jbgui.GAlignFrame#hideAllButSelection_actionPerformed(java.awt.
-   * event.ActionEvent)
-   */
-  @Override
-  public void hideAllButSelection_actionPerformed(ActionEvent e)
-  {
-    toggleHiddenRegions(false, false);
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * jalview.jbgui.GAlignFrame#hideAllSelection_actionPerformed(java.awt.event
-   * .ActionEvent)
-   */
-  @Override
-  public void hideAllSelection_actionPerformed(ActionEvent e)
-  {
-    SequenceGroup sg = viewport.getSelectionGroup();
-    viewport.expandColSelection(sg, false);
-    viewport.hideAllSelectedSeqs();
-    viewport.hideSelectedColumns();
-    alignPanel.paintAlignment(true);
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * jalview.jbgui.GAlignFrame#showAllhidden_actionPerformed(java.awt.event.
-   * ActionEvent)
-   */
-  @Override
-  public void showAllhidden_actionPerformed(ActionEvent e)
-  {
-    viewport.showAllHiddenColumns();
-    viewport.showAllHiddenSeqs();
-    alignPanel.paintAlignment(true);
-  }
-
-  @Override
-  public void hideSelColumns_actionPerformed(ActionEvent e)
-  {
-    viewport.hideSelectedColumns();
-    alignPanel.paintAlignment(true);
-  }
-
-  @Override
-  public void hiddenMarkers_actionPerformed(ActionEvent e)
-  {
-    viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
-    repaint();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void scaleAbove_actionPerformed(ActionEvent e)
-  {
-    viewport.setScaleAboveWrapped(scaleAbove.isSelected());
-    alignPanel.paintAlignment(true);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void scaleLeft_actionPerformed(ActionEvent e)
-  {
-    viewport.setScaleLeftWrapped(scaleLeft.isSelected());
-    alignPanel.paintAlignment(true);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void scaleRight_actionPerformed(ActionEvent e)
-  {
-    viewport.setScaleRightWrapped(scaleRight.isSelected());
-    alignPanel.paintAlignment(true);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
-  {
-    viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
-    alignPanel.paintAlignment(true);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void viewTextMenuItem_actionPerformed(ActionEvent e)
-  {
-    viewport.setShowText(viewTextMenuItem.isSelected());
-    alignPanel.paintAlignment(true);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
-  {
-    viewport.setRenderGaps(renderGapsMenuItem.isSelected());
-    alignPanel.paintAlignment(true);
-  }
-
-  public FeatureSettings featureSettings;
-
-  @Override
-  public void featureSettings_actionPerformed(ActionEvent e)
-  {
-    if (featureSettings != null)
-    {
-      featureSettings.close();
-      featureSettings = null;
-    }
-    if (!showSeqFeatures.isSelected())
-    {
-      // make sure features are actually displayed
-      showSeqFeatures.setSelected(true);
-      showSeqFeatures_actionPerformed(null);
-    }
-    featureSettings = new FeatureSettings(this);
-  }
-
-  /**
-   * Set or clear 'Show Sequence Features'
-   * 
-   * @param evt
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void showSeqFeatures_actionPerformed(ActionEvent evt)
-  {
-    viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
-    alignPanel.paintAlignment(true);
-    if (alignPanel.getOverviewPanel() != null)
-    {
-      alignPanel.getOverviewPanel().updateOverviewImage();
-    }
-  }
-
-  /**
-   * Set or clear 'Show Sequence Features'
-   * 
-   * @param evt
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void showSeqFeaturesHeight_actionPerformed(ActionEvent evt)
-  {
-    viewport.setShowSequenceFeaturesHeight(showSeqFeaturesHeight
-            .isSelected());
-    if (viewport.getShowSequenceFeaturesHeight())
-    {
-      // ensure we're actually displaying features
-      viewport.setShowSequenceFeatures(true);
-      showSeqFeatures.setSelected(true);
-    }
-    alignPanel.paintAlignment(true);
-    if (alignPanel.getOverviewPanel() != null)
-    {
-      alignPanel.getOverviewPanel().updateOverviewImage();
-    }
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
-  {
-    viewport.setShowAnnotation(annotationPanelMenuItem.isSelected());
-    alignPanel.setAnnotationVisible(annotationPanelMenuItem.isSelected());
-  }
-
-  @Override
-  public void alignmentProperties()
-  {
-    JEditorPane editPane = new JEditorPane("text/html", "");
-    editPane.setEditable(false);
-    StringBuffer contents = new AlignmentProperties(viewport.getAlignment())
-            .formatAsHtml();
-    editPane.setText(MessageManager.formatMessage("label.html_content", new String[]{contents.toString()}));
-    JInternalFrame frame = new JInternalFrame();
-    frame.getContentPane().add(new JScrollPane(editPane));
-
-    Desktop.instance.addInternalFrame(frame, "Alignment Properties: "
-            + getTitle(), 500, 400);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void overviewMenuItem_actionPerformed(ActionEvent e)
-  {
-    if (alignPanel.overviewPanel != null)
-    {
-      return;
-    }
-
-    JInternalFrame frame = new JInternalFrame();
-    OverviewPanel overview = new OverviewPanel(alignPanel);
-    frame.setContentPane(overview);
-    Desktop.addInternalFrame(frame, "Overview " + this.getTitle(),
-            frame.getWidth(), frame.getHeight());
-    frame.pack();
-    frame.setLayer(JLayeredPane.PALETTE_LAYER);
-    frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
-    {
-      @Override
-      public void internalFrameClosed(
-              javax.swing.event.InternalFrameEvent evt)
-      {
-        alignPanel.setOverviewPanel(null);
-      };
-    });
-
-    alignPanel.setOverviewPanel(overview);
-  }
-
-  @Override
-  public void textColour_actionPerformed(ActionEvent e)
-  {
-    new TextColourChooser().chooseColour(alignPanel, null);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void noColourmenuItem_actionPerformed(ActionEvent e)
-  {
-    changeColour(null);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void clustalColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new ClustalxColourScheme(viewport.getAlignment(),
-            viewport.getHiddenRepSequences()));
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void zappoColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new ZappoColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void taylorColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new TaylorColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void hydrophobicityColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new HydrophobicColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void helixColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new HelixColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void strandColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new StrandColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void turnColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new TurnColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void buriedColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new BuriedColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void nucleotideColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new NucleotideColourScheme());
-  }
-
-  @Override
-  public void purinePyrimidineColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new PurinePyrimidineColourScheme());
-  }
-
-  /*
-   * public void covariationColour_actionPerformed(ActionEvent e) {
-   * changeColour(new
-   * CovariationColourScheme(viewport.getAlignment().getAlignmentAnnotation
-   * ()[0])); }
-   */
-  @Override
-  public void annotationColour_actionPerformed(ActionEvent e)
-  {
-    new AnnotationColourChooser(viewport, alignPanel);
-  }
-
-  @Override
-  public void rnahelicesColour_actionPerformed(ActionEvent e)
-  {
-    new RNAHelicesColourChooser(viewport, alignPanel);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void applyToAllGroups_actionPerformed(ActionEvent e)
-  {
-    viewport.setColourAppliesToAllGroups(applyToAllGroups.isSelected());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param cs
-   *          DOCUMENT ME!
-   */
-  public void changeColour(ColourSchemeI cs)
-  {
-    // TODO: compare with applet and pull up to model method
-    int threshold = 0;
-
-    if (cs != null)
-    {
-      if (viewport.getAbovePIDThreshold())
-      {
-        threshold = SliderPanel.setPIDSliderSource(alignPanel, cs,
-                "Background");
-
-        cs.setThreshold(threshold, viewport.getIgnoreGapsConsensus());
-
-        viewport.setGlobalColourScheme(cs);
-      }
-      else
-      {
-        cs.setThreshold(0, viewport.getIgnoreGapsConsensus());
-      }
-
-      if (viewport.getConservationSelected())
-      {
-
-        Alignment al = (Alignment) viewport.getAlignment();
-        Conservation c = new Conservation("All",
-                ResidueProperties.propHash, 3, al.getSequences(), 0,
-                al.getWidth() - 1);
-
-        c.calculate();
-        c.verdict(false, viewport.getConsPercGaps());
-
-        cs.setConservation(c);
-
-        cs.setConservationInc(SliderPanel.setConservationSlider(alignPanel,
-                cs, "Background"));
-      }
-      else
-      {
-        cs.setConservation(null);
-      }
-
-      cs.setConsensus(viewport.getSequenceConsensusHash());
-    }
-
-    viewport.setGlobalColourScheme(cs);
-
-    if (viewport.getColourAppliesToAllGroups())
-    {
-
-      for (SequenceGroup sg : viewport.getAlignment().getGroups())
-      {
-        if (cs == null)
-        {
-          sg.cs = null;
-          continue;
-        }
-
-        if (cs instanceof ClustalxColourScheme)
-        {
-          sg.cs = new ClustalxColourScheme(sg,
-                  viewport.getHiddenRepSequences());
-        }
-        else if (cs instanceof UserColourScheme)
-        {
-          sg.cs = new UserColourScheme(((UserColourScheme) cs).getColours());
-        }
-        else
-        {
-          try
-          {
-            sg.cs = cs.getClass().newInstance();
-          } catch (Exception ex)
-          {
-          }
-        }
-
-        if (viewport.getAbovePIDThreshold()
-                || cs instanceof PIDColourScheme
-                || cs instanceof Blosum62ColourScheme)
-        {
-          sg.cs.setThreshold(threshold, viewport.getIgnoreGapsConsensus());
-
-          sg.cs.setConsensus(AAFrequency.calculate(
-                  sg.getSequences(viewport.getHiddenRepSequences()),
-                  sg.getStartRes(), sg.getEndRes() + 1));
-        }
-        else
-        {
-          sg.cs.setThreshold(0, viewport.getIgnoreGapsConsensus());
-        }
-
-        if (viewport.getConservationSelected())
-        {
-          Conservation c = new Conservation("Group",
-                  ResidueProperties.propHash, 3, sg.getSequences(viewport
-                          .getHiddenRepSequences()), sg.getStartRes(),
-                  sg.getEndRes() + 1);
-          c.calculate();
-          c.verdict(false, viewport.getConsPercGaps());
-          sg.cs.setConservation(c);
-        }
-        else
-        {
-          sg.cs.setConservation(null);
-        }
-      }
-    }
-
-    if (alignPanel.getOverviewPanel() != null)
-    {
-      alignPanel.getOverviewPanel().updateOverviewImage();
-    }
-
-    alignPanel.paintAlignment(true);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void modifyPID_actionPerformed(ActionEvent e)
-  {
-    if (viewport.getAbovePIDThreshold()
-            && viewport.getGlobalColourScheme() != null)
-    {
-      SliderPanel.setPIDSliderSource(alignPanel,
-              viewport.getGlobalColourScheme(), "Background");
-      SliderPanel.showPIDSlider();
-    }
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void modifyConservation_actionPerformed(ActionEvent e)
-  {
-    if (viewport.getConservationSelected()
-            && viewport.getGlobalColourScheme() != null)
-    {
-      SliderPanel.setConservationSlider(alignPanel,
-              viewport.getGlobalColourScheme(), "Background");
-      SliderPanel.showConservationSlider();
-    }
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void conservationMenuItem_actionPerformed(ActionEvent e)
-  {
-    viewport.setConservationSelected(conservationMenuItem.isSelected());
-
-    viewport.setAbovePIDThreshold(false);
-    abovePIDThreshold.setSelected(false);
-
-    changeColour(viewport.getGlobalColourScheme());
-
-    modifyConservation_actionPerformed(null);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void abovePIDThreshold_actionPerformed(ActionEvent e)
-  {
-    viewport.setAbovePIDThreshold(abovePIDThreshold.isSelected());
-
-    conservationMenuItem.setSelected(false);
-    viewport.setConservationSelected(false);
-
-    changeColour(viewport.getGlobalColourScheme());
-
-    modifyPID_actionPerformed(null);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void userDefinedColour_actionPerformed(ActionEvent e)
-  {
-    if (e.getActionCommand().equals("User Defined..."))
-    {
-      new UserDefinedColours(alignPanel, null);
-    }
-    else
-    {
-      UserColourScheme udc = (UserColourScheme) UserDefinedColours
-              .getUserColourSchemes().get(e.getActionCommand());
-
-      changeColour(udc);
-    }
-  }
-
-  public void updateUserColourMenu()
-  {
-
-    Component[] menuItems = colourMenu.getMenuComponents();
-    int i, iSize = menuItems.length;
-    for (i = 0; i < iSize; i++)
-    {
-      if (menuItems[i].getName() != null
-              && menuItems[i].getName().equals("USER_DEFINED"))
-      {
-        colourMenu.remove(menuItems[i]);
-        iSize--;
-      }
-    }
-    if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)
-    {
-      java.util.Enumeration userColours = jalview.gui.UserDefinedColours
-              .getUserColourSchemes().keys();
-
-      while (userColours.hasMoreElements())
-      {
-        final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(
-                userColours.nextElement().toString());
-        radioItem.setName("USER_DEFINED");
-        radioItem.addMouseListener(new MouseAdapter()
-        {
-          @Override
-          public void mousePressed(MouseEvent evt)
-          {
-            if (evt.isControlDown()
-                    || SwingUtilities.isRightMouseButton(evt))
-            {
-              radioItem.removeActionListener(radioItem.getActionListeners()[0]);
-
-              int option = JOptionPane.showInternalConfirmDialog(
-                      jalview.gui.Desktop.desktop,
-                      MessageManager.getString("label.remove_from_default_list"),
-                      MessageManager.getString("label.remove_user_defined_colour"),
-                      JOptionPane.YES_NO_OPTION);
-              if (option == JOptionPane.YES_OPTION)
-              {
-                jalview.gui.UserDefinedColours
-                        .removeColourFromDefaults(radioItem.getText());
-                colourMenu.remove(radioItem);
-              }
-              else
-              {
-                radioItem.addActionListener(new ActionListener()
-                {
-                  @Override
-                  public void actionPerformed(ActionEvent evt)
-                  {
-                    userDefinedColour_actionPerformed(evt);
-                  }
-                });
-              }
-            }
-          }
-        });
-        radioItem.addActionListener(new ActionListener()
-        {
-          @Override
-          public void actionPerformed(ActionEvent evt)
-          {
-            userDefinedColour_actionPerformed(evt);
-          }
-        });
-
-        colourMenu.insert(radioItem, 15);
-        colours.add(radioItem);
-      }
-    }
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void PIDColour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new PIDColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void BLOSUM62Colour_actionPerformed(ActionEvent e)
-  {
-    changeColour(new Blosum62ColourScheme());
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
-  {
-    SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
-    AlignmentSorter.sortByPID(viewport.getAlignment(), viewport
-            .getAlignment().getSequenceAt(0), null);
-    addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
-            viewport.getAlignment()));
-    alignPanel.paintAlignment(true);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void sortIDMenuItem_actionPerformed(ActionEvent e)
-  {
-    SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
-    AlignmentSorter.sortByID(viewport.getAlignment());
-    addHistoryItem(new OrderCommand("ID Sort", oldOrder,
-            viewport.getAlignment()));
-    alignPanel.paintAlignment(true);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void sortLengthMenuItem_actionPerformed(ActionEvent e)
-  {
-    SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
-    AlignmentSorter.sortByLength(viewport.getAlignment());
-    addHistoryItem(new OrderCommand("Length Sort", oldOrder,
-            viewport.getAlignment()));
-    alignPanel.paintAlignment(true);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void sortGroupMenuItem_actionPerformed(ActionEvent e)
-  {
-    SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
-    AlignmentSorter.sortByGroup(viewport.getAlignment());
-    addHistoryItem(new OrderCommand("Group Sort", oldOrder,
-            viewport.getAlignment()));
-
-    alignPanel.paintAlignment(true);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
-  {
-    new RedundancyPanel(alignPanel, this);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
-  {
-    if ((viewport.getSelectionGroup() == null)
-            || (viewport.getSelectionGroup().getSize() < 2))
-    {
-      JOptionPane.showInternalMessageDialog(this,
-              MessageManager.getString("label.you_must_select_least_two_sequences"), MessageManager.getString("label.invalid_selection"),
-              JOptionPane.WARNING_MESSAGE);
-    }
-    else
-    {
-      JInternalFrame frame = new JInternalFrame();
-      frame.setContentPane(new PairwiseAlignPanel(viewport));
-      Desktop.addInternalFrame(frame, "Pairwise Alignment", 600, 500);
-    }
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void PCAMenuItem_actionPerformed(ActionEvent e)
-  {
-    if (((viewport.getSelectionGroup() != null)
-            && (viewport.getSelectionGroup().getSize() < 4) && (viewport
-            .getSelectionGroup().getSize() > 0))
-            || (viewport.getAlignment().getHeight() < 4))
-    {
-      JOptionPane.showInternalMessageDialog(this,
-              MessageManager.getString("label.principal_component_analysis_must_take_least_four_input_sequences"),
-              MessageManager.getString("label.sequence_selection_insufficient"),
-              JOptionPane.WARNING_MESSAGE);
-
-      return;
-    }
-
-    new PCAPanel(alignPanel);
-  }
-
-  @Override
-  public void autoCalculate_actionPerformed(ActionEvent e)
-  {
-    viewport.autoCalculateConsensus = autoCalculate.isSelected();
-    if (viewport.autoCalculateConsensus)
-    {
-      viewport.firePropertyChange("alignment", null, viewport
-              .getAlignment().getSequences());
-    }
-  }
-
-  @Override
-  public void sortByTreeOption_actionPerformed(ActionEvent e)
-  {
-    viewport.sortByTree = sortByTree.isSelected();
-  }
-
-  @Override
-  protected void listenToViewSelections_actionPerformed(ActionEvent e)
-  {
-    viewport.followSelection = listenToViewSelections.isSelected();
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)
-  {
-    NewTreePanel("AV", "PID", "Average distance tree using PID");
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)
-  {
-    NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)
-  {
-    NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)
-  {
-    NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param type
-   *          DOCUMENT ME!
-   * @param pwType
-   *          DOCUMENT ME!
-   * @param title
-   *          DOCUMENT ME!
-   */
-  void NewTreePanel(String type, String pwType, String title)
-  {
-    TreePanel tp;
-
-    if (viewport.getSelectionGroup() != null
-            && viewport.getSelectionGroup().getSize() > 0)
-    {
-      if (viewport.getSelectionGroup().getSize() < 3)
-      {
-        JOptionPane
-                .showMessageDialog(
-                        Desktop.desktop,
-                        MessageManager.getString("label.you_need_more_two_sequences_selected_build_tree"),
-                        MessageManager.getString("label.not_enough_sequences"), JOptionPane.WARNING_MESSAGE);
-        return;
-      }
-
-      SequenceGroup sg = viewport.getSelectionGroup();
-
-      /* Decide if the selection is a column region */
-      for (SequenceI _s : sg.getSequences())
-      {
-        if (_s.getLength() < sg.getEndRes())
-        {
-          JOptionPane
-                  .showMessageDialog(
-                          Desktop.desktop,
-                          MessageManager.getString("label.selected_region_to_tree_may_only_contain_residues_or_gaps"),
-                          MessageManager.getString("label.sequences_selection_not_aligned"),
-                          JOptionPane.WARNING_MESSAGE);
-
-          return;
-        }
-      }
-
-      title = title + " on region";
-      tp = new TreePanel(alignPanel, type, pwType);
-    }
-    else
-    {
-      // are the visible sequences aligned?
-      if (!viewport.getAlignment().isAligned(false))
-      {
-        JOptionPane
-                .showMessageDialog(
-                        Desktop.desktop,
-                        MessageManager.getString("label.sequences_must_be_aligned_before_creating_tree"),
-                        MessageManager.getString("label.sequences_not_aligned"),
-                        JOptionPane.WARNING_MESSAGE);
-
-        return;
-      }
-
-      if (viewport.getAlignment().getHeight() < 2)
-      {
-        return;
-      }
-
-      tp = new TreePanel(alignPanel, type, pwType);
-    }
-
-    title += " from ";
-
-    if (viewport.viewName != null)
-    {
-      title += viewport.viewName + " of ";
-    }
-
-    title += this.title;
-
-    Desktop.addInternalFrame(tp, title, 600, 500);
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param title
-   *          DOCUMENT ME!
-   * @param order
-   *          DOCUMENT ME!
-   */
-  public void addSortByOrderMenuItem(String title,
-          final AlignmentOrder order)
-  {
-    final JMenuItem item = new JMenuItem("by " + title);
-    sort.add(item);
-    item.addActionListener(new java.awt.event.ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
-
-        // TODO: JBPNote - have to map order entries to curent SequenceI
-        // pointers
-        AlignmentSorter.sortBy(viewport.getAlignment(), order);
-
-        addHistoryItem(new OrderCommand(order.getName(), oldOrder, viewport
-                .getAlignment()));
-
-        alignPanel.paintAlignment(true);
-      }
-    });
-  }
-
-  /**
-   * Add a new sort by annotation score menu item
-   * 
-   * @param sort
-   *          the menu to add the option to
-   * @param scoreLabel
-   *          the label used to retrieve scores for each sequence on the
-   *          alignment
-   */
-  public void addSortByAnnotScoreMenuItem(JMenu sort,
-          final String scoreLabel)
-  {
-    final JMenuItem item = new JMenuItem(scoreLabel);
-    sort.add(item);
-    item.addActionListener(new java.awt.event.ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
-        AlignmentSorter.sortByAnnotationScore(scoreLabel,
-                viewport.getAlignment());// ,viewport.getSelectionGroup());
-        addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
-                viewport.getAlignment()));
-        alignPanel.paintAlignment(true);
-      }
-    });
-  }
-
-  /**
-   * last hash for alignment's annotation array - used to minimise cost of
-   * rebuild.
-   */
-  protected int _annotationScoreVectorHash;
-
-  /**
-   * search the alignment and rebuild the sort by annotation score submenu the
-   * last alignment annotation vector hash is stored to minimize cost of
-   * rebuilding in subsequence calls.
-   * 
-   */
-  @Override
-  public void buildSortByAnnotationScoresMenu()
-  {
-    if (viewport.getAlignment().getAlignmentAnnotation() == null)
-    {
-      return;
-    }
-
-    if (viewport.getAlignment().getAlignmentAnnotation().hashCode() != _annotationScoreVectorHash)
-    {
-      sortByAnnotScore.removeAll();
-      // almost certainly a quicker way to do this - but we keep it simple
-      Hashtable scoreSorts = new Hashtable();
-      AlignmentAnnotation aann[];
-      for (SequenceI sqa : viewport.getAlignment().getSequences())
-      {
-        aann = sqa.getAnnotation();
-        for (int i = 0; aann != null && i < aann.length; i++)
-        {
-          if (aann[i].hasScore() && aann[i].sequenceRef != null)
-          {
-            scoreSorts.put(aann[i].label, aann[i].label);
-          }
-        }
-      }
-      Enumeration labels = scoreSorts.keys();
-      while (labels.hasMoreElements())
-      {
-        addSortByAnnotScoreMenuItem(sortByAnnotScore,
-                (String) labels.nextElement());
-      }
-      sortByAnnotScore.setVisible(scoreSorts.size() > 0);
-      scoreSorts.clear();
-
-      _annotationScoreVectorHash = viewport.getAlignment()
-              .getAlignmentAnnotation().hashCode();
-    }
-  }
-
-  /**
-   * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a
-   * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>
-   * call. Listeners are added to remove the menu item when the treePanel is
-   * closed, and adjust the tree leaf to sequence mapping when the alignment is
-   * modified.
-   * 
-   * @param treePanel
-   *          Displayed tree window.
-   * @param title
-   *          SortBy menu item title.
-   */
-  @Override
-  public void buildTreeMenu()
-  {
-    sortByTreeMenu.removeAll();
-
-    Vector comps = (Vector) PaintRefresher.components.get(viewport
-            .getSequenceSetId());
-    Vector treePanels = new Vector();
-    int i, iSize = comps.size();
-    for (i = 0; i < iSize; i++)
-    {
-      if (comps.elementAt(i) instanceof TreePanel)
-      {
-        treePanels.add(comps.elementAt(i));
-      }
-    }
-
-    iSize = treePanels.size();
-
-    if (iSize < 1)
-    {
-      sortByTreeMenu.setVisible(false);
-      return;
-    }
-
-    sortByTreeMenu.setVisible(true);
-
-    for (i = 0; i < treePanels.size(); i++)
-    {
-      final TreePanel tp = (TreePanel) treePanels.elementAt(i);
-      final JMenuItem item = new JMenuItem(tp.getTitle());
-      final NJTree tree = ((TreePanel) treePanels.elementAt(i)).getTree();
-      item.addActionListener(new java.awt.event.ActionListener()
-      {
-        @Override
-        public void actionPerformed(ActionEvent e)
-        {
-          tp.sortByTree_actionPerformed(null);
-          addHistoryItem(tp.sortAlignmentIn(alignPanel));
-
-        }
-      });
-
-      sortByTreeMenu.add(item);
-    }
-  }
-
-  public boolean sortBy(AlignmentOrder alorder, String undoname)
-  {
-    SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
-    AlignmentSorter.sortBy(viewport.getAlignment(), alorder);
-    if (undoname != null)
-    {
-      addHistoryItem(new OrderCommand(undoname, oldOrder,
-              viewport.getAlignment()));
-    }
-    alignPanel.paintAlignment(true);
-    return true;
-  }
-
-  /**
-   * Work out whether the whole set of sequences or just the selected set will
-   * be submitted for multiple alignment.
-   * 
-   */
-  public jalview.datamodel.AlignmentView gatherSequencesForAlignment()
-  {
-    // Now, check we have enough sequences
-    AlignmentView msa = null;
-
-    if ((viewport.getSelectionGroup() != null)
-            && (viewport.getSelectionGroup().getSize() > 1))
-    {
-      // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to
-      // some common interface!
-      /*
-       * SequenceGroup seqs = viewport.getSelectionGroup(); int sz; msa = new
-       * SequenceI[sz = seqs.getSize(false)];
-       * 
-       * for (int i = 0; i < sz; i++) { msa[i] = (SequenceI)
-       * seqs.getSequenceAt(i); }
-       */
-      msa = viewport.getAlignmentView(true);
-    }
-    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;
-  }
-
-  /**
-   * Decides what is submitted to a secondary structure prediction service: the
-   * first sequence in the alignment, or in the current selection, or, if the
-   * alignment is 'aligned' (ie padded with gaps), then the currently selected
-   * region or the whole alignment. (where the first sequence in the set is the
-   * one that the prediction will be for).
-   */
-  public AlignmentView gatherSeqOrMsaForSecStrPrediction()
-  {
-    AlignmentView seqs = null;
-
-    if ((viewport.getSelectionGroup() != null)
-            && (viewport.getSelectionGroup().getSize() > 0))
-    {
-      seqs = viewport.getAlignmentView(true);
-    }
-    else
-    {
-      seqs = viewport.getAlignmentView(false);
-    }
-    // limit sequences - JBPNote in future - could spawn multiple prediction
-    // jobs
-    // TODO: viewport.getAlignment().isAligned is a global state - the local
-    // selection may well be aligned - we preserve 2.0.8 behaviour for moment.
-    if (!viewport.getAlignment().isAligned(false))
-    {
-      seqs.setSequences(new SeqCigar[]
-      { seqs.getSequences()[0] });
-      // TODO: if seqs.getSequences().length>1 then should really have warned
-      // user!
-
-    }
-    return seqs;
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void LoadtreeMenuItem_actionPerformed(ActionEvent e)
-  {
-    // Pick the tree file
-    JalviewFileChooser chooser = new JalviewFileChooser(
-            jalview.bin.Cache.getProperty("LAST_DIRECTORY"));
-    chooser.setFileView(new JalviewFileView());
-    chooser.setDialogTitle("Select a newick-like tree file");
-    chooser.setToolTipText("Load a tree file");
-
-    int value = chooser.showOpenDialog(null);
-
-    if (value == JalviewFileChooser.APPROVE_OPTION)
-    {
-      String choice = chooser.getSelectedFile().getPath();
-      jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
-      jalview.io.NewickFile fin = null;
-      try
-      {
-        fin = new jalview.io.NewickFile(choice, "File");
-        viewport.setCurrentTree(ShowNewickTree(fin, choice).getTree());
-      } catch (Exception ex)
-      {
-        JOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),
-                MessageManager.getString("label.problem_reading_tree_file"), JOptionPane.WARNING_MESSAGE);
-        ex.printStackTrace();
-      }
-      if (fin != null && fin.hasWarningMessage())
-      {
-        JOptionPane.showMessageDialog(Desktop.desktop,
-                fin.getWarningMessage(), MessageManager.getString("label.possible_problem_with_tree_file"),
-                JOptionPane.WARNING_MESSAGE);
-      }
-    }
-  }
-
-  @Override
-  protected void tcoffeeColorScheme_actionPerformed(ActionEvent e)
-  {
-    changeColour(new TCoffeeColourScheme(alignPanel.getAlignment()));
-  }
-
-  public TreePanel ShowNewickTree(NewickFile nf, String title)
-  {
-    return ShowNewickTree(nf, title, 600, 500, 4, 5);
-  }
-
-  public TreePanel ShowNewickTree(NewickFile nf, String title,
-          AlignmentView input)
-  {
-    return ShowNewickTree(nf, title, input, 600, 500, 4, 5);
-  }
-
-  public TreePanel ShowNewickTree(NewickFile nf, String title, int w,
-          int h, int x, int y)
-  {
-    return ShowNewickTree(nf, title, null, w, h, x, y);
-  }
-
-  /**
-   * Add a treeviewer for the tree extracted from a newick file object to the
-   * current alignment view
-   * 
-   * @param nf
-   *          the tree
-   * @param title
-   *          tree viewer title
-   * @param input
-   *          Associated alignment input data (or null)
-   * @param w
-   *          width
-   * @param h
-   *          height
-   * @param x
-   *          position
-   * @param y
-   *          position
-   * @return TreePanel handle
-   */
-  public TreePanel ShowNewickTree(NewickFile nf, String title,
-          AlignmentView input, int w, int h, int x, int y)
-  {
-    TreePanel tp = null;
-
-    try
-    {
-      nf.parse();
-
-      if (nf.getTree() != null)
-      {
-        tp = new TreePanel(alignPanel, "FromFile", title, nf, input);
-
-        tp.setSize(w, h);
-
-        if (x > 0 && y > 0)
-        {
-          tp.setLocation(x, y);
-        }
-
-        Desktop.addInternalFrame(tp, title, w, h);
-      }
-    } catch (Exception ex)
-    {
-      ex.printStackTrace();
-    }
-
-    return tp;
-  }
-
-  private boolean buildingMenu = false;
-
-  /**
-   * Generates menu items and listener event actions for web service clients
-   * 
-   */
-  public void BuildWebServiceMenu()
-  {
-    while (buildingMenu)
-    {
-      try
-      {
-        System.err.println("Waiting for building menu to finish.");
-        Thread.sleep(10);
-      } catch (Exception e)
-      {
-      }
-      ;
-    }
-    final AlignFrame me = this;
-    buildingMenu = true;
-    new Thread(new Runnable()
-    {
-      @Override
-      public void run()
-      {
-        final List<JMenuItem> legacyItems=new ArrayList<JMenuItem>();
-        try
-        {
-          System.err.println("Building ws menu again "
-                  + Thread.currentThread());
-          // TODO: add support for context dependent disabling of services based
-          // on
-          // alignment and current selection
-          // TODO: add additional serviceHandle parameter to specify abstract
-          // handler
-          // class independently of AbstractName
-          // TODO: add in rediscovery GUI function to restart discoverer
-          // TODO: group services by location as well as function and/or
-          // introduce
-          // object broker mechanism.
-          final Vector<JMenu> wsmenu = new Vector<JMenu>();
-          final IProgressIndicator af = me;
-          final JMenu msawsmenu = new JMenu("Alignment");
-          final JMenu secstrmenu = new JMenu(
-                  "Secondary Structure Prediction");
-          final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
-          final JMenu analymenu = new JMenu("Analysis");
-          final JMenu dismenu = new JMenu("Protein Disorder");
-          // JAL-940 - only show secondary structure prediction services from
-          // the legacy server
-          if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)
-              // &&
-          Discoverer.services != null && (Discoverer.services.size() > 0))
-          {
-            // TODO: refactor to allow list of AbstractName/Handler bindings to
-            // be
-            // stored or retrieved from elsewhere
-            // No MSAWS used any more:
-            // Vector msaws = null; // (Vector) Discoverer.services.get("MsaWS");
-            Vector secstrpr = (Vector) Discoverer.services
-                    .get("SecStrPred");
-            if (secstrpr != null)
-            {
-              // Add any secondary structure prediction services
-              for (int i = 0, j = secstrpr.size(); i < j; i++)
-              {
-                final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle) secstrpr
-                        .get(i);
-                jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer
-                        .getServiceClient(sh);
-                int p=secstrmenu.getItemCount();
-                impl.attachWSMenuEntry(secstrmenu, me);
-                int q=secstrmenu.getItemCount();
-                for (int litm=p;litm<q; litm++)
-                {
-                  legacyItems.add(secstrmenu.getItem(litm));
-                }
-              }
-            }
-          }
-          
-          // Add all submenus in the order they should appear on the web
-          // services menu
-          wsmenu.add(msawsmenu);
-          wsmenu.add(secstrmenu);
-          wsmenu.add(dismenu);
-          wsmenu.add(analymenu);
-          // No search services yet
-          // wsmenu.add(seqsrchmenu);
-
-          javax.swing.SwingUtilities.invokeLater(new Runnable()
-          {
-            @Override
-            public void run()
-            {
-              try
-              {
-                webService.removeAll();
-                // first, add discovered services onto the webservices menu
-                if (wsmenu.size() > 0)
-                {
-                  for (int i = 0, j = wsmenu.size(); i < j; i++)
-                  {
-                    webService.add(wsmenu.get(i));
-                  }
-                }
-                else
-                {
-                  webService.add(me.webServiceNoServices);
-                }
-                // TODO: move into separate menu builder class.
-                boolean new_sspred=false;
-                if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
-                {
-                  Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();
-                  if (jws2servs != null)
-                  {
-                    if (jws2servs.hasServices())
-                    {
-                      jws2servs.attachWSMenuEntry(webService, me);
-                      for (Jws2Instance sv:jws2servs.getServices()) {
-                        if (sv.description.toLowerCase().contains("jpred"))
-                        {
-                          for (JMenuItem jmi:legacyItems)
-                          {
-                            jmi.setVisible(false);
-                          }
-                        }
-                      }
-                      
-                    }
-                    if (jws2servs.isRunning())
-                    {
-                      JMenuItem tm = new JMenuItem(
-                              "Still discovering JABA Services");
-                      tm.setEnabled(false);
-                      webService.add(tm);
-                    }
-                  }
-                }
-                build_urlServiceMenu(me.webService);
-                build_fetchdbmenu(webService);
-                for (JMenu item : wsmenu)
-                {
-                  if (item.getItemCount() == 0)
-                  {
-                    item.setEnabled(false);
-                  }
-                  else
-                  {
-                    item.setEnabled(true);
-                  }
-                }
-              } catch (Exception e)
-              {
-                Cache.log
-                        .debug("Exception during web service menu building process.",
-                                e);
-              }
-              ;
-            }
-          });
-        } catch (Exception e)
-        {
-        }
-        ;
-
-        buildingMenu = false;
-      }
-    }).start();
-
-  }
-
-  /**
-   * construct any groupURL type service menu entries.
-   * 
-   * @param webService
-   */
-  private void build_urlServiceMenu(JMenu webService)
-  {
-    // TODO: remove this code when 2.7 is released
-    // DEBUG - alignmentView
-    /*
-     * JMenuItem testAlView = new JMenuItem("Test AlignmentView"); final
-     * AlignFrame af = this; testAlView.addActionListener(new ActionListener() {
-     * 
-     * @Override public void actionPerformed(ActionEvent e) {
-     * jalview.datamodel.AlignmentView
-     * .testSelectionViews(af.viewport.getAlignment(),
-     * af.viewport.getColumnSelection(), af.viewport.selectionGroup); }
-     * 
-     * }); webService.add(testAlView);
-     */
-    // TODO: refactor to RestClient discoverer and merge menu entries for
-    // rest-style services with other types of analysis/calculation service
-    // SHmmr test client - still being implemented.
-    // DEBUG - alignmentView
-
-    for (jalview.ws.rest.RestClient client : jalview.ws.rest.RestClient
-            .getRestClients())
-    {
-      client.attachWSMenuEntry(
-              JvSwingUtils.findOrCreateMenu(webService, client.getAction()),
-              this);
-    }
-
-    if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))
-    {
-      jalview.ws.EnfinEnvision2OneWay.getInstance().attachWSMenuEntry(
-              webService, this);
-    }
-  }
-
-  /*
-   * public void vamsasStore_actionPerformed(ActionEvent e) { JalviewFileChooser
-   * chooser = new JalviewFileChooser(jalview.bin.Cache.
-   * getProperty("LAST_DIRECTORY"));
-   * 
-   * chooser.setFileView(new JalviewFileView()); chooser.setDialogTitle("Export
-   * to Vamsas file"); chooser.setToolTipText("Export");
-   * 
-   * int value = chooser.showSaveDialog(this);
-   * 
-   * if (value == JalviewFileChooser.APPROVE_OPTION) {
-   * jalview.io.VamsasDatastore vs = new jalview.io.VamsasDatastore(viewport);
-   * //vs.store(chooser.getSelectedFile().getAbsolutePath() ); vs.storeJalview(
-   * chooser.getSelectedFile().getAbsolutePath(), this); } }
-   */
-  /**
-   * prototype of an automatically enabled/disabled analysis function
-   * 
-   */
-  protected void setShowProductsEnabled()
-  {
-    SequenceI[] selection = viewport.getSequenceSelection();
-    if (canShowProducts(selection, viewport.getSelectionGroup() != null,
-            viewport.getAlignment().getDataset()))
-    {
-      showProducts.setEnabled(true);
-
-    }
-    else
-    {
-      showProducts.setEnabled(false);
-    }
-  }
-
-  /**
-   * search selection for sequence xRef products and build the show products
-   * menu.
-   * 
-   * @param selection
-   * @param dataset
-   * @return true if showProducts menu should be enabled.
-   */
-  public boolean canShowProducts(SequenceI[] selection,
-          boolean isRegionSelection, Alignment dataset)
-  {
-    boolean showp = false;
-    try
-    {
-      showProducts.removeAll();
-      final boolean dna = viewport.getAlignment().isNucleotide();
-      final Alignment ds = dataset;
-      String[] ptypes = (selection == null || selection.length == 0) ? null
-              : CrossRef.findSequenceXrefTypes(dna, selection, dataset);
-      // Object[] prods =
-      // CrossRef.buildXProductsList(viewport.getAlignment().isNucleotide(),
-      // selection, dataset, true);
-      final SequenceI[] sel = selection;
-      for (int t = 0; ptypes != null && t < ptypes.length; t++)
-      {
-        showp = true;
-        final boolean isRegSel = isRegionSelection;
-        final AlignFrame af = this;
-        final String source = ptypes[t];
-        JMenuItem xtype = new JMenuItem(ptypes[t]);
-        xtype.addActionListener(new ActionListener()
-        {
-
-          @Override
-          public void actionPerformed(ActionEvent e)
-          {
-            // TODO: new thread for this call with vis-delay
-            af.showProductsFor(af.viewport.getSequenceSelection(), ds,
-                    isRegSel, dna, source);
-          }
-
-        });
-        showProducts.add(xtype);
-      }
-      showProducts.setVisible(showp);
-      showProducts.setEnabled(showp);
-    } catch (Exception e)
-    {
-      jalview.bin.Cache.log
-              .warn("canTranslate threw an exception - please report to help@jalview.org",
-                      e);
-      return false;
-    }
-    return showp;
-  }
-
-  protected void showProductsFor(SequenceI[] sel, Alignment ds,
-          boolean isRegSel, boolean dna, String source)
-  {
-    final boolean fisRegSel = isRegSel;
-    final boolean fdna = dna;
-    final String fsrc = source;
-    final AlignFrame ths = this;
-    final SequenceI[] fsel = sel;
-    Runnable foo = new Runnable()
-    {
-
-      @Override
-      public void run()
-      {
-        final long sttime = System.currentTimeMillis();
-        ths.setProgressBar("Searching for sequences from " + fsrc, sttime);
-        try
-        {
-          Alignment ds = ths.getViewport().getAlignment().getDataset(); // update
-          // our local
-          // dataset
-          // reference
-          Alignment prods = CrossRef
-                  .findXrefSequences(fsel, fdna, fsrc, ds);
-          if (prods != null)
-          {
-            SequenceI[] sprods = new SequenceI[prods.getHeight()];
-            for (int s = 0; s < sprods.length; s++)
-            {
-              sprods[s] = (prods.getSequenceAt(s)).deriveSequence();
-              if (ds.getSequences() == null
-                      || !ds.getSequences().contains(
-                              sprods[s].getDatasetSequence()))
-                ds.addSequence(sprods[s].getDatasetSequence());
-              sprods[s].updatePDBIds();
-            }
-            Alignment al = new Alignment(sprods);
-            AlignedCodonFrame[] cf = prods.getCodonFrames();
-            al.setDataset(ds);
-            for (int s = 0; cf != null && s < cf.length; s++)
-            {
-              al.addCodonFrame(cf[s]);
-              cf[s] = null;
-            }
-            AlignFrame naf = new AlignFrame(al, DEFAULT_WIDTH,
-                    DEFAULT_HEIGHT);
-            String newtitle = "" + ((fdna) ? "Proteins " : "Nucleotides ")
-                    + " for " + ((fisRegSel) ? "selected region of " : "")
-                    + getTitle();
-            Desktop.addInternalFrame(naf, newtitle, DEFAULT_WIDTH,
-                    DEFAULT_HEIGHT);
-          }
-          else
-          {
-            System.err.println("No Sequences generated for xRef type "
-                    + fsrc);
-          }
-        } catch (Exception e)
-        {
-          jalview.bin.Cache.log.error(
-                  "Exception when finding crossreferences", e);
-        } catch (OutOfMemoryError e)
-        {
-          new OOMWarning("whilst fetching crossreferences", e);
-        } catch (Error e)
-        {
-          jalview.bin.Cache.log.error("Error when finding crossreferences",
-                  e);
-        }
-        ths.setProgressBar("Finished searching for sequences from " + fsrc,
-                sttime);
-      }
-
-    };
-    Thread frunner = new Thread(foo);
-    frunner.start();
-  }
-
-  public boolean canShowTranslationProducts(SequenceI[] selection,
-          AlignmentI alignment)
-  {
-    // old way
-    try
-    {
-      return (jalview.analysis.Dna.canTranslate(selection,
-              viewport.getViewAsVisibleContigs(true)));
-    } catch (Exception e)
-    {
-      jalview.bin.Cache.log
-              .warn("canTranslate threw an exception - please report to help@jalview.org",
-                      e);
-      return false;
-    }
-  }
-
-  @Override
-  public void showProducts_actionPerformed(ActionEvent e)
-  {
-    // /////////////////////////////
-    // Collect Data to be translated/transferred
-
-    SequenceI[] selection = viewport.getSequenceSelection();
-    AlignmentI al = null;
-    try
-    {
-      al = jalview.analysis.Dna.CdnaTranslate(selection, viewport
-              .getViewAsVisibleContigs(true), viewport.getGapCharacter(),
-              viewport.getAlignment().getDataset());
-    } catch (Exception ex)
-    {
-      al = null;
-      jalview.bin.Cache.log.debug("Exception during translation.", ex);
-    }
-    if (al == null)
-    {
-      JOptionPane
-              .showMessageDialog(
-                      Desktop.desktop,
-                      MessageManager.getString("label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation"),
-                      MessageManager.getString("label.translation_failed"), JOptionPane.WARNING_MESSAGE);
-    }
-    else
-    {
-      AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
-      Desktop.addInternalFrame(af, "Translation of " + this.getTitle(),
-              DEFAULT_WIDTH, DEFAULT_HEIGHT);
-    }
-  }
-
-  @Override
-  public void showTranslation_actionPerformed(ActionEvent e)
-  {
-    // /////////////////////////////
-    // Collect Data to be translated/transferred
-
-    SequenceI[] selection = viewport.getSequenceSelection();
-    String[] seqstring = viewport.getViewAsString(true);
-    AlignmentI al = null;
-    try
-    {
-      al = jalview.analysis.Dna.CdnaTranslate(selection, seqstring,
-              viewport.getViewAsVisibleContigs(true), viewport
-                      .getGapCharacter(), viewport.getAlignment()
-                      .getAlignmentAnnotation(), viewport.getAlignment()
-                      .getWidth(), viewport.getAlignment().getDataset());
-    } catch (Exception ex)
-    {
-      al = null;
-      jalview.bin.Cache.log.error("Exception during translation. Please report this !", ex);
-      JOptionPane
-      .showMessageDialog(
-              Desktop.desktop,
-              MessageManager.getString("label.error_when_translating_sequences_submit_bug_report"),
-              MessageManager.getString("label.implementation_error") + MessageManager.getString("translation_failed"), JOptionPane.ERROR_MESSAGE);
-      return;
-    }
-    if (al == null)
-    {
-      JOptionPane
-              .showMessageDialog(
-                      Desktop.desktop,
-                      MessageManager.getString("label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation"),
-                      MessageManager.getString("label.translation_failed"), JOptionPane.WARNING_MESSAGE);
-    }
-    else
-    {
-      AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
-      Desktop.addInternalFrame(af, "Translation of " + this.getTitle(),
-              DEFAULT_WIDTH, DEFAULT_HEIGHT);
-    }
-  }
-
-  /**
-   * Try to load a features file onto the alignment.
-   * 
-   * @param file
-   *          contents or path to retrieve file
-   * @param type
-   *          access mode of file (see jalview.io.AlignFile)
-   * @return true if features file was parsed corectly.
-   */
-  public boolean parseFeaturesFile(String file, String type)
-  {
-    boolean featuresFile = false;
-    try
-    {
-      featuresFile = new FeaturesFile(file, type).parse(viewport
-              .getAlignment().getDataset(), alignPanel.seqPanel.seqCanvas
-              .getFeatureRenderer().featureColours, false,
-              jalview.bin.Cache.getDefault("RELAXEDSEQIDMATCHING", false));
-    } catch (Exception ex)
-    {
-      ex.printStackTrace();
-    }
-
-    if (featuresFile)
-    {
-      viewport.showSequenceFeatures = true;
-      showSeqFeatures.setSelected(true);
-      if (alignPanel.seqPanel.seqCanvas.fr != null)
-      {
-        // update the min/max ranges where necessary
-        alignPanel.seqPanel.seqCanvas.fr.findAllFeatures(true);
-      }
-      if (featureSettings != null)
-      {
-        featureSettings.setTableData();
-      }
-      alignPanel.paintAlignment(true);
-    }
-
-    return featuresFile;
-  }
-
-  @Override
-  public void dragEnter(DropTargetDragEvent evt)
-  {
-  }
-
-  @Override
-  public void dragExit(DropTargetEvent evt)
-  {
-  }
-
-  @Override
-  public void dragOver(DropTargetDragEvent evt)
-  {
-  }
-
-  @Override
-  public void dropActionChanged(DropTargetDragEvent evt)
-  {
-  }
-
-  @Override
-  public void drop(DropTargetDropEvent evt)
-  {
-    Transferable t = evt.getTransferable();
-    java.util.List files = null;
-
-    try
-    {
-      DataFlavor uriListFlavor = new DataFlavor(
-              "text/uri-list;class=java.lang.String");
-      if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
-      {
-        // Works on Windows and MacOSX
-        evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
-        files = (java.util.List) t
-                .getTransferData(DataFlavor.javaFileListFlavor);
-      }
-      else if (t.isDataFlavorSupported(uriListFlavor))
-      {
-        // This is used by Unix drag system
-        evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
-        String data = (String) t.getTransferData(uriListFlavor);
-        files = new java.util.ArrayList(1);
-        for (java.util.StringTokenizer st = new java.util.StringTokenizer(
-                data, "\r\n"); st.hasMoreTokens();)
-        {
-          String s = st.nextToken();
-          if (s.startsWith("#"))
-          {
-            // the line is a comment (as per the RFC 2483)
-            continue;
-          }
-
-          java.net.URI uri = new java.net.URI(s);
-          // check to see if we can handle this kind of URI
-          if (uri.getScheme().toLowerCase().startsWith("http"))
-          {
-            files.add(uri.toString());
-          }
-          else
-          {
-            // otherwise preserve old behaviour: catch all for file objects
-            java.io.File file = new java.io.File(uri);
-            files.add(file.toString());
-          }
-        }
-      }
-    } catch (Exception e)
-    {
-      e.printStackTrace();
-    }
-    if (files != null)
-    {
-      try
-      {
-        // check to see if any of these files have names matching sequences in
-        // the alignment
-        SequenceIdMatcher idm = new SequenceIdMatcher(viewport
-                .getAlignment().getSequencesArray());
-        /**
-         * Object[] { String,SequenceI}
-         */
-        ArrayList<Object[]> filesmatched = new ArrayList<Object[]>();
-        ArrayList<String> filesnotmatched = new ArrayList<String>();
-        for (int i = 0; i < files.size(); i++)
-        {
-          String file = files.get(i).toString();
-          String pdbfn = "";
-          String protocol = FormatAdapter.checkProtocol(file);
-          if (protocol == jalview.io.FormatAdapter.FILE)
-          {
-            File fl = new File(file);
-            pdbfn = fl.getName();
-          }
-          else if (protocol == jalview.io.FormatAdapter.URL)
-          {
-            URL url = new URL(file);
-            pdbfn = url.getFile();
-          }
-          if (pdbfn.length() > 0)
-          {
-            // attempt to find a match in the alignment
-            SequenceI[] mtch = idm.findAllIdMatches(pdbfn);
-            int l = 0, c = pdbfn.indexOf(".");
-            while (mtch == null && c != -1)
-            {
-              do
-              {
-                l = c;
-              } while ((c = pdbfn.indexOf(".", l)) > l);
-              if (l > -1)
-              {
-                pdbfn = pdbfn.substring(0, l);
-              }
-              mtch = idm.findAllIdMatches(pdbfn);
-            }
-            if (mtch != null)
-            {
-              String type = null;
-              try
-              {
-                type = new IdentifyFile().Identify(file, protocol);
-              } catch (Exception ex)
-              {
-                type = null;
-              }
-              if (type != null)
-              {
-                if (type.equalsIgnoreCase("PDB"))
-                {
-                  filesmatched.add(new Object[]
-                  { file, protocol, mtch });
-                  continue;
-                }
-              }
-            }
-            // File wasn't named like one of the sequences or wasn't a PDB file.
-            filesnotmatched.add(file);
-          }
-        }
-        int assocfiles = 0;
-        if (filesmatched.size() > 0)
-        {
-          if (Cache.getDefault("AUTOASSOCIATE_PDBANDSEQS", false)
-                  || JOptionPane
-                          .showConfirmDialog(
-                                  this,
-                                  MessageManager.formatMessage("label.automatically_associate_pdb_files_with_sequences_same_name",
-                                                 new String[]{Integer.valueOf(filesmatched.size()).toString()}),
-                                  MessageManager.getString("label.automatically_associate_pdb_files_by_name"),
-                                  JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION)
-
-          {
-            for (Object[] fm : filesmatched)
-            {
-              // try and associate
-              // TODO: may want to set a standard ID naming formalism for
-              // associating PDB files which have no IDs.
-              for (SequenceI toassoc : (SequenceI[]) fm[2])
-              {
-                PDBEntry pe = new AssociatePdbFileWithSeq()
-                        .associatePdbWithSeq((String) fm[0],
-                                (String) fm[1], toassoc, false);
-                if (pe != null)
-                {
-                  System.err.println("Associated file : "
-                          + ((String) fm[0]) + " with "
-                          + toassoc.getDisplayId(true));
-                  assocfiles++;
-                }
-              }
-              alignPanel.paintAlignment(true);
-            }
-          }
-        }
-        if (filesnotmatched.size() > 0)
-        {
-          if (assocfiles > 0
-                  && (Cache.getDefault(
-                          "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false) || JOptionPane
-                          .showConfirmDialog(
-                                  this,
-                                  MessageManager.formatMessage("label.ignore_unmatched_dropped_files_info", new String[]{Integer.valueOf(filesnotmatched.size()).toString()}),
-                                  MessageManager.getString("label.ignore_unmatched_dropped_files"),
-                                  JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION))
-          {
-            return;
-          }
-          for (String fn : filesnotmatched)
-          {
-            loadJalviewDataFile(fn, null, null, null);
-          }
-
-        }
-      } catch (Exception ex)
-      {
-        ex.printStackTrace();
-      }
-    }
-  }
-
-  /**
-   * Attempt to load a "dropped" file or URL string: First by testing whether
-   * it's and Annotation file, then a JNet file, and finally a features file. If
-   * all are false then the user may have dropped an alignment file onto this
-   * AlignFrame.
-   * 
-   * @param file
-   *          either a filename or a URL string.
-   */
-  public void loadJalviewDataFile(String file, String protocol,
-          String format, SequenceI assocSeq)
-  {
-    try
-    {
-      if (protocol == null)
-      {
-        protocol = jalview.io.FormatAdapter.checkProtocol(file);
-      }
-      // if the file isn't identified, or not positively identified as some
-      // other filetype (PFAM is default unidentified alignment file type) then
-      // try to parse as annotation.
-      boolean isAnnotation = (format == null || format
-              .equalsIgnoreCase("PFAM")) ? new AnnotationFile()
-              .readAnnotationFile(viewport.getAlignment(), file, protocol)
-              : false;
-
-      if (!isAnnotation)
-      {
-        // first see if its a T-COFFEE score file
-        TCoffeeScoreFile tcf = null;
-        try
-        {
-          tcf = new TCoffeeScoreFile(file, protocol);
-          if (tcf.isValid())
-          {
-            if (tcf.annotateAlignment(viewport.getAlignment(), true))
-            {
-              tcoffeeColour.setEnabled(true);
-              tcoffeeColour.setSelected(true);
-              changeColour(new TCoffeeColourScheme(viewport.getAlignment()));
-              isAnnotation = true;
-              statusBar.setText(MessageManager.getString("label.successfully_pasted_tcoffee_scores_to_alignment"));
-            }
-            else
-            {
-              // some problem - if no warning its probable that the ID matching
-              // process didn't work
-              JOptionPane
-                      .showMessageDialog(
-                              Desktop.desktop,
-                              tcf.getWarningMessage() == null ? MessageManager.getString("label.check_file_matches_sequence_ids_alignment")
-                                      : tcf.getWarningMessage(),
-                              MessageManager.getString("label.problem_reading_tcoffee_score_file"),
-                              JOptionPane.WARNING_MESSAGE);
-            }
-          }
-          else
-          {
-            tcf = null;
-          }
-        } catch (Exception x)
-        {
-          Cache.log
-                  .debug("Exception when processing data source as T-COFFEE score file",
-                          x);
-          tcf = null;
-        }
-        if (tcf == null)
-        {
-          // try to see if its a JNet 'concise' style annotation file *before*
-          // we
-          // try to parse it as a features file
-          if (format == null)
-          {
-            format = new IdentifyFile().Identify(file, protocol);
-          }
-          if (format.equalsIgnoreCase("JnetFile"))
-          {
-            jalview.io.JPredFile predictions = new jalview.io.JPredFile(
-                    file, protocol);
-            new JnetAnnotationMaker().add_annotation(predictions,
-                    viewport.getAlignment(), 0, false);
-            isAnnotation = true;
-          }
-          else
-          {
-            /*
-             * if (format.equalsIgnoreCase("PDB")) {
-             * 
-             * String pdbfn = ""; // try to match up filename with sequence id
-             * try { if (protocol == jalview.io.FormatAdapter.FILE) { File fl =
-             * new File(file); pdbfn = fl.getName(); } else if (protocol ==
-             * jalview.io.FormatAdapter.URL) { URL url = new URL(file); pdbfn =
-             * url.getFile(); } } catch (Exception e) { } ; if (assocSeq ==
-             * null) { SequenceIdMatcher idm = new SequenceIdMatcher(viewport
-             * .getAlignment().getSequencesArray()); if (pdbfn.length() > 0) {
-             * // attempt to find a match in the alignment SequenceI mtch =
-             * idm.findIdMatch(pdbfn); int l = 0, c = pdbfn.indexOf("."); while
-             * (mtch == null && c != -1) { while ((c = pdbfn.indexOf(".", l)) >
-             * l) { l = c; } if (l > -1) { pdbfn = pdbfn.substring(0, l); } mtch
-             * = idm.findIdMatch(pdbfn); } if (mtch != null) { // try and
-             * associate // prompt ? PDBEntry pe = new AssociatePdbFileWithSeq()
-             * .associatePdbWithSeq(file, protocol, mtch, true); if (pe != null)
-             * { System.err.println("Associated file : " + file + " with " +
-             * mtch.getDisplayId(true)); alignPanel.paintAlignment(true); } } //
-             * TODO: maybe need to load as normal otherwise return; } }
-             */
-            // try to parse it as a features file
-            boolean isGroupsFile = parseFeaturesFile(file, protocol);
-            // if it wasn't a features file then we just treat it as a general
-            // alignment file to load into the current view.
-            if (!isGroupsFile)
-            {
-              new FileLoader().LoadFile(viewport, file, protocol, format);
-            }
-            else
-            {
-              alignPanel.paintAlignment(true);
-            }
-          }
-        }
-      }
-      if (isAnnotation)
-      {
-
-        alignPanel.adjustAnnotationHeight();
-        viewport.updateSequenceIdColours();
-        buildSortByAnnotationScoresMenu();
-        alignPanel.paintAlignment(true);
-      }
-    } catch (Exception ex)
-    {
-      ex.printStackTrace();
-    } catch (OutOfMemoryError oom)
-    {
-      try
-      {
-        System.gc();
-      } catch (Exception x)
-      {
-      }
-      ;
-      new OOMWarning(
-              "loading data "
-                      + (protocol != null ? (protocol.equals(FormatAdapter.PASTE) ? "from clipboard."
-                              : "using " + protocol + " from " + file)
-                              : ".")
-                      + (format != null ? "(parsing as '" + format
-                              + "' file)" : ""), oom, Desktop.desktop);
-    }
-  }
-
-  @Override
-  public void tabSelectionChanged(int index)
-  {
-    if (index > -1)
-    {
-      alignPanel = (AlignmentPanel) alignPanels.elementAt(index);
-      viewport = alignPanel.av;
-      avc.setViewportAndAlignmentPanel(viewport, alignPanel);
-      setMenusFromViewport(viewport);
-    }
-  }
-
-  @Override
-  public void tabbedPane_mousePressed(MouseEvent e)
-  {
-    if (SwingUtilities.isRightMouseButton(e))
-    {
-      String reply = JOptionPane.showInternalInputDialog(this,
-              MessageManager.getString("label.enter_view_name"), MessageManager.getString("label.enter_view_name"),
-              JOptionPane.QUESTION_MESSAGE);
-
-      if (reply != null)
-      {
-        viewport.viewName = reply;
-        tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
-      }
-    }
-  }
-
-  public AlignViewport getCurrentView()
-  {
-    return viewport;
-  }
-
-  /**
-   * Open the dialog for regex description parsing.
-   */
-  @Override
-  protected void extractScores_actionPerformed(ActionEvent e)
-  {
-    ParseProperties pp = new jalview.analysis.ParseProperties(
-            viewport.getAlignment());
-    // TODO: verify regex and introduce GUI dialog for version 2.5
-    // if (pp.getScoresFromDescription("col", "score column ",
-    // "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)",
-    // true)>0)
-    if (pp.getScoresFromDescription("description column",
-            "score in description column ", "\\W*([-+eE0-9.]+)", true) > 0)
-    {
-      buildSortByAnnotationScoresMenu();
-    }
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * jalview.jbgui.GAlignFrame#showDbRefs_actionPerformed(java.awt.event.ActionEvent
-   * )
-   */
-  @Override
-  protected void showDbRefs_actionPerformed(ActionEvent e)
-  {
-    viewport.setShowDbRefs(showDbRefsMenuitem.isSelected());
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @seejalview.jbgui.GAlignFrame#showNpFeats_actionPerformed(java.awt.event.
-   * ActionEvent)
-   */
-  @Override
-  protected void showNpFeats_actionPerformed(ActionEvent e)
-  {
-    viewport.setShowNpFeats(showNpFeatsMenuitem.isSelected());
-  }
-
-  /**
-   * find the viewport amongst the tabs in this alignment frame and close that
-   * tab
-   * 
-   * @param av
-   */
-  public boolean closeView(AlignViewport av)
-  {
-    if (viewport == av)
-    {
-      this.closeMenuItem_actionPerformed(false);
-      return true;
-    }
-    Component[] comp = tabbedPane.getComponents();
-    for (int i = 0; comp != null && i < comp.length; i++)
-    {
-      if (comp[i] instanceof AlignmentPanel)
-      {
-        if (((AlignmentPanel) comp[i]).av == av)
-        {
-          // close the view.
-          closeView((AlignmentPanel) comp[i]);
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-
-  protected void build_fetchdbmenu(JMenu webService)
-  {
-    // Temporary hack - DBRef Fetcher always top level ws entry.
-    // TODO We probably want to store a sequence database checklist in
-    // preferences and have checkboxes.. rather than individual sources selected
-    // here
-    final JMenu rfetch = new JMenu("Fetch DB References");
-    rfetch.setToolTipText("Retrieve and parse sequence database records for the alignment or the currently selected sequences");
-    webService.add(rfetch);
-
-    JMenuItem fetchr = new JMenuItem("Standard Databases");
-    fetchr.setToolTipText("Fetch from EMBL/EMBLCDS or Uniprot/PDB and any selected DAS sources");
-    fetchr.addActionListener(new ActionListener()
-    {
-
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        new Thread(new Runnable()
-        {
-
-          @Override
-          public void run()
-          {
-            new jalview.ws.DBRefFetcher(alignPanel.av
-                    .getSequenceSelection(), alignPanel.alignFrame)
-                    .fetchDBRefs(false);
-          }
-        }).start();
-
-      }
-
-    });
-    rfetch.add(fetchr);
-    final AlignFrame me = this;
-    new Thread(new Runnable()
-    {
-      @Override
-      public void run()
-      {
-        final jalview.ws.SequenceFetcher sf = SequenceFetcher
-                .getSequenceFetcherSingleton(me);
-        javax.swing.SwingUtilities.invokeLater(new Runnable()
-        {
-          @Override
-          public void run()
-          {
-            String[] dbclasses = sf.getOrderedSupportedSources();
-            // sf.getDbInstances(jalview.ws.dbsources.DasSequenceSource.class);
-            // jalview.util.QuickSort.sort(otherdb, otherdb);
-            List<DbSourceProxy> otherdb;
-            JMenu dfetch = new JMenu();
-            JMenu ifetch = new JMenu();
-            JMenuItem fetchr = null;
-            int comp = 0, icomp = 0, mcomp = 15;
-            String mname = null;
-            int dbi = 0;
-            for (String dbclass : dbclasses)
-            {
-              otherdb = sf.getSourceProxy(dbclass);
-              // add a single entry for this class, or submenu allowing 'fetch
-              // all' or pick one
-              if (otherdb == null || otherdb.size() < 1)
-              {
-                continue;
-              }
-              // List<DbSourceProxy> dbs=otherdb;
-              // otherdb=new ArrayList<DbSourceProxy>();
-              // for (DbSourceProxy db:dbs)
-              // {
-              // if (!db.isA(DBRefSource.ALIGNMENTDB)
-              // }
-              if (mname == null)
-              {
-                mname = "From " + dbclass;
-              }
-              if (otherdb.size() == 1)
-              {
-                final DbSourceProxy[] dassource = otherdb
-                        .toArray(new DbSourceProxy[0]);
-                DbSourceProxy src = otherdb.get(0);
-                fetchr = new JMenuItem(src.getDbSource());
-                fetchr.addActionListener(new ActionListener()
-                {
-
-                  @Override
-                  public void actionPerformed(ActionEvent e)
-                  {
-                    new Thread(new Runnable()
-                    {
-
-                      @Override
-                      public void run()
-                      {
-                        new jalview.ws.DBRefFetcher(alignPanel.av
-                                .getSequenceSelection(),
-                                alignPanel.alignFrame, dassource)
-                                .fetchDBRefs(false);
-                      }
-                    }).start();
-                  }
-
-                });
-                fetchr.setToolTipText("<html>"
-                        + JvSwingUtils.wrapTooltip("Retrieve from "
-                                + src.getDbName()) + "<html>");
-                dfetch.add(fetchr);
-                comp++;
-              }
-              else
-              {
-                final DbSourceProxy[] dassource = otherdb
-                        .toArray(new DbSourceProxy[0]);
-                // fetch all entry
-                DbSourceProxy src = otherdb.get(0);
-                fetchr = new JMenuItem("Fetch All '" + src.getDbSource()
-                        + "'");
-                fetchr.addActionListener(new ActionListener()
-                {
-                  @Override
-                  public void actionPerformed(ActionEvent e)
-                  {
-                    new Thread(new Runnable()
-                    {
-
-                      @Override
-                      public void run()
-                      {
-                        new jalview.ws.DBRefFetcher(alignPanel.av
-                                .getSequenceSelection(),
-                                alignPanel.alignFrame, dassource)
-                                .fetchDBRefs(false);
-                      }
-                    }).start();
-                  }
-                });
-
-                fetchr.setToolTipText("<html>"
-                        + JvSwingUtils.wrapTooltip("Retrieve from all "
-                                + otherdb.size() + " sources in "
-                                + src.getDbSource() + "<br>First is :"
-                                + src.getDbName()) + "<html>");
-                dfetch.add(fetchr);
-                comp++;
-                // and then build the rest of the individual menus
-                ifetch = new JMenu("Sources from " + src.getDbSource());
-                icomp = 0;
-                String imname = null;
-                int i = 0;
-                for (DbSourceProxy sproxy : otherdb)
-                {
-                  String dbname = sproxy.getDbName();
-                  String sname = dbname.length() > 5 ? dbname.substring(0,
-                          5) + "..." : dbname;
-                  String msname = dbname.length() > 10 ? dbname.substring(
-                          0, 10) + "..." : dbname;
-                  if (imname == null)
-                  {
-                    imname = "from '" + sname + "'";
-                  }
-                  fetchr = new JMenuItem(msname);
-                  final DbSourceProxy[] dassrc =
-                  { sproxy };
-                  fetchr.addActionListener(new ActionListener()
-                  {
-
-                    @Override
-                    public void actionPerformed(ActionEvent e)
-                    {
-                      new Thread(new Runnable()
-                      {
-
-                        @Override
-                        public void run()
-                        {
-                          new jalview.ws.DBRefFetcher(alignPanel.av
-                                  .getSequenceSelection(),
-                                  alignPanel.alignFrame, dassrc)
-                                  .fetchDBRefs(false);
-                        }
-                      }).start();
-                    }
-
-                  });
-                  fetchr.setToolTipText("<html>"
-                          + JvSwingUtils.wrapTooltip("Retrieve from "
-                                  + dbname) + "</html>");
-                  ifetch.add(fetchr);
-                  ++i;
-                  if (++icomp >= mcomp || i == (otherdb.size()))
-                  {
-                    ifetch.setText(MessageManager.formatMessage("label.source_to_target",new String[]{imname,sname}));
-                    dfetch.add(ifetch);
-                    ifetch = new JMenu();
-                    imname = null;
-                    icomp = 0;
-                    comp++;
-                  }
-                }
-              }
-              ++dbi;
-              if (comp >= mcomp || dbi >= (dbclasses.length))
-              {
-                dfetch.setText(MessageManager.formatMessage("label.source_to_target",new String[]{mname,dbclass}));
-                rfetch.add(dfetch);
-                dfetch = new JMenu();
-                mname = null;
-                comp = 0;
-              }
-            }
-          }
-        });
-      }
-    }).start();
-
-  }
-
-  /**
-   * Left justify the whole alignment.
-   */
-  @Override
-  protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)
-  {
-    AlignmentI al = viewport.getAlignment();
-    al.justify(false);
-    viewport.firePropertyChange("alignment", null, al);
-  }
-
-  /**
-   * Right justify the whole alignment.
-   */
-  @Override
-  protected void justifyRightMenuItem_actionPerformed(ActionEvent e)
-  {
-    AlignmentI al = viewport.getAlignment();
-    al.justify(true);
-    viewport.firePropertyChange("alignment", null, al);
-  }
-
-  public void setShowSeqFeatures(boolean b)
-  {
-    showSeqFeatures.setSelected(true);
-    viewport.setShowSequenceFeatures(true);
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * jalview.jbgui.GAlignFrame#showUnconservedMenuItem_actionPerformed(java.
-   * awt.event.ActionEvent)
-   */
-  @Override
-  protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
-  {
-    viewport.setShowUnconserved(showNonconservedMenuItem.getState());
-    alignPanel.paintAlignment(true);
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * jalview.jbgui.GAlignFrame#showGroupConsensus_actionPerformed(java.awt.event
-   * .ActionEvent)
-   */
-  @Override
-  protected void showGroupConsensus_actionPerformed(ActionEvent e)
-  {
-    viewport.setShowGroupConsensus(showGroupConsensus.getState());
-    alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
-
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * jalview.jbgui.GAlignFrame#showGroupConservation_actionPerformed(java.awt
-   * .event.ActionEvent)
-   */
-  @Override
-  protected void showGroupConservation_actionPerformed(ActionEvent e)
-  {
-    viewport.setShowGroupConservation(showGroupConservation.getState());
-    alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt
-   * .event.ActionEvent)
-   */
-  @Override
-  protected void showConsensusHistogram_actionPerformed(ActionEvent e)
-  {
-    viewport.setShowConsensusHistogram(showConsensusHistogram.getState());
-    alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt
-   * .event.ActionEvent)
-   */
-  @Override
-  protected void showSequenceLogo_actionPerformed(ActionEvent e)
-  {
-    viewport.setShowSequenceLogo(showSequenceLogo.getState());
-    alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
-  }
-
-  @Override
-  protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)
-  {
-    showSequenceLogo.setState(true);
-    viewport.setShowSequenceLogo(true);
-    viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState());
-    alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
-  }
-
-  @Override
-  protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e)
-  {
-    alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see
-   * jalview.jbgui.GAlignFrame#makeGrpsFromSelection_actionPerformed(java.awt
-   * .event.ActionEvent)
-   */
-  @Override
-  protected void makeGrpsFromSelection_actionPerformed(ActionEvent e)
-  {
-    if (avc.makeGroupsFromSelection()) {
-      PaintRefresher.Refresh(this, viewport.getSequenceSetId());
-      alignPanel.updateAnnotation();
-      alignPanel.paintAlignment(true);
-    }
-  }
-
-  @Override
-  protected void createGroup_actionPerformed(ActionEvent e)
-  {
-    if (avc.createGroup())
-    {
-      alignPanel.alignmentChanged();
-    }
-  }
-
-  @Override
-  protected void unGroup_actionPerformed(ActionEvent e)
-  {
-    if (avc.unGroup())
-    {
-      alignPanel.alignmentChanged();
-    }
-  }
-
-  /**
-   * make the given alignmentPanel the currently selected tab
-   * 
-   * @param alignmentPanel
-   */
-  public void setDisplayedView(AlignmentPanel alignmentPanel)
-  {
-    if (!viewport.getSequenceSetId().equals(
-            alignmentPanel.av.getSequenceSetId()))
-    {
-      throw new Error(
-              "Implementation error: cannot show a view from another alignment in an AlignFrame.");
-    }
-    if (tabbedPane != null
-            & alignPanels.indexOf(alignmentPanel) != tabbedPane
-                    .getSelectedIndex())
-    {
-      tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
-    }
-  }
-}
-
-class PrintThread extends Thread
-{
-  AlignmentPanel ap;
-
-  public PrintThread(AlignmentPanel ap)
-  {
-    this.ap = ap;
-  }
-
-  static PageFormat pf;
-
-  @Override
-  public void run()
-  {
-    PrinterJob printJob = PrinterJob.getPrinterJob();
-
-    if (pf != null)
-    {
-      printJob.setPrintable(ap, pf);
-    }
-    else
-    {
-      printJob.setPrintable(ap);
-    }
-
-    if (printJob.printDialog())
-    {
-      try
-      {
-        printJob.print();
-      } catch (Exception PrintException)
-      {
-        PrintException.printStackTrace();
-      }
-    }
-  }
-}
+/*\r
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)\r
+ * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle\r
+ * \r
+ * This file is part of Jalview.\r
+ * \r
+ * Jalview is free software: you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License \r
+ * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\r
+ *  \r
+ * Jalview is distributed in the hope that it will be useful, but \r
+ * WITHOUT ANY WARRANTY; without even the implied warranty \r
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR \r
+ * PURPOSE.  See the GNU General Public License for more details.\r
+ * \r
+ * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
+package jalview.gui;\r
+\r
+import jalview.analysis.AAFrequency;\r
+import jalview.analysis.AlignmentSorter;\r
+import jalview.analysis.Conservation;\r
+import jalview.analysis.CrossRef;\r
+import jalview.analysis.NJTree;\r
+import jalview.analysis.ParseProperties;\r
+import jalview.analysis.SequenceIdMatcher;\r
+import jalview.api.AlignViewControllerI;\r
+import jalview.bin.Cache;\r
+import jalview.commands.CommandI;\r
+import jalview.commands.EditCommand;\r
+import jalview.commands.OrderCommand;\r
+import jalview.commands.RemoveGapColCommand;\r
+import jalview.commands.RemoveGapsCommand;\r
+import jalview.commands.SlideSequencesCommand;\r
+import jalview.commands.TrimRegionCommand;\r
+import jalview.datamodel.AlignedCodonFrame;\r
+import jalview.datamodel.Alignment;\r
+import jalview.datamodel.AlignmentAnnotation;\r
+import jalview.datamodel.AlignmentI;\r
+import jalview.datamodel.AlignmentOrder;\r
+import jalview.datamodel.AlignmentView;\r
+import jalview.datamodel.ColumnSelection;\r
+import jalview.datamodel.PDBEntry;\r
+import jalview.datamodel.SeqCigar;\r
+import jalview.datamodel.Sequence;\r
+import jalview.datamodel.SequenceGroup;\r
+import jalview.datamodel.SequenceI;\r
+import jalview.io.AlignmentProperties;\r
+import jalview.io.AnnotationFile;\r
+import jalview.io.FeaturesFile;\r
+import jalview.io.FileLoader;\r
+import jalview.io.FormatAdapter;\r
+import jalview.io.HTMLOutput;\r
+import jalview.io.IdentifyFile;\r
+import jalview.io.JalviewFileChooser;\r
+import jalview.io.JalviewFileView;\r
+import jalview.io.JnetAnnotationMaker;\r
+import jalview.io.NewickFile;\r
+import jalview.io.TCoffeeScoreFile;\r
+import jalview.jbgui.GAlignFrame;\r
+import jalview.schemes.Blosum62ColourScheme;\r
+import jalview.schemes.BuriedColourScheme;\r
+import jalview.schemes.ClustalxColourScheme;\r
+import jalview.schemes.ColourSchemeI;\r
+import jalview.schemes.ColourSchemeProperty;\r
+import jalview.schemes.HelixColourScheme;\r
+import jalview.schemes.HydrophobicColourScheme;\r
+import jalview.schemes.NucleotideColourScheme;\r
+import jalview.schemes.PIDColourScheme;\r
+import jalview.schemes.PurinePyrimidineColourScheme;\r
+import jalview.schemes.RNAHelicesColourChooser;\r
+import jalview.schemes.ResidueProperties;\r
+import jalview.schemes.StrandColourScheme;\r
+import jalview.schemes.TCoffeeColourScheme;\r
+import jalview.schemes.TaylorColourScheme;\r
+import jalview.schemes.TurnColourScheme;\r
+import jalview.schemes.UserColourScheme;\r
+import jalview.schemes.ZappoColourScheme;\r
+import jalview.util.MessageManager;\r
+import jalview.ws.jws1.Discoverer;\r
+import jalview.ws.jws2.Jws2Discoverer;\r
+import jalview.ws.jws2.jabaws2.Jws2Instance;\r
+import jalview.ws.seqfetcher.DbSourceProxy;\r
+\r
+import java.awt.BorderLayout;\r
+import java.awt.Color;\r
+import java.awt.Component;\r
+import java.awt.GridLayout;\r
+import java.awt.Rectangle;\r
+import java.awt.Toolkit;\r
+import java.awt.datatransfer.Clipboard;\r
+import java.awt.datatransfer.DataFlavor;\r
+import java.awt.datatransfer.StringSelection;\r
+import java.awt.datatransfer.Transferable;\r
+import java.awt.dnd.DnDConstants;\r
+import java.awt.dnd.DropTargetDragEvent;\r
+import java.awt.dnd.DropTargetDropEvent;\r
+import java.awt.dnd.DropTargetEvent;\r
+import java.awt.dnd.DropTargetListener;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.awt.event.KeyAdapter;\r
+import java.awt.event.KeyEvent;\r
+import java.awt.event.MouseAdapter;\r
+import java.awt.event.MouseEvent;\r
+import java.awt.print.PageFormat;\r
+import java.awt.print.PrinterJob;\r
+import java.beans.PropertyChangeEvent;\r
+import java.io.File;\r
+import java.net.URL;\r
+import java.util.ArrayList;\r
+import java.util.Enumeration;\r
+import java.util.Hashtable;\r
+import java.util.List;\r
+import java.util.Vector;\r
+\r
+import javax.swing.JButton;\r
+import javax.swing.JEditorPane;\r
+import javax.swing.JInternalFrame;\r
+import javax.swing.JLabel;\r
+import javax.swing.JLayeredPane;\r
+import javax.swing.JMenu;\r
+import javax.swing.JMenuItem;\r
+import javax.swing.JOptionPane;\r
+import javax.swing.JPanel;\r
+import javax.swing.JProgressBar;\r
+import javax.swing.JRadioButtonMenuItem;\r
+import javax.swing.JScrollPane;\r
+import javax.swing.SwingUtilities;\r
+\r
+/**\r
+ * DOCUMENT ME!\r
+ * \r
+ * @author $author$\r
+ * @version $Revision$\r
+ */\r
+public class AlignFrame extends GAlignFrame implements DropTargetListener,\r
+        IProgressIndicator\r
+{\r
+\r
+  /** DOCUMENT ME!! */\r
+  public static final int DEFAULT_WIDTH = 700;\r
+\r
+  /** DOCUMENT ME!! */\r
+  public static final int DEFAULT_HEIGHT = 500;\r
+\r
+  public AlignmentPanel alignPanel;\r
+\r
+  AlignViewport viewport;\r
\r
+  public AlignViewControllerI avc;\r
\r
+\r
+  Vector alignPanels = new Vector();\r
+\r
+  /**\r
+   * Last format used to load or save alignments in this window\r
+   */\r
+  String currentFileFormat = null;\r
+\r
+  /**\r
+   * Current filename for this alignment\r
+   */\r
+  String fileName = null;\r
+\r
+  /**\r
+   * Creates a new AlignFrame object with specific width and height.\r
+   * \r
+   * @param al\r
+   * @param width\r
+   * @param height\r
+   */\r
+  public AlignFrame(AlignmentI al, int width, int height)\r
+  {\r
+    this(al, null, width, height);\r
+  }\r
+\r
+  /**\r
+   * Creates a new AlignFrame object with specific width, height and\r
+   * sequenceSetId\r
+   * \r
+   * @param al\r
+   * @param width\r
+   * @param height\r
+   * @param sequenceSetId\r
+   */\r
+  public AlignFrame(AlignmentI al, int width, int height,\r
+          String sequenceSetId)\r
+  {\r
+    this(al, null, width, height, sequenceSetId);\r
+  }\r
+\r
+  /**\r
+   * Creates a new AlignFrame object with specific width, height and\r
+   * sequenceSetId\r
+   * \r
+   * @param al\r
+   * @param width\r
+   * @param height\r
+   * @param sequenceSetId\r
+   * @param viewId\r
+   */\r
+  public AlignFrame(AlignmentI al, int width, int height,\r
+          String sequenceSetId, String viewId)\r
+  {\r
+    this(al, null, width, height, sequenceSetId, viewId);\r
+  }\r
+\r
+  /**\r
+   * new alignment window with hidden columns\r
+   * \r
+   * @param al\r
+   *          AlignmentI\r
+   * @param hiddenColumns\r
+   *          ColumnSelection or null\r
+   * @param width\r
+   *          Width of alignment frame\r
+   * @param height\r
+   *          height of frame.\r
+   */\r
+  public AlignFrame(AlignmentI al, ColumnSelection hiddenColumns,\r
+          int width, int height)\r
+  {\r
+    this(al, hiddenColumns, width, height, null);\r
+  }\r
+\r
+  /**\r
+   * Create alignment frame for al with hiddenColumns, a specific width and\r
+   * height, and specific sequenceId\r
+   * \r
+   * @param al\r
+   * @param hiddenColumns\r
+   * @param width\r
+   * @param height\r
+   * @param sequenceSetId\r
+   *          (may be null)\r
+   */\r
+  public AlignFrame(AlignmentI al, ColumnSelection hiddenColumns,\r
+          int width, int height, String sequenceSetId)\r
+  {\r
+    this(al, hiddenColumns, width, height, sequenceSetId, null);\r
+  }\r
+\r
+  /**\r
+   * Create alignment frame for al with hiddenColumns, a specific width and\r
+   * height, and specific sequenceId\r
+   * \r
+   * @param al\r
+   * @param hiddenColumns\r
+   * @param width\r
+   * @param height\r
+   * @param sequenceSetId\r
+   *          (may be null)\r
+   * @param viewId\r
+   *          (may be null)\r
+   */\r
+  public AlignFrame(AlignmentI al, ColumnSelection hiddenColumns,\r
+          int width, int height, String sequenceSetId, String viewId)\r
+  {\r
+    setSize(width, height);\r
+    viewport = new AlignViewport(al, hiddenColumns, sequenceSetId, viewId);\r
+\r
+    alignPanel = new AlignmentPanel(this, viewport);\r
+\r
+    if (al.getDataset() == null)\r
+    {\r
+      al.setDataset(null);\r
+    }\r
+\r
+    addAlignmentPanel(alignPanel, true);\r
+    init();\r
+  }\r
+\r
+  /**\r
+   * Make a new AlignFrame from exisiting alignmentPanels\r
+   * \r
+   * @param ap\r
+   *          AlignmentPanel\r
+   * @param av\r
+   *          AlignViewport\r
+   */\r
+  public AlignFrame(AlignmentPanel ap)\r
+  {\r
+    viewport = ap.av;\r
+    alignPanel = ap;\r
+    addAlignmentPanel(ap, false);\r
+    init();\r
+  }\r
+\r
+  /**\r
+   * initalise the alignframe from the underlying viewport data and the\r
+   * configurations\r
+   */\r
+  void init()\r
+  {\r
+    avc = new jalview.controller.AlignViewController(viewport, alignPanel);\r
+    if (viewport.getAlignmentConservationAnnotation() == null)\r
+    {\r
+      BLOSUM62Colour.setEnabled(false);\r
+      conservationMenuItem.setEnabled(false);\r
+      modifyConservation.setEnabled(false);\r
+      // PIDColour.setEnabled(false);\r
+      // abovePIDThreshold.setEnabled(false);\r
+      // modifyPID.setEnabled(false);\r
+    }\r
+\r
+    String sortby = jalview.bin.Cache.getDefault("SORT_ALIGNMENT",\r
+            "No sort");\r
+\r
+    if (sortby.equals("Id"))\r
+    {\r
+      sortIDMenuItem_actionPerformed(null);\r
+    }\r
+    else if (sortby.equals("Pairwise Identity"))\r
+    {\r
+      sortPairwiseMenuItem_actionPerformed(null);\r
+    }\r
+\r
+    if (Desktop.desktop != null)\r
+    {\r
+      this.setDropTarget(new java.awt.dnd.DropTarget(this, this));\r
+      addServiceListeners();\r
+      setGUINucleotide(viewport.getAlignment().isNucleotide());\r
+    }\r
+\r
+    setMenusFromViewport(viewport);\r
+    buildSortByAnnotationScoresMenu();\r
+    if (viewport.wrapAlignment)\r
+    {\r
+      wrapMenuItem_actionPerformed(null);\r
+    }\r
+\r
+    if (jalview.bin.Cache.getDefault("SHOW_OVERVIEW", false))\r
+    {\r
+      this.overviewMenuItem_actionPerformed(null);\r
+    }\r
+\r
+    addKeyListener();\r
+    \r
+  }\r
+\r
+  /**\r
+   * Change the filename and format for the alignment, and enable the 'reload'\r
+   * button functionality.\r
+   * \r
+   * @param file\r
+   *          valid filename\r
+   * @param format\r
+   *          format of file\r
+   */\r
+  public void setFileName(String file, String format)\r
+  {\r
+    fileName = file;\r
+    currentFileFormat = format;\r
+    reload.setEnabled(true);\r
+  }\r
+\r
+  void addKeyListener()\r
+  {\r
+    addKeyListener(new KeyAdapter()\r
+    {\r
+      @Override\r
+      public void keyPressed(KeyEvent evt)\r
+      {\r
+        if (viewport.cursorMode\r
+                && ((evt.getKeyCode() >= KeyEvent.VK_0 && evt.getKeyCode() <= KeyEvent.VK_9) || (evt\r
+                        .getKeyCode() >= KeyEvent.VK_NUMPAD0 && evt\r
+                        .getKeyCode() <= KeyEvent.VK_NUMPAD9))\r
+                && Character.isDigit(evt.getKeyChar()))\r
+          alignPanel.seqPanel.numberPressed(evt.getKeyChar());\r
+\r
+        switch (evt.getKeyCode())\r
+        {\r
+\r
+        case 27: // escape key\r
+          deselectAllSequenceMenuItem_actionPerformed(null);\r
+\r
+          break;\r
+\r
+        case KeyEvent.VK_DOWN:\r
+          if (evt.isAltDown() || !viewport.cursorMode)\r
+            moveSelectedSequences(false);\r
+          if (viewport.cursorMode)\r
+            alignPanel.seqPanel.moveCursor(0, 1);\r
+          break;\r
+\r
+        case KeyEvent.VK_UP:\r
+          if (evt.isAltDown() || !viewport.cursorMode)\r
+            moveSelectedSequences(true);\r
+          if (viewport.cursorMode)\r
+            alignPanel.seqPanel.moveCursor(0, -1);\r
+\r
+          break;\r
+\r
+        case KeyEvent.VK_LEFT:\r
+          if (evt.isAltDown() || !viewport.cursorMode)\r
+            slideSequences(false, alignPanel.seqPanel.getKeyboardNo1());\r
+          else\r
+            alignPanel.seqPanel.moveCursor(-1, 0);\r
+\r
+          break;\r
+\r
+        case KeyEvent.VK_RIGHT:\r
+          if (evt.isAltDown() || !viewport.cursorMode)\r
+            slideSequences(true, alignPanel.seqPanel.getKeyboardNo1());\r
+          else\r
+            alignPanel.seqPanel.moveCursor(1, 0);\r
+          break;\r
+\r
+        case KeyEvent.VK_SPACE:\r
+          if (viewport.cursorMode)\r
+          {\r
+            alignPanel.seqPanel.insertGapAtCursor(evt.isControlDown()\r
+                    || evt.isShiftDown() || evt.isAltDown());\r
+          }\r
+          break;\r
+\r
+        // case KeyEvent.VK_A:\r
+        // if (viewport.cursorMode)\r
+        // {\r
+        // alignPanel.seqPanel.insertNucAtCursor(false,"A");\r
+        // //System.out.println("A");\r
+        // }\r
+        // break;\r
+        /*\r
+         * case KeyEvent.VK_CLOSE_BRACKET: if (viewport.cursorMode) {\r
+         * System.out.println("closing bracket"); } break;\r
+         */\r
+        case KeyEvent.VK_DELETE:\r
+        case KeyEvent.VK_BACK_SPACE:\r
+          if (!viewport.cursorMode)\r
+          {\r
+            cut_actionPerformed(null);\r
+          }\r
+          else\r
+          {\r
+            alignPanel.seqPanel.deleteGapAtCursor(evt.isControlDown()\r
+                    || evt.isShiftDown() || evt.isAltDown());\r
+          }\r
+\r
+          break;\r
+\r
+        case KeyEvent.VK_S:\r
+          if (viewport.cursorMode)\r
+          {\r
+            alignPanel.seqPanel.setCursorRow();\r
+          }\r
+          break;\r
+        case KeyEvent.VK_C:\r
+          if (viewport.cursorMode && !evt.isControlDown())\r
+          {\r
+            alignPanel.seqPanel.setCursorColumn();\r
+          }\r
+          break;\r
+        case KeyEvent.VK_P:\r
+          if (viewport.cursorMode)\r
+          {\r
+            alignPanel.seqPanel.setCursorPosition();\r
+          }\r
+          break;\r
+\r
+        case KeyEvent.VK_ENTER:\r
+        case KeyEvent.VK_COMMA:\r
+          if (viewport.cursorMode)\r
+          {\r
+            alignPanel.seqPanel.setCursorRowAndColumn();\r
+          }\r
+          break;\r
+\r
+        case KeyEvent.VK_Q:\r
+          if (viewport.cursorMode)\r
+          {\r
+            alignPanel.seqPanel.setSelectionAreaAtCursor(true);\r
+          }\r
+          break;\r
+        case KeyEvent.VK_M:\r
+          if (viewport.cursorMode)\r
+          {\r
+            alignPanel.seqPanel.setSelectionAreaAtCursor(false);\r
+          }\r
+          break;\r
+\r
+        case KeyEvent.VK_F2:\r
+          viewport.cursorMode = !viewport.cursorMode;\r
+          statusBar.setText(MessageManager.formatMessage("label.keyboard_editing_mode", new String[]{(viewport.cursorMode ? "on" : "off")}));\r
+          if (viewport.cursorMode)\r
+          {\r
+            alignPanel.seqPanel.seqCanvas.cursorX = viewport.startRes;\r
+            alignPanel.seqPanel.seqCanvas.cursorY = viewport.startSeq;\r
+          }\r
+          alignPanel.seqPanel.seqCanvas.repaint();\r
+          break;\r
+\r
+        case KeyEvent.VK_F1:\r
+          try\r
+          {\r
+            ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();\r
+            java.net.URL url = javax.help.HelpSet.findHelpSet(cl,\r
+                    "help/help");\r
+            javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);\r
+\r
+            javax.help.HelpBroker hb = hs.createHelpBroker();\r
+            hb.setCurrentID("home");\r
+            hb.setDisplayed(true);\r
+          } catch (Exception ex)\r
+          {\r
+            ex.printStackTrace();\r
+          }\r
+          break;\r
+        case KeyEvent.VK_H:\r
+        {\r
+          boolean toggleSeqs = !evt.isControlDown();\r
+          boolean toggleCols = !evt.isShiftDown();\r
+          toggleHiddenRegions(toggleSeqs, toggleCols);\r
+          break;\r
+        }\r
+        case KeyEvent.VK_PAGE_UP:\r
+          if (viewport.wrapAlignment)\r
+          {\r
+            alignPanel.scrollUp(true);\r
+          }\r
+          else\r
+          {\r
+            alignPanel.setScrollValues(viewport.startRes, viewport.startSeq\r
+                    - viewport.endSeq + viewport.startSeq);\r
+          }\r
+          break;\r
+        case KeyEvent.VK_PAGE_DOWN:\r
+          if (viewport.wrapAlignment)\r
+          {\r
+            alignPanel.scrollUp(false);\r
+          }\r
+          else\r
+          {\r
+            alignPanel.setScrollValues(viewport.startRes, viewport.startSeq\r
+                    + viewport.endSeq - viewport.startSeq);\r
+          }\r
+          break;\r
+        }\r
+      }\r
+\r
+      @Override\r
+      public void keyReleased(KeyEvent evt)\r
+      {\r
+        switch (evt.getKeyCode())\r
+        {\r
+        case KeyEvent.VK_LEFT:\r
+          if (evt.isAltDown() || !viewport.cursorMode)\r
+            viewport.firePropertyChange("alignment", null, viewport\r
+                    .getAlignment().getSequences());\r
+          break;\r
+\r
+        case KeyEvent.VK_RIGHT:\r
+          if (evt.isAltDown() || !viewport.cursorMode)\r
+            viewport.firePropertyChange("alignment", null, viewport\r
+                    .getAlignment().getSequences());\r
+          break;\r
+        }\r
+      }\r
+    });\r
+  }\r
+\r
+  public void addAlignmentPanel(final AlignmentPanel ap, boolean newPanel)\r
+  {\r
+    ap.alignFrame = this;\r
+    avc = new jalview.controller.AlignViewController(viewport, alignPanel);\r
+\r
+    alignPanels.addElement(ap);\r
+\r
+    PaintRefresher.Register(ap, ap.av.getSequenceSetId());\r
+\r
+    int aSize = alignPanels.size();\r
+\r
+    tabbedPane.setVisible(aSize > 1 || ap.av.viewName != null);\r
+\r
+    if (aSize == 1 && ap.av.viewName == null)\r
+    {\r
+      this.getContentPane().add(ap, BorderLayout.CENTER);\r
+    }\r
+    else\r
+    {\r
+      if (aSize == 2)\r
+      {\r
+        setInitialTabVisible();\r
+      }\r
+\r
+      expandViews.setEnabled(true);\r
+      gatherViews.setEnabled(true);\r
+      tabbedPane.addTab(ap.av.viewName, ap);\r
+\r
+      ap.setVisible(false);\r
+    }\r
+\r
+    if (newPanel)\r
+    {\r
+      if (ap.av.isPadGaps())\r
+      {\r
+        ap.av.getAlignment().padGaps();\r
+      }\r
+      ap.av.updateConservation(ap);\r
+      ap.av.updateConsensus(ap);\r
+      ap.av.updateStrucConsensus(ap);\r
+    }\r
+  }\r
+\r
+  public void setInitialTabVisible()\r
+  {\r
+    expandViews.setEnabled(true);\r
+    gatherViews.setEnabled(true);\r
+    tabbedPane.setVisible(true);\r
+    AlignmentPanel first = (AlignmentPanel) alignPanels.firstElement();\r
+    tabbedPane.addTab(first.av.viewName, first);\r
+    this.getContentPane().add(tabbedPane, BorderLayout.CENTER);\r
+  }\r
+\r
+  public AlignViewport getViewport()\r
+  {\r
+    return viewport;\r
+  }\r
+\r
+  /* Set up intrinsic listeners for dynamically generated GUI bits. */\r
+  private void addServiceListeners()\r
+  {\r
+    final java.beans.PropertyChangeListener thisListener;\r
+    Desktop.instance.addJalviewPropertyChangeListener("services",\r
+            thisListener = new java.beans.PropertyChangeListener()\r
+            {\r
+              @Override\r
+              public void propertyChange(PropertyChangeEvent evt)\r
+              {\r
+                // // System.out.println("Discoverer property change.");\r
+                // if (evt.getPropertyName().equals("services"))\r
+                {\r
+                  SwingUtilities.invokeLater(new Runnable()\r
+                  {\r
+\r
+                    @Override\r
+                    public void run()\r
+                    {\r
+                      System.err\r
+                              .println("Rebuild WS Menu for service change");\r
+                      BuildWebServiceMenu();\r
+                    }\r
+\r
+                  });\r
+                }\r
+              }\r
+            });\r
+    addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()\r
+    {\r
+      @Override\r
+      public void internalFrameClosed(\r
+              javax.swing.event.InternalFrameEvent evt)\r
+      {\r
+        System.out.println("deregistering discoverer listener");\r
+        Desktop.instance.removeJalviewPropertyChangeListener("services",\r
+                thisListener);\r
+        closeMenuItem_actionPerformed(true);\r
+      };\r
+    });\r
+    // Finally, build the menu once to get current service state\r
+    new Thread(new Runnable()\r
+    {\r
+      @Override\r
+      public void run()\r
+      {\r
+        BuildWebServiceMenu();\r
+      }\r
+    }).start();\r
+  }\r
+\r
+  public void setGUINucleotide(boolean nucleotide)\r
+  {\r
+    showTranslation.setVisible(nucleotide);\r
+    conservationMenuItem.setEnabled(!nucleotide);\r
+    modifyConservation.setEnabled(!nucleotide);\r
+    showGroupConservation.setEnabled(!nucleotide);\r
+    rnahelicesColour.setEnabled(nucleotide);\r
+    purinePyrimidineColour.setEnabled(nucleotide);\r
+    // Remember AlignFrame always starts as protein\r
+    // if (!nucleotide)\r
+    // {\r
+    // showTr\r
+    // calculateMenu.remove(calculateMenu.getItemCount() - 2);\r
+    // }\r
+  }\r
+\r
+  /**\r
+   * set up menus for the currently viewport. This may be called after any\r
+   * operation that affects the data in the current view (selection changed,\r
+   * etc) to update the menus to reflect the new state.\r
+   */\r
+  public void setMenusForViewport()\r
+  {\r
+    setMenusFromViewport(viewport);\r
+  }\r
+\r
+  /**\r
+   * Need to call this method when tabs are selected for multiple views, or when\r
+   * loading from Jalview2XML.java\r
+   * \r
+   * @param av\r
+   *          AlignViewport\r
+   */\r
+  void setMenusFromViewport(AlignViewport av)\r
+  {\r
+    padGapsMenuitem.setSelected(av.isPadGaps());\r
+    colourTextMenuItem.setSelected(av.showColourText);\r
+    abovePIDThreshold.setSelected(av.getAbovePIDThreshold());\r
+    conservationMenuItem.setSelected(av.getConservationSelected());\r
+    seqLimits.setSelected(av.getShowJVSuffix());\r
+    idRightAlign.setSelected(av.rightAlignIds);\r
+    centreColumnLabelsMenuItem.setState(av.centreColumnLabels);\r
+    renderGapsMenuItem.setSelected(av.renderGaps);\r
+    wrapMenuItem.setSelected(av.wrapAlignment);\r
+    scaleAbove.setVisible(av.wrapAlignment);\r
+    scaleLeft.setVisible(av.wrapAlignment);\r
+    scaleRight.setVisible(av.wrapAlignment);\r
+    annotationPanelMenuItem.setState(av.showAnnotation);\r
+    viewBoxesMenuItem.setSelected(av.showBoxes);\r
+    viewTextMenuItem.setSelected(av.showText);\r
+    showNonconservedMenuItem.setSelected(av.getShowUnconserved());\r
+    showGroupConsensus.setSelected(av.isShowGroupConsensus());\r
+    showGroupConservation.setSelected(av.isShowGroupConservation());\r
+    showConsensusHistogram.setSelected(av.isShowConsensusHistogram());\r
+    showSequenceLogo.setSelected(av.isShowSequenceLogo());\r
+    normaliseSequenceLogo.setSelected(av.isNormaliseSequenceLogo());\r
+\r
+    setColourSelected(ColourSchemeProperty.getColourName(av\r
+            .getGlobalColourScheme()));\r
+\r
+    showSeqFeatures.setSelected(av.showSequenceFeatures);\r
+    hiddenMarkers.setState(av.showHiddenMarkers);\r
+    applyToAllGroups.setState(av.getColourAppliesToAllGroups());\r
+    showNpFeatsMenuitem.setSelected(av.isShowNpFeats());\r
+    showDbRefsMenuitem.setSelected(av.isShowDbRefs());\r
+    autoCalculate.setSelected(av.autoCalculateConsensus);\r
+    sortByTree.setSelected(av.sortByTree);\r
+    listenToViewSelections.setSelected(av.followSelection);\r
+    rnahelicesColour.setEnabled(av.getAlignment().hasRNAStructure());\r
+    rnahelicesColour\r
+            .setSelected(av.getGlobalColourScheme() instanceof jalview.schemes.RNAHelicesColour);\r
+    setShowProductsEnabled();\r
+    updateEditMenuBar();\r
+  }\r
+\r
+  // methods for implementing IProgressIndicator\r
+  // need to refactor to a reusable stub class\r
+  Hashtable progressBars, progressBarHandlers;\r
+\r
+  /*\r
+   * (non-Javadoc)\r
+   * \r
+   * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)\r
+   */\r
+  @Override\r
+  public void setProgressBar(String message, long id)\r
+  {\r
+    if (progressBars == null)\r
+    {\r
+      progressBars = new Hashtable();\r
+      progressBarHandlers = new Hashtable();\r
+    }\r
+\r
+    JPanel progressPanel;\r
+    Long lId = new Long(id);\r
+    GridLayout layout = (GridLayout) statusPanel.getLayout();\r
+    if (progressBars.get(lId) != null)\r
+    {\r
+      progressPanel = (JPanel) progressBars.get(new Long(id));\r
+      statusPanel.remove(progressPanel);\r
+      progressBars.remove(lId);\r
+      progressPanel = null;\r
+      if (message != null)\r
+      {\r
+        statusBar.setText(message);\r
+      }\r
+      if (progressBarHandlers.contains(lId))\r
+      {\r
+        progressBarHandlers.remove(lId);\r
+      }\r
+      layout.setRows(layout.getRows() - 1);\r
+    }\r
+    else\r
+    {\r
+      progressPanel = new JPanel(new BorderLayout(10, 5));\r
+\r
+      JProgressBar progressBar = new JProgressBar();\r
+      progressBar.setIndeterminate(true);\r
+\r
+      progressPanel.add(new JLabel(message), BorderLayout.WEST);\r
+      progressPanel.add(progressBar, BorderLayout.CENTER);\r
+\r
+      layout.setRows(layout.getRows() + 1);\r
+      statusPanel.add(progressPanel);\r
+\r
+      progressBars.put(lId, progressPanel);\r
+    }\r
+    // update GUI\r
+    // setMenusForViewport();\r
+    validate();\r
+  }\r
+\r
+  @Override\r
+  public void registerHandler(final long id,\r
+          final IProgressIndicatorHandler handler)\r
+  {\r
+    if (progressBarHandlers == null || !progressBars.contains(new Long(id)))\r
+    {\r
+      throw new Error(\r
+              "call setProgressBar before registering the progress bar's handler.");\r
+    }\r
+    progressBarHandlers.put(new Long(id), handler);\r
+    final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));\r
+    if (handler.canCancel())\r
+    {\r
+      JButton cancel = new JButton(MessageManager.getString("action.cancel"));\r
+      final IProgressIndicator us = this;\r
+      cancel.addActionListener(new ActionListener()\r
+      {\r
+\r
+        @Override\r
+        public void actionPerformed(ActionEvent e)\r
+        {\r
+          handler.cancelActivity(id);\r
+          us.setProgressBar(\r
+                  "Cancelled "\r
+                          + ((JLabel) progressPanel.getComponent(0))\r
+                                  .getText(), id);\r
+        }\r
+      });\r
+      progressPanel.add(cancel, BorderLayout.EAST);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * \r
+   * @return true if any progress bars are still active\r
+   */\r
+  @Override\r
+  public boolean operationInProgress()\r
+  {\r
+    if (progressBars != null && progressBars.size() > 0)\r
+    {\r
+      return true;\r
+    }\r
+    return false;\r
+  }\r
+\r
+  /*\r
+   * Added so Castor Mapping file can obtain Jalview Version\r
+   */\r
+  public String getVersion()\r
+  {\r
+    return jalview.bin.Cache.getProperty("VERSION");\r
+  }\r
+\r
+  public FeatureRenderer getFeatureRenderer()\r
+  {\r
+    return alignPanel.seqPanel.seqCanvas.getFeatureRenderer();\r
+  }\r
+\r
+  @Override\r
+  public void fetchSequence_actionPerformed(ActionEvent e)\r
+  {\r
+    new SequenceFetcher(this);\r
+  }\r
+\r
+  @Override\r
+  public void addFromFile_actionPerformed(ActionEvent e)\r
+  {\r
+    Desktop.instance.inputLocalFileMenuItem_actionPerformed(viewport);\r
+  }\r
+\r
+  @Override\r
+  public void reload_actionPerformed(ActionEvent e)\r
+  {\r
+    if (fileName != null)\r
+    {\r
+      // TODO: JAL-1108 - ensure all associated frames are closed regardless of\r
+      // originating file's format\r
+      // TODO: work out how to recover feature settings for correct view(s) when\r
+      // file is reloaded.\r
+      if (currentFileFormat.equals("Jalview"))\r
+      {\r
+        JInternalFrame[] frames = Desktop.desktop.getAllFrames();\r
+        for (int i = 0; i < frames.length; i++)\r
+        {\r
+          if (frames[i] instanceof AlignFrame && frames[i] != this\r
+                  && ((AlignFrame) frames[i]).fileName != null\r
+                  && ((AlignFrame) frames[i]).fileName.equals(fileName))\r
+          {\r
+            try\r
+            {\r
+              frames[i].setSelected(true);\r
+              Desktop.instance.closeAssociatedWindows();\r
+            } catch (java.beans.PropertyVetoException ex)\r
+            {\r
+            }\r
+          }\r
+\r
+        }\r
+        Desktop.instance.closeAssociatedWindows();\r
+\r
+        FileLoader loader = new FileLoader();\r
+        String protocol = fileName.startsWith("http:") ? "URL" : "File";\r
+        loader.LoadFile(viewport, fileName, protocol, currentFileFormat);\r
+      }\r
+      else\r
+      {\r
+        Rectangle bounds = this.getBounds();\r
+\r
+        FileLoader loader = new FileLoader();\r
+        String protocol = fileName.startsWith("http:") ? "URL" : "File";\r
+        AlignFrame newframe = loader.LoadFileWaitTillLoaded(fileName,\r
+                protocol, currentFileFormat);\r
+\r
+        newframe.setBounds(bounds);\r
+        if (featureSettings != null && featureSettings.isShowing())\r
+        {\r
+          final Rectangle fspos = featureSettings.frame.getBounds();\r
+          // TODO: need a 'show feature settings' function that takes bounds -\r
+          // need to refactor Desktop.addFrame\r
+          newframe.featureSettings_actionPerformed(null);\r
+          final FeatureSettings nfs = newframe.featureSettings;\r
+          SwingUtilities.invokeLater(new Runnable()\r
+          {\r
+            @Override\r
+            public void run()\r
+            {\r
+              nfs.frame.setBounds(fspos);\r
+            }\r
+          });\r
+          this.featureSettings.close();\r
+          this.featureSettings = null;\r
+        }\r
+        this.closeMenuItem_actionPerformed(true);\r
+      }\r
+    }\r
+  }\r
+\r
+  @Override\r
+  public void addFromText_actionPerformed(ActionEvent e)\r
+  {\r
+    Desktop.instance.inputTextboxMenuItem_actionPerformed(viewport);\r
+  }\r
+\r
+  @Override\r
+  public void addFromURL_actionPerformed(ActionEvent e)\r
+  {\r
+    Desktop.instance.inputURLMenuItem_actionPerformed(viewport);\r
+  }\r
+\r
+  @Override\r
+  public void save_actionPerformed(ActionEvent e)\r
+  {\r
+    if (fileName == null\r
+            || (currentFileFormat == null || !jalview.io.FormatAdapter\r
+                    .isValidIOFormat(currentFileFormat, true))\r
+            || fileName.startsWith("http"))\r
+    {\r
+      saveAs_actionPerformed(null);\r
+    }\r
+    else\r
+    {\r
+      saveAlignment(fileName, currentFileFormat);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void saveAs_actionPerformed(ActionEvent e)\r
+  {\r
+    JalviewFileChooser chooser = new JalviewFileChooser(\r
+            jalview.bin.Cache.getProperty("LAST_DIRECTORY"),\r
+            jalview.io.AppletFormatAdapter.WRITABLE_EXTENSIONS,\r
+            jalview.io.AppletFormatAdapter.WRITABLE_FNAMES,\r
+            currentFileFormat, false);\r
+\r
+    chooser.setFileView(new JalviewFileView());\r
+    chooser.setDialogTitle("Save Alignment to file");\r
+    chooser.setToolTipText(MessageManager.getString("action.save"));\r
+\r
+    int value = chooser.showSaveDialog(this);\r
+\r
+    if (value == JalviewFileChooser.APPROVE_OPTION)\r
+    {\r
+      currentFileFormat = chooser.getSelectedFormat();\r
+      if (currentFileFormat == null)\r
+      {\r
+        JOptionPane.showInternalMessageDialog(Desktop.desktop,\r
+                MessageManager.getString("label.select_file_format_before_saving"),\r
+                MessageManager.getString("label.file_format_not_specified"), JOptionPane.WARNING_MESSAGE);\r
+        value = chooser.showSaveDialog(this);\r
+        return;\r
+      }\r
+\r
+      fileName = chooser.getSelectedFile().getPath();\r
+\r
+      jalview.bin.Cache.setProperty("DEFAULT_FILE_FORMAT",\r
+              currentFileFormat);\r
+\r
+      jalview.bin.Cache.setProperty("LAST_DIRECTORY", fileName);\r
+      if (currentFileFormat.indexOf(" ") > -1)\r
+      {\r
+        currentFileFormat = currentFileFormat.substring(0,\r
+                currentFileFormat.indexOf(" "));\r
+      }\r
+      saveAlignment(fileName, currentFileFormat);\r
+    }\r
+  }\r
+\r
+  public boolean saveAlignment(String file, String format)\r
+  {\r
+    boolean success = true;\r
+\r
+    if (format.equalsIgnoreCase("Jalview"))\r
+    {\r
+      String shortName = title;\r
+\r
+      if (shortName.indexOf(java.io.File.separatorChar) > -1)\r
+      {\r
+        shortName = shortName.substring(shortName\r
+                .lastIndexOf(java.io.File.separatorChar) + 1);\r
+      }\r
+\r
+      success = new Jalview2XML().SaveAlignment(this, file, shortName);\r
+\r
+      statusBar.setText(MessageManager.formatMessage("label.successfully_saved_to_file_in_format",new String[]{fileName, format}));\r
+\r
+\r
+    }\r
+    else\r
+    {\r
+      if (!jalview.io.AppletFormatAdapter.isValidFormat(format, true))\r
+      {\r
+        warningMessage("Cannot save file " + fileName + " using format "\r
+                + format, "Alignment output format not supported");\r
+        saveAs_actionPerformed(null);\r
+        // JBPNote need to have a raise_gui flag here\r
+        return false;\r
+      }\r
+\r
+      String[] omitHidden = null;\r
+\r
+      if (viewport.hasHiddenColumns())\r
+      {\r
+        int reply = JOptionPane\r
+                .showInternalConfirmDialog(\r
+                        Desktop.desktop,\r
+                        MessageManager.getString("label.alignment_contains_hidden_columns"),\r
+                        MessageManager.getString("action.save_omit_hidden_columns"),\r
+                        JOptionPane.YES_NO_OPTION,\r
+                        JOptionPane.QUESTION_MESSAGE);\r
+\r
+        if (reply == JOptionPane.YES_OPTION)\r
+        {\r
+          omitHidden = viewport.getViewAsString(false);\r
+        }\r
+      }\r
+      FormatAdapter f = new FormatAdapter();\r
+      String output = f.formatSequences(format,\r
+              viewport.getAlignment(), // class cast exceptions will\r
+              // occur in the distant future\r
+              omitHidden, f.getCacheSuffixDefault(format),\r
+              viewport.getColumnSelection());\r
+\r
+      if (output == null)\r
+      {\r
+        success = false;\r
+      }\r
+      else\r
+      {\r
+        try\r
+        {\r
+          java.io.PrintWriter out = new java.io.PrintWriter(\r
+                  new java.io.FileWriter(file));\r
+\r
+          out.print(output);\r
+          out.close();\r
+          this.setTitle(file);\r
+          statusBar.setText(MessageManager.formatMessage("label.successfully_saved_to_file_in_format",new String[]{fileName, format}));\r
+        } catch (Exception ex)\r
+        {\r
+          success = false;\r
+          ex.printStackTrace();\r
+        }\r
+      }\r
+    }\r
+\r
+    if (!success)\r
+    {\r
+      JOptionPane.showInternalMessageDialog(this, MessageManager.formatMessage("label.couldnt_save_file", new String[]{fileName}),\r
+              MessageManager.getString("label.error_saving_file"), JOptionPane.WARNING_MESSAGE);\r
+    }\r
+\r
+    return success;\r
+  }\r
+\r
+  private void warningMessage(String warning, String title)\r
+  {\r
+    if (new jalview.util.Platform().isHeadless())\r
+    {\r
+      System.err.println("Warning: " + title + "\nWarning: " + warning);\r
+\r
+    }\r
+    else\r
+    {\r
+      JOptionPane.showInternalMessageDialog(this, warning, title,\r
+              JOptionPane.WARNING_MESSAGE);\r
+    }\r
+    return;\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void outputText_actionPerformed(ActionEvent e)\r
+  {\r
+    String[] omitHidden = null;\r
+\r
+    if (viewport.hasHiddenColumns())\r
+    {\r
+      int reply = JOptionPane\r
+              .showInternalConfirmDialog(\r
+                      Desktop.desktop,\r
+                      MessageManager.getString("label.alignment_contains_hidden_columns"),\r
+                      MessageManager.getString("action.save_omit_hidden_columns"),\r
+                      JOptionPane.YES_NO_OPTION,\r
+                      JOptionPane.QUESTION_MESSAGE);\r
+\r
+      if (reply == JOptionPane.YES_OPTION)\r
+      {\r
+        omitHidden = viewport.getViewAsString(false);\r
+      }\r
+    }\r
+\r
+    CutAndPasteTransfer cap = new CutAndPasteTransfer();\r
+    cap.setForInput(null);\r
+\r
+    try\r
+    {\r
+      cap.setText(new FormatAdapter().formatSequences(e.getActionCommand(),\r
+              viewport.getAlignment(), omitHidden,\r
+              viewport.getColumnSelection()));\r
+      Desktop.addInternalFrame(cap,\r
+              MessageManager.formatMessage("label.alignment_output_command", new String[]{e.getActionCommand()}), 600, 500);\r
+    } catch (OutOfMemoryError oom)\r
+    {\r
+      new OOMWarning("Outputting alignment as " + e.getActionCommand(), oom);\r
+      cap.dispose();\r
+    }\r
+\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void htmlMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    new HTMLOutput(alignPanel,\r
+            alignPanel.seqPanel.seqCanvas.getSequenceRenderer(),\r
+            alignPanel.seqPanel.seqCanvas.getFeatureRenderer());\r
+  }\r
+\r
+  public void createImageMap(File file, String image)\r
+  {\r
+    alignPanel.makePNGImageMap(file, image);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void createPNG(File f)\r
+  {\r
+    alignPanel.makePNG(f);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void createEPS(File f)\r
+  {\r
+    alignPanel.makeEPS(f);\r
+  }\r
+\r
+  @Override\r
+  public void pageSetup_actionPerformed(ActionEvent e)\r
+  {\r
+    PrinterJob printJob = PrinterJob.getPrinterJob();\r
+    PrintThread.pf = printJob.pageDialog(printJob.defaultPage());\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void printMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    // Putting in a thread avoids Swing painting problems\r
+    PrintThread thread = new PrintThread(alignPanel);\r
+    thread.start();\r
+  }\r
+\r
+  @Override\r
+  public void exportFeatures_actionPerformed(ActionEvent e)\r
+  {\r
+    new AnnotationExporter().exportFeatures(alignPanel);\r
+  }\r
+\r
+  @Override\r
+  public void exportAnnotations_actionPerformed(ActionEvent e)\r
+  {\r
+    new AnnotationExporter().exportAnnotations(alignPanel,\r
+            viewport.showAnnotation ? viewport.getAlignment()\r
+                    .getAlignmentAnnotation() : null, viewport\r
+                    .getAlignment().getGroups(), ((Alignment) viewport\r
+                    .getAlignment()).alignmentProperties);\r
+  }\r
+\r
+  @Override\r
+  public void associatedData_actionPerformed(ActionEvent e)\r
+  {\r
+    // Pick the tree file\r
+    JalviewFileChooser chooser = new JalviewFileChooser(\r
+            jalview.bin.Cache.getProperty("LAST_DIRECTORY"));\r
+    chooser.setFileView(new JalviewFileView());\r
+    chooser.setDialogTitle(MessageManager.getString("label.load_jalview_annotations"));\r
+    chooser.setToolTipText(MessageManager.getString("label.load_jalview_annotations"));\r
+\r
+    int value = chooser.showOpenDialog(null);\r
+\r
+    if (value == JalviewFileChooser.APPROVE_OPTION)\r
+    {\r
+      String choice = chooser.getSelectedFile().getPath();\r
+      jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);\r
+      loadJalviewDataFile(choice, null, null, null);\r
+    }\r
+\r
+  }\r
+\r
+  /**\r
+   * Close the current view or all views in the alignment frame. If the frame\r
+   * only contains one view then the alignment will be removed from memory.\r
+   * \r
+   * @param closeAllTabs\r
+   */\r
+  @Override\r
+  public void closeMenuItem_actionPerformed(boolean closeAllTabs)\r
+  {\r
+    if (alignPanels != null && alignPanels.size() < 2)\r
+    {\r
+      closeAllTabs = true;\r
+    }\r
+\r
+    try\r
+    {\r
+      if (alignPanels != null)\r
+      {\r
+        if (closeAllTabs)\r
+        {\r
+          if (this.isClosed())\r
+          {\r
+            // really close all the windows - otherwise wait till\r
+            // setClosed(true) is called\r
+            for (int i = 0; i < alignPanels.size(); i++)\r
+            {\r
+              AlignmentPanel ap = (AlignmentPanel) alignPanels.elementAt(i);\r
+              ap.closePanel();\r
+            }\r
+          }\r
+        }\r
+        else\r
+        {\r
+          closeView(alignPanel);\r
+        }\r
+      }\r
+\r
+      if (closeAllTabs)\r
+      {\r
+        this.setClosed(true);\r
+      }\r
+    } catch (Exception ex)\r
+    {\r
+      ex.printStackTrace();\r
+    }\r
+  }\r
+\r
+  /**\r
+   * close alignPanel2 and shuffle tabs appropriately.\r
+   * \r
+   * @param alignPanel2\r
+   */\r
+  public void closeView(AlignmentPanel alignPanel2)\r
+  {\r
+    int index = tabbedPane.getSelectedIndex();\r
+    int closedindex = tabbedPane.indexOfComponent(alignPanel2);\r
+    alignPanels.removeElement(alignPanel2);\r
+    // Unnecessary\r
+    // if (viewport == alignPanel2.av)\r
+    // {\r
+    // viewport = null;\r
+    // }\r
+    alignPanel2.closePanel();\r
+    alignPanel2 = null;\r
+\r
+    tabbedPane.removeTabAt(closedindex);\r
+    tabbedPane.validate();\r
+\r
+    if (index > closedindex || index == tabbedPane.getTabCount())\r
+    {\r
+      // modify currently selected tab index if necessary.\r
+      index--;\r
+    }\r
+\r
+    this.tabSelectionChanged(index);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   */\r
+  void updateEditMenuBar()\r
+  {\r
+\r
+    if (viewport.historyList.size() > 0)\r
+    {\r
+      undoMenuItem.setEnabled(true);\r
+      CommandI command = (CommandI) viewport.historyList.peek();\r
+      undoMenuItem.setText(MessageManager.formatMessage("label.undo_command", new String[]{command.getDescription()}));\r
+    }\r
+    else\r
+    {\r
+      undoMenuItem.setEnabled(false);\r
+      undoMenuItem.setText(MessageManager.getString("action.undo"));\r
+    }\r
+\r
+    if (viewport.redoList.size() > 0)\r
+    {\r
+      redoMenuItem.setEnabled(true);\r
+\r
+      CommandI command = (CommandI) viewport.redoList.peek();\r
+      redoMenuItem.setText(MessageManager.formatMessage("label.redo_command", new String[]{command.getDescription()}));\r
+    }\r
+    else\r
+    {\r
+      redoMenuItem.setEnabled(false);\r
+      redoMenuItem.setText(MessageManager.getString("action.redo"));\r
+    }\r
+  }\r
+\r
+  public void addHistoryItem(CommandI command)\r
+  {\r
+    if (command.getSize() > 0)\r
+    {\r
+      viewport.historyList.push(command);\r
+      viewport.redoList.clear();\r
+      updateEditMenuBar();\r
+      viewport.updateHiddenColumns();\r
+      // viewport.hasHiddenColumns = (viewport.getColumnSelection() != null\r
+      // && viewport.getColumnSelection().getHiddenColumns() != null &&\r
+      // viewport.getColumnSelection()\r
+      // .getHiddenColumns().size() > 0);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * \r
+   * @return alignment objects for all views\r
+   */\r
+  AlignmentI[] getViewAlignments()\r
+  {\r
+    if (alignPanels != null)\r
+    {\r
+      Enumeration e = alignPanels.elements();\r
+      AlignmentI[] als = new AlignmentI[alignPanels.size()];\r
+      for (int i = 0; e.hasMoreElements(); i++)\r
+      {\r
+        als[i] = ((AlignmentPanel) e.nextElement()).av.getAlignment();\r
+      }\r
+      return als;\r
+    }\r
+    if (viewport != null)\r
+    {\r
+      return new AlignmentI[]\r
+      { viewport.getAlignment() };\r
+    }\r
+    return null;\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void undoMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    if (viewport.historyList.empty())\r
+      return;\r
+    CommandI command = (CommandI) viewport.historyList.pop();\r
+    viewport.redoList.push(command);\r
+    command.undoCommand(getViewAlignments());\r
+\r
+    AlignViewport originalSource = getOriginatingSource(command);\r
+    updateEditMenuBar();\r
+\r
+    if (originalSource != null)\r
+    {\r
+      if (originalSource != viewport)\r
+      {\r
+        Cache.log\r
+                .warn("Implementation worry: mismatch of viewport origin for undo");\r
+      }\r
+      originalSource.updateHiddenColumns();\r
+      // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=\r
+      // null\r
+      // && viewport.getColumnSelection().getHiddenColumns() != null &&\r
+      // viewport.getColumnSelection()\r
+      // .getHiddenColumns().size() > 0);\r
+      originalSource.firePropertyChange("alignment", null, originalSource\r
+              .getAlignment().getSequences());\r
+    }\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void redoMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    if (viewport.redoList.size() < 1)\r
+    {\r
+      return;\r
+    }\r
+\r
+    CommandI command = (CommandI) viewport.redoList.pop();\r
+    viewport.historyList.push(command);\r
+    command.doCommand(getViewAlignments());\r
+\r
+    AlignViewport originalSource = getOriginatingSource(command);\r
+    updateEditMenuBar();\r
+\r
+    if (originalSource != null)\r
+    {\r
+\r
+      if (originalSource != viewport)\r
+      {\r
+        Cache.log\r
+                .warn("Implementation worry: mismatch of viewport origin for redo");\r
+      }\r
+      originalSource.updateHiddenColumns();\r
+      // originalSource.hasHiddenColumns = (viewport.getColumnSelection() !=\r
+      // null\r
+      // && viewport.getColumnSelection().getHiddenColumns() != null &&\r
+      // viewport.getColumnSelection()\r
+      // .getHiddenColumns().size() > 0);\r
+      originalSource.firePropertyChange("alignment", null, originalSource\r
+              .getAlignment().getSequences());\r
+    }\r
+  }\r
+\r
+  AlignViewport getOriginatingSource(CommandI command)\r
+  {\r
+    AlignViewport originalSource = null;\r
+    // For sequence removal and addition, we need to fire\r
+    // the property change event FROM the viewport where the\r
+    // original alignment was altered\r
+    AlignmentI al = null;\r
+    if (command instanceof EditCommand)\r
+    {\r
+      EditCommand editCommand = (EditCommand) command;\r
+      al = editCommand.getAlignment();\r
+      Vector comps = (Vector) PaintRefresher.components.get(viewport\r
+              .getSequenceSetId());\r
+\r
+      for (int i = 0; i < comps.size(); i++)\r
+      {\r
+        if (comps.elementAt(i) instanceof AlignmentPanel)\r
+        {\r
+          if (al == ((AlignmentPanel) comps.elementAt(i)).av.getAlignment())\r
+          {\r
+            originalSource = ((AlignmentPanel) comps.elementAt(i)).av;\r
+            break;\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    if (originalSource == null)\r
+    {\r
+      // The original view is closed, we must validate\r
+      // the current view against the closed view first\r
+      if (al != null)\r
+      {\r
+        PaintRefresher.validateSequences(al, viewport.getAlignment());\r
+      }\r
+\r
+      originalSource = viewport;\r
+    }\r
+\r
+    return originalSource;\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param up\r
+   *          DOCUMENT ME!\r
+   */\r
+  public void moveSelectedSequences(boolean up)\r
+  {\r
+    SequenceGroup sg = viewport.getSelectionGroup();\r
+\r
+    if (sg == null)\r
+    {\r
+      return;\r
+    }\r
+    viewport.getAlignment().moveSelectedSequencesByOne(sg,\r
+            viewport.getHiddenRepSequences(), up);\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  synchronized void slideSequences(boolean right, int size)\r
+  {\r
+    List<SequenceI> sg = new Vector();\r
+    if (viewport.cursorMode)\r
+    {\r
+      sg.add(viewport.getAlignment().getSequenceAt(\r
+              alignPanel.seqPanel.seqCanvas.cursorY));\r
+    }\r
+    else if (viewport.getSelectionGroup() != null\r
+            && viewport.getSelectionGroup().getSize() != viewport\r
+                    .getAlignment().getHeight())\r
+    {\r
+      sg = viewport.getSelectionGroup().getSequences(\r
+              viewport.getHiddenRepSequences());\r
+    }\r
+\r
+    if (sg.size() < 1)\r
+    {\r
+      return;\r
+    }\r
+\r
+    Vector invertGroup = new Vector();\r
+\r
+    for (int i = 0; i < viewport.getAlignment().getHeight(); i++)\r
+    {\r
+      if (!sg.contains(viewport.getAlignment().getSequenceAt(i)))\r
+        invertGroup.add(viewport.getAlignment().getSequenceAt(i));\r
+    }\r
+\r
+    SequenceI[] seqs1 = sg.toArray(new SequenceI[0]);\r
+\r
+    SequenceI[] seqs2 = new SequenceI[invertGroup.size()];\r
+    for (int i = 0; i < invertGroup.size(); i++)\r
+      seqs2[i] = (SequenceI) invertGroup.elementAt(i);\r
+\r
+    SlideSequencesCommand ssc;\r
+    if (right)\r
+      ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1,\r
+              size, viewport.getGapCharacter());\r
+    else\r
+      ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2,\r
+              size, viewport.getGapCharacter());\r
+\r
+    int groupAdjustment = 0;\r
+    if (ssc.getGapsInsertedBegin() && right)\r
+    {\r
+      if (viewport.cursorMode)\r
+        alignPanel.seqPanel.moveCursor(size, 0);\r
+      else\r
+        groupAdjustment = size;\r
+    }\r
+    else if (!ssc.getGapsInsertedBegin() && !right)\r
+    {\r
+      if (viewport.cursorMode)\r
+        alignPanel.seqPanel.moveCursor(-size, 0);\r
+      else\r
+        groupAdjustment = -size;\r
+    }\r
+\r
+    if (groupAdjustment != 0)\r
+    {\r
+      viewport.getSelectionGroup().setStartRes(\r
+              viewport.getSelectionGroup().getStartRes() + groupAdjustment);\r
+      viewport.getSelectionGroup().setEndRes(\r
+              viewport.getSelectionGroup().getEndRes() + groupAdjustment);\r
+    }\r
+\r
+    boolean appendHistoryItem = false;\r
+    if (viewport.historyList != null && viewport.historyList.size() > 0\r
+            && viewport.historyList.peek() instanceof SlideSequencesCommand)\r
+    {\r
+      appendHistoryItem = ssc\r
+              .appendSlideCommand((SlideSequencesCommand) viewport.historyList\r
+                      .peek());\r
+    }\r
+\r
+    if (!appendHistoryItem)\r
+      addHistoryItem(ssc);\r
+\r
+    repaint();\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void copy_actionPerformed(ActionEvent e)\r
+  {\r
+    System.gc();\r
+    if (viewport.getSelectionGroup() == null)\r
+    {\r
+      return;\r
+    }\r
+    // TODO: preserve the ordering of displayed alignment annotation in any\r
+    // internal paste (particularly sequence associated annotation)\r
+    SequenceI[] seqs = viewport.getSelectionAsNewSequence();\r
+    String[] omitHidden = null;\r
+\r
+    if (viewport.hasHiddenColumns())\r
+    {\r
+      omitHidden = viewport.getViewAsString(true);\r
+    }\r
+\r
+    String output = new FormatAdapter().formatSequences("Fasta", seqs,\r
+            omitHidden);\r
+\r
+    StringSelection ss = new StringSelection(output);\r
+\r
+    try\r
+    {\r
+      jalview.gui.Desktop.internalCopy = true;\r
+      // Its really worth setting the clipboard contents\r
+      // to empty before setting the large StringSelection!!\r
+      Toolkit.getDefaultToolkit().getSystemClipboard()\r
+              .setContents(new StringSelection(""), null);\r
+\r
+      Toolkit.getDefaultToolkit().getSystemClipboard()\r
+              .setContents(ss, Desktop.instance);\r
+    } catch (OutOfMemoryError er)\r
+    {\r
+      new OOMWarning("copying region", er);\r
+      return;\r
+    }\r
+\r
+    Vector hiddenColumns = null;\r
+    if (viewport.hasHiddenColumns())\r
+    {\r
+      hiddenColumns = new Vector();\r
+      int hiddenOffset = viewport.getSelectionGroup().getStartRes(), hiddenCutoff = viewport\r
+              .getSelectionGroup().getEndRes();\r
+      for (int i = 0; i < viewport.getColumnSelection().getHiddenColumns()\r
+              .size(); i++)\r
+      {\r
+        int[] region = (int[]) viewport.getColumnSelection()\r
+                .getHiddenColumns().elementAt(i);\r
+        if (region[0] >= hiddenOffset && region[1] <= hiddenCutoff)\r
+        {\r
+          hiddenColumns.addElement(new int[]\r
+          { region[0] - hiddenOffset, region[1] - hiddenOffset });\r
+        }\r
+      }\r
+    }\r
+\r
+    Desktop.jalviewClipboard = new Object[]\r
+    { seqs, viewport.getAlignment().getDataset(), hiddenColumns };\r
+    statusBar.setText(MessageManager.formatMessage("label.copied_sequences_to_clipboard", new String[]{Integer.valueOf(seqs.length).toString()}));\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void pasteNew_actionPerformed(ActionEvent e)\r
+  {\r
+    paste(true);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void pasteThis_actionPerformed(ActionEvent e)\r
+  {\r
+    paste(false);\r
+  }\r
+\r
+  /**\r
+   * Paste contents of Jalview clipboard\r
+   * \r
+   * @param newAlignment\r
+   *          true to paste to a new alignment, otherwise add to this.\r
+   */\r
+  void paste(boolean newAlignment)\r
+  {\r
+    boolean externalPaste = true;\r
+    try\r
+    {\r
+      Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();\r
+      Transferable contents = c.getContents(this);\r
+\r
+      if (contents == null)\r
+      {\r
+        return;\r
+      }\r
+\r
+      String str, format;\r
+      try\r
+      {\r
+        str = (String) contents.getTransferData(DataFlavor.stringFlavor);\r
+        if (str.length() < 1)\r
+        {\r
+          return;\r
+        }\r
+\r
+        format = new IdentifyFile().Identify(str, "Paste");\r
+\r
+      } catch (OutOfMemoryError er)\r
+      {\r
+        new OOMWarning("Out of memory pasting sequences!!", er);\r
+        return;\r
+      }\r
+\r
+      SequenceI[] sequences;\r
+      boolean annotationAdded = false;\r
+      AlignmentI alignment = null;\r
+\r
+      if (Desktop.jalviewClipboard != null)\r
+      {\r
+        // The clipboard was filled from within Jalview, we must use the\r
+        // sequences\r
+        // And dataset from the copied alignment\r
+        SequenceI[] newseq = (SequenceI[]) Desktop.jalviewClipboard[0];\r
+        // be doubly sure that we create *new* sequence objects.\r
+        sequences = new SequenceI[newseq.length];\r
+        for (int i = 0; i < newseq.length; i++)\r
+        {\r
+          sequences[i] = new Sequence(newseq[i]);\r
+        }\r
+        alignment = new Alignment(sequences);\r
+        externalPaste = false;\r
+      }\r
+      else\r
+      {\r
+        // parse the clipboard as an alignment.\r
+        alignment = new FormatAdapter().readFile(str, "Paste", format);\r
+        sequences = alignment.getSequencesArray();\r
+      }\r
+\r
+      int alwidth = 0;\r
+      ArrayList<Integer> newGraphGroups = new ArrayList<Integer>();\r
+      int fgroup = -1;\r
+\r
+      if (newAlignment)\r
+      {\r
+\r
+        if (Desktop.jalviewClipboard != null)\r
+        {\r
+          // dataset is inherited\r
+          alignment.setDataset((Alignment) Desktop.jalviewClipboard[1]);\r
+        }\r
+        else\r
+        {\r
+          // new dataset is constructed\r
+          alignment.setDataset(null);\r
+        }\r
+        alwidth = alignment.getWidth() + 1;\r
+      }\r
+      else\r
+      {\r
+        AlignmentI pastedal = alignment; // preserve pasted alignment object\r
+        // Add pasted sequences and dataset into existing alignment.\r
+        alignment = viewport.getAlignment();\r
+        alwidth = alignment.getWidth() + 1;\r
+        // decide if we need to import sequences from an existing dataset\r
+        boolean importDs = Desktop.jalviewClipboard != null\r
+                && Desktop.jalviewClipboard[1] != alignment.getDataset();\r
+        // importDs==true instructs us to copy over new dataset sequences from\r
+        // an existing alignment\r
+        Vector newDs = (importDs) ? new Vector() : null; // used to create\r
+        // minimum dataset set\r
+\r
+        for (int i = 0; i < sequences.length; i++)\r
+        {\r
+          if (importDs)\r
+          {\r
+            newDs.addElement(null);\r
+          }\r
+          SequenceI ds = sequences[i].getDatasetSequence(); // null for a simple\r
+          // paste\r
+          if (importDs && ds != null)\r
+          {\r
+            if (!newDs.contains(ds))\r
+            {\r
+              newDs.setElementAt(ds, i);\r
+              ds = new Sequence(ds);\r
+              // update with new dataset sequence\r
+              sequences[i].setDatasetSequence(ds);\r
+            }\r
+            else\r
+            {\r
+              ds = sequences[newDs.indexOf(ds)].getDatasetSequence();\r
+            }\r
+          }\r
+          else\r
+          {\r
+            // copy and derive new dataset sequence\r
+            sequences[i] = sequences[i].deriveSequence();\r
+            alignment.getDataset().addSequence(\r
+                    sequences[i].getDatasetSequence());\r
+            // TODO: avoid creation of duplicate dataset sequences with a\r
+            // 'contains' method using SequenceI.equals()/SequenceI.contains()\r
+          }\r
+          alignment.addSequence(sequences[i]); // merges dataset\r
+        }\r
+        if (newDs != null)\r
+        {\r
+          newDs.clear(); // tidy up\r
+        }\r
+        if (alignment.getAlignmentAnnotation() != null)\r
+        {\r
+          for (AlignmentAnnotation alan : alignment\r
+                  .getAlignmentAnnotation())\r
+          {\r
+            if (alan.graphGroup > fgroup)\r
+            {\r
+              fgroup = alan.graphGroup;\r
+            }\r
+          }\r
+        }\r
+        if (pastedal.getAlignmentAnnotation() != null)\r
+        {\r
+          // Add any annotation attached to alignment.\r
+          AlignmentAnnotation[] alann = pastedal.getAlignmentAnnotation();\r
+          for (int i = 0; i < alann.length; i++)\r
+          {\r
+            annotationAdded = true;\r
+            if (alann[i].sequenceRef == null && !alann[i].autoCalculated)\r
+            {\r
+              AlignmentAnnotation newann = new AlignmentAnnotation(alann[i]);\r
+              if (newann.graphGroup > -1)\r
+              {\r
+                if (newGraphGroups.size() <= newann.graphGroup\r
+                        || newGraphGroups.get(newann.graphGroup) == null)\r
+                {\r
+                  for (int q = newGraphGroups.size(); q <= newann.graphGroup; q++)\r
+                  {\r
+                    newGraphGroups.add(q, null);\r
+                  }\r
+                  newGraphGroups.set(newann.graphGroup, new Integer(\r
+                          ++fgroup));\r
+                }\r
+                newann.graphGroup = newGraphGroups.get(newann.graphGroup)\r
+                        .intValue();\r
+              }\r
+\r
+              newann.padAnnotation(alwidth);\r
+              alignment.addAnnotation(newann);\r
+            }\r
+          }\r
+        }\r
+      }\r
+      if (!newAlignment)\r
+      {\r
+        // /////\r
+        // ADD HISTORY ITEM\r
+        //\r
+        addHistoryItem(new EditCommand("Add sequences", EditCommand.PASTE,\r
+                sequences, 0, alignment.getWidth(), alignment));\r
+      }\r
+      // Add any annotations attached to sequences\r
+      for (int i = 0; i < sequences.length; i++)\r
+      {\r
+        if (sequences[i].getAnnotation() != null)\r
+        {\r
+          AlignmentAnnotation newann;\r
+          for (int a = 0; a < sequences[i].getAnnotation().length; a++)\r
+          {\r
+            annotationAdded = true;\r
+            newann = sequences[i].getAnnotation()[a];\r
+            newann.adjustForAlignment();\r
+            newann.padAnnotation(alwidth);\r
+            if (newann.graphGroup > -1)\r
+            {\r
+              if (newann.graphGroup > -1)\r
+              {\r
+                if (newGraphGroups.size() <= newann.graphGroup\r
+                        || newGraphGroups.get(newann.graphGroup) == null)\r
+                {\r
+                  for (int q = newGraphGroups.size(); q <= newann.graphGroup; q++)\r
+                  {\r
+                    newGraphGroups.add(q, null);\r
+                  }\r
+                  newGraphGroups.set(newann.graphGroup, new Integer(\r
+                          ++fgroup));\r
+                }\r
+                newann.graphGroup = newGraphGroups.get(newann.graphGroup)\r
+                        .intValue();\r
+              }\r
+            }\r
+            alignment.addAnnotation(sequences[i].getAnnotation()[a]); // annotation\r
+            // was\r
+            // duplicated\r
+            // earlier\r
+            alignment\r
+                    .setAnnotationIndex(sequences[i].getAnnotation()[a], a);\r
+          }\r
+        }\r
+      }\r
+      if (!newAlignment)\r
+      {\r
+\r
+        // propagate alignment changed.\r
+        viewport.setEndSeq(alignment.getHeight());\r
+        if (annotationAdded)\r
+        {\r
+          // Duplicate sequence annotation in all views.\r
+          AlignmentI[] alview = this.getViewAlignments();\r
+          for (int i = 0; i < sequences.length; i++)\r
+          {\r
+            AlignmentAnnotation sann[] = sequences[i].getAnnotation();\r
+            if (sann == null)\r
+              continue;\r
+            for (int avnum = 0; avnum < alview.length; avnum++)\r
+            {\r
+              if (alview[avnum] != alignment)\r
+              {\r
+                // duplicate in a view other than the one with input focus\r
+                int avwidth = alview[avnum].getWidth() + 1;\r
+                // this relies on sann being preserved after we\r
+                // modify the sequence's annotation array for each duplication\r
+                for (int a = 0; a < sann.length; a++)\r
+                {\r
+                  AlignmentAnnotation newann = new AlignmentAnnotation(\r
+                          sann[a]);\r
+                  sequences[i].addAlignmentAnnotation(newann);\r
+                  newann.padAnnotation(avwidth);\r
+                  alview[avnum].addAnnotation(newann); // annotation was\r
+                  // duplicated earlier\r
+                  // TODO JAL-1145 graphGroups are not updated for sequence\r
+                  // annotation added to several views. This may cause\r
+                  // strangeness\r
+                  alview[avnum].setAnnotationIndex(newann, a);\r
+                }\r
+              }\r
+            }\r
+          }\r
+          buildSortByAnnotationScoresMenu();\r
+        }\r
+        viewport.firePropertyChange("alignment", null,\r
+                alignment.getSequences());\r
+        if (alignPanels != null)\r
+        {\r
+          for (AlignmentPanel ap : ((Vector<AlignmentPanel>) alignPanels))\r
+          {\r
+            ap.validateAnnotationDimensions(false);\r
+          }\r
+        }\r
+        else\r
+        {\r
+          alignPanel.validateAnnotationDimensions(false);\r
+        }\r
+\r
+      }\r
+      else\r
+      {\r
+        AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,\r
+                DEFAULT_HEIGHT);\r
+        String newtitle = new String("Copied sequences");\r
+\r
+        if (Desktop.jalviewClipboard != null\r
+                && Desktop.jalviewClipboard[2] != null)\r
+        {\r
+          Vector hc = (Vector) Desktop.jalviewClipboard[2];\r
+          for (int i = 0; i < hc.size(); i++)\r
+          {\r
+            int[] region = (int[]) hc.elementAt(i);\r
+            af.viewport.hideColumns(region[0], region[1]);\r
+          }\r
+        }\r
+\r
+        // >>>This is a fix for the moment, until a better solution is\r
+        // found!!<<<\r
+        af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer()\r
+                .transferSettings(\r
+                        alignPanel.seqPanel.seqCanvas.getFeatureRenderer());\r
+\r
+        // TODO: maintain provenance of an alignment, rather than just make the\r
+        // title a concatenation of operations.\r
+        if (!externalPaste)\r
+        {\r
+          if (title.startsWith("Copied sequences"))\r
+          {\r
+            newtitle = title;\r
+          }\r
+          else\r
+          {\r
+            newtitle = newtitle.concat("- from " + title);\r
+          }\r
+        }\r
+        else\r
+        {\r
+          newtitle = new String("Pasted sequences");\r
+        }\r
+\r
+        Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,\r
+                DEFAULT_HEIGHT);\r
+\r
+      }\r
+\r
+    } catch (Exception ex)\r
+    {\r
+      ex.printStackTrace();\r
+      System.out.println("Exception whilst pasting: " + ex);\r
+      // could be anything being pasted in here\r
+    }\r
+\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void cut_actionPerformed(ActionEvent e)\r
+  {\r
+    copy_actionPerformed(null);\r
+    delete_actionPerformed(null);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void delete_actionPerformed(ActionEvent evt)\r
+  {\r
+\r
+    SequenceGroup sg = viewport.getSelectionGroup();\r
+    if (sg == null)\r
+    {\r
+      return;\r
+    }\r
+\r
+    Vector seqs = new Vector();\r
+    SequenceI seq;\r
+    for (int i = 0; i < sg.getSize(); i++)\r
+    {\r
+      seq = sg.getSequenceAt(i);\r
+      seqs.addElement(seq);\r
+    }\r
+\r
+    // If the cut affects all sequences, remove highlighted columns\r
+    if (sg.getSize() == viewport.getAlignment().getHeight())\r
+    {\r
+      viewport.getColumnSelection().removeElements(sg.getStartRes(),\r
+              sg.getEndRes() + 1);\r
+    }\r
+\r
+    SequenceI[] cut = new SequenceI[seqs.size()];\r
+    for (int i = 0; i < seqs.size(); i++)\r
+    {\r
+      cut[i] = (SequenceI) seqs.elementAt(i);\r
+    }\r
+\r
+    /*\r
+     * //ADD HISTORY ITEM\r
+     */\r
+    addHistoryItem(new EditCommand("Cut Sequences", EditCommand.CUT, cut,\r
+            sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,\r
+            viewport.getAlignment()));\r
+\r
+    viewport.setSelectionGroup(null);\r
+    viewport.sendSelection();\r
+    viewport.getAlignment().deleteGroup(sg);\r
+\r
+    viewport.firePropertyChange("alignment", null, viewport.getAlignment()\r
+            .getSequences());\r
+    if (viewport.getAlignment().getHeight() < 1)\r
+    {\r
+      try\r
+      {\r
+        this.setClosed(true);\r
+      } catch (Exception ex)\r
+      {\r
+      }\r
+    }\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void deleteGroups_actionPerformed(ActionEvent e)\r
+  {\r
+    if (avc.deleteGroups()) {\r
+      PaintRefresher.Refresh(this, viewport.getSequenceSetId());\r
+      alignPanel.updateAnnotation();\r
+      alignPanel.paintAlignment(true);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    SequenceGroup sg = new SequenceGroup();\r
+\r
+    for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)\r
+    {\r
+      sg.addSequence(viewport.getAlignment().getSequenceAt(i), false);\r
+    }\r
+\r
+    sg.setEndRes(viewport.getAlignment().getWidth() - 1);\r
+    viewport.setSelectionGroup(sg);\r
+    viewport.sendSelection();\r
+    alignPanel.paintAlignment(true);\r
+    PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    if (viewport.cursorMode)\r
+    {\r
+      alignPanel.seqPanel.keyboardNo1 = null;\r
+      alignPanel.seqPanel.keyboardNo2 = null;\r
+    }\r
+    viewport.setSelectionGroup(null);\r
+    viewport.getColumnSelection().clear();\r
+    viewport.setSelectionGroup(null);\r
+    alignPanel.seqPanel.seqCanvas.highlightSearchResults(null);\r
+    alignPanel.idPanel.idCanvas.searchResults = null;\r
+    alignPanel.paintAlignment(true);\r
+    PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());\r
+    viewport.sendSelection();\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void invertSequenceMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    SequenceGroup sg = viewport.getSelectionGroup();\r
+\r
+    if (sg == null)\r
+    {\r
+      selectAllSequenceMenuItem_actionPerformed(null);\r
+\r
+      return;\r
+    }\r
+\r
+    for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)\r
+    {\r
+      sg.addOrRemove(viewport.getAlignment().getSequenceAt(i), false);\r
+    }\r
+\r
+    alignPanel.paintAlignment(true);\r
+    PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());\r
+    viewport.sendSelection();\r
+  }\r
+\r
+  @Override\r
+  public void invertColSel_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.invertColumnSelection();\r
+    alignPanel.paintAlignment(true);\r
+    viewport.sendSelection();\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void remove2LeftMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    trimAlignment(true);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void remove2RightMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    trimAlignment(false);\r
+  }\r
+\r
+  void trimAlignment(boolean trimLeft)\r
+  {\r
+    ColumnSelection colSel = viewport.getColumnSelection();\r
+    int column;\r
+\r
+    if (colSel.size() > 0)\r
+    {\r
+      if (trimLeft)\r
+      {\r
+        column = colSel.getMin();\r
+      }\r
+      else\r
+      {\r
+        column = colSel.getMax();\r
+      }\r
+\r
+      SequenceI[] seqs;\r
+      if (viewport.getSelectionGroup() != null)\r
+      {\r
+        seqs = viewport.getSelectionGroup().getSequencesAsArray(\r
+                viewport.getHiddenRepSequences());\r
+      }\r
+      else\r
+      {\r
+        seqs = viewport.getAlignment().getSequencesArray();\r
+      }\r
+\r
+      TrimRegionCommand trimRegion;\r
+      if (trimLeft)\r
+      {\r
+        trimRegion = new TrimRegionCommand("Remove Left",\r
+                TrimRegionCommand.TRIM_LEFT, seqs, column,\r
+                viewport.getAlignment(), viewport.getColumnSelection(),\r
+                viewport.getSelectionGroup());\r
+        viewport.setStartRes(0);\r
+      }\r
+      else\r
+      {\r
+        trimRegion = new TrimRegionCommand("Remove Right",\r
+                TrimRegionCommand.TRIM_RIGHT, seqs, column,\r
+                viewport.getAlignment(), viewport.getColumnSelection(),\r
+                viewport.getSelectionGroup());\r
+      }\r
+\r
+      statusBar.setText(MessageManager.formatMessage("label.removed_columns", new String[]{Integer.valueOf(trimRegion.getSize()).toString()}));\r
+\r
+      addHistoryItem(trimRegion);\r
+\r
+      for (SequenceGroup sg : viewport.getAlignment().getGroups())\r
+      {\r
+        if ((trimLeft && !sg.adjustForRemoveLeft(column))\r
+                || (!trimLeft && !sg.adjustForRemoveRight(column)))\r
+        {\r
+          viewport.getAlignment().deleteGroup(sg);\r
+        }\r
+      }\r
+\r
+      viewport.firePropertyChange("alignment", null, viewport\r
+              .getAlignment().getSequences());\r
+    }\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    int start = 0, end = viewport.getAlignment().getWidth() - 1;\r
+\r
+    SequenceI[] seqs;\r
+    if (viewport.getSelectionGroup() != null)\r
+    {\r
+      seqs = viewport.getSelectionGroup().getSequencesAsArray(\r
+              viewport.getHiddenRepSequences());\r
+      start = viewport.getSelectionGroup().getStartRes();\r
+      end = viewport.getSelectionGroup().getEndRes();\r
+    }\r
+    else\r
+    {\r
+      seqs = viewport.getAlignment().getSequencesArray();\r
+    }\r
+\r
+    RemoveGapColCommand removeGapCols = new RemoveGapColCommand(\r
+            "Remove Gapped Columns", seqs, start, end,\r
+            viewport.getAlignment());\r
+\r
+    addHistoryItem(removeGapCols);\r
+\r
+    statusBar.setText(MessageManager.formatMessage("label.removed_empty_columns", new String[]{Integer.valueOf(removeGapCols.getSize()).toString()}));\r
+\r
+    // This is to maintain viewport position on first residue\r
+    // of first sequence\r
+    SequenceI seq = viewport.getAlignment().getSequenceAt(0);\r
+    int startRes = seq.findPosition(viewport.startRes);\r
+    // ShiftList shifts;\r
+    // viewport.getAlignment().removeGaps(shifts=new ShiftList());\r
+    // edit.alColumnChanges=shifts.getInverse();\r
+    // if (viewport.hasHiddenColumns)\r
+    // viewport.getColumnSelection().compensateForEdits(shifts);\r
+    viewport.setStartRes(seq.findIndex(startRes) - 1);\r
+    viewport.firePropertyChange("alignment", null, viewport.getAlignment()\r
+            .getSequences());\r
+\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    int start = 0, end = viewport.getAlignment().getWidth() - 1;\r
+\r
+    SequenceI[] seqs;\r
+    if (viewport.getSelectionGroup() != null)\r
+    {\r
+      seqs = viewport.getSelectionGroup().getSequencesAsArray(\r
+              viewport.getHiddenRepSequences());\r
+      start = viewport.getSelectionGroup().getStartRes();\r
+      end = viewport.getSelectionGroup().getEndRes();\r
+    }\r
+    else\r
+    {\r
+      seqs = viewport.getAlignment().getSequencesArray();\r
+    }\r
+\r
+    // This is to maintain viewport position on first residue\r
+    // of first sequence\r
+    SequenceI seq = viewport.getAlignment().getSequenceAt(0);\r
+    int startRes = seq.findPosition(viewport.startRes);\r
+\r
+    addHistoryItem(new RemoveGapsCommand("Remove Gaps", seqs, start, end,\r
+            viewport.getAlignment()));\r
+\r
+    viewport.setStartRes(seq.findIndex(startRes) - 1);\r
+\r
+    viewport.firePropertyChange("alignment", null, viewport.getAlignment()\r
+            .getSequences());\r
+\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void padGapsMenuitem_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setPadGaps(padGapsMenuitem.isSelected());\r
+    viewport.firePropertyChange("alignment", null, viewport.getAlignment()\r
+            .getSequences());\r
+  }\r
+\r
+  // else\r
+  {\r
+    // if (justifySeqs>0)\r
+    {\r
+      // alignment.justify(justifySeqs!=RIGHT_JUSTIFY);\r
+    }\r
+  }\r
+\r
+  // }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void findMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    new Finder();\r
+  }\r
+\r
+  @Override\r
+  public void newView_actionPerformed(ActionEvent e)\r
+  {\r
+    newView(true);\r
+  }\r
+\r
+  /**\r
+   * \r
+   * @param copyAnnotation\r
+   *          if true then duplicate all annnotation, groups and settings\r
+   * @return new alignment panel, already displayed.\r
+   */\r
+  public AlignmentPanel newView(boolean copyAnnotation)\r
+  {\r
+    return newView(null, copyAnnotation);\r
+  }\r
+\r
+  /**\r
+   * \r
+   * @param viewTitle\r
+   *          title of newly created view\r
+   * @return new alignment panel, already displayed.\r
+   */\r
+  public AlignmentPanel newView(String viewTitle)\r
+  {\r
+    return newView(viewTitle, true);\r
+  }\r
+\r
+  /**\r
+   * \r
+   * @param viewTitle\r
+   *          title of newly created view\r
+   * @param copyAnnotation\r
+   *          if true then duplicate all annnotation, groups and settings\r
+   * @return new alignment panel, already displayed.\r
+   */\r
+  public AlignmentPanel newView(String viewTitle, boolean copyAnnotation)\r
+  {\r
+    AlignmentPanel newap = new Jalview2XML().copyAlignPanel(alignPanel,\r
+            true);\r
+    if (!copyAnnotation)\r
+    {\r
+      // just remove all the current annotation except for the automatic stuff\r
+      newap.av.getAlignment().deleteAllGroups();\r
+      for (AlignmentAnnotation alan : newap.av.getAlignment()\r
+              .getAlignmentAnnotation())\r
+      {\r
+        if (!alan.autoCalculated)\r
+        {\r
+          newap.av.getAlignment().deleteAnnotation(alan);\r
+        }\r
+        ;\r
+      }\r
+    }\r
+\r
+    newap.av.gatherViewsHere = false;\r
+\r
+    if (viewport.viewName == null)\r
+    {\r
+      viewport.viewName = "Original";\r
+    }\r
+\r
+    newap.av.historyList = viewport.historyList;\r
+    newap.av.redoList = viewport.redoList;\r
+\r
+    int index = Desktop.getViewCount(viewport.getSequenceSetId());\r
+    // make sure the new view has a unique name - this is essential for Jalview\r
+    // 2 archives\r
+    boolean addFirstIndex = false;\r
+    if (viewTitle == null || viewTitle.trim().length() == 0)\r
+    {\r
+      viewTitle = "View";\r
+      addFirstIndex = true;\r
+    }\r
+    else\r
+    {\r
+      index = 1;// we count from 1 if given a specific name\r
+    }\r
+    String newViewName = viewTitle + ((addFirstIndex) ? " " + index : "");\r
+    Vector comps = (Vector) PaintRefresher.components.get(viewport\r
+            .getSequenceSetId());\r
+    Vector existingNames = new Vector();\r
+    for (int i = 0; i < comps.size(); i++)\r
+    {\r
+      if (comps.elementAt(i) instanceof AlignmentPanel)\r
+      {\r
+        AlignmentPanel ap = (AlignmentPanel) comps.elementAt(i);\r
+        if (!existingNames.contains(ap.av.viewName))\r
+        {\r
+          existingNames.addElement(ap.av.viewName);\r
+        }\r
+      }\r
+    }\r
+\r
+    while (existingNames.contains(newViewName))\r
+    {\r
+      newViewName = viewTitle + " " + (++index);\r
+    }\r
+\r
+    newap.av.viewName = newViewName;\r
+\r
+    addAlignmentPanel(newap, true);\r
+    newap.alignmentChanged();\r
+    \r
+    if (alignPanels.size() == 2)\r
+    {\r
+      viewport.gatherViewsHere = true;\r
+    }\r
+    tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);\r
+    return newap;\r
+  }\r
+\r
+  @Override\r
+  public void expandViews_actionPerformed(ActionEvent e)\r
+  {\r
+    Desktop.instance.explodeViews(this);\r
+  }\r
+\r
+  @Override\r
+  public void gatherViews_actionPerformed(ActionEvent e)\r
+  {\r
+    Desktop.instance.gatherViews(this);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void font_actionPerformed(ActionEvent e)\r
+  {\r
+    new FontChooser(alignPanel);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void seqLimit_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setShowJVSuffix(seqLimits.isSelected());\r
+\r
+    alignPanel.idPanel.idCanvas.setPreferredSize(alignPanel\r
+            .calculateIdWidth());\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  @Override\r
+  public void idRightAlign_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.rightAlignIds = idRightAlign.isSelected();\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  @Override\r
+  public void centreColumnLabels_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.centreColumnLabels = centreColumnLabelsMenuItem.getState();\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  /*\r
+   * (non-Javadoc)\r
+   * \r
+   * @see jalview.jbgui.GAlignFrame#followHighlight_actionPerformed()\r
+   */\r
+  @Override\r
+  protected void followHighlight_actionPerformed()\r
+  {\r
+    if (viewport.followHighlight = this.followHighlightMenuItem.getState())\r
+    {\r
+      alignPanel.scrollToPosition(\r
+              alignPanel.seqPanel.seqCanvas.searchResults, false);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void colourTextMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setColourText(colourTextMenuItem.isSelected());\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void wrapMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    scaleAbove.setVisible(wrapMenuItem.isSelected());\r
+    scaleLeft.setVisible(wrapMenuItem.isSelected());\r
+    scaleRight.setVisible(wrapMenuItem.isSelected());\r
+    viewport.setWrapAlignment(wrapMenuItem.isSelected());\r
+    alignPanel.setWrapAlignment(wrapMenuItem.isSelected());\r
+  }\r
+\r
+  @Override\r
+  public void showAllSeqs_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.showAllHiddenSeqs();\r
+  }\r
+\r
+  @Override\r
+  public void showAllColumns_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.showAllHiddenColumns();\r
+    repaint();\r
+  }\r
+\r
+  @Override\r
+  public void hideSelSequences_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.hideAllSelectedSeqs();\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  /**\r
+   * called by key handler and the hide all/show all menu items\r
+   * \r
+   * @param toggleSeqs\r
+   * @param toggleCols\r
+   */\r
+  private void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols)\r
+  {\r
+\r
+    boolean hide = false;\r
+    SequenceGroup sg = viewport.getSelectionGroup();\r
+    if (!toggleSeqs && !toggleCols)\r
+    {\r
+      // Hide everything by the current selection - this is a hack - we do the\r
+      // invert and then hide\r
+      // first check that there will be visible columns after the invert.\r
+      if ((viewport.getColumnSelection() != null\r
+              && viewport.getColumnSelection().getSelected() != null && viewport\r
+              .getColumnSelection().getSelected().size() > 0)\r
+              || (sg != null && sg.getSize() > 0 && sg.getStartRes() <= sg\r
+                      .getEndRes()))\r
+      {\r
+        // now invert the sequence set, if required - empty selection implies\r
+        // that no hiding is required.\r
+        if (sg != null)\r
+        {\r
+          invertSequenceMenuItem_actionPerformed(null);\r
+          sg = viewport.getSelectionGroup();\r
+          toggleSeqs = true;\r
+\r
+        }\r
+        viewport.expandColSelection(sg, true);\r
+        // finally invert the column selection and get the new sequence\r
+        // selection.\r
+        invertColSel_actionPerformed(null);\r
+        toggleCols = true;\r
+      }\r
+    }\r
+\r
+    if (toggleSeqs)\r
+    {\r
+      if (sg != null && sg.getSize() != viewport.getAlignment().getHeight())\r
+      {\r
+        hideSelSequences_actionPerformed(null);\r
+        hide = true;\r
+      }\r
+      else if (!(toggleCols && viewport.getColumnSelection().getSelected()\r
+              .size() > 0))\r
+      {\r
+        showAllSeqs_actionPerformed(null);\r
+      }\r
+    }\r
+\r
+    if (toggleCols)\r
+    {\r
+      if (viewport.getColumnSelection().getSelected().size() > 0)\r
+      {\r
+        hideSelColumns_actionPerformed(null);\r
+        if (!toggleSeqs)\r
+        {\r
+          viewport.setSelectionGroup(sg);\r
+        }\r
+      }\r
+      else if (!hide)\r
+      {\r
+        showAllColumns_actionPerformed(null);\r
+      }\r
+    }\r
+  }\r
+\r
+  /*\r
+   * (non-Javadoc)\r
+   * \r
+   * @see\r
+   * jalview.jbgui.GAlignFrame#hideAllButSelection_actionPerformed(java.awt.\r
+   * event.ActionEvent)\r
+   */\r
+  @Override\r
+  public void hideAllButSelection_actionPerformed(ActionEvent e)\r
+  {\r
+    toggleHiddenRegions(false, false);\r
+  }\r
+\r
+  /*\r
+   * (non-Javadoc)\r
+   * \r
+   * @see\r
+   * jalview.jbgui.GAlignFrame#hideAllSelection_actionPerformed(java.awt.event\r
+   * .ActionEvent)\r
+   */\r
+  @Override\r
+  public void hideAllSelection_actionPerformed(ActionEvent e)\r
+  {\r
+    SequenceGroup sg = viewport.getSelectionGroup();\r
+    viewport.expandColSelection(sg, false);\r
+    viewport.hideAllSelectedSeqs();\r
+    viewport.hideSelectedColumns();\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  /*\r
+   * (non-Javadoc)\r
+   * \r
+   * @see\r
+   * jalview.jbgui.GAlignFrame#showAllhidden_actionPerformed(java.awt.event.\r
+   * ActionEvent)\r
+   */\r
+  @Override\r
+  public void showAllhidden_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.showAllHiddenColumns();\r
+    viewport.showAllHiddenSeqs();\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  @Override\r
+  public void hideSelColumns_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.hideSelectedColumns();\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  @Override\r
+  public void hiddenMarkers_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());\r
+    repaint();\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void scaleAbove_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setScaleAboveWrapped(scaleAbove.isSelected());\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void scaleLeft_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setScaleLeftWrapped(scaleLeft.isSelected());\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void scaleRight_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setScaleRightWrapped(scaleRight.isSelected());\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void viewBoxesMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setShowBoxes(viewBoxesMenuItem.isSelected());\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void viewTextMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setShowText(viewTextMenuItem.isSelected());\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void renderGapsMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setRenderGaps(renderGapsMenuItem.isSelected());\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  public FeatureSettings featureSettings;\r
+\r
+  @Override\r
+  public void featureSettings_actionPerformed(ActionEvent e)\r
+  {\r
+    if (featureSettings != null)\r
+    {\r
+      featureSettings.close();\r
+      featureSettings = null;\r
+    }\r
+    if (!showSeqFeatures.isSelected())\r
+    {\r
+      // make sure features are actually displayed\r
+      showSeqFeatures.setSelected(true);\r
+      showSeqFeatures_actionPerformed(null);\r
+    }\r
+    featureSettings = new FeatureSettings(this);\r
+  }\r
+\r
+  /**\r
+   * Set or clear 'Show Sequence Features'\r
+   * \r
+   * @param evt\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void showSeqFeatures_actionPerformed(ActionEvent evt)\r
+  {\r
+    viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());\r
+    alignPanel.paintAlignment(true);\r
+    if (alignPanel.getOverviewPanel() != null)\r
+    {\r
+      alignPanel.getOverviewPanel().updateOverviewImage();\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Set or clear 'Show Sequence Features'\r
+   * \r
+   * @param evt\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void showSeqFeaturesHeight_actionPerformed(ActionEvent evt)\r
+  {\r
+    viewport.setShowSequenceFeaturesHeight(showSeqFeaturesHeight\r
+            .isSelected());\r
+    if (viewport.getShowSequenceFeaturesHeight())\r
+    {\r
+      // ensure we're actually displaying features\r
+      viewport.setShowSequenceFeatures(true);\r
+      showSeqFeatures.setSelected(true);\r
+    }\r
+    alignPanel.paintAlignment(true);\r
+    if (alignPanel.getOverviewPanel() != null)\r
+    {\r
+      alignPanel.getOverviewPanel().updateOverviewImage();\r
+    }\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void annotationPanelMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setShowAnnotation(annotationPanelMenuItem.isSelected());\r
+    alignPanel.setAnnotationVisible(annotationPanelMenuItem.isSelected());\r
+  }\r
+\r
+  @Override\r
+  public void alignmentProperties()\r
+  {\r
+    JEditorPane editPane = new JEditorPane("text/html", "");\r
+    editPane.setEditable(false);\r
+    StringBuffer contents = new AlignmentProperties(viewport.getAlignment())\r
+            .formatAsHtml();\r
+    editPane.setText(MessageManager.formatMessage("label.html_content", new String[]{contents.toString()}));\r
+    JInternalFrame frame = new JInternalFrame();\r
+    frame.getContentPane().add(new JScrollPane(editPane));\r
+\r
+    Desktop.instance.addInternalFrame(frame, MessageManager.formatMessage("label.alignment_properties", new String[]{getTitle()}), 500, 400);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void overviewMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    if (alignPanel.overviewPanel != null)\r
+    {\r
+      return;\r
+    }\r
+\r
+    JInternalFrame frame = new JInternalFrame();\r
+    OverviewPanel overview = new OverviewPanel(alignPanel);\r
+    frame.setContentPane(overview);\r
+    Desktop.addInternalFrame(frame, MessageManager.formatMessage("label.overview_params", new String[]{this.getTitle()}),\r
+            frame.getWidth(), frame.getHeight());\r
+    frame.pack();\r
+    frame.setLayer(JLayeredPane.PALETTE_LAYER);\r
+    frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()\r
+    {\r
+      @Override\r
+      public void internalFrameClosed(\r
+              javax.swing.event.InternalFrameEvent evt)\r
+      {\r
+        alignPanel.setOverviewPanel(null);\r
+      };\r
+    });\r
+\r
+    alignPanel.setOverviewPanel(overview);\r
+  }\r
+\r
+  @Override\r
+  public void textColour_actionPerformed(ActionEvent e)\r
+  {\r
+    new TextColourChooser().chooseColour(alignPanel, null);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void noColourmenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    changeColour(null);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void clustalColour_actionPerformed(ActionEvent e)\r
+  {\r
+    changeColour(new ClustalxColourScheme(viewport.getAlignment(),\r
+            viewport.getHiddenRepSequences()));\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void zappoColour_actionPerformed(ActionEvent e)\r
+  {\r
+    changeColour(new ZappoColourScheme());\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void taylorColour_actionPerformed(ActionEvent e)\r
+  {\r
+    changeColour(new TaylorColourScheme());\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void hydrophobicityColour_actionPerformed(ActionEvent e)\r
+  {\r
+    changeColour(new HydrophobicColourScheme());\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void helixColour_actionPerformed(ActionEvent e)\r
+  {\r
+    changeColour(new HelixColourScheme());\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void strandColour_actionPerformed(ActionEvent e)\r
+  {\r
+    changeColour(new StrandColourScheme());\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void turnColour_actionPerformed(ActionEvent e)\r
+  {\r
+    changeColour(new TurnColourScheme());\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void buriedColour_actionPerformed(ActionEvent e)\r
+  {\r
+    changeColour(new BuriedColourScheme());\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void nucleotideColour_actionPerformed(ActionEvent e)\r
+  {\r
+    changeColour(new NucleotideColourScheme());\r
+  }\r
+\r
+  @Override\r
+  public void purinePyrimidineColour_actionPerformed(ActionEvent e)\r
+  {\r
+    changeColour(new PurinePyrimidineColourScheme());\r
+  }\r
+\r
+  /*\r
+   * public void covariationColour_actionPerformed(ActionEvent e) {\r
+   * changeColour(new\r
+   * CovariationColourScheme(viewport.getAlignment().getAlignmentAnnotation\r
+   * ()[0])); }\r
+   */\r
+  @Override\r
+  public void annotationColour_actionPerformed(ActionEvent e)\r
+  {\r
+    new AnnotationColourChooser(viewport, alignPanel);\r
+  }\r
+\r
+  @Override\r
+  public void rnahelicesColour_actionPerformed(ActionEvent e)\r
+  {\r
+    new RNAHelicesColourChooser(viewport, alignPanel);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void applyToAllGroups_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setColourAppliesToAllGroups(applyToAllGroups.isSelected());\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param cs\r
+   *          DOCUMENT ME!\r
+   */\r
+  public void changeColour(ColourSchemeI cs)\r
+  {\r
+    // TODO: compare with applet and pull up to model method\r
+    int threshold = 0;\r
+\r
+    if (cs != null)\r
+    {\r
+      if (viewport.getAbovePIDThreshold())\r
+      {\r
+        threshold = SliderPanel.setPIDSliderSource(alignPanel, cs,\r
+                "Background");\r
+\r
+        cs.setThreshold(threshold, viewport.getIgnoreGapsConsensus());\r
+\r
+        viewport.setGlobalColourScheme(cs);\r
+      }\r
+      else\r
+      {\r
+        cs.setThreshold(0, viewport.getIgnoreGapsConsensus());\r
+      }\r
+\r
+      if (viewport.getConservationSelected())\r
+      {\r
+\r
+        Alignment al = (Alignment) viewport.getAlignment();\r
+        Conservation c = new Conservation("All",\r
+                ResidueProperties.propHash, 3, al.getSequences(), 0,\r
+                al.getWidth() - 1);\r
+\r
+        c.calculate();\r
+        c.verdict(false, viewport.getConsPercGaps());\r
+\r
+        cs.setConservation(c);\r
+\r
+        cs.setConservationInc(SliderPanel.setConservationSlider(alignPanel,\r
+                cs, "Background"));\r
+      }\r
+      else\r
+      {\r
+        cs.setConservation(null);\r
+      }\r
+\r
+      cs.setConsensus(viewport.getSequenceConsensusHash());\r
+    }\r
+\r
+    viewport.setGlobalColourScheme(cs);\r
+\r
+    if (viewport.getColourAppliesToAllGroups())\r
+    {\r
+\r
+      for (SequenceGroup sg : viewport.getAlignment().getGroups())\r
+      {\r
+        if (cs == null)\r
+        {\r
+          sg.cs = null;\r
+          continue;\r
+        }\r
+\r
+        if (cs instanceof ClustalxColourScheme)\r
+        {\r
+          sg.cs = new ClustalxColourScheme(sg,\r
+                  viewport.getHiddenRepSequences());\r
+        }\r
+        else if (cs instanceof UserColourScheme)\r
+        {\r
+          sg.cs = new UserColourScheme(((UserColourScheme) cs).getColours());\r
+        }\r
+        else\r
+        {\r
+          try\r
+          {\r
+            sg.cs = cs.getClass().newInstance();\r
+          } catch (Exception ex)\r
+          {\r
+          }\r
+        }\r
+\r
+        if (viewport.getAbovePIDThreshold()\r
+                || cs instanceof PIDColourScheme\r
+                || cs instanceof Blosum62ColourScheme)\r
+        {\r
+          sg.cs.setThreshold(threshold, viewport.getIgnoreGapsConsensus());\r
+\r
+          sg.cs.setConsensus(AAFrequency.calculate(\r
+                  sg.getSequences(viewport.getHiddenRepSequences()),\r
+                  sg.getStartRes(), sg.getEndRes() + 1));\r
+        }\r
+        else\r
+        {\r
+          sg.cs.setThreshold(0, viewport.getIgnoreGapsConsensus());\r
+        }\r
+\r
+        if (viewport.getConservationSelected())\r
+        {\r
+          Conservation c = new Conservation("Group",\r
+                  ResidueProperties.propHash, 3, sg.getSequences(viewport\r
+                          .getHiddenRepSequences()), sg.getStartRes(),\r
+                  sg.getEndRes() + 1);\r
+          c.calculate();\r
+          c.verdict(false, viewport.getConsPercGaps());\r
+          sg.cs.setConservation(c);\r
+        }\r
+        else\r
+        {\r
+          sg.cs.setConservation(null);\r
+        }\r
+      }\r
+    }\r
+\r
+    if (alignPanel.getOverviewPanel() != null)\r
+    {\r
+      alignPanel.getOverviewPanel().updateOverviewImage();\r
+    }\r
+\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void modifyPID_actionPerformed(ActionEvent e)\r
+  {\r
+    if (viewport.getAbovePIDThreshold()\r
+            && viewport.getGlobalColourScheme() != null)\r
+    {\r
+      SliderPanel.setPIDSliderSource(alignPanel,\r
+              viewport.getGlobalColourScheme(), "Background");\r
+      SliderPanel.showPIDSlider();\r
+    }\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void modifyConservation_actionPerformed(ActionEvent e)\r
+  {\r
+    if (viewport.getConservationSelected()\r
+            && viewport.getGlobalColourScheme() != null)\r
+    {\r
+      SliderPanel.setConservationSlider(alignPanel,\r
+              viewport.getGlobalColourScheme(), "Background");\r
+      SliderPanel.showConservationSlider();\r
+    }\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void conservationMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setConservationSelected(conservationMenuItem.isSelected());\r
+\r
+    viewport.setAbovePIDThreshold(false);\r
+    abovePIDThreshold.setSelected(false);\r
+\r
+    changeColour(viewport.getGlobalColourScheme());\r
+\r
+    modifyConservation_actionPerformed(null);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void abovePIDThreshold_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setAbovePIDThreshold(abovePIDThreshold.isSelected());\r
+\r
+    conservationMenuItem.setSelected(false);\r
+    viewport.setConservationSelected(false);\r
+\r
+    changeColour(viewport.getGlobalColourScheme());\r
+\r
+    modifyPID_actionPerformed(null);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void userDefinedColour_actionPerformed(ActionEvent e)\r
+  {\r
+    if (e.getActionCommand().equals(MessageManager.getString("action.user_defined")))\r
+    {\r
+      new UserDefinedColours(alignPanel, null);\r
+    }\r
+    else\r
+    {\r
+      UserColourScheme udc = (UserColourScheme) UserDefinedColours\r
+              .getUserColourSchemes().get(e.getActionCommand());\r
+\r
+      changeColour(udc);\r
+    }\r
+  }\r
+\r
+  public void updateUserColourMenu()\r
+  {\r
+\r
+    Component[] menuItems = colourMenu.getMenuComponents();\r
+    int i, iSize = menuItems.length;\r
+    for (i = 0; i < iSize; i++)\r
+    {\r
+      if (menuItems[i].getName() != null\r
+              && menuItems[i].getName().equals("USER_DEFINED"))\r
+      {\r
+        colourMenu.remove(menuItems[i]);\r
+        iSize--;\r
+      }\r
+    }\r
+    if (jalview.gui.UserDefinedColours.getUserColourSchemes() != null)\r
+    {\r
+      java.util.Enumeration userColours = jalview.gui.UserDefinedColours\r
+              .getUserColourSchemes().keys();\r
+\r
+      while (userColours.hasMoreElements())\r
+      {\r
+        final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(\r
+                userColours.nextElement().toString());\r
+        radioItem.setName("USER_DEFINED");\r
+        radioItem.addMouseListener(new MouseAdapter()\r
+        {\r
+          @Override\r
+          public void mousePressed(MouseEvent evt)\r
+          {\r
+            if (evt.isControlDown()\r
+                    || SwingUtilities.isRightMouseButton(evt))\r
+            {\r
+              radioItem.removeActionListener(radioItem.getActionListeners()[0]);\r
+\r
+              int option = JOptionPane.showInternalConfirmDialog(\r
+                      jalview.gui.Desktop.desktop,\r
+                      MessageManager.getString("label.remove_from_default_list"),\r
+                      MessageManager.getString("label.remove_user_defined_colour"),\r
+                      JOptionPane.YES_NO_OPTION);\r
+              if (option == JOptionPane.YES_OPTION)\r
+              {\r
+                jalview.gui.UserDefinedColours\r
+                        .removeColourFromDefaults(radioItem.getText());\r
+                colourMenu.remove(radioItem);\r
+              }\r
+              else\r
+              {\r
+                radioItem.addActionListener(new ActionListener()\r
+                {\r
+                  @Override\r
+                  public void actionPerformed(ActionEvent evt)\r
+                  {\r
+                    userDefinedColour_actionPerformed(evt);\r
+                  }\r
+                });\r
+              }\r
+            }\r
+          }\r
+        });\r
+        radioItem.addActionListener(new ActionListener()\r
+        {\r
+          @Override\r
+          public void actionPerformed(ActionEvent evt)\r
+          {\r
+            userDefinedColour_actionPerformed(evt);\r
+          }\r
+        });\r
+\r
+        colourMenu.insert(radioItem, 15);\r
+        colours.add(radioItem);\r
+      }\r
+    }\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void PIDColour_actionPerformed(ActionEvent e)\r
+  {\r
+    changeColour(new PIDColourScheme());\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void BLOSUM62Colour_actionPerformed(ActionEvent e)\r
+  {\r
+    changeColour(new Blosum62ColourScheme());\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();\r
+    AlignmentSorter.sortByPID(viewport.getAlignment(), viewport\r
+            .getAlignment().getSequenceAt(0), null);\r
+    addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,\r
+            viewport.getAlignment()));\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void sortIDMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();\r
+    AlignmentSorter.sortByID(viewport.getAlignment());\r
+    addHistoryItem(new OrderCommand("ID Sort", oldOrder,\r
+            viewport.getAlignment()));\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void sortLengthMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();\r
+    AlignmentSorter.sortByLength(viewport.getAlignment());\r
+    addHistoryItem(new OrderCommand("Length Sort", oldOrder,\r
+            viewport.getAlignment()));\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void sortGroupMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();\r
+    AlignmentSorter.sortByGroup(viewport.getAlignment());\r
+    addHistoryItem(new OrderCommand("Group Sort", oldOrder,\r
+            viewport.getAlignment()));\r
+\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    new RedundancyPanel(alignPanel, this);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    if ((viewport.getSelectionGroup() == null)\r
+            || (viewport.getSelectionGroup().getSize() < 2))\r
+    {\r
+      JOptionPane.showInternalMessageDialog(this,\r
+              MessageManager.getString("label.you_must_select_least_two_sequences"), MessageManager.getString("label.invalid_selection"),\r
+              JOptionPane.WARNING_MESSAGE);\r
+    }\r
+    else\r
+    {\r
+      JInternalFrame frame = new JInternalFrame();\r
+      frame.setContentPane(new PairwiseAlignPanel(viewport));\r
+      Desktop.addInternalFrame(frame, MessageManager.getString("action.pairwise_alignment"), 600, 500);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void PCAMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    if (((viewport.getSelectionGroup() != null)\r
+            && (viewport.getSelectionGroup().getSize() < 4) && (viewport\r
+            .getSelectionGroup().getSize() > 0))\r
+            || (viewport.getAlignment().getHeight() < 4))\r
+    {\r
+      JOptionPane.showInternalMessageDialog(this,\r
+              MessageManager.getString("label.principal_component_analysis_must_take_least_four_input_sequences"),\r
+              MessageManager.getString("label.sequence_selection_insufficient"),\r
+              JOptionPane.WARNING_MESSAGE);\r
+\r
+      return;\r
+    }\r
+\r
+    new PCAPanel(alignPanel);\r
+  }\r
+\r
+  @Override\r
+  public void autoCalculate_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.autoCalculateConsensus = autoCalculate.isSelected();\r
+    if (viewport.autoCalculateConsensus)\r
+    {\r
+      viewport.firePropertyChange("alignment", null, viewport\r
+              .getAlignment().getSequences());\r
+    }\r
+  }\r
+\r
+  @Override\r
+  public void sortByTreeOption_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.sortByTree = sortByTree.isSelected();\r
+  }\r
+\r
+  @Override\r
+  protected void listenToViewSelections_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.followSelection = listenToViewSelections.isSelected();\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    NewTreePanel("AV", "PID", "Average distance tree using PID");\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param type\r
+   *          DOCUMENT ME!\r
+   * @param pwType\r
+   *          DOCUMENT ME!\r
+   * @param title\r
+   *          DOCUMENT ME!\r
+   */\r
+  void NewTreePanel(String type, String pwType, String title)\r
+  {\r
+    TreePanel tp;\r
+\r
+    if (viewport.getSelectionGroup() != null\r
+            && viewport.getSelectionGroup().getSize() > 0)\r
+    {\r
+      if (viewport.getSelectionGroup().getSize() < 3)\r
+      {\r
+        JOptionPane\r
+                .showMessageDialog(\r
+                        Desktop.desktop,\r
+                        MessageManager.getString("label.you_need_more_two_sequences_selected_build_tree"),\r
+                        MessageManager.getString("label.not_enough_sequences"), JOptionPane.WARNING_MESSAGE);\r
+        return;\r
+      }\r
+\r
+      SequenceGroup sg = viewport.getSelectionGroup();\r
+\r
+      /* Decide if the selection is a column region */\r
+      for (SequenceI _s : sg.getSequences())\r
+      {\r
+        if (_s.getLength() < sg.getEndRes())\r
+        {\r
+          JOptionPane\r
+                  .showMessageDialog(\r
+                          Desktop.desktop,\r
+                          MessageManager.getString("label.selected_region_to_tree_may_only_contain_residues_or_gaps"),\r
+                          MessageManager.getString("label.sequences_selection_not_aligned"),\r
+                          JOptionPane.WARNING_MESSAGE);\r
+\r
+          return;\r
+        }\r
+      }\r
+\r
+      title = title + " on region";\r
+      tp = new TreePanel(alignPanel, type, pwType);\r
+    }\r
+    else\r
+    {\r
+      // are the visible sequences aligned?\r
+      if (!viewport.getAlignment().isAligned(false))\r
+      {\r
+        JOptionPane\r
+                .showMessageDialog(\r
+                        Desktop.desktop,\r
+                        MessageManager.getString("label.sequences_must_be_aligned_before_creating_tree"),\r
+                        MessageManager.getString("label.sequences_not_aligned"),\r
+                        JOptionPane.WARNING_MESSAGE);\r
+\r
+        return;\r
+      }\r
+\r
+      if (viewport.getAlignment().getHeight() < 2)\r
+      {\r
+        return;\r
+      }\r
+\r
+      tp = new TreePanel(alignPanel, type, pwType);\r
+    }\r
+\r
+    title += " from ";\r
+\r
+    if (viewport.viewName != null)\r
+    {\r
+      title += viewport.viewName + " of ";\r
+    }\r
+\r
+    title += this.title;\r
+\r
+    Desktop.addInternalFrame(tp, title, 600, 500);\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param title\r
+   *          DOCUMENT ME!\r
+   * @param order\r
+   *          DOCUMENT ME!\r
+   */\r
+  public void addSortByOrderMenuItem(String title,\r
+          final AlignmentOrder order)\r
+  {\r
+    final JMenuItem item = new JMenuItem("by " + title);\r
+    sort.add(item);\r
+    item.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      @Override\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();\r
+\r
+        // TODO: JBPNote - have to map order entries to curent SequenceI\r
+        // pointers\r
+        AlignmentSorter.sortBy(viewport.getAlignment(), order);\r
+\r
+        addHistoryItem(new OrderCommand(order.getName(), oldOrder, viewport\r
+                .getAlignment()));\r
+\r
+        alignPanel.paintAlignment(true);\r
+      }\r
+    });\r
+  }\r
+\r
+  /**\r
+   * Add a new sort by annotation score menu item\r
+   * \r
+   * @param sort\r
+   *          the menu to add the option to\r
+   * @param scoreLabel\r
+   *          the label used to retrieve scores for each sequence on the\r
+   *          alignment\r
+   */\r
+  public void addSortByAnnotScoreMenuItem(JMenu sort,\r
+          final String scoreLabel)\r
+  {\r
+    final JMenuItem item = new JMenuItem(scoreLabel);\r
+    sort.add(item);\r
+    item.addActionListener(new java.awt.event.ActionListener()\r
+    {\r
+      @Override\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();\r
+        AlignmentSorter.sortByAnnotationScore(scoreLabel,\r
+                viewport.getAlignment());// ,viewport.getSelectionGroup());\r
+        addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,\r
+                viewport.getAlignment()));\r
+        alignPanel.paintAlignment(true);\r
+      }\r
+    });\r
+  }\r
+\r
+  /**\r
+   * last hash for alignment's annotation array - used to minimise cost of\r
+   * rebuild.\r
+   */\r
+  protected int _annotationScoreVectorHash;\r
+\r
+  /**\r
+   * search the alignment and rebuild the sort by annotation score submenu the\r
+   * last alignment annotation vector hash is stored to minimize cost of\r
+   * rebuilding in subsequence calls.\r
+   * \r
+   */\r
+  @Override\r
+  public void buildSortByAnnotationScoresMenu()\r
+  {\r
+    if (viewport.getAlignment().getAlignmentAnnotation() == null)\r
+    {\r
+      return;\r
+    }\r
+\r
+    if (viewport.getAlignment().getAlignmentAnnotation().hashCode() != _annotationScoreVectorHash)\r
+    {\r
+      sortByAnnotScore.removeAll();\r
+      // almost certainly a quicker way to do this - but we keep it simple\r
+      Hashtable scoreSorts = new Hashtable();\r
+      AlignmentAnnotation aann[];\r
+      for (SequenceI sqa : viewport.getAlignment().getSequences())\r
+      {\r
+        aann = sqa.getAnnotation();\r
+        for (int i = 0; aann != null && i < aann.length; i++)\r
+        {\r
+          if (aann[i].hasScore() && aann[i].sequenceRef != null)\r
+          {\r
+            scoreSorts.put(aann[i].label, aann[i].label);\r
+          }\r
+        }\r
+      }\r
+      Enumeration labels = scoreSorts.keys();\r
+      while (labels.hasMoreElements())\r
+      {\r
+        addSortByAnnotScoreMenuItem(sortByAnnotScore,\r
+                (String) labels.nextElement());\r
+      }\r
+      sortByAnnotScore.setVisible(scoreSorts.size() > 0);\r
+      scoreSorts.clear();\r
+\r
+      _annotationScoreVectorHash = viewport.getAlignment()\r
+              .getAlignmentAnnotation().hashCode();\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Maintain the Order by->Displayed Tree menu. Creates a new menu item for a\r
+   * TreePanel with an appropriate <code>jalview.analysis.AlignmentSorter</code>\r
+   * call. Listeners are added to remove the menu item when the treePanel is\r
+   * closed, and adjust the tree leaf to sequence mapping when the alignment is\r
+   * modified.\r
+   * \r
+   * @param treePanel\r
+   *          Displayed tree window.\r
+   * @param title\r
+   *          SortBy menu item title.\r
+   */\r
+  @Override\r
+  public void buildTreeMenu()\r
+  {\r
+    sortByTreeMenu.removeAll();\r
+\r
+    Vector comps = (Vector) PaintRefresher.components.get(viewport\r
+            .getSequenceSetId());\r
+    Vector treePanels = new Vector();\r
+    int i, iSize = comps.size();\r
+    for (i = 0; i < iSize; i++)\r
+    {\r
+      if (comps.elementAt(i) instanceof TreePanel)\r
+      {\r
+        treePanels.add(comps.elementAt(i));\r
+      }\r
+    }\r
+\r
+    iSize = treePanels.size();\r
+\r
+    if (iSize < 1)\r
+    {\r
+      sortByTreeMenu.setVisible(false);\r
+      return;\r
+    }\r
+\r
+    sortByTreeMenu.setVisible(true);\r
+\r
+    for (i = 0; i < treePanels.size(); i++)\r
+    {\r
+      final TreePanel tp = (TreePanel) treePanels.elementAt(i);\r
+      final JMenuItem item = new JMenuItem(tp.getTitle());\r
+      final NJTree tree = ((TreePanel) treePanels.elementAt(i)).getTree();\r
+      item.addActionListener(new java.awt.event.ActionListener()\r
+      {\r
+        @Override\r
+        public void actionPerformed(ActionEvent e)\r
+        {\r
+          tp.sortByTree_actionPerformed(null);\r
+          addHistoryItem(tp.sortAlignmentIn(alignPanel));\r
+\r
+        }\r
+      });\r
+\r
+      sortByTreeMenu.add(item);\r
+    }\r
+  }\r
+\r
+  public boolean sortBy(AlignmentOrder alorder, String undoname)\r
+  {\r
+    SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();\r
+    AlignmentSorter.sortBy(viewport.getAlignment(), alorder);\r
+    if (undoname != null)\r
+    {\r
+      addHistoryItem(new OrderCommand(undoname, oldOrder,\r
+              viewport.getAlignment()));\r
+    }\r
+    alignPanel.paintAlignment(true);\r
+    return true;\r
+  }\r
+\r
+  /**\r
+   * Work out whether the whole set of sequences or just the selected set will\r
+   * be submitted for multiple alignment.\r
+   * \r
+   */\r
+  public jalview.datamodel.AlignmentView gatherSequencesForAlignment()\r
+  {\r
+    // Now, check we have enough sequences\r
+    AlignmentView msa = null;\r
+\r
+    if ((viewport.getSelectionGroup() != null)\r
+            && (viewport.getSelectionGroup().getSize() > 1))\r
+    {\r
+      // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to\r
+      // some common interface!\r
+      /*\r
+       * SequenceGroup seqs = viewport.getSelectionGroup(); int sz; msa = new\r
+       * SequenceI[sz = seqs.getSize(false)];\r
+       * \r
+       * for (int i = 0; i < sz; i++) { msa[i] = (SequenceI)\r
+       * seqs.getSequenceAt(i); }\r
+       */\r
+      msa = viewport.getAlignmentView(true);\r
+    }\r
+    else\r
+    {\r
+      /*\r
+       * Vector seqs = viewport.getAlignment().getSequences();\r
+       * \r
+       * if (seqs.size() > 1) { msa = new SequenceI[seqs.size()];\r
+       * \r
+       * for (int i = 0; i < seqs.size(); i++) { msa[i] = (SequenceI)\r
+       * seqs.elementAt(i); } }\r
+       */\r
+      msa = viewport.getAlignmentView(false);\r
+    }\r
+    return msa;\r
+  }\r
+\r
+  /**\r
+   * Decides what is submitted to a secondary structure prediction service: the\r
+   * first sequence in the alignment, or in the current selection, or, if the\r
+   * alignment is 'aligned' (ie padded with gaps), then the currently selected\r
+   * region or the whole alignment. (where the first sequence in the set is the\r
+   * one that the prediction will be for).\r
+   */\r
+  public AlignmentView gatherSeqOrMsaForSecStrPrediction()\r
+  {\r
+    AlignmentView seqs = null;\r
+\r
+    if ((viewport.getSelectionGroup() != null)\r
+            && (viewport.getSelectionGroup().getSize() > 0))\r
+    {\r
+      seqs = viewport.getAlignmentView(true);\r
+    }\r
+    else\r
+    {\r
+      seqs = viewport.getAlignmentView(false);\r
+    }\r
+    // limit sequences - JBPNote in future - could spawn multiple prediction\r
+    // jobs\r
+    // TODO: viewport.getAlignment().isAligned is a global state - the local\r
+    // selection may well be aligned - we preserve 2.0.8 behaviour for moment.\r
+    if (!viewport.getAlignment().isAligned(false))\r
+    {\r
+      seqs.setSequences(new SeqCigar[]\r
+      { seqs.getSequences()[0] });\r
+      // TODO: if seqs.getSequences().length>1 then should really have warned\r
+      // user!\r
+\r
+    }\r
+    return seqs;\r
+  }\r
+\r
+  /**\r
+   * DOCUMENT ME!\r
+   * \r
+   * @param e\r
+   *          DOCUMENT ME!\r
+   */\r
+  @Override\r
+  protected void LoadtreeMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    // Pick the tree file\r
+    JalviewFileChooser chooser = new JalviewFileChooser(\r
+            jalview.bin.Cache.getProperty("LAST_DIRECTORY"));\r
+    chooser.setFileView(new JalviewFileView());\r
+    chooser.setDialogTitle(MessageManager.getString("label.select_newick_like_tree_file"));\r
+    chooser.setToolTipText(MessageManager.getString("label.load_tree_file"));\r
+\r
+    int value = chooser.showOpenDialog(null);\r
+\r
+    if (value == JalviewFileChooser.APPROVE_OPTION)\r
+    {\r
+      String choice = chooser.getSelectedFile().getPath();\r
+      jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);\r
+      jalview.io.NewickFile fin = null;\r
+      try\r
+      {\r
+        fin = new jalview.io.NewickFile(choice, "File");\r
+        viewport.setCurrentTree(ShowNewickTree(fin, choice).getTree());\r
+      } catch (Exception ex)\r
+      {\r
+        JOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(),\r
+                MessageManager.getString("label.problem_reading_tree_file"), JOptionPane.WARNING_MESSAGE);\r
+        ex.printStackTrace();\r
+      }\r
+      if (fin != null && fin.hasWarningMessage())\r
+      {\r
+        JOptionPane.showMessageDialog(Desktop.desktop,\r
+                fin.getWarningMessage(), MessageManager.getString("label.possible_problem_with_tree_file"),\r
+                JOptionPane.WARNING_MESSAGE);\r
+      }\r
+    }\r
+  }\r
+\r
+  @Override\r
+  protected void tcoffeeColorScheme_actionPerformed(ActionEvent e)\r
+  {\r
+    changeColour(new TCoffeeColourScheme(alignPanel.getAlignment()));\r
+  }\r
+\r
+  public TreePanel ShowNewickTree(NewickFile nf, String title)\r
+  {\r
+    return ShowNewickTree(nf, title, 600, 500, 4, 5);\r
+  }\r
+\r
+  public TreePanel ShowNewickTree(NewickFile nf, String title,\r
+          AlignmentView input)\r
+  {\r
+    return ShowNewickTree(nf, title, input, 600, 500, 4, 5);\r
+  }\r
+\r
+  public TreePanel ShowNewickTree(NewickFile nf, String title, int w,\r
+          int h, int x, int y)\r
+  {\r
+    return ShowNewickTree(nf, title, null, w, h, x, y);\r
+  }\r
+\r
+  /**\r
+   * Add a treeviewer for the tree extracted from a newick file object to the\r
+   * current alignment view\r
+   * \r
+   * @param nf\r
+   *          the tree\r
+   * @param title\r
+   *          tree viewer title\r
+   * @param input\r
+   *          Associated alignment input data (or null)\r
+   * @param w\r
+   *          width\r
+   * @param h\r
+   *          height\r
+   * @param x\r
+   *          position\r
+   * @param y\r
+   *          position\r
+   * @return TreePanel handle\r
+   */\r
+  public TreePanel ShowNewickTree(NewickFile nf, String title,\r
+          AlignmentView input, int w, int h, int x, int y)\r
+  {\r
+    TreePanel tp = null;\r
+\r
+    try\r
+    {\r
+      nf.parse();\r
+\r
+      if (nf.getTree() != null)\r
+      {\r
+        tp = new TreePanel(alignPanel, "FromFile", title, nf, input);\r
+\r
+        tp.setSize(w, h);\r
+\r
+        if (x > 0 && y > 0)\r
+        {\r
+          tp.setLocation(x, y);\r
+        }\r
+\r
+        Desktop.addInternalFrame(tp, title, w, h);\r
+      }\r
+    } catch (Exception ex)\r
+    {\r
+      ex.printStackTrace();\r
+    }\r
+\r
+    return tp;\r
+  }\r
+\r
+  private boolean buildingMenu = false;\r
+\r
+  /**\r
+   * Generates menu items and listener event actions for web service clients\r
+   * \r
+   */\r
+  public void BuildWebServiceMenu()\r
+  {\r
+    while (buildingMenu)\r
+    {\r
+      try\r
+      {\r
+        System.err.println("Waiting for building menu to finish.");\r
+        Thread.sleep(10);\r
+      } catch (Exception e)\r
+      {\r
+      }\r
+      ;\r
+    }\r
+    final AlignFrame me = this;\r
+    buildingMenu = true;\r
+    new Thread(new Runnable()\r
+    {\r
+      @Override\r
+      public void run()\r
+      {\r
+        final List<JMenuItem> legacyItems=new ArrayList<JMenuItem>();\r
+        try\r
+        {\r
+          System.err.println("Building ws menu again "\r
+                  + Thread.currentThread());\r
+          // TODO: add support for context dependent disabling of services based\r
+          // on\r
+          // alignment and current selection\r
+          // TODO: add additional serviceHandle parameter to specify abstract\r
+          // handler\r
+          // class independently of AbstractName\r
+          // TODO: add in rediscovery GUI function to restart discoverer\r
+          // TODO: group services by location as well as function and/or\r
+          // introduce\r
+          // object broker mechanism.\r
+          final Vector<JMenu> wsmenu = new Vector<JMenu>();\r
+          final IProgressIndicator af = me;\r
+          final JMenu msawsmenu = new JMenu("Alignment");\r
+          final JMenu secstrmenu = new JMenu(\r
+                  "Secondary Structure Prediction");\r
+          final JMenu seqsrchmenu = new JMenu("Sequence Database Search");\r
+          final JMenu analymenu = new JMenu("Analysis");\r
+          final JMenu dismenu = new JMenu("Protein Disorder");\r
+          // JAL-940 - only show secondary structure prediction services from\r
+          // the legacy server\r
+          if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)\r
+              // &&\r
+          Discoverer.services != null && (Discoverer.services.size() > 0))\r
+          {\r
+            // TODO: refactor to allow list of AbstractName/Handler bindings to\r
+            // be\r
+            // stored or retrieved from elsewhere\r
+            // No MSAWS used any more:\r
+            // Vector msaws = null; // (Vector) Discoverer.services.get("MsaWS");\r
+            Vector secstrpr = (Vector) Discoverer.services\r
+                    .get("SecStrPred");\r
+            if (secstrpr != null)\r
+            {\r
+              // Add any secondary structure prediction services\r
+              for (int i = 0, j = secstrpr.size(); i < j; i++)\r
+              {\r
+                final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle) secstrpr\r
+                        .get(i);\r
+                jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer\r
+                        .getServiceClient(sh);\r
+                int p=secstrmenu.getItemCount();\r
+                impl.attachWSMenuEntry(secstrmenu, me);\r
+                int q=secstrmenu.getItemCount();\r
+                for (int litm=p;litm<q; litm++)\r
+                {\r
+                  legacyItems.add(secstrmenu.getItem(litm));\r
+                }\r
+              }\r
+            }\r
+          }\r
+          \r
+          // Add all submenus in the order they should appear on the web\r
+          // services menu\r
+          wsmenu.add(msawsmenu);\r
+          wsmenu.add(secstrmenu);\r
+          wsmenu.add(dismenu);\r
+          wsmenu.add(analymenu);\r
+          // No search services yet\r
+          // wsmenu.add(seqsrchmenu);\r
+\r
+          javax.swing.SwingUtilities.invokeLater(new Runnable()\r
+          {\r
+            @Override\r
+            public void run()\r
+            {\r
+              try\r
+              {\r
+                webService.removeAll();\r
+                // first, add discovered services onto the webservices menu\r
+                if (wsmenu.size() > 0)\r
+                {\r
+                  for (int i = 0, j = wsmenu.size(); i < j; i++)\r
+                  {\r
+                    webService.add(wsmenu.get(i));\r
+                  }\r
+                }\r
+                else\r
+                {\r
+                  webService.add(me.webServiceNoServices);\r
+                }\r
+                // TODO: move into separate menu builder class.\r
+                boolean new_sspred=false;\r
+                if (Cache.getDefault("SHOW_JWS2_SERVICES", true))\r
+                {\r
+                  Jws2Discoverer jws2servs = Jws2Discoverer.getDiscoverer();\r
+                  if (jws2servs != null)\r
+                  {\r
+                    if (jws2servs.hasServices())\r
+                    {\r
+                      jws2servs.attachWSMenuEntry(webService, me);\r
+                      for (Jws2Instance sv:jws2servs.getServices()) {\r
+                        if (sv.description.toLowerCase().contains("jpred"))\r
+                        {\r
+                          for (JMenuItem jmi:legacyItems)\r
+                          {\r
+                            jmi.setVisible(false);\r
+                          }\r
+                        }\r
+                      }\r
+                      \r
+                    }\r
+                    if (jws2servs.isRunning())\r
+                    {\r
+                      JMenuItem tm = new JMenuItem(\r
+                              "Still discovering JABA Services");\r
+                      tm.setEnabled(false);\r
+                      webService.add(tm);\r
+                    }\r
+                  }\r
+                }\r
+                build_urlServiceMenu(me.webService);\r
+                build_fetchdbmenu(webService);\r
+                for (JMenu item : wsmenu)\r
+                {\r
+                  if (item.getItemCount() == 0)\r
+                  {\r
+                    item.setEnabled(false);\r
+                  }\r
+                  else\r
+                  {\r
+                    item.setEnabled(true);\r
+                  }\r
+                }\r
+              } catch (Exception e)\r
+              {\r
+                Cache.log\r
+                        .debug("Exception during web service menu building process.",\r
+                                e);\r
+              }\r
+              ;\r
+            }\r
+          });\r
+        } catch (Exception e)\r
+        {\r
+        }\r
+        ;\r
+\r
+        buildingMenu = false;\r
+      }\r
+    }).start();\r
+\r
+  }\r
+\r
+  /**\r
+   * construct any groupURL type service menu entries.\r
+   * \r
+   * @param webService\r
+   */\r
+  private void build_urlServiceMenu(JMenu webService)\r
+  {\r
+    // TODO: remove this code when 2.7 is released\r
+    // DEBUG - alignmentView\r
+    /*\r
+     * JMenuItem testAlView = new JMenuItem("Test AlignmentView"); final\r
+     * AlignFrame af = this; testAlView.addActionListener(new ActionListener() {\r
+     * \r
+     * @Override public void actionPerformed(ActionEvent e) {\r
+     * jalview.datamodel.AlignmentView\r
+     * .testSelectionViews(af.viewport.getAlignment(),\r
+     * af.viewport.getColumnSelection(), af.viewport.selectionGroup); }\r
+     * \r
+     * }); webService.add(testAlView);\r
+     */\r
+    // TODO: refactor to RestClient discoverer and merge menu entries for\r
+    // rest-style services with other types of analysis/calculation service\r
+    // SHmmr test client - still being implemented.\r
+    // DEBUG - alignmentView\r
+\r
+    for (jalview.ws.rest.RestClient client : jalview.ws.rest.RestClient\r
+            .getRestClients())\r
+    {\r
+      client.attachWSMenuEntry(\r
+              JvSwingUtils.findOrCreateMenu(webService, client.getAction()),\r
+              this);\r
+    }\r
+\r
+    if (Cache.getDefault("SHOW_ENFIN_SERVICES", true))\r
+    {\r
+      jalview.ws.EnfinEnvision2OneWay.getInstance().attachWSMenuEntry(\r
+              webService, this);\r
+    }\r
+  }\r
+\r
+  /*\r
+   * public void vamsasStore_actionPerformed(ActionEvent e) { JalviewFileChooser\r
+   * chooser = new JalviewFileChooser(jalview.bin.Cache.\r
+   * getProperty("LAST_DIRECTORY"));\r
+   * \r
+   * chooser.setFileView(new JalviewFileView()); chooser.setDialogTitle("Export\r
+   * to Vamsas file"); chooser.setToolTipText("Export");\r
+   * \r
+   * int value = chooser.showSaveDialog(this);\r
+   * \r
+   * if (value == JalviewFileChooser.APPROVE_OPTION) {\r
+   * jalview.io.VamsasDatastore vs = new jalview.io.VamsasDatastore(viewport);\r
+   * //vs.store(chooser.getSelectedFile().getAbsolutePath() ); vs.storeJalview(\r
+   * chooser.getSelectedFile().getAbsolutePath(), this); } }\r
+   */\r
+  /**\r
+   * prototype of an automatically enabled/disabled analysis function\r
+   * \r
+   */\r
+  protected void setShowProductsEnabled()\r
+  {\r
+    SequenceI[] selection = viewport.getSequenceSelection();\r
+    if (canShowProducts(selection, viewport.getSelectionGroup() != null,\r
+            viewport.getAlignment().getDataset()))\r
+    {\r
+      showProducts.setEnabled(true);\r
+\r
+    }\r
+    else\r
+    {\r
+      showProducts.setEnabled(false);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * search selection for sequence xRef products and build the show products\r
+   * menu.\r
+   * \r
+   * @param selection\r
+   * @param dataset\r
+   * @return true if showProducts menu should be enabled.\r
+   */\r
+  public boolean canShowProducts(SequenceI[] selection,\r
+          boolean isRegionSelection, Alignment dataset)\r
+  {\r
+    boolean showp = false;\r
+    try\r
+    {\r
+      showProducts.removeAll();\r
+      final boolean dna = viewport.getAlignment().isNucleotide();\r
+      final Alignment ds = dataset;\r
+      String[] ptypes = (selection == null || selection.length == 0) ? null\r
+              : CrossRef.findSequenceXrefTypes(dna, selection, dataset);\r
+      // Object[] prods =\r
+      // CrossRef.buildXProductsList(viewport.getAlignment().isNucleotide(),\r
+      // selection, dataset, true);\r
+      final SequenceI[] sel = selection;\r
+      for (int t = 0; ptypes != null && t < ptypes.length; t++)\r
+      {\r
+        showp = true;\r
+        final boolean isRegSel = isRegionSelection;\r
+        final AlignFrame af = this;\r
+        final String source = ptypes[t];\r
+        JMenuItem xtype = new JMenuItem(ptypes[t]);\r
+        xtype.addActionListener(new ActionListener()\r
+        {\r
+\r
+          @Override\r
+          public void actionPerformed(ActionEvent e)\r
+          {\r
+            // TODO: new thread for this call with vis-delay\r
+            af.showProductsFor(af.viewport.getSequenceSelection(), ds,\r
+                    isRegSel, dna, source);\r
+          }\r
+\r
+        });\r
+        showProducts.add(xtype);\r
+      }\r
+      showProducts.setVisible(showp);\r
+      showProducts.setEnabled(showp);\r
+    } catch (Exception e)\r
+    {\r
+      jalview.bin.Cache.log\r
+              .warn("canTranslate threw an exception - please report to help@jalview.org",\r
+                      e);\r
+      return false;\r
+    }\r
+    return showp;\r
+  }\r
+\r
+  protected void showProductsFor(SequenceI[] sel, Alignment ds,\r
+          boolean isRegSel, boolean dna, String source)\r
+  {\r
+    final boolean fisRegSel = isRegSel;\r
+    final boolean fdna = dna;\r
+    final String fsrc = source;\r
+    final AlignFrame ths = this;\r
+    final SequenceI[] fsel = sel;\r
+    Runnable foo = new Runnable()\r
+    {\r
+\r
+      @Override\r
+      public void run()\r
+      {\r
+        final long sttime = System.currentTimeMillis();\r
+        ths.setProgressBar("Searching for sequences from " + fsrc, sttime);\r
+        try\r
+        {\r
+          Alignment ds = ths.getViewport().getAlignment().getDataset(); // update\r
+          // our local\r
+          // dataset\r
+          // reference\r
+          Alignment prods = CrossRef\r
+                  .findXrefSequences(fsel, fdna, fsrc, ds);\r
+          if (prods != null)\r
+          {\r
+            SequenceI[] sprods = new SequenceI[prods.getHeight()];\r
+            for (int s = 0; s < sprods.length; s++)\r
+            {\r
+              sprods[s] = (prods.getSequenceAt(s)).deriveSequence();\r
+              if (ds.getSequences() == null\r
+                      || !ds.getSequences().contains(\r
+                              sprods[s].getDatasetSequence()))\r
+                ds.addSequence(sprods[s].getDatasetSequence());\r
+              sprods[s].updatePDBIds();\r
+            }\r
+            Alignment al = new Alignment(sprods);\r
+            AlignedCodonFrame[] cf = prods.getCodonFrames();\r
+            al.setDataset(ds);\r
+            for (int s = 0; cf != null && s < cf.length; s++)\r
+            {\r
+              al.addCodonFrame(cf[s]);\r
+              cf[s] = null;\r
+            }\r
+            AlignFrame naf = new AlignFrame(al, DEFAULT_WIDTH,\r
+                    DEFAULT_HEIGHT);\r
+            String newtitle = "" + ((fdna) ? "Proteins " : "Nucleotides ")\r
+                    + " for " + ((fisRegSel) ? "selected region of " : "")\r
+                    + getTitle();\r
+            Desktop.addInternalFrame(naf, newtitle, DEFAULT_WIDTH,\r
+                    DEFAULT_HEIGHT);\r
+          }\r
+          else\r
+          {\r
+            System.err.println("No Sequences generated for xRef type "\r
+                    + fsrc);\r
+          }\r
+        } catch (Exception e)\r
+        {\r
+          jalview.bin.Cache.log.error(\r
+                  "Exception when finding crossreferences", e);\r
+        } catch (OutOfMemoryError e)\r
+        {\r
+          new OOMWarning("whilst fetching crossreferences", e);\r
+        } catch (Error e)\r
+        {\r
+          jalview.bin.Cache.log.error("Error when finding crossreferences",\r
+                  e);\r
+        }\r
+        ths.setProgressBar("Finished searching for sequences from " + fsrc,\r
+                sttime);\r
+      }\r
+\r
+    };\r
+    Thread frunner = new Thread(foo);\r
+    frunner.start();\r
+  }\r
+\r
+  public boolean canShowTranslationProducts(SequenceI[] selection,\r
+          AlignmentI alignment)\r
+  {\r
+    // old way\r
+    try\r
+    {\r
+      return (jalview.analysis.Dna.canTranslate(selection,\r
+              viewport.getViewAsVisibleContigs(true)));\r
+    } catch (Exception e)\r
+    {\r
+      jalview.bin.Cache.log\r
+              .warn("canTranslate threw an exception - please report to help@jalview.org",\r
+                      e);\r
+      return false;\r
+    }\r
+  }\r
+\r
+  @Override\r
+  public void showProducts_actionPerformed(ActionEvent e)\r
+  {\r
+    // /////////////////////////////\r
+    // Collect Data to be translated/transferred\r
+\r
+    SequenceI[] selection = viewport.getSequenceSelection();\r
+    AlignmentI al = null;\r
+    try\r
+    {\r
+      al = jalview.analysis.Dna.CdnaTranslate(selection, viewport\r
+              .getViewAsVisibleContigs(true), viewport.getGapCharacter(),\r
+              viewport.getAlignment().getDataset());\r
+    } catch (Exception ex)\r
+    {\r
+      al = null;\r
+      jalview.bin.Cache.log.debug("Exception during translation.", ex);\r
+    }\r
+    if (al == null)\r
+    {\r
+      JOptionPane\r
+              .showMessageDialog(\r
+                      Desktop.desktop,\r
+                      MessageManager.getString("label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation"),\r
+                      MessageManager.getString("label.translation_failed"), JOptionPane.WARNING_MESSAGE);\r
+    }\r
+    else\r
+    {\r
+      AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);\r
+      Desktop.addInternalFrame(af, MessageManager.formatMessage("label.translation_of_params", new String[]{this.getTitle()}),\r
+              DEFAULT_WIDTH, DEFAULT_HEIGHT);\r
+    }\r
+  }\r
+\r
+  @Override\r
+  public void showTranslation_actionPerformed(ActionEvent e)\r
+  {\r
+    // /////////////////////////////\r
+    // Collect Data to be translated/transferred\r
+\r
+    SequenceI[] selection = viewport.getSequenceSelection();\r
+    String[] seqstring = viewport.getViewAsString(true);\r
+    AlignmentI al = null;\r
+    try\r
+    {\r
+      al = jalview.analysis.Dna.CdnaTranslate(selection, seqstring,\r
+              viewport.getViewAsVisibleContigs(true), viewport\r
+                      .getGapCharacter(), viewport.getAlignment()\r
+                      .getAlignmentAnnotation(), viewport.getAlignment()\r
+                      .getWidth(), viewport.getAlignment().getDataset());\r
+    } catch (Exception ex)\r
+    {\r
+      al = null;\r
+      jalview.bin.Cache.log.error("Exception during translation. Please report this !", ex);\r
+      JOptionPane\r
+      .showMessageDialog(\r
+              Desktop.desktop,\r
+              MessageManager.getString("label.error_when_translating_sequences_submit_bug_report"),\r
+              MessageManager.getString("label.implementation_error") + MessageManager.getString("translation_failed"), JOptionPane.ERROR_MESSAGE);\r
+      return;\r
+    }\r
+    if (al == null)\r
+    {\r
+      JOptionPane\r
+              .showMessageDialog(\r
+                      Desktop.desktop,\r
+                      MessageManager.getString("label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation"),\r
+                      MessageManager.getString("label.translation_failed"), JOptionPane.WARNING_MESSAGE);\r
+    }\r
+    else\r
+    {\r
+      AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);\r
+      Desktop.addInternalFrame(af, MessageManager.formatMessage("label.translation_of_params", new String[]{this.getTitle()}),\r
+              DEFAULT_WIDTH, DEFAULT_HEIGHT);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Try to load a features file onto the alignment.\r
+   * \r
+   * @param file\r
+   *          contents or path to retrieve file\r
+   * @param type\r
+   *          access mode of file (see jalview.io.AlignFile)\r
+   * @return true if features file was parsed corectly.\r
+   */\r
+  public boolean parseFeaturesFile(String file, String type)\r
+  {\r
+    boolean featuresFile = false;\r
+    try\r
+    {\r
+      featuresFile = new FeaturesFile(file, type).parse(viewport\r
+              .getAlignment().getDataset(), alignPanel.seqPanel.seqCanvas\r
+              .getFeatureRenderer().featureColours, false,\r
+              jalview.bin.Cache.getDefault("RELAXEDSEQIDMATCHING", false));\r
+    } catch (Exception ex)\r
+    {\r
+      ex.printStackTrace();\r
+    }\r
+\r
+    if (featuresFile)\r
+    {\r
+      viewport.showSequenceFeatures = true;\r
+      showSeqFeatures.setSelected(true);\r
+      if (alignPanel.seqPanel.seqCanvas.fr != null)\r
+      {\r
+        // update the min/max ranges where necessary\r
+        alignPanel.seqPanel.seqCanvas.fr.findAllFeatures(true);\r
+      }\r
+      if (featureSettings != null)\r
+      {\r
+        featureSettings.setTableData();\r
+      }\r
+      alignPanel.paintAlignment(true);\r
+    }\r
+\r
+    return featuresFile;\r
+  }\r
+\r
+  @Override\r
+  public void dragEnter(DropTargetDragEvent evt)\r
+  {\r
+  }\r
+\r
+  @Override\r
+  public void dragExit(DropTargetEvent evt)\r
+  {\r
+  }\r
+\r
+  @Override\r
+  public void dragOver(DropTargetDragEvent evt)\r
+  {\r
+  }\r
+\r
+  @Override\r
+  public void dropActionChanged(DropTargetDragEvent evt)\r
+  {\r
+  }\r
+\r
+  @Override\r
+  public void drop(DropTargetDropEvent evt)\r
+  {\r
+    Transferable t = evt.getTransferable();\r
+    java.util.List files = null;\r
+\r
+    try\r
+    {\r
+      DataFlavor uriListFlavor = new DataFlavor(\r
+              "text/uri-list;class=java.lang.String");\r
+      if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))\r
+      {\r
+        // Works on Windows and MacOSX\r
+        evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);\r
+        files = (java.util.List) t\r
+                .getTransferData(DataFlavor.javaFileListFlavor);\r
+      }\r
+      else if (t.isDataFlavorSupported(uriListFlavor))\r
+      {\r
+        // This is used by Unix drag system\r
+        evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);\r
+        String data = (String) t.getTransferData(uriListFlavor);\r
+        files = new java.util.ArrayList(1);\r
+        for (java.util.StringTokenizer st = new java.util.StringTokenizer(\r
+                data, "\r\n"); st.hasMoreTokens();)\r
+        {\r
+          String s = st.nextToken();\r
+          if (s.startsWith("#"))\r
+          {\r
+            // the line is a comment (as per the RFC 2483)\r
+            continue;\r
+          }\r
+\r
+          java.net.URI uri = new java.net.URI(s);\r
+          // check to see if we can handle this kind of URI\r
+          if (uri.getScheme().toLowerCase().startsWith("http"))\r
+          {\r
+            files.add(uri.toString());\r
+          }\r
+          else\r
+          {\r
+            // otherwise preserve old behaviour: catch all for file objects\r
+            java.io.File file = new java.io.File(uri);\r
+            files.add(file.toString());\r
+          }\r
+        }\r
+      }\r
+    } catch (Exception e)\r
+    {\r
+      e.printStackTrace();\r
+    }\r
+    if (files != null)\r
+    {\r
+      try\r
+      {\r
+        // check to see if any of these files have names matching sequences in\r
+        // the alignment\r
+        SequenceIdMatcher idm = new SequenceIdMatcher(viewport\r
+                .getAlignment().getSequencesArray());\r
+        /**\r
+         * Object[] { String,SequenceI}\r
+         */\r
+        ArrayList<Object[]> filesmatched = new ArrayList<Object[]>();\r
+        ArrayList<String> filesnotmatched = new ArrayList<String>();\r
+        for (int i = 0; i < files.size(); i++)\r
+        {\r
+          String file = files.get(i).toString();\r
+          String pdbfn = "";\r
+          String protocol = FormatAdapter.checkProtocol(file);\r
+          if (protocol == jalview.io.FormatAdapter.FILE)\r
+          {\r
+            File fl = new File(file);\r
+            pdbfn = fl.getName();\r
+          }\r
+          else if (protocol == jalview.io.FormatAdapter.URL)\r
+          {\r
+            URL url = new URL(file);\r
+            pdbfn = url.getFile();\r
+          }\r
+          if (pdbfn.length() > 0)\r
+          {\r
+            // attempt to find a match in the alignment\r
+            SequenceI[] mtch = idm.findAllIdMatches(pdbfn);\r
+            int l = 0, c = pdbfn.indexOf(".");\r
+            while (mtch == null && c != -1)\r
+            {\r
+              do\r
+              {\r
+                l = c;\r
+              } while ((c = pdbfn.indexOf(".", l)) > l);\r
+              if (l > -1)\r
+              {\r
+                pdbfn = pdbfn.substring(0, l);\r
+              }\r
+              mtch = idm.findAllIdMatches(pdbfn);\r
+            }\r
+            if (mtch != null)\r
+            {\r
+              String type = null;\r
+              try\r
+              {\r
+                type = new IdentifyFile().Identify(file, protocol);\r
+              } catch (Exception ex)\r
+              {\r
+                type = null;\r
+              }\r
+              if (type != null)\r
+              {\r
+                if (type.equalsIgnoreCase("PDB"))\r
+                {\r
+                  filesmatched.add(new Object[]\r
+                  { file, protocol, mtch });\r
+                  continue;\r
+                }\r
+              }\r
+            }\r
+            // File wasn't named like one of the sequences or wasn't a PDB file.\r
+            filesnotmatched.add(file);\r
+          }\r
+        }\r
+        int assocfiles = 0;\r
+        if (filesmatched.size() > 0)\r
+        {\r
+          if (Cache.getDefault("AUTOASSOCIATE_PDBANDSEQS", false)\r
+                  || JOptionPane\r
+                          .showConfirmDialog(\r
+                                  this,\r
+                                  MessageManager.formatMessage("label.automatically_associate_pdb_files_with_sequences_same_name",\r
+                                                 new String[]{Integer.valueOf(filesmatched.size()).toString()}),\r
+                                  MessageManager.getString("label.automatically_associate_pdb_files_by_name"),\r
+                                  JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION)\r
+\r
+          {\r
+            for (Object[] fm : filesmatched)\r
+            {\r
+              // try and associate\r
+              // TODO: may want to set a standard ID naming formalism for\r
+              // associating PDB files which have no IDs.\r
+              for (SequenceI toassoc : (SequenceI[]) fm[2])\r
+              {\r
+                PDBEntry pe = new AssociatePdbFileWithSeq()\r
+                        .associatePdbWithSeq((String) fm[0],\r
+                                (String) fm[1], toassoc, false);\r
+                if (pe != null)\r
+                {\r
+                  System.err.println("Associated file : "\r
+                          + ((String) fm[0]) + " with "\r
+                          + toassoc.getDisplayId(true));\r
+                  assocfiles++;\r
+                }\r
+              }\r
+              alignPanel.paintAlignment(true);\r
+            }\r
+          }\r
+        }\r
+        if (filesnotmatched.size() > 0)\r
+        {\r
+          if (assocfiles > 0\r
+                  && (Cache.getDefault(\r
+                          "AUTOASSOCIATE_PDBANDSEQS_IGNOREOTHERS", false) || JOptionPane\r
+                          .showConfirmDialog(\r
+                                  this,\r
+                                  MessageManager.formatMessage("label.ignore_unmatched_dropped_files_info", new String[]{Integer.valueOf(filesnotmatched.size()).toString()}),\r
+                                  MessageManager.getString("label.ignore_unmatched_dropped_files"),\r
+                                  JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION))\r
+          {\r
+            return;\r
+          }\r
+          for (String fn : filesnotmatched)\r
+          {\r
+            loadJalviewDataFile(fn, null, null, null);\r
+          }\r
+\r
+        }\r
+      } catch (Exception ex)\r
+      {\r
+        ex.printStackTrace();\r
+      }\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Attempt to load a "dropped" file or URL string: First by testing whether\r
+   * it's and Annotation file, then a JNet file, and finally a features file. If\r
+   * all are false then the user may have dropped an alignment file onto this\r
+   * AlignFrame.\r
+   * \r
+   * @param file\r
+   *          either a filename or a URL string.\r
+   */\r
+  public void loadJalviewDataFile(String file, String protocol,\r
+          String format, SequenceI assocSeq)\r
+  {\r
+    try\r
+    {\r
+      if (protocol == null)\r
+      {\r
+        protocol = jalview.io.FormatAdapter.checkProtocol(file);\r
+      }\r
+      // if the file isn't identified, or not positively identified as some\r
+      // other filetype (PFAM is default unidentified alignment file type) then\r
+      // try to parse as annotation.\r
+      boolean isAnnotation = (format == null || format\r
+              .equalsIgnoreCase("PFAM")) ? new AnnotationFile()\r
+              .readAnnotationFile(viewport.getAlignment(), file, protocol)\r
+              : false;\r
+\r
+      if (!isAnnotation)\r
+      {\r
+        // first see if its a T-COFFEE score file\r
+        TCoffeeScoreFile tcf = null;\r
+        try\r
+        {\r
+          tcf = new TCoffeeScoreFile(file, protocol);\r
+          if (tcf.isValid())\r
+          {\r
+            if (tcf.annotateAlignment(viewport.getAlignment(), true))\r
+            {\r
+              tcoffeeColour.setEnabled(true);\r
+              tcoffeeColour.setSelected(true);\r
+              changeColour(new TCoffeeColourScheme(viewport.getAlignment()));\r
+              isAnnotation = true;\r
+              statusBar.setText(MessageManager.getString("label.successfully_pasted_tcoffee_scores_to_alignment"));\r
+            }\r
+            else\r
+            {\r
+              // some problem - if no warning its probable that the ID matching\r
+              // process didn't work\r
+              JOptionPane\r
+                      .showMessageDialog(\r
+                              Desktop.desktop,\r
+                              tcf.getWarningMessage() == null ? MessageManager.getString("label.check_file_matches_sequence_ids_alignment")\r
+                                      : tcf.getWarningMessage(),\r
+                              MessageManager.getString("label.problem_reading_tcoffee_score_file"),\r
+                              JOptionPane.WARNING_MESSAGE);\r
+            }\r
+          }\r
+          else\r
+          {\r
+            tcf = null;\r
+          }\r
+        } catch (Exception x)\r
+        {\r
+          Cache.log\r
+                  .debug("Exception when processing data source as T-COFFEE score file",\r
+                          x);\r
+          tcf = null;\r
+        }\r
+        if (tcf == null)\r
+        {\r
+          // try to see if its a JNet 'concise' style annotation file *before*\r
+          // we\r
+          // try to parse it as a features file\r
+          if (format == null)\r
+          {\r
+            format = new IdentifyFile().Identify(file, protocol);\r
+          }\r
+          if (format.equalsIgnoreCase("JnetFile"))\r
+          {\r
+            jalview.io.JPredFile predictions = new jalview.io.JPredFile(\r
+                    file, protocol);\r
+            new JnetAnnotationMaker().add_annotation(predictions,\r
+                    viewport.getAlignment(), 0, false);\r
+            isAnnotation = true;\r
+          }\r
+          else\r
+          {\r
+            /*\r
+             * if (format.equalsIgnoreCase("PDB")) {\r
+             * \r
+             * String pdbfn = ""; // try to match up filename with sequence id\r
+             * try { if (protocol == jalview.io.FormatAdapter.FILE) { File fl =\r
+             * new File(file); pdbfn = fl.getName(); } else if (protocol ==\r
+             * jalview.io.FormatAdapter.URL) { URL url = new URL(file); pdbfn =\r
+             * url.getFile(); } } catch (Exception e) { } ; if (assocSeq ==\r
+             * null) { SequenceIdMatcher idm = new SequenceIdMatcher(viewport\r
+             * .getAlignment().getSequencesArray()); if (pdbfn.length() > 0) {\r
+             * // attempt to find a match in the alignment SequenceI mtch =\r
+             * idm.findIdMatch(pdbfn); int l = 0, c = pdbfn.indexOf("."); while\r
+             * (mtch == null && c != -1) { while ((c = pdbfn.indexOf(".", l)) >\r
+             * l) { l = c; } if (l > -1) { pdbfn = pdbfn.substring(0, l); } mtch\r
+             * = idm.findIdMatch(pdbfn); } if (mtch != null) { // try and\r
+             * associate // prompt ? PDBEntry pe = new AssociatePdbFileWithSeq()\r
+             * .associatePdbWithSeq(file, protocol, mtch, true); if (pe != null)\r
+             * { System.err.println("Associated file : " + file + " with " +\r
+             * mtch.getDisplayId(true)); alignPanel.paintAlignment(true); } } //\r
+             * TODO: maybe need to load as normal otherwise return; } }\r
+             */\r
+            // try to parse it as a features file\r
+            boolean isGroupsFile = parseFeaturesFile(file, protocol);\r
+            // if it wasn't a features file then we just treat it as a general\r
+            // alignment file to load into the current view.\r
+            if (!isGroupsFile)\r
+            {\r
+              new FileLoader().LoadFile(viewport, file, protocol, format);\r
+            }\r
+            else\r
+            {\r
+              alignPanel.paintAlignment(true);\r
+            }\r
+          }\r
+        }\r
+      }\r
+      if (isAnnotation)\r
+      {\r
+\r
+        alignPanel.adjustAnnotationHeight();\r
+        viewport.updateSequenceIdColours();\r
+        buildSortByAnnotationScoresMenu();\r
+        alignPanel.paintAlignment(true);\r
+      }\r
+    } catch (Exception ex)\r
+    {\r
+      ex.printStackTrace();\r
+    } catch (OutOfMemoryError oom)\r
+    {\r
+      try\r
+      {\r
+        System.gc();\r
+      } catch (Exception x)\r
+      {\r
+      }\r
+      ;\r
+      new OOMWarning(\r
+              "loading data "\r
+                      + (protocol != null ? (protocol.equals(FormatAdapter.PASTE) ? "from clipboard."\r
+                              : "using " + protocol + " from " + file)\r
+                              : ".")\r
+                      + (format != null ? "(parsing as '" + format\r
+                              + "' file)" : ""), oom, Desktop.desktop);\r
+    }\r
+  }\r
+\r
+  @Override\r
+  public void tabSelectionChanged(int index)\r
+  {\r
+    if (index > -1)\r
+    {\r
+      alignPanel = (AlignmentPanel) alignPanels.elementAt(index);\r
+      viewport = alignPanel.av;\r
+      avc.setViewportAndAlignmentPanel(viewport, alignPanel);\r
+      setMenusFromViewport(viewport);\r
+    }\r
+  }\r
+\r
+  @Override\r
+  public void tabbedPane_mousePressed(MouseEvent e)\r
+  {\r
+    if (SwingUtilities.isRightMouseButton(e))\r
+    {\r
+      String reply = JOptionPane.showInternalInputDialog(this,\r
+              MessageManager.getString("label.enter_view_name"), MessageManager.getString("label.enter_view_name"),\r
+              JOptionPane.QUESTION_MESSAGE);\r
+\r
+      if (reply != null)\r
+      {\r
+        viewport.viewName = reply;\r
+        tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);\r
+      }\r
+    }\r
+  }\r
+\r
+  public AlignViewport getCurrentView()\r
+  {\r
+    return viewport;\r
+  }\r
+\r
+  /**\r
+   * Open the dialog for regex description parsing.\r
+   */\r
+  @Override\r
+  protected void extractScores_actionPerformed(ActionEvent e)\r
+  {\r
+    ParseProperties pp = new jalview.analysis.ParseProperties(\r
+            viewport.getAlignment());\r
+    // TODO: verify regex and introduce GUI dialog for version 2.5\r
+    // if (pp.getScoresFromDescription("col", "score column ",\r
+    // "\\W*([-+]?\\d*\\.?\\d*e?-?\\d*)\\W+([-+]?\\d*\\.?\\d*e?-?\\d*)",\r
+    // true)>0)\r
+    if (pp.getScoresFromDescription("description column",\r
+            "score in description column ", "\\W*([-+eE0-9.]+)", true) > 0)\r
+    {\r
+      buildSortByAnnotationScoresMenu();\r
+    }\r
+  }\r
+\r
+  /*\r
+   * (non-Javadoc)\r
+   * \r
+   * @see\r
+   * jalview.jbgui.GAlignFrame#showDbRefs_actionPerformed(java.awt.event.ActionEvent\r
+   * )\r
+   */\r
+  @Override\r
+  protected void showDbRefs_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setShowDbRefs(showDbRefsMenuitem.isSelected());\r
+  }\r
+\r
+  /*\r
+   * (non-Javadoc)\r
+   * \r
+   * @seejalview.jbgui.GAlignFrame#showNpFeats_actionPerformed(java.awt.event.\r
+   * ActionEvent)\r
+   */\r
+  @Override\r
+  protected void showNpFeats_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setShowNpFeats(showNpFeatsMenuitem.isSelected());\r
+  }\r
+\r
+  /**\r
+   * find the viewport amongst the tabs in this alignment frame and close that\r
+   * tab\r
+   * \r
+   * @param av\r
+   */\r
+  public boolean closeView(AlignViewport av)\r
+  {\r
+    if (viewport == av)\r
+    {\r
+      this.closeMenuItem_actionPerformed(false);\r
+      return true;\r
+    }\r
+    Component[] comp = tabbedPane.getComponents();\r
+    for (int i = 0; comp != null && i < comp.length; i++)\r
+    {\r
+      if (comp[i] instanceof AlignmentPanel)\r
+      {\r
+        if (((AlignmentPanel) comp[i]).av == av)\r
+        {\r
+          // close the view.\r
+          closeView((AlignmentPanel) comp[i]);\r
+          return true;\r
+        }\r
+      }\r
+    }\r
+    return false;\r
+  }\r
+\r
+  protected void build_fetchdbmenu(JMenu webService)\r
+  {\r
+    // Temporary hack - DBRef Fetcher always top level ws entry.\r
+    // TODO We probably want to store a sequence database checklist in\r
+    // preferences and have checkboxes.. rather than individual sources selected\r
+    // here\r
+    final JMenu rfetch = new JMenu(MessageManager.getString("action.fetch_db_references"));\r
+    rfetch.setToolTipText(MessageManager.getString("label.retrieve_parse_sequence_database_records_alignment_or_selected_sequences"));\r
+    webService.add(rfetch);\r
+\r
+    JMenuItem fetchr = new JMenuItem(MessageManager.getString("label.standard_databases"));\r
+    fetchr.setToolTipText(MessageManager.getString("label.fetch_embl_uniprot"));\r
+    fetchr.addActionListener(new ActionListener()\r
+    {\r
+\r
+      @Override\r
+      public void actionPerformed(ActionEvent e)\r
+      {\r
+        new Thread(new Runnable()\r
+        {\r
+\r
+          @Override\r
+          public void run()\r
+          {\r
+            new jalview.ws.DBRefFetcher(alignPanel.av\r
+                    .getSequenceSelection(), alignPanel.alignFrame)\r
+                    .fetchDBRefs(false);\r
+          }\r
+        }).start();\r
+\r
+      }\r
+\r
+    });\r
+    rfetch.add(fetchr);\r
+    final AlignFrame me = this;\r
+    new Thread(new Runnable()\r
+    {\r
+      @Override\r
+      public void run()\r
+      {\r
+        final jalview.ws.SequenceFetcher sf = SequenceFetcher\r
+                .getSequenceFetcherSingleton(me);\r
+        javax.swing.SwingUtilities.invokeLater(new Runnable()\r
+        {\r
+          @Override\r
+          public void run()\r
+          {\r
+            String[] dbclasses = sf.getOrderedSupportedSources();\r
+            // sf.getDbInstances(jalview.ws.dbsources.DasSequenceSource.class);\r
+            // jalview.util.QuickSort.sort(otherdb, otherdb);\r
+            List<DbSourceProxy> otherdb;\r
+            JMenu dfetch = new JMenu();\r
+            JMenu ifetch = new JMenu();\r
+            JMenuItem fetchr = null;\r
+            int comp = 0, icomp = 0, mcomp = 15;\r
+            String mname = null;\r
+            int dbi = 0;\r
+            for (String dbclass : dbclasses)\r
+            {\r
+              otherdb = sf.getSourceProxy(dbclass);\r
+              // add a single entry for this class, or submenu allowing 'fetch\r
+              // all' or pick one\r
+              if (otherdb == null || otherdb.size() < 1)\r
+              {\r
+                continue;\r
+              }\r
+              // List<DbSourceProxy> dbs=otherdb;\r
+              // otherdb=new ArrayList<DbSourceProxy>();\r
+              // for (DbSourceProxy db:dbs)\r
+              // {\r
+              // if (!db.isA(DBRefSource.ALIGNMENTDB)\r
+              // }\r
+              if (mname == null)\r
+              {\r
+                mname = "From " + dbclass;\r
+              }\r
+              if (otherdb.size() == 1)\r
+              {\r
+                final DbSourceProxy[] dassource = otherdb\r
+                        .toArray(new DbSourceProxy[0]);\r
+                DbSourceProxy src = otherdb.get(0);\r
+                fetchr = new JMenuItem(src.getDbSource());\r
+                fetchr.addActionListener(new ActionListener()\r
+                {\r
+\r
+                  @Override\r
+                  public void actionPerformed(ActionEvent e)\r
+                  {\r
+                    new Thread(new Runnable()\r
+                    {\r
+\r
+                      @Override\r
+                      public void run()\r
+                      {\r
+                        new jalview.ws.DBRefFetcher(alignPanel.av\r
+                                .getSequenceSelection(),\r
+                                alignPanel.alignFrame, dassource)\r
+                                .fetchDBRefs(false);\r
+                      }\r
+                    }).start();\r
+                  }\r
+\r
+                });\r
+                fetchr.setToolTipText("<html>"\r
+                        + JvSwingUtils.wrapTooltip("Retrieve from "\r
+                                + src.getDbName()) + "<html>");\r
+                dfetch.add(fetchr);\r
+                comp++;\r
+              }\r
+              else\r
+              {\r
+                final DbSourceProxy[] dassource = otherdb\r
+                        .toArray(new DbSourceProxy[0]);\r
+                // fetch all entry\r
+                DbSourceProxy src = otherdb.get(0);\r
+                fetchr = new JMenuItem(MessageManager.formatMessage("label.fetch_all_param", new String[]{src.getDbSource()}));\r
+                fetchr.addActionListener(new ActionListener()\r
+                {\r
+                  @Override\r
+                  public void actionPerformed(ActionEvent e)\r
+                  {\r
+                    new Thread(new Runnable()\r
+                    {\r
+\r
+                      @Override\r
+                      public void run()\r
+                      {\r
+                        new jalview.ws.DBRefFetcher(alignPanel.av\r
+                                .getSequenceSelection(),\r
+                                alignPanel.alignFrame, dassource)\r
+                                .fetchDBRefs(false);\r
+                      }\r
+                    }).start();\r
+                  }\r
+                });\r
+\r
+                fetchr.setToolTipText("<html>"\r
+                        + JvSwingUtils.wrapTooltip("Retrieve from all "\r
+                                + otherdb.size() + " sources in "\r
+                                + src.getDbSource() + "<br>First is :"\r
+                                + src.getDbName()) + "<html>");\r
+                dfetch.add(fetchr);\r
+                comp++;\r
+                // and then build the rest of the individual menus\r
+                ifetch = new JMenu("Sources from " + src.getDbSource());\r
+                icomp = 0;\r
+                String imname = null;\r
+                int i = 0;\r
+                for (DbSourceProxy sproxy : otherdb)\r
+                {\r
+                  String dbname = sproxy.getDbName();\r
+                  String sname = dbname.length() > 5 ? dbname.substring(0,\r
+                          5) + "..." : dbname;\r
+                  String msname = dbname.length() > 10 ? dbname.substring(\r
+                          0, 10) + "..." : dbname;\r
+                  if (imname == null)\r
+                  {\r
+                    imname = "from '" + sname + "'";\r
+                  }\r
+                  fetchr = new JMenuItem(msname);\r
+                  final DbSourceProxy[] dassrc =\r
+                  { sproxy };\r
+                  fetchr.addActionListener(new ActionListener()\r
+                  {\r
+\r
+                    @Override\r
+                    public void actionPerformed(ActionEvent e)\r
+                    {\r
+                      new Thread(new Runnable()\r
+                      {\r
+\r
+                        @Override\r
+                        public void run()\r
+                        {\r
+                          new jalview.ws.DBRefFetcher(alignPanel.av\r
+                                  .getSequenceSelection(),\r
+                                  alignPanel.alignFrame, dassrc)\r
+                                  .fetchDBRefs(false);\r
+                        }\r
+                      }).start();\r
+                    }\r
+\r
+                  });\r
+                  fetchr.setToolTipText("<html>"\r
+                          + JvSwingUtils.wrapTooltip("Retrieve from "\r
+                                  + dbname) + "</html>");\r
+                  ifetch.add(fetchr);\r
+                  ++i;\r
+                  if (++icomp >= mcomp || i == (otherdb.size()))\r
+                  {\r
+                    ifetch.setText(MessageManager.formatMessage("label.source_to_target",new String[]{imname,sname}));\r
+                    dfetch.add(ifetch);\r
+                    ifetch = new JMenu();\r
+                    imname = null;\r
+                    icomp = 0;\r
+                    comp++;\r
+                  }\r
+                }\r
+              }\r
+              ++dbi;\r
+              if (comp >= mcomp || dbi >= (dbclasses.length))\r
+              {\r
+                dfetch.setText(MessageManager.formatMessage("label.source_to_target",new String[]{mname,dbclass}));\r
+                rfetch.add(dfetch);\r
+                dfetch = new JMenu();\r
+                mname = null;\r
+                comp = 0;\r
+              }\r
+            }\r
+          }\r
+        });\r
+      }\r
+    }).start();\r
+\r
+  }\r
+\r
+  /**\r
+   * Left justify the whole alignment.\r
+   */\r
+  @Override\r
+  protected void justifyLeftMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    AlignmentI al = viewport.getAlignment();\r
+    al.justify(false);\r
+    viewport.firePropertyChange("alignment", null, al);\r
+  }\r
+\r
+  /**\r
+   * Right justify the whole alignment.\r
+   */\r
+  @Override\r
+  protected void justifyRightMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    AlignmentI al = viewport.getAlignment();\r
+    al.justify(true);\r
+    viewport.firePropertyChange("alignment", null, al);\r
+  }\r
+\r
+  public void setShowSeqFeatures(boolean b)\r
+  {\r
+    showSeqFeatures.setSelected(true);\r
+    viewport.setShowSequenceFeatures(true);\r
+  }\r
+\r
+  /*\r
+   * (non-Javadoc)\r
+   * \r
+   * @see\r
+   * jalview.jbgui.GAlignFrame#showUnconservedMenuItem_actionPerformed(java.\r
+   * awt.event.ActionEvent)\r
+   */\r
+  @Override\r
+  protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setShowUnconserved(showNonconservedMenuItem.getState());\r
+    alignPanel.paintAlignment(true);\r
+  }\r
+\r
+  /*\r
+   * (non-Javadoc)\r
+   * \r
+   * @see\r
+   * jalview.jbgui.GAlignFrame#showGroupConsensus_actionPerformed(java.awt.event\r
+   * .ActionEvent)\r
+   */\r
+  @Override\r
+  protected void showGroupConsensus_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setShowGroupConsensus(showGroupConsensus.getState());\r
+    alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());\r
+\r
+  }\r
+\r
+  /*\r
+   * (non-Javadoc)\r
+   * \r
+   * @see\r
+   * jalview.jbgui.GAlignFrame#showGroupConservation_actionPerformed(java.awt\r
+   * .event.ActionEvent)\r
+   */\r
+  @Override\r
+  protected void showGroupConservation_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setShowGroupConservation(showGroupConservation.getState());\r
+    alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());\r
+  }\r
+\r
+  /*\r
+   * (non-Javadoc)\r
+   * \r
+   * @see\r
+   * jalview.jbgui.GAlignFrame#showConsensusHistogram_actionPerformed(java.awt\r
+   * .event.ActionEvent)\r
+   */\r
+  @Override\r
+  protected void showConsensusHistogram_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setShowConsensusHistogram(showConsensusHistogram.getState());\r
+    alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());\r
+  }\r
+\r
+  /*\r
+   * (non-Javadoc)\r
+   * \r
+   * @see\r
+   * jalview.jbgui.GAlignFrame#showConsensusProfile_actionPerformed(java.awt\r
+   * .event.ActionEvent)\r
+   */\r
+  @Override\r
+  protected void showSequenceLogo_actionPerformed(ActionEvent e)\r
+  {\r
+    viewport.setShowSequenceLogo(showSequenceLogo.getState());\r
+    alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());\r
+  }\r
+\r
+  @Override\r
+  protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)\r
+  {\r
+    showSequenceLogo.setState(true);\r
+    viewport.setShowSequenceLogo(true);\r
+    viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState());\r
+    alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());\r
+  }\r
+\r
+  @Override\r
+  protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e)\r
+  {\r
+    alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState());\r
+  }\r
+\r
+  /*\r
+   * (non-Javadoc)\r
+   * \r
+   * @see\r
+   * jalview.jbgui.GAlignFrame#makeGrpsFromSelection_actionPerformed(java.awt\r
+   * .event.ActionEvent)\r
+   */\r
+  @Override\r
+  protected void makeGrpsFromSelection_actionPerformed(ActionEvent e)\r
+  {\r
+    if (avc.makeGroupsFromSelection()) {\r
+      PaintRefresher.Refresh(this, viewport.getSequenceSetId());\r
+      alignPanel.updateAnnotation();\r
+      alignPanel.paintAlignment(true);\r
+    }\r
+  }\r
+\r
+  @Override\r
+  protected void createGroup_actionPerformed(ActionEvent e)\r
+  {\r
+    if (avc.createGroup())\r
+    {\r
+      alignPanel.alignmentChanged();\r
+    }\r
+  }\r
+\r
+  @Override\r
+  protected void unGroup_actionPerformed(ActionEvent e)\r
+  {\r
+    if (avc.unGroup())\r
+    {\r
+      alignPanel.alignmentChanged();\r
+    }\r
+  }\r
+\r
+  /**\r
+   * make the given alignmentPanel the currently selected tab\r
+   * \r
+   * @param alignmentPanel\r
+   */\r
+  public void setDisplayedView(AlignmentPanel alignmentPanel)\r
+  {\r
+    if (!viewport.getSequenceSetId().equals(\r
+            alignmentPanel.av.getSequenceSetId()))\r
+    {\r
+      throw new Error(\r
+              "Implementation error: cannot show a view from another alignment in an AlignFrame.");\r
+    }\r
+    if (tabbedPane != null\r
+            & alignPanels.indexOf(alignmentPanel) != tabbedPane\r
+                    .getSelectedIndex())\r
+    {\r
+      tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));\r
+    }\r
+  }\r
+}\r
+\r
+class PrintThread extends Thread\r
+{\r
+  AlignmentPanel ap;\r
+\r
+  public PrintThread(AlignmentPanel ap)\r
+  {\r
+    this.ap = ap;\r
+  }\r
+\r
+  static PageFormat pf;\r
+\r
+  @Override\r
+  public void run()\r
+  {\r
+    PrinterJob printJob = PrinterJob.getPrinterJob();\r
+\r
+    if (pf != null)\r
+    {\r
+      printJob.setPrintable(ap, pf);\r
+    }\r
+    else\r
+    {\r
+      printJob.setPrintable(ap);\r
+    }\r
+\r
+    if (printJob.printDialog())\r
+    {\r
+      try\r
+      {\r
+        printJob.print();\r
+      } catch (Exception PrintException)\r
+      {\r
+        PrintException.printStackTrace();\r
+      }\r
+    }\r
+  }\r
+}\r