- 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)