JAL-1645 Version-Rel Version 2.9 Year-Rel 2015 Licensing glob
[jalview.git] / src / jalview / appletgui / FeatureRenderer.java
old mode 100755 (executable)
new mode 100644 (file)
index 5e65409..1dc48d2
 /*
- * Jalview - A Sequence Alignment Editor and Viewer
- * Copyright (C) 2007 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
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9)
+ * Copyright (C) 2015 The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
  * of the License, or (at your option) any later version.
- *
- * 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.
- *
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
 package jalview.appletgui;
 
-import java.util.*;
-
-import java.awt.*;
-
-import java.awt.event.*;
-
-
-import jalview.appletgui.FeatureSettings.MyCheckbox;
-import jalview.datamodel.*;
+import jalview.datamodel.SearchResults;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
+import jalview.schemes.AnnotationColourGradient;
+import jalview.schemes.GraduatedColor;
+import jalview.util.MessageManager;
+import jalview.viewmodel.AlignmentViewport;
+
+import java.awt.BorderLayout;
+import java.awt.Button;
+import java.awt.Choice;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.GridLayout;
+import java.awt.Label;
+import java.awt.Panel;
+import java.awt.ScrollPane;
+import java.awt.TextArea;
+import java.awt.TextField;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Hashtable;
 
 /**
  * DOCUMENT ME!
- *
+ * 
  * @author $author$
  * @version $Revision$
  */
