JAL-1482 feature renderer and manipulation code refactored to renderer and abstract...
authorj.procter@dundee.ac.uk <jprocter@Jims-MacBook-Pro-2.local>
Fri, 8 Aug 2014 17:11:21 +0000 (18:11 +0100)
committerj.procter@dundee.ac.uk <jprocter@Jims-MacBook-Pro-2.local>
Fri, 8 Aug 2014 17:12:32 +0000 (18:12 +0100)
25 files changed:
src/jalview/appletgui/APopupMenu.java
src/jalview/appletgui/AlignFrame.java
src/jalview/appletgui/FeatureColourChooser.java
src/jalview/appletgui/FeatureRenderer.java
src/jalview/appletgui/FeatureSettings.java
src/jalview/appletgui/OverviewPanel.java
src/jalview/appletgui/SeqPanel.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/AnnotationExporter.java
src/jalview/gui/FeatureColourChooser.java
src/jalview/gui/FeatureRenderer.java
src/jalview/gui/FeatureSettings.java
src/jalview/gui/IdPanel.java
src/jalview/gui/Jalview2XML.java
src/jalview/gui/Jalview2XML_V1.java
src/jalview/gui/OverviewPanel.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/SeqPanel.java
src/jalview/io/FeaturesFile.java
src/jalview/io/HTMLOutput.java
src/jalview/io/SequenceAnnotationReport.java
src/jalview/renderer/seqfeatures/FeatureRenderer.java [new file with mode: 0644]
src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java
src/jalview/ws/AWSThread.java

index 7a77935..51ecd88 100644 (file)
@@ -707,7 +707,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
                       true,
                       true,
                       false,
-                      (ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr.minmax
+                      (ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr.getMinMax()
                               : null);
       contents.append("</p>");
     }
index e0dad58..8d1255c 100644 (file)
@@ -25,6 +25,7 @@ import jalview.analysis.Conservation;
 import jalview.api.AlignViewControllerGuiI;
 import jalview.api.AlignViewControllerI;
 import jalview.api.SequenceStructureBinding;
+import jalview.api.FeatureRenderer;
 import jalview.bin.JalviewLite;
 import jalview.commands.CommandI;
 import jalview.commands.EditCommand;
@@ -90,9 +91,12 @@ import java.awt.event.WindowEvent;
 import java.io.IOException;
 import java.net.URL;
 import java.net.URLEncoder;
+import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.StringTokenizer;
 import java.util.Vector;
 
@@ -286,7 +290,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     {
       featuresFile = new jalview.io.FeaturesFile(file, type)
               .parse(viewport.getAlignment(), alignPanel.seqPanel.seqCanvas
-                      .getFeatureRenderer().featureColours, featureLinks,
+                      .getFeatureRenderer().getFeatureColours(), featureLinks,
                       true, viewport.applet.getDefaultParameter(
                               "relaxedidmatch", false));
     } catch (Exception ex)
@@ -305,6 +309,11 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
         viewport.setShowSequenceFeatures(true);
         sequenceFeatures.setState(true);
       }
+      if (alignPanel.seqPanel.seqCanvas.fr != null)
+      {
+        // update the min/max ranges where necessary
+        alignPanel.seqPanel.seqCanvas.fr.findAllFeatures(true);
+      }
       if (viewport.featureSettings != null)
       {
         viewport.featureSettings.refreshTable();
@@ -1201,20 +1210,13 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     return annotation;
   }
 
-  private Hashtable getDisplayedFeatureCols()
+  private Map<String,Object> getDisplayedFeatureCols()
   {
     if (alignPanel.getFeatureRenderer() != null
-            && viewport.featuresDisplayed != null)
+            && viewport.getFeaturesDisplayed()!= null)
     {
-      FeatureRenderer fr = alignPanel.getFeatureRenderer();
-      Hashtable fcols = new Hashtable();
-      Enumeration en = viewport.featuresDisplayed.keys();
-      while (en.hasMoreElements())
-      {
-        Object col = en.nextElement();
-        fcols.put(col, fr.featureColours.get(col));
-      }
-      return fcols;
+      return alignPanel.getFeatureRenderer().getDisplayedFeatureCols();
+      
     }
     return null;
   }
@@ -1418,6 +1420,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
   /**
    * TODO: JAL-1104
    */
+  @Override
   public void addHistoryItem(CommandI command)
   {
     if (command.getSize() > 0)
@@ -2240,7 +2243,14 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     if (alignPanel != null
             && (fr = alignPanel.getFeatureRenderer()) != null)
     {
-      return fr.getGroups();
+      List gps = fr.getFeatureGroups();
+      int p=0;
+      String[] _gps = new String[gps.size()];
+      for (Object gp:gps)
+      {
+        _gps[p++] = gp.toString();
+      }
+      return _gps;
     }
     return null;
   }
@@ -2258,7 +2268,14 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     if (alignPanel != null
             && (fr = alignPanel.getFeatureRenderer()) != null)
     {
-      return fr.getGroups(visible);
+      List gps = fr.getGroups(visible);
+      int p=0;
+      String[] _gps = new String[gps.size()];
+      for (Object gp:gps)
+      {
+        _gps[p++] = gp.toString();
+      }
+      return _gps;
     }
     return null;
   }
@@ -2279,7 +2296,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     if (alignPanel != null
             && (fr = alignPanel.getFeatureRenderer()) != null)
     {
-      fr.setGroupState(groups, state);
+      
+      fr.setGroupVisibility((List)Arrays.asList(groups), state);
       alignPanel.seqPanel.seqCanvas.repaint();
       if (alignPanel.overviewPanel != null)
       {
index 32ffdbf..c87803c 100644 (file)
@@ -73,10 +73,10 @@ public class FeatureColourChooser extends Panel implements ActionListener,
   {
     this.type = type;
     fr = frenderer;
-    float mm[] = ((float[][]) fr.minmax.get(type))[0];
+    float mm[] = ((float[][]) fr.getMinMax().get(type))[0];
     min = mm[0];
     max = mm[1];
-    oldcs = fr.featureColours.get(type);
+    oldcs = fr.getFeatureColours().get(type);
     if (oldcs instanceof GraduatedColor)
     {
       cs = new GraduatedColor((GraduatedColor) oldcs, min, max);
@@ -130,7 +130,7 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     {
       // cancel
       reset();
-      PaintRefresher.Refresh(this, fr.av.getSequenceSetId());
+      PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId());
       frame.setVisible(false);
     }
   }
@@ -289,7 +289,7 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     threshline.value = (float) slider.getValue() / 1000f;
     cs.setThresh(threshline.value);
     changeColour();
-    PaintRefresher.Refresh(this, fr.av.getSequenceSetId());
+    PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId());
     // ap.paintAlignment(false);
   }
 
@@ -402,16 +402,16 @@ public class FeatureColourChooser extends Panel implements ActionListener,
       }
     }
 
-    fr.featureColours.put(type, acg);
+    fr.setColour(type, acg);
     cs = acg;
-    PaintRefresher.Refresh(this, fr.av.getSequenceSetId());
+    PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId());
     // ap.paintAlignment(false);
   }
 
   void reset()
   {
-    fr.featureColours.put(type, oldcs);
-    PaintRefresher.Refresh(this, fr.av.getSequenceSetId());
+    fr.setColour(type, oldcs);
+    PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId());
     // ap.paintAlignment(true);
 
   }
@@ -433,7 +433,7 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     }
     else
     {
-      PaintRefresher.Refresh(this, fr.av.getSequenceSetId());
+      PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId());
     }
     // ap.paintAlignment(true);
   }
index 14338fa..ac1f58c 100644 (file)
 package jalview.appletgui;
 
 import java.util.*;
-
 import java.awt.*;
-
 import java.awt.event.*;
 
 import jalview.datamodel.*;
 import jalview.schemes.AnnotationColourGradient;
 import jalview.schemes.GraduatedColor;
 import jalview.util.MessageManager;
+import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
 
 /**
  * DOCUMENT ME!
@@ -37,34 +36,13 @@ import jalview.util.MessageManager;
  * @author $author$
  * @version $Revision$
  */
-public class FeatureRenderer implements jalview.api.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.
    * 
@@ -73,49 +51,10 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
    */
   public FeatureRenderer(AlignViewport av)
   {
+    super();
     this.av = av;
 
-    if (!System.getProperty("java.version").startsWith("1.1"))
-    {
-      transparencySetter = new TransparencySetter();
-    }
-  }
-
-  public void transferSettings(jalview.api.FeatureRenderer _fr)
-  {
-    if (_fr instanceof FeatureRenderer)
-    {
-      FeatureRenderer fr = (FeatureRenderer) _fr;
-      renderOrder = fr.renderOrder;
-      featureGroups = fr.featureGroups;
-      featureColours = fr.featureColours;
-      transparency = fr.transparency;
-      if (av != null && fr.av != null && fr.av != av)
-      {
-        if (fr.av.featuresDisplayed != null)
-        {
-          if (av.featuresDisplayed == null)
-          {
-            av.featuresDisplayed = new Hashtable();
-          }
-          else
-          {
-            av.featuresDisplayed.clear();
-          }
-          Enumeration en = fr.av.featuresDisplayed.keys();
-          while (en.hasMoreElements())
-          {
-            av.featuresDisplayed.put(en.nextElement(), Boolean.TRUE);
-          }
-        }
-      }
-    }
-    else
-    {
-      throw new Error(
-              "Implementation error: cannot port feature settings from implementation of type "
-                      + _fr.getClass() + " to " + getClass());
-    }
+    setTransparencyAvailable(!System.getProperty("java.version").startsWith("1.1"));
   }
 
   static String lastFeatureAdded;
@@ -462,6 +401,7 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
         }
 
         ffile.parseDescriptionHTML(sf, false);
+        setVisible(lastFeatureAdded); // if user edited name then make sure new type is visible
       }
       if (deleteFeature)
       {
@@ -482,36 +422,17 @@ public class FeatureRenderer implements jalview.api.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, fcol);
 
         if (lastFeatureGroupAdded != null)
         {
-          featureGroups.put(lastFeatureGroupAdded, new Boolean(true));
-        }
-        if (fcol instanceof Color)
-        {
-          setColour(lastFeatureAdded, fcol);
+          setGroupVisibility(lastFeatureGroupAdded, true);
         }
-        av.featuresDisplayed.put(lastFeatureAdded,
-                getFeatureStyle(lastFeatureAdded));
-
-        findAllFeatures();
-
-        String[] tro = new String[renderOrder.length];
-        tro[0] = renderOrder[renderOrder.length - 1];
-        System.arraycopy(renderOrder, 0, tro, 1, renderOrder.length - 1);
-        renderOrder = tro;
+        setColour(lastFeatureAdded, fcol);
+        setVisible(lastFeatureAdded);
+        findAllFeatures(false); // different to original applet behaviour ? 
+        // findAllFeatures();
       }
       else
       {
@@ -520,9 +441,9 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
       }
     }
     // refresh the alignment and the feature settings dialog
-    if (av.featureSettings != null)
+    if (((jalview.appletgui.AlignViewport) av).featureSettings != null)
     {
-      av.featureSettings.refreshTable();
+      ((jalview.appletgui.AlignViewport) av).featureSettings.refreshTable();
     }
     // findAllFeatures();
 
