GPL license added
[jalview.git] / src / jalview / gui / AlignFrame.java
index 6170cf9..8cb12d1 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
-    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
-    // add conservation graph to alignment\r
-    viewport.updateConservation();\r
-    viewport.updateConsensus();\r
-\r
-\r
-    alignPanel = new AlignmentPanel(this, viewport);\r
-\r
-    alignPanel.annotationPanel.adjustPanelHeight();\r
-    alignPanel.annotationSpaceFillerHolder.setPreferredSize(alignPanel.annotationPanel.getPreferredSize());\r
-    alignPanel.annotationScroller.setPreferredSize(alignPanel.annotationPanel.getPreferredSize());\r
-\r
-    getContentPane().add(alignPanel, java.awt.BorderLayout.CENTER);\r
-\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 [] = null;\r
-    if(e.getActionCommand().equals("FASTA"))\r
-      suffix = new String[]{"fa", "fasta"};\r
-    else if(e.getActionCommand().equals("MSF"))\r
-      suffix = new String[]{"msf"};\r
-    else if(e.getActionCommand().equals("CLUSTAL"))\r
-      suffix = new String[]{"aln"};\r
-    else if(e.getActionCommand().equals("BLC"))\r
-      suffix = new String[]{"blc"};\r
-    else if(e.getActionCommand().equals("PIR"))\r
-      suffix = new String[]{"pir"};\r
-    else if(e.getActionCommand().equals("PFAM"))\r
-      suffix = new String[]{"pfam"};\r
-\r
-\r
-    JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty("LAST_DIRECTORY")\r
-        , 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
-      viewport.updateConsensus();\r
-      alignPanel.RefreshPanels();\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, 500);\r
-      }\r
-      else\r
-      {\r
-        viewport.setEndSeq(viewport.alignment.getHeight());\r
-        viewport.alignment.getWidth();\r
-        viewport.updateConservation();\r
-        viewport.updateConsensus();\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
-   viewport.updateConservation();\r
-   viewport.updateConsensus();\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
-     viewport.updateConsensus();\r
-     alignPanel.RefreshPanels();\r
-     alignPanel.RefreshPanels();\r
-  }\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
-\r
-      if(viewport.getSelectionGroup()!=null)\r
-        viewport.getSelectionGroup().adjustForRemoveLeft(min);\r
-\r
-      Vector groups = viewport.alignment.getGroups();\r
-      for(int i=0; i<groups.size(); i++)\r
-      {\r
-        SequenceGroup sg = (SequenceGroup) groups.get(i);\r
-        if(!sg.adjustForRemoveLeft(min))\r
-          viewport.alignment.deleteGroup(sg);\r
-      }\r
-\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
-      viewport.getAlignment().trimRight(max);\r
-      if(viewport.getSelectionGroup()!=null)\r
-        viewport.getSelectionGroup().adjustForRemoveRight(max);\r
-\r
-      Vector groups = viewport.alignment.getGroups();\r
-      for(int i=0; i<groups.size(); i++)\r
-      {\r
-        SequenceGroup sg = (SequenceGroup) groups.get(i);\r
-        if(!sg.adjustForRemoveRight(max))\r
-          viewport.alignment.deleteGroup(sg);\r
-      }\r
-\r
-\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
-    viewport.updateConservation();\r
-    viewport.updateConsensus();\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
-    viewport.updateConservation();\r
-    viewport.updateConsensus();\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
-    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
-    scaleAbove.setVisible( wrapMenuItem.isSelected() );\r
-    scaleLeft.setVisible( wrapMenuItem.isSelected() );\r
-    scaleRight.setVisible( wrapMenuItem.isSelected() );\r
-    alignPanel.RefreshPanels();\r
-  }\r
-\r
-  protected void scaleAbove_actionPerformed(ActionEvent e)\r
-  {\r
-    viewport.setScaleAboveWrapped(scaleAbove.isSelected());\r
-    alignPanel.repaint();\r
-  }\r
-\r
-  protected void scaleLeft_actionPerformed(ActionEvent e)\r
-  {\r
-    viewport.setScaleLeftWrapped(scaleLeft.isSelected());\r
-    alignPanel.repaint();\r
-  }\r
-\r
-  protected void scaleRight_actionPerformed(ActionEvent e)\r
-  {\r
-    viewport.setScaleRightWrapped(scaleRight.isSelected());\r
-    alignPanel.repaint();\r
-  }\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 annotationPanelMenuItem_actionPerformed(ActionEvent e)\r
-  {\r
-    if(annotationPanelMenuItem.isSelected() && viewport.getWrapAlignment())\r
-    {\r
-      annotationPanelMenuItem.setSelected(false);\r
-      return;\r
-    }\r
-    viewport.setShowAnnotation( annotationPanelMenuItem.isSelected() );\r
-    alignPanel.setAnnotationVisible( annotationPanelMenuItem.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
-    if(coloursChanging)\r
-      return;\r
-\r
-    coloursChanging = true;\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
-    coloursChanging = false;\r
-  }\r
-\r
-  boolean coloursChanging = false;\r
-  public void abovePIDThreshold_actionPerformed(ActionEvent e)\r
-  {\r
-    if(coloursChanging)\r
-      return;\r
-\r
-    coloursChanging = true;\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
-    coloursChanging = false;\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
-  protected void jpred_actionPerformed(ActionEvent e)\r
-{\r
-\r
-    JInternalFrame frame = new JInternalFrame();\r
-    if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup().getSize()>0)\r
-    {\r
-      // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!\r
-      SequenceGroup seqs = viewport.getSelectionGroup();\r
-      if (seqs.getSize() == 1 || !viewport.alignment.isAligned())\r
-      {\r
-        JPredClient ct = new JPredClient( (SequenceI)\r
-                                         seqs.getSequenceAt(0));\r
-      }\r
-      else\r
-      {\r
-        int sz;\r
-        SequenceI[] msa = new SequenceI[sz=seqs.getSize()];\r
-        for (int i = 0; i < sz; i++)\r
-        {\r
-          msa[i] = (SequenceI) seqs.getSequenceAt(i);\r
-        }\r
-\r
-        JPredClient ct = new JPredClient(msa);\r
-      }\r
-\r
-    }\r
-    else\r
-    {\r
-      Vector seqs = viewport.getAlignment().getSequences();\r
-\r
-      if (seqs.size() == 1 || !viewport.alignment.isAligned())\r
-      {\r
-        JPredClient ct = new JPredClient( (SequenceI)\r
-                                         seqs.elementAt(0));\r
-      }\r
-      else\r
-      {\r
-        SequenceI[] msa = new SequenceI[seqs.size()];\r
-        for (int i = 0; i < seqs.size(); i++)\r
-        {\r
-          msa[i] = (SequenceI) seqs.elementAt(i);\r
-        }\r
-\r
-        JPredClient ct = new JPredClient(msa);\r
-      }\r
-\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) 2005 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 Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+*/
+
+package jalview.gui;
+
+import java.util.*;
+
+import java.awt.*;
+import java.awt.datatransfer.*;
+import java.awt.event.*;
+import java.awt.print.*;
+import javax.swing.*;
+import javax.swing.event.*;
+
+import jalview.analysis.*;
+import jalview.datamodel.*;
+import jalview.io.*;
+import jalview.jbgui.*;
+import jalview.schemes.*;
+import jalview.ws.*;
+import java.beans.PropertyChangeEvent;
+
+public class AlignFrame extends GAlignFrame
+{
+  final AlignmentPanel alignPanel;
+  final AlignViewport viewport;
+  public static final int NEW_WINDOW_WIDTH = 700;
+  public static final int NEW_WINDOW_HEIGHT = 500;
+  public String currentFileFormat = "Jalview";
+
+  public AlignFrame(AlignmentI al)
+  {
+    viewport = new AlignViewport(al);
+
+    alignPanel = new AlignmentPanel(this, viewport);
+    alignPanel.annotationPanel.adjustPanelHeight();
+    alignPanel.annotationSpaceFillerHolder.setPreferredSize(alignPanel.annotationPanel.getPreferredSize());
+    alignPanel.annotationScroller.setPreferredSize(alignPanel.annotationPanel.getPreferredSize());
+    alignPanel.setAnnotationVisible( viewport.getShowAnnotation() );
+
+    getContentPane().add(alignPanel, java.awt.BorderLayout.CENTER);
+
+    addInternalFrameListener(new InternalFrameAdapter()
+   {
+     public void internalFrameActivated(InternalFrameEvent evt)
+     {
+          javax.swing.SwingUtilities.invokeLater(new Runnable()
+          {
+            public void run()
+            {      alignPanel.requestFocus();    }
+          });
+
+     }
+   });
+
+  }
+
+  public void saveAlignmentMenu_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);
+
+    chooser.setAcceptAllFileFilterUsed(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();
+      jalview.bin.Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat);
+
+      if (currentFileFormat.equals("Jalview"))
+      {
+        String shortName = title;
+        if(shortName.indexOf(java.io.File.separatorChar)>-1)
+              shortName = shortName.substring(
+                    shortName.lastIndexOf(java.io.File.separatorChar)+1);
+
+        String choice = chooser.getSelectedFile().getPath();
+        Jalview2XML.SaveState(this, choice, shortName);
+        // USE Jalview2XML to save this file
+        return;
+      }
+
+      String choice =  chooser.getSelectedFile().getPath();
+      jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
+      String output = FormatAdapter.formatSequences(currentFileFormat, viewport.getAlignment().getSequences());
+      try{
+        java.io.PrintWriter out = new java.io.PrintWriter( new java.io.FileWriter( choice )  );
+        out.println(output);
+        out.close();
+      }
+      catch(Exception ex){}
+    }
+
+  }
+
+  protected void outputText_actionPerformed(ActionEvent e)
+  {
+     CutAndPasteTransfer cap = new CutAndPasteTransfer();
+     Desktop.addInternalFrame(cap, "Alignment output - "+e.getActionCommand(), 600, 500);
+     cap.setText( FormatAdapter.formatSequences(e.getActionCommand(), viewport.getAlignment().getSequences()));
+  }
+
+  protected void htmlMenuItem_actionPerformed(ActionEvent e)
+  {
+    new HTMLOutput(viewport);
+  }
+
+  protected void createPNG_actionPerformed(ActionEvent e)
+  {
+    alignPanel.makePNG();
+  }
+
+  protected void epsFile_actionPerformed(ActionEvent e)
+  {
+    alignPanel.makeEPS();
+  }
+
+
+  public void printMenuItem_actionPerformed(ActionEvent e)
+  {
+    //Putting in a thread avoids Swing painting problems
+    PrintThread thread = new PrintThread();
+    thread.start();
+  }
+
+  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();
+        }
+      }
+    }
+
+  }
+
+
+
+
+  public void closeMenuItem_actionPerformed(ActionEvent e)
+  {
+    try{
+      this.setClosed(true);
+    }catch(Exception ex){}
+  }
+
+  Stack historyList = new Stack();
+  Stack redoList = new Stack();
+  private int treeCount = 0;
+
+  void updateEditMenuBar()
+   {
+     if(historyList.size()>0)
+      {
+        undoMenuItem.setEnabled(true);
+        HistoryItem hi = (HistoryItem)historyList.peek();
+        undoMenuItem.setText("Undo "+hi.getDescription());
+      }
+     else
+     {
+       undoMenuItem.setEnabled(false);
+       undoMenuItem.setText("Undo");
+     }
+
+     if(redoList.size()>0)
+      {
+        redoMenuItem.setEnabled(true);
+        HistoryItem hi = (HistoryItem)redoList.peek();
+        redoMenuItem.setText("Redo "+hi.getDescription());
+      }
+     else
+     {
+       redoMenuItem.setEnabled(false);
+       redoMenuItem.setText("Redo");
+     }
+   }
+
+   public void addHistoryItem(HistoryItem hi)
+   {
+     historyList.push(hi);
+     updateEditMenuBar();
+   }
+
+   protected void undoMenuItem_actionPerformed(ActionEvent e)
+   {
+       HistoryItem hi = (HistoryItem)historyList.pop();
+       redoList.push(new HistoryItem(hi.getDescription(), viewport.alignment, HistoryItem.HIDE));
+       restoreHistoryItem(hi);
+   }
+
+
+   protected void redoMenuItem_actionPerformed(ActionEvent e)
+   {
+      HistoryItem hi = (HistoryItem)redoList.pop();
+      restoreHistoryItem(hi);
+      updateEditMenuBar();
+      viewport.updateConsensus();
+      alignPanel.repaint();
+      alignPanel.repaint();
+   }
+
+
+   // used by undo and redo
+   void restoreHistoryItem(HistoryItem hi)
+   {
+      if(hi.getType()== HistoryItem.SORT)
+      {
+           for(int i=0; i<hi.getSequences().size(); i++)
+             viewport.alignment.getSequences().setElementAt(hi.getSequences().elementAt(i), i);
+      }
+      else
+      {
+        for (int i = 0; i < hi.getSequences().size(); i++)
+        {
+          SequenceI restore = (SequenceI) hi.getSequences().elementAt(i);
+          if(restore.getLength()==0)
+          {
+            restore.setSequence(hi.getHidden().elementAt(i).toString());
+            viewport.alignment.getSequences().insertElementAt(
+               restore,
+               hi.getAlignIndex(i));
+          }
+          else
+            restore.setSequence(hi.getHidden().elementAt(i).toString());
+        }
+        if(hi.getType()==HistoryItem.PASTE)
+        {
+          for(int i=viewport.alignment.getHeight()-1;i>hi.getSequences().size()-1; i--)
+            viewport.alignment.deleteSequence(i);
+        }
+      }
+      updateEditMenuBar();
+
+      viewport.updateConsensus();
+      viewport.updateConservation();
+      alignPanel.repaint();
+      viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());
+  }
+
+  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.sequences.contains(seq))
+          continue;
+
+        SequenceI temp = viewport.alignment.getSequenceAt(i - 1);
+        if (sg.sequences.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.sequences.contains(seq))
+          continue;
+
+        SequenceI temp = viewport.alignment.getSequenceAt(i + 1);
+        if (sg.sequences.contains(temp))
+          continue;
+
+        viewport.alignment.getSequences().setElementAt(temp, i);
+        viewport.alignment.getSequences().setElementAt(seq, i + 1);
+      }
+    }
+
+    alignPanel.repaint();
+  }
+
+
+
+  protected void copy_actionPerformed(ActionEvent e)
+  {
+     if(viewport.getSelectionGroup()==null)
+       return;
+
+     SequenceGroup sg = viewport.getSelectionGroup();
+
+     Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
+     StringBuffer buffer= new StringBuffer();
+
+     Hashtable orderedSeqs = new Hashtable();
+     for(int i=0; i<sg.getSize(); i++)
+     {
+        SequenceI seq = sg.getSequenceAt(i);
+        int index = viewport.alignment.findIndex(seq);
+        orderedSeqs.put(index+"", seq);
+     }
+
+     int index=0;
+     for(int i=0; i<sg.getSize(); i++)
+     {
+       SequenceI seq = null;
+       while( seq == null )
+       {
+         if(orderedSeqs.containsKey(index+""))
+         {
+           seq = (SequenceI) orderedSeqs.get(index + "");
+           index++;
+           break;
+         }
+         else
+           index++;
+       }
+
+         buffer.append( seq.getName()+"\t"+seq.findPosition( sg.getStartRes() ) +"\t"
+                        +seq.findPosition( sg.getEndRes() )+ "\t"
+                        +sg.getSequenceAt(i).getSequence(sg.getStartRes(), sg.getEndRes()+1)+"\n");
+     }
+     c.setContents( new StringSelection( buffer.toString()) , null ) ;
+
+  }
+
+
+  protected void pasteNew_actionPerformed(ActionEvent e)
+  {
+    paste(true);
+  }
+
+  protected void pasteThis_actionPerformed(ActionEvent e)
+  {
+    addHistoryItem(new HistoryItem("Paste Sequences", viewport.alignment, HistoryItem.PASTE));
+    paste(false);
+  }
+
+  void paste(boolean newAlignment)
+  {
+    try{
+      Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
+      Transferable contents = c.getContents(this);
+      if (contents == null)
+        return;
+
+      String str = (String) contents.getTransferData(DataFlavor.stringFlavor);
+      StringTokenizer st = new StringTokenizer(str);
+      ArrayList seqs = new ArrayList();
+      while (st.hasMoreElements())
+      {
+        String name = st.nextToken();
+        int start = Integer.parseInt(st.nextToken());
+        int end = Integer.parseInt(st.nextToken());
+        Sequence sequence = new Sequence(name,st.nextToken(), start, end);
+
+        if(!newAlignment)
+          viewport.alignment.addSequence(sequence);
+        else
+          seqs.add(sequence);
+      }
+
+      if(newAlignment)
+      {
+        SequenceI[] newSeqs = new SequenceI[seqs.size()];
+        seqs.toArray(newSeqs);
+        AlignFrame af = new AlignFrame(new Alignment(newSeqs));
+        String newtitle = new String("Copied sequences");
+        if( title.startsWith("Copied sequences"))
+         newtitle = title;
+       else
+         newtitle = newtitle.concat("- from "+title);
+
+        Desktop.addInternalFrame(af, newtitle, NEW_WINDOW_WIDTH, NEW_WINDOW_HEIGHT);
+      }
+      else
+      {
+        viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());
+        viewport.setEndSeq(viewport.alignment.getHeight());
+        viewport.alignment.getWidth();
+        viewport.updateConservation();
+        viewport.updateConsensus();
+        alignPanel.repaint();
+      }
+
+    }catch(Exception ex){}// could be anything being pasted in here
+
+  }
+
+
+  protected void cut_actionPerformed(ActionEvent e)
+  {
+    copy_actionPerformed(null);
+    delete_actionPerformed(null);
+  }
+
+  protected void delete_actionPerformed(ActionEvent e)
+  {
+    boolean seqsdeleted=false;
+
+    if (viewport.getSelectionGroup() == null)
+      return;
+
+    addHistoryItem(new HistoryItem("Delete Sequences", viewport.alignment, HistoryItem.HIDE));
+
+     SequenceGroup sg = viewport.getSelectionGroup();
+     for (int i=0;i < sg.sequences.size(); i++)
+     {
+       SequenceI seq = sg.getSequenceAt(i);
+       int index = viewport.getAlignment().findIndex(seq);
+       seq.deleteChars(sg.getStartRes(),sg.getEndRes()+1);
+
+       if(seq.getSequence().length()<1) {
+         seqsdeleted=true;
+         viewport.getAlignment().deleteSequence(seq);
+        } else {
+         viewport.getAlignment().getSequences().setElementAt(seq, index);
+       }
+     }
+
+     viewport.setSelectionGroup(null);
+     viewport.alignment.deleteGroup(sg);
+     if (seqsdeleted)
+       viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());
+     viewport.resetSeqLimits( alignPanel.seqPanel.seqCanvas.getHeight());
+     if(viewport.getAlignment().getHeight()<1)
+     try
+     {
+       this.setClosed(true);
+     }catch(Exception ex){}
+   viewport.updateConservation();
+   viewport.updateConsensus();
+   alignPanel.repaint();
+ }
+
+
+  protected void deleteGroups_actionPerformed(ActionEvent e)
+  {
+    viewport.alignment.deleteAllGroups();
+    viewport.setSelectionGroup(null);
+    alignPanel.repaint();
+  }
+
+
+
+  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));
+    sg.setEndRes(viewport.alignment.getWidth());
+    viewport.setSelectionGroup(sg);
+    PaintRefresher.Refresh(null);
+  }
+
+  public void deselectAllSequenceMenuItem_actionPerformed(ActionEvent e)
+  {
+    viewport.setSelectionGroup(null);
+    viewport.getColumnSelection().clear();
+    viewport.setSelectionGroup(null);
+    PaintRefresher.Refresh(null);
+  }
+
+  public void invertSequenceMenuItem_actionPerformed(ActionEvent e)
+  {
+    SequenceGroup sg = viewport.getSelectionGroup();
+    for (int i=0; i<viewport.getAlignment().getSequences().size(); i++)
+      sg.addOrRemove (viewport.getAlignment().getSequenceAt(i));
+
+    PaintRefresher.Refresh(null);
+  }
+
+  public void remove2LeftMenuItem_actionPerformed(ActionEvent e)
+  {
+    ColumnSelection colSel = viewport.getColumnSelection();
+    if (colSel.size() > 0)
+    {
+      addHistoryItem(new HistoryItem("Remove Left",viewport.alignment,
+                                     HistoryItem.HIDE));
+      int min = colSel.getMin();
+      viewport.getAlignment().trimLeft(min);
+      colSel.compensateForEdit(0,min);
+
+      if(viewport.getSelectionGroup()!=null)
+        viewport.getSelectionGroup().adjustForRemoveLeft(min);
+
+      Vector groups = viewport.alignment.getGroups();
+      for(int i=0; i<groups.size(); i++)
+      {
+        SequenceGroup sg = (SequenceGroup) groups.get(i);
+        if(!sg.adjustForRemoveLeft(min))
+          viewport.alignment.deleteGroup(sg);
+      }
+
+      alignPanel.repaint();
+    }
+  }
+
+  public void remove2RightMenuItem_actionPerformed(ActionEvent e)
+  {
+    ColumnSelection colSel = viewport.getColumnSelection();
+    if (colSel.size() > 0)
+    {
+      addHistoryItem(new HistoryItem("Remove Right",viewport.alignment,
+                                     HistoryItem.HIDE));
+
+      int max = colSel.getMax();
+      viewport.getAlignment().trimRight(max);
+      if(viewport.getSelectionGroup()!=null)
+        viewport.getSelectionGroup().adjustForRemoveRight(max);
+
+      Vector groups = viewport.alignment.getGroups();
+      for(int i=0; i<groups.size(); i++)
+      {
+        SequenceGroup sg = (SequenceGroup) groups.get(i);
+        if(!sg.adjustForRemoveRight(max))
+          viewport.alignment.deleteGroup(sg);
+      }
+
+
+
+      alignPanel.repaint();
+    }
+
+  }
+
+  public void removeGappedColumnMenuItem_actionPerformed(ActionEvent e)
+  {
+    addHistoryItem(new HistoryItem("Remove Gapped Columns",
+                                   viewport.alignment,
+                                   HistoryItem.HIDE));
+
+    viewport.getAlignment().removeGaps();
+    viewport.updateConservation();
+    viewport.updateConsensus();
+    alignPanel.repaint();
+  }
+
+  public void removeAllGapsMenuItem_actionPerformed(ActionEvent e)
+  {
+    addHistoryItem(new HistoryItem("Remove Gaps",
+                                   viewport.alignment,
+                                   HistoryItem.HIDE));
+    SequenceI current;
+    int jSize;
+    for (int i=0; i < viewport.getAlignment().getSequences().size();i++)
+    {
+      current = viewport.getAlignment().getSequenceAt(i);
+      jSize = current.getLength();
+      for (int j=0; j < jSize; j++)
+        if(jalview.util.Comparison.isGap(current.getCharAt(j)))
+        {
+          current.deleteCharAt(j);
+          j--;
+          jSize--;
+        }
+    }
+    viewport.updateConservation();
+    viewport.updateConsensus();
+    alignPanel.repaint();
+  }
+
+
+  public void padGapsMenuitem_actionPerformed(ActionEvent e)
+    {
+      addHistoryItem(new HistoryItem("Pad Gaps",
+                                     viewport.alignment,
+                                     HistoryItem.HIDE));
+      SequenceI current;
+      int Width = viewport.getAlignment().getWidth()-1;
+      for (int i=0; i < viewport.getAlignment().getSequences().size();i++)
+      {
+        current = viewport.getAlignment().getSequenceAt(i);
+
+        if (current.getLength()<Width)
+          current.insertCharAt(Width, viewport.getGapCharacter());
+      }
+      viewport.updateConservation();
+      viewport.updateConsensus();
+      alignPanel.repaint();
+  }
+
+
+  public void findMenuItem_actionPerformed(ActionEvent e)
+  {
+    JInternalFrame frame = new JInternalFrame();
+    Finder finder = new Finder(viewport, alignPanel, frame);
+    frame.setContentPane(finder);
+    Desktop.addInternalFrame(frame, "Find", 340,110);
+    frame.setLayer(JLayeredPane.PALETTE_LAYER);
+
+  }
+
+
+  public void font_actionPerformed(ActionEvent e)
+  {
+    FontChooser fc = new FontChooser( alignPanel );
+  }
+
+  protected void fullSeqId_actionPerformed(ActionEvent e)
+  {
+    viewport.setShowFullId( fullSeqId.isSelected() );
+
+    alignPanel.idPanel.idCanvas.setPreferredSize( alignPanel.calculateIdWidth() );
+    alignPanel.repaint();
+  }
+
+  protected void colourTextMenuItem_actionPerformed(ActionEvent e)
+  {
+      viewport.setColourText( colourTextMenuItem.isSelected() );
+      alignPanel.repaint();
+  }
+
+  protected void wrapMenuItem_actionPerformed(ActionEvent e)
+  {
+    viewport.setWrapAlignment( wrapMenuItem.isSelected() );
+    alignPanel.setWrapAlignment( wrapMenuItem.isSelected() );
+    scaleAbove.setVisible( wrapMenuItem.isSelected() );
+    scaleLeft.setVisible( wrapMenuItem.isSelected() );
+    scaleRight.setVisible( wrapMenuItem.isSelected() );
+    alignPanel.repaint();
+  }
+
+  protected void scaleAbove_actionPerformed(ActionEvent e)
+  {
+    viewport.setScaleAboveWrapped(scaleAbove.isSelected());
+    alignPanel.repaint();
+  }
+
+  protected void scaleLeft_actionPerformed(ActionEvent e)
+  {
+    viewport.setScaleLeftWrapped(scaleLeft.isSelected());
+    alignPanel.repaint();
+  }
+
+  protected void scaleRight_actionPerformed(ActionEvent e)
+  {
+    viewport.setScaleRightWrapped(scaleRight.isSelected());
+    alignPanel.repaint();
+  }
+
+
+
+  public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
+  {
+    viewport.setShowBoxes( viewBoxesMenuItem.isSelected() );
+    alignPanel.repaint();
+  }
+
+  public void viewTextMenuItem_actionPerformed(ActionEvent e)
+  {
+    viewport.setShowText( viewTextMenuItem.isSelected() );
+    alignPanel.repaint();
+  }
+
+
+  protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
+  {
+    viewport.setRenderGaps(renderGapsMenuItem.isSelected());
+    alignPanel.repaint();
+  }
+
+  public void sequenceFeatures_actionPerformed(ActionEvent evt)
+  {
+    viewport.showSequenceFeatures(sequenceFeatures.isSelected());
+    if(viewport.showSequenceFeatures && !((Alignment)viewport.alignment).featuresAdded)
+    {
+         SequenceFeatureFetcher sft = new SequenceFeatureFetcher(viewport.alignment, alignPanel);
+         ((Alignment)viewport.alignment).featuresAdded = true;
+    }
+    alignPanel.repaint();
+  }
+
+  public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
+  {
+    if(annotationPanelMenuItem.isSelected() && viewport.getWrapAlignment())
+    {
+      annotationPanelMenuItem.setSelected(false);
+      return;
+    }
+    viewport.setShowAnnotation( annotationPanelMenuItem.isSelected() );
+    alignPanel.setAnnotationVisible( annotationPanelMenuItem.isSelected() );
+  }
+
+  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 );
+
+
+  }
+
+  protected void noColourmenuItem_actionPerformed(ActionEvent e)
+  {
+    changeColour( null );
+  }
+
+
+  public void clustalColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new ClustalxColourScheme(viewport.alignment.getSequences(), viewport.alignment.getWidth()));
+  }
+
+  public void zappoColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new ZappoColourScheme());
+  }
+
+  public void taylorColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new TaylorColourScheme());
+  }
+
+
+  public void hydrophobicityColour_actionPerformed(ActionEvent e)
+  {
+    changeColour( new HydrophobicColourScheme() );
+  }
+
+  public void helixColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new HelixColourScheme() );
+  }
+
+
+  public void strandColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new StrandColourScheme());
+  }
+
+
+  public void turnColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new TurnColourScheme());
+  }
+
+
+  public void buriedColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new BuriedColourScheme() );
+  }
+
+  public void nucleotideColour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new NucleotideColourScheme());
+  }
+
+
+  protected void applyToAllGroups_actionPerformed(ActionEvent e)
+  {
+    viewport.setColourAppliesToAllGroups(applyToAllGroups.isSelected());
+  }
+
+
+
+  void changeColour(ColourSchemeI cs)
+  {
+    int threshold = 0;
+
+    if ( viewport.getAbovePIDThreshold() )
+    {
+      threshold = SliderPanel.setPIDSliderSource(alignPanel, cs, "Background");
+
+      if (cs instanceof ResidueColourScheme)
+        ( (ResidueColourScheme) cs).setThreshold(threshold);
+      else if (cs instanceof ScoreColourScheme)
+        ( (ScoreColourScheme) cs).setThreshold(threshold);
+
+      viewport.setGlobalColourScheme(cs);
+    }
+    else if (cs instanceof ResidueColourScheme)
+      ( (ResidueColourScheme) cs).setThreshold(0);
+    else if (cs instanceof ScoreColourScheme)
+      ( (ScoreColourScheme) cs).setThreshold(0);
+
+
+
+    if (viewport.getConservationSelected())
+    {
+      ConservationColourScheme ccs = null;
+
+      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);
+
+      ccs = new ConservationColourScheme(c, cs);
+
+      // MUST NOTIFY THE COLOURSCHEME OF CONSENSUS!
+      ccs.setConsensus( viewport.vconsensus );
+      viewport.setGlobalColourScheme(ccs);
+
+      ccs.inc = SliderPanel.setConservationSlider(alignPanel, ccs, "Background");
+
+    }
+    else
+    {
+        // MUST NOTIFY THE COLOURSCHEME OF CONSENSUS!
+        if (cs != null)
+          cs.setConsensus(viewport.vconsensus);
+        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;
+        else if (cs instanceof ClustalxColourScheme)
+          sg.cs = new ClustalxColourScheme(sg.sequences, 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())
+        {
+          if (sg.cs instanceof ResidueColourScheme)
+            ( (ResidueColourScheme) sg.cs).setThreshold(threshold);
+          else if (sg.cs instanceof ScoreColourScheme)
+            ( (ScoreColourScheme) sg.cs).setThreshold(threshold);
+
+           sg.cs.setConsensus( AAFrequency.calculate(sg.sequences, 0, sg.getWidth()) );
+        }
+
+        if( viewport.getConservationSelected() )
+        {
+          Conservation c = new Conservation("Group",
+                                            ResidueProperties.propHash, 3,
+                                            sg.sequences, 0, viewport.alignment.getWidth()-1);
+          c.calculate();
+          c.verdict(false, viewport.ConsPercGaps);
+          ConservationColourScheme ccs = new ConservationColourScheme(c, sg.cs);
+
+          // MUST NOTIFY THE COLOURSCHEME OF CONSENSUS!
+          ccs.setConsensus( AAFrequency.calculate(sg.sequences, 0, sg.getWidth()));
+          sg.cs = ccs;
+        }
+        else if(cs!=null)
+        {
+          // MUST NOTIFY THE COLOURSCHEME OF CONSENSUS!
+          sg.cs.setConsensus(AAFrequency.calculate(sg.sequences, 0, sg.getWidth()));
+        }
+
+      }
+    }
+
+    if(alignPanel.getOverviewPanel()!=null)
+      alignPanel.getOverviewPanel().updateOverviewImage();
+    alignPanel.repaint();
+  }
+
+  protected void modifyPID_actionPerformed(ActionEvent e)
+  {
+      if(viewport.getAbovePIDThreshold())
+      {
+        SliderPanel.setPIDSliderSource(alignPanel, viewport.getGlobalColourScheme(),
+                                   "Background");
+        SliderPanel.showPIDSlider();
+      }
+  }
+
+  protected void modifyConservation_actionPerformed(ActionEvent e)
+  {
+    if(viewport.getConservationSelected())
+    {
+      SliderPanel.setConservationSlider(alignPanel, viewport.globalColourScheme,
+                                        "Background");
+      SliderPanel.showConservationSlider();
+    }
+  }
+
+
+  protected  void conservationMenuItem_actionPerformed(ActionEvent e)
+  {
+    viewport.setConservationSelected(conservationMenuItem.isSelected());
+
+    viewport.setAbovePIDThreshold(false);
+    abovePIDThreshold.setSelected(false);
+
+   ColourSchemeI cs = viewport.getGlobalColourScheme();
+   if(cs instanceof ConservationColourScheme )
+     changeColour( ((ConservationColourScheme)cs).cs );
+    else
+      changeColour( cs );
+
+    modifyConservation_actionPerformed(null);
+  }
+
+  public void abovePIDThreshold_actionPerformed(ActionEvent e)
+  {
+    viewport.setAbovePIDThreshold(abovePIDThreshold.isSelected());
+
+    conservationMenuItem.setSelected(false);
+    viewport.setConservationSelected(false);
+
+    ColourSchemeI cs = viewport.getGlobalColourScheme();
+
+    if(cs instanceof ConservationColourScheme )
+        changeColour( ((ConservationColourScheme)cs).cs );
+    else
+        changeColour( cs );
+
+    modifyPID_actionPerformed(null);
+  }
+
+
+
+  public void userDefinedColour_actionPerformed(ActionEvent e)
+  {
+    new UserDefinedColours( alignPanel, null);
+  }
+
+  public void PIDColour_actionPerformed(ActionEvent e)
+  {
+    changeColour( new PIDColourScheme() );
+  }
+
+
+  public void BLOSUM62Colour_actionPerformed(ActionEvent e)
+  {
+    changeColour(new Blosum62ColourScheme() );
+  }
+
+
+
+  public void sortPairwiseMenuItem_actionPerformed(ActionEvent e)
+  {
+    addHistoryItem(new HistoryItem("Pairwise Sort", viewport.alignment, HistoryItem.SORT));
+    AlignmentSorter.sortByPID(viewport.getAlignment(), viewport.getAlignment().getSequenceAt(0));
+    alignPanel.repaint();
+  }
+
+  public void sortIDMenuItem_actionPerformed(ActionEvent e)
+  {
+    addHistoryItem(new HistoryItem("ID Sort", viewport.alignment, HistoryItem.SORT));
+    AlignmentSorter.sortByID( viewport.getAlignment() );
+    alignPanel.repaint();
+  }
+
+  public void sortGroupMenuItem_actionPerformed(ActionEvent e)
+  {
+    addHistoryItem(new HistoryItem("Group Sort", viewport.alignment, HistoryItem.SORT));
+  //  AlignmentSorter.sortByGroup(viewport.getAlignment());
+    AlignmentSorter.sortGroups(viewport.getAlignment());
+    alignPanel.repaint();
+  }
+
+  public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
+  {
+    RedundancyPanel sp = new RedundancyPanel(alignPanel,this);
+    JInternalFrame frame = new JInternalFrame();
+    frame.setContentPane(sp);
+    Desktop.addInternalFrame(frame, "Redundancy threshold selection", 400, 100, false);
+
+  }
+
+  public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
+  {
+    if((viewport.getSelectionGroup()==null) ||
+       viewport.getSelectionGroup().getSize()<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);
+    }
+  }
+
+  public void PCAMenuItem_actionPerformed(ActionEvent e)
+  {
+
+    if( (viewport.getSelectionGroup()!=null && viewport.getSelectionGroup().getSize()<4 && viewport.getSelectionGroup().getSize()>0)
+       || viewport.getAlignment().getHeight()<4)
+    {
+      JOptionPane.showInternalMessageDialog(this, "Principal component analysis must take\n"
+                                    +"at least 4 input sequences.",
+                                    "Sequence selection insufficient",
+                                    JOptionPane.WARNING_MESSAGE);
+      return;
+    }
+
+    try{
+      PCAPanel pcaPanel = new PCAPanel(viewport, null);
+      JInternalFrame frame = new JInternalFrame();
+      frame.setContentPane(pcaPanel);
+      Desktop.addInternalFrame(frame, "Principal component analysis", 400, 400);
+   }catch(java.lang.OutOfMemoryError ex)
+   {
+     JOptionPane.showInternalMessageDialog(this, "Too many sequences selected\nfor Principal Component Analysis!!",
+                                   "Out of memory", JOptionPane.WARNING_MESSAGE);
+   }
+
+
+  }
+
+  public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)
+  {
+    NewTreePanel("AV", "PID", "Average distance tree using PID");
+  }
+
+  public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)
+  {
+    NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");
+  }
+
+
+  protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)
+  {
+    NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");
+  }
+
+  protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)
+  {
+    NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");
+  }
+
+  void NewTreePanel(String type, String pwType, String title)
+  {
+    String ltitle;
+    final TreePanel tp;
+    if (viewport.getSelectionGroup() != null &&
+        viewport.getSelectionGroup().getSize() > 3)
+    {
+      int s=0;
+      SequenceGroup sg = viewport.getSelectionGroup();
+
+      /* Decide if the selection is a column region */
+      while (s<sg.sequences.size()) {
+        if (((SequenceI) sg.sequences.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(viewport, viewport.getSelectionGroup().sequences, type,
+                         pwType,
+                         sg.getStartRes(), sg.getEndRes());
+    }
+    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;
+     }
+     tp = new TreePanel(viewport, viewport.getAlignment().getSequences(),
+                        type, pwType, 0, viewport.alignment.getWidth());
+   }
+
+   addTreeMenuItem(tp, title);
+   viewport.setCurrentTree(tp.getTree());
+
+   Desktop.addInternalFrame(tp, title+" from "+this.title, 600, 500);
+  }
+
+  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)
+      {
+        addHistoryItem(new HistoryItem("Sort", viewport.alignment,
+                                       HistoryItem.SORT));
+        // TODO: JBPNote - have to map order entries to curent SequenceI pointers
+        AlignmentSorter.sortBy(viewport.getAlignment(), order);
+        alignPanel.repaint();
+      }
+    });
+  }
+
+  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)
+      {
+        addHistoryItem(new HistoryItem("Tree Sort", viewport.alignment,
+                                       HistoryItem.SORT));
+        AlignmentSorter.sortByTree(viewport.getAlignment(), treePanel.getTree());
+        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);
+      };
+    });
+    viewport.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
+      public void propertyChange(PropertyChangeEvent evt)
+      {
+        if (evt.getPropertyName().equals("alignment")) {
+          treePanel.getTree().UpdatePlaceHolders( (Vector) evt.getNewValue());
+          treePanel.repaint();
+        }
+      }
+
+    }
+    );
+  }
+
+
+  public void clustalAlignMenuItem_actionPerformed(ActionEvent e)
+  {
+      // TODO:resolve which menu item was actually selected
+      // Now, check we have enough sequences
+        SequenceI[] msa=null;
+        if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup().getSize()>1)
+        {
+          // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!
+          SequenceGroup seqs = viewport.getSelectionGroup();
+          int sz;
+          msa = new SequenceI[sz=seqs.getSize()];
+          for (int i = 0; i < sz; i++)
+          {
+            msa[i] = (SequenceI) seqs.getSequenceAt(i);
+          }
+
+          }
+        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);
+            }
+
+          }
+
+        }
+        if (msa!=null) {
+          jalview.ws.MsaWSClient ct = new jalview.ws.MsaWSClient("ClustalWS", title, msa, false, true);
+        }
+  }
+  public void ClustalRealign_actionPerformed(ActionEvent e)
+  {
+      // TODO:resolve which menu item was actually selected
+      // Now, check we have enough sequences
+        SequenceI[] msa=null;
+        if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup().getSize()>1)
+        {
+          // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!
+          SequenceGroup seqs = viewport.getSelectionGroup();
+          int sz;
+          msa = new SequenceI[sz=seqs.getSize()];
+          for (int i = 0; i < sz; i++)
+          {
+            msa[i] = (SequenceI) seqs.getSequenceAt(i);
+          }
+
+          }
+        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);
+            }
+
+          }
+
+        }
+        if (msa!=null) {
+          jalview.ws.MsaWSClient ct = new jalview.ws.MsaWSClient("ClustalWS", title, msa, true, true);
+        }
+  }
+
+
+  protected void jpred_actionPerformed(ActionEvent e)
+{
+    SequenceI seq=null;
+    SequenceI[] msa=null;
+
+    if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup().getSize()>0)
+    {
+      // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!
+      SequenceGroup seqs = viewport.getSelectionGroup();
+      if (seqs.getSize() == 1 || !viewport.alignment.isAligned())
+      {
+        seq = (SequenceI)seqs.getSequenceAt(0);
+      }
+      else
+      {
+        int sz;
+        msa = new SequenceI[sz=seqs.getSize()];
+        for (int i = 0; i < sz; i++)
+        {
+          msa[i] = (SequenceI) seqs.getSequenceAt(i);
+        }
+      }
+    }
+    else
+    {
+      Vector seqs = viewport.getAlignment().getSequences();
+
+      if (seqs.size() == 1 || !viewport.alignment.isAligned())
+      {
+        seq = (SequenceI) seqs.elementAt(0);
+      }
+      else
+      {
+        msa = new SequenceI[seqs.size()];
+        for (int i = 0; i < seqs.size(); i++)
+        {
+          msa[i] = (SequenceI) seqs.elementAt(i);
+        }
+      }
+    }
+    if (msa!=null) {
+      JPredClient ct = new JPredClient(title, msa);
+    } else
+    if (seq!=null) {
+      JPredClient ct = new JPredClient(title, seq);
+    } else {
+      System.err.print("JALVIEW ERROR! - Unexpected JPred selection state!\n");
+    }
+  }
+  protected void msaAlignMenuItem_actionPerformed(ActionEvent e)
+  {
+    // TODO:resolve which menu item was actually selected
+    // Now, check we have enough sequences
+    SequenceI[] msa=null;
+    if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup().getSize()>1)
+      {
+        // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!
+        SequenceGroup seqs = viewport.getSelectionGroup();
+        int sz;
+        msa = new SequenceI[sz=seqs.getSize()];
+        for (int i = 0; i < sz; i++)
+        {
+          msa[i] = (SequenceI) seqs.getSequenceAt(i);
+        }
+
+
+      }
+      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);
+          }
+
+        }
+
+      }
+      if (msa!=null) {
+        MsaWSClient ct = new jalview.ws.MsaWSClient("MuscleWS",title, msa, false, true);
+      }
+  }
+    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");
+        ShowNewickTree(fin, choice);
+      }
+      catch (Exception ex)
+      {
+        JOptionPane.showMessageDialog(Desktop.desktop,
+                                      "Problem reading tree file",
+                                      ex.getMessage(),
+                                      JOptionPane.WARNING_MESSAGE);
+        ex.printStackTrace();
+      }
+    }
+  }
+
+  public void ShowNewickTree(NewickFile nf, String title)
+  {
+    try{
+      nf.parse();
+      if (nf.getTree() != null)
+      {
+        TreePanel tp = new TreePanel(viewport,
+                                     viewport.getAlignment().getSequences(),
+                                     nf, "FromFile", title);
+        Desktop.addInternalFrame(tp, title, 600, 500);
+        addTreeMenuItem(tp, title);
+        viewport.setCurrentTree(tp.getTree());
+      }
+     }catch(Exception ex){ex.printStackTrace();}
+  }
+
+}