-public class FeatureRenderer
+public class FeatureRenderer extends
+        jalview.renderer.seqfeatures.FeatureRenderer
 {
-  AlignViewport av;
-
-  Hashtable featureColours = new Hashtable();
-
-  // A higher level for grouping features of a
-  // particular type
-  Hashtable featureGroups = null;
 
   // Holds web links for feature groups and feature types
   // in the form label|link
   Hashtable featureLinks = null;
 
-  // This is actually an Integer held in the hashtable,
-  // Retrieved using the key feature type
-  Object currentColour;
-
-  String[] renderOrder;
-
-  FontMetrics fm;
-  int charOffset;
-
-  float transparency = 1f;
-
-  TransparencySetter transparencySetter = null;
-
   /**
    * Creates a new FeatureRenderer object.
-   *
-   * @param av DOCUMENT ME!
+   * 
+   * @param av
+   *          DOCUMENT ME!
    */
-  public FeatureRenderer(AlignViewport av)
+  public FeatureRenderer(AlignmentViewport av)
   {
+    super();
     this.av = av;
 
-    if (!System.getProperty("java.version").startsWith("1.1"))
-    {
-      transparencySetter = new TransparencySetter();
-    }
-  }
-
-  public void transferSettings(FeatureRenderer fr)
-  {
-    renderOrder = fr.renderOrder;
-    featureGroups = fr.featureGroups;
-    featureColours = fr.featureColours;
-    transparency = fr.transparency;
+    setTransparencyAvailable(!System.getProperty("java.version")
+            .startsWith("1.1"));
   }
 
-
   static String lastFeatureAdded;
+
   static String lastFeatureGroupAdded;
+
   static String lastDescriptionAdded;
 
   int featureIndex = 0;
+
   boolean deleteFeature = false;
-  Panel colourPanel;
+
+  FeatureColourPanel colourPanel;
+
+  class FeatureColourPanel extends Panel
+  {
+    String label = "";
+
+    private Color maxCol;
+
+    private boolean isColourByLabel, isGcol;
+
+    /**
+     * render a feature style in the amend feature dialog box
+     */
+    public void updateColor(Object newcol)
+    {
+
+      Color bg, col = null;
+      GraduatedColor gcol = null;
+      String vlabel = "";
+      if (newcol instanceof Color)
+      {
+        isGcol = false;
+        col = (Color) newcol;
+        gcol = null;
+      }
+      else if (newcol instanceof GraduatedColor)
+      {
+        isGcol = true;
+        gcol = (GraduatedColor) newcol;
+        col = null;
+      }
+      else
+      {
+        throw new Error(
+                MessageManager
+                        .getString("error.invalid_colour_for_mycheckbox"));
+      }
+      if (col != null)
+      {
+        setBackground(bg = col);
+      }
+      else
+      {
+        if (gcol.getThreshType() != AnnotationColourGradient.NO_THRESHOLD)
+        {
+          vlabel += " "
+                  + ((gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD) ? "(>)"
+                          : "(<)");
+        }
+        if (isColourByLabel = gcol.isColourByLabel())
+        {
+          setBackground(bg = Color.white);
+          vlabel += " (by Label)";
+        }
+        else
+        {
+          setBackground(bg = gcol.getMinColor());
+          maxCol = gcol.getMaxColor();
+        }
+      }
+      label = vlabel;
+      setBackground(bg);
+      repaint();
+    }
+
+    FeatureColourPanel()
+    {
+      super(null);
+    }
+
+    public void paint(Graphics g)
+    {
+      Dimension d = getSize();
+      if (isGcol)
+      {
+        if (isColourByLabel)
+        {
+          g.setColor(Color.white);
+          g.fillRect(d.width / 2, 0, d.width / 2, d.height);
+          g.setColor(Color.black);
+          Font f = new Font("Verdana", Font.PLAIN, 10);
+          g.setFont(f);
+          g.drawString(MessageManager.getString("label.label"), 0, 0);
+        }
+        else
+        {
+          g.setColor(maxCol);
+          g.fillRect(d.width / 2, 0, d.width / 2, d.height);
+
+        }
+      }
+    }
+
+  }
+
   boolean amendFeatures(final SequenceI[] sequences,
-                        final SequenceFeature[] features,
-                        boolean newFeatures,
-                        final AlignmentPanel ap)
+          final SequenceFeature[] features, boolean newFeatures,
+          final AlignmentPanel ap)
   {
     Panel bigPanel = new Panel(new BorderLayout());
     final TextField name = new TextField(16);
@@ -107,75 +193,74 @@ public class FeatureRenderer
     Button deleteButton = new Button("Delete");
     deleteFeature = false;
 
-    colourPanel = new Panel(null);
-    colourPanel.setSize(110,15);
+    colourPanel = new FeatureColourPanel();
+    colourPanel.setSize(110, 15);
     final FeatureRenderer fr = this;
 
     Panel panel = new Panel(new GridLayout(3, 1));
 
+    featureIndex = 0; // feature to be amended.
     Panel tmp;
 
-    ///////////////////////////////////////
-    ///MULTIPLE FEATURES AT SELECTED RESIDUE
-    if(!newFeatures && features.length>1)
+    // /////////////////////////////////////
+    // /MULTIPLE FEATURES AT SELECTED RESIDUE
+    if (!newFeatures && features.length > 1)
     {
-     panel = new Panel(new GridLayout(4, 1));
-     tmp = new Panel();
-     tmp.add(new Label("Select Feature: "));
-     overlaps = new Choice();
-     for(int i=0; i<features.length; i++)
-     {
-       String item = features[i].getType()
-        +"/"+features[i].getBegin()+"-"+features[i].getEnd();
-
-       if(features[i].getFeatureGroup()!=null)
-         item += " ("+features[i].getFeatureGroup()+")";
-
-       overlaps.addItem(item);
-     }
-
-     tmp.add(overlaps);
-
-     overlaps.addItemListener(new java.awt.event.ItemListener()
-     {
-       public void itemStateChanged(java.awt.event.ItemEvent e)
-       {
-         int index = overlaps.getSelectedIndex();
-         if (index != -1)
-         {
-           featureIndex = index;
-           name.setText(features[index].getType());
-           description.setText(features[index].getDescription());
-           source.setText(features[index].getFeatureGroup());
-           start.setText(features[index].getBegin()+"");
-           end.setText(features[index].getEnd()+"");
-
-           SearchResults highlight = new SearchResults();
-           highlight.addResult(sequences[0],
-                               features[index].getBegin(),
-                               features[index].getEnd());
-
-           ap.seqPanel.seqCanvas.highlightSearchResults(highlight);
-
-         }
-         Color col = getColour(name.getText());
-         if (col == null)
-         {
-           col = new
-               jalview.schemes.UserColourScheme()
-               .createColourFromName(name.getText());
-         }
-
-         colourPanel.setBackground(col);
-       }
-     });
-
-
-     panel.add(tmp);
-    }
-    //////////
-    //////////////////////////////////////
+      panel = new Panel(new GridLayout(4, 1));
+      tmp = new Panel();
+      tmp.add(new Label("Select Feature: "));
+      overlaps = new Choice();
+      for (int i = 0; i < features.length; i++)
+      {
+        String item = features[i].getType() + "/" + features[i].getBegin()
+                + "-" + features[i].getEnd();
+
+        if (features[i].getFeatureGroup() != null)
+        {
+          item += " (" + features[i].getFeatureGroup() + ")";
+        }
 
+        overlaps.addItem(item);
+      }
+
+      tmp.add(overlaps);
+
+      overlaps.addItemListener(new java.awt.event.ItemListener()
+      {
+        public void itemStateChanged(java.awt.event.ItemEvent e)
+        {
+          int index = overlaps.getSelectedIndex();
+          if (index != -1)
+          {
+            featureIndex = index;
+            name.setText(features[index].getType());
+            description.setText(features[index].getDescription());
+            source.setText(features[index].getFeatureGroup());
+            start.setText(features[index].getBegin() + "");
+            end.setText(features[index].getEnd() + "");
+
+            SearchResults highlight = new SearchResults();
+            highlight.addResult(sequences[0], features[index].getBegin(),
+                    features[index].getEnd());
+
+            ap.seqPanel.seqCanvas.highlightSearchResults(highlight);
+
+          }
+          Object col = getFeatureStyle(name.getText());
+          if (col == null)
+          {
+            col = new jalview.schemes.UserColourScheme()
+                    .createColourFromName(name.getText());
+          }
+
+          colourPanel.updateColor(col);
+        }
+      });
+
+      panel.add(tmp);
+    }
+    // ////////
+    // ////////////////////////////////////
 
     tmp = new Panel();
     panel.add(tmp);