@@ -530,760 +451,4 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer
 
     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 = new Integer(
-                    getColour(sequenceFeatures[sfindex]).getRGB());// 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,
-                  getColour(sequenceFeatures[sfindex])
-                  // 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,
-                  getColour(sequenceFeatures[sfindex])
-                  // new Color(((Integer) av.featuresDisplayed
-                  // .get(sequenceFeatures[sfindex].type)).intValue())
-                  , start, end, y1);
-
-        }
-        else
-        {
-          if (showFeature(sequenceFeatures[sfindex]))
-          {
-            renderFeature(g, seq,
-                    seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
-                    seq.findIndex(sequenceFeatures[sfindex].end) - 1,
-                    getColour(sequenceFeatures[sfindex]), start, end, y1);
-          }
-        }
-
-      }
-    }
-
-    if (transparencySetter != null && g != null)
-    {
-      transparencySetter.setTransparency(g, 1.0f);
-    }
-  }
-
-  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;
-
-      }
-    }
-  }
-
-  Hashtable minmax = null;
-
-  /**
-   * Called when alignment in associated view has new/modified features to
-   * discover and display.
-   * 
-   */
-  public void featuresAdded()
-  {
-    lastSeq = null;
-    findAllFeatures();
-  }
-
-  /**
-   * find all features on the alignment
-   */
-  void findAllFeatures()
-  {
-    jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
-
-    av.featuresDisplayed = new Hashtable();
-    Vector allfeatures = new Vector();
-    minmax = new Hashtable();
-    AlignmentI alignment = av.getAlignment();
-    for (int i = 0; i < alignment.getHeight(); i++)
-    {
-      SequenceFeature[] features = alignment.getSequenceAt(i)
-              .getSequenceFeatures();
-
-      if (features == null)
-      {
-        continue;
-      }
-
-      int index = 0;
-      while (index < features.length)
-      {
-        if (features[index].begin == 0 && features[index].end == 0)
-        {
-          index++;
-          continue;
-        }
-        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());
-        }
-        if (features[index].score != Float.NaN)
-        {
-          int nonpos = features[index].getBegin() >= 1 ? 0 : 1;
-          float[][] mm = (float[][]) minmax.get(features[index].getType());
-          if (mm == null)
-          {
-            mm = new float[][]
-            { null, null };
-            minmax.put(features[index].getType(), mm);
-          }
-          if (mm[nonpos] == null)
-          {
-            mm[nonpos] = new float[]
-            { features[index].score, features[index].score };
-
-          }
-          else
-          {
-            if (mm[nonpos][0] > features[index].score)
-            {
-              mm[nonpos][0] = features[index].score;
-            }
-            if (mm[nonpos][1] < features[index].score)
-            {
-              mm[nonpos][1] = features[index].score;
-            }
-          }
-        }
-
-        index++;
-      }
-    }
-
-    renderOrder = new String[allfeatures.size()];
-    Enumeration en = allfeatures.elements();
-    int i = allfeatures.size() - 1;
-    while (en.hasMoreElements())
-    {
-      renderOrder[i] = en.nextElement().toString();
-      i--;
-    }
-  }
-
-  /**
-   * get a feature style object for the given type string. Creates a
-   * java.awt.Color for a featureType with no existing colourscheme. TODO:
-   * replace return type with object implementing standard abstract colour/style
-   * interface
-   * 
-   * @param featureType
-   * @return java.awt.Color or GraduatedColor
-   */
-  public Object getFeatureStyle(String featureType)
-  {
-    Object fc = featureColours.get(featureType);
-    if (fc == null)
-    {
-      jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
-      Color col = ucs.createColourFromName(featureType);
-      featureColours.put(featureType, fc = col);
-    }
-    return fc;
-  }
-
-  public Color getColour(String featureType)
-  {
-    Object fc = getFeatureStyle(featureType);
-
-    if (fc instanceof Color)
-    {
-      return (Color) fc;
-    }
-    else
-    {
-      if (fc instanceof GraduatedColor)
-      {
-        return ((GraduatedColor) fc).getMaxColor();
-      }
-    }
-    throw new Error("Implementation Error: Unrecognised render object "
-            + fc.getClass() + " for features of type " + featureType);
-  }
-
-  /**
-   * 
-   * @param sequenceFeature
-   * @return true if feature is visible.
-   */
-  private boolean showFeature(SequenceFeature sequenceFeature)
-  {
-    Object fc = getFeatureStyle(sequenceFeature.type);
-    if (fc instanceof GraduatedColor)
-    {
-      return ((GraduatedColor) fc).isColored(sequenceFeature);
-    }
-    else
-    {
-      return true;
-    }
-  }
-
-  /**
-   * implement graduated colouring for features with scores
-   * 
-   * @param feature
-   * @return render colour for the given feature
-   */
-  public Color getColour(SequenceFeature feature)
-  {
-    Object fc = getFeatureStyle(feature.getType());
-    if (fc instanceof Color)
-    {
-      return (Color) fc;
-    }
-    else
-    {
-      if (fc instanceof GraduatedColor)
-      {
-        return ((GraduatedColor) fc).findColor(feature);
-      }
-    }
-    throw new Error("Implementation Error: Unrecognised render object "
-            + fc.getClass() + " for features of type " + feature.getType());
-  }
-
-  public void setColour(String featureType, Object col)
-  {
-    // overwrite
-    // Color _col = (col instanceof Color) ? ((Color) col) : (col instanceof
-    // GraduatedColor) ? ((GraduatedColor) col).getMaxColor() : null;
-    // Object c = featureColours.get(featureType);
-    // if (c == null || c instanceof Color || (c instanceof GraduatedColor &&
-    // !((GraduatedColor)c).getMaxColor().equals(_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, 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]);
-        featureGroups.put(toset[i], new Boolean(visible));
-        if (st != null)
-        {
-          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);
-        }
-      }
-    }
-  }
-
-  ArrayList<String> hiddenGroups = new ArrayList<String>();
-
-  /**
-   * 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();
-    }
-    hiddenGroups = new ArrayList<String>();
-    hiddenGroups.addAll(featureGroups.keySet());
-    ArrayList allFeatures = new ArrayList();
-    ArrayList allGroups = new ArrayList();
-    SequenceFeature[] tmpfeatures;
-    String group;
-    AlignmentI alignment = av.getAlignment();
-    for (int i = 0; i < alignment.getHeight(); i++)
-    {
-      if (alignment.getSequenceAt(i).getSequenceFeatures() == null)
-      {
-        continue;
-      }
-
-      alignmentHasFeatures = true;
-
-      tmpfeatures = alignment.getSequenceAt(i).getSequenceFeatures();
-      int index = 0;
-      while (index < tmpfeatures.length)
-      {
-        if (tmpfeatures[index].getFeatureGroup() != null)
-        {
-          group = tmpfeatures[index].featureGroup;
-          // Remove group from the hiddenGroup list
-          hiddenGroups.remove(group);
-          if (!allGroups.contains(group))
-          {
-            allGroups.add(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.add(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;
-    AlignmentI alignment = av.getAlignment();
-    for (int i = 0; i < alignment.getHeight(); i++)
-    {
-      if (alignment.getSequenceAt(i).getSequenceFeatures() == null)
-      {
-        continue;
-      }
-
-      alignmentHasFeatures = true;
-
-      tmpfeatures = 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;
-  }
-
-  /**
-   * 
-   * @return the displayed feature type as an array of strings
-   */
-  protected String[] getDisplayedFeatureTypes()
-  {
-    String[] typ = null;
-    synchronized (renderOrder)
-    {
-      typ = new String[renderOrder.length];
-      System.arraycopy(renderOrder, 0, typ, 0, typ.length);
-      for (int i = 0; i < typ.length; i++)
-      {
-        if (av.featuresDisplayed.get(typ[i]) == null)
-        {
-          typ[i] = null;
-        }
-      }
-    }
-    return typ;
-  }
-}
-
-class TransparencySetter
-{
-  void setTransparency(Graphics g, float value)
-  {
-    Graphics2D g2 = (Graphics2D) g;
-    g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
-            value));
-  }
 }
index f6e7772..bde68cc 100755 (executable)
@@ -21,7 +21,7 @@
 package jalview.appletgui;
 
 import java.util.*;
-
+import java.util.List;
 import java.awt.*;
 import java.awt.event.*;
 
@@ -50,8 +50,6 @@ public class FeatureSettings extends Panel implements ItemListener,
 
   ScrollPane scrollPane;
 
-  boolean alignmentHasFeatures = false;
-
   Image linkImage;
 
   Scrollbar transparency;
@@ -64,9 +62,9 @@ public class FeatureSettings extends Panel implements ItemListener,
     fr = ap.seqPanel.seqCanvas.getFeatureRenderer();
 
     transparency = new Scrollbar(Scrollbar.HORIZONTAL,
-            100 - (int) (fr.transparency * 100), 1, 1, 100);
+            100 - (int) (fr.getTransparency() * 100), 1, 1, 100);
 
-    if (fr.transparencySetter != null)
+    if (fr.isTransparencyAvailable())
     {
       transparency.addAdjustmentListener(this);
     }
@@ -81,9 +79,9 @@ public class FeatureSettings extends Panel implements ItemListener,
       linkImage = java.awt.Toolkit.getDefaultToolkit().getImage(url);
     }
 
-    if (av.featuresDisplayed == null)
+    if (av.isShowSequenceFeatures() || !fr.hasRenderOrder())
     {
-      fr.findAllFeatures();
+      fr.findAllFeatures(true); // was default - now true to make all visible
     }
 
     setTableData();
@@ -91,7 +89,7 @@ public class FeatureSettings extends Panel implements ItemListener,
     this.setLayout(new BorderLayout());
     scrollPane = new ScrollPane();
     scrollPane.add(featurePanel);
-    if (alignmentHasFeatures)
+    if (fr.getAllFeatureColours()!=null && fr.getAllFeatureColours().size()>0)
     {
       add(scrollPane, BorderLayout.CENTER);
     }
@@ -104,7 +102,7 @@ public class FeatureSettings extends Panel implements ItemListener,
 
     Panel tPanel = new Panel(new BorderLayout());
 
-    if (fr.transparencySetter != null)
+    if (fr.isTransparencyAvailable())
     {
       tPanel.add(transparency, BorderLayout.CENTER);
       tPanel.add(new Label("Transparency"), BorderLayout.EAST);
@@ -124,8 +122,8 @@ public class FeatureSettings extends Panel implements ItemListener,
     {
       groupPanel
               .setLayout(new GridLayout(
-                      (fr.featureGroups.size() - fr.hiddenGroups.size()) / 4 + 1,
-                      4));
+                      (fr.getFeatureGroupsSize()) / 4 + 1,
+                      4)); // JBPNote - this was scaled on number of visible groups. seems broken
       groupPanel.validate();
 
       add(groupPanel, BorderLayout.NORTH);
