diff --git a/uk/ac/sanger/artemis/editor/Annotation.java b/uk/ac/sanger/artemis/editor/Annotation.java
new file mode 100644
index 0000000000000000000000000000000000000000..6d7978d25583ac59b5c536dd10ab79cacf1fcf23
--- /dev/null
+++ b/uk/ac/sanger/artemis/editor/Annotation.java
@@ -0,0 +1,328 @@
+/* 
+ *
+ * created: Wed Aug 3 2004
+ *
+ * This file is part of Artemis
+ *
+ * Copyright(C) 2000  Genome Research Limited
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+package uk.ac.sanger.artemis.editor;
+
+import java.util.StringTokenizer;
+import javax.swing.event.*;
+import javax.swing.text.html.*;
+import javax.swing.text.DefaultStyledDocument;
+import javax.swing.text.StyledDocument;
+import javax.swing.text.Document;
+import javax.swing.*;
+import java.awt.BorderLayout;
+import java.awt.Font;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.io.IOException;
+import javax.swing.text.BadLocationException;
+import java.net.URL;
+
+public class Annotation extends JEditorPane
+                        implements HyperlinkListener
+{
+  private int startRange;
+  private int endRange;
+  /** busy cursor */
+  private Cursor cbusy = new Cursor(Cursor.WAIT_CURSOR);
+  /** done cursor */
+  private Cursor cdone = new Cursor(Cursor.DEFAULT_CURSOR);
+  /** desktop pane */
+  private JDesktopPane desktop = null;
+
+  public Annotation(JDesktopPane desktop)
+  {
+    super();
+
+    this.desktop = desktop;
+    setEditable(false);
+    setContentType("text/html");
+    Font font = new Font("Monospaced",Font.PLAIN,12);
+    setFont(font);
+    addHyperlinkListener(this);
+  }
+
+  
+  public Annotation(URL url) throws IOException
+  {
+    super(url);
+
+    setEditable(false);
+    addHyperlinkListener(this);
+  }
+
+
+  protected void setAnnotation(String text)
+  {
+    setText("<html><body>"+text+"</html></body>");
+    reportHTML();
+    startRange = getDocument().getLength();
+  }
+
+  protected void reportHTML()
+  {
+    try
+    {
+      String txt = ((HTMLDocument)getDocument()).getText(0,getDocument().getLength());
+      System.out.println("TXT:\n"+txt);
+      System.out.println("\nHTML:\n"+getText()+"\n\n");
+    }
+    catch(BadLocationException ble)
+    {
+      ble.printStackTrace();
+    }
+  }
+
+  protected void insert(String s, boolean ortholog)
+  {
+    s = getDatabaseHTML(s,"SWALL:");
+    s = getDatabaseHTML(s,"UNIPROT:");
+    s = getDatabaseHTML(s,"EMBL:");
+
+    int ind = s.indexOf("/gene");
+    
+    Document doc = getDocument();
+    int offset = doc.getLength();
+    if(ortholog)
+      offset = startRange;
+
+    insert(s,offset);
+    reportHTML();
+  }
+
+
+  protected void insert(String s, int offset)
+  {
+    try
+    {
+      HTMLEditorKit edKit = (HTMLEditorKit)getEditorKit();
+//    ((HTMLDocument)getDocument()).insertString(offset,"\n",null);
+      edKit.insertHTML((HTMLDocument)getDocument(),offset,"<BR>\n"+s,0,0,HTML.Tag.BR);
+//    HTMLEditorKit.InsertHTMLTextAction("similarity",s,HTML.Tag.BODY,HTML.Tag.P);
+    }
+    catch(BadLocationException ble)
+    {
+      ble.printStackTrace();
+    }
+    catch(Exception exp)
+    {
+      exp.printStackTrace();
+    }
+  }
+
+
+  private String getDatabaseHTML(String s, String db)
+  {
+    int ind = s.indexOf(db);
+    if(ind>-1)
+    {
+      String startStr = s.substring(0,ind);
+      int ind2 = s.indexOf(" ",ind);
+      int ind3 = s.indexOf(")",ind);     
+      if(ind3>-1 && ind3<ind2)
+        ind2 = ind3;
+      ind3 = s.indexOf(";",ind);
+      if(ind3>-1 && ind3<ind2)
+        ind2 = ind3;
+
+      String midStr = s.substring(ind,ind2);
+      String endStr = s.substring(ind2);
+
+      String srscmd = "http://srs.sanger.ac.uk/srsbin/cgi-bin/wgetz?-e+" +
+                      "["+midStr+"]";
+
+      s = startStr + "<a href=\""+srscmd+"\">" +
+          midStr   + "</a>" + endStr;
+    }
+    return s;
+  }
+
+  private void replaceRange(String newStr,int start,int end)
+  {
+    HTMLDocument doc = (HTMLDocument)getDocument();
+
+    try
+    {
+      doc.remove(start,(end-start));
+      insert(newStr,start);
+    }
+    catch(BadLocationException ble)
+    {
+      ble.printStackTrace();
+    }
+    setDocument(doc);
+  }
+
+  /**
+  *
+  * Deletes the annotation line that contains an ID.
+  *
+  */
+  protected void delete(String id, boolean ortholog)
+  {
+//  try
+//  {
+//    reportHTML();
+
+//    String txt = ((HTMLDocument)getDocument()).getText(0,getDocument().getLength());
+//    String line = null;
+//    int eol = 0;
+//    int len = 0;
+//    BufferedReader buffRead = new BufferedReader(new StringReader(txt));
+//    while((line = buffRead.readLine()) != null)
+//    {
+//      len = line.length()+1;
+//      if(line.indexOf("SWALL:"+id) > -1)
+//      {
+//        len += eol;
+//       
+//        if(ortholog)
+//        {
+//          line = buffRead.readLine();
+//          if(line != null && line.startsWith("/gene="))
+//            len += line.length();
+//        }
+
+//        if(len > txt.length())
+//          len = txt.length();
+
+//        replaceRange("",eol-1,len);
+//        reportHTML();
+//        return;
+//      }
+//      eol += len;
+//    }
+      String txt = getText();
+      int indID = txt.indexOf("SWALL:"+id);
+      if(indID == -1)
+        indID = txt.indexOf("UNIPROT:"+id);
+
+      int ind1 = 0;
+      int ind2 = 0;
+      
+      while((ind2 = txt.indexOf("<br>",ind1)) > -1)
+      {
+        if(ind2 < indID)
+          ind1 = ind2+1; 
+        else
+          break;
+      }
+      
+      ind2 = txt.indexOf("<br>",indID);
+
+      // if ortholog then delete gene line as well
+      if(ortholog)
+        ind2 = txt.indexOf("<br>",ind2+4);
+      
+      if(ind2 == -1)
+        ind2 = txt.length();
+
+      setText(txt.substring(0,ind1-1)+txt.substring(ind2));
+//  }
+//  catch(BadLocationException ble) { ble.printStackTrace(); }
+//  catch(IOException ioe) { ioe.printStackTrace(); }
+    
+  }
+
+
+  /**
+  *
+  * Method to handle hyper link events.
+  * @param event        hyper link event
+  *
+  */
+  public void hyperlinkUpdate(HyperlinkEvent event)
+  {
+    if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
+    {
+      setCursor(cbusy);
+      try
+      {
+        URL url = event.getURL();
+        
+        int ind1 = event.getDescription().indexOf("[");
+        int ind2 = event.getDescription().lastIndexOf("]");
+
+        String search = "";
+        if(ind1 > -1 && ind2 > -1)
+          search = event.getDescription().substring(ind1+1,ind2);
+        
+        if(desktop != null)
+        {
+          if(BigPane.srsTabPane.isSelected())
+          {
+            if(BigPane.srsFrame == null)
+              BigPane.setUpSRSFrame((2*desktop.getHeight())/3,desktop);
+            Annotation edPane = new Annotation(url);
+            JScrollPane jsp = new JScrollPane(edPane);
+            JTabbedPane jtab = (JTabbedPane)BigPane.srsFrame.getContentPane().getComponent(0);
+            jtab.insertTab(search, null,jsp,null,0);
+            BigPane.srsFrame.setVisible(true);
+          }
+
+          if(BigPane.srsWin.isSelected())
+          {
+            int hgt = (2*desktop.getHeight())/3;
+            Annotation edPane = new Annotation(url);
+            JScrollPane jsp = new JScrollPane(edPane);
+            JInternalFrame jif = new JInternalFrame("SRS "+search,
+                                                   true, //resizable
+                                                   true, //closable
+                                                   true, //maximizable
+                                                   true);//iconifiable);
+            JMenuBar menuBar = new JMenuBar();
+            menuBar.add(new CommonMenu(jif));
+            jif.setJMenuBar(menuBar);
+            jif.getContentPane().add(jsp);
+            jif.setLocation(0,0);
+            jif.setSize(800,hgt);
+            jif.setVisible(true);
+            desktop.add(jif);
+          }
+ 
+          if(BigPane.srsBrowser.isSelected())
+            BrowserControl.displayURL(event.getDescription());
+        }
+        else
+        {
+          setPage(url); 
+        }
+      }
+      catch(IOException ioe)
+      {
+        setCursor(cdone);
+        ioe.printStackTrace();
+//      ("Can't follow link to " +
+//                event.getURL().toExternalForm() );
+      }
+
+      setCursor(cdone);
+    }
+  }
+
+
+}
+
diff --git a/uk/ac/sanger/artemis/editor/BigPane.java b/uk/ac/sanger/artemis/editor/BigPane.java
new file mode 100644
index 0000000000000000000000000000000000000000..4928ae8949ae8dc56238920c2bfabbea82c5a6c0
--- /dev/null
+++ b/uk/ac/sanger/artemis/editor/BigPane.java
@@ -0,0 +1,199 @@
+/*
+ *
+ * created: Wed Aug 3 2004
+ *
+ * This file is part of Artemis
+ *
+ * Copyright(C) 2000  Genome Research Limited
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+package uk.ac.sanger.artemis.editor;
+
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.Dimension;
+import java.awt.Toolkit;
+import java.awt.Font;
+import java.util.Vector;
+
+import javax.swing.*;
+
+public class BigPane extends JFrame
+{
+
+  Font font = new Font("Monospaced",Font.PLAIN,12);
+  protected static JCheckBoxMenuItem srsBrowser;
+  protected static JCheckBoxMenuItem srsTabPane;
+  protected static JCheckBoxMenuItem srsWin;
+  protected static JInternalFrame srsFrame;
+
+  public BigPane(String dataFile[])
+  {
+    super();
+
+    setFont(font);
+    JDesktopPane desktop = new JDesktopPane();
+    desktop.setDragMode(JDesktopPane.LIVE_DRAG_MODE);
+    getContentPane().add(desktop);
+
+    //Make the big window be indented 100 pixels from each edge
+    //of the screen.
+    int inset = 100;
+    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+    setBounds(inset, inset,
+              screenSize.width  - inset*2,
+              screenSize.height - inset*2);
+
+    addWindowListener(new winExit());
+
+    JMenuBar menuBar = createMenuBar(desktop);
+    setJMenuBar(menuBar);
+
+    // data set
+    int hgt = getHeight()-60;
+    int wid = (getWidth()/2)-400;
+    DataViewInternalFrame dataView = new DataViewInternalFrame(dataFile,desktop);
+    dataView.setLocation(wid,0);
+    dataView.setSize(800,hgt);
+    dataView.setVisible(true);
+    desktop.add(dataView);
+
+    setVisible(true);
+  }
+
+  private JMenuBar createMenuBar(final JDesktopPane desktop)
+  {
+    JMenuBar menuBar = new JMenuBar();
+    JMenu fileMenu = new JMenu("File");
+    menuBar.add(fileMenu);
+
+    JMenuItem exitMenu = new JMenuItem("Exit");
+    exitMenu.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        System.exit(0);
+      }
+    });
+        
+    fileMenu.add(exitMenu);
+
+   //srs menu items
+    JMenu optionMenu = new JMenu("Options");
+    menuBar.add(optionMenu);
+
+    JMenu srsMenu = new JMenu("Show SRS in");
+    optionMenu.add(srsMenu);
+    
+    srsBrowser = new JCheckBoxMenuItem("External Broser",false);
+    srsTabPane = new JCheckBoxMenuItem("Tabbed Pane",true);
+    srsWin     = new JCheckBoxMenuItem("New Window",false);
+
+    srsMenu.add(srsBrowser);
+    srsMenu.add(srsTabPane);
+    srsMenu.add(srsWin);
+
+   //drag mode
+    JMenu dragMenu = new JMenu("Drag Mode");
+    optionMenu.add(dragMenu);
+
+    JRadioButtonMenuItem liveDrag = new JRadioButtonMenuItem("Live",true);
+    liveDrag.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        desktop.setDragMode(JDesktopPane.LIVE_DRAG_MODE);
+      }
+    });
+
+    dragMenu.add(liveDrag);
+
+    JRadioButtonMenuItem outlineDrag = new JRadioButtonMenuItem("Outline",false);
+    outlineDrag.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
+      }
+    });
+    dragMenu.add(outlineDrag);
+    ButtonGroup buttGroup = new ButtonGroup();
+    buttGroup.add(liveDrag);
+    buttGroup.add(outlineDrag);
+      
+
+    return menuBar;
+  }
+
+  
+  protected static void setUpSRSFrame(int hgt, JDesktopPane desktop)
+  {
+    BigPane.srsFrame = new JInternalFrame("SRS",
+                                           true, //resizable
+                                           true, //closable
+                                           true, //maximizable
+                                           true);//iconifiable
+    BigPane.srsFrame.setLocation(0,0);
+    BigPane.srsFrame.setSize(500,hgt);
+    final JTabbedPane jtab = new JTabbedPane();
+    BigPane.srsFrame.getContentPane().add(jtab);
+
+    JMenuBar menuBar = new JMenuBar();
+    CommonMenu cmen = new CommonMenu(BigPane.srsFrame);
+    menuBar.add(cmen);
+    JMenuItem closeTabMenu = new JMenuItem("Close tab");
+    cmen.add(closeTabMenu);
+    closeTabMenu.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        int select = jtab.getSelectedIndex(); 
+        jtab.removeTabAt(select);
+      }
+    });
+
+    BigPane.srsFrame.setJMenuBar(menuBar);
+    desktop.add(BigPane.srsFrame);
+  }
+
+  /**
+  *
+  * Extends WindowAdapter to close window.
+  *
+  */
+  class winExit extends WindowAdapter
+  {
+     public void windowClosing(WindowEvent we)
+     {
+       System.exit(0); 
+     }
+  }
+
+
+  public static void main(String args[])
+  {
+    if(args.length < 1)
+    {
+      System.out.println("Usage:: java BigPane data_file");
+      System.exit(0);
+    }
+    new BigPane(args);
+  }
+}
diff --git a/uk/ac/sanger/artemis/editor/BrowserControl.java b/uk/ac/sanger/artemis/editor/BrowserControl.java
new file mode 100644
index 0000000000000000000000000000000000000000..7bdaf78a816e1fb5481676dfdd37aae3c82e5fe6
--- /dev/null
+++ b/uk/ac/sanger/artemis/editor/BrowserControl.java
@@ -0,0 +1,127 @@
+/*
+ *
+ * created: Wed Aug 3 2004
+ *
+ * This file is part of Artemis
+ *
+ * Copyright(C) 2000  Genome Research Limited
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *
+ * A simple, static class to display a URL in the system browser.
+ *
+ * Under Unix, the system browser is hard-coded to be 'netscape'.
+ * Netscape must be in your PATH for this to work.  
+ *
+ * Under Windows, this will bring up the default browser under windows,
+ * usually either Netscape or Microsoft IE.  The default browser is
+ * determined by the OS.  
+ *
+ * Taken from: http://www.javaworld.com/javaworld/javatips/jw-javatip66_p.html
+ *
+ */
+
+package uk.ac.sanger.artemis.editor;
+
+import java.io.IOException;
+
+public class BrowserControl
+{
+
+  // The default system browser under windows.
+  private static final String WIN_PATH = "rundll32";
+  // The flag to display a url.
+  private static final String WIN_FLAG = "url.dll,FileProtocolHandler";
+  // The default browser under unix.
+  private static final String UNIX_PATH = "netscape";
+  // The flag to display a url.
+  private static final String UNIX_FLAG = "-remote openURL";
+
+  /**
+   * Display a file in the system browser.  If you want to display a
+   * file, you must include the absolute path name.
+   *
+   * @param url the file's url (the url must start with either "http://"
+   *        or "file://").
+   */
+  public static void displayURL(String url)
+  {
+    boolean windows = isWindowsPlatform();
+    String cmd = null;
+    try
+    {
+      if(windows)
+      {
+        // cmd = 'rundll32 url.dll,FileProtocolHandler http://...'
+        cmd = WIN_PATH + " " + WIN_FLAG + " " + url;
+        Process p = Runtime.getRuntime().exec(cmd);
+      }
+      else
+      {
+        // Netscape has to be running for the "-remote" command to work
+        cmd = UNIX_PATH + " " + UNIX_FLAG + "(" + url + ")";
+        Process p = Runtime.getRuntime().exec(cmd);
+        try
+        {
+          // wait for exit code -- if it's 0, command worked,
+          // otherwise we need to start the browser up.
+          int exitCode = p.waitFor();
+          if(exitCode != 0)
+          {
+            // Command failed, start up the browser
+            cmd = UNIX_PATH + " "  + url;
+            p = Runtime.getRuntime().exec(cmd);
+          }
+        }
+        catch(InterruptedException x)
+        {
+          System.err.println("Error bringing up browser, cmd='" +
+                             cmd + "'");
+          System.err.println("Caught: " + x);
+        }
+      }
+    }
+    catch(IOException x)
+    {
+      // couldn't exec browser
+      System.err.println("Could not invoke browser, command=" + cmd);
+      System.err.println("Caught: " + x);
+    }
+  }
+
+  /**
+   * Try to determine whether this application is running under Windows
+   * or some other platform by examing the "os.name" property.
+   *
+   * @return true if this application is running under a Windows OS
+   */
+  public static boolean isWindowsPlatform()
+  {
+    String os = System.getProperty("os.name");
+    if ( os != null && os.startsWith("Windows"))
+      return true;
+    else
+      return false;
+
+  }
+  /**
+   * Simple example.
+   */
+  public static void main(String[] args)
+  {
+    displayURL("http://www.sanger.ac.uk");
+  }
+}
diff --git a/uk/ac/sanger/artemis/editor/CommonMenu.java b/uk/ac/sanger/artemis/editor/CommonMenu.java
new file mode 100644
index 0000000000000000000000000000000000000000..00be52c04e91b497351777ea778d33bffd5ab672
--- /dev/null
+++ b/uk/ac/sanger/artemis/editor/CommonMenu.java
@@ -0,0 +1,57 @@
+/*
+ *
+ * created: Wed Aug 3 2004
+ *
+ * This file is part of Artemis
+ *
+ * Copyright(C) 2000  Genome Research Limited
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+package uk.ac.sanger.artemis.editor;
+
+import javax.swing.*;
+import java.awt.event.*;
+
+public class CommonMenu extends JMenu
+{
+
+  public CommonMenu(final JInternalFrame f)
+  {
+    super("File");
+     
+    JMenuItem closeMenu = new JMenuItem("Close");
+    closeMenu.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        f.setVisible(false);
+        try
+        {
+          JTabbedPane jtab = (JTabbedPane)f.getContentPane().getComponent(0);
+          jtab.removeAll();
+        }
+        catch(ClassCastException cce)
+        {
+          f.dispose();
+        }
+      }
+    });
+    add(closeMenu);
+  }
+
+}
diff --git a/uk/ac/sanger/artemis/editor/DataCollectionPane.java b/uk/ac/sanger/artemis/editor/DataCollectionPane.java
new file mode 100644
index 0000000000000000000000000000000000000000..f91b942c192b56b5ff2c044b1040ea931165b971
--- /dev/null
+++ b/uk/ac/sanger/artemis/editor/DataCollectionPane.java
@@ -0,0 +1,452 @@
+/*
+ *
+ * created: Wed Aug 3 2004
+ *
+ * This file is part of Artemis
+ *
+ * Copyright(C) 2000  Genome Research Limited
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+package uk.ac.sanger.artemis.editor;
+
+import javax.swing.*;
+import java.util.StringTokenizer;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+
+import java.awt.BorderLayout;
+import java.awt.Font;
+import java.awt.Dimension;
+import java.awt.Color;
+import java.awt.Insets;
+import java.net.URL;
+
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+public class DataCollectionPane extends JScrollPane
+{
+
+  public DataCollectionPane(Vector hitInfoCollection, String dataFile,
+                            final FastaTextPane fastaTextPane,
+                            final Annotation ann, final JDesktopPane desktop)
+  {
+    super();
+
+    Font font = new Font("Monospaced",Font.PLAIN,12);
+
+    Box bdown = Box.createVerticalBox();
+    ScrollPanel scrollPanel = new ScrollPanel();
+    scrollPanel.add(bdown);
+
+    Hashtable goHash = new Hashtable();
+    Enumeration hitEnum = hitInfoCollection.elements();
+    while(hitEnum.hasMoreElements())
+    {
+      HitInfo hit = (HitInfo)hitEnum.nextElement();
+      Vector gov = hit.getGO();
+      if(gov != null)
+      {
+        Enumeration gov_enum = gov.elements();
+        while(gov_enum.hasMoreElements())
+        {
+          String id = ((String)gov_enum.nextElement()).trim();
+          goHash.put(id,"");
+        }
+      }
+    }
+
+    getGoHash("/nfs/disk222/yeastpub/analysis/pathogen/GO/go.flat",goHash);
+
+    final Vector orthoCheckBox = new Vector();
+    hitEnum = hitInfoCollection.elements();
+
+    while(hitEnum.hasMoreElements())
+    {
+      Box bacross = Box.createHorizontalBox();
+      final HitInfo hit = (HitInfo)hitEnum.nextElement();
+
+// ortholog / paralog
+      final JCheckBox orthoBox = new JCheckBox("ORTH");
+      final JCheckBox paraBox  = new JCheckBox("PARA");
+
+      orthoBox.setMargin(new Insets(2,1,1,1));
+      paraBox.setMargin(new Insets(2,1,1,1));
+  
+      orthoBox.setActionCommand(hit.getID());
+      orthoCheckBox.add(orthoBox);
+
+      bacross.add(orthoBox);
+      orthoBox.setFont(font);
+      orthoBox.addActionListener(new ActionListener()
+      {
+        public void actionPerformed(ActionEvent e)
+        {
+          Enumeration checkEnum = orthoCheckBox.elements();
+          while(checkEnum.hasMoreElements())
+          {
+            JCheckBox cb = (JCheckBox)checkEnum.nextElement();
+            if( cb.isSelected() &&
+               !cb.getActionCommand().equals(orthoBox.getActionCommand()))
+            {
+              cb.setSelected(false);
+              ann.delete(cb.getActionCommand(),true);
+            }
+          }
+
+          if(orthoBox.isSelected())
+          {
+            if(paraBox.isSelected())
+            {
+              paraBox.setSelected(false);
+              ann.delete(hit.getID(),false);
+            }
+
+            setAnnotation(hit,ann,fastaTextPane.getFormat(),true);
+          }
+          else
+            ann.delete(hit.getID(),true);           
+        }
+      });
+
+      bacross.add(paraBox);
+      paraBox.setFont(font);
+      paraBox.addActionListener(new ActionListener()
+      {
+        public void actionPerformed(ActionEvent e)
+        {
+          if(paraBox.isSelected())
+          {
+            if(orthoBox.isSelected())
+            {
+              orthoBox.setSelected(false);
+              ann.delete(hit.getID(),true);
+            }
+           
+            setAnnotation(hit,ann,fastaTextPane.getFormat(),false);
+          }
+          else
+            ann.delete(hit.getID(),false);
+        }
+      });
+
+
+// heading
+      JLabel hiLabel = new JLabel(hit.getHeader());
+      hiLabel.setFont(font);
+      hiLabel.setForeground(Color.RED);
+
+// align button
+      final JButton selectButt = new JButton("ALIGN");
+      selectButt.setMargin(new Insets(1,1,1,1));
+      selectButt.addActionListener(new ActionListener()
+      {
+        public void actionPerformed(ActionEvent e)
+        {
+          fastaTextPane.show(hit);
+        }
+      });
+      selectButt.setFont(font);
+
+// retrieve srs entry
+      JButton srsButt = new JButton("->SRS");
+      srsButt.setMargin(new Insets(1,1,1,1));
+
+      srsButt.addActionListener(new ActionListener()
+      {
+        public void actionPerformed(ActionEvent e)
+        {
+          String srscmd = "srs.sanger.ac.uk/srsbin/cgi-bin/wgetz?-e+";
+          if(hit.getID() != null)
+          {
+            String search = hit.getID();
+            srscmd = srscmd.concat("[{swall}-ID:"+search+"*]");
+            if(hit.getAcc() != null)
+              srscmd = srscmd.concat("|[{swall}-AccNumber:"+hit.getAcc()+"*]");  
+
+            if(BigPane.srsBrowser.isSelected())
+              BrowserControl.displayURL(srscmd);
+
+            try
+            {
+              URL url = new URL("http://"+srscmd);
+              if(BigPane.srsTabPane.isSelected())
+              {
+                if(BigPane.srsFrame == null)
+                {
+                  BigPane.setUpSRSFrame((2*desktop.getHeight())/3,desktop);
+//                int hgt = (2*desktop.getHeight())/3;
+//                BigPane.srsFrame = new JInternalFrame("SRS",
+//                                                   true, //resizable
+//                                                   true, //closable
+//                                                   true, //maximizable
+//                                                   true);//iconifiable
+//                JTabbedPane jtab = new JTabbedPane();
+//                BigPane.srsFrame.getContentPane().add(jtab);
+//                BigPane.srsFrame.setLocation(0,0);
+//                BigPane.srsFrame.setSize(800,hgt);
+  
+//                JMenuBar menuBar = new JMenuBar();
+//                menuBar.add(new CommonMenu(BigPane.srsFrame));
+//                BigPane.srsFrame.setJMenuBar(menuBar);
+
+//                desktop.add(BigPane.srsFrame);
+                }
+                Annotation edPane = new Annotation(url);
+                JScrollPane jsp = new JScrollPane(edPane);
+                JTabbedPane jtab = (JTabbedPane)BigPane.srsFrame.getContentPane().getComponent(0);
+                jtab.insertTab(search,null,jsp,null,0);
+                BigPane.srsFrame.setVisible(true);
+              }
+  
+              if(BigPane.srsWin.isSelected())
+              {
+                int hgt = (2*desktop.getHeight())/3;
+                Annotation edPane = new Annotation(url);
+                JScrollPane jsp = new JScrollPane(edPane);
+                JInternalFrame jif = new JInternalFrame("SRS "+search,
+                                                     true, //resizable
+                                                     true, //closable
+                                                     true, //maximizable
+                                                     true);//iconifiable);
+                JMenuBar menuBar = new JMenuBar();
+                menuBar.add(new CommonMenu(jif));
+                jif.setJMenuBar(menuBar);
+                jif.getContentPane().add(jsp);
+                jif.setLocation(0,0);
+                jif.setSize(800,hgt);
+                jif.setVisible(true);
+                desktop.add(jif);
+              }
+            }
+            catch(Exception exp)
+            {
+              exp.printStackTrace();  
+            }
+          } 
+          else
+            JOptionPane.showMessageDialog(DataCollectionPane.this, 
+                     "No ID to retrieve SRS entry!", "Missing ID",
+                                  JOptionPane.INFORMATION_MESSAGE); 
+        }
+      });
+      srsButt.setFont(font);
+
+      bacross.add(hiLabel);
+      bacross.add(selectButt);
+      bacross.add(srsButt);
+     
+      bacross.add(Box.createHorizontalGlue());
+      bdown.add(bacross);
+
+      Vector gov = hit.getGO();
+      if(gov != null)
+      {
+        Enumeration gov_enum = gov.elements();
+        while(gov_enum.hasMoreElements())
+        {
+          final String go_id = ((String)gov_enum.nextElement()).trim();
+          bacross = Box.createHorizontalBox();
+          JButton goButton = new JButton("GO:"+go_id);
+          goButton.setFont(font);
+          goButton.addActionListener(new ActionListener()
+          {
+            public void actionPerformed(ActionEvent e)
+            {
+              String go_cmd = "http://www.godatabase.org/cgi-bin/amigo/go.cgi?query=GO%3A"+go_id;
+              BrowserControl.displayURL(go_cmd);
+            }
+          });
+          bacross.add(Box.createHorizontalStrut(10));
+          bacross.add(goButton);
+          goButton.setMargin(new Insets(0,1,0,1));
+
+          JLabel goLabel = new JLabel((String)goHash.get(go_id));
+          goLabel.setFont(font);
+          bacross.add(goLabel);
+          bdown.add(bacross);
+          bacross.add(Box.createHorizontalGlue());
+        }
+      }
+    }
+
+    setViewportView(scrollPanel);
+    setPreferredSize(new Dimension(500,300));
+  }
+
+
+  protected static void getzCall(HitInfo hit, boolean ortholog)
+  {
+    String env[] = { "PATH=/usr/local/pubseq/bin/" };
+    if(hit.getOrganism() == null ||
+       hit.getDescription()== null)
+    {
+
+      String cmd[]   = { "getz", "-f", "org description",
+                         "[libs={swall}-acc:"+
+                          hit.getAcc()+"]|[libs={swall}-id:"+hit.getID()+"]" };
+      ExternalApplication app = new ExternalApplication(cmd,
+                                                  env,null);
+      String res = app.getProcessStdout();
+
+      int ind1 = res.indexOf("OS ");
+      int ind2 = res.indexOf("\n");
+
+      if(ind1 > -1)
+        hit.setOrganism(res.substring(ind1+3,ind2).trim());
+   
+      ind1 = res.indexOf("DE ");
+      if(ind1 > -1)
+        hit.setDescription(res.substring(ind1+3).trim());
+    }
+
+    if(hit.getEMBL() == null)
+    {
+      String cmd2[]   = { "getz", "-f", "id",
+                 "[libs={swall}-id:"+hit.getID()+"]>EMBL" };
+      ExternalApplication app = new ExternalApplication(cmd2,env,null);
+      String res = app.getProcessStdout();
+  
+      int ind1 = res.indexOf("ID ");
+      if(ind1 > -1)
+      {
+        StringTokenizer tok = new StringTokenizer(res);
+        tok.nextToken();
+        hit.setEMBL(tok.nextToken());
+      }
+    }
+
+    if(ortholog)
+    {
+      String geneName = hit.getGeneName();
+      if(geneName == null)
+      {
+        String cmd3[]   = { "getz", "-f", "gen",
+                       "[libs={swall}-acc:"+
+                        hit.getAcc()+"]|[libs={swall}-id:"+hit.getID()+"]" };
+        ExternalApplication app = new ExternalApplication(cmd3,
+                                                env,null);
+        geneName = app.getProcessStdout();
+      }
+
+      int ind1 = geneName.indexOf("GN ");
+      if(ind1 > -1)
+      {
+        geneName = geneName.substring(ind1+3).trim();
+        if(geneName.startsWith("Name="))
+        {
+          geneName = geneName.substring(5);
+          ind1 = geneName.indexOf(";");
+          if(ind1 > -1)
+            geneName = geneName.substring(0,ind1);
+        }
+
+        if(!geneName.toLowerCase().startsWith("orderedlocusnames="))
+          hit.setGeneName(geneName);
+      }
+    }
+  }
+
+  private void setAnnotation(HitInfo hit, Annotation ann,
+                             String resultFormat, boolean ortholog)
+  {
+    getzCall(hit,ortholog);
+
+// gene name for orthologs
+    String orthoText = "";
+    if(ortholog)
+    {
+      String geneName = hit.getGeneName();
+      if(hit.getGeneName() != null)
+        orthoText = "<br>\n/gene=\""+hit.getGeneName()+"\"";
+    }
+
+    StringBuffer buff = new StringBuffer();
+    
+    if(hit.getDB() != null)
+      buff.append(hit.getDB()+":"+hit.getID());
+    else
+      buff.append(" UNIPROT:"+hit.getID());
+
+    if(hit.getEMBL() != null)
+      buff.append(" (EMBL:"+hit.getEMBL()+")");
+    buff.append(";");
+
+    if(hit.getOrganism() != null)
+      buff.append(" "+hit.getOrganism()+";");
+    if(hit.getLength() != null)
+      buff.append(" length="  + hit.getLength()+";");
+    if(hit.getUngapped() != null)
+      buff.append("ungapped id=" + hit.getUngapped()+";");
+    if(hit.getEValue() != null)
+      buff.append(" E()="     + hit.getEValue()+";");
+    if(hit.getOverlap() != null)
+      buff.append(" "+hit.getOverlap()+";");
+    if(hit.getQueryRange() != null)
+      buff.append("query "   + hit.getQueryRange()+";");
+    if(hit.getSubjectRange() != null)
+      buff.append("subject " + hit.getSubjectRange());
+    buff.append("\"");
+
+    ann.insert("\n/similarity=\""+resultFormat+";"+
+               buff.toString()+orthoText, ortholog);
+
+//  ann.insert("\n/similarity=\""+resultFormat+"; SWALL:"+hit.getID()+
+//                   " (EMBL:"+hit.getEMBL()+"); "+
+//                   hit.getOrganism()+"; "+
+//                   hit.getDescription()+"; "+
+//                   "length="  + hit.getLength()+"; "+
+//                   "id="      + hit.getIdentity()+"; "+
+//                   "ungapped id=" + hit.getUngapped()+"; "+
+//                   "E()="     + hit.getEValue()+"; "+
+//                   hit.getOverlap()+"; "+
+//                   "query "   + hit.getQueryRange()+"; "+
+//                   "subject " + hit.getSubjectRange()+"\""+
+//                   orthoText, ortholog);
+  }
+
+  public void getGoHash(String filename, Hashtable goHash)
+  {
+    try
+    {
+      String line = null;
+      BufferedReader buffRead = new BufferedReader(new FileReader(filename));
+      while((line = buffRead.readLine()) != null)
+      {
+        StringTokenizer tok = new StringTokenizer(line,"\t");
+        String ID = tok.nextToken().substring(3);
+        String desc  = tok.nextToken();
+        
+        if(tok.hasMoreTokens())
+          desc = desc.concat("; "+tok.nextToken());
+        
+        if(goHash.containsKey(ID))
+          goHash.put(ID,desc);
+      }
+    }
+    catch(IOException ioe) { ioe.printStackTrace(); }
+  }
+
+
+}
+
diff --git a/uk/ac/sanger/artemis/editor/DataViewInternalFrame.java b/uk/ac/sanger/artemis/editor/DataViewInternalFrame.java
new file mode 100644
index 0000000000000000000000000000000000000000..90a8b5a85651f7afb3bf28a0e9fa25abb88fb78f
--- /dev/null
+++ b/uk/ac/sanger/artemis/editor/DataViewInternalFrame.java
@@ -0,0 +1,84 @@
+/*
+ *
+ * created: Wed Aug 3 2004
+ *
+ * This file is part of Artemis
+ *
+ * Copyright(C) 2000  Genome Research Limited
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+package uk.ac.sanger.artemis.editor;
+
+import javax.swing.*;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.util.Vector;
+
+public class DataViewInternalFrame extends JInternalFrame
+{
+  private JTabbedPane tabPane = new JTabbedPane();
+
+  public DataViewInternalFrame(String dataFile[],
+                               JDesktopPane desktop)
+  {
+    super("Document " + dataFile[0], 
+              true, //resizable
+              true, //closable
+              true, //maximizable
+              true);//iconifiable
+
+    Annotation ann   = new Annotation(desktop);
+    JPanel dataPanel = (JPanel)getContentPane();
+    dataPanel.setLayout(new BorderLayout());
+
+    StringBuffer annFormat = new StringBuffer();
+
+    for(int i=0; i<dataFile.length; i++)
+    {
+      // add fasta results internal frame
+      FastaTextPane fastaPane = new FastaTextPane(dataFile[i]);
+
+      annFormat.append("/"+fastaPane.getFormat()+"_file=\""+
+                                    dataFile[i]+"\"\n");
+      // add data pane
+      Vector hits = fastaPane.getHitCollection();
+      DataCollectionPane dataPane =
+         new DataCollectionPane(hits, dataFile[i], fastaPane, ann, desktop);
+
+      JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
+                                        fastaPane,dataPane);
+      split.setDividerLocation(150);
+
+      tabPane.add(fastaPane.getFormat(),split);
+    }
+  
+    // add annotator text pane
+    ann.setAnnotation(annFormat.toString().trim());
+    JScrollPane annotationScroll = new JScrollPane(ann);   
+    annotationScroll.setPreferredSize(new Dimension(500,300));
+
+    JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
+                                      annotationScroll,tabPane);
+    split.setDividerLocation(250);
+    dataPanel.add(split);
+     
+    setVisible(true);
+  }
+
+}
+
diff --git a/uk/ac/sanger/artemis/editor/ExternalApplication.java b/uk/ac/sanger/artemis/editor/ExternalApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..ce3ca9bfbcd28f8472b77fb435d66fd4cab13939
--- /dev/null
+++ b/uk/ac/sanger/artemis/editor/ExternalApplication.java
@@ -0,0 +1,313 @@
+/*
+ *
+ * created: Wed Aug 3 2004
+ *
+ * This file is part of Artemis
+ *
+ * Copyright(C) 2000  Genome Research Limited
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+package uk.ac.sanger.artemis.editor;
+
+import java.io.*;
+
+/**
+*
+* Used to run an external command and get the stdout
+* and stderr.
+*
+*/
+public class ExternalApplication
+{
+
+  /** running process */
+  private Process p;
+  /** standard out */
+  private StringBuffer stdout = new StringBuffer();
+  /** standard error */
+  private StringBuffer stderr = new StringBuffer();
+  /** running directory */
+  private File project;
+  /** process status */
+  private String status;
+  private StdoutHandler stdouth;
+  private StderrHandler stderrh;
+
+  /**
+  *
+  * @param cmd            command to run
+  * @param envp           environment
+  * @param project        running directory
+  *
+  */
+  public ExternalApplication(String[] cmd, 
+                       String[] envp, File project)
+  {
+    this.project = project;
+    status = "0";
+
+    Runtime cmdRun = Runtime.getRuntime();
+    try
+    {
+      p = cmdRun.exec(cmd,envp,project);
+
+      // 2 threads to read in stdout & stderr buffers 
+      // to prevent blocking
+      stdouth = new StdoutHandler(this);
+      stderrh = new StderrHandler(this);
+      stdouth.start();
+      stderrh.start();
+    }
+    catch(IOException ioe)
+    {
+      ioe.printStackTrace();
+      System.out.println("ExternalApplication Error executing: "+
+                          cmd);
+      status = "1";
+    }
+  }
+
+
+  /**
+  *
+  * Read in the process stderr.
+  *
+  */
+  private void readProcessStderr()
+  {
+
+    BufferedInputStream stderrStream = null;
+    BufferedReader stderrRead = null;
+    try
+    {
+      String line;
+      stderrStream =
+         new BufferedInputStream(p.getErrorStream());
+      stderrRead =
+         new BufferedReader(new InputStreamReader(stderrStream));
+      char c[] = new char[100];
+      int nc = 0;
+
+      while((nc = stderrRead.read(c,0,100)) != -1)
+        stderr = stderr.append(new String(c,0,nc));
+    }
+    catch (IOException io)
+    {
+      System.err.println("ExternalApplication: Error in "+
+                                "collecting standard out");
+    }
+    finally
+    {
+      try
+      {
+        if(stderrStream!=null)
+          stderrStream.close();
+      }
+      catch(IOException ioe)
+      {
+        System.err.println("ExternalApplication: Error closing stream");
+      }
+      try
+      {
+        if(stderrRead!=null)
+          stderrRead.close();
+      }
+      catch(IOException ioe)
+      {
+        System.err.println("ExternalApplication: Error closing reader");
+      }
+    }
+
+    return;
+  }
+
+  /**
+  *
+  * Read in the process stdout.
+  *
+  */
+  private void readProcessStdout()
+  {
+    
+    BufferedInputStream stdoutStream = null;
+    BufferedReader stdoutRead = null;
+    try
+    {
+      String line;
+      stdoutStream =
+         new BufferedInputStream(p.getInputStream());
+      stdoutRead =
+         new BufferedReader(new InputStreamReader(stdoutStream));
+ 
+      
+      char c[] = new char[100];
+      int nc = 0;
+      String chunk;
+
+      while((nc = stdoutRead.read(c,0,100)) != -1)
+      {
+        chunk  = new String(c,0,nc);
+        stdout = stdout.append(chunk);
+      }
+
+    }
+    catch (IOException io)
+    {
+      System.err.println("ExternalApplication: Error in "+ 
+                                "collecting standard out");
+    }
+    finally
+    {
+      try
+      {
+        if(stdoutStream!=null)
+          stdoutStream.close();
+      }
+      catch(IOException ioe)
+      {
+        System.err.println("ExternalApplication: Error closing stream");
+      } 
+      try
+      {
+        if(stdoutRead!=null)
+          stdoutRead.close();
+      }
+      catch(IOException ioe)
+      {
+        System.err.println("ExternalApplication: Error closing reader");
+      }
+    }
+ 
+    return;
+  }
+
+  /**
+  *
+  * Get the stdout for the process.
+  * @return standard out.
+  *
+  */
+  public String getProcessStdout()
+  {
+    try
+    {
+      // make sure we hang around for stdout
+      while(stdouth.isAlive())
+        Thread.currentThread().sleep(10);
+    }
+    catch(InterruptedException ie)
+    {
+      ie.printStackTrace();
+    }
+                                                                                
+    return new String(stdout.toString().trim());
+  }
+
+
+  /**
+  *
+  * Get the stderr for the process.
+  * @return standard error.
+  *
+  */
+  public String getProcessStderr()
+  {
+    try
+    {
+      // make sure we hang around for stderr
+      while(stderrh.isAlive())
+        Thread.currentThread().sleep(10);
+    }
+    catch(InterruptedException ie)
+    {
+      ie.printStackTrace();
+    }
+                                                                                
+    return new String(stderr.toString().trim());
+  }
+
+  /**
+  *
+  * Wait for the process to end
+  *
+  */
+  public int waitFor()
+  {
+    try
+    {
+      return p.waitFor();
+    }
+    catch(InterruptedException ie)
+    {
+      ie.printStackTrace();
+    }
+    return -1;
+  }
+
+  /**
+  *
+  * @return process
+  *
+  */
+  public Process getProcess()
+  {
+    return p;
+  }
+
+  /**
+  *
+  * @return status
+  *
+  */
+  public String getStatus()
+  {
+    return status;
+  }
+
+  class StdoutHandler extends Thread
+  {
+    ExternalApplication rea;
+
+    protected StdoutHandler(ExternalApplication rea)
+    {
+      this.rea = rea;
+    }
+
+    public void run()
+    {
+      rea.readProcessStdout();
+    }
+  }
+
+  class StderrHandler extends Thread
+  {
+    ExternalApplication rea;
+
+    protected StderrHandler(ExternalApplication rea)
+    {
+      this.rea = rea;
+    }
+
+    public void run()
+    {
+      rea.readProcessStderr();
+    }
+  }
+
+}
+
diff --git a/uk/ac/sanger/artemis/editor/FastaTextPane.java b/uk/ac/sanger/artemis/editor/FastaTextPane.java
new file mode 100644
index 0000000000000000000000000000000000000000..ef0e9a0d812185da32a0d7fb3712f46f4dee6643
--- /dev/null
+++ b/uk/ac/sanger/artemis/editor/FastaTextPane.java
@@ -0,0 +1,420 @@
+/*
+ *
+ * created: Wed Aug 3 2004
+ *
+ * This file is part of Artemis
+ *
+ * Copyright(C) 2000  Genome Research Limited
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+package uk.ac.sanger.artemis.editor;
+
+import java.awt.Point;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.JScrollPane;
+import java.awt.BorderLayout;
+import java.awt.Font;
+import java.awt.Dimension;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+
+import uk.ac.sanger.artemis.util.WorkingGZIPInputStream;
+
+public class FastaTextPane extends JScrollPane
+{
+  private JTextArea textArea;
+  private Vector hitInfoCollection = null;
+  private String format = null;
+
+  public FastaTextPane(String dataFile)
+  {
+    super();
+    //read fasta file
+
+    format = getResultsFormat(dataFile);
+    StringBuffer contents = null;
+
+    if(format.equals("fasta"))
+      contents = readFASTAFile(dataFile,format);
+    else if(format.equals("blastp"))
+      contents = readBLASTPFile(dataFile,format);
+
+    Font font = new Font("Monospaced",Font.PLAIN,12);
+
+    textArea = new JTextArea(contents.toString());
+    setTextAreaFont(font);
+    textArea.setEditable(false);
+
+    setViewportView(textArea);
+    setPreferredSize(new Dimension(500,300));
+  }
+
+  /**
+  *
+  * Get the format of the results (e.g. FASTA or BLASTP).
+  * @return format
+  *
+  */
+  protected String getFormat()
+  {
+    return format;
+  }
+
+  protected void setTextAreaFont(Font f)
+  {
+    textArea.setFont(f);
+  }
+  
+  protected InputStream getInputStream(String dataFile)
+            throws IOException
+  {
+    FileInputStream inStream = new FileInputStream(dataFile);
+    if(dataFile.endsWith(".gz"))
+      return new WorkingGZIPInputStream(inStream);
+    else
+      return inStream;
+  }
+
+  /**
+  *
+  * Get the format of the results in a file. FASTA and
+  * BLASTP are supported.
+  *
+  */
+  protected String getResultsFormat(String dataFile)
+  {
+    File fn = new File(dataFile);
+    InputStreamReader streamReader = null;
+    BufferedReader buffReader = null;
+    String line = null;
+    String format = null;
+
+    try
+    {
+      streamReader = new InputStreamReader(getInputStream(dataFile));
+      buffReader = new BufferedReader(streamReader);
+      while( (line = buffReader.readLine()) != null)
+      {
+        if(line.startsWith("BLASTP"))
+        {
+          format = "blastp";
+          break;
+        }
+        else if(line.indexOf("FASTA") > -1)
+        {
+          format = "fasta";
+          break;
+        }
+      }
+      streamReader.close();
+      buffReader.close();
+    }
+    catch (IOException ioe)
+    {
+      System.out.println("Cannot read file: " + dataFile);
+    }
+    
+    return format;
+  }
+
+
+  protected StringBuffer readBLASTPFile(String dataFile, String format)
+  {
+    File fn = new File(dataFile);
+    StringBuffer sbuff = new StringBuffer();
+
+    InputStreamReader streamReader = null;
+    BufferedReader buffReader = null;
+
+    hitInfoCollection = new Vector();
+    try
+    {
+      streamReader = new InputStreamReader(getInputStream(dataFile));
+      buffReader = new BufferedReader(streamReader);
+
+      String line = null;
+      int textPosition = 0;
+      int len     = 0;
+      HitInfo hit = null;
+      int ind1 = 0;
+
+      while( (line = buffReader.readLine()) != null)
+      {
+        len = line.length()+1;
+        sbuff.append(line+"\n");
+        if(line.startsWith("Sequences producing significant alignments:"))
+        {
+          buffReader.readLine();
+          while( !(line = buffReader.readLine()).equals("") )
+          {
+            textPosition += line.length()+1;
+            sbuff.append(line+"\n");
+  
+            hit = new HitInfo(line,format);
+            hitInfoCollection.add(hit);
+          }
+
+        }
+        else if(line.startsWith(">"))  // start of alignment
+        {
+          String currentID = line;
+
+          int ind = line.indexOf(" ");
+          if(ind > -1)
+            currentID = line.substring(1,ind);
+
+          int ind2 = currentID.indexOf(":");
+          if(ind2 > -1)
+          {
+            currentID = currentID.substring(ind2+1); 
+          }
+
+          if(hit != null)
+            hit.setEndPosition(textPosition);
+
+          hit = getHitInfo(currentID,hitInfoCollection);
+          hit.setStartPosition(textPosition);
+
+
+          String going = "";
+          ind = line.indexOf("GO:");
+          if(ind > -1)
+            going = line.substring(ind+3);
+          
+          String nextLine = null;
+          buffReader.mark(210);
+          while((nextLine = buffReader.readLine()).indexOf("Length") == -1)
+          {
+            if(going.equals("") && ((ind = nextLine.indexOf("GO:")) > -1))
+              going = nextLine.substring(ind+3);
+            else if(!going.equals(""))
+              going = going.concat(nextLine);
+          }
+
+          buffReader.reset();
+          if(!going.equals(""))
+            hit.setGO(going); 
+        }
+        else if( (ind1 = line.indexOf("Identities = ")) > -1)
+        {
+          ind1 = line.indexOf("(",ind1)+1;
+          if(ind1 > -1)
+            hit.setIdentity(line.substring(ind1,line.indexOf(")",ind1)).trim());
+        }
+        else if( (ind1 = line.indexOf("  Length = ")) > -1)
+          hit.setLength(line.substring(ind1+11));
+
+        textPosition += len;
+      }
+
+      if(hit != null)
+        hit.setEndPosition(textPosition);
+
+      streamReader.close();
+      buffReader.close();
+
+      GetzThread getz = new GetzThread(hitInfoCollection);
+      getz.start();
+    }
+    catch (IOException ioe)
+    {
+      System.out.println("Cannot read file: " + dataFile);
+    }
+    return sbuff;
+  }
+
+
+  protected StringBuffer readFASTAFile(String dataFile, String format)
+  {
+    File fn = new File(dataFile);
+    StringBuffer sbuff = new StringBuffer();
+
+    InputStreamReader streamReader = null;
+    BufferedReader buffReader = null;
+
+    hitInfoCollection = new Vector();
+    try
+    {
+      streamReader = new InputStreamReader(getInputStream(dataFile));
+      buffReader = new BufferedReader(streamReader);
+
+      String line = null;
+      int textPosition = 0;
+      int len    = 0;
+      HitInfo hi = null;
+
+      while( (line = buffReader.readLine()) != null)
+      {
+        len = line.length()+1;
+        sbuff.append(line+"\n");  
+
+        int ind1;
+
+        if(line.startsWith("The best scores are:"))
+        {
+          while( !(line = buffReader.readLine()).equals("") )
+          {
+            textPosition += line.length()+1;
+            sbuff.append(line+"\n");
+            hitInfoCollection.add(new HitInfo(line,format)); 
+          }
+        }
+        else if(line.startsWith(">>"))  // start of alignment
+        {
+          int ind = line.indexOf(" ");
+          String currentID = line.substring(2,ind);
+          
+          if(hi != null)
+            hi.setEndPosition(textPosition);
+
+          hi = getHitInfo(currentID,hitInfoCollection);
+          hi.setStartPosition(textPosition);
+        }
+        else if(line.startsWith("Smith-Waterman")) // Smith-Waterman
+        {
+          ind1 = line.indexOf("score:");
+          int ind2;
+          if(ind1 > -1)
+          {
+            ind2 = line.indexOf(";",ind1);
+            hi.setScore(line.substring(ind1+6,ind2));
+     
+            ind1 = ind2+1;
+            ind2 = line.indexOf("identity");
+            if(ind2 > -1)
+              hi.setIdentity(line.substring(ind1,ind2).trim());
+          
+            ind1 = line.indexOf("(",ind2);
+            if(ind1 > -1)
+            {
+              ind2 = line.indexOf("ungapped)",ind1);
+              hi.setUngapped(line.substring(ind1+1,ind2).trim());
+            }
+
+            ind1 = line.indexOf(" in ",ind2);
+            ind2 = line.indexOf("(",ind1);
+            if(ind1 > -1 && ind2 > -1)
+              hi.setOverlap(line.substring(ind1+4,ind2).trim());
+           
+            ind1 = ind2+1;
+            ind2 = line.indexOf(":",ind1);
+            if(ind2 > -1)
+              hi.setQueryRange(line.substring(ind1,ind2));
+
+            ind1 = ind2+1;
+            ind2 = line.indexOf(")",ind1);
+            if(ind2 > -1)
+              hi.setSubjectRange(line.substring(ind1,ind2)); 
+          }
+        }
+        else if( (ind1 = line.indexOf(" E():")) > -1)
+        {
+          StringTokenizer tok = new StringTokenizer(line.substring(ind1+5));
+          hi.setEValue(tok.nextToken().trim());
+        }
+ 
+        textPosition += len;
+      }
+  
+      if(hi != null)
+        hi.setEndPosition(textPosition);
+   
+      streamReader.close();
+      buffReader.close();
+
+      GetzThread getz = new GetzThread(hitInfoCollection);
+      getz.start();
+    }
+    catch (IOException ioe)
+    {
+      System.out.println("Cannot read file: " + dataFile);
+    }
+    return sbuff;
+  }
+
+  protected Vector getHitCollection()
+  {
+    return hitInfoCollection;
+  }
+
+  protected HitInfo getHitInfo(String ID, Vector hitInfoCollection)
+  {
+    Enumeration hitInfo = hitInfoCollection.elements();
+    
+    while(hitInfo.hasMoreElements())
+    {
+      HitInfo hi = (HitInfo)hitInfo.nextElement();
+      if(hi.getID().equals(ID))
+        return hi;
+    }
+
+    return null;
+  }
+
+  class GetzThread extends Thread
+  {
+    private Vector hitInfoCollection;
+
+    protected GetzThread(Vector hitInfoCollection)
+    {
+      this.hitInfoCollection = hitInfoCollection;
+    }
+
+    public void run()
+    {
+      int max = hitInfoCollection.size();
+      if(max > 10)
+        max = 10;
+
+      for(int i=0; i<max; i++)
+        DataCollectionPane.getzCall((HitInfo)hitInfoCollection.get(i),false);
+    }
+
+  }
+
+
+  public void show(Object obj)
+  {
+    if(obj instanceof HitInfo)
+    {
+      HitInfo hit = (HitInfo)obj;
+
+      int start = hit.getStartPosition();
+      int end   = hit.getEndPosition();
+//    textArea.moveCaretPosition(end);
+      textArea.moveCaretPosition(start);
+
+      Point pos  = getViewport().getViewPosition();
+      Dimension rect = getViewport().getViewSize();
+      double hgt = rect.getHeight()+pos.getY();
+      pos.setLocation(pos.getX(),hgt);
+      getViewport().setViewPosition(pos);
+    }
+  }
+ 
+
+}
+
diff --git a/uk/ac/sanger/artemis/editor/HitInfo.java b/uk/ac/sanger/artemis/editor/HitInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..f1c3959e168b8e3b5949ae5773d58f3624df455f
--- /dev/null
+++ b/uk/ac/sanger/artemis/editor/HitInfo.java
@@ -0,0 +1,547 @@
+/*
+ *
+ * created: Wed Aug 3 2004
+ *
+ * This file is part of Artemis
+ *
+ * Copyright(C) 2000  Genome Research Limited
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+package uk.ac.sanger.artemis.editor;
+
+import java.util.StringTokenizer;
+import java.util.NoSuchElementException;
+import java.util.Vector;
+
+/**
+*
+* Hit information is contained in this object.
+*
+*/
+public class HitInfo
+{
+  /** Hit in database */
+  private String db     = null;
+  /** Hit ID */
+  private String id     = null;
+  /** Hit accession number */
+  private String acc    = null;
+  /** Organism source */
+  private String org    = null;
+  /** Gene name */
+  private String geneName = null;
+  /** Description     */
+  private String desc   = null;
+  /** Sequence length */
+  private String length = null;
+  /** */
+  private String opt    = null;
+  private String zscore = null;
+  private String evalue = null;
+  private String header = null;
+  /** EMBL ID from linking to EMBL in SRS */
+  private String emblID = null;
+  private String score  = null;
+  /** percentage identity */
+  private String identity  = null;
+  /** ungapped identity   */
+  private String ungapped  = null;
+  /** amino acid overlap  */
+  private String aaOverlap = null;
+  /** query range in the alignment   */
+  private String queryRange   = null;
+  /** subject range in the alignment */
+  private String subjectRange = null;
+  /** start position of this hit in the results output */
+  private int startPosition = 0;
+  /** end position of this hit in the results output   */
+  private int endPosition   = 0;
+
+  /** collection of GO terms */
+  private Vector go;
+ 
+  public HitInfo(String header, String format)
+  {
+    header = header.trim();
+    this.header = header;
+    if(format.equals("fasta"))
+      setFastaHitInfo(header);
+    else if(format.equals("blastp"))
+      setBLASTPInfo(header);
+  }
+
+
+  /**
+  *
+  * Extract id, accession numbers etc. from the
+  * header of BLASTP results.
+  * @param header	results header line from BLASTP.
+  *
+  */
+  protected void setBLASTPInfo(String header)
+  {
+    int ind1 = header.indexOf(" ");
+    if(ind1 > -1)
+      id = header.substring(0,ind1);
+    else
+      return;
+
+    int ind1a = id.indexOf(":");
+    if(ind1a > -1)
+    {
+      db = id.substring(0,ind1a);
+      id = id.substring(ind1a+1);
+    }
+
+    int ind2 = header.indexOf(" ",ind1+1);
+    if(ind2 > -1)
+      acc = header.substring(ind1+1,ind2);
+    else
+      return;
+
+    ind1 = header.lastIndexOf(" ");
+    evalue = header.substring(ind1).trim();
+  
+    ind2  = header.substring(0,ind1).trim().lastIndexOf(" ");
+    if(ind2>-1)
+      score = header.substring(ind2,ind1).trim();
+  }
+
+  /**
+  *
+  * Extract id, accession numbers etc. from the
+  * header of FASTA results.
+  * @param header       results header line from FASTA.
+  *
+  */
+  protected void setFastaHitInfo(String header)
+  {
+    int ind1 = header.indexOf(" ");
+    if(ind1 > -1)
+      id = header.substring(0,ind1);
+    else
+      return;
+
+    int ind2 = header.indexOf(" ",ind1+1);
+    if(ind2 > -1)
+      acc = header.substring(ind1+1,ind2);
+    else
+      return;
+
+    ind1 = ind2;
+    ind2 = header.indexOf("(",ind1);
+    if(ind2 > -1)
+      org = header.substring(ind1,ind2).trim();
+    else
+      return;
+
+    ind1 = ind2+1;
+    ind2 = header.indexOf(")",ind1);
+    if(ind2 > -1)
+      length = header.substring(ind1,ind2).trim();
+    else
+      return;
+
+    StringTokenizer tok = new StringTokenizer(header.substring(ind2+1));
+    try
+    {
+      opt    = tok.nextToken();
+      zscore = tok.nextToken();
+      evalue = tok.nextToken();
+    }
+    catch(NoSuchElementException exp){}
+    
+  }
+
+  /**
+  *
+  * Set the start position of the alignment in the
+  * results.
+  * @param startPosition	start position.
+  *
+  */
+  protected void setStartPosition(int startPosition)
+  {
+    this.startPosition = startPosition;
+  }
+
+  /**
+  *
+  * Set the end position of the alignment in the
+  * results.
+  * @param endPosition		end position.
+  *
+  */
+  protected void setEndPosition(int endPosition)
+  {
+    this.endPosition = endPosition;
+  }
+
+  /**
+  *
+  * Set the sequence length.
+  * @param length	sequence length.
+  *
+  */
+  protected void setLength(String length)
+  {
+    this.length = length;
+  }
+
+  /**
+  *
+  * Get the sequence length.
+  * @return sequence length.
+  *
+  */
+  protected String getLength()
+  {
+    return length;
+  }
+
+  /**
+  *
+  * Get the results header.
+  * @return results header.
+  *
+  */
+  protected String getHeader()
+  {
+    return header; 
+  }
+
+  /**
+  *
+  * Get the alignment start position.
+  * @return start position.
+  *
+  */
+  protected int getStartPosition()
+  {
+   return startPosition;
+  }
+
+  /**
+  *
+  * Get the alignment end position.
+  * @return end position.
+  *
+  */
+  protected int getEndPosition()
+  {
+   return endPosition;
+  }
+
+  /**
+  *
+  * Get the database.
+  * @return database.
+  *
+  */
+  protected String getDB()
+  {
+    return db;
+  }
+
+
+  /**
+  *
+  * Get the sequence ID.
+  * @return sequence ID.
+  *
+  */
+  protected String getID()
+  {
+    return id;
+  }
+  
+  /**
+  *
+  * Get the sequence accession number.
+  * @return sequence accession number.
+  *
+  */
+  protected String getAcc()
+  {
+    return acc;
+  }
+
+  /**
+  *
+  * Get the organism source (OS).
+  * @return organism source.
+  *
+  */
+  protected String getOrganism()
+  {
+    return org;
+  }
+
+  /**
+  *
+  * Set the organism source (OS).
+  * @param org 	organism source.
+  *
+  */
+  protected void setOrganism(String org)
+  {
+    this.org = org;
+  }
+
+  /**
+  *
+  * Set the description (DE).
+  * @param desc	sequence description.
+  *
+  */
+  protected void setDescription(String desc)
+  {
+    this.desc = desc;
+  }
+
+  /**
+  *
+  * Get the description (DE).
+  * @return sequence description.
+  *
+  */
+  protected String getDescription()
+  {
+    return desc;
+  }
+
+  /**
+  *
+  * Set the EMBL linked entry (obtained from database 
+  * linking in SRS).
+  * @param emblID	EMBL ID.
+  *
+  */
+  protected void setEMBL(String emblID)
+  {
+    this.emblID = emblID;
+  }
+
+  /**
+  *
+  * Get the EMBL linked entry (obtained from database 
+  * linking in SRS).
+  * @return EMBL ID.
+  *
+  */
+  protected String getEMBL()
+  {
+    return emblID;
+  }
+
+  /**
+  *
+  * Set the sequence alignment score.
+  * @param score 	alignment score.
+  *
+  */
+  protected void setScore(String score)
+  {
+    this.score = score;
+  }
+
+  /**
+  *
+  * Get the sequence alignment score.
+  * @return alignment score.
+  *
+  */
+  protected String getScore()
+  {
+    return score;
+  }
+
+  /**
+  *
+  * Set the percentage identity found in the alignment.
+  * @param identity	percentage identity.
+  *
+  */
+  protected void setIdentity(String identity)
+  {
+    this.identity = identity;
+  }
+
+  /**
+  *
+  * Get the percentage identity found in the alignment.
+  * @return percentage identity.
+  *
+  */
+  protected String getIdentity()
+  {
+    return identity;
+  }
+
+  /**
+  *
+  * Set the percentage ungapped identity found in the alignment.
+  * @param ungapped     percentage ungapped identity.
+  *
+  */
+  protected void setUngapped(String ungapped)
+  {
+    this.ungapped = ungapped;
+  }
+
+  /**
+  *
+  * Get the percentage ungapped identity found in the alignment.
+  * @return percentage ungapped identity.
+  *
+  */
+  protected String getUngapped()
+  {
+    return ungapped;
+  }
+
+  /**
+  *
+  * Set the e-value for this hit.
+  * @param evalue  e-value.
+  *
+  */
+  protected void setEValue(String evalue)
+  {
+    this.evalue = evalue;
+  }
+
+  /**
+  *
+  * Get the e-value for this hit.
+  * @return e-value.
+  *
+  */
+  protected String getEValue()
+  {
+    return evalue;
+  }
+
+  /**
+  *
+  * Set the number of amino acids that overlap in this
+  * alignment.
+  * @param aaOverlap  number of aa-overlaps.
+  *
+  */
+  protected void setOverlap(String aaOverlap)
+  {
+    this.aaOverlap = aaOverlap;
+  }
+
+  /**
+  *
+  * Get the number of amino acids that overlap in this
+  * alignment.
+  * @return number of aa-overlaps.
+  *
+  */
+  protected String getOverlap()
+  {
+    return aaOverlap;
+  }
+
+  /**
+  *
+  * Set the query range in this alignment.
+  * @param queryRange 	query range.
+  *
+  */
+  protected void setQueryRange(String queryRange)
+  {
+    this.queryRange = queryRange;
+  }
+
+  /**
+  *
+  * Get the query range in this alignment.
+  * @return query range.
+  *
+  */
+  protected String getQueryRange()
+  {
+    return queryRange;
+  }
+
+  /**
+  *
+  * Set the subject range in this alignment.
+  * @param subjectRange   subject range.
+  *
+  */
+  protected void setSubjectRange(String subjectRange)
+  {
+    this.subjectRange = subjectRange;
+  }
+
+  /**
+  *
+  * Get the subject range in this alignment.
+  * @return subject range.
+  *
+  */
+  protected String getSubjectRange()
+  {
+    return subjectRange;
+  }
+
+  /**
+  *
+  * Set the gene name (for ortholog).
+  * @param geneName	gene name.
+  *
+  */
+  protected void setGeneName(String geneName)
+  {
+    this.geneName = geneName;
+  }
+
+  /**
+  *
+  * Get the gene name (for ortholog).
+  * @return gene name.
+  *
+  */
+  protected String getGeneName()
+  {
+    return geneName;
+  }
+
+  protected void setGO(String go_terms)
+  {
+    go_terms = go_terms.trim();
+    StringTokenizer tok = new StringTokenizer(go_terms);
+    while(tok.hasMoreElements())
+    {
+      if(go == null)
+        go = new Vector();
+      go.add(tok.nextToken());
+    }
+  }
+
+  protected Vector getGO()
+  {
+    return go;
+  }
+}
+
diff --git a/uk/ac/sanger/artemis/editor/ScrollPanel.java b/uk/ac/sanger/artemis/editor/ScrollPanel.java
new file mode 100644
index 0000000000000000000000000000000000000000..cb78b0e05d0766704e6bcf809dbe2c568e1bf2c6
--- /dev/null
+++ b/uk/ac/sanger/artemis/editor/ScrollPanel.java
@@ -0,0 +1,81 @@
+/*
+ *
+ * created: Wed Aug 3 2004
+ *
+ * This file is part of Artemis
+ *
+ * Copyright(C) 2000  Genome Research Limited
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+package uk.ac.sanger.artemis.editor;
+
+import javax.swing.*;
+import java.awt.LayoutManager;
+import java.awt.Rectangle;
+import java.awt.Dimension;
+import java.awt.Color;
+
+/**
+*
+* Extends JPanel to implement Scrollable to speed scroll pane
+* scrolling
+*
+*/
+public class ScrollPanel extends JPanel implements Scrollable
+{
+
+  public ScrollPanel()
+  {
+    super();
+  }
+
+  public ScrollPanel(LayoutManager l)
+  {
+    super(l);
+  }
+
+  public Dimension getPreferredScrollableViewportSize()
+  {
+    return getPreferredSize();
+  }
+
+  public boolean getScrollableTracksViewportHeight()
+  {
+    return false;
+  }
+
+  public boolean getScrollableTracksViewportWidth()
+  {
+    return false;
+  }
+
+  public int getScrollableBlockIncrement(Rectangle r,
+                    int orientation, int direction)
+  {
+    return 60;
+  }
+
+  public int getScrollableUnitIncrement(Rectangle r,
+                    int orientation, int direction)
+  {
+    return 10;
+  }
+
+
+}
+