@@ -184,7 +269,7 @@ public class FeatureRenderer
 
     tmp = new Panel();
     panel.add(tmp);
-    tmp.add(new Label("Group: ",Label.RIGHT));
+    tmp.add(new Label("Group: ", Label.RIGHT));
     tmp.add(source);
 
     tmp = new Panel();
@@ -238,101 +323,111 @@ public class FeatureRenderer
       }
     }
 
+    String title = newFeatures ? MessageManager
+            .getString("label.create_new_sequence_features")
+            : MessageManager.formatMessage("label.amend_delete_features",
+                    new String[] { sequences[0].getName() });
 
-    String title = newFeatures ? "Create New Sequence Feature(s)" :
-        "Amend/Delete Features for "
-        + sequences[0].getName();
-
-    final JVDialog dialog = new JVDialog(ap.alignFrame,
-                               title,
-                               true,
-                               385,240);
+    final JVDialog dialog = new JVDialog(ap.alignFrame, title, true, 385,
+            240);
 
     dialog.setMainPanel(bigPanel);
 
-    if(newFeatures)
+    if (newFeatures)
     {
       name.setText(lastFeatureAdded);
       source.setText(lastFeatureGroupAdded);
     }
     else
     {
-      dialog.ok.setLabel("Amend");
+      dialog.ok.setLabel(MessageManager.getString("label.amend"));
       dialog.buttonPanel.add(deleteButton, 1);
       deleteButton.addActionListener(new ActionListener()
-          {
-            public void actionPerformed(ActionEvent evt)
-            {
-              deleteFeature = true;
-              dialog.setVisible(false);
-            }
-          });
+      {
+        public void actionPerformed(ActionEvent evt)
+        {
+          deleteFeature = true;
+          dialog.setVisible(false);
+        }
+      });
       name.setText(features[0].getType());
       source.setText(features[0].getFeatureGroup());
     }
 
-    start.setText(features[0].getBegin()+"");
-    end.setText(features[0].getEnd()+"");
+    start.setText(features[0].getBegin() + "");
+    end.setText(features[0].getEnd() + "");
     description.setText(features[0].getDescription());
-
     Color col = getColour(name.getText());
     if (col == null)
     {
-      col = new
-          jalview.schemes.UserColourScheme()
-          .createColourFromName(name.getText());
+      col = new jalview.schemes.UserColourScheme()
+              .createColourFromName(name.getText());
     }