@@ -185,7 +183,7 @@ public class FeatureSettings extends Panel implements ItemListener,
 
       public void actionPerformed(ActionEvent e)
       {
-        me.sortByScore(new String[]
+        me.ap.alignFrame.avc.sortAlignmentByFeatureScore(new String[]
         { type });
       }
 
@@ -197,7 +195,7 @@ public class FeatureSettings extends Panel implements ItemListener,
 
       public void actionPerformed(ActionEvent e)
       {
-        me.sortByDens(new String[]
+        me.ap.alignFrame.avc.sortAlignmentByFeatureDensity(new String[]
         { type });
       }
 
@@ -253,8 +251,7 @@ public class FeatureSettings extends Panel implements ItemListener,
 
   public void setTableData()
   {
-    alignmentHasFeatures = fr.buildGroupHash();
-    if (alignmentHasFeatures)
+    if (fr.getAllFeatureColours()!=null && fr.getAllFeatureColours().size()>0)
     {
       rebuildGroups();
 
@@ -279,18 +276,17 @@ public class FeatureSettings extends Panel implements ItemListener,
     }
     // TODO: JAL-964 - smoothly incorporate new group entries if panel already
     // displayed and new groups present
-    Enumeration gps = fr.featureGroups.keys();
-    while (gps.hasMoreElements())
+    for (String group:(List<String>)fr.getFeatureGroups())
     {
-      String group = (String) gps.nextElement();
-      Boolean vis = (Boolean) fr.featureGroups.get(group);
-      Checkbox check = new MyCheckbox(group, vis.booleanValue(),
+      boolean vis = fr.checkGroupVisibility(group, false);
+      Checkbox check = new MyCheckbox(group, vis,
               (fr.featureLinks != null && fr.featureLinks
                       .containsKey(group)));
       check.addMouseListener(this);
       check.setFont(new Font("Serif", Font.BOLD, 12));
-      check.addItemListener(this);
-      check.setVisible(fr.hiddenGroups.contains(group));
+      check.addItemListener(groupItemListener);
+      // note - visibility seems to correlate with displayed. ???wtf ??
+      check.setVisible(vis);
       groupPanel.add(check);
     }
     if (rdrw)
@@ -298,7 +294,6 @@ public class FeatureSettings extends Panel implements ItemListener,
       groupPanel.validate();
     }
   }
-
   // This routine adds and removes checkboxes depending on
   // Group selection states
   void resetTable(boolean groupsChanged)
@@ -320,8 +315,7 @@ public class FeatureSettings extends Panel implements ItemListener,
       {
         group = tmpfeatures[index].featureGroup;
 
-        if (group == null || fr.featureGroups.get(group) == null
-                || ((Boolean) fr.featureGroups.get(group)).booleanValue())
+        if (group == null || fr.checkGroupVisibility(group, true))
         {
           type = tmpfeatures[index].getType();
           if (!visibleChecks.contains(type))
@@ -350,13 +344,14 @@ public class FeatureSettings extends Panel implements ItemListener,
       }
     }
 
-    if (fr.renderOrder != null)
+    if (fr.getRenderOrder() != 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--)
+      List<String> rol = fr.getRenderOrder();
+      for (int ro = rol.size() - 1; ro > -1; ro--)
       {
-        String item = fr.renderOrder[ro];
+        String item = rol.get(ro);
 
         if (!visibleChecks.contains(item))
         {
@@ -418,7 +413,7 @@ public class FeatureSettings extends Panel implements ItemListener,
     if (addCheck)
     {
       boolean selected = false;
-      if (groupsChanged || av.featuresDisplayed.containsKey(type))
+      if (groupsChanged || av.getFeaturesDisplayed().isVisible(type))
       {
         selected = true;
       }
@@ -455,26 +450,22 @@ public class FeatureSettings extends Panel implements ItemListener,
     selectionChanged();
   }
 
-  public void itemStateChanged(ItemEvent evt)
-  {
-    if (evt != null)
-    {
-      // Is the source a top level featureGroup?
+  private ItemListener groupItemListener = new ItemListener() {
+    public void itemStateChanged(ItemEvent evt) {
       Checkbox source = (Checkbox) evt.getSource();
-      if (fr.featureGroups.containsKey(source.getLabel()))
+      fr.setGroupVisibility(source.getLabel(),
+              source.getState());
+      ap.seqPanel.seqCanvas.repaint();
+      if (ap.overviewPanel != null)
       {
-        fr.featureGroups.put(source.getLabel(),
-                new Boolean(source.getState()));
-        ap.seqPanel.seqCanvas.repaint();
-        if (ap.overviewPanel != null)
-        {
-          ap.overviewPanel.updateOverviewImage();
-        }
-
-        resetTable(true);
-        return;
+        ap.overviewPanel.updateOverviewImage();
       }
-    }
+      resetTable(true);
+      return;
+    };
+  };
+  public void itemStateChanged(ItemEvent evt)
+  {
     selectionChanged();
   }
 
@@ -618,7 +609,7 @@ public class FeatureSettings extends Panel implements ItemListener,
     MyCheckbox check = (MyCheckbox) evt.getSource();
     if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) != 0)
     {
-      this.popupSort(check, fr.minmax, evt.getX(), evt.getY());
+      this.popupSort(check, fr.getMinMax(), evt.getX(), evt.getY());
     }
     if (fr.featureLinks != null && fr.featureLinks.containsKey(check.type))
     {
@@ -658,7 +649,7 @@ public class FeatureSettings extends Panel implements ItemListener,
 
   public void adjustmentValueChanged(AdjustmentEvent evt)
   {
-    fr.transparency = ((float) (100 - transparency.getValue()) / 100f);
+    fr.setTransparency((float) (100 - transparency.getValue()) / 100f);
     ap.seqPanel.seqCanvas.repaint();
 
   }
@@ -772,81 +763,4 @@ public class FeatureSettings extends Panel implements ItemListener,
     }
   }
 
-  protected void sortByDens(String[] typ)
-  {
-    sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
-  }
-
-  private String[] getDisplayedFeatureTypes()
-  {
-    String[] typ = null;
-    if (fr != null)
-    {
-      synchronized (fr.renderOrder)
-      {
-        typ = new String[fr.renderOrder.length];
-        System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
-        for (int i = 0; i < typ.length; i++)
-        {
-          if (av.featuresDisplayed.get(typ[i]) == null)
-          {
-            typ[i] = null;
-          }
-        }
-      }
-    }
-    return typ;
-  }
-
-  protected void sortBy(String[] typ, String methodText, final String method)
-  {
-    if (typ == null)
-    {
-      typ = getDisplayedFeatureTypes();
-    }
-    String gps[] = null;
-    gps = fr.getGroups(true);
-    if (typ != null)
-    {
-      for (int i = 0; i < typ.length; i++)
-      {
-        System.err.println("Sorting on Types:" + typ[i]);
-      }
-    }
-    if (gps != null)
-    {
-
-      for (int i = 0; i < gps.length; i++)
-      {
-        System.err.println("Sorting on groups:" + gps[i]);
-      }
-    }
-    AlignmentPanel alignPanel = ap;
-    AlignmentI al = alignPanel.av.getAlignment();
-
-    int start, stop;
-    SequenceGroup sg = alignPanel.av.getSelectionGroup();
-    if (sg != null)
-    {
-      start = sg.getStartRes();
-      stop = sg.getEndRes();
-    }
-    else
-    {
-      start = 0;
-      stop = al.getWidth();
-    }
-    SequenceI[] oldOrder = al.getSequencesArray();
-    AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
-    this.ap.alignFrame.addHistoryItem(new OrderCommand(methodText,
-            oldOrder, alignPanel.av.getAlignment()));
-    alignPanel.paintAlignment(true);
-
-  }
-
-  protected void sortByScore(String[] typ)
-  {
-    sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
-  }
-
 }
index e646051..8486fe0 100755 (executable)
@@ -69,7 +69,6 @@ public class OverviewPanel extends Panel implements Runnable,
     sr.renderGaps = false;
     sr.forOverview = true;
     fr = new FeatureRenderer(av);
-    fr.overview = true;
 
     // scale the initial size of overviewpanel to shape of alignment
     float initialScale = (float) av.getAlignment().getWidth()
@@ -231,8 +230,7 @@ public class OverviewPanel extends Panel implements Runnable,
 
     if (av.isShowSequenceFeatures())
     {
-      fr.featureGroups = ap.seqPanel.seqCanvas.getFeatureRenderer().featureGroups;
-      fr.featureColours = ap.seqPanel.seqCanvas.getFeatureRenderer().featureColours;
+      fr.transferSettings(ap.seqPanel.seqCanvas.fr);
     }
 
     resizing = true;
index 5ba22b6..baf27f1 100644 (file)
@@ -800,19 +800,17 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     {
       for (int i = 0; i < features.length; i++)
       {
-        if (av.featuresDisplayed == null
-                || !av.featuresDisplayed.containsKey(features[i].getType()))
+        if (av.getFeaturesDisplayed() == null
+                || !av.getFeaturesDisplayed().isVisible(features[i].getType()))
         {
           continue;
         }
 
         if (features[i].featureGroup != null
-                && seqCanvas.fr.featureGroups != null
-                && seqCanvas.fr.featureGroups
-                        .containsKey(features[i].featureGroup)
-                && !((Boolean) seqCanvas.fr.featureGroups
-                        .get(features[i].featureGroup)).booleanValue())
+                && !seqCanvas.fr.checkGroupVisibility(features[i].featureGroup,false))
+        {
           continue;
+        }
 
         if ((features[i].getBegin() <= res)
                 && (features[i].getEnd() >= res))
index b958f90..f364f74 100644 (file)
@@ -4786,7 +4786,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       featuresFile = new FeaturesFile(file, type).parse(viewport
               .getAlignment().getDataset(), alignPanel.seqPanel.seqCanvas
-              .getFeatureRenderer().featureColours, false,
+              .getFeatureRenderer().getFeatureColours(), false,
               jalview.bin.Cache.getDefault("RELAXEDSEQIDMATCHING", false));
     } catch (Exception ex)
     {
index 8c18a15..1bc4ba7 100644 (file)
@@ -1519,7 +1519,7 @@ public class AlignmentPanel extends GAlignmentPanel implements
   {
     return seqPanel.seqCanvas.getFeatureRenderer();
   }
-  public void updateFeatureRenderer(FeatureRenderer fr)
+  public void updateFeatureRenderer(jalview.renderer.seqfeatures.FeatureRenderer fr)
   {
     fr.transferSettings(seqPanel.seqCanvas.getFeatureRenderer());
   }
index 0975d24..61c5ee1 100644 (file)
@@ -112,14 +112,16 @@ public class AnnotationExporter extends JPanel
         if (GFFFormat.isSelected())
         {
           text = new FeaturesFile().printGFFFormat(ap.av.getAlignment()
-                  .getDataset().getSequencesArray(),
-                  getDisplayedFeatureCols(), true, ap.av.isShowNpFeats());// ap.av.featuresDisplayed//);
+                  .getDataset().getSequencesArray(), ap
+                  .getFeatureRenderer().getDisplayedFeatureCols(), true,
+                  ap.av.isShowNpFeats());// ap.av.featuresDisplayed//);
         }
         else
         {
           text = new FeaturesFile().printJalviewFormat(ap.av.getAlignment()
-                  .getDataset().getSequencesArray(),
-                  getDisplayedFeatureCols(), true, ap.av.isShowNpFeats()); // ap.av.featuresDisplayed);
+                  .getDataset().getSequencesArray(), ap
+                  .getFeatureRenderer().getDisplayedFeatureCols(), true,
+                  ap.av.isShowNpFeats()); // ap.av.featuresDisplayed);
         }
       }
       else
@@ -159,14 +161,14 @@ public class AnnotationExporter extends JPanel
       if (GFFFormat.isSelected())
       {
         text = new FeaturesFile().printGFFFormat(ap.av.getAlignment()
-                .getDataset().getSequencesArray(),
-                getDisplayedFeatureCols(), true, ap.av.isShowNpFeats());
+                .getDataset().getSequencesArray(), ap.getFeatureRenderer()
+                .getDisplayedFeatureCols(), true, ap.av.isShowNpFeats());
       }
       else
       {
         text = new FeaturesFile().printJalviewFormat(ap.av.getAlignment()
-                .getDataset().getSequencesArray(),
-                getDisplayedFeatureCols(), true, ap.av.isShowNpFeats());
+                .getDataset().getSequencesArray(), ap.getFeatureRenderer()
+                .getDisplayedFeatureCols(), true, ap.av.isShowNpFeats());
       }
     }
     else if (!features)
@@ -207,26 +209,6 @@ public class AnnotationExporter extends JPanel
     close_actionPerformed(null);
   }
 
-  private Hashtable getDisplayedFeatureCols()
-  {
-    Hashtable fcols = new Hashtable();
-    if (ap.av.featuresDisplayed == null)
-    {
-      return fcols;
-    }
-    Enumeration en = ap.av.featuresDisplayed.keys();
-    FeatureRenderer fr = ap.seqPanel.seqCanvas.getFeatureRenderer(); // consider
-                                                                     // higher
-                                                                     // level
-                                                                     // method ?
-    while (en.hasMoreElements())
-    {
-      Object col = en.nextElement();
-      fcols.put(col, fr.featureColours.get(col));
-    }
-    return fcols;
-  }
-
   public void close_actionPerformed(ActionEvent e)
   {
     try
index 8ab7c85..d1d1b6d 100644 (file)
@@ -109,10 +109,10 @@ public class FeatureColourChooser extends JalviewDialog
       }
     });
 
-    float mm[] = ((float[][]) fr.minmax.get(type))[0];
+    float mm[] = ((float[][]) fr.getMinMax().get(type))[0];
     min = mm[0];
     max = mm[1];
-    oldcs = fr.featureColours.get(type);
+    oldcs = fr.getFeatureColours().get(type);
     if (oldcs instanceof GraduatedColor)
     {
       if (((GraduatedColor) oldcs).isAutoScale())
@@ -470,7 +470,7 @@ public class FeatureColourChooser extends JalviewDialog
       maxColour.setForeground(oldmaxColour);
       minColour.setForeground(oldminColour);
     }
-    fr.featureColours.put(type, acg);
+    fr.setColour(type, acg);
     cs = acg;
     ap.paintAlignment(false);
   }
@@ -495,7 +495,7 @@ public class FeatureColourChooser extends JalviewDialog
 
   void reset()
   {
-    fr.featureColours.put(type, oldcs);
+    fr.setColour(type, oldcs);
     ap.paintAlignment(false);
     cs = null;
   }
index d36105a..ccb8ad1 100644 (file)
 package jalview.gui;
 
 import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-
 import java.awt.*;
 import java.awt.event.*;
 import java.awt.image.*;
 import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
 
 import javax.swing.*;
 
@@ -41,38 +38,11 @@ import jalview.util.MessageManager;
  * @author $author$
  * @version $Revision$
  */
