accelerators, save menu item
[jalview.git] / src / jalview / gui / AlignFrame.java
index ca9903c..f82efb5 100755 (executable)
-/********************\r
- * 2004 Jalview Reengineered\r
- * Barton Group\r
- * Dundee University\r
- *\r
- * AM Waterhouse\r
- *******************/\r
-\r
-\r
-\r
-\r
-package jalview.gui;\r
-\r
-import jalview.jbgui.GAlignFrame;\r
-import jalview.schemes.*;\r
-import jalview.datamodel.*;\r
-import jalview.analysis.*;\r
-import jalview.io.*;\r
-import jalview.ws.*;\r
-import java.awt.*;\r
-import java.awt.event.*;\r
-import java.awt.print.*;\r
-import javax.swing.*;\r
-import javax.swing.event.*;\r
-import java.util.*;\r
-import  java.awt.datatransfer.*;\r
-\r
-\r
-public class AlignFrame extends GAlignFrame\r
-{\r
-  final AlignmentPanel alignPanel;\r
-  final AlignViewport viewport;\r
-  public AlignFrame(AlignmentI al)\r
-  {\r
-    super();\r
-    viewport = new AlignViewport(al,true,true,false);\r
-\r
-    String fontName = jalview.bin.Cache.getProperty("FONT_NAME");\r
-    String fontStyle= jalview.bin.Cache.getProperty("FONT_STYLE");\r
-    String fontSize = jalview.bin.Cache.getProperty("FONT_SIZE");\r
-    if(fontName!=null && fontStyle!=null && fontSize!=null)\r
-      viewport.setFont( new Font(fontName,Integer.parseInt(fontStyle),Integer.parseInt(fontSize)) );\r
-\r
-\r
-\r
-    alignPanel = new AlignmentPanel(this, viewport);\r
-    getContentPane().add(alignPanel, java.awt.BorderLayout.CENTER);\r
-\r
-    addInternalFrameListener(new InternalFrameAdapter()\r
-   {\r
-     public void internalFrameActivated(InternalFrameEvent evt)\r
-     {\r
-          javax.swing.SwingUtilities.invokeLater(new Runnable()\r
-          {\r
-            public void run()\r
-            {      alignPanel.requestFocus();    }\r
-          });\r
-\r
-     }\r
-   });\r
-\r
-  }\r
-\r
-  protected void saveAs_actionPerformed(ActionEvent e)\r
-  {\r
-    String suffix = "";\r
-    if(e.getActionCommand().equals("FASTA"))\r
-      suffix = "fa";\r
-    else if(e.getActionCommand().equals("MSF"))\r
-      suffix = "msf";\r
-    else if(e.getActionCommand().equals("CLUSTAL"))\r
-      suffix = "aln";\r
-    else if(e.getActionCommand().equals("BLC"))\r
-      suffix = "blc";\r
-    else if(e.getActionCommand().equals("PIR"))\r
-      suffix = "pir";\r
-    else if(e.getActionCommand().equals("PFAM"))\r
-      suffix = "pfam";\r
-\r
-    JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty("LAST_DIRECTORY")\r
-        , new String[]{suffix}, e.getActionCommand()+" file");\r
-    chooser.setFileView(new JalviewFileView());\r
-    chooser.setDialogTitle("Save Alignment to file - "+e.getActionCommand() +" format.");\r
-    chooser.setToolTipText("Save");\r
-    int value = chooser.showSaveDialog(this);\r
-    if(value == JalviewFileChooser.APPROVE_OPTION)\r
-    {\r
-      String choice =  chooser.getSelectedFile().getPath();\r
-      jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);\r
-      String output = FormatAdapter.get(e.getActionCommand(), viewport.getAlignment().getSequences());\r
-      try{\r
-        java.io.PrintWriter out = new java.io.PrintWriter( new java.io.FileWriter( choice )  );\r
-        out.println(output);\r
-        out.close();\r
-      }\r
-      catch(Exception ex){}\r
-    }\r
-\r
-  }\r
-\r
-  protected void outputText_actionPerformed(ActionEvent e)\r
-  {\r
-     CutAndPasteTransfer cap = new CutAndPasteTransfer(false);\r
-     JInternalFrame frame = new JInternalFrame();\r
-     cap.formatForOutput();\r
-     frame.setContentPane(cap);\r
-     Desktop.addInternalFrame(frame, "Alignment output - "+e.getActionCommand(), 600, 500);\r
-     cap.setText( FormatAdapter.get(e.getActionCommand(), viewport.getAlignment().getSequences()));\r
-  }\r
-\r
-  protected void htmlMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    HTMLOutput htmlOutput = new HTMLOutput(viewport);\r
-    htmlOutput = null;\r
-  }\r
-\r
-  protected void createPNG_actionPerformed(ActionEvent e)\r
-  {\r
-    alignPanel.makePNG();\r
-  }\r
-\r
-  protected void epsFile_actionPerformed(ActionEvent e)\r
-  {\r
-    alignPanel.makeEPS();\r
-  }\r
-\r
-\r
-  public void printMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    //Putting in a thread avoids Swing painting problems\r
-    PrintThread thread = new PrintThread();\r
-    thread.start();\r
-  }\r
-\r
-  class PrintThread extends Thread\r
-  {\r
-    public void run()\r
-    {\r
-      PrinterJob printJob = PrinterJob.getPrinterJob();\r
-      PageFormat pf = printJob.pageDialog(printJob.defaultPage());\r
-      printJob.setPrintable(alignPanel, pf);\r
-      if (printJob.printDialog())\r
-      {\r
-        try\r
-        {\r
-          printJob.print();\r
-        }\r
-        catch (Exception PrintException)\r
-        {\r
-          PrintException.printStackTrace();\r
-        }\r
-      }\r
-    }\r
-\r
-  }\r
-\r
-\r
-\r
-\r
-  public void closeMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    try{\r
-      this.setClosed(true);\r
-    }catch(Exception ex){}\r
-  }\r
-\r
-  Stack historyList = new Stack();\r
-  Stack redoList = new Stack();\r
-  JMenuBar jMenuBar1 = new JMenuBar();\r
-\r
-  void updateEditMenuBar()\r
-  {\r
-    if(historyList.size()>0)\r
-     {\r
-       undoMenuItem.setEnabled(true);\r
-       Object [] history = (Object[])historyList.get(0);\r
-       undoMenuItem.setText("Undo "+history[0]);\r
-     }\r
-    else\r
-    {\r
-      undoMenuItem.setEnabled(false);\r
-      undoMenuItem.setText("Undo");\r
-    }\r
-\r
-    if(redoList.size()>0)\r
-     {\r
-       redoMenuItem.setEnabled(true);\r
-       Object [] history = (Object[])redoList.get(0);\r
-       redoMenuItem.setText("Redo "+history[0]);\r
-     }\r
-    else\r
-    {\r
-      redoMenuItem.setEnabled(false);\r
-      redoMenuItem.setText("Redo");\r
-    }\r
-  }\r
-\r
-  public void addHistoryItem(String type)\r
-  {\r
-    // must make sure we add new sequence objects her, not refs to the existing sequences\r
-    redoList.clear();\r
-    SequenceI[] seq = new SequenceI[viewport.getAlignment().getHeight()];\r
-    for(int i=0; i<viewport.getAlignment().getHeight(); i++)\r
-    {\r
-      seq[i] = new Sequence( viewport.getAlignment().getSequenceAt(i).getName(),\r
-                             viewport.getAlignment().getSequenceAt(i).getSequence());\r
-    }\r
-\r
-    historyList.add(0, new Object[]{type,  seq} );\r
-    updateEditMenuBar();\r
-  }\r
-\r
-  protected void undoMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    Object [] history = (Object[])historyList.remove(0);\r
-    // add the redo state before continuing!!\r
-    SequenceI[] seq = new SequenceI[viewport.getAlignment().getHeight()];\r
-    for (int i = 0; i < viewport.getAlignment().getHeight(); i++)\r
-    {\r
-      seq[i] = new Sequence(viewport.getAlignment().getSequenceAt(i).getName(),\r
-                            viewport.getAlignment().getSequenceAt(i).\r
-                            getSequence());\r
-    }\r
-    /////////\r
-\r
-    redoList.add(0, new Object[] {history[0], seq});\r
-\r
-      seq = (SequenceI[]) history[1];\r
-      viewport.setAlignment( new Alignment(seq) );\r
-      updateEditMenuBar();\r
-      alignPanel.RefreshPanels();\r
-  }\r
-\r
-  public void moveSelectedSequences(boolean up)\r
-  {\r
-    SequenceGroup sg = viewport.getSelectionGroup();\r
-    if (sg == null)\r
-      return;\r
-\r
-    if (up)\r
-    {\r
-      for (int i = 1; i < viewport.alignment.getHeight(); i++)\r
-      {\r
-        SequenceI seq = viewport.alignment.getSequenceAt(i);\r
-        if (!sg.sequences.contains(seq))\r
-          continue;\r
-\r
-        SequenceI temp = viewport.alignment.getSequenceAt(i - 1);\r
-        if (sg.sequences.contains(temp))\r
-          continue;\r
-\r
-        viewport.alignment.getSequences().setElementAt(temp, i);\r
-        viewport.alignment.getSequences().setElementAt(seq, i - 1);\r
-      }\r
-    }\r
-    else\r
-    {\r
-      for (int i = viewport.alignment.getHeight() - 2; i > -1; i--)\r
-      {\r
-        SequenceI seq = viewport.alignment.getSequenceAt(i);\r
-        if (!sg.sequences.contains(seq))\r
-          continue;\r
-\r
-        SequenceI temp = viewport.alignment.getSequenceAt(i + 1);\r
-        if (sg.sequences.contains(temp))\r
-          continue;\r
-\r
-        viewport.alignment.getSequences().setElementAt(temp, i);\r
-        viewport.alignment.getSequences().setElementAt(seq, i + 1);\r
-      }\r
-    }\r
-\r
-    alignPanel.RefreshPanels();\r
-  }\r
-\r
-\r
-\r
-  protected void copy_actionPerformed(ActionEvent e)\r
-  {\r
-   if(viewport.getSelectionGroup()==null)\r
-     return;\r
-\r
-   SequenceGroup sg = viewport.getSelectionGroup();\r
-\r
-     Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();\r
-     StringBuffer buffer= new StringBuffer();\r
-\r
-       for(int i=0; i<sg.getSize(); i++)\r
-       {\r
-         SequenceI seq = sg.getSequenceAt(i);\r
-         buffer.append( seq.getName()+"\t"+seq.findPosition( sg.getStartRes() ) +"\t"\r
-                        +seq.findPosition( sg.getEndRes() )+ "\t"\r
-                        +sg.getSequenceAt(i).getSequence(sg.getStartRes(), sg.getEndRes()+1)+"\n");\r
-       }\r
-     c.setContents( new StringSelection( buffer.toString()) , null ) ;\r
-\r
-  }\r
-\r
-\r
-  protected void pasteNew_actionPerformed(ActionEvent e)\r
-  {\r
-    paste(true);\r
-  }\r
-\r
-  protected void pasteThis_actionPerformed(ActionEvent e)\r
-  {\r
-    addHistoryItem("Paste");\r
-    paste(false);\r
-  }\r
-\r
-  void paste(boolean newAlignment)\r
-  {\r
-    try{\r
-      Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();\r
-      Transferable contents = c.getContents(this);\r
-      if (contents == null)\r
-        return;\r
-\r
-      String str = (String) contents.getTransferData(DataFlavor.stringFlavor);\r
-      StringTokenizer st = new StringTokenizer(str);\r
-      ArrayList seqs = new ArrayList();\r
-      while (st.hasMoreElements())\r
-      {\r
-        String name = st.nextToken();\r
-        int start = Integer.parseInt(st.nextToken());\r
-        int end = Integer.parseInt(st.nextToken());\r
-        Sequence sequence = new Sequence(name,st.nextToken(), start, end);\r
-\r
-        if(!newAlignment)\r
-          viewport.alignment.addSequence(sequence);\r
-        else\r
-          seqs.add(sequence);\r
-      }\r
-\r
-      if(newAlignment)\r
-      {\r
-        SequenceI[] newSeqs = new SequenceI[seqs.size()];\r
-        seqs.toArray(newSeqs);\r
-        AlignFrame af = new AlignFrame(new Alignment(newSeqs));\r
-        int newHeight = newSeqs.length * af.viewport.getCharHeight() + 200;\r
-        if (newHeight > 500)\r
-          newHeight = 500;\r
-        Desktop.addInternalFrame(af, "Copied sequences", 700, newHeight);\r
-      }\r
-      else\r
-      {\r
-        viewport.setEndSeq(viewport.alignment.getHeight());\r
-        viewport.alignment.getWidth();\r
-        alignPanel.RefreshPanels();\r
-      }\r
-\r
-    }catch(Exception ex){}// could be anything being pasted in here\r
-\r
-  }\r
-\r
-\r
-  protected void cut_actionPerformed(ActionEvent e)\r
-  {\r
-    copy_actionPerformed(null);\r
-    delete_actionPerformed(null);\r
-  }\r
-\r
-  protected void delete_actionPerformed(ActionEvent e)\r
-  {\r
-    addHistoryItem("Delete");\r
-    if (viewport.getSelectionGroup() == null)\r
-      return;\r
-\r
-     SequenceGroup sg = viewport.getSelectionGroup();\r
-     for (int i=0;i < sg.sequences.size(); i++)\r
-     {\r
-       SequenceI seq = sg.getSequenceAt(i);\r
-       int index = viewport.getAlignment().findIndex(seq);\r
-       seq.deleteChars(sg.getStartRes(), sg.getEndRes()+1);\r
-\r
-       if(seq.getSequence().length()<1)\r
-          viewport.getAlignment().deleteSequence(seq);\r
-      else\r
-          viewport.getAlignment().getSequences().setElementAt(seq, index);\r
-     }\r
-\r
-     viewport.setSelectionGroup(null);\r
-     viewport.alignment.deleteGroup(sg);\r
-     viewport.resetSeqLimits( alignPanel.seqPanel.seqCanvas.getHeight());\r
-     if(viewport.getAlignment().getHeight()<1)\r
-     try\r
-     {\r
-       this.setClosed(true);\r
-     }catch(Exception ex){}\r
-     alignPanel.RefreshPanels();\r
-\r
-  }\r
-\r
-\r
-\r
-  protected void redoMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-     Object [] history = (Object[])redoList.remove(0);\r
-     SequenceI[] seq = (SequenceI[]) history[1];\r
-     viewport.setAlignment( new Alignment(seq) );\r
-     updateEditMenuBar();\r
-     alignPanel.RefreshPanels();\r
-  }\r
-\r
-\r
-  public void groupsMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    GroupEditor geditor = new GroupEditor(viewport, alignPanel);\r
-    JInternalFrame frame = new JInternalFrame();\r
-    frame.setContentPane(geditor);\r
-    Desktop.addInternalFrame(frame, "Group editor", 710, 410);\r
-    frame.setResizable(false);\r
-  }\r
-\r
-  protected void deleteGroups_actionPerformed(ActionEvent e)\r
-  {\r
-    viewport.alignment.deleteAllGroups();\r
-    viewport.setSelectionGroup(null);\r
-\r
-    alignPanel.RefreshPanels();\r
-  }\r
-\r
-\r
-\r
-  public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    SequenceGroup sg = new SequenceGroup();\r
-    for (int i=0; i<viewport.getAlignment().getSequences().size(); i++)\r
-      sg.addSequence( viewport.getAlignment().getSequenceAt(i));\r
-    sg.setEndRes(viewport.alignment.getWidth());\r
-    viewport.setSelectionGroup(sg);\r
-    PaintRefresher.Refresh(null);\r
-  }\r
-\r
-  public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    viewport.setSelectionGroup(null);\r
-    PaintRefresher.Refresh(null);\r
-  }\r
-\r
-  public void invertSequenceMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    SequenceGroup sg = viewport.getSelectionGroup();\r
-    for (int i=0; i<viewport.getAlignment().getSequences().size(); i++)\r
-      sg.addOrRemove (viewport.getAlignment().getSequenceAt(i));\r
-\r
-    PaintRefresher.Refresh(null);\r
-  }\r
-\r
-\r
-  public void deselectAllColumnsMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    viewport.getColumnSelection().clear();\r
-    repaint();\r
-  }\r
-\r
-  public void remove2LeftMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    addHistoryItem("delete columns");\r
-    ColumnSelection colSel = viewport.getColumnSelection();\r
-    if (colSel.size() > 0)\r
-    {\r
-      int min = colSel.getMin();\r
-      viewport.getAlignment().trimLeft(min);\r
-      colSel.compensateForEdit(0,min);\r
-      alignPanel.RefreshPanels();\r
-    }\r
-  }\r
-\r
-  public void remove2RightMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    addHistoryItem("delete columns");\r
-    ColumnSelection colSel = viewport.getColumnSelection();\r
-    if (colSel.size() > 0)\r
-    {\r
-      int max = colSel.getMax();\r
-      if(max>1)\r
-        viewport.getAlignment().trimRight(max);\r
-\r
-      alignPanel.RefreshPanels();\r
-    }\r
-\r
-  }\r
-\r
-  public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    addHistoryItem("delete gapped columns");\r
-    viewport.getAlignment().removeGaps();\r
-    alignPanel.RefreshPanels();\r
-  }\r
-\r
-  public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    addHistoryItem("delete all gaps");\r
-    SequenceI current;\r
-    int jSize;\r
-    for (int i=0; i < viewport.getAlignment().getSequences().size();i++)\r
-    {\r
-      current = viewport.getAlignment().getSequenceAt(i);\r
-      jSize = current.getLength();\r
-      for (int j=0; j < jSize; j++)\r
-        if(jalview.util.Comparison.isGap(current.getCharAt(j)))\r
-        {\r
-          current.deleteCharAt(j);\r
-          j--;\r
-          jSize--;\r
-        }\r
-    }\r
-\r
-    alignPanel.RefreshPanels();\r
-  }\r
-\r
-  public void setGapCharMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    char thisChar = '-';\r
-    char nextChar = '.';\r
-    if(viewport.getGapCharacter()=='-')\r
-    {\r
-      thisChar = '.';\r
-      nextChar = '-';\r
-    }\r
-    setGapCharMenuItem.setText("Set gap character to \""+nextChar+"\"");\r
-    viewport.setGapCharacter(thisChar);\r
-    alignPanel.RefreshPanels();\r
-  }\r
-\r
-  public void findMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-      JInternalFrame frame = new JInternalFrame();\r
-      Finder finder = new Finder(viewport, alignPanel, frame);\r
-      frame.setContentPane(finder);\r
-     Desktop.addInternalFrame(frame, "Find", 340,110);\r
-\r
-  }\r
-\r
-\r
-  public void font_actionPerformed(ActionEvent e)\r
-  {\r
-   // JOptionPane op = new JOptionPane();\r
-    JInternalFrame frame = new JInternalFrame();\r
-    FontChooser fc = new FontChooser( alignPanel, frame );\r
-    frame.setContentPane(fc);\r
-    Desktop.addInternalFrame(frame, "Change Font", 480,100);\r
-  }\r
-\r
-  protected void fullSeqId_actionPerformed(ActionEvent e)\r
-  {\r
-    viewport.setShowFullId( fullSeqId.isSelected() );\r
-\r
-    alignPanel.idPanel.idCanvas.setPreferredSize( alignPanel.calculateIdWidth() );\r
-    alignPanel.RefreshPanels();\r
-  }\r
-\r
-  protected void colourTextMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-      viewport.setColourText( colourTextMenuItem.isSelected() );\r
-      alignPanel.RefreshPanels();\r
-  }\r
-\r
-  protected void wrapMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    viewport.setWrapAlignment( wrapMenuItem.isSelected() );\r
-    alignPanel.setWrapAlignment( wrapMenuItem.isSelected() );\r
-  }\r
-\r
-\r
-  public void viewBoxesMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    viewport.setShowBoxes( viewBoxesMenuItem.isSelected() );\r
-    alignPanel.RefreshPanels();\r
-  }\r
-\r
-  public void viewTextMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    viewport.setShowText( viewTextMenuItem.isSelected() );\r
-    alignPanel.RefreshPanels();\r
-  }\r
-\r
-\r
-  protected void renderGapsMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    viewport.setRenderGaps(renderGapsMenuItem.isSelected());\r
-    alignPanel.RefreshPanels();\r
-  }\r
-\r
-  public void sequenceFeatures_actionPerformed(ActionEvent evt)\r
-  {\r
-    viewport.showSequenceFeatures(sequenceFeatures.isSelected());\r
-    if(viewport.showSequenceFeatures && !((Alignment)viewport.alignment).featuresAdded)\r
-    {\r
-         AlignmentUtil.fetchSequenceFeatures( viewport.alignment , alignPanel);\r
-         ((Alignment)viewport.alignment).featuresAdded = true;\r
-    }\r
-    alignPanel.RefreshPanels();\r
-  }\r
-\r
-  public void consensusGraphMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    alignPanel.setGraphPanelVisible( consensusGraphMenuItem.isSelected() );\r
-  }\r
-\r
-  public void overviewMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    if (alignPanel.overviewPanel != null)\r
-      return;\r
-\r
-    JInternalFrame frame = new JInternalFrame();\r
-    OverviewPanel overview = alignPanel.getOverviewPanel();\r
-   try{\r
-     overview = new OverviewPanel(alignPanel, viewport);\r
-     frame.setContentPane(overview);\r
-    Desktop.addInternalFrame(frame, "Overview " + this.getTitle(),\r
-                             frame.getWidth(), frame.getHeight());\r
-    frame.pack();\r
-    frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()\r
-    { public void internalFrameClosed(javax.swing.event.InternalFrameEvent evt)\r
-      {\r
-            alignPanel.setOverviewPanel(null);\r
-      };\r
-    });\r
-    alignPanel.setOverviewPanel( overview );\r
-\r
-  }catch(java.lang.OutOfMemoryError ex)\r
-   {\r
-     JOptionPane.showInternalMessageDialog(this, "Sequence alignment too large to\nproduce overview image!!"\r
-                                   +"\nTry reducing the font size.",\r
-                                   "Out of memory", JOptionPane.WARNING_MESSAGE);\r
-   }\r
-\r
-\r
-  }\r
-\r
-  protected void noColourmenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    changeColour( null );\r
-  }\r
-\r
-\r
-  public void clustalColour_actionPerformed(ActionEvent e)\r
-  {\r
-    abovePIDThreshold.setSelected(false);\r
-    changeColour(new ClustalxColourScheme(viewport.alignment.getSequences(), viewport.alignment.getWidth()));\r
-  }\r
-\r
-  public void zappoColour_actionPerformed(ActionEvent e)\r
-  {\r
-    changeColour(new ZappoColourScheme());\r
-  }\r
-\r
-  public void taylorColour_actionPerformed(ActionEvent e)\r
-  {\r
-    changeColour(new TaylorColourScheme());\r
-  }\r
-\r
-\r
-  public void hydrophobicityColour_actionPerformed(ActionEvent e)\r
-  {\r
-    changeColour( new HydrophobicColourScheme() );\r
-  }\r
-\r
-  public void helixColour_actionPerformed(ActionEvent e)\r
-  {\r
-    changeColour(new HelixColourScheme() );\r
-  }\r
-\r
-\r
-  public void strandColour_actionPerformed(ActionEvent e)\r
-  {\r
-    changeColour(new StrandColourScheme());\r
-  }\r
-\r
-\r
-  public void turnColour_actionPerformed(ActionEvent e)\r
-  {\r
-    changeColour(new TurnColourScheme());\r
-  }\r
-\r
-\r
-  public void buriedColour_actionPerformed(ActionEvent e)\r
-  {\r
-    changeColour(new BuriedColourScheme() );\r
-  }\r
-\r
-  public void nucleotideColour_actionPerformed(ActionEvent e)\r
-  {\r
-    changeColour(new NucleotideColourScheme());\r
-  }\r
-\r
-\r
-  protected void applyToAllGroups_actionPerformed(ActionEvent e)\r
-  {\r
-    viewport.setColourAppliesToAllGroups(applyToAllGroups.isSelected());\r
-  }\r
-\r
-\r
-\r
-  void changeColour(ColourSchemeI cs)\r
-  {\r
-\r
-    if(viewport.getColourAppliesToAllGroups())\r
-    {\r
-      Vector groups = viewport.alignment.getGroups();\r
-      for(int i=0; i<groups.size(); i++)\r
-      {\r
-        SequenceGroup sg = (SequenceGroup)groups.elementAt(i);\r
-        sg.cs = cs;\r
-\r
-        if(abovePIDThreshold.isSelected())\r
-          abovePIDThreshold_actionPerformed(null);\r
-        else if( viewport.getConservationSelected() )\r
-        {\r
-          Conservation c = new Conservation("Group",\r
-                                            ResidueProperties.propHash, 3,\r
-                                            sg.sequences, sg.getStartRes(),\r
-                                            sg.getEndRes());\r
-          c.calculate();\r
-          c.verdict(false, 100);\r
-          ConservationColourScheme ccs = new ConservationColourScheme(c, sg.cs);\r
-\r
-          sg.cs = ccs;\r
-        }\r
-\r
-      }\r
-    }\r
-\r
-\r
-    if ( viewport.getAbovePIDThreshold())\r
-    {\r
-      int threshold = 0;\r
-      threshold = Desktop.setPIDSliderSource(alignPanel, cs, "Background");\r
-      Desktop.hideConservationSlider();\r
-\r
-      if (cs instanceof ResidueColourScheme)\r
-        ( (ResidueColourScheme) cs).setThreshold(threshold);\r
-      else if (cs instanceof ScoreColourScheme)\r
-        ( (ScoreColourScheme) cs).setThreshold(threshold);\r
-\r
-      viewport.setGlobalColourScheme(cs);\r
-\r
-    }\r
-    else\r
-    if (cs instanceof ResidueColourScheme)\r
-      ( (ResidueColourScheme) cs).setThreshold(0);\r
-    else if (cs instanceof ScoreColourScheme)\r
-      ( (ScoreColourScheme) cs).setThreshold(0);\r
-\r
-\r
-\r
-\r
-if ( viewport.getConservationSelected() )\r
- {\r
-   ConservationColourScheme ccs = null;\r
-\r
-   Alignment al = (Alignment) viewport.alignment;\r
-   Conservation c = new Conservation("All",\r
-                                     ResidueProperties.propHash, 3,\r
-                                     al.getSequences(), 0,\r
-                                     al.getWidth());\r
-\r
-   c.calculate();\r
-   c.verdict(false, 100);\r
-\r
-   ccs = new ConservationColourScheme(c, cs);\r
-\r
-   int threshold = Desktop.setConservationSliderSource(alignPanel, ccs,\r
-       "Background");\r
-\r
-   ccs.inc = threshold;\r
-\r
-   viewport.setGlobalColourScheme(ccs);\r
-\r
-  }\r
-  else\r
-       viewport.setGlobalColourScheme( cs );\r
-\r
-    alignPanel.RefreshPanels();\r
-  }\r
-\r
-\r
-  protected  void conservationMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    viewport.setConservationSelected(conservationMenuItem.isSelected());\r
-\r
-    viewport.setAbovePIDThreshold(false);\r
-    abovePIDThreshold.setSelected(false);\r
-    Desktop.hidePIDSlider();\r
-    if(!viewport.getConservationSelected())\r
-      Desktop.hideConservationSlider();\r
-\r
-   ColourSchemeI cs = viewport.getGlobalColourScheme();\r
-   if(cs instanceof ConservationColourScheme )\r
-     changeColour( ((ConservationColourScheme)cs).cs );\r
-    else\r
-      changeColour( cs );\r
-  }\r
-\r
-\r
-  public void abovePIDThreshold_actionPerformed(ActionEvent e)\r
-  {\r
-    viewport.setAbovePIDThreshold(abovePIDThreshold.isSelected());\r
-\r
-    conservationMenuItem.setSelected(false);\r
-    viewport.setConservationSelected(false);\r
-    Desktop.hideConservationSlider();\r
-\r
-    if(!viewport.getAbovePIDThreshold())\r
-      Desktop.hidePIDSlider();\r
-\r
-\r
-    ColourSchemeI cs = viewport.getGlobalColourScheme();\r
-    if(cs instanceof ConservationColourScheme )\r
-        changeColour( ((ConservationColourScheme)cs).cs );\r
-    else\r
-        changeColour( cs );\r
-\r
-  }\r
-\r
-\r
-\r
-  public void userDefinedColour_actionPerformed(ActionEvent e)\r
-  {\r
-    JInternalFrame frame = new JInternalFrame();\r
-    UserDefinedColours chooser = new UserDefinedColours( frame, alignPanel, null);\r
-    frame.setContentPane(chooser);\r
-    Desktop.addInternalFrame(frame,"User defined colours", 450,540 );\r
-    frame.setResizable(false);\r
-    frame.setIconifiable(false);\r
-    frame.setMaximizable(false);\r
-  }\r
-\r
-  public void PIDColour_actionPerformed(ActionEvent e)\r
-  {\r
-    changeColour( new PIDColourScheme() );\r
-  }\r
-\r
-\r
-  public void BLOSUM62Colour_actionPerformed(ActionEvent e)\r
-  {\r
-    changeColour(new Blosum62ColourScheme(viewport) );\r
-  }\r
-\r
-\r
-\r
-  public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    addHistoryItem("sort");\r
-    AlignmentSorter.sortByPID(viewport.getAlignment(), viewport.getAlignment().getSequenceAt(0));\r
-    alignPanel.RefreshPanels();\r
-  }\r
-\r
-  public void sortIDMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    addHistoryItem("sort");\r
-    AlignmentSorter.sortByID( viewport.getAlignment() );\r
-    alignPanel.RefreshPanels();\r
-  }\r
-\r
-  public void sortGroupMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    addHistoryItem("sort");\r
-    AlignmentSorter.sortByGroup(viewport.getAlignment());\r
-    AlignmentSorter.sortGroups(viewport.getAlignment());\r
-    alignPanel.RefreshPanels();\r
-  }\r
-\r
-  public void sortTreeOrderMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    addHistoryItem("sort");\r
-    if(viewport.getCurrentTree()==null)\r
-      return;\r
-\r
-    AlignmentSorter.sortByTree(viewport.getAlignment(), viewport.getCurrentTree());\r
-    alignPanel.RefreshPanels();\r
-  }\r
-\r
-  public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    RedundancyPanel sp = new RedundancyPanel(alignPanel);\r
-    JInternalFrame frame = new JInternalFrame();\r
-    frame.setContentPane(sp);\r
-    Desktop.addInternalFrame(frame, "Redundancy threshold selection", 400, 100);\r
-    frame.setMaximizable(false);\r
-    frame.setResizable(false);\r
-\r
-  }\r
-\r
-  public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    if(viewport.getSelectionGroup().getSize()<2)\r
-      JOptionPane.showInternalMessageDialog(this, "You must select at least 2 sequences.", "Invalid Selection", JOptionPane.WARNING_MESSAGE);\r
-    else\r
-    {\r
-      JInternalFrame frame = new JInternalFrame();\r
-      frame.setContentPane(new PairwiseAlignPanel(viewport));\r
-      Desktop.addInternalFrame(frame, "Pairwise Alignment", 600, 500);\r
-    }\r
-  }\r
-\r
-  public void PCAMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-\r
-    if( (viewport.getSelectionGroup()!=null && viewport.getSelectionGroup().getSize()<4 && viewport.getSelectionGroup().getSize()>0)\r
-       || viewport.getAlignment().getHeight()<4)\r
-    {\r
-      JOptionPane.showInternalMessageDialog(this, "Principal component analysis must take\n"\r
-                                    +"at least 4 input sequences.",\r
-                                    "Sequence selection insufficient",\r
-                                    JOptionPane.WARNING_MESSAGE);\r
-      return;\r
-    }\r
-\r
-    try{\r
-      PCAPanel pcaPanel = new PCAPanel(viewport, null);\r
-      JInternalFrame frame = new JInternalFrame();\r
-      frame.setContentPane(pcaPanel);\r
-      Desktop.addInternalFrame(frame, "Principal component analysis", 400, 400);\r
-   }catch(java.lang.OutOfMemoryError ex)\r
-   {\r
-     JOptionPane.showInternalMessageDialog(this, "Too many sequences selected\nfor Principal Component Analysis!!",\r
-                                   "Out of memory", JOptionPane.WARNING_MESSAGE);\r
-   }\r
-\r
-\r
-  }\r
-\r
-  public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    NewTreePanel("AV", "PID", "Average distance tree using PID");\r
-  }\r
-\r
-  public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");\r
-  }\r
-\r
-\r
-  protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");\r
-  }\r
-\r
-  protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62PID");\r
-  }\r
-\r
-  void NewTreePanel(String type, String pwType, String title)\r
-  {\r
-    //are the sequences aligned?\r
-    if(!viewport.alignment.isAligned())\r
-    {\r
-      JOptionPane.showMessageDialog(Desktop.desktop, "The sequences must be aligned before creating a tree.",\r
-                                    "Sequences not aligned", JOptionPane.WARNING_MESSAGE);\r
-      return;\r
-    }\r
-\r
-    TreePanel tp=null;\r
-   if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup().getSize() > 3)\r
-   {\r
-     tp = new TreePanel(viewport, viewport.getSelectionGroup().sequences,type, pwType,\r
-                         0, viewport.alignment.getWidth());\r
-   }\r
-   else\r
-   {\r
-     tp = new TreePanel(viewport, viewport.getAlignment().getSequences(),\r
-                         type, pwType,  0, viewport.alignment.getWidth());\r
-   }\r
-\r
-   Desktop.addInternalFrame(tp, title, 600, 500);\r
-  }\r
-\r
-\r
-\r
-\r
-  public void clustalAlignMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    JInternalFrame frame = new JInternalFrame();\r
-    ClustalThread ct = new ClustalThread(frame);\r
-    Thread t = new Thread(ct);\r
-    t.start();\r
-    frame.setContentPane(ct);\r
-     Desktop.addInternalFrame(frame, title, 300, 80);\r
-\r
-  }\r
-\r
-  class ClustalThread extends JPanel implements Runnable\r
-  {\r
-    Image [] image;\r
-    int imageIndex = 0;\r
-    boolean webServiceRunning = false;\r
-    JInternalFrame frame;\r
-    public ClustalThread(JInternalFrame frame)\r
-    {\r
-      this.frame = frame;\r
-      image = new Image[9];\r
-      for(int i=0; i<9; i++)\r
-      {\r
-        java.net.URL url = getClass().getResource("/images/dna" + (i+1) + ".gif");\r
-        if (url != null)\r
-        {\r
-          image[i] = java.awt.Toolkit.getDefaultToolkit().createImage(url);\r
-          MediaTracker mt = new MediaTracker(this);\r
-          mt.addImage(image[i], i);\r
-          try{mt.waitForID(i);}\r
-          catch(Exception ex){}\r
-        }\r
-      }\r
-      DNATwirler twirler = new DNATwirler();\r
-      twirler.start();\r
-      webServiceRunning = true;\r
-    }\r
-\r
-    class DNATwirler extends Thread\r
-    {\r
-      public void run()\r
-      {\r
-        while(webServiceRunning)\r
-        {\r
-          try{\r
-            Thread.sleep(100);\r
-            imageIndex++;\r
-            imageIndex %=9;\r
-            repaint();\r
-          }\r
-          catch(Exception ex){}\r
-        }\r
-      }\r
-    }\r
-\r
-    // JBPNote\r
-    // Should check to see if the server settings are valid\r
-    // Need visual-delay indication here.\r
-    public void run()\r
-       {\r
-      /*   jalview.ws.Jemboss jemboss = new jalview.ws.Jemboss();\r
-         Vector sv = viewport.getAlignment().getSequences();\r
-         SequenceI[] seqs = new SequenceI[sv.size()];\r
-\r
-         int i = 0;\r
-         do\r
-         {\r
-           seqs[i] = (SequenceI) sv.elementAt(i);\r
-         }\r
-         while (++i < sv.size());\r
-\r
-         SequenceI[] alignment = jemboss.clustalW(seqs); // gaps removed within method\r
-\r
-         if (alignment != null)\r
-         {\r
-           AlignFrame af = new AlignFrame(new Alignment(alignment));\r
-          af.clustalColour.setSelected(true);\r
-          af.clustalColour_actionPerformed(null);\r
-           Desktop.addInternalFrame(af, getTitle().concat(" - ClustalW Alignment"),\r
-                                    700, 500); // JBPNote - is there a new window geom. property ?\r
-         }\r
-         else\r
-           JOptionPane.showMessageDialog(Desktop.desktop, "Problem obtaining clustal alignment", "Web service error",\r
-                                         JOptionPane.WARNING_MESSAGE);\r
-\r
-         webServiceRunning = false;\r
-         try{\r
-           frame.setClosed(true);\r
-         }catch(Exception ex){}\r
-       }\r
-\r
-       public void paintComponent(Graphics g)\r
-       {\r
-         g.setColor(Color.white);\r
-         g.fillRect(0,0,getWidth(), getHeight());\r
-         if(image!=null)\r
-         {\r
-           g.drawImage(image[imageIndex],10,10,this);\r
-         }\r
-         g.setFont(new Font("Arial", Font.BOLD, 12));\r
-         g.setColor(Color.black);\r
-         g.drawString("Clustal Alignment Web Service running", 30,30);\r
-       }\r
-  }\r
-  public void jpredMenuItem_actionPerformed(ActionEvent e)\r
-    {\r
-    //  JInternalFrame frame = new JInternalFrame();\r
-//      JPredClient ct = new JPredClient((SequenceI)\r
-    ///                                   viewport.getAlignment().getSequences().elementAt(0));\r
-    }\r
-\r
-*/}}\r
-  protected void LoadtreeMenuItem_actionPerformed(ActionEvent e) {\r
-    // Pick the tree file\r
-    JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.\r
-        getProperty("LAST_DIRECTORY"));\r
-    chooser.setFileView(new JalviewFileView());\r
-    chooser.setDialogTitle("Select a newick-like tree file");\r
-    chooser.setToolTipText("Load a tree file");\r
-    int value = chooser.showOpenDialog(null);\r
-    if (value == JalviewFileChooser.APPROVE_OPTION)\r
-    {\r
-      String choice = chooser.getSelectedFile().getPath();\r
-      jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);\r
-      TreePanel treepanel = null;\r
-      try\r
-      {\r
-        jalview.io.NewickFile fin = new jalview.io.NewickFile(choice, "File");\r
-        fin.parse();\r
-\r
-        if (fin.getTree() != null)\r
-        {\r
-          TreePanel tp = null;\r
-          tp = new TreePanel(viewport, viewport.getAlignment().getSequences(),\r
-                             fin, "FromFile", choice);\r
-          Desktop.addInternalFrame(tp, title, 600, 500);\r
-        }\r
-      }\r
-      catch (Exception ex)\r
-      {\r
-        JOptionPane.showMessageDialog(Desktop.desktop,\r
-                                      "Problem reading tree file",\r
-                                      ex.getMessage(),\r
-                                      JOptionPane.WARNING_MESSAGE);\r
-        ex.printStackTrace();\r
-      }\r
-    }\r
-  }\r
-\r
-}\r
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer
+ * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+ *
+ * This program 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Softwarechang
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package jalview.gui;
+
+import java.beans.*;
+import java.io.*;
+import java.util.*;
+
+import java.awt.*;
+import java.awt.datatransfer.*;
+import java.awt.event.*;
+import java.awt.print.*;
+import javax.swing.*;
+
+import jalview.analysis.*;
+import jalview.datamodel.*;
+import jalview.io.*;
+import jalview.jbgui.*;
+import jalview.schemes.*;
+import jalview.commands.*;
+import jalview.ws.*;
+import java.awt.dnd.*;
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author $author$
+ * @version $Revision$
+ */
+public class AlignFrame extends GAlignFrame implements DropTargetListener
+{
+  /** DOCUMENT ME!! */
+  public static final int DEFAULT_WIDTH = 700;
+
+  /** DOCUMENT ME!! */
+  public static final int DEFAULT_HEIGHT = 500;
+  public AlignmentPanel alignPanel;
+
+  AlignViewport viewport;
+
+  Vector alignPanels = new Vector();
+
+
+  /** DOCUMENT ME!! */
+  public String currentFileFormat = null;
+
+  public String fileName = null;
+
+  private int treeCount = 0;
+
+  /**
+   * Creates a new AlignFrame object.
+   *
+   * @param al DOCUMENT ME!
+   */
+  public AlignFrame(AlignmentI al, int width, int height)
+  {
+    this(al, null, width, height);
+  }
+
+
+  /**
+   * new alignment window with hidden columns
+   * @param al AlignmentI
+   * @param hiddenColumns ColumnSelection or null
+   */
+  public AlignFrame(AlignmentI al, ColumnSelection hiddenColumns,
+                    int width, int height)
+  {
+    this.setSize(width, height);
+    viewport = new AlignViewport(al, hiddenColumns);
+
+    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();
+  }
+
+  void init()
+  {
+    this.setDropTarget(new java.awt.dnd.DropTarget(this, this));
+
+    if (viewport.conservation == 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)
+   {
+     addServiceListeners();
+     setGUINucleotide(viewport.alignment.isNucleotide());
+   }
+
+   setMenusFromViewport(viewport);
+
+   if (viewport.wrapAlignment)
+   {
+     wrapMenuItem_actionPerformed(null);
+   }
+
+   addKeyListener();
+
+
+  }
+
+  void addKeyListener()
+  {
+      final AlignFrame af = this;
+      addKeyListener(new KeyAdapter()
+      {
+        public void keyPressed(KeyEvent evt)
+        {
+          if (viewport.cursorMode
+              && evt.getKeyCode() >= KeyEvent.VK_0
+              && evt.getKeyCode() <= KeyEvent.VK_9)
+          {
+            alignPanel.seqPanel.numberPressed(evt.getKeyChar());
+          }
+
+          switch (evt.getKeyCode())
+          {
+            case KeyEvent.VK_V:
+              if (!evt.isControlDown())
+              {
+                AlignmentPanel newap =
+                    new Jalview2XML().copyAlignPanel(alignPanel, true);
+
+                if(viewport.viewName==null)
+                  viewport.viewName="View 1";
+
+                newap.av.historyList = viewport.historyList;
+                newap.av.redoList = viewport.redoList;
+                newap.av.viewName = "View " +
+                    (Desktop.getViewCount(viewport.getSequenceSetId())+1);
+
+                addAlignmentPanel(newap, false);
+
+                tabbedPane.setSelectedIndex(tabbedPane.getTabCount()-1);
+
+              }
+              break;
+            case KeyEvent.VK_G:
+              Desktop.instance.gatherViews(af);
+              break;
+
+            case KeyEvent.VK_X:
+              if (!evt.isControlDown())
+              {
+                Desktop.instance.explodeViews(af);
+              }
+              break;
+
+
+            case 27: // escape key
+              deselectAllSequenceMenuItem_actionPerformed(null);
+
+              break;
+
+            case KeyEvent.VK_DOWN:
+              if (viewport.cursorMode)
+              {
+                alignPanel.seqPanel.moveCursor(0, 1);
+              }
+              else
+                moveSelectedSequences(false);
+              break;
+
+            case KeyEvent.VK_UP:
+              if (viewport.cursorMode)
+              {
+                alignPanel.seqPanel.moveCursor(0, -1);
+              }
+              else
+                moveSelectedSequences(true);
+              break;
+
+            case KeyEvent.VK_LEFT:
+              if (viewport.cursorMode)
+              {
+                alignPanel.seqPanel.moveCursor( -1, 0);
+              }
+              break;
+
+            case KeyEvent.VK_RIGHT:
+              if (viewport.cursorMode)
+              {
+                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_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("Keyboard editing mode is " +
+                                           (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();
+
+              boolean hide = false;
+
+              SequenceGroup sg = viewport.getSelectionGroup();
+              if (toggleSeqs)
+              {
+                if (sg != null && sg.getSize(false) != viewport.alignment.getHeight())
+                {
+                  hideSelSequences_actionPerformed(null);
+                  hide = true;
+                }
+                else if (! (toggleCols && viewport.colSel.getSelected().size() > 0))
+                  showAllSeqs_actionPerformed(null);
+              }
+
+              if (toggleCols)
+              {
+                if (viewport.colSel.getSelected().size() > 0)
+                {
+                  hideSelColumns_actionPerformed(null);
+                  if (!toggleSeqs)
+                    viewport.selectionGroup = sg;
+                }
+                else if (!hide)
+                  showAllColumns_actionPerformed(null);
+              }
+              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;
+          }
+        }
+      });
+  }
+
+
+  public void addAlignmentPanel(final AlignmentPanel ap,
+                                boolean newPanel)
+  {
+    ap.alignFrame = this;
+
+    alignPanels.addElement(ap);
+
+    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)
+      {
+        AlignmentPanel first = (AlignmentPanel) alignPanels.firstElement();
+        tabbedPane.addTab(first.av.viewName==null?"Original":first.av.viewName,first);
+
+        this.getContentPane().add(tabbedPane, BorderLayout.CENTER);
+      }
+
+      tabbedPane.addTab(ap.av.viewName==null?"Original":ap.av.viewName, ap);
+
+      ap.setVisible(false);
+    }
+
+    if(newPanel)
+    {
+      ap.av.updateConsensus(ap);
+      ap.av.updateConservation(ap);
+    }
+  }
+
+
+  public AlignViewport getViewport()
+  {
+    return viewport;
+  }
+
+  /* Set up intrinsic listeners for dynamically generated GUI bits. */
+  private void addServiceListeners()
+  {
+    final java.beans.PropertyChangeListener thisListener;
+    // Do this once to get current state
+    BuildWebServiceMenu();
+    Desktop.discoverer.addPropertyChangeListener(
+        thisListener = new java.beans.PropertyChangeListener()
+    {
+      public void propertyChange(PropertyChangeEvent evt)
+      {
+        // System.out.println("Discoverer property change.");
+        if (evt.getPropertyName().equals("services"))
+        {
+          // System.out.println("Rebuilding web service menu");
+          BuildWebServiceMenu();
+        }
+      }
+    });
+
+    addInternalFrameListener(new javax.swing.event.
+                             InternalFrameAdapter()
+    {
+      public void internalFrameClosed(
+          javax.swing.event.InternalFrameEvent evt)
+      {
+        // System.out.println("deregistering discoverer listener");
+        Desktop.discoverer.removePropertyChangeListener(thisListener);
+        closeMenuItem_actionPerformed(null);
+      }
+      ;
+    });
+  }
+
+  public void setGUINucleotide(boolean nucleotide)
+  {
+    showTranslation.setVisible( nucleotide );
+    conservationMenuItem.setEnabled( !nucleotide );
+    modifyConservation.setEnabled(   !nucleotide );
+
+    //Remember AlignFrame always starts as protein
+    if(!nucleotide)
+    {
+      calculateMenu.remove(calculateMenu.getItemCount()-2);
+    }
+  }
+
+  /**
+   * 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)
+  {
+    colourTextMenuItem.setSelected(av.showColourText);
+    abovePIDThreshold.setSelected(av.getAbovePIDThreshold());
+    conservationMenuItem.setSelected(av.getConservationSelected());
+    seqLimits.setSelected(av.getShowJVSuffix());
+    renderGapsMenuItem.setSelected(av.renderGaps);
+    wrapMenuItem.setSelected(av.wrapAlignment);
+    annotationPanelMenuItem.setState(av.showAnnotation);
+    viewBoxesMenuItem.setSelected(av.showBoxes);
+    viewTextMenuItem.setSelected(av.showText);
+
+    setColourSelected(ColourSchemeProperty.
+                      getColourName(av.getGlobalColourScheme()));
+
+    showSeqFeatures.setSelected(av.showSequenceFeatures);
+    hiddenMarkers.setState(av.showHiddenMarkers);
+    applyToAllGroups.setState(av.colourAppliesToAllGroups);
+    smoothFont.setState(av.antiAlias);
+
+    updateEditMenuBar();
+  }
+
+
+  Hashtable progressBars;
+  public void setProgressBar(String message, long id)
+  {
+    if(progressBars == null)
+      progressBars = new Hashtable();
+
+    JPanel progressPanel;
+    GridLayout layout = (GridLayout) statusPanel.getLayout();
+    if(progressBars.get( new Long(id) )!=null)
+     {
+       progressPanel = (JPanel)progressBars.get( new Long(id) );
+       statusPanel.remove(progressPanel);
+       progressBars.remove( progressPanel );
+       progressPanel = null;
+       if(message!=null)
+         statusBar.setText(message);
+
+       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(new Long(id), progressPanel);
+    }
+
+    validate();
+  }
+
+
+
+
+  /*
+   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();
+  }
+
+
+  public void fetchSequence_actionPerformed(ActionEvent e)
+  {
+    new SequenceFetcher(this);
+  }
+
+  public void addFromFile_actionPerformed(ActionEvent e)
+  {
+    Desktop.instance.inputLocalFileMenuItem_actionPerformed(viewport);
+  }
+
+  public void addFromText_actionPerformed(ActionEvent e)
+  {
+    Desktop.instance.inputTextboxMenuItem_actionPerformed(viewport);
+  }
+
+  public void addFromURL_actionPerformed(ActionEvent e)
+  {
+    Desktop.instance.inputURLMenuItem_actionPerformed(viewport);
+  }
+
+
+  public void save_actionPerformed(ActionEvent e)
+  {
+    if(fileName==null || currentFileFormat==null)
+      saveAs_actionPerformed(null);
+    else
+      saveAlignment(fileName, currentFileFormat);
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void saveAs_actionPerformed(ActionEvent e)
+  {
+    JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.
+        getProperty( "LAST_DIRECTORY"),
+        new String[]
+        { "fa, fasta, fastq", "aln", "pfam", "msf", "pir", "blc","jar" },
+        new String[]
+        { "Fasta", "Clustal", "PFAM", "MSF", "PIR", "BLC", "Jalview" },
+        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,
+                                                "You must select a file format before saving!",
+                                                "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);
+
+      saveAlignment(fileName, currentFileFormat);
+    }
+  }
+
+  public boolean saveAlignment(String file, String format)
+  {
+    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);
+      }
+
+      new Jalview2XML().SaveAlignment(this, file, shortName);
+
+      statusBar.setText("Successfully saved to file: "
+                          +fileName+" in "
+                          +format +" format.");
+
+
+      // USE Jalview2XML to save this file
+      return true;
+    }
+    else
+    {
+
+      String[] omitHidden = null;
+
+      if (viewport.hasHiddenColumns)
+      {
+        int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,
+            "The Alignment contains hidden columns."
+            + "\nDo you want to save only the visible alignment?",
+            "Save / Omit Hidden Columns",
+            JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
+
+        if (reply == JOptionPane.YES_OPTION)
+          omitHidden = viewport.getViewAsString(false);
+      }
+
+      String output = new FormatAdapter().formatSequences(
+          format,
+          viewport.alignment.getSequencesArray(),
+          omitHidden);
+
+      if (output == null)
+      {
+        return false;
+      }
+
+      try
+      {
+        java.io.PrintWriter out = new java.io.PrintWriter(
+            new java.io.FileWriter(file));
+
+        out.print(output);
+        out.close();
+        this.setTitle(file);
+        statusBar.setText("Successfully saved to file: "
+                          +fileName+" in "
+                          +format +" format.");
+        return true;
+      }
+      catch (Exception ex)
+      {
+        ex.printStackTrace();
+      }
+    }
+    return false;
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void outputText_actionPerformed(ActionEvent e)
+  {
+    String [] omitHidden = null;
+
+    if(viewport.hasHiddenColumns)
+    {
+      int reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,
+          "The Alignment contains hidden columns."
+      +"\nDo you want to output only the visible alignment?",
+      "Save / Omit Hidden Columns",
+      JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
+
+      if(reply==JOptionPane.YES_OPTION)
+      {
+        omitHidden = viewport.getViewAsString(false);
+      }
+    }
+
+    CutAndPasteTransfer cap = new CutAndPasteTransfer();
+    Desktop.addInternalFrame(cap,
+                             "Alignment output - " + e.getActionCommand(), 600,
+                             500);
+
+
+    cap.setText(new FormatAdapter().formatSequences(
+        e.getActionCommand(),
+        viewport.alignment.getSequencesArray(),
+        omitHidden));
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void htmlMenuItem_actionPerformed(ActionEvent e)
+  {
+    new HTMLOutput(viewport,
+                   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!
+   */
+  public void createPNG(File f)
+  {
+    alignPanel.makePNG(f);
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void createEPS(File f)
+  {
+    alignPanel.makeEPS(f);
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void printMenuItem_actionPerformed(ActionEvent e)
+  {
+    //Putting in a thread avoids Swing painting problems
+    PrintThread thread = new PrintThread();
+    thread.start();
+  }
+
+  public void exportFeatures_actionPerformed(ActionEvent e)
+  {
+    new AnnotationExporter().exportFeatures(alignPanel);
+  }
+
+
+  public void exportAnnotations_actionPerformed(ActionEvent e)
+  {
+    new AnnotationExporter().exportAnnotations(
+      alignPanel,
+      viewport.alignment.getAlignmentAnnotation()
+        );
+  }
+
+
+  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);
+    }
+
+  }
+
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void closeMenuItem_actionPerformed(ActionEvent e)
+  {
+    try
+    {
+      if(alignPanels!=null)
+      {
+        for (int i = 0; i < alignPanels.size(); i++)
+        {
+          AlignmentPanel ap = (AlignmentPanel) alignPanels.elementAt(i);
+          PaintRefresher.RemoveComponent(ap.seqPanel.seqCanvas);
+          PaintRefresher.RemoveComponent(ap.idPanel.idCanvas);
+          PaintRefresher.RemoveComponent(ap);
+        }
+      //  alignPanels = null;
+      }
+    //  else
+     //   System.out.println("null one here");
+
+    //  alignPanel = null;
+    //  viewport = null;
+
+      this.setClosed(true);
+    }
+    catch (Exception ex)
+    {
+      ex.printStackTrace();
+    }
+  }
+
+
+  /**
+   * DOCUMENT ME!
+   */
+  void updateEditMenuBar()
+  {
+
+    if (viewport.historyList.size() > 0)
+    {
+      undoMenuItem.setEnabled(true);
+      CommandI command = (CommandI) viewport.historyList.peek();
+      undoMenuItem.setText("Undo " + command.getDescription());
+    }
+    else
+    {
+      undoMenuItem.setEnabled(false);
+      undoMenuItem.setText("Undo");
+    }
+
+    if (viewport.redoList.size() > 0)
+    {
+      redoMenuItem.setEnabled(true);
+
+      CommandI command = (CommandI) viewport.redoList.peek();
+      redoMenuItem.setText("Redo " + command.getDescription());
+    }
+    else
+    {
+      redoMenuItem.setEnabled(false);
+      redoMenuItem.setText("Redo");
+    }
+  }
+
+
+  public void addHistoryItem(CommandI command)
+  {
+    if(command.getSize()>0)
+    {
+      viewport.historyList.push(command);
+      viewport.redoList.clear();
+      updateEditMenuBar();
+      viewport.hasHiddenColumns = viewport.colSel.getHiddenColumns() != null;
+    }
+  }
+
+
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void undoMenuItem_actionPerformed(ActionEvent e)
+  {
+    CommandI command = (CommandI)viewport.historyList.pop();
+    viewport.redoList.push(command);
+    command.undoCommand();
+
+    viewport.hasHiddenColumns = viewport.colSel.getHiddenColumns() != null;
+    updateEditMenuBar();
+    viewport.firePropertyChange("alignment", null,
+                                viewport.getAlignment().getSequences());
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void redoMenuItem_actionPerformed(ActionEvent e)
+  {
+    CommandI command = (CommandI) viewport.redoList.pop();
+    viewport.historyList.push(command);
+    command.doCommand();
+    viewport.hasHiddenColumns = viewport.colSel.getHiddenColumns()!=null;
+
+    updateEditMenuBar();
+    viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());
+  }
+
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param up DOCUMENT ME!
+   */
+  public void moveSelectedSequences(boolean up)
+  {
+    SequenceGroup sg = viewport.getSelectionGroup();
+
+    if (sg == null)
+    {
+      return;
+    }
+
+    if (up)
+    {
+      for (int i = 1; i < viewport.alignment.getHeight(); i++)
+      {
+        SequenceI seq = viewport.alignment.getSequenceAt(i);
+
+        if (!sg.getSequences(false).contains(seq))
+        {
+          continue;
+        }
+
+        SequenceI temp = viewport.alignment.getSequenceAt(i - 1);
+
+        if (sg.getSequences(false).contains(temp))
+        {
+          continue;
+        }
+
+        viewport.alignment.getSequences().setElementAt(temp, i);
+        viewport.alignment.getSequences().setElementAt(seq, i - 1);
+      }
+    }
+    else
+    {
+      for (int i = viewport.alignment.getHeight() - 2; i > -1; i--)
+      {
+        SequenceI seq = viewport.alignment.getSequenceAt(i);
+
+        if (!sg.getSequences(false).contains(seq))
+        {
+          continue;
+        }
+
+        SequenceI temp = viewport.alignment.getSequenceAt(i + 1);
+
+        if (sg.getSequences(false).contains(temp))
+        {
+          continue;
+        }
+
+        viewport.alignment.getSequences().setElementAt(temp, i);
+        viewport.alignment.getSequences().setElementAt(seq, i + 1);
+      }
+    }
+
+    alignPanel.repaint();
+  }
+
+
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void copy_actionPerformed(ActionEvent e)
+  {
+    System.gc();
+    if (viewport.getSelectionGroup() == null)
+    {
+      return;
+    }
+
+    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
+    {
+      //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)
+    {
+      er.printStackTrace();
+      javax.swing.SwingUtilities.invokeLater(new Runnable()
+          {
+            public void run()
+            {
+              javax.swing.JOptionPane.showInternalMessageDialog(Desktop.desktop,
+                  "Out of memory copying region!!"
+                  +
+                  "\nSee help files for increasing Java Virtual Machine memory."
+                  , "Out of memory",
+                  javax.swing.JOptionPane.WARNING_MESSAGE);
+            }
+          });
+
+      return;
+    }
+
+    Vector hiddenColumns = null;
+    if(viewport.hasHiddenColumns)
+    {
+      hiddenColumns =new Vector();
+      int hiddenOffset = viewport.getSelectionGroup().getStartRes();
+      for(int i=0; i<viewport.getColumnSelection().getHiddenColumns().size(); i++)
+      {
+        int[] region = (int[])
+            viewport.getColumnSelection().getHiddenColumns().elementAt(i);
+
+        hiddenColumns.addElement(new int[]{region[0]-hiddenOffset,
+                          region[1]-hiddenOffset});
+      }
+    }
+
+
+
+    Desktop.jalviewClipboard = new Object[]{ seqs,
+        viewport.alignment.getDataset(),
+        hiddenColumns};
+    statusBar.setText("Copied "+seqs.length+" sequences to clipboard.");
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void pasteNew_actionPerformed(ActionEvent e)
+  {
+    paste(true);
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void pasteThis_actionPerformed(ActionEvent e)
+  {
+    paste(false);
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param newAlignment DOCUMENT ME!
+   */
+  void paste(boolean newAlignment)
+  {
+    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)
+      {
+        er.printStackTrace();
+        javax.swing.SwingUtilities.invokeLater(new Runnable()
+        {
+          public void run()
+          {
+            javax.swing.JOptionPane.showInternalMessageDialog(Desktop.desktop,
+                "Out of memory pasting sequences!!"
+                +
+                "\nSee help files for increasing Java Virtual Machine memory."
+                , "Out of memory",
+                javax.swing.JOptionPane.WARNING_MESSAGE);
+          }
+        });
+
+        return;
+      }
+
+      SequenceI[] sequences;
+
+
+     if(Desktop.jalviewClipboard!=null)
+     {
+       // The clipboard was filled from within Jalview, we must use the sequences
+       // And dataset from the copied alignment
+       sequences = (SequenceI[])Desktop.jalviewClipboard[0];
+     }
+     else
+     {
+       sequences = new FormatAdapter().readFile(str, "Paste", format);
+     }
+
+     AlignmentI alignment = null;
+
+      if (newAlignment)
+      {
+          alignment = new Alignment(sequences);
+
+          if (Desktop.jalviewClipboard != null)
+            alignment.setDataset( (Alignment) Desktop.jalviewClipboard[1]);
+          else
+            alignment.setDataset(null);
+      }
+      else
+      {
+        alignment = viewport.getAlignment();
+
+        //!newAlignment
+        SequenceI [] newseqs = new SequenceI[sequences.length];
+        for (int i = 0; i < sequences.length; i++)
+        {
+          newseqs[i] = new Sequence(sequences[i].getName(),
+              sequences[i].getSequence(), sequences[i].getStart(),
+              sequences[i].getEnd());
+
+          alignment.addSequence(newseqs[i]);
+        }
+
+        /*
+         //ADD HISTORY ITEM
+         */
+        addHistoryItem(new EditCommand(
+            "Add sequences",
+            EditCommand.PASTE,
+            newseqs,
+            0,
+            alignment.getWidth(),
+            alignment)
+            );
+
+
+        viewport.setEndSeq(alignment.getHeight());
+        alignment.getWidth();
+        viewport.firePropertyChange("alignment", null, alignment.getSequences());
+      }
+
+
+
+      // Add any annotations attached to sequences
+      for (int i = 0; i < sequences.length; i++)
+     {
+       if (sequences[i].getAnnotation() != null)
+       {
+         for (int a = 0; a < sequences[i].getAnnotation().length; a++)
+         {
+           AlignmentAnnotation newAnnot =
+               new AlignmentAnnotation(
+                   sequences[i].getAnnotation()[a].label,
+                   sequences[i].getAnnotation()[a].description,
+                   sequences[i].getAnnotation()[a].annotations,
+                   sequences[i].getAnnotation()[a].graphMin,
+                   sequences[i].getAnnotation()[a].graphMax,
+                   sequences[i].getAnnotation()[a].graph);
+
+           sequences[i].getAnnotation()[a] = newAnnot;
+           newAnnot.sequenceMapping = sequences[i].getAnnotation()[a].
+               sequenceMapping;
+           newAnnot.sequenceRef = sequences[i];
+           newAnnot.adjustForAlignment();
+           alignment.addAnnotation(newAnnot);
+           alignment.setAnnotationIndex(newAnnot, a);
+         }
+
+         alignPanel.annotationPanel.adjustPanelHeight();
+       }
+     }
+
+     if(newAlignment)
+     {
+       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());
+
+
+       if (title.startsWith("Copied sequences"))
+       {
+         newtitle = title;
+       }
+       else
+       {
+         newtitle = newtitle.concat("- from " + title);
+       }
+
+       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!
+   */
+  protected void cut_actionPerformed(ActionEvent e)
+  {
+    copy_actionPerformed(null);
+    delete_actionPerformed(null);
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void delete_actionPerformed(ActionEvent e)
+  {
+
+    SequenceGroup sg = viewport.getSelectionGroup();
+    if (sg == null)
+    {
+      return;
+    }
+
+    Vector seqs = new Vector();
+    int cutLength = sg.getEndRes()-sg.getStartRes()+1;
+    boolean seqsCut = false;
+    SequenceI seq;
+    for (int i = 0; i < sg.getSize(false); i++)
+    {
+      seq = sg.getSequenceAt(i);
+      seqs.addElement(seq);
+      if(seq.getLength()<=cutLength)
+        seqsCut = true;
+    }
+
+
+   // If the cut affects all sequences, remove highlighted columns
+   if (sg.getSize(false) == viewport.alignment.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.alignment));
+
+
+    viewport.setSelectionGroup(null);
+    viewport.alignment.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!
+   */
+  protected void deleteGroups_actionPerformed(ActionEvent e)
+  {
+    viewport.alignment.deleteAllGroups();
+    viewport.setSelectionGroup(null);
+    PaintRefresher.Refresh(this, viewport.getSequenceSetId());
+    alignPanel.repaint();
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  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.alignment.getWidth() - 1);
+    viewport.setSelectionGroup(sg);
+    alignPanel.repaint();
+    PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  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.repaint();
+    PaintRefresher.Refresh(this, viewport.getSequenceSetId());
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  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);
+    }
+
+    PaintRefresher.Refresh(this, viewport.getSequenceSetId());
+  }
+
+  public void invertColSel_actionPerformed(ActionEvent e)
+  {
+    viewport.invertColumnSelection();
+    alignPanel.repaint();
+  }
+
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
+  {
+    trimAlignment(true);
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  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(true);
+      else
+        seqs = viewport.alignment.getSequencesArray();
+
+
+      TrimRegionCommand trimRegion;
+      if(trimLeft)
+      {
+        trimRegion = new TrimRegionCommand("Remove Left",
+                                    TrimRegionCommand.TRIM_LEFT,
+                                    seqs,
+                                    column,
+                                    viewport.alignment,
+                                    viewport.colSel,
+                                    viewport.selectionGroup);
+      }
+     else
+     {
+       trimRegion = new TrimRegionCommand("Remove Right",
+                                   TrimRegionCommand.TRIM_RIGHT,
+                                   seqs,
+                                   column,
+                                   viewport.alignment,
+                                   viewport.colSel,
+                                   viewport.selectionGroup);
+     }
+
+     statusBar.setText("Removed "+trimRegion.getSize()+" columns.");
+
+
+      addHistoryItem(trimRegion);
+
+      Vector groups = viewport.alignment.getGroups();
+
+      for (int i = 0; i < groups.size(); i++)
+      {
+        SequenceGroup sg = (SequenceGroup) groups.get(i);
+
+        if ( (trimLeft && !sg.adjustForRemoveLeft(column))
+            || (!trimLeft && !sg.adjustForRemoveRight(column)))
+        {
+          viewport.alignment.deleteGroup(sg);
+        }
+      }
+
+      viewport.firePropertyChange("alignment", null,
+                                  viewport.getAlignment().getSequences());
+    }
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
+  {
+    int start = 0, end = viewport.alignment.getWidth()-1;
+
+    SequenceI[] seqs;
+    if (viewport.getSelectionGroup() != null)
+    {
+      seqs = viewport.getSelectionGroup().getSequencesAsArray(true);
+      start = viewport.getSelectionGroup().getStartRes();
+      end = viewport.getSelectionGroup().getEndRes();
+    }
+    else
+      seqs = viewport.alignment.getSequencesArray();
+
+
+    RemoveGapColCommand removeGapCols =
+        new RemoveGapColCommand("Remove Gapped Columns",
+                                seqs,
+                                start, end,
+                                viewport.getGapCharacter());
+
+    addHistoryItem(removeGapCols);
+
+    statusBar.setText("Removed "+removeGapCols.getSize()+" empty columns.");
+
+    //This is to maintain viewport position on first residue
+    //of first sequence
+    SequenceI seq = viewport.alignment.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!
+   */
+  public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
+  {
+    int start = 0, end = viewport.alignment.getWidth()-1;
+
+    SequenceI[] seqs;
+    if (viewport.getSelectionGroup() != null)
+    {
+      seqs = viewport.getSelectionGroup().getSequencesAsArray(true);
+      start = viewport.getSelectionGroup().getStartRes();
+      end = viewport.getSelectionGroup().getEndRes();
+    }
+    else
+      seqs = viewport.alignment.getSequencesArray();
+
+    //This is to maintain viewport position on first residue
+    //of first sequence
+    SequenceI seq = viewport.alignment.getSequenceAt(0);
+    int startRes = seq.findPosition(viewport.startRes);
+
+    addHistoryItem(new RemoveGapsCommand("Remove Gaps",
+                                           seqs,
+                                           start, end,
+                     viewport.getGapCharacter()));
+
+    viewport.setStartRes(seq.findIndex(startRes)-1);
+
+    viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());
+
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void padGapsMenuitem_actionPerformed(ActionEvent e)
+  {
+    viewport.padGaps = padGapsMenuitem.isSelected();
+
+    viewport.firePropertyChange("alignment",
+                                null,
+                                viewport.getAlignment().getSequences());
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void findMenuItem_actionPerformed(ActionEvent e)
+  {
+    JInternalFrame frame = new JInternalFrame();
+    Finder finder = new Finder(viewport, alignPanel, frame);
+    frame.setContentPane(finder);
+    frame.setLayer(JLayeredPane.PALETTE_LAYER);
+    Desktop.addInternalFrame(frame, "Find", 340, 110);
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void font_actionPerformed(ActionEvent e)
+  {
+    new FontChooser(alignPanel);
+  }
+
+  public void smoothFont_actionPerformed(ActionEvent e)
+  {
+    viewport.antiAlias = smoothFont.isSelected();
+    alignPanel.annotationPanel.image = null;
+    alignPanel.repaint();
+  }
+
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void seqLimit_actionPerformed(ActionEvent e)
+  {
+    viewport.setShowJVSuffix(seqLimits.isSelected());
+
+    alignPanel.idPanel.idCanvas.setPreferredSize(alignPanel.calculateIdWidth());
+    alignPanel.repaint();
+  }
+
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void colourTextMenuItem_actionPerformed(ActionEvent e)
+  {
+    viewport.setColourText(colourTextMenuItem.isSelected());
+    alignPanel.repaint();
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  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());
+  }
+
+  public void showAllSeqs_actionPerformed(ActionEvent e)
+  {
+    viewport.showAllHiddenSeqs();
+  }
+
+  public void showAllColumns_actionPerformed(ActionEvent e)
+  {
+    viewport.showAllHiddenColumns();
+    repaint();
+  }
+
+  public void hideSelSequences_actionPerformed(ActionEvent e)
+  {
+    viewport.hideAllSelectedSeqs();
+    alignPanel.repaint();
+  }
+
+  public void hideSelColumns_actionPerformed(ActionEvent e)
+  {
+    viewport.hideSelectedColumns();
+    alignPanel.repaint();
+  }
+
+  public void hiddenMarkers_actionPerformed(ActionEvent e)
+  {
+    viewport.setShowHiddenMarkers(hiddenMarkers.isSelected());
+    repaint();
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void scaleAbove_actionPerformed(ActionEvent e)
+  {
+    viewport.setScaleAboveWrapped(scaleAbove.isSelected());
+    alignPanel.repaint();
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void scaleLeft_actionPerformed(ActionEvent e)
+  {
+    viewport.setScaleLeftWrapped(scaleLeft.isSelected());
+    alignPanel.repaint();
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void scaleRight_actionPerformed(ActionEvent e)
+  {
+    viewport.setScaleRightWrapped(scaleRight.isSelected());
+    alignPanel.repaint();
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
+  {
+    viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
+    alignPanel.repaint();
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void viewTextMenuItem_actionPerformed(ActionEvent e)
+  {
+    viewport.setShowText(viewTextMenuItem.isSelected());
+    alignPanel.repaint();
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
+  {
+    viewport.setRenderGaps(renderGapsMenuItem.isSelected());
+    alignPanel.repaint();
+  }
+
+
+  public FeatureSettings featureSettings;
+  public void featureSettings_actionPerformed(ActionEvent e)
+  {
+    if(featureSettings !=null )
+    {
+      featureSettings.close();
+      featureSettings = null;
+    }
+    featureSettings = new FeatureSettings(this);
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param evt DOCUMENT ME!
+   */
+  public void showSeqFeatures_actionPerformed(ActionEvent evt)
+  {
+    viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
+    alignPanel.repaint();
+    if (alignPanel.getOverviewPanel() != null)
+    {
+      alignPanel.getOverviewPanel().updateOverviewImage();
+    }
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
+  {
+    viewport.setShowAnnotation(annotationPanelMenuItem.isSelected());
+    alignPanel.setAnnotationVisible(annotationPanelMenuItem.isSelected());
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  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()
+    {
+      public void internalFrameClosed(
+          javax.swing.event.InternalFrameEvent evt)
+      {
+        alignPanel.setOverviewPanel(null);
+      }
+      ;
+    });
+
+    alignPanel.setOverviewPanel(overview);
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void noColourmenuItem_actionPerformed(ActionEvent e)
+  {
+    changeColour(null);
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void clustalColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new ClustalxColourScheme(
+        viewport.alignment.getSequences(), viewport.alignment.getWidth()));
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void zappoColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new ZappoColourScheme());
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void taylorColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new TaylorColourScheme());
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void hydrophobicityColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new HydrophobicColourScheme());
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void helixColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new HelixColourScheme());
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void strandColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new StrandColourScheme());
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void turnColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new TurnColourScheme());
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void buriedColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new BuriedColourScheme());
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void nucleotideColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new NucleotideColourScheme());
+  }
+
+  public void annotationColour_actionPerformed(ActionEvent e)
+  {
+    new AnnotationColourChooser(viewport, alignPanel);
+  }
+
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void applyToAllGroups_actionPerformed(ActionEvent e)
+  {
+    viewport.setColourAppliesToAllGroups(applyToAllGroups.isSelected());
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param cs DOCUMENT ME!
+   */
+  public void changeColour(ColourSchemeI cs)
+  {
+    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.alignment;
+        Conservation c = new Conservation("All",
+                                          ResidueProperties.propHash, 3,
+                                          al.getSequences(), 0,
+                                          al.getWidth() - 1);
+
+        c.calculate();
+        c.verdict(false, viewport.ConsPercGaps);
+
+        cs.setConservation(c);
+
+        cs.setConservationInc(SliderPanel.setConservationSlider(alignPanel, cs,
+            "Background"));
+      }
+      else
+      {
+        cs.setConservation(null);
+      }
+
+      cs.setConsensus(viewport.hconsensus);
+    }
+
+    viewport.setGlobalColourScheme(cs);
+
+    if (viewport.getColourAppliesToAllGroups())
+    {
+      Vector groups = viewport.alignment.getGroups();
+
+      for (int i = 0; i < groups.size(); i++)
+      {
+        SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
+
+        if (cs == null)
+        {
+          sg.cs = null;
+          continue;
+        }
+
+        if (cs instanceof ClustalxColourScheme)
+        {
+          sg.cs = new ClustalxColourScheme(
+              sg.getSequences(true), sg.getWidth());
+        }
+        else if (cs instanceof UserColourScheme)
+        {
+          sg.cs = new UserColourScheme( ( (UserColourScheme) cs).getColours());
+        }
+        else
+        {
+          try
+          {
+            sg.cs = (ColourSchemeI) 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(true), 0,
+             sg.getWidth()));
+       }
+        else
+          sg.cs.setThreshold(0, viewport.getIgnoreGapsConsensus());
+
+
+        if (viewport.getConservationSelected())
+        {
+          Conservation c = new Conservation("Group",
+                                            ResidueProperties.propHash, 3,
+                                            sg.getSequences(true), 0,
+                                            viewport.alignment.getWidth() - 1);
+          c.calculate();
+          c.verdict(false, viewport.ConsPercGaps);
+          sg.cs.setConservation(c);
+        }
+        else
+          sg.cs.setConservation(null);
+      }
+    }
+
+    if (alignPanel.getOverviewPanel() != null)
+    {
+      alignPanel.getOverviewPanel().updateOverviewImage();
+    }
+
+    alignPanel.repaint();
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void modifyPID_actionPerformed(ActionEvent e)
+  {
+    if (viewport.getAbovePIDThreshold() && viewport.globalColourScheme!=null)
+    {
+      SliderPanel.setPIDSliderSource(alignPanel,
+                                     viewport.getGlobalColourScheme(),
+                                     "Background");
+      SliderPanel.showPIDSlider();
+    }
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void modifyConservation_actionPerformed(ActionEvent e)
+  {
+    if (viewport.getConservationSelected() && viewport.globalColourScheme!=null)
+    {
+      SliderPanel.setConservationSlider(alignPanel,
+                                        viewport.globalColourScheme,
+                                        "Background");
+      SliderPanel.showConservationSlider();
+    }
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  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!
+   */
+  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!
+   */
+  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()
+            {
+              public void mousePressed(MouseEvent evt)
+              {
+                if(evt.isControlDown() || SwingUtilities.isRightMouseButton(evt))
+                {
+                  radioItem.removeActionListener(radioItem.getActionListeners()[0]);
+
+                  int option = JOptionPane.showInternalConfirmDialog(jalview.gui.Desktop.desktop,
+                      "Remove from default list?",
+                      "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()
+                    {
+                      public void actionPerformed(ActionEvent evt)
+                      {
+                        userDefinedColour_actionPerformed(evt);
+                      }
+                    });
+                }
+              }
+            });
+        radioItem.addActionListener(new ActionListener()
+        {
+          public void actionPerformed(ActionEvent evt)
+          {
+            userDefinedColour_actionPerformed(evt);
+          }
+        });
+
+        colourMenu.insert(radioItem, 15);
+        colours.add(radioItem);
+      }
+    }
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void PIDColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new PIDColourScheme());
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void BLOSUM62Colour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new Blosum62ColourScheme());
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
+  {
+    SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
+    AlignmentSorter.sortByPID(viewport.getAlignment(),
+                              viewport.getAlignment().getSequenceAt(0));
+    addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder, viewport.alignment));
+    alignPanel.repaint();
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void sortIDMenuItem_actionPerformed(ActionEvent e)
+  {
+    SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
+    AlignmentSorter.sortByID(viewport.getAlignment());
+    addHistoryItem(new OrderCommand("ID Sort", oldOrder, viewport.alignment));
+    alignPanel.repaint();
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void sortGroupMenuItem_actionPerformed(ActionEvent e)
+  {
+    SequenceI [] oldOrder = viewport.getAlignment().getSequencesArray();
+    AlignmentSorter.sortByGroup(viewport.getAlignment());
+    addHistoryItem(new OrderCommand("Group Sort", oldOrder, viewport.alignment));
+
+    alignPanel.repaint();
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
+  {
+    new RedundancyPanel(alignPanel, this);
+  }
+
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
+  {
+    if ( (viewport.getSelectionGroup() == null) ||
+        (viewport.getSelectionGroup().getSize(false) < 2))
+    {
+      JOptionPane.showInternalMessageDialog(this,
+                                            "You must select at least 2 sequences.",
+                                            "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!
+   */
+  public void PCAMenuItem_actionPerformed(ActionEvent e)
+  {
+    if ( ( (viewport.getSelectionGroup() != null) &&
+          (viewport.getSelectionGroup().getSize(false) < 4) &&
+          (viewport.getSelectionGroup().getSize(false) > 0)) ||
+        (viewport.getAlignment().getHeight() < 4))
+    {
+      JOptionPane.showInternalMessageDialog(this,
+                                            "Principal component analysis must take\n" +
+                                            "at least 4 input sequences.",
+                                            "Sequence selection insufficient",
+                                            JOptionPane.WARNING_MESSAGE);
+
+      return;
+    }
+
+     new PCAPanel(viewport);
+  }
+
+
+  public void autoCalculate_actionPerformed(ActionEvent e)
+  {
+    viewport.autoCalculateConsensus = autoCalculate.isSelected();
+    if(viewport.autoCalculateConsensus)
+    {
+      viewport.firePropertyChange("alignment",
+                                  null,
+                                  viewport.getAlignment().getSequences());
+    }
+  }
+
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)
+  {
+    NewTreePanel("AV", "PID", "Average distance tree using PID");
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)
+  {
+    NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)
+  {
+    NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");
+  }
+
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  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) {
+      if (viewport.getSelectionGroup().getSize(false) < 3) {
+        JOptionPane.showMessageDialog(Desktop.desktop,
+                                      "You need to have more than two sequences selected to build a tree!",
+                                      "Not enough sequences",
+                                      JOptionPane.WARNING_MESSAGE);
+        return;
+      }
+
+      int s = 0;
+      SequenceGroup sg = viewport.getSelectionGroup();
+
+      /* Decide if the selection is a column region */
+      while (s < sg.getSize(false))
+      {
+        if ( ( (SequenceI) sg.getSequences(false).elementAt(s++)).getLength() <
+            sg.getEndRes())
+        {
+          JOptionPane.showMessageDialog(Desktop.desktop,
+                                        "The selected region to create a tree may\nonly contain residues or gaps.\n" +
+                                        "Try using the Pad function in the edit menu,\n" +
+                                        "or one of the multiple sequence alignment web services.",
+                                        "Sequences in selection are not aligned",
+                                        JOptionPane.WARNING_MESSAGE);
+
+          return;
+        }
+      }
+
+      title = title + " on region";
+      tp = new TreePanel(alignPanel, type, pwType);
+    }
+    else
+    {
+      //are the sequences aligned?
+      if (!viewport.alignment.isAligned())
+      {
+        JOptionPane.showMessageDialog(Desktop.desktop,
+                                      "The sequences must be aligned before creating a tree.\n" +
+                                      "Try using the Pad function in the edit menu,\n" +
+                                      "or one of the multiple sequence alignment web services.",
+                                      "Sequences not aligned",
+                                      JOptionPane.WARNING_MESSAGE);
+
+        return;
+      }
+
+      if(viewport.alignment.getHeight()<2)
+        return;
+
+      tp = new TreePanel(alignPanel, type, pwType);
+    }
+
+    addTreeMenuItem(tp, title);
+
+    Desktop.addInternalFrame(tp, title + " from " + this.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()
+    {
+      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.alignment));
+
+        alignPanel.repaint();
+      }
+    });
+  }
+
+  /**
+   * 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.
+   */
+  void addTreeMenuItem(final TreePanel treePanel, String title)
+  {
+    final JMenuItem item = new JMenuItem(title);
+
+    treeCount++;
+
+    if (treeCount == 1)
+    {
+      sort.add(sortByTreeMenu);
+    }
+
+    sortByTreeMenu.add(item);
+    item.addActionListener(new java.awt.event.ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
+        AlignmentSorter.sortByTree(viewport.getAlignment(),
+                                   treePanel.getTree());
+
+        addHistoryItem(new OrderCommand("Tree Sort",
+                                        oldOrder,
+                                        viewport.alignment));
+
+
+        alignPanel.repaint();
+      }
+    });
+
+    treePanel.addInternalFrameListener(new javax.swing.event.
+                                       InternalFrameAdapter()
+    {
+      public void internalFrameClosed(
+          javax.swing.event.InternalFrameEvent evt)
+      {
+        treeCount--;
+        sortByTreeMenu.remove(item);
+
+        if (treeCount == 0)
+        {
+          sort.remove(sortByTreeMenu);
+        }
+      }
+      ;
+    });
+  }
+
+  /**
+   * Work out whether the whole set of sequences
+   * or just the selected set will be submitted for multiple alignment.
+   *
+   */
+  private jalview.datamodel.AlignmentView gatherSequencesForAlignment()
+  {
+    // Now, check we have enough sequences
+    AlignmentView msa = null;
+
+    if ( (viewport.getSelectionGroup() != null) &&
+        (viewport.getSelectionGroup().getSize(false) > 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 currently selected sequence, or the currently selected alignment
+   * (where the first sequence in the set is the one that the prediction
+   * will be for).
+   */
+  AlignmentView gatherSeqOrMsaForSecStrPrediction()
+  {
+   AlignmentView seqs = null;
+
+    if ( (viewport.getSelectionGroup() != null) &&
+        (viewport.getSelectionGroup().getSize(false) > 0))
+    {
+      seqs = viewport.getAlignmentView(true);
+    }
+    else
+    {
+      seqs = viewport.getAlignmentView(false);
+    }
+    // limit sequences - JBPNote in future - could spawn multiple prediction jobs
+    // TODO: viewport.alignment.isAligned is a global state - the local selection may well be aligned - we preserve 2.0.8 behaviour for moment.
+    if (!viewport.alignment.isAligned())
+    {
+      seqs.setSequences(new SeqCigar[] { seqs.getSequences()[0] } );
+    }
+    return seqs;
+  }
+  /**
+   * DOCUMENT ME!
+   *
+   * @param e DOCUMENT ME!
+   */
+  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);
+
+      try
+      {
+        jalview.io.NewickFile fin = new jalview.io.NewickFile(choice,
+            "File");
+        viewport.setCurrentTree(ShowNewickTree(fin, choice).getTree());
+      }
+      catch (Exception ex)
+      {
+        JOptionPane.showMessageDialog(Desktop.desktop,
+                                      "Problem reading tree file",
+                                      ex.getMessage(),
+                                      JOptionPane.WARNING_MESSAGE);
+        ex.printStackTrace();
+      }
+    }
+  }
+
+
+  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);
+        addTreeMenuItem(tp, title);
+      }
+    }
+    catch (Exception ex)
+    {
+      ex.printStackTrace();
+    }
+
+    return tp;
+  }
+
+  class PrintThread
+      extends Thread
+  {
+    public void run()
+    {
+      PrinterJob printJob = PrinterJob.getPrinterJob();
+      PageFormat pf = printJob.pageDialog(printJob.defaultPage());
+      printJob.setPrintable(alignPanel, pf);
+
+      if (printJob.printDialog())
+      {
+        try
+        {
+          printJob.print();
+        }
+        catch (Exception PrintException)
+        {
+          PrintException.printStackTrace();
+        }
+      }
+    }
+  }
+
+  /**
+   * Generates menu items and listener event actions for web service clients
+   *
+   */
+  public void BuildWebServiceMenu()
+  {
+    if ( (Discoverer.services != null)
+        && (Discoverer.services.size() > 0))
+    {
+      Vector msaws = (Vector) Discoverer.services.get("MsaWS");
+      Vector secstrpr = (Vector) Discoverer.services.get("SecStrPred");
+      Vector wsmenu = new Vector();
+      final AlignFrame af = this;
+      if (msaws != null)
+      {
+        // Add any Multiple Sequence Alignment Services
+        final JMenu msawsmenu = new JMenu("Alignment");
+        for (int i = 0, j = msaws.size(); i < j; i++)
+        {
+          final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle) msaws.
+              get(i);
+          final JMenuItem method = new JMenuItem(sh.getName());
+          method.addActionListener(new ActionListener()
+          {
+            public void actionPerformed(ActionEvent e)
+            {
+              AlignmentView msa = gatherSequencesForAlignment();
+              new jalview.ws.MsaWSClient(sh, title, msa,
+                  false, true, viewport.getAlignment().getDataset(), af);
+
+            }
+
+          });
+          msawsmenu.add(method);
+          // Deal with services that we know accept partial alignments.
+          if (sh.getName().indexOf("lustal") > -1)
+          {
+            // We know that ClustalWS can accept partial alignments for refinement.
+            final JMenuItem methodR = new JMenuItem(sh.getName()+" Realign");
+            methodR.addActionListener(new ActionListener()
+            {
+              public void actionPerformed(ActionEvent e)
+              {
+                AlignmentView msa = gatherSequencesForAlignment();
+                new jalview.ws.MsaWSClient(sh, title, msa,
+                    true, true, viewport.getAlignment().getDataset(), af);
+
+              }
+
+            });
+            msawsmenu.add(methodR);
+
+          }
+        }
+        wsmenu.add(msawsmenu);
+      }
+      if (secstrpr != null)
+      {
+        // Add any secondary structure prediction services
+        final JMenu secstrmenu = new JMenu("Secondary Structure Prediction");
+        for (int i = 0, j = secstrpr.size(); i < j; i++)
+        {
+          final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle)
+              secstrpr.get(i);
+          final JMenuItem method = new JMenuItem(sh.getName());
+          method.addActionListener(new ActionListener()
+          {
+            public void actionPerformed(ActionEvent e)
+            {
+              AlignmentView msa = gatherSeqOrMsaForSecStrPrediction();
+              if (msa.getSequences().length == 1)
+              {
+                // Single Sequence prediction
+                new jalview.ws.JPredClient(sh, title, false, msa, af, true);
+              }
+              else
+              {
+                if (msa.getSequences().length > 1)
+                {
+                  // Sequence profile based prediction
+                  new jalview.ws.JPredClient(sh,
+                      title, true, msa, af, true);
+                }
+              }
+            }
+          });
+          secstrmenu.add(method);
+        }
+        wsmenu.add(secstrmenu);
+      }
+      this.webService.removeAll();
+      for (int i = 0, j = wsmenu.size(); i < j; i++)
+      {
+        webService.add( (JMenu) wsmenu.get(i));
+      }
+    }
+    else
+    {
+      this.webService.removeAll();
+      this.webService.add(this.webServiceNoServices);
+    }
+    // TODO: add in rediscovery function
+    // TODO: reduce code redundancy.
+    // TODO: group services by location as well as function.
+  }
+
+ /* 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);
+    }
+  }*/
+
+
+
+
+public void showTranslation_actionPerformed(ActionEvent e)
+{
+  SequenceI [] selection = viewport.getSelectionAsNewSequence();
+  String [] seqstring = viewport.getViewAsString(true);
+
+  int s, sSize = selection.length;
+  SequenceI [] newSeq = new SequenceI[sSize];
+
+  int res, resSize;
+  StringBuffer protein;
+  String seq;
+  for(s=0; s<sSize; s++)
+  {
+    protein = new StringBuffer();
+    seq = AlignSeq.extractGaps("-. ", seqstring[s]);
+    resSize = seq.length();
+    resSize -= resSize%3;
+
+    for(res = 0; res < resSize; res+=3)
+    {
+      String codon = seq.substring(res, res+3);
+      codon = codon.replace('U', 'T');
+      String aa = ResidueProperties.codonTranslate(codon);
+      if(aa==null)
+        protein.append(viewport.getGapCharacter());
+      else if(aa.equals("STOP"))
+        protein.append("X");
+      else
+        protein.append( aa );
+    }
+    newSeq[s] = new Sequence(selection[s].getName(),
+                             protein.toString());
+  }
+
+
+  AlignmentI al = new Alignment(newSeq);
+  al.setDataset(null);
+
+
+  ////////////////////////////////
+  // Copy annotations across
+  jalview.datamodel.AlignmentAnnotation[] annotations
+      = viewport.alignment.getAlignmentAnnotation();
+  int a, aSize;
+  if(annotations!=null)
+  {
+    for (int i = 0; i < annotations.length; i++)
+    {
+      if (annotations[i].label.equals("Quality") ||
+          annotations[i].label.equals("Conservation") ||
+          annotations[i].label.equals("Consensus"))
+      {
+        continue;
+      }
+
+      aSize = viewport.alignment.getWidth() / 3;
+      jalview.datamodel.Annotation[] anots =
+          new jalview.datamodel.Annotation[aSize];
+
+      for (a = 0; a < viewport.alignment.getWidth(); a++)
+      {
+        if (annotations[i].annotations[a] == null
+            || annotations[i].annotations[a] == null)
+          continue;
+
+        anots[a / 3] = new Annotation(
+            annotations[i].annotations[a].displayCharacter,
+            annotations[i].annotations[a].description,
+            annotations[i].annotations[a].secondaryStructure,
+            annotations[i].annotations[a].value,
+            annotations[i].annotations[a].colour);
+      }
+
+      jalview.datamodel.AlignmentAnnotation aa
+          = new jalview.datamodel.AlignmentAnnotation(annotations[i].label,
+          annotations[i].description, anots);
+      al.addAnnotation(aa);
+    }
+  }
+
+    AlignFrame af = new AlignFrame(al, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+    Desktop.addInternalFrame(af, "Translation of "+this.getTitle(),
+                             DEFAULT_WIDTH,
+                             DEFAULT_HEIGHT);
+
+
+
+
+}
+
+/**
+ * DOCUMENT ME!
+ *
+ * @param String DOCUMENT ME!
+ */
+public boolean parseFeaturesFile(String file, String type)
+{
+    boolean featuresFile = false;
+    try{
+      featuresFile = new FeaturesFile(file, type).parse(viewport.alignment.getDataset(),
+                                         alignPanel.seqPanel.seqCanvas.
+                                         getFeatureRenderer().featureColours,
+                                         false);
+    }
+    catch(Exception ex)
+    {
+      ex.printStackTrace();
+    }
+
+    if(featuresFile)
+    {
+      viewport.showSequenceFeatures = true;
+      showSeqFeatures.setSelected(true);
+      alignPanel.repaint();
+    }
+
+    return featuresFile;
+}
+
+public void dragEnter(DropTargetDragEvent evt)
+{}
+
+public void dragExit(DropTargetEvent evt)
+{}
+
+public void dragOver(DropTargetDragEvent evt)
+{}
+
+public void dropActionChanged(DropTargetDragEvent evt)
+{}
+
+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);
+          java.io.File file = new java.io.File(uri);
+          files.add(file);
+        }
+      }
+    }
+    catch (Exception e)
+    {
+      e.printStackTrace();
+    }
+    if (files != null)
+    {
+      try
+      {
+
+        for (int i = 0; i < files.size(); i++)
+        {
+          loadJalviewDataFile(files.get(i).toString());
+        }
+      }
+      catch (Exception ex)
+      {
+        ex.printStackTrace();
+      }
+    }
+}
+
+  // This method will attempt to load a "dropped" file first by testing
+  // whether its and Annotation file, then features file. If both are
+  // false then the user may have dropped an alignment file onto this
+  // AlignFrame
+   public void loadJalviewDataFile(String file)
+  {
+    try{
+      String protocol = "File";
+
+      if (file.indexOf("http:") > -1 || file.indexOf("file:") > -1)
+      {
+        protocol = "URL";
+      }
+
+      boolean isAnnotation = new AnnotationFile().readAnnotationFile(viewport.
+          alignment, file);
+
+      if (!isAnnotation)
+      {
+        boolean isGroupsFile = parseFeaturesFile(file,protocol);
+        if (!isGroupsFile)
+        {
+          String 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);
+            alignPanel.adjustAnnotationHeight();
+            alignPanel.repaint();
+          }
+          else
+            new FileLoader().LoadFile(viewport, file, protocol, format);
+        }
+      }
+      else
+      {
+        // (isAnnotation)
+        alignPanel.adjustAnnotationHeight();
+      }
+
+    }catch(Exception ex)
+    {
+      ex.printStackTrace();
+    }
+  }
+
+  public void tabSelectionChanged(int index)
+  {
+    if (index > -1)
+    {
+      alignPanel = (AlignmentPanel) alignPanels.elementAt(index);
+      viewport = alignPanel.av;
+      setMenusFromViewport(viewport);
+    }
+  }
+
+  public void tabbedPane_mousePressed(MouseEvent e)
+  {
+    if(SwingUtilities.isRightMouseButton(e))
+    {
+      String reply = JOptionPane.showInternalInputDialog(this,
+          "Enter View Name",
+          "Edit View Name",
+          JOptionPane.QUESTION_MESSAGE);
+
+      if (reply != null)
+      {
+        viewport.viewName = reply;
+        tabbedPane.setTitleAt( tabbedPane.getSelectedIndex() ,reply);
+      }
+    }
+  }
+
+
+  public AlignViewport getCurrentView()
+  {
+    return viewport;
+  }
+}