-
-    colourPanel.setBackground(col);
-
+    Object fcol = getFeatureStyle(name.getText());
+    // simply display the feature color in a box
+    colourPanel.updateColor(fcol);
     dialog.setResizable(true);
-
-
+    // TODO: render the graduated color in the box.
     colourPanel.addMouseListener(new java.awt.event.MouseAdapter()
     {
       public void mousePressed(java.awt.event.MouseEvent evt)
       {
-        new UserDefinedColours(fr, ap.alignFrame);
+        if (!colourPanel.isGcol)
+        {
+          new UserDefinedColours(fr, ap.alignFrame);
+        }
+        else
+        {
+          FeatureColourChooser fcc = new FeatureColourChooser(
+                  ap.alignFrame, name.getText());
+          dialog.transferFocus();
+        }
       }
     });
-
     dialog.setVisible(true);
 
     jalview.io.FeaturesFile ffile = new jalview.io.FeaturesFile();
 
     if (dialog.accept)
     {
-      //This ensures that the last sequence
-      //is refreshed and new features are rendered
+      // This ensures that the last sequence
+      // is refreshed and new features are rendered
       lastSeq = null;
       lastFeatureAdded = name.getText().trim();
       lastFeatureGroupAdded = source.getText().trim();
       lastDescriptionAdded = description.getText().replace('\n', ' ');
     }
 