-public class FeatureRenderer extends jalview.viewmodel.FeatureRenderer implements jalview.api.FeatureRenderer
+public class FeatureRenderer extends jalview.renderer.seqfeatures.FeatureRenderer implements jalview.api.FeatureRenderer
 {
-  AlignmentPanel ap;
-
-  AlignViewport av;
-
   Color resBoxColour;
 
-  /**
-   * global transparency for feature
-   */
-  float transparency = 1.0f;
-
-  FontMetrics fm;
-
-  int charOffset;
-
-  Map featureColours = new ConcurrentHashMap();
-
-  // A higher level for grouping features of a
-  // particular type
-  Map featureGroups = new ConcurrentHashMap();
-
-  // This is actually an Integer held in the hashtable,
-  // Retrieved using the key feature type
-  Object currentColour;
-
-  String[] renderOrder;
-
-  PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
-
-  Vector allfeatures;
+  AlignmentPanel ap;
 
   /**
    * Creates a new FeatureRenderer object.
@@ -82,6 +52,7 @@ public class FeatureRenderer extends jalview.viewmodel.FeatureRenderer implement
    */
   public FeatureRenderer(AlignmentPanel ap)
   {
+    super();
     this.ap = ap;
     this.av = ap.av;
     if (ap != null && ap.seqPanel != null && ap.seqPanel.seqCanvas != null
@@ -91,898 +62,6 @@ public class FeatureRenderer extends jalview.viewmodel.FeatureRenderer implement
     }
   }
 
-  public class FeatureRendererSettings implements Cloneable
-  {
-    String[] renderOrder;
-
-    Map featureGroups;
-
-    Map featureColours;
-
-    float transparency;
-
-    Map featureOrder;
-
-    public FeatureRendererSettings(String[] renderOrder,
-            Hashtable featureGroups, Hashtable featureColours,
-            float transparency, Hashtable featureOrder)
-    {
-      super();
-      this.renderOrder = renderOrder;
-      this.featureGroups = featureGroups;
-      this.featureColours = featureColours;
-      this.transparency = transparency;
-      this.featureOrder = featureOrder;
-    }
-
-    /**
-     * create an independent instance of the feature renderer settings
-     * 
-     * @param fr
-     */
-    public FeatureRendererSettings(FeatureRenderer fr)
-    {
-      renderOrder = null;
-      featureGroups = new ConcurrentHashMap();
-      featureColours = new ConcurrentHashMap();
-      featureOrder = new ConcurrentHashMap();
-      if (fr.renderOrder != null)
-      {
-        this.renderOrder = new String[fr.renderOrder.length];
-        System.arraycopy(fr.renderOrder, 0, renderOrder, 0,
-                fr.renderOrder.length);
-      }
-      if (fr.featureGroups != null)
-      {
-        this.featureGroups = new ConcurrentHashMap(fr.featureGroups);
-      }
-      if (fr.featureColours != null)
-      {
-        this.featureColours = new ConcurrentHashMap(fr.featureColours);
-      }
-      Iterator en = fr.featureColours.keySet().iterator();
-      while (en.hasNext())
-      {
-        Object next = en.next();
-        Object val = featureColours.get(next);
-        if (val instanceof GraduatedColor)
-        {
-          featureColours
-                  .put(next, new GraduatedColor((GraduatedColor) val));
-        }
-      }
-      this.transparency = fr.transparency;
-      if (fr.featureOrder != null)
-      {
-        this.featureOrder = new ConcurrentHashMap(fr.featureOrder);
-      }
-    }
-  }
-
-  public FeatureRendererSettings getSettings()
-  {
-    return new FeatureRendererSettings(this);
-  }
-
-  public void transferSettings(FeatureRendererSettings fr)
-  {
-    this.renderOrder = fr.renderOrder;
-    this.featureGroups = fr.featureGroups;
-    this.featureColours = fr.featureColours;
-    this.transparency = fr.transparency;
-    this.featureOrder = fr.featureOrder;
-  }
-
-  /**
-   * update from another feature renderer
-   * 
-   * @param fr
-   *          settings to copy
-   */
-  public void transferSettings(jalview.api.FeatureRenderer _fr)
-  {
-    FeatureRenderer fr = (FeatureRenderer) _fr;
-    FeatureRendererSettings frs = new FeatureRendererSettings(fr);
-    this.renderOrder = frs.renderOrder;
-    this.featureGroups = frs.featureGroups;
-    this.featureColours = frs.featureColours;
-    this.transparency = frs.transparency;
-    this.featureOrder = frs.featureOrder;
-    if (av != null && av != fr.av)
-    {
-      // copy over the displayed feature settings
-      if (fr.av != null)
-      {
-        if (fr.av.featuresDisplayed != null)
-        {
-          // update display settings
-          if (av.featuresDisplayed == null)
-          {
-            av.featuresDisplayed = new Hashtable(fr.av.featuresDisplayed);
-          }
-          else
-          {
-            av.featuresDisplayed.clear();
-            Enumeration en = fr.av.featuresDisplayed.keys();
-            while (en.hasMoreElements())
-            {
-              av.featuresDisplayed.put(en.nextElement(), Boolean.TRUE);
-            }
-
-          }
-        }
-      }
-    }
-  }
-
-  BufferedImage offscreenImage;
-
-  boolean offscreenRender = false;
-
-  public Color findFeatureColour(Color initialCol, SequenceI seq, int res)
-  {
-    return new Color(findFeatureColour(initialCol.getRGB(), seq, res));
-  }
-
-  /**
-   * This is used by the Molecule Viewer and Overview to get the accurate
-   * colourof the rendered sequence
-   */
-  public synchronized int findFeatureColour(int initialCol, SequenceI seq,
-          int column)
-  {
-    if (!av.showSequenceFeatures)
-    {
-      return initialCol;
-    }
-
-    if (seq != lastSeq)
-    {
-      lastSeq = seq;
-      sequenceFeatures = lastSeq.getDatasetSequence().getSequenceFeatures();
-      if (sequenceFeatures != null)
-      {
-        sfSize = sequenceFeatures.length;
-      }
-    }
-
-    if (sequenceFeatures != lastSeq.getDatasetSequence()
-            .getSequenceFeatures())
-    {
-      sequenceFeatures = lastSeq.getDatasetSequence().getSequenceFeatures();
-      if (sequenceFeatures != null)
-      {
-        sfSize = sequenceFeatures.length;
-      }
-    }
-
-    if (sequenceFeatures == null || sfSize == 0)
-    {
-      return initialCol;
-    }
-
-    if (jalview.util.Comparison.isGap(lastSeq.getCharAt(column)))
-    {
-      return Color.white.getRGB();
-    }
-
-    // Only bother making an offscreen image if transparency is applied
-    if (transparency != 1.0f && offscreenImage == null)
-    {
-      offscreenImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
-    }
-
-    currentColour = null;
-    // TODO: non-threadsafe - each rendering thread needs its own instance of
-    // the feature renderer - or this should be synchronized.
-    offscreenRender = true;
-
-    if (offscreenImage != null)
-    {
-      offscreenImage.setRGB(0, 0, initialCol);
-      drawSequence(offscreenImage.getGraphics(), lastSeq, column, column, 0);
-
-      return offscreenImage.getRGB(0, 0);
-    }
-    else
-    {
-      drawSequence(null, lastSeq, lastSeq.findPosition(column), -1, -1);
-
-      if (currentColour == null)
-      {
-        return initialCol;
-      }
-      else
-      {
-        return ((Integer) currentColour).intValue();
-      }
-    }
-
-  }
-
-  /**
-   * 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;
-
-  /**
-   * show scores as heights
-   */
-  protected boolean varyHeight = false;
-
-  synchronized public void drawSequence(Graphics g, SequenceI seq,
-          int start, int end, int y1)
-  {
-
-    if (seq.getDatasetSequence().getSequenceFeatures() == null
-            || seq.getDatasetSequence().getSequenceFeatures().length == 0)
-    {
-      return;
-    }
-
-    if (g != null)
-    {
-      fm = g.getFontMetrics();
-    }
-
-    if (av.featuresDisplayed == null || renderOrder == null
-            || newFeatureAdded)
-    {
-      findAllFeatures();
-      if (av.featuresDisplayed.size() < 1)
-      {
-        return;
-      }
-
-      sequenceFeatures = seq.getDatasetSequence().getSequenceFeatures();
-    }
-
-    if (lastSeq == null
-            || seq != lastSeq
-            || seq.getDatasetSequence().getSequenceFeatures() != sequenceFeatures)
-    {
-      lastSeq = seq;
-      sequenceFeatures = seq.getDatasetSequence().getSequenceFeatures();
-    }
-
-    if (transparency != 1 && g != null)
-    {
-      Graphics2D g2 = (Graphics2D) g;
-      g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
-              transparency));
-    }
-
-    if (!offscreenRender)
-    {
-      spos = lastSeq.findPosition(start);
-      epos = lastSeq.findPosition(end);
-    }
-
-    sfSize = sequenceFeatures.length;
-    String type;
-    for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++)
-    {
-      type = renderOrder[renderIndex];
-
-      if (type == null || !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
-                && sequenceFeatures[sfindex].featureGroup.length() != 0
-                && featureGroups
-                        .containsKey(sequenceFeatures[sfindex].featureGroup)
-                && !((Boolean) featureGroups
-                        .get(sequenceFeatures[sfindex].featureGroup))
-                        .booleanValue())
-        {
-          continue;
-        }
-
-        if (!offscreenRender
-                && (sequenceFeatures[sfindex].getBegin() > epos || sequenceFeatures[sfindex]
-                        .getEnd() < spos))
-        {
-          continue;
-        }
-
-        if (offscreenRender && offscreenImage == null)
-        {
-          if (sequenceFeatures[sfindex].begin <= start
-                  && sequenceFeatures[sfindex].end >= start)
-          {
-            // this is passed out to the overview and other sequence renderers
-            // (e.g. molecule viewer) to get displayed colour for rendered
-            // sequence
-            currentColour = new Integer(
-                    getColour(sequenceFeatures[sfindex]).getRGB());
-            // used to be retreived from av.featuresDisplayed
-            // 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,
-                  getColour(sequenceFeatures[sfindex])
-                  // 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,
-                  getColour(sequenceFeatures[sfindex])
-                  // new Color(((Integer) av.featuresDisplayed
-                  // .get(sequenceFeatures[sfindex].type)).intValue())
-                  , start, end, y1);
-
-        }
-        else if (showFeature(sequenceFeatures[sfindex]))
-        {
-          if (av.showSeqFeaturesHeight
-                  && sequenceFeatures[sfindex].score != Float.NaN)
-          {
-            renderScoreFeature(g, seq,
-                    seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
-                    seq.findIndex(sequenceFeatures[sfindex].end) - 1,
-                    getColour(sequenceFeatures[sfindex]), start, end, y1,
-                    normaliseScore(sequenceFeatures[sfindex]));
-          }
-          else
-          {
-            renderFeature(g, seq,
-                    seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
-                    seq.findIndex(sequenceFeatures[sfindex].end) - 1,
-                    getColour(sequenceFeatures[sfindex]), start, end, y1);
-          }
-        }
-
-      }
-
-    }
-
-    if (transparency != 1.0f && g != null)
-    {
-      Graphics2D g2 = (Graphics2D) g;
-      g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
-              1.0f));
-    }
-  }
-
-  Hashtable minmax = new Hashtable();
-
-  /**
-   * normalise a score against the max/min bounds for the feature type.
-   * 
-   * @param sequenceFeature
-   * @return byte[] { signed, normalised signed (-127 to 127) or unsigned
-   *         (0-255) value.
-   */
-  private final byte[] normaliseScore(SequenceFeature sequenceFeature)
-  {
-    float[] mm = ((float[][]) minmax.get(sequenceFeature.type))[0];
-    final byte[] r = new byte[]
-    { 0, (byte) 255 };
-    if (mm != null)
-    {
-      if (r[0] != 0 || mm[0] < 0.0)
-      {
-        r[0] = 1;
-        r[1] = (byte) ((int) 128.0 + 127.0 * (sequenceFeature.score / mm[1]));
-      }
-      else
-      {
-        r[1] = (byte) ((int) 255.0 * (sequenceFeature.score / mm[1]));
-      }
-    }
-    return r;
-  }
-
-  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;
-      }
-      int pady = (y1 + av.charHeight) - av.charHeight / 5;
-      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 (offscreenRender || !av.validCharWidth)
-        {
-          continue;
-        }
-
-        g.setColor(Color.white);
-        charOffset = (av.charWidth - fm.charWidth(s)) / 2;
-        g.drawString(String.valueOf(s), charOffset
-                + (av.charWidth * (i - start)), pady);
-
-      }
-    }
-  }
-
-  void renderScoreFeature(Graphics g, SequenceI seq, int fstart, int fend,
-          Color featureColour, int start, int end, int y1, byte[] bs)
-  {
-
-    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;
-      }
-      int pady = (y1 + av.charHeight) - av.charHeight / 5;
-      int ystrt = 0, yend = av.charHeight;
-      if (bs[0] != 0)
-      {
-        // signed - zero is always middle of residue line.
-        if (bs[1] < 128)
-        {
-          yend = av.charHeight * (128 - bs[1]) / 512;
-          ystrt = av.charHeight - yend / 2;
-        }
-        else
-        {
-          ystrt = av.charHeight / 2;
-          yend = av.charHeight * (bs[1] - 128) / 512;
-        }
-      }
-      else
-      {
-        yend = av.charHeight * bs[1] / 255;
-        ystrt = av.charHeight - yend;
-
-      }
-      for (i = fstart; i <= fend; i++)
-      {
-        s = seq.getCharAt(i);
-
-        if (jalview.util.Comparison.isGap(s))
-        {
-          continue;
-        }
-
-        g.setColor(featureColour);
-        int x = (i - start) * av.charWidth;
-        g.drawRect(x, y1, av.charWidth, av.charHeight);
-        g.fillRect(x, y1 + ystrt, av.charWidth, yend);
-
-        if (offscreenRender || !av.validCharWidth)
-        {
-          continue;
-        }
-
-        g.setColor(Color.black);
-        charOffset = (av.charWidth - fm.charWidth(s)) / 2;
-        g.drawString(String.valueOf(s), charOffset
-                + (av.charWidth * (i - start)), pady);
-
-      }
-    }
-  }
-
-  boolean newFeatureAdded = false;
-
-  /**
-   * Called when alignment in associated view has new/modified features to
-   * discover and display.
-   * 
-   */
-  public void featuresAdded()
-  {
-    lastSeq = null;
-    findAllFeatures();
-  }
-
-  boolean findingFeatures = false;
-
-  /**
-   * search the alignment for all new features, give them a colour and display
-   * them. Then fires a PropertyChangeEvent on the changeSupport object.
-   * 
-   */
-  void findAllFeatures()
-  {
-    synchronized (firing)
-    {
-      if (firing.equals(Boolean.FALSE))
-      {
-        firing = Boolean.TRUE;
-        findAllFeatures(true); // add all new features as visible
-        changeSupport.firePropertyChange("changeSupport", null, null);
-        firing = Boolean.FALSE;
-      }
-    }
-  }
-
-  /**
-   * Searches alignment for all features and updates colours
-   * 
-   * @param newMadeVisible
-   *          if true newly added feature types will be rendered immediatly
-   */
-  synchronized void findAllFeatures(boolean newMadeVisible)
-  {
-    newFeatureAdded = false;
-
-    if (findingFeatures)
-    {
-      newFeatureAdded = true;
-      return;
-    }
-
-    findingFeatures = true;
-
-    if (av.featuresDisplayed == null)
-    {
-      av.featuresDisplayed = new Hashtable();
-    }
-
-    allfeatures = new Vector();
-    Vector oldfeatures = new Vector();
-    if (renderOrder != null)
-    {
-      for (int i = 0; i < renderOrder.length; i++)
-      {
-        if (renderOrder[i] != null)
-        {
-          oldfeatures.addElement(renderOrder[i]);
-        }
-      }
-    }
-    if (minmax == null)
-    {
-      minmax = new Hashtable();
-    }
-    AlignmentI alignment = av.getAlignment();
-    for (int i = 0; i < alignment.getHeight(); i++)
-    {
-      SequenceFeature[] features = alignment.getSequenceAt(i)
-              .getDatasetSequence().getSequenceFeatures();
-
-      if (features == null)
-      {
-        continue;
-      }
-
-      int index = 0;
-      while (index < features.length)
-      {
-        if (!av.featuresDisplayed.containsKey(features[index].getType()))
-        {
-
-          if (featureGroups.containsKey(features[index].getType()))
-          {
-            boolean visible = ((Boolean) featureGroups
-                    .get(features[index].featureGroup)).booleanValue();
-
-            if (!visible)
-            {
-              index++;
-              continue;
-            }
-          }
-
-          if (!(features[index].begin == 0 && features[index].end == 0))
-          {
-            // If beginning and end are 0, the feature is for the whole sequence
-            // and we don't want to render the feature in the normal way
-
-            if (newMadeVisible
-                    && !oldfeatures.contains(features[index].getType()))
-            {
-              // this is a new feature type on the alignment. Mark it for
-              // display.
-              av.featuresDisplayed.put(features[index].getType(),
-                      new Integer(getColour(features[index].getType())
-                              .getRGB()));
-              setOrder(features[index].getType(), 0);
-            }
-          }
-        }
-        if (!allfeatures.contains(features[index].getType()))
-        {
-          allfeatures.addElement(features[index].getType());
-        }
-        if (features[index].score != Float.NaN)
-        {
-          int nonpos = features[index].getBegin() >= 1 ? 0 : 1;
-          float[][] mm = (float[][]) minmax.get(features[index].getType());
-          if (mm == null)
-          {
-            mm = new float[][]
-            { null, null };
-            minmax.put(features[index].getType(), mm);
-          }
-          if (mm[nonpos] == null)
-          {
-            mm[nonpos] = new float[]
-            { features[index].score, features[index].score };
-
-          }
-          else
-          {
-            if (mm[nonpos][0] > features[index].score)
-            {
-              mm[nonpos][0] = features[index].score;
-            }
-            if (mm[nonpos][1] < features[index].score)
-            {
-              mm[nonpos][1] = features[index].score;
-            }
-          }
-        }
-        index++;
-      }
-    }
-    updateRenderOrder(allfeatures);
-    findingFeatures = false;
-  }
-
-  protected Boolean firing = Boolean.FALSE;
-
-  /**
-   * replaces the current renderOrder with the unordered features in
-   * allfeatures. The ordering of any types in both renderOrder and allfeatures
-   * is preserved, and all new feature types are rendered on top of the existing
-   * types, in the order given by getOrder or the order given in allFeatures.
-   * Note. this operates directly on the featureOrder hash for efficiency. TODO:
-   * eliminate the float storage for computing/recalling the persistent ordering
-   * New Cability: updates min/max for colourscheme range if its dynamic
-   * 
-   * @param allFeatures
-   */
-  private void updateRenderOrder(Vector allFeatures)
-  {
-    Vector allfeatures = new Vector(allFeatures);
-    String[] oldRender = renderOrder;
-    renderOrder = new String[allfeatures.size()];
-    Object mmrange, fc = null;
-    boolean initOrders = (featureOrder == null);
-    int opos = 0;
-    if (oldRender != null && oldRender.length > 0)
-    {
-      for (int j = 0; j < oldRender.length; j++)
-      {
-        if (oldRender[j] != null)
-        {
-          if (initOrders)
-          {
-            setOrder(oldRender[j], (1 - (1 + (float) j)
-                    / (float) oldRender.length));
-          }
-          if (allfeatures.contains(oldRender[j]))
-          {
-            renderOrder[opos++] = oldRender[j]; // existing features always
-            // appear below new features
-            allfeatures.removeElement(oldRender[j]);
-            if (minmax != null)
-            {
-              mmrange = minmax.get(oldRender[j]);
-              if (mmrange != null)
-              {
-                fc = featureColours.get(oldRender[j]);
-                if (fc != null && fc instanceof GraduatedColor
-                        && ((GraduatedColor) fc).isAutoScale())
-                {
-                  ((GraduatedColor) fc).updateBounds(
-                          ((float[][]) mmrange)[0][0],
-                          ((float[][]) mmrange)[0][1]);
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-    if (allfeatures.size() == 0)
-    {
-      // no new features - leave order unchanged.
-      return;
-    }
-    int i = allfeatures.size() - 1;
-    int iSize = i;
-    boolean sort = false;
-    String[] newf = new String[allfeatures.size()];
-    float[] sortOrder = new float[allfeatures.size()];
-    Enumeration en = allfeatures.elements();
-    // sort remaining elements
-    while (en.hasMoreElements())
-    {
-      newf[i] = en.nextElement().toString();
-      if (minmax != null)
-      {
-        // update from new features minmax if necessary
-        mmrange = minmax.get(newf[i]);
-        if (mmrange != null)
-        {
-          fc = featureColours.get(newf[i]);
-          if (fc != null && fc instanceof GraduatedColor
-                  && ((GraduatedColor) fc).isAutoScale())
-          {
-            ((GraduatedColor) fc).updateBounds(((float[][]) mmrange)[0][0],
-                    ((float[][]) mmrange)[0][1]);
-          }
-        }
-      }
-      if (initOrders || !featureOrder.containsKey(newf[i]))
-      {
-        int denom = initOrders ? allfeatures.size() : featureOrder.size();
-        // new unordered feature - compute persistent ordering at head of
-        // existing features.
-        setOrder(newf[i], i / (float) denom);
-      }
-      // set order from newly found feature from persisted ordering.
-      sortOrder[i] = 2 - ((Float) featureOrder.get(newf[i])).floatValue();
-      if (i < iSize)
-      {
-        // only sort if we need to
-        sort = sort || sortOrder[i] > sortOrder[i + 1];
-      }
-      i--;
-    }
-    if (iSize > 1 && sort)
-    {
-      jalview.util.QuickSort.sort(sortOrder, newf);
-    }
-    sortOrder = null;
-    System.arraycopy(newf, 0, renderOrder, opos, newf.length);
-  }
-
-  /**
-   * get a feature style object for the given type string. Creates a
-   * java.awt.Color for a featureType with no existing colourscheme. TODO:
-   * replace return type with object implementing standard abstract colour/style
-   * interface
-   * 
-   * @param featureType
-   * @return java.awt.Color or GraduatedColor
-   */
-  public Object getFeatureStyle(String featureType)
-  {
-    Object fc = featureColours.get(featureType);
-    if (fc == null)
-    {
-      jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
-      Color col = ucs.createColourFromName(featureType);
-      featureColours.put(featureType, fc = col);
-    }
-    return fc;
-  }
-
-  /**
-   * return a nominal colour for this feature
-   * 
-   * @param featureType
-   * @return standard color, or maximum colour for graduated colourscheme
-   */
-  public Color getColour(String featureType)
-  {
-    Object fc = getFeatureStyle(featureType);
-
-    if (fc instanceof Color)
-    {
-      return (Color) fc;
-    }
-    else
-    {
-      if (fc instanceof GraduatedColor)
-      {
-        return ((GraduatedColor) fc).getMaxColor();
-      }
-    }
-    throw new Error("Implementation Error: Unrecognised render object "
-            + fc.getClass() + " for features of type " + featureType);
-  }
-
-  /**
-   * calculate the render colour for a specific feature using current feature
-   * settings.
-   * 
-   * @param feature
-   * @return render colour for the given feature
-   */
-  public Color getColour(SequenceFeature feature)
-  {
-    Object fc = getFeatureStyle(feature.getType());
-    if (fc instanceof Color)
-    {
-      return (Color) fc;
-    }
-    else
-    {
-      if (fc instanceof GraduatedColor)
-      {
-        return ((GraduatedColor) fc).findColor(feature);
-      }
-    }
-    throw new Error("Implementation Error: Unrecognised render object "
-            + fc.getClass() + " for features of type " + feature.getType());
-  }
-
-  private boolean showFeature(SequenceFeature sequenceFeature)
-  {
-    Object fc = getFeatureStyle(sequenceFeature.type);
-    if (fc instanceof GraduatedColor)
-    {
-      return ((GraduatedColor) fc).isColored(sequenceFeature);
-    }
-    else
-    {
-      return true;
-    }
-  }
-
   // // /////////////
   // // Feature Editing Dialog
   // // Will be refactored in next release.
@@ -1256,7 +335,7 @@ public class FeatureRenderer extends jalview.viewmodel.FeatureRenderer implement
         sf.description = lastDescriptionAdded;
 
         setColour(sf.type, fcol);
-        av.featuresDisplayed.put(sf.type, getColour(sf.type));
+        getFeaturesDisplayed().setVisible(sf.type);
 
         try
         {
@@ -1277,27 +356,20 @@ public class FeatureRenderer extends jalview.viewmodel.FeatureRenderer implement
         for (int i = 0; i < sequences.length; i++)
         {
           features[i].type = lastFeatureAdded;
-          if (lastFeatureGroupAdded != null)
-            features[i].featureGroup = lastFeatureGroupAdded;
+          // fix for JAL-1538 - always set feature group here
+          features[i].featureGroup = lastFeatureGroupAdded;
           features[i].description = lastDescriptionAdded;
           sequences[i].addSequenceFeature(features[i]);
           ffile.parseDescriptionHTML(features[i], false);
         }
 
-        if (av.featuresDisplayed == null)
-        {
-          av.featuresDisplayed = new Hashtable();
-        }
-
+        
         if (lastFeatureGroupAdded != null)
         {
-          if (featureGroups == null)
-            featureGroups = new Hashtable();
-          featureGroups.put(lastFeatureGroupAdded, new Boolean(true));
+          setGroupVisibility(lastFeatureGroupAdded, true);
         }
         setColour(lastFeatureAdded, fcol);
-        av.featuresDisplayed.put(lastFeatureAdded,
-                getColour(lastFeatureAdded));
+        setVisible(lastFeatureAdded);
 
         findAllFeatures(false);
 
@@ -1316,6 +388,7 @@ public class FeatureRenderer extends jalview.viewmodel.FeatureRenderer implement
     return true;
   }
 
+
   /**
    * update the amend feature button dependent on the given style
    * 
@@ -1343,145 +416,4 @@ public class FeatureRenderer extends jalview.viewmodel.FeatureRenderer implement
       // colour.setForeground(colour.getBackground());
     }
   }
-
-  public void setColour(String featureType, Object col)
-  {
-    // overwrite
-    // Color _col = (col instanceof Color) ? ((Color) col) : (col instanceof
-    // GraduatedColor) ? ((GraduatedColor) col).getMaxColor() : null;
-    // Object c = featureColours.get(featureType);
-    // if (c == null || c instanceof Color || (c instanceof GraduatedColor &&
-    // !((GraduatedColor)c).getMaxColor().equals(_col)))
-    {
-      featureColours.put(featureType, col);
-    }
-  }
-
-  public void setTransparency(float value)
-  {
-    transparency = value;
-  }
-
-  public float getTransparency()
-  {
-    return transparency;
-  }
-
-  /**
-   * Replace current ordering with new ordering
-   * 
-   * @param data
-   *          { String(Type), Colour(Type), Boolean(Displayed) }
-   */
-  public void setFeaturePriority(Object[][] data)
-  {
-    setFeaturePriority(data, true);
-  }
-
-  /**
-   * 
-   * @param data
-   *          { String(Type), Colour(Type), Boolean(Displayed) }
-   * @param visibleNew
-   *          when true current featureDisplay list will be cleared
-   */
-  public void setFeaturePriority(Object[][] data, boolean visibleNew)
-  {
-    if (visibleNew)
-    {
-      if (av.featuresDisplayed != null)
-      {
-        av.featuresDisplayed.clear();
-      }
-      else
-      {
-        av.featuresDisplayed = new Hashtable();
-      }
-    }
-    if (data == null)
-    {
-      return;
-    }
-
-    // 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
-    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, data[i][1]); // todo : typesafety - feature color
-        // interface object
-        if (((Boolean) data[i][2]).booleanValue())
-        {
-          av.featuresDisplayed.put(type, new Integer(getColour(type)
-                  .getRGB()));
-        }
-
-        renderOrder[data.length - i - 1] = type;
-      }
-    }
-
-  }
-
-  Map featureOrder = null;
-
-  /**
-   * analogous to colour - store a normalized ordering for all feature types in
-   * this rendering context.
-   * 
-   * @param type
-   *          Feature type string
-   * @param position
-   *          normalized priority - 0 means always appears on top, 1 means
-   *          always last.
-   */
-  public float setOrder(String type, float position)
-  {
-    if (featureOrder == null)
-    {
-      featureOrder = new Hashtable();
-    }
-    featureOrder.put(type, new Float(position));
-    return position;
-  }
-
-  /**
-   * get the global priority (0 (top) to 1 (bottom))
-   * 
-   * @param type
-   * @return [0,1] or -1 for a type without a priority
-   */
-  public float getOrder(String type)
-  {
-    if (featureOrder != null)
-    {
-      if (featureOrder.containsKey(type))
-      {
-        return ((Float) featureOrder.get(type)).floatValue();
-      }
-    }
-    return -1;
-  }
-
-  /**
-   * @param listener
-   * @see java.beans.PropertyChangeSupport#addPropertyChangeListener(java.beans.PropertyChangeListener)
-   */
-  public void addPropertyChangeListener(PropertyChangeListener listener)
-  {
-    changeSupport.addPropertyChangeListener(listener);
-  }
-
-  /**
-   * @param listener
-   * @see java.beans.PropertyChangeSupport#removePropertyChangeListener(java.beans.PropertyChangeListener)
-   */
-  public void removePropertyChangeListener(PropertyChangeListener listener)
-  {
-    changeSupport.removePropertyChangeListener(listener);
-  }
 }
index 3dae4e5..d30f5a0 100644 (file)
@@ -33,6 +33,7 @@ import javax.swing.event.*;
 import javax.swing.table.*;
 
 import jalview.analysis.AlignmentSorter;
+import jalview.api.FeaturesDisplayedI;
 import jalview.bin.Cache;
 import jalview.commands.OrderCommand;
 import jalview.datamodel.*;
@@ -58,6 +59,8 @@ public class FeatureSettings extends JPanel
 
   Object[][] originalData;
 
+  private float originalTransparency;
+
   final JInternalFrame frame;
 
   JScrollPane scrollPane = new JScrollPane();
@@ -74,8 +77,8 @@ public class FeatureSettings extends JPanel
   {
     this.af = af;
     fr = af.getFeatureRenderer();
-
-    transparency.setMaximum(100 - (int) (fr.transparency * 100));
+    // allow transparency to be recovered
+    transparency.setMaximum(100 - (int) ((originalTransparency=fr.getTransparency()) * 100));
 
     try
     {
@@ -104,8 +107,8 @@ public class FeatureSettings extends JPanel
         if (evt.isPopupTrigger())
         {
           popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0),
-                  table.getValueAt(selectedRow, 1), fr.minmax, evt.getX(),
-                  evt.getY());
+                  table.getValueAt(selectedRow, 1), fr.getMinMax(),
+                  evt.getX(), evt.getY());
         }
         else if (evt.getClickCount() == 2)
         {
@@ -150,8 +153,7 @@ public class FeatureSettings extends JPanel
     dassourceBrowser = new DasSourceBrowser(this);
     dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER);
 
-    if (af.getViewport().featuresDisplayed == null
-            || fr.renderOrder == null)
+    if (af.getViewport().isShowSequenceFeatures() || !fr.hasRenderOrder())
     {
       fr.findAllFeatures(true); // display everything!
     }
@@ -216,7 +218,7 @@ public class FeatureSettings extends JPanel
 
       public void actionPerformed(ActionEvent e)
       {
-        me.sortByScore(new String[]
+        me.af.avc.sortAlignmentByFeatureScore(new String[]
         { type });
       }
 
@@ -228,7 +230,7 @@ public class FeatureSettings extends JPanel
 
       public void actionPerformed(ActionEvent e)
       {
-        me.sortByDens(new String[]
+        me.af.avc.sortAlignmentByFeatureDensity(new String[]
         { type });
       }
 
@@ -352,10 +354,6 @@ public class FeatureSettings extends JPanel
 
   synchronized public void setTableData()
   {
-    if (fr.featureGroups == null)
-    {
-      fr.featureGroups = new Hashtable();
-    }
     Vector allFeatures = new Vector();
     Vector allGroups = new Vector();
     SequenceFeature[] tmpfeatures;
@@ -386,10 +384,7 @@ public class FeatureSettings extends JPanel
           if (!allGroups.contains(group))
           {
             allGroups.addElement(group);
-            if (group != null)
-            {
-              checkGroupState(group);
-            }
+            checkGroupState(group);
           }
         }
 
@@ -407,21 +402,14 @@ public class FeatureSettings extends JPanel
   }
 
   /**
+   * Synchronise gui group list and check visibility of group
    * 
    * @param group
-   * @return true if group has been seen before and is already added to set.
+   * @return true if group is visible
    */
   private boolean checkGroupState(String group)
   {
-    boolean visible;
-    if (fr.featureGroups.containsKey(group))
-    {
-      visible = ((Boolean) fr.featureGroups.get(group)).booleanValue();
-    }
-    else
-    {
-      visible = true; // new group is always made visible
-    }
+    boolean visible = fr.checkGroupVisibility(group, true);
 
     if (groupPanel == null)
     {
@@ -442,10 +430,8 @@ public class FeatureSettings extends JPanel
     if (alreadyAdded)
     {
 
-      return true;
+      return visible;
     }
-
-    fr.featureGroups.put(group, new Boolean(visible));
     final String grp = group;
     final JCheckBox check = new JCheckBox(group, visible);
     check.setFont(new Font("Serif", Font.BOLD, 12));
@@ -453,8 +439,7 @@ public class FeatureSettings extends JPanel
     {
       public void itemStateChanged(ItemEvent evt)
       {
-        fr.featureGroups.put(check.getText(),
-                new Boolean(check.isSelected()));
+        fr.setGroupVisibility(check.getText(), check.isSelected());
         af.alignPanel.seqPanel.seqCanvas.repaint();
         if (af.alignPanel.overviewPanel != null)
         {
@@ -466,7 +451,7 @@ public class FeatureSettings extends JPanel
       }
     });
     groupPanel.add(check);
-    return false;
+    return visible;
   }
 
   boolean resettingTable = false;
@@ -510,11 +495,8 @@ public class FeatureSettings extends JPanel
           continue;
         }
 
-        if (group == null || fr.featureGroups.get(group) == null
-                || ((Boolean) fr.featureGroups.get(group)).booleanValue())
+        if (group == null || checkGroupState(group))
         {
-          if (group != null)
-            checkGroupState(group);
           type = tmpfeatures[index].getType();
           if (!visibleChecks.contains(type))
           {
@@ -549,17 +531,20 @@ public class FeatureSettings extends JPanel
     Object[][] data = new Object[fSize][3];
     int dataIndex = 0;
 
-    if (fr.renderOrder != null)
+    if (fr.hasRenderOrder())
     {
       if (!handlingUpdate)
+      {
         fr.findAllFeatures(groupChanged != null); // prod to update
-      // colourschemes. but don't
-      // affect display
-      // 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--)
+        // colourschemes. but don't
+        // affect display
+        // First add the checks in the previous render order,
+        // in case the window has been closed and reopened
+      }
+      List<String> frl = fr.getRenderOrder();
+      for (int ro = frl.size() - 1; ro > -1; ro--)
       {
-        type = fr.renderOrder[ro];
+        type = frl.get(ro);
 
         if (!visibleChecks.contains(type))
         {
@@ -568,8 +553,8 @@ public class FeatureSettings extends JPanel
 
         data[dataIndex][0] = type;
         data[dataIndex][1] = fr.getFeatureStyle(type);
-        data[dataIndex][2] = new Boolean(
-                af.getViewport().featuresDisplayed.containsKey(type));
+        data[dataIndex][2] = new Boolean(af.getViewport()
+                .getFeaturesDisplayed().isVisible(type));
         dataIndex++;
         visibleChecks.removeElement(type);
       }
@@ -587,7 +572,7 @@ public class FeatureSettings extends JPanel
       if (data[dataIndex][1] == null)
       {
         // "Colour has been updated in another view!!"
-        fr.renderOrder = null;
+        fr.clearRenderOrder();
         return;
       }
 
@@ -609,8 +594,8 @@ public class FeatureSettings extends JPanel
 
     if (groupPanel != null)
     {
-      groupPanel.setLayout(new GridLayout(fr.featureGroups.size() / 4 + 1,
-              4));
+      groupPanel.setLayout(new GridLayout(
+              fr.getFeatureGroupsSize() / 4 + 1, 4));
 
       groupPanel.validate();
       bigPanel.add(groupPanel, BorderLayout.NORTH);
@@ -761,9 +746,10 @@ public class FeatureSettings extends JPanel
         PrintWriter out = new PrintWriter(new OutputStreamWriter(
                 new FileOutputStream(choice), "UTF-8"));
 
-        Iterator e = fr.featureColours.keySet().iterator();
-        float[] sortOrder = new float[fr.featureColours.size()];
-        String[] sortTypes = new String[fr.featureColours.size()];
+        Set fr_colours = fr.getAllFeatureColours();
+        Iterator e = fr_colours.iterator();
+        float[] sortOrder = new float[fr_colours.size()];
+        String[] sortTypes = new String[fr_colours.size()];
         int i = 0;
         while (e.hasNext())
         {
@@ -976,7 +962,7 @@ public class FeatureSettings extends JPanel
     {
       public void actionPerformed(ActionEvent e)
       {
-        sortByScore(null);
+        af.avc.sortAlignmentByFeatureScore(null);
       }
     });
     sortByDens.setFont(JvSwingUtils.getLabelFont());
@@ -986,7 +972,7 @@ public class FeatureSettings extends JPanel
     {
       public void actionPerformed(ActionEvent e)
       {
-        sortByDens(null);
+        af.avc.sortAlignmentByFeatureDensity(null);
       }
     });
     cancel.setFont(JvSwingUtils.getLabelFont());
@@ -995,6 +981,7 @@ public class FeatureSettings extends JPanel
     {
       public void actionPerformed(ActionEvent e)
       {
+        fr.setTransparency(originalTransparency);
         updateFeatureRenderer(originalData);
         close();
       }
@@ -1086,131 +1073,6 @@ public class FeatureSettings extends JPanel
     settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH);
   }
 
-  protected void sortByDens(String[] typ)
-  {
-    sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
-  }
-
-  protected void sortBy(String[] typ, String methodText, final String method)
-  {
-    if (typ == null)
-    {
-      typ = getDisplayedFeatureTypes();
-    }
-    String gps[] = null;
-    gps = getDisplayedFeatureGroups();
-    if (typ != null)
-    {
-      ArrayList types = new ArrayList();
-      for (int i = 0; i < typ.length; i++)
-      {
-        if (typ[i] != null)
-        {
-          types.add(typ[i]);
-        }
-        typ = new String[types.size()];
-        types.toArray(typ);
-      }
-    }
-    if (gps != null)
-    {
-      ArrayList grps = new ArrayList();
-
-      for (int i = 0; i < gps.length; i++)
-      {
-        if (gps[i] != null)
-        {
-          grps.add(gps[i]);
-        }
-      }
-      gps = new String[grps.size()];
-      grps.toArray(gps);
-    }
-    AlignmentPanel alignPanel = af.alignPanel;
-    AlignmentI al = alignPanel.av.getAlignment();
-
-    int start, stop;
-    SequenceGroup sg = alignPanel.av.getSelectionGroup();
-    if (sg != null)
-    {
-      start = sg.getStartRes();
-      stop = sg.getEndRes();
-    }
-    else
-    {
-      start = 0;
-      stop = al.getWidth();
-    }
-    SequenceI[] oldOrder = al.getSequencesArray();
-    AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
-    af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
-            .getAlignment()));
-    alignPanel.paintAlignment(true);
-
-  }
-
-  protected void sortByScore(String[] typ)
-  {
-    sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
-  }
-
-  private String[] getDisplayedFeatureTypes()
-  {
-    String[] typ = null;
-    if (fr != null)
-    {
-      synchronized (fr.renderOrder)
-      {
-        typ = new String[fr.renderOrder.length];
-        System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length);
-        for (int i = 0; i < typ.length; i++)
-        {
-          if (af.viewport.featuresDisplayed.get(typ[i]) == null)
-          {
-            typ[i] = null;
-          }
-        }
-      }
-    }
-    return typ;
-  }
-
-  private String[] getDisplayedFeatureGroups()
-  {
-    String[] gps = null;
-    ArrayList<String> _gps = new ArrayList<String>();
-    if (fr != null)
-    {
-
-      if (fr.featureGroups != null)
-      {
-        Iterator en = fr.featureGroups.keySet().iterator();
-        int g = 0;
-        boolean valid = false;
-        while (en.hasNext())
-        {
-          String gp = (String) en.next();
-          Boolean on = (Boolean) fr.featureGroups.get(gp);
-          if (on != null && on.booleanValue())
-          {
-            valid = true;
-            _gps.add(gp);
-          }
-        }
-        if (!valid)
-        {
-          return null;
-        }
-        else
-        {
-          gps = new String[_gps.size()];
-          _gps.toArray(gps);
-        }
-      }
-    }
-    return gps;
-  }
-
   public void fetchDAS_actionPerformed(ActionEvent e)
   {
     fetchDAS.setEnabled(false);
index ee779f7..30a8a5e 100755 (executable)
@@ -100,7 +100,7 @@ public class IdPanel extends JPanel implements MouseListener,
       seqAnnotReport
               .createSequenceAnnotationReport(tip, sequence,
                       av.isShowDbRefs(), av.isShowNpFeats(),
-                      sp.seqCanvas.fr.minmax);
+                      sp.seqCanvas.fr.getMinMax());
       setToolTipText("<html>" + sequence.getDisplayId(true) + " "
               + tip.toString() + "</html>");
     }
index 3ab5a8d..d7453c8 100644 (file)
@@ -42,6 +42,8 @@ import jalview.schemes.*;
 import jalview.util.Platform;
 import jalview.util.jarInputStreamProvider;
 import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
+import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
 import jalview.ws.jws2.Jws2Discoverer;
 import jalview.ws.jws2.dm.AAConSettings;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
@@ -1081,11 +1083,12 @@ public class Jalview2XML
       view.setFollowHighlight(av.followHighlight);
       view.setFollowSelection(av.followSelection);
       view.setIgnoreGapsinConsensus(av.getIgnoreGapsConsensus());
-      if (av.featuresDisplayed != null)
+      if (av.getFeaturesDisplayed() != null)
       {
         jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
 
-        String[] renderOrder = ap.seqPanel.seqCanvas.getFeatureRenderer().renderOrder;
+        String[] renderOrder = ap.seqPanel.seqCanvas.getFeatureRenderer()
+                .getRenderOrder().toArray(new String[0]);
 
         Vector settingsAdded = new Vector();
         Object gstyle = null;
@@ -1116,8 +1119,8 @@ public class Jalview2XML
                       .getColour(renderOrder[ro]).getRGB());
             }
 
-            setting.setDisplay(av.featuresDisplayed
-                    .containsKey(renderOrder[ro]));
+            setting.setDisplay(av.getFeaturesDisplayed().isVisible(
+                    renderOrder[ro]));
             float rorder = ap.seqPanel.seqCanvas.getFeatureRenderer()
                     .getOrder(renderOrder[ro]);
             if (rorder > -1)
@@ -1130,8 +1133,8 @@ public class Jalview2XML
         }
 
         // Make sure we save none displayed feature settings
