updated to jalview 2.1 and begun ArchiveClient/VamsasClient/VamsasStore updates.
[jalview.git] / src / jalview / gui / FeatureSettings.java
index 7dae703..ffa01d5 100755 (executable)
-/*\r
- * Jalview - A Sequence Alignment Editor and Viewer\r
- * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
- *\r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License\r
- * as published by the Free Software Foundation; either version 2\r
- * of the License, or (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
- */\r
-package jalview.gui;\r
-\r
-import jalview.datamodel.*;\r
-import javax.swing.*;\r
-import javax.swing.event.*;\r
-import java.awt.*;\r
-import java.util.*;\r
-import javax.swing.BorderFactory;\r
-import java.awt.event.*;\r
-import javax.swing.table.*;\r
-import java.io.*;\r
-import jalview.io.JalviewFileChooser;\r
-\r
-public class FeatureSettings extends JPanel\r
-{\r
-\r
-  final FeatureRenderer fr;\r
-  final AlignmentPanel ap;\r
-  final AlignViewport av;\r
-  Object [][] originalData;\r
-  final JInternalFrame frame;\r
-  JScrollPane scrollPane = new JScrollPane();\r
-  JTable table;\r
-\r
-  public FeatureSettings(AlignViewport av, final AlignmentPanel ap)\r
-  {\r
-    this.ap = ap;\r
-    this.av = av;\r
-    fr = ap.seqPanel.seqCanvas.getFeatureRenderer();\r
-    av.alignment.getSequences();\r
-    frame = new JInternalFrame();\r
-    frame.setContentPane(this);\r
-    Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 300);\r
-\r
-    setTableData();\r
-\r
-    final JSlider transparency = new JSlider(0, 70, 0);\r
-    transparency.addChangeListener(new ChangeListener()\r
-    {\r
-      public void stateChanged(ChangeEvent evt)\r
-      {\r
-        fr.setTransparency( (float) (100 - transparency.getValue()) / 100f);\r
-        ap.repaint();\r
-      }\r
-    });\r
-\r
-    JPanel transPanel = new JPanel(new FlowLayout());\r
-    transPanel.add(new JLabel("Transparency"));\r
-    transPanel.add(transparency);\r
-\r
-    //////////////////////////////////////////////\r
-    //We're going to need those OK cancel buttons\r
-    JPanel buttonPanel = new JPanel(new FlowLayout());\r
-    JButton button = new JButton("OK");\r
-    button.addActionListener(new ActionListener()\r
-    {\r
-      public void actionPerformed(ActionEvent evt)\r
-      {\r
-        try\r
-        {\r
-          frame.setClosed(true);\r
-        }\r
-        catch (Exception exe)\r
-        {}\r
-      }\r
-    });\r
-    buttonPanel.add(button);\r
-    button = new JButton("Cancel");\r
-    button.addActionListener(new ActionListener()\r
-    {\r
-      public void actionPerformed(ActionEvent evt)\r
-      {\r
-        try\r
-        {\r
-          updateFeatureRenderer(originalData);\r
-          frame.setClosed(true);\r
-        }\r
-        catch (Exception exe)\r
-        {}\r
-      }\r
-    });\r
-    buttonPanel.add(button);\r
-\r
-    button = new JButton("Load Colours");\r
-    button.addActionListener(new ActionListener()\r
-    {\r
-      public void actionPerformed(ActionEvent evt)\r
-      {\r
-        load();\r
-      }\r
-    });\r
-    buttonPanel.add(button);\r
-    button = new JButton("Save Colours");\r
-    button.addActionListener(new ActionListener()\r
-    {\r
-      public void actionPerformed(ActionEvent evt)\r
-      {\r
-        save();\r
-      }\r
-    });\r
-    buttonPanel.add(button);\r
-\r
-    this.setLayout(new BorderLayout());\r
-    JPanel bigPanel = new JPanel(new BorderLayout());\r
-    bigPanel.add(transPanel, BorderLayout.SOUTH);\r
-    bigPanel.add(scrollPane, BorderLayout.CENTER);\r
-\r
-    add(bigPanel, BorderLayout.CENTER);\r
-    add(buttonPanel, BorderLayout.SOUTH);\r
-\r
-\r
-  }\r
-\r
-  void setTableData()\r
-  {\r
-    Vector allFeatures = new Vector();\r
-    Vector features;\r
-    Enumeration e;\r
-    SequenceFeature sf;\r
-\r
-    for(int i=0; i< av.alignment.getHeight(); i++)\r
-    {\r
-       features = av.alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures();\r
-       if(features==null)\r
-         continue;\r
-\r
-       e = features.elements();\r
-       while(e.hasMoreElements())\r
-       {\r
-         sf = (SequenceFeature)e.nextElement();\r
-         if(!allFeatures.contains(sf.getType()))\r
-         {\r
-           allFeatures.addElement(sf.getType());\r
-         }\r
-       }\r
-    }\r
-    if(allFeatures.size()<1)\r
-     {\r
-       try{\r
-         frame.setClosed(true);\r
-       }catch(Exception ex){}\r
-       return;\r
-     }\r
-\r
-    int fSize = allFeatures.size();\r
-\r
-    String type;\r
-    boolean originalExists = false;\r
-    if(originalData!=null)\r
-      originalExists = true;\r
-    else\r
-      originalData = new Object[fSize][3];\r
-\r
-    Object [][] data = new Object[fSize][3];\r
-    for(int i=0; i<fSize; i++)\r
-    {\r
-      type = allFeatures.elementAt(i).toString();\r
-      Color col = fr.getColour(type);\r
-      data[i][0]=type;\r
-      data[i][1]=col;\r
-      if(fr.featuresDisplayed!=null)\r
-         data[i][2] = new Boolean(fr.featuresDisplayed.contains(type));\r
-      else\r
-        data[i][2] = new Boolean(true);\r
-\r
-      if(!originalExists)\r
-      {\r
-        originalData[i][0] = type;\r
-        originalData[i][1] = col;\r
-        if (fr.featuresDisplayed != null)\r
-          originalData[i][2] = new Boolean(fr.featuresDisplayed.contains(type));\r
-        else\r
-          originalData[i][2] = new Boolean(true);\r
-      }\r
-    }\r
-    ////////////////////////////////////\r
-        //Now build the table\r
-        table = new JTable(new FeatureTableModel(data));\r
-        scrollPane.setViewportView(table);\r
-        table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));\r
-        table.setFont(new Font("Verdana", Font.PLAIN, 12));\r
-        table.setDefaultRenderer(Color.class,\r
-                             new ColorRenderer());\r
-\r
-        table.setDefaultEditor(Color.class,\r
-                          new ColorEditor());\r
-\r
-        table.getColumnModel().getColumn(0).setPreferredWidth(200);\r
-\r
-        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);\r
-\r
-        table.addMouseListener(new MouseAdapter()\r
-            {\r
-              public void mousePressed(MouseEvent evt)\r
-              {\r
-                selectedRow = table.rowAtPoint(evt.getPoint());\r
-              }\r
-            });\r
-\r
-        table.addMouseMotionListener(new MouseMotionAdapter()\r
-            {\r
-              public void mouseDragged(MouseEvent evt)\r
-              {\r
-                int newRow = table.rowAtPoint(evt.getPoint());\r
-                if(newRow!=selectedRow\r
-                   && selectedRow!=-1\r
-                   && newRow!=-1)\r
-                {\r
-                  Object[] temp = new Object[3];\r
-                  temp[0] = table.getValueAt(selectedRow, 0);\r
-                  temp[1] = table.getValueAt(selectedRow, 1);\r
-                  temp[2] = table.getValueAt(selectedRow, 2);\r
-\r
-                  table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);\r
-                  table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);\r
-                  table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);\r
-\r
-                  table.setValueAt(temp[0], newRow, 0);\r
-                  table.setValueAt(temp[1], newRow, 1);\r
-                  table.setValueAt(temp[2], newRow, 2);\r
-\r
-                  selectedRow = newRow;\r
-                }\r
-              }\r
-        });\r
-\r
-  }\r
-\r
-  void load()\r
-  {\r
-    JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(\r
-                 "LAST_DIRECTORY"), new String[] { "fc" },\r
-             new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");\r
-     chooser.setFileView(new jalview.io.JalviewFileView());\r
-     chooser.setDialogTitle("Load Feature Colours");\r
-     chooser.setToolTipText("Load");\r
-\r
-     int value = chooser.showOpenDialog(this);\r
-\r
-     if (value == JalviewFileChooser.APPROVE_OPTION)\r
-     {\r
-       File file = chooser.getSelectedFile();\r
-\r
-       try\r
-       {\r
-         InputStreamReader in = new InputStreamReader(new FileInputStream(\r
-             file), "UTF-8");\r
-\r
-         jalview.binding.JalviewUserColours jucs = new jalview.binding.\r
-             JalviewUserColours();\r
-         jucs = (jalview.binding.JalviewUserColours) jucs.unmarshal(in);\r
-\r
-\r
-         for (int i = 0; i < jucs.getColourCount(); i++)\r
-         {\r
-           fr.setColour( jucs.getColour(i).getName(),\r
-                          new Color(Integer.parseInt( jucs.getColour(i).getRGB(), 16)));\r
-         }\r
-\r
-         setTableData();\r
-         ap.repaint();\r
-       }\r
-       catch (Exception ex)\r
-       {\r
-         System.out.println("Error loading User ColourFile\n" + ex);\r
-       }\r
-     }\r
-  }\r
-\r
-  void save()\r
-  {\r
-    JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(\r
-                "LAST_DIRECTORY"), new String[] { "fc" },\r
-            new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");\r
-    chooser.setFileView(new jalview.io.JalviewFileView());\r
-    chooser.setDialogTitle("Save Feature Colour Scheme");\r
-    chooser.setToolTipText("Save");\r
-\r
-    int value = chooser.showSaveDialog(this);\r
-\r
-    if (value == JalviewFileChooser.APPROVE_OPTION)\r
-    {\r
-        String choice = chooser.getSelectedFile().getPath();\r
-        jalview.binding.JalviewUserColours ucs = new jalview.binding.JalviewUserColours();\r
-        ucs.setSchemeName("Sequence Features");\r
-        try\r
-        {\r
-            PrintWriter out = new PrintWriter(new OutputStreamWriter(\r
-                        new FileOutputStream(choice), "UTF-8"));\r
-\r
-            Enumeration e = fr.featureColours.keys();\r
-           while(e.hasMoreElements())\r
-           {\r
-\r
-\r
-                jalview.binding.Colour col = new jalview.binding.Colour();\r
-                col.setName(e.nextElement().toString());\r
-                col.setRGB(jalview.util.Format.getHexString(\r
-                        fr.getColour(col.getName())));\r
-                ucs.addColour(col);\r
-            }\r
-\r
-            ucs.marshal(out);\r
-            out.close();\r
-        }\r
-        catch (Exception ex)\r
-        {\r
-            ex.printStackTrace();\r
-        }\r
-    }\r
-\r
-  }\r
-\r
-  public void updateFeatureRenderer(Object [][] data)\r
-  {\r
-    fr.setFeaturePriority( data );\r
-    ap.repaint();\r
-  }\r
-\r
-  int selectedRow =-1;\r
-\r
-\r
-  /////////////////////////////////////////////////////////////////////////\r
-  // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html\r
-  /////////////////////////////////////////////////////////////////////////\r
-  class FeatureTableModel\r
-      extends AbstractTableModel\r
-  {\r
-    FeatureTableModel(Object[][] data)\r
-    {\r
-      this.data = data;\r
-    }\r
-\r
-    private String[] columnNames = {"Feature Type", "Colour","Display"};\r
-          private Object[][] data;\r
-\r
-          public Object[][] getData()\r
-          {\r
-            return data;\r
-          }\r
-\r
-          public int getColumnCount() {\r
-              return columnNames.length;\r
-          }\r
-\r
-          public Object[] getRow(int row)\r
-          {\r
-            return data[row];\r
-          }\r
-\r
-          public int getRowCount() {\r
-              return data.length;\r
-          }\r
-\r
-          public String getColumnName(int col) {\r
-              return columnNames[col];\r
-          }\r
-\r
-          public Object getValueAt(int row, int col) {\r
-              return data[row][col];\r
-          }\r
-\r
-          public Class getColumnClass(int c) {\r
-              return getValueAt(0, c).getClass();\r
-          }\r
-\r
-          public boolean isCellEditable(int row, int col) {\r
-              return col==0 ? false:true;\r
-          }\r
-\r
-          public void setValueAt(Object value, int row, int col) {\r
-              data[row][col] = value;\r
-              fireTableCellUpdated(row, col);\r
-              updateFeatureRenderer(data);\r
-          }\r
-\r
-    }\r
-    class ColorRenderer extends JLabel\r
-                              implements TableCellRenderer {\r
-       javax.swing.border.Border unselectedBorder = null;\r
-       javax.swing.border.Border selectedBorder = null;\r
-\r
-       public ColorRenderer() {\r
-           setOpaque(true); //MUST do this for background to show up.\r
-       }\r
-\r
-       public Component getTableCellRendererComponent(\r
-                               JTable table, Object color,\r
-                               boolean isSelected, boolean hasFocus,\r
-                               int row, int column) {\r
-           Color newColor = (Color)color;\r
-           setBackground(newColor);\r
-               if (isSelected) {\r
-                   if (selectedBorder == null) {\r
-                       selectedBorder = BorderFactory.createMatteBorder(2,5,2,5,\r
-                                                 table.getSelectionBackground());\r
-                   }\r
-                   setBorder(selectedBorder);\r
-               } else {\r
-                   if (unselectedBorder == null) {\r
-                       unselectedBorder = BorderFactory.createMatteBorder(2,5,2,5,\r
-                                                 table.getBackground());\r
-                   }\r
-                   setBorder(unselectedBorder);\r
-               }\r
-\r
-           setToolTipText("RGB value: " + newColor.getRed() + ", "\r
-                                        + newColor.getGreen() + ", "\r
-                                        + newColor.getBlue());\r
-           return this;\r
-       }\r
-   }\r
-}\r
-\r
- class ColorEditor extends AbstractCellEditor\r
-                          implements TableCellEditor,\r
-                                     ActionListener {\r
-     Color currentColor;\r
-     JButton button;\r
-     JColorChooser colorChooser;\r
-     JDialog dialog;\r
-     protected static final String EDIT = "edit";\r
-\r
-     public ColorEditor() {\r
-         //Set up the editor (from the table's point of view),\r
-         //which is a button.\r
-         //This button brings up the color chooser dialog,\r
-         //which is the editor from the user's point of view.\r
-         button = new JButton();\r
-         button.setActionCommand(EDIT);\r
-         button.addActionListener(this);\r
-         button.setBorderPainted(false);\r
-         //Set up the dialog that the button brings up.\r
-         colorChooser = new JColorChooser();\r
-         dialog = JColorChooser.createDialog(button,\r
-                                         "Select new Colour",\r
-                                         true,  //modal\r
-                                         colorChooser,\r
-                                         this,  //OK button handler\r
-                                         null); //no CANCEL button handler\r
-     }\r
-\r
-     /**\r
-      * Handles events from the editor button and from\r
-      * the dialog's OK button.\r
-      */\r
-     public void actionPerformed(ActionEvent e) {\r
-\r
-          if (EDIT.equals(e.getActionCommand())) {\r
-             //The user has clicked the cell, so\r
-             //bring up the dialog.\r
-             button.setBackground(currentColor);\r
-             colorChooser.setColor(currentColor);\r
-             dialog.setVisible(true);\r
-\r
-             //Make the renderer reappear.\r
-             fireEditingStopped();\r
-\r
-         } else { //User pressed dialog's "OK" button.\r
-             currentColor = colorChooser.getColor();\r
-         }\r
-     }\r
-\r
-     //Implement the one CellEditor method that AbstractCellEditor doesn't.\r
-     public Object getCellEditorValue() {\r
-         return currentColor;\r
-     }\r
-\r
-     //Implement the one method defined by TableCellEditor.\r
-     public Component getTableCellEditorComponent(JTable table,\r
-                                                  Object value,\r
-                                                  boolean isSelected,\r
-                                                  int row,\r
-                                                  int column) {\r
-         currentColor = (Color)value;\r
-         return button;\r
-     }\r
-}\r
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer
+ * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+package jalview.gui;
+
+import jalview.datamodel.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import java.awt.*;
+import java.util.*;
+import javax.swing.BorderFactory;
+import java.awt.event.*;
+import javax.swing.table.*;
+import java.io.*;
+import jalview.io.JalviewFileChooser;
+import java.awt.BorderLayout;
+import java.awt.Font;
+import java.awt.Color;
+
+public class FeatureSettings extends JPanel
+{
+  DasSourceBrowser dassourceBrowser;
+  JPanel settingsPane = new JPanel();
+  JPanel dasSettingsPane = new JPanel();
+
+  final FeatureRenderer fr;
+  final AlignFrame af;
+  Object [][] originalData;
+  final JInternalFrame frame;
+  JScrollPane scrollPane = new JScrollPane();
+  JTable table;
+  JPanel groupPanel;
+  JSlider transparency = new JSlider();
+
+  JPanel transPanel = new JPanel(new FlowLayout());
+
+  public FeatureSettings(AlignFrame af)
+  {
+    this.af = af;
+    fr = af.getFeatureRenderer();
+
+    transparency.setMaximum( 100 - (int)(fr.transparency*100) ) ;
+
+   try
+   {
+     jbInit();
+   }
+   catch (Exception ex)
+   {
+     ex.printStackTrace();
+   }
+
+   table = new JTable();
+   table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
+   table.setFont(new Font("Verdana", Font.PLAIN, 12));
+   table.setDefaultRenderer(Color.class,
+                            new ColorRenderer());
+
+   table.setDefaultEditor(Color.class,
+                          new ColorEditor());
+
+   table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+   table.addMouseListener(new MouseAdapter()
+   {
+     public void mousePressed(MouseEvent evt)
+     {
+       selectedRow = table.rowAtPoint(evt.getPoint());
+     }
+   });
+
+   table.addMouseMotionListener(new MouseMotionAdapter()
+   {
+     public void mouseDragged(MouseEvent evt)
+     {
+       int newRow = table.rowAtPoint(evt.getPoint());
+       if (newRow != selectedRow
+           && selectedRow != -1
+           && newRow != -1)
+       {
+         Object[] temp = new Object[3];
+         temp[0] = table.getValueAt(selectedRow, 0);
+         temp[1] = table.getValueAt(selectedRow, 1);
+         temp[2] = table.getValueAt(selectedRow, 2);
+
+         table.setValueAt(table.getValueAt(newRow, 0), selectedRow, 0);
+         table.setValueAt(table.getValueAt(newRow, 1), selectedRow, 1);
+         table.setValueAt(table.getValueAt(newRow, 2), selectedRow, 2);
+
+         table.setValueAt(temp[0], newRow, 0);
+         table.setValueAt(temp[1], newRow, 1);
+         table.setValueAt(temp[2], newRow, 2);
+
+         selectedRow = newRow;
+       }
+     }
+   });
+
+   scrollPane.setViewportView(table);
+
+    dassourceBrowser = new DasSourceBrowser();
+    dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
+
+
+
+    if (af.getViewport().featuresDisplayed == null || fr.renderOrder==null)
+       fr.findAllFeatures();
+
+    setTableData();
+
+    frame = new JInternalFrame();
+    frame.setContentPane(this);
+    Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 450);
+    frame.setLayer(JLayeredPane.PALETTE_LAYER);
+  }
+
+  synchronized public void setTableData()
+  {
+    if (fr.featureGroups == null)
+      fr.featureGroups = new Hashtable();
+
+    Vector allFeatures = new Vector();
+    Vector allGroups = new Vector();
+    SequenceFeature[] tmpfeatures;
+    String group;
+
+    for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
+    {
+      if (af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures() == null)
+        continue;
+
+      tmpfeatures = af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures();
+
+      int index = 0;
+      while (index < tmpfeatures.length)
+      {
+        if(tmpfeatures[index].begin == 0 && tmpfeatures[index].end ==0)
+        {
+          index++;
+          continue;
+        }
+
+        if(tmpfeatures[index].getFeatureGroup()!=null)
+        {
+          group = tmpfeatures[index].featureGroup;
+          if(!allGroups.contains(group))
+           {
+             allGroups.addElement(group);
+
+             boolean visible = true;
+             if (fr.featureGroups.containsKey(group))
+             {
+               visible = ( (Boolean) fr.featureGroups.get(group)).booleanValue();
+             }
+
+               if (groupPanel == null)
+               {
+                 groupPanel = new JPanel();
+               }
+
+               boolean alreadyAdded = false;
+               for(int g=0; g<groupPanel.getComponentCount(); g++)
+               {
+                 if(((JCheckBox)groupPanel.getComponent(g))
+                    .getText().equals(group))
+                 {
+                   alreadyAdded = true;
+                   break;
+                 }
+               }
+
+               if(alreadyAdded)
+                 continue;
+
+               fr.featureGroups.put(group, new Boolean(visible));
+
+               final JCheckBox check = new JCheckBox(group, visible);
+               check.setFont(new Font("Serif", Font.BOLD, 12));
+               check.addItemListener(new ItemListener()
+               {
+                 public void itemStateChanged(ItemEvent evt)
+                 {
+                   fr.featureGroups.put(check.getText(),
+                                        new Boolean(check.isSelected()));
+                   af.alignPanel.seqPanel.seqCanvas.repaint();
+                   if (af.alignPanel.overviewPanel != null)
+                     af.alignPanel.overviewPanel.updateOverviewImage();
+
+                   resetTable(true);
+                 }
+               });
+               groupPanel.add(check);
+             }
+       }
+
+       if (!allFeatures.contains(tmpfeatures[index].getType()))
+       {
+           allFeatures.addElement(tmpfeatures[index].getType());
+       }
+       index ++;
+    }
+  }
+
+     resetTable(false);
+
+     validate();
+  }
+
+
+  void resetTable(boolean groupsChanged)
+  {
+   SequenceFeature [] tmpfeatures;
+   String group=null, type;
+   Vector visibleChecks = new Vector();
+
+   //Find out which features should be visible depending on which groups
+   //are selected / deselected
+    for (int i = 0; i < af.getViewport().alignment.getHeight(); i++)
+    {
+
+        tmpfeatures = af.getViewport().alignment.getSequenceAt(i).getDatasetSequence().getSequenceFeatures();
+        if (tmpfeatures == null)
+          continue;
+
+        int index = 0;
+        while (index < tmpfeatures.length)
+        {
+          group = tmpfeatures[index].featureGroup;
+
+          if(tmpfeatures[index].begin==0 && tmpfeatures[index].end==0)
+          {
+            index ++;
+            continue;
+          }
+
+          if (group==null || fr.featureGroups.get(group)==null ||
+              ((Boolean) fr.featureGroups.get(group)).booleanValue())
+          {
+            type = tmpfeatures[index].getType();
+            if(!visibleChecks.contains(type) )
+            {
+              visibleChecks.addElement(type);
+            }
+          }
+          index++;
+        }
+    }
+
+    int fSize = visibleChecks.size();
+    Object [][] data = new Object[fSize][3];
+    int dataIndex = 0;
+
+    if(fr.renderOrder!=null)
+    {
+      //First add the checks in the previous render order,
+      //in case the window has been closed and reopened
+      for(int ro=fr.renderOrder.length-1; ro>-1; ro--)
+      {
+           type = fr.renderOrder[ro];
+
+           if(!visibleChecks.contains(type))
+             continue;
+
+           data[dataIndex][0] = type;
+           data[dataIndex][1] = fr.getColour(type);
+           data[dataIndex][2] = new Boolean(af.getViewport().featuresDisplayed.containsKey(type));
+           dataIndex++;
+           visibleChecks.removeElement(type);
+      }
+    }
+
+    fSize = visibleChecks.size();
+    for(int i=0; i<fSize; i++)
+    {
+      //These must be extra features belonging to the group
+      //which was just selected
+      type = visibleChecks.elementAt(i).toString();
+      data[dataIndex][0] = type;
+
+      data[dataIndex][1] = fr.getColour(type);
+      data[dataIndex][2] = new Boolean(true);
+      dataIndex++;
+    }
+
+    if(originalData==null)
+    {
+      originalData = new Object[data.length][3];
+      System.arraycopy(data,0,originalData,0,data.length);
+    }
+
+    table.setModel(new FeatureTableModel(data));
+    table.getColumnModel().getColumn(0).setPreferredWidth(200);
+
+
+    if (groupPanel != null)
+    {
+      groupPanel.setLayout(
+          new GridLayout(fr.featureGroups.size() / 4 + 1, 4));
+
+      groupPanel.validate();
+      bigPanel.add(groupPanel, BorderLayout.NORTH);
+    }
+
+    updateFeatureRenderer(data);
+
+  }
+
+  void load()
+  {
+    JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
+                 "LAST_DIRECTORY"), new String[] { "fc" },
+             new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");
+     chooser.setFileView(new jalview.io.JalviewFileView());
+     chooser.setDialogTitle("Load Feature Colours");
+     chooser.setToolTipText("Load");
+
+     int value = chooser.showOpenDialog(this);
+
+     if (value == JalviewFileChooser.APPROVE_OPTION)
+     {
+       File file = chooser.getSelectedFile();
+
+       try
+       {
+         InputStreamReader in = new InputStreamReader(new FileInputStream(
+             file), "UTF-8");
+
+         jalview.binding.JalviewUserColours jucs = new jalview.binding.
+             JalviewUserColours();
+         jucs = (jalview.binding.JalviewUserColours) jucs.unmarshal(in);
+
+
+         for (int i = 0; i < jucs.getColourCount(); i++)
+         {
+           fr.setColour( jucs.getColour(i).getName(),
+                          new Color(Integer.parseInt( jucs.getColour(i).getRGB(), 16)));
+         }
+
+         setTableData();
+         af.alignPanel.repaint();
+       }
+       catch (Exception ex)
+       {
+         System.out.println("Error loading User Colour File\n" + ex);
+       }
+     }
+  }
+
+  void save()
+  {
+    JalviewFileChooser chooser = new JalviewFileChooser(jalview.bin.Cache.getProperty(
+                "LAST_DIRECTORY"), new String[] { "fc" },
+            new String[] { "Sequence Feature Colours" }, "Sequence Feature Colours");
+    chooser.setFileView(new jalview.io.JalviewFileView());
+    chooser.setDialogTitle("Save Feature Colour Scheme");
+    chooser.setToolTipText("Save");
+
+    int value = chooser.showSaveDialog(this);
+
+    if (value == JalviewFileChooser.APPROVE_OPTION)
+    {
+        String choice = chooser.getSelectedFile().getPath();
+        jalview.binding.JalviewUserColours ucs = new jalview.binding.JalviewUserColours();
+        ucs.setSchemeName("Sequence Features");
+        try
+        {
+            PrintWriter out = new PrintWriter(new OutputStreamWriter(
+                        new FileOutputStream(choice), "UTF-8"));
+
+            Enumeration e = fr.featureColours.keys();
+           while(e.hasMoreElements())
+           {
+                jalview.binding.Colour col = new jalview.binding.Colour();
+                col.setName(e.nextElement().toString());
+                col.setRGB(jalview.util.Format.getHexString(
+                        fr.getColour(col.getName())));
+                ucs.addColour(col);
+            }
+
+            ucs.marshal(out);
+            out.close();
+        }
+        catch (Exception ex)
+        {
+            ex.printStackTrace();
+        }
+    }
+  }
+
+  public void invertSelection()
+  {
+    for(int i=0; i<table.getRowCount(); i++)
+    {
+      Boolean value = (Boolean)table.getValueAt(i,2);
+
+      table.setValueAt(
+          new Boolean(!value.booleanValue()),
+                       i,2);
+    }
+  }
+
+  public void close()
+  {
+    try
+    {
+      frame.setClosed(true);
+    }
+    catch (Exception exe)
+    {}
+
+  }
+
+  public void updateFeatureRenderer(Object [][] data)
+  {
+    fr.setFeaturePriority( data );
+    af.alignPanel.repaint();
+
+    if(af.alignPanel.overviewPanel!=null)
+      af.alignPanel.overviewPanel.updateOverviewImage();
+  }
+
+  int selectedRow =-1;
+  JTabbedPane tabbedPane = new JTabbedPane();
+  BorderLayout borderLayout1 = new BorderLayout();
+  BorderLayout borderLayout2 = new BorderLayout();
+  BorderLayout borderLayout3 = new BorderLayout();
+  JPanel bigPanel = new JPanel();
+  BorderLayout borderLayout4 = new BorderLayout();
+  JButton invert = new JButton();
+  JPanel buttonPanel = new JPanel();
+  JButton cancel = new JButton();
+  JButton ok = new JButton();
+  JButton loadColours = new JButton();
+  JButton saveColours = new JButton();
+  JPanel dasButtonPanel = new JPanel();
+  JButton fetchDAS = new JButton();
+  JButton saveDAS = new JButton();
+  private void jbInit()
+      throws Exception
+  {
+    this.setLayout(borderLayout1);
+    settingsPane.setLayout(borderLayout2);
+    dasSettingsPane.setLayout(borderLayout3);
+    bigPanel.setLayout(borderLayout4);
+    invert.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
+    invert.setText("Invert Selection");
+    invert.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        invertSelection();
+      }
+    });
+    cancel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
+    cancel.setText("Cancel");
+    cancel.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+          updateFeatureRenderer(originalData);
+          close();
+      }
+    });
+    ok.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
+    ok.setText("OK");
+    ok.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        close();
+      }
+    });
+    loadColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
+    loadColours.setText("Load Colours");
+    loadColours.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        load();
+      }
+    });
+    saveColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
+    saveColours.setText("Save Colours");
+    saveColours.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        save();
+      }
+    });
+    transparency.addChangeListener(new ChangeListener()
+    {
+      public void stateChanged(ChangeEvent evt)
+      {
+        fr.setTransparency( (float) (100 - transparency.getValue()) / 100f);
+        af.alignPanel.repaint();
+      }
+    });
+
+
+    transparency.setMaximum(70);
+    fetchDAS.setText("Fetch DAS Features");
+    fetchDAS.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        fetchDAS_actionPerformed(e);
+      }
+    });
+    saveDAS.setText("Save as default");
+    saveDAS.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        saveDAS_actionPerformed(e);
+      }
+    });
+    dasButtonPanel.setBorder(BorderFactory.createEtchedBorder());
+    dasSettingsPane.setBorder(null);
+    this.add(tabbedPane, java.awt.BorderLayout.CENTER);
+    tabbedPane.addTab("Feature Settings", settingsPane );
+    tabbedPane.addTab("DAS Settings", dasSettingsPane);
+    bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH);
+    transPanel.add(transparency);
+    transPanel.add(invert);
+    buttonPanel.add(ok);
+    buttonPanel.add(cancel);
+    buttonPanel.add(loadColours);
+    buttonPanel.add(saveColours);
+    bigPanel.add(scrollPane, java.awt.BorderLayout.CENTER);
+    dasSettingsPane.add(dasButtonPanel, java.awt.BorderLayout.SOUTH);
+    dasButtonPanel.add(fetchDAS);
+    dasButtonPanel.add(saveDAS);
+    settingsPane.add(bigPanel, java.awt.BorderLayout.CENTER);
+    settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
+  }
+
+  public void fetchDAS_actionPerformed(ActionEvent e)
+  {
+    Vector selectedSources = dassourceBrowser.getSelectedSources();
+
+    SequenceI [] dataset, seqs ;
+    int iSize;
+
+    if(af.getViewport().getSelectionGroup()!=null
+      && af.getViewport().getSelectionGroup().getSize(false)>0)
+    {
+      iSize = af.getViewport().getSelectionGroup().getSize(false);
+      dataset = new SequenceI[iSize];
+      seqs = af.getViewport().getSelectionGroup().
+          getSequencesInOrder(
+              af.getViewport().getAlignment());
+    }
+    else
+    {
+       iSize = af.getViewport().getAlignment().getHeight();
+       seqs = af.getViewport().getAlignment().getSequencesArray();
+    }
+
+    dataset = new SequenceI[iSize];
+    for (int i = 0; i < iSize; i++)
+    {
+      dataset[i] = seqs[i].getDatasetSequence();
+    }
+
+    new jalview.io.DasSequenceFeatureFetcher(
+        dataset,
+        af,
+        selectedSources);
+
+    af.getViewport().setShowSequenceFeatures(true);
+    af.showSeqFeatures.setSelected(true);
+  }
+
+  public void saveDAS_actionPerformed(ActionEvent e)
+  {
+    dassourceBrowser.saveProperties(jalview.bin.Cache.applicationProperties);
+  }
+
+  /////////////////////////////////////////////////////////////////////////
+  // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
+  /////////////////////////////////////////////////////////////////////////
+  class FeatureTableModel
+      extends AbstractTableModel
+  {
+    FeatureTableModel(Object[][] data)
+    {
+      this.data = data;
+    }
+
+    private String[] columnNames = {"Feature Type", "Colour","Display"};
+          private Object[][] data;
+
+          public Object[][] getData()
+          {
+            return data;
+          }
+
+          public void setData(Object[][] data)
+          {
+            this.data = data;
+          }
+
+          public int getColumnCount() {
+              return columnNames.length;
+          }
+
+          public Object[] getRow(int row)
+          {
+            return data[row];
+          }
+
+          public int getRowCount() {
+              return data.length;
+          }
+
+          public String getColumnName(int col) {
+              return columnNames[col];
+          }
+
+          public Object getValueAt(int row, int col) {
+              return data[row][col];
+          }
+
+          public Class getColumnClass(int c) {
+              return getValueAt(0, c).getClass();
+          }
+
+          public boolean isCellEditable(int row, int col) {
+              return col==0 ? false:true;
+          }
+
+          public void setValueAt(Object value, int row, int col) {
+              data[row][col] = value;
+              fireTableCellUpdated(row, col);
+              updateFeatureRenderer(data);
+          }
+
+    }
+    class ColorRenderer extends JLabel
+                              implements TableCellRenderer {
+       javax.swing.border.Border unselectedBorder = null;
+       javax.swing.border.Border selectedBorder = null;
+
+       public ColorRenderer() {
+           setOpaque(true); //MUST do this for background to show up.
+       }
+
+       public Component getTableCellRendererComponent(
+                               JTable table, Object color,
+                               boolean isSelected, boolean hasFocus,
+                               int row, int column) {
+           Color newColor = (Color)color;
+           setBackground(newColor);
+               if (isSelected) {
+                   if (selectedBorder == null) {
+                       selectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
+                                                 table.getSelectionBackground());
+                   }
+                   setBorder(selectedBorder);
+               } else {
+                   if (unselectedBorder == null) {
+                       unselectedBorder = BorderFactory.createMatteBorder(2,5,2,5,
+                                                 table.getBackground());
+                   }
+                   setBorder(unselectedBorder);
+               }
+
+           setToolTipText("RGB value: " + newColor.getRed() + ", "
+                                        + newColor.getGreen() + ", "
+                                        + newColor.getBlue());
+           return this;
+       }
+   }
+}
+
+ class ColorEditor extends AbstractCellEditor
+                          implements TableCellEditor,
+                                     ActionListener {
+     Color currentColor;
+     JButton button;
+     JColorChooser colorChooser;
+     JDialog dialog;
+     protected static final String EDIT = "edit";
+
+     public ColorEditor() {
+         //Set up the editor (from the table's point of view),
+         //which is a button.
+         //This button brings up the color chooser dialog,
+         //which is the editor from the user's point of view.
+         button = new JButton();
+         button.setActionCommand(EDIT);
+         button.addActionListener(this);
+         button.setBorderPainted(false);
+         //Set up the dialog that the button brings up.
+         colorChooser = new JColorChooser();
+         dialog = JColorChooser.createDialog(button,
+                                         "Select new Colour",
+                                         true,  //modal
+                                         colorChooser,
+                                         this,  //OK button handler
+                                         null); //no CANCEL button handler
+     }
+
+     /**
+      * Handles events from the editor button and from
+      * the dialog's OK button.
+      */
+     public void actionPerformed(ActionEvent e) {
+
+          if (EDIT.equals(e.getActionCommand())) {
+             //The user has clicked the cell, so
+             //bring up the dialog.
+             button.setBackground(currentColor);
+             colorChooser.setColor(currentColor);
+             dialog.setVisible(true);
+
+             //Make the renderer reappear.
+             fireEditingStopped();
+
+         } else { //User pressed dialog's "OK" button.
+             currentColor = colorChooser.getColor();
+         }
+     }
+
+     //Implement the one CellEditor method that AbstractCellEditor doesn't.
+     public Object getCellEditorValue() {
+         return currentColor;
+     }
+
+     //Implement the one method defined by TableCellEditor.
+     public Component getTableCellEditorComponent(JTable table,
+                                                  Object value,
+                                                  boolean isSelected,
+                                                  int row,
+                                                  int column) {
+         currentColor = (Color)value;
+         return button;
+     }
+}