-    if(lastFeatureGroupAdded !=null && lastFeatureGroupAdded.length()<1)
+    if (lastFeatureGroupAdded != null && lastFeatureGroupAdded.length() < 1)
+    {
       lastFeatureGroupAdded = null;
-
+    }
 
     if (!newFeatures)
     {
-      SequenceFeature sf = features[featureIndex];
 
+      SequenceFeature sf = features[featureIndex];
       if (dialog.accept)
       {
         sf.type = lastFeatureAdded;
         sf.featureGroup = lastFeatureGroupAdded;
         sf.description = lastDescriptionAdded;
-        setColour(sf.type, colourPanel.getBackground());
+        if (!colourPanel.isGcol)
+        {
+          // update colour - otherwise its already done.
+          setColour(sf.type, colourPanel.getBackground());
+        }
         try
         {
           sf.begin = Integer.parseInt(start.getText());
-          sf.end =  Integer.parseInt(end.getText());
+          sf.end = Integer.parseInt(end.getText());
+        } catch (NumberFormatException ex)
+        {
         }
-        catch (NumberFormatException ex)
-        {}
 
         ffile.parseDescriptionHTML(sf, false);
+        setVisible(lastFeatureAdded); // if user edited name then make sure new
+                                      // type is visible
       }
       if (deleteFeature)
       {
@@ -342,7 +437,7 @@ public class FeatureRenderer
     }
     else
     {
-      if (dialog.accept && name.getText().length()>0)
+      if (dialog.accept && name.getText().length() > 0)
       {
         for (int i = 0; i < sequences.length; i++)
         {
@@ -353,623 +448,33 @@ public class FeatureRenderer
           ffile.parseDescriptionHTML(features[i], false);
         }
 
-        if (av.featuresDisplayed == null)
-        {
-          av.featuresDisplayed = new Hashtable();
-        }
-
-        if (featureGroups == null)
-        {
-          featureGroups = new Hashtable();
-        }
-
-        col = colourPanel.getBackground();
-        setColour(lastFeatureAdded, col);
+        Color newColour = colourPanel.getBackground();
+        // setColour(lastFeatureAdded, fcol);
 
-        if(lastFeatureGroupAdded!=null)
+        if (lastFeatureGroupAdded != null)
         {
-          featureGroups.put(lastFeatureGroupAdded, new Boolean(true));
-          av.featuresDisplayed.put(lastFeatureGroupAdded,
-                                   new Integer(col.getRGB()));
+          setGroupVisibility(lastFeatureGroupAdded, true);
         }
-        findAllFeatures();
-
-        String [] tro = new String[renderOrder.length];
-        tro[0] = renderOrder[renderOrder.length-1];
-        System.arraycopy(renderOrder,0,tro,1,renderOrder.length-1);
-        renderOrder = tro;
-
-        ap.paintAlignment(true);
-
-        return true;
+        setColour(lastFeatureAdded, newColour); // was fcol
+        setVisible(lastFeatureAdded);
+        findAllFeatures(false); // different to original applet behaviour ?
+        // findAllFeatures();
       }
       else
       {
+        // no update to the alignment
         return false;
       }
     }
-
-    findAllFeatures();
-
-    ap.paintAlignment(true);
-
-    return true;
-  }
-
-
-  public Color findFeatureColour(Color initialCol, SequenceI seq, int i)
-  {
-    overview = true;
-    if (!av.showSequenceFeatures)
-    {
-      return initialCol;
-    }
-
-    lastSeq = seq;
-    sequenceFeatures = lastSeq.getSequenceFeatures();
-    if (sequenceFeatures == null)
-    {
-      return initialCol;
-    }
-
-    sfSize = sequenceFeatures.length;
-
-    if (jalview.util.Comparison.isGap(lastSeq.getCharAt(i)))
-    {
-      return Color.white;
-    }
-
-    currentColour = null;
-
-    drawSequence(null, lastSeq, lastSeq.findPosition(i), -1, -1);
-
-    if (currentColour == null)
-    {
-      return initialCol;
-    }
-
-    return new Color( ( (Integer) currentColour).intValue());
-  }
-
-  /**
-   * This is used by the Molecule Viewer to get the accurate colour
-   * of the rendered sequence
-   */
-  boolean overview = false;
-
-
-  /**
-   * DOCUMENT ME!
-   *
-   * @param g DOCUMENT ME!
-   * @param seq DOCUMENT ME!
-   * @param sg DOCUMENT ME!
-   * @param start DOCUMENT ME!
-   * @param end DOCUMENT ME!
-   * @param x1 DOCUMENT ME!
-   * @param y1 DOCUMENT ME!
-   * @param width DOCUMENT ME!
-   * @param height DOCUMENT ME!
-   */
-  // String type;
-  // SequenceFeature sf;
-
-  SequenceI lastSeq;
-  SequenceFeature[] sequenceFeatures;
-  int sfSize, sfindex, spos, epos;
-
-  synchronized public void drawSequence(Graphics g, SequenceI seq,
-                           int start, int end, int y1)
-  {
-    if (seq.getSequenceFeatures() == null
-        || seq.getSequenceFeatures().length == 0)
-    {
-      return;
-    }
-
-    if (transparencySetter != null && g != null)
-    {
-      transparencySetter.setTransparency(g, transparency);
-    }
-
-    if (lastSeq == null || seq != lastSeq || sequenceFeatures!=seq.getSequenceFeatures())
-    {
-      lastSeq = seq;
-      sequenceFeatures = seq.getSequenceFeatures();
-      sfSize = sequenceFeatures.length;
-    }
-
-    if (av.featuresDisplayed == null || renderOrder == null)
-    {
-      findAllFeatures();
-      if (av.featuresDisplayed.size() < 1)
-      {
-        return;
-      }
-
-      sequenceFeatures = seq.getSequenceFeatures();
-      sfSize = sequenceFeatures.length;
-    }
-    if (!overview)
-    {
-      spos = lastSeq.findPosition(start);
-      epos = lastSeq.findPosition(end);
-      if (g != null)
-      {
-        fm = g.getFontMetrics();
-      }
-    }
-    String type;
-    for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++)
-    {
-      type = renderOrder[renderIndex];
-      if (!av.featuresDisplayed.containsKey(type))
-      {
-        continue;
-      }
-
-      // loop through all features in sequence to find
-      // current feature to render
-      for (sfindex = 0; sfindex < sfSize; sfindex++)
-      {
-        if (!sequenceFeatures[sfindex].type.equals(type))
-        {
-          continue;
-        }
-
-        if (featureGroups != null
-            && sequenceFeatures[sfindex].featureGroup != null
-            &&
-            featureGroups.containsKey(sequenceFeatures[sfindex].featureGroup)
-            &&
-            ! ( (Boolean) featureGroups.get(sequenceFeatures[sfindex].
-                                            featureGroup)).
-            booleanValue())
-        {
-          continue;
-        }
-
-        if (!overview && (sequenceFeatures[sfindex].getBegin() > epos
-                          || sequenceFeatures[sfindex].getEnd() < spos))
-        {
-          continue;
-        }
-
-        if (overview)
-        {
-          if (sequenceFeatures[sfindex].begin <= start &&
-              sequenceFeatures[sfindex].end >= start)
-          {
-            currentColour = av.featuresDisplayed.get(sequenceFeatures[sfindex].
-                type);
-          }
-
-        }
-        else if (sequenceFeatures[sfindex].type.equals("disulfide bond"))
-        {
-
-          renderFeature(g, seq,
-                        seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
-                        seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
-                        new Color( ( (Integer) av.featuresDisplayed.get(
-                            sequenceFeatures[sfindex].type)).intValue()),
-                        start, end, y1);
-          renderFeature(g, seq,
-                        seq.findIndex(sequenceFeatures[sfindex].end) - 1,
-                        seq.findIndex(sequenceFeatures[sfindex].end) - 1,
-                        new Color( ( (Integer) av.featuresDisplayed.get(
-                            sequenceFeatures[sfindex].type)).intValue()),
-                        start, end, y1);
-
-        }
-        else
-        {
-          renderFeature(g, seq,
-                        seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
-                        seq.findIndex(sequenceFeatures[sfindex].end) - 1,
-                        getColour(sequenceFeatures[sfindex].type),
-                        start, end, y1);
-        }
-
-      }
-    }
-
-    if (transparencySetter != null && g != null)
+    // refresh the alignment and the feature settings dialog
+    if (((jalview.appletgui.AlignViewport) av).featureSettings != null)
     {
-      transparencySetter.setTransparency(g, 1.0f);
+      ((jalview.appletgui.AlignViewport) av).featureSettings.refreshTable();
     }