-        Iterator en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureColours
-                .keySet().iterator();
+        Iterator en = ap.seqPanel.seqCanvas.getFeatureRenderer()
+                .getFeatureColours().keySet().iterator();
         while (en.hasNext())
         {
           String key = en.next().toString();
@@ -1155,8 +1158,9 @@ public class Jalview2XML
           fs.addSetting(setting);
           settingsAdded.addElement(key);
         }
-        en = ap.seqPanel.seqCanvas.getFeatureRenderer().featureGroups
-                .keySet().iterator();
+        // is groups actually supposed to be a map here ?
+        en = ap.seqPanel.seqCanvas.getFeatureRenderer().getFeatureGroups()
+                .iterator();
         Vector groupsAdded = new Vector();
         while (en.hasNext())
         {
@@ -1168,7 +1172,7 @@ public class Jalview2XML
           Group g = new Group();
           g.setName(grp);
           g.setDisplay(((Boolean) ap.seqPanel.seqCanvas
-                  .getFeatureRenderer().featureGroups.get(grp))
+                  .getFeatureRenderer().checkGroupVisibility(grp, false))
                   .booleanValue());
           fs.addGroup(g);
           groupsAdded.addElement(grp);
@@ -3500,9 +3504,14 @@ public class Jalview2XML
     // recover featre settings
     if (jms.getFeatureSettings() != null)
     {
-      af.viewport.featuresDisplayed = new Hashtable();
+      FeaturesDisplayed fdi;
+      af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
       String[] renderOrder = new String[jms.getFeatureSettings()
               .getSettingCount()];
+      Hashtable featureGroups = new Hashtable();
+      Hashtable featureColours = new Hashtable();
+      Hashtable featureOrder = new Hashtable();
+
       for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
       {
         Setting setting = jms.getFeatureSettings().getSetting(fs);
@@ -3529,37 +3538,42 @@ public class Jalview2XML
             gc.setColourByLabel(setting.getColourByLabel());
           }
           // and put in the feature colour table.
-          af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
-                  setting.getType(), gc);
+          featureColours.put(setting.getType(), gc);
         }
         else
         {
-          af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
-                  setting.getType(),
+          featureColours.put(setting.getType(),
                   new java.awt.Color(setting.getColour()));
         }
         renderOrder[fs] = setting.getType();
         if (setting.hasOrder())