-  }
+    // findAllFeatures();
 
-  char s;
-  int i;
-  void renderFeature(Graphics g, SequenceI seq,
-                     int fstart, int fend, Color featureColour, int start,
-                     int end, int y1)
-  {
-
-    if ( ( (fstart <= end) && (fend >= start)))
-    {
-      if (fstart < start)
-      { // fix for if the feature we have starts before the sequence start,
-        fstart = start; // but the feature end is still valid!!
-      }
-
-      if (fend >= end)
-      {
-        fend = end;
-      }
-
-      for (i = fstart; i <= fend; i++)
-      {
-        s = seq.getCharAt(i);
-
-        if (jalview.util.Comparison.isGap(s))
-        {
-          continue;
-        }
-
-        g.setColor(featureColour);
-
-        g.fillRect( (i - start) * av.charWidth, y1, av.charWidth, av.charHeight);
-
-        if (!av.validCharWidth)
-        {
-          continue;
-        }
-
-        g.setColor(Color.white);
-        charOffset = (av.charWidth - fm.charWidth(s)) / 2;
-        g.drawString(String.valueOf(s),
-                     charOffset + (av.charWidth * (i - start)),
-                     (y1 + av.charHeight) - av.charHeight / 5); //pady = height / 5;
-
-      }
-    }
-  }
-
-  void findAllFeatures()
-  {
-    jalview.schemes.UserColourScheme ucs = new
-        jalview.schemes.UserColourScheme();
-
-    av.featuresDisplayed = new Hashtable();
-    Vector allfeatures = new Vector();
-    for (int i = 0; i < av.alignment.getHeight(); i++)
-    {
-      SequenceFeature[] features = av.alignment.getSequenceAt(i).
-          getSequenceFeatures();
-
-      if (features == null)
-      {
-        continue;
-      }
-
-      int index = 0;
-      while (index < features.length)
-      {
-        if (!av.featuresDisplayed.containsKey(features[index].getType()))
-        {
-          if (getColour(features[index].getType()) == null)
-          {
-            featureColours.put(features[index].getType(),
-                               ucs.createColourFromName(features[index].
-                getType()));
-          }
-
-          av.featuresDisplayed.put(features[index].getType(),
-                                   new Integer(getColour(features[index].
-              getType()).getRGB()));
-          allfeatures.addElement(features[index].getType());
-        }
-        index++;
-      }
-    }
-
-    renderOrder = new String[allfeatures.size()];
-    Enumeration en = allfeatures.elements();
-    int i = allfeatures.size() - 1;
-    while (en.hasMoreElements())
-    {
-      renderOrder[i] = en.nextElement().toString();
-      i--;
-    }
-  }
-
-  public Color getColour(String featureType)
-  {
-    if (!featureColours.containsKey(featureType))
-    {
-      jalview.schemes.UserColourScheme ucs = new
-          jalview.schemes.UserColourScheme();
-      Color col = ucs.createColourFromName(featureType);
-      featureColours.put(featureType, col);
-      return col;
-    }
-    else
-      return (Color) featureColours.get(featureType);
-  }
-
-
-  public void setColour(String featureType, Color col)
-  {
-    featureColours.put(featureType, col);
-  }
-
-  public void setFeaturePriority(Object[][] data)
-  {
-    // The feature table will display high priority
-    // features at the top, but theses are the ones
-    // we need to render last, so invert the data
-    if (av.featuresDisplayed != null)
-    {
-      av.featuresDisplayed.clear();
-    }
-
-   /* if (visibleNew)
-    {
-      if (av.featuresDisplayed != null)
-      {
-        av.featuresDisplayed.clear();
-      }
-      else
-      {
-        av.featuresDisplayed = new Hashtable();
-      }
-    }
-    if (data == null)
-    {
-      return;
-    }*/
-
-
-    renderOrder = new String[data.length];
-
-    if (data.length > 0)
-    {
-      for (int i = 0; i < data.length; i++)
-      {
-        String type = data[i][0].toString();
-        setColour(type, (Color) data[i][1]);
-        if ( ( (Boolean) data[i][2]).booleanValue())
-        {
-          av.featuresDisplayed.put(type, new Integer(getColour(type).getRGB()));
-        }
-
-        renderOrder[data.length - i - 1] = type;
-      }
-    }
-  }
-  /**
-   * @return a simple list of feature group names or null 
-   */
-  public String[] getGroups()
-  {
-    buildGroupHash();
-    if (featureGroups!=null)
-    {
-      String[] gps = new String[featureGroups.size()];
-      Enumeration gn = featureGroups.keys();
-      int i=0;
-      while (gn.hasMoreElements())
-      {
-        gps[i++]  = (String) gn.nextElement();
-      }
-      return gps;
-    }
-    return null;
-  }
-  /**
-   * get visible or invisible groups
-   * @param visible true to return visible groups, false to return hidden ones.
-   * @return list of groups
-   */
-  public String[] getGroups(boolean visible) 
-  {
-    buildGroupHash();
-    if (featureGroups!=null)
-    {
-      Vector gp = new Vector();
-      
-      Enumeration gn = featureGroups.keys();
-      while (gn.hasMoreElements())
-      {
-        String nm = (String) gn.nextElement();
-        Boolean state = (Boolean) featureGroups.get(nm);
-        if (state.booleanValue()==visible)
-        {
-          gp.addElement(nm);
-        }
-      }
-      String[] gps = new String[gp.size()];
-      gp.copyInto(gps);
-      
-      int i=0;
-      while (gn.hasMoreElements())
-      {
-        gps[i++]  = (String) gn.nextElement();
-      }
-      return gps;
-    }
-    return null;
-  }
-  /**
-   * set all feature groups in toset to be visible or invisible
-   * @param toset group names
-   * @param visible the state of the named groups to set
-   */
-  public void setGroupState(String[] toset, boolean visible)
-  {
-    buildGroupHash();
-    if (toset!=null && toset.length>0 && featureGroups!=null)
-    {
-      boolean rdrw = false;
-      for (int i=0;i<toset.length; i++)
-      {
-        Object st = featureGroups.get(toset[i]);
-        if (st!=null)
-        {
-          featureGroups.put(toset[i], new Boolean(visible));
-          rdrw = rdrw || (visible!=((Boolean) st).booleanValue());
-        }
-      }
-      if (rdrw)
-      {
-        if (this.av!=null)
-          if (this.av.featureSettings!=null)
-          {
-            av.featureSettings.rebuildGroups();
-            this.av.featureSettings.resetTable(true);
-          } else {
-            buildFeatureHash();
-          }
-          if (av!=null)
-          {
-            av.alignmentChanged(null);
-          }
-      }
-    }
-  }
-  /**
-   * analyse alignment for groups and hash tables
-   * (used to be embedded in FeatureSettings.setTableData)
-   * @return true if features are on the alignment
-   */
-  public boolean buildGroupHash()
-  {
-    boolean alignmentHasFeatures=false;
-    if (featureGroups == null)
-    {
-      featureGroups = new Hashtable();
-    }
-    Vector allFeatures = new Vector();
-    Vector allGroups = new Vector();
-    SequenceFeature[] tmpfeatures;
-    String group;
-    for (int i = 0; i < av.alignment.getHeight(); i++)
-    {
-      if (av.alignment.getSequenceAt(i).getSequenceFeatures() == null)
-      {
-        continue;
-      }
-
-      alignmentHasFeatures = true;
-
-      tmpfeatures = av.alignment.getSequenceAt(i).getSequenceFeatures();
-      int index = 0;
-      while (index < tmpfeatures.length)
-      {
-        if (tmpfeatures[index].getFeatureGroup() != null)
-        {
-          group = tmpfeatures[index].featureGroup;
-          if (!allGroups.contains(group))
-          {
-            allGroups.addElement(group);
-
-            boolean visible = true;
-            if (featureGroups.containsKey(group))
-            {
-              visible = ( (Boolean) featureGroups.get(group)).booleanValue();
-            } else {
-              featureGroups.put(group, new Boolean(visible));
-            }
-          }
-        }
-
-        if (!allFeatures.contains(tmpfeatures[index].getType()))
-        {
-          allFeatures.addElement(tmpfeatures[index].getType());
-        }
-        index++;
-      }
-    }
-    
-    return alignmentHasFeatures;
-  }
-  /**
-   * rebuild the featuresDisplayed and renderorder list based on the featureGroups hash and any existing display state
-   * and force a repaint if necessary
-   * @return true if alignment has visible features
-   */
-  public boolean buildFeatureHash() {
-    boolean alignmentHasFeatures=false;
-    if (featureGroups==null)
-    {
-      alignmentHasFeatures = buildGroupHash();
-    }
-    if (!alignmentHasFeatures)
-      return false;
-    Hashtable fdisp = av.featuresDisplayed;
-    Vector allFeatures = new Vector();
-    SequenceFeature[] tmpfeatures;
-    String group;
-    for (int i = 0; i < av.alignment.getHeight(); i++)
-    {
-      if (av.alignment.getSequenceAt(i).getSequenceFeatures() == null)
-      {
-        continue;
-      }
-
-      alignmentHasFeatures = true;
-
-      tmpfeatures = av.alignment.getSequenceAt(i).getSequenceFeatures();
-      int index = 0;
-      while (index < tmpfeatures.length)
-      {
-        boolean visible = true;
-        if (tmpfeatures[index].getFeatureGroup() != null)
-        {
-          group = tmpfeatures[index].featureGroup;
-          if (featureGroups.containsKey(group))
-          {
-            visible = ( (Boolean) featureGroups.get(group)).booleanValue();
-          }
-        }
-        
-        if (visible && !allFeatures.contains(tmpfeatures[index].getType()))
-        {
-          allFeatures.addElement(tmpfeatures[index].getType());
-        }
-        index++;
-      }
-    }
-    if (allFeatures.size()>0)
-    {
-      String[] neworder = new String[allFeatures.size()];
-      int p=neworder.length-1;
-      for (int i=renderOrder.length-1; i>=0; i--)
-      {
-        if (allFeatures.contains(renderOrder[i]))
-        {
-          neworder[p--] = renderOrder[i];
-          allFeatures.removeElement(renderOrder[i]);
-        } else {
-          av.featuresDisplayed.remove(renderOrder[i]);
-        }
-      }
-      for (int i=allFeatures.size()-1; i>0; i++)
-      {
-        Object e = allFeatures.elementAt(i);
-        if (e!=null)
-        {
-          neworder[p--] = (String) e;
-          av.featuresDisplayed.put(e, getColour((String)e));
-        }
-      }
-      renderOrder = neworder;
-      return true;
-    }
-    
-    return alignmentHasFeatures;
-  }
-}
+    ap.paintAlignment(true);
 
-class TransparencySetter
-{
-  void setTransparency(Graphics g, float value)
-  {
-     Graphics2D g2 = (Graphics2D) g;
-     g2.setComposite(
-        AlphaComposite.getInstance(
-             AlphaComposite.SRC_OVER, value));
+    return true;
   }
 }