-          af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
-                  setting.getType(), setting.getOrder());
+        {
+          featureOrder.put(setting.getType(), setting.getOrder());
+        }
         else
-          af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setOrder(
-                  setting.getType(),
-                  fs / jms.getFeatureSettings().getSettingCount());
+        {
+          featureOrder.put(setting.getType(), new Float(fs
+                  / jms.getFeatureSettings().getSettingCount()));
+        }
         if (setting.getDisplay())
         {
-          af.viewport.featuresDisplayed.put(setting.getType(), new Integer(
-                  setting.getColour()));
+          fdi.setVisible(setting.getType());
         }
       }
-      af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().renderOrder = renderOrder;
-      Hashtable fgtable;
-      af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().featureGroups = fgtable = new Hashtable();
+      Hashtable fgtable = new Hashtable();
       for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
       {
         Group grp = jms.getFeatureSettings().getGroup(gs);
         fgtable.put(grp.getName(), new Boolean(grp.getDisplay()));
       }
+      // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
+      // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ?
+      // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
+      FeatureRendererSettings frs = new FeatureRendererSettings(
+              renderOrder, fgtable, featureColours, 1.0f, featureOrder);
+      af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer()
+              .transferSettings(frs);
+
     }
 
     if (view.getHiddenColumnsCount() > 0)
index 718677c..f246fd3 100755 (executable)
@@ -27,10 +27,12 @@ import java.util.jar.*;
 import javax.swing.*;
 
 import org.exolab.castor.xml.*;
+
 import jalview.binding.*;
 import jalview.schemes.*;
 import jalview.util.MessageManager;
 import jalview.util.jarInputStreamProvider;
+import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
 
 /**
  * DOCUMENT ME!
@@ -394,25 +396,27 @@ public class Jalview2XML_V1
 
     if (jms.getFeatureSettings() != null)
     {
-      af.viewport.featuresDisplayed = new Hashtable();
+      Hashtable featuresDisplayed = new Hashtable();
+      Hashtable featureColours = new Hashtable();
       String[] renderOrder = new String[jms.getFeatureSettings()
               .getSettingCount()];
       for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
       {
         Setting setting = jms.getFeatureSettings().getSetting(fs);
 
-        af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().setColour(
+        featureColours.put(
                 setting.getType(), new java.awt.Color(setting.getColour()));
 
         renderOrder[fs] = setting.getType();
 
         if (setting.getDisplay())
         {
-          af.viewport.featuresDisplayed.put(setting.getType(), new Integer(
+          featuresDisplayed.put(setting.getType(), new Integer(
                   setting.getColour()));
         }
       }
-      af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().renderOrder = renderOrder;
+      FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder, new Hashtable(), featureColours, 1.0f, null);
+      af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer().transferSettings(frs);
     }
 
     af.setMenusFromViewport(af.viewport);
index 5edf218..8829692 100755 (executable)
@@ -67,7 +67,7 @@ public class OverviewPanel extends JPanel implements Runnable
   // main visible SeqCanvas
   SequenceRenderer sr;
 
-  FeatureRenderer fr;
+  jalview.renderer.seqfeatures.FeatureRenderer fr;
 
   /**
    * Creates a new OverviewPanel object.
index 3cf4fe0..6b5040e 100644 (file)
@@ -1470,7 +1470,7 @@ public class PopupMenu extends JPopupMenu
                       true,
                       true,
                       false,
-                      (ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr.minmax
+                      (ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr.getMinMax()
                               : null);
       contents.append("</p>");
     }
index 4c2cff2..a13d5f6 100644 (file)
@@ -225,42 +225,6 @@ public class SeqPanel extends JPanel implements MouseListener,
     return seq;
   }
 
-  SequenceFeature[] findFeaturesAtRes(SequenceI sequence, int res)
-  {
-    Vector tmp = new Vector();
-    SequenceFeature[] features = sequence.getSequenceFeatures();
-    if (features != null)
-    {
-      for (int i = 0; i < features.length; i++)
-      {
-        if (av.featuresDisplayed == null
-                || !av.featuresDisplayed.containsKey(features[i].getType()))
-        {
-          continue;
-        }
-
-        if (features[i].featureGroup != null
-                && seqCanvas.fr.featureGroups != null
-                && seqCanvas.fr.featureGroups
-                        .containsKey(features[i].featureGroup)
-                && !((Boolean) seqCanvas.fr.featureGroups
-                        .get(features[i].featureGroup)).booleanValue())
-          continue;
-
-        if ((features[i].getBegin() <= res)
-                && (features[i].getEnd() >= res))
-        {
-          tmp.addElement(features[i]);
-        }
-      }
-    }
-
-    features = new SequenceFeature[tmp.size()];
-    tmp.copyInto(features);
-
-    return features;
-  }
-
   void endEditing()
   {
     if (editCommand != null && editCommand.getSize() > 0)
@@ -729,11 +693,11 @@ public class SeqPanel extends JPanel implements MouseListener,
     if (av.isShowSequenceFeatures())
     {
       int rpos;
-      SequenceFeature[] features = findFeaturesAtRes(
+      List<SequenceFeature> features = ap.getFeatureRenderer().findFeaturesAtRes(
               sequence.getDatasetSequence(),
               rpos = sequence.findPosition(res));
       seqARep.appendFeatures(tooltipText, rpos, features,
-              this.ap.seqPanel.seqCanvas.fr.minmax);
+              this.ap.seqPanel.seqCanvas.fr.getMinMax());
     }
     if (tooltipText.length() == 6) // <html></html>
     {
@@ -1370,21 +1334,21 @@ public class SeqPanel extends JPanel implements MouseListener,
         av.setSelectionGroup(null);
       }
 
-      SequenceFeature[] features = findFeaturesAtRes(
+      List<SequenceFeature> features = seqCanvas.getFeatureRenderer().findFeaturesAtRes(
               sequence.getDatasetSequence(),
               sequence.findPosition(findRes(evt)));
 
-      if (features != null && features.length > 0)
+      if (features != null && features.size()> 0)
       {
         SearchResults highlight = new SearchResults();
-        highlight.addResult(sequence, features[0].getBegin(),
-                features[0].getEnd());
+        highlight.addResult(sequence, features.get(0).getBegin(),
+                features.get(0).getEnd());
         seqCanvas.highlightSearchResults(highlight);
       }
-      if (features != null && features.length > 0)
+      if (features != null && features.size()> 0)
       {
         seqCanvas.getFeatureRenderer().amendFeatures(new SequenceI[]
-        { sequence }, features, false, ap);
+        { sequence }, features.toArray(new SequenceFeature[features.size()]), false, ap);
 
         seqCanvas.highlightSearchResults(null);
       }
@@ -1499,16 +1463,16 @@ public class SeqPanel extends JPanel implements MouseListener,
 
     if (javax.swing.SwingUtilities.isRightMouseButton(evt))
     {
-      SequenceFeature[] allFeatures = findFeaturesAtRes(
+      List<SequenceFeature> allFeatures = ap.getFeatureRenderer().findFeaturesAtRes(
               sequence.getDatasetSequence(), sequence.findPosition(res));
       Vector links = new Vector();
-      for (int i = 0; i < allFeatures.length; i++)
+      for (SequenceFeature sf:allFeatures)
       {
-        if (allFeatures[i].links != null)
+        if (sf.links != null)
         {
-          for (int j = 0; j < allFeatures[i].links.size(); j++)
+          for (int j = 0; j < sf.links.size(); j++)
           {
-            links.addElement(allFeatures[i].links.elementAt(j));
+            links.addElement(sf.links.elementAt(j));
           }
         }
       }
index 87b829f..5b621e7 100755 (executable)
@@ -678,7 +678,7 @@ public class FeaturesFile extends AlignFile
    *          hash of feature types and colours
    * @return features file contents
    */
-  public String printJalviewFormat(SequenceI[] seqs, Hashtable visible)
+  public String printJalviewFormat(SequenceI[] seqs, Map<String,Object> visible)
   {
     return printJalviewFormat(seqs, visible, true, true);
   }
@@ -697,7 +697,7 @@ public class FeaturesFile extends AlignFile
    *          of group or type)
    * @return features file contents
    */
-  public String printJalviewFormat(SequenceI[] seqs, Hashtable visible,
+  public String printJalviewFormat(SequenceI[] seqs, Map visible,
           boolean visOnly, boolean nonpos)
   {
     StringBuffer out = new StringBuffer();
@@ -714,11 +714,11 @@ public class FeaturesFile extends AlignFile
       // write feature colours only if we're given them and we are generating
       // viewed features
       // TODO: decide if feature links should also be written here ?
-      Enumeration en = visible.keys();
+      Iterator en = visible.keySet().iterator();
       String type, color;
-      while (en.hasMoreElements())
+      while (en.hasNext())
       {
-        type = en.nextElement().toString();
+        type = en.next().toString();
 
         if (visible.get(type) instanceof GraduatedColor)
         {
@@ -926,12 +926,12 @@ public class FeaturesFile extends AlignFile
    * @param visible
    * @return
    */
-  public String printGFFFormat(SequenceI[] seqs, Hashtable visible)
+  public String printGFFFormat(SequenceI[] seqs, Map<String,Object> visible)
   {
     return printGFFFormat(seqs, visible, true, true);
   }
 
-  public String printGFFFormat(SequenceI[] seqs, Hashtable visible,
+  public String printGFFFormat(SequenceI[] seqs, Map<String,Object> visible,
           boolean visOnly, boolean nonpos)
   {
     StringBuffer out = new StringBuffer();
index ac7f5b3..af5fc03 100755 (executable)
@@ -34,7 +34,7 @@ public class HTMLOutput
 
   SequenceRenderer sr;
 
-  FeatureRenderer fr;
+  jalview.renderer.seqfeatures.FeatureRenderer fr;
 
   Color color;
 
index 6fba9c6..1757239 100644 (file)
@@ -22,6 +22,7 @@ package jalview.io;
 
 import java.util.ArrayList;
 import java.util.Hashtable;
+import java.util.List;
 import java.util.Vector;
 
 import jalview.datamodel.DBRefEntry;
@@ -54,30 +55,30 @@ public class SequenceAnnotationReport
    *          TODO refactor to Jalview 'utilities' somehow.
    */
   public void appendFeatures(final StringBuffer tooltipText2, int rpos,
-          SequenceFeature[] features)
+          List<SequenceFeature> features)
   {
     appendFeatures(tooltipText2, rpos, features, null);
   }
 
   public void appendFeatures(final StringBuffer tooltipText2, int rpos,
-          SequenceFeature[] features, Hashtable minmax)
+          List<SequenceFeature> features, Hashtable minmax)
   {
     String tmpString;
     if (features != null)
     {
-      for (int i = 0; i < features.length; i++)
+      for (SequenceFeature feature:features)
       {
-        if (features[i].getType().equals("disulfide bond"))
+        if (feature.getType().equals("disulfide bond"))
         {
-          if (features[i].getBegin() == rpos
-                  || features[i].getEnd() == rpos)
+          if (feature.getBegin() == rpos
+                  || feature.getEnd() == rpos)
           {
             if (tooltipText2.length() > 6)
             {
               tooltipText2.append("<br>");
             }
-            tooltipText2.append("disulfide bond " + features[i].getBegin()
-                    + ":" + features[i].getEnd());
+            tooltipText2.append("disulfide bond " + feature.getBegin()
+                    + ":" + feature.getEnd());
           }
         }
         else
@@ -87,25 +88,25 @@ public class SequenceAnnotationReport
             tooltipText2.append("<br>");
           }
           // TODO: remove this hack to display link only features
-          boolean linkOnly = features[i].getValue("linkonly") != null;
+          boolean linkOnly = feature.getValue("linkonly") != null;
           if (!linkOnly)
           {
-            tooltipText2.append(features[i].getType() + " ");
+            tooltipText2.append(feature.getType() + " ");
             if (rpos != 0)
             {
               // we are marking a positional feature
-              tooltipText2.append(features[i].begin);
+              tooltipText2.append(feature.begin);
             }
-            if (features[i].begin != features[i].end)
+            if (feature.begin != feature.end)
             {
-              tooltipText2.append(" " + features[i].end);
+              tooltipText2.append(" " + feature.end);
             }
 
-            if (features[i].getDescription() != null
-                    && !features[i].description.equals(features[i]
+            if (feature.getDescription() != null
+                    && !feature.description.equals(feature
                             .getType()))
             {
-              tmpString = features[i].getDescription();
+              tmpString = feature.getDescription();
               String tmp2up = tmpString.toUpperCase();
               int startTag = tmp2up.indexOf("<HTML>");
               if (startTag > -1)
@@ -150,27 +151,27 @@ public class SequenceAnnotationReport
               }
             }
             // check score should be shown
-            if (features[i].getScore() != Float.NaN)
+            if (feature.getScore() != Float.NaN)
             {
               float[][] rng = (minmax == null) ? null : ((float[][]) minmax
-                      .get(features[i].getType()));
+                      .get(feature.getType()));
               if (rng != null && rng[0] != null && rng[0][0] != rng[0][1])
               {
-                tooltipText2.append(" Score=" + features[i].getScore());
+                tooltipText2.append(" Score=" + feature.getScore());
               }
             }
-            if (features[i].getValue("status") != null)
+            if (feature.getValue("status") != null)
             {
-              String status = features[i].getValue("status").toString();
+              String status = feature.getValue("status").toString();
               if (status.length() > 0)
               {
-                tooltipText2.append("; (" + features[i].getValue("status")
+                tooltipText2.append("; (" + feature.getValue("status")
                         + ")");
               }
             }
           }
         }
-        if (features[i].links != null)
+        if (feature.links != null)
         {
           if (linkImageURL != null)
           {
@@ -178,7 +179,7 @@ public class SequenceAnnotationReport
           }
           else
           {
-            for (String urlstring : (Vector<String>) features[i].links)
+            for (String urlstring : (Vector<String>) feature.links)
             {
               try
               {
@@ -364,7 +365,6 @@ public class SequenceAnnotationReport
 
     // ADD NON POSITIONAL SEQUENCE INFO
     SequenceFeature[] features = ds.getSequenceFeatures();
-    SequenceFeature[] tfeat = new SequenceFeature[1];
     if (showNpFeats && features != null)
     {
       for (int i = 0; i < features.length; i++)
@@ -372,7 +372,8 @@ public class SequenceAnnotationReport
         if (features[i].begin == 0 && features[i].end == 0)
         {
           int sz = -tip.length();
-          tfeat[0] = features[i];
+          List<SequenceFeature> tfeat = new ArrayList<SequenceFeature>();
+          tfeat.add(features[i]);
           appendFeatures(tip, 0, tfeat, minmax);
           sz += tip.length();
           maxWidth = Math.max(maxWidth, sz);
diff --git a/src/jalview/renderer/seqfeatures/FeatureRenderer.java b/src/jalview/renderer/seqfeatures/FeatureRenderer.java
new file mode 100644 (file)
index 0000000..909ee10
--- /dev/null
@@ -0,0 +1,435 @@
+package jalview.renderer.seqfeatures;
+
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+public class FeatureRenderer extends
+        jalview.viewmodel.seqfeatures.FeatureRendererModel
+{
+
+  FontMetrics fm;
+
+  int charOffset;
+
+  boolean offscreenRender = 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!
+   */
+  protected SequenceI lastSeq;
+
+  char s;
+
+  int i;
+
+  int av_charHeight, av_charWidth;
+
+  boolean av_validCharWidth, av_isShowSeqFeatureHeight;
+
+  protected void updateAvConfig()
+  {
+    av_charHeight = av.getCharHeight();
+    av_charWidth = av.getCharWidth();
+    av_validCharWidth = av.isValidCharWidth();
+    av_isShowSeqFeatureHeight = av.isShowSequenceFeaturesHeight();
+  }
+
+  void renderFeature(Graphics g, SequenceI seq, int fstart, int fend,
+          Color featureColour, int start, int end, int y1)
+  {
+    updateAvConfig();
+    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;
+      }
+      int pady = (y1 + av_charHeight) - av_charHeight / 5;
+      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 (offscreenRender || !av_validCharWidth)
+        {
+          continue;
+        }
+
+        g.setColor(Color.white);
+        charOffset = (av_charWidth - fm.charWidth(s)) / 2;
+        g.drawString(String.valueOf(s), charOffset
+                + (av_charWidth * (i - start)), pady);
+
+      }
+    }
+  }
+
+  void renderScoreFeature(Graphics g, SequenceI seq, int fstart, int fend,
+          Color featureColour, int start, int end, int y1, byte[] bs)
+  {
+    updateAvConfig();
+    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;
+      }
+      int pady = (y1 + av_charHeight) - av_charHeight / 5;
+      int ystrt = 0, yend = av_charHeight;
+      if (bs[0] != 0)
+      {
+        // signed - zero is always middle of residue line.
+        if (bs[1] < 128)
+        {
+          yend = av_charHeight * (128 - bs[1]) / 512;
+          ystrt = av_charHeight - yend / 2;
+        }
+        else
+        {
+          ystrt = av_charHeight / 2;
+          yend = av_charHeight * (bs[1] - 128) / 512;
+        }
+      }
+      else
+      {
+        yend = av_charHeight * bs[1] / 255;
+        ystrt = av_charHeight - yend;
+
+      }
+      for (i = fstart; i <= fend; i++)
+      {
+        s = seq.getCharAt(i);
+
+        if (jalview.util.Comparison.isGap(s))
+        {
+          continue;
+        }
+
+        g.setColor(featureColour);
+        int x = (i - start) * av_charWidth;
+        g.drawRect(x, y1, av_charWidth, av_charHeight);
+        g.fillRect(x, y1 + ystrt, av_charWidth, yend);
+
+        if (offscreenRender || !av_validCharWidth)
+        {
+          continue;
+        }
+
+        g.setColor(Color.black);
+        charOffset = (av_charWidth - fm.charWidth(s)) / 2;
+        g.drawString(String.valueOf(s), charOffset
+                + (av_charWidth * (i - start)), pady);
+
+      }
+    }
+  }
+
+  BufferedImage offscreenImage;
+
+  public Color findFeatureColour(Color initialCol, SequenceI seq, int res)
+  {
+    return new Color(findFeatureColour(initialCol.getRGB(), seq, res));
+  }
+
+  /**
+   * This is used by the Molecule Viewer and Overview to get the accurate
+   * colourof the rendered sequence
+   */
+  public synchronized int findFeatureColour(int initialCol, final SequenceI seq,
+          int column)
+  {
+    if (!av.isShowSequenceFeatures())
+    {
+      return initialCol;
+    }
+
+    final SequenceI aseq = (seq.getDatasetSequence() != null) ? seq
+            .getDatasetSequence() : seq;
+    if (seq != lastSeq)
+    {
+      lastSeq = seq;
+      sequenceFeatures = aseq.getSequenceFeatures();
+      if (sequenceFeatures != null)
+      {
+        sfSize = sequenceFeatures.length;
+      }
+    }
+    else
+    {
+      if (sequenceFeatures != lastSeq.getSequenceFeatures())
+      {
+        sequenceFeatures = lastSeq.getSequenceFeatures();
+        if (sequenceFeatures != null)
+        {
+          sfSize = sequenceFeatures.length;
+        }
+      }
+    }
+
+    if (sequenceFeatures == null || sfSize == 0)
+    {
+      return initialCol;
+    }
+
+    if (jalview.util.Comparison.isGap(lastSeq.getCharAt(column)))
+    {
+      return Color.white.getRGB();
+    }
+
+    // Only bother making an offscreen image if transparency is applied
+    if (transparency != 1.0f && offscreenImage == null)
+    {
+      offscreenImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
+    }
+
+    currentColour = null;
+    // TODO: non-threadsafe - each rendering thread needs its own instance of
+    // the feature renderer - or this should be synchronized.
+    offscreenRender = true;
+
+    if (offscreenImage != null)
+    {
+      offscreenImage.setRGB(0, 0, initialCol);
+      drawSequence(offscreenImage.getGraphics(), lastSeq, column, column, 0);
+
+      return offscreenImage.getRGB(0, 0);
+    }
+    else
+    {
+      drawSequence(null, lastSeq, lastSeq.findPosition(column), -1, -1);
+
+      if (currentColour == null)
+      {
+        return initialCol;
+      }
+      else
+      {
+        return ((Integer) currentColour).intValue();
+      }
+    }
+
+  }
+
+  private volatile SequenceFeature[] sequenceFeatures;
+
+  int sfSize;
+
+  int sfindex;
+
+  int spos;
+
+  int epos;
+
+  public synchronized void drawSequence(Graphics g, final SequenceI seq,
+          int start, int end, int y1)
+  {
+    final SequenceI aseq = (seq.getDatasetSequence() != null) ? seq
+            .getDatasetSequence() : seq;
+    if (aseq.getSequenceFeatures() == null
+            || aseq.getSequenceFeatures().length == 0)
+    {
+      return;
+    }
+
+    if (g != null)
+    {
+      fm = g.getFontMetrics();
+    }
+
+    updateFeatures();
+
+    if (lastSeq == null || seq != lastSeq
+            || aseq.getSequenceFeatures() != sequenceFeatures)
+    {
+      lastSeq = seq;
+      sequenceFeatures = aseq.getSequenceFeatures();
+    }
+
+    if (transparency != 1 && g != null)
+    {
+      Graphics2D g2 = (Graphics2D) g;
+      g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
+              transparency));
+    }
+
+    if (!offscreenRender)
+    {
+      spos = lastSeq.findPosition(start);
+      epos = lastSeq.findPosition(end);
+    }
+
+    sfSize = sequenceFeatures.length;
+    String type;
+    for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++)
+    {
+      type = renderOrder[renderIndex];
+
+      if (type == null || !showFeatureOfType(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
+                && sequenceFeatures[sfindex].featureGroup.length() != 0
+                && featureGroups
+                        .containsKey(sequenceFeatures[sfindex].featureGroup)
+                && !((Boolean) featureGroups
+                        .get(sequenceFeatures[sfindex].featureGroup))
+                        .booleanValue())
+        {
+          continue;
+        }
+
+        if (!offscreenRender
+                && (sequenceFeatures[sfindex].getBegin() > epos || sequenceFeatures[sfindex]
+                        .getEnd() < spos))
+        {
+          continue;
+        }
+
+        if (offscreenRender && offscreenImage == null)
+        {
+          if (sequenceFeatures[sfindex].begin <= start
+                  && sequenceFeatures[sfindex].end >= start)
+          {
+            // this is passed out to the overview and other sequence renderers
+            // (e.g. molecule viewer) to get displayed colour for rendered
+            // sequence
+            currentColour = new Integer(
+                    getColour(sequenceFeatures[sfindex]).getRGB());
+            // used to be retreived from av.featuresDisplayed
+            // 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,
+                  getColour(sequenceFeatures[sfindex])
+                  // 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,
+                  getColour(sequenceFeatures[sfindex])
+                  // new Color(((Integer) av.featuresDisplayed
+                  // .get(sequenceFeatures[sfindex].type)).intValue())
+                  , start, end, y1);
+
+        }
+        else if (showFeature(sequenceFeatures[sfindex]))
+        {
+          if (av_isShowSeqFeatureHeight
+                  && sequenceFeatures[sfindex].score != Float.NaN)
+          {
+            renderScoreFeature(g, seq,
+                    seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
+                    seq.findIndex(sequenceFeatures[sfindex].end) - 1,
+                    getColour(sequenceFeatures[sfindex]), start, end, y1,
+                    normaliseScore(sequenceFeatures[sfindex]));
+          }
+          else
+          {
+            renderFeature(g, seq,
+                    seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
+                    seq.findIndex(sequenceFeatures[sfindex].end) - 1,
+                    getColour(sequenceFeatures[sfindex]), start, end, y1);
+          }
+        }
+
+      }
+
+    }
+
+    if (transparency != 1.0f && g != null && transparencyAvailable)
+    {
+      Graphics2D g2 = (Graphics2D) g;
+      g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
+              1.0f));
+    }
+  }
+
+  boolean transparencyAvailable = true;
+
+  protected void setTransparencyAvailable(boolean isTransparencyAvailable)
+  {
+    transparencyAvailable = isTransparencyAvailable;
+  }
+
+  @Override
+  public boolean isTransparencyAvailable()
+  {
+    return transparencyAvailable;
+  }
+
+  /**
+   * Called when alignment in associated view has new/modified features to
+   * discover and display.
+   * 
+   */
+  public void featuresAdded()
+  {
+    lastSeq = null;
+    findAllFeatures();
+  }
+}
index a53004d..c3b6c1e 100644 (file)
@@ -252,7 +252,7 @@ public abstract class FeatureRendererModel implements
     {
       for (int i = 0; i < features.length; i++)
       {
-        if (av.areFeaturesDisplayed()
+        if (!av.areFeaturesDisplayed()
                 || !av.getFeaturesDisplayed().isVisible(
                         features[i].getType()))
         {
index 7ab1781..1fa4663 100644 (file)
@@ -28,7 +28,7 @@ import jalview.datamodel.AlignmentView;
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
 import jalview.gui.WebserviceInfo;
-import jalview.gui.FeatureRenderer.FeatureRendererSettings;
+import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
 
 public abstract class AWSThread extends Thread
 {