2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3 * Copyright (C) 2014 The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.appletgui;
27 import java.awt.event.*;
29 import jalview.datamodel.*;
30 import jalview.schemes.AnnotationColourGradient;
31 import jalview.schemes.GraduatedColor;
32 import jalview.util.MessageManager;
40 public class FeatureRenderer implements jalview.api.FeatureRenderer
44 Hashtable featureColours = new Hashtable();
46 // A higher level for grouping features of a
48 Hashtable featureGroups = null;
50 // Holds web links for feature groups and feature types
51 // in the form label|link
52 Hashtable featureLinks = null;
54 // This is actually an Integer held in the hashtable,
55 // Retrieved using the key feature type
64 float transparency = 1f;
66 TransparencySetter transparencySetter = null;
69 * Creates a new FeatureRenderer object.
74 public FeatureRenderer(AlignViewport av)
78 if (!System.getProperty("java.version").startsWith("1.1"))
80 transparencySetter = new TransparencySetter();
84 public void transferSettings(jalview.api.FeatureRenderer _fr)
86 if (_fr instanceof FeatureRenderer)
88 FeatureRenderer fr = (FeatureRenderer) _fr;
89 renderOrder = fr.renderOrder;
90 featureGroups = fr.featureGroups;
91 featureColours = fr.featureColours;
92 transparency = fr.transparency;
93 if (av != null && fr.av != null && fr.av != av)
95 if (fr.av.featuresDisplayed != null)
97 if (av.featuresDisplayed == null)
99 av.featuresDisplayed = new Hashtable();
103 av.featuresDisplayed.clear();
105 Enumeration en = fr.av.featuresDisplayed.keys();
106 while (en.hasMoreElements())
108 av.featuresDisplayed.put(en.nextElement(), Boolean.TRUE);
116 "Implementation error: cannot port feature settings from implementation of type "
117 + _fr.getClass() + " to " + getClass());
121 static String lastFeatureAdded;
123 static String lastFeatureGroupAdded;
125 static String lastDescriptionAdded;
127 int featureIndex = 0;
129 boolean deleteFeature = false;
131 FeatureColourPanel colourPanel;
133 class FeatureColourPanel extends Panel
137 private Color maxCol;
139 private boolean isColourByLabel, isGcol;
142 * render a feature style in the amend feature dialog box
144 public void updateColor(Object newcol)
147 Color bg, col = null;
148 GraduatedColor gcol = null;
150 if (newcol instanceof Color)
153 col = (Color) newcol;
156 else if (newcol instanceof GraduatedColor)
159 gcol = (GraduatedColor) newcol;
164 throw new Error("Invalid color for MyCheckBox");
168 setBackground(bg = col);
172 if (gcol.getThreshType() != AnnotationColourGradient.NO_THRESHOLD)
175 + ((gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD) ? "(>)"
178 if (isColourByLabel = gcol.isColourByLabel())
180 setBackground(bg = Color.white);
181 vlabel += " (by Label)";
185 setBackground(bg = gcol.getMinColor());
186 maxCol = gcol.getMaxColor();
199 public void paint(Graphics g)
201 Dimension d = getSize();
206 g.setColor(Color.white);
207 g.fillRect(d.width / 2, 0, d.width / 2, d.height);
208 g.setColor(Color.black);
209 Font f = new Font("Verdana", Font.PLAIN, 10);
211 g.drawString(MessageManager.getString("label.label"), 0, 0);
216 g.fillRect(d.width / 2, 0, d.width / 2, d.height);
224 boolean amendFeatures(final SequenceI[] sequences,
225 final SequenceFeature[] features, boolean newFeatures,
226 final AlignmentPanel ap)
228 Panel bigPanel = new Panel(new BorderLayout());
229 final TextField name = new TextField(16);
230 final TextField source = new TextField(16);
231 final TextArea description = new TextArea(3, 35);
232 final TextField start = new TextField(8);
233 final TextField end = new TextField(8);
234 final Choice overlaps;
235 Button deleteButton = new Button("Delete");
236 deleteFeature = false;
238 colourPanel = new FeatureColourPanel();
239 colourPanel.setSize(110, 15);
240 final FeatureRenderer fr = this;
242 Panel panel = new Panel(new GridLayout(3, 1));
244 featureIndex = 0; // feature to be amended.
247 // /////////////////////////////////////
248 // /MULTIPLE FEATURES AT SELECTED RESIDUE
249 if (!newFeatures && features.length > 1)
251 panel = new Panel(new GridLayout(4, 1));
253 tmp.add(new Label("Select Feature: "));
254 overlaps = new Choice();
255 for (int i = 0; i < features.length; i++)
257 String item = features[i].getType() + "/" + features[i].getBegin()
258 + "-" + features[i].getEnd();
260 if (features[i].getFeatureGroup() != null)
261 item += " (" + features[i].getFeatureGroup() + ")";
263 overlaps.addItem(item);
268 overlaps.addItemListener(new java.awt.event.ItemListener()
270 public void itemStateChanged(java.awt.event.ItemEvent e)
272 int index = overlaps.getSelectedIndex();
275 featureIndex = index;
276 name.setText(features[index].getType());
277 description.setText(features[index].getDescription());
278 source.setText(features[index].getFeatureGroup());
279 start.setText(features[index].getBegin() + "");
280 end.setText(features[index].getEnd() + "");
282 SearchResults highlight = new SearchResults();
283 highlight.addResult(sequences[0], features[index].getBegin(),
284 features[index].getEnd());
286 ap.seqPanel.seqCanvas.highlightSearchResults(highlight);
289 Object col = getFeatureStyle(name.getText());
292 col = new jalview.schemes.UserColourScheme()
293 .createColourFromName(name.getText());
296 colourPanel.updateColor(col);
303 // ////////////////////////////////////
307 tmp.add(new Label("Name: ", Label.RIGHT));
312 tmp.add(new Label("Group: ", Label.RIGHT));
317 tmp.add(new Label("Colour: ", Label.RIGHT));
318 tmp.add(colourPanel);
320 bigPanel.add(panel, BorderLayout.NORTH);
323 panel.add(new Label("Description: ", Label.RIGHT));
324 panel.add(new ScrollPane().add(description));
328 bigPanel.add(panel, BorderLayout.SOUTH);
331 panel.add(new Label(" Start:", Label.RIGHT));
333 panel.add(new Label(" End:", Label.RIGHT));
335 bigPanel.add(panel, BorderLayout.CENTER);
339 bigPanel.add(panel, BorderLayout.CENTER);
342 if (lastFeatureAdded == null)
344 if (features[0].type != null)
346 lastFeatureAdded = features[0].type;
350 lastFeatureAdded = "feature_1";
354 if (lastFeatureGroupAdded == null)
356 if (features[0].featureGroup != null)
358 lastFeatureGroupAdded = features[0].featureGroup;
362 lastFeatureAdded = "Jalview";
366 String title = newFeatures ? "Create New Sequence Feature(s)"
367 : "Amend/Delete Features for " + sequences[0].getName();
369 final JVDialog dialog = new JVDialog(ap.alignFrame, title, true, 385,
372 dialog.setMainPanel(bigPanel);
376 name.setText(lastFeatureAdded);
377 source.setText(lastFeatureGroupAdded);
381 dialog.ok.setLabel(MessageManager.getString("label.amend"));
382 dialog.buttonPanel.add(deleteButton, 1);
383 deleteButton.addActionListener(new ActionListener()
385 public void actionPerformed(ActionEvent evt)
387 deleteFeature = true;
388 dialog.setVisible(false);
391 name.setText(features[0].getType());
392 source.setText(features[0].getFeatureGroup());
395 start.setText(features[0].getBegin() + "");
396 end.setText(features[0].getEnd() + "");
397 description.setText(features[0].getDescription());
398 Color col = getColour(name.getText());
401 col = new jalview.schemes.UserColourScheme()
402 .createColourFromName(name.getText());
404 Object fcol = getFeatureStyle(name.getText());
405 // simply display the feature color in a box
406 colourPanel.updateColor(fcol);
407 dialog.setResizable(true);
408 // TODO: render the graduated color in the box.
409 colourPanel.addMouseListener(new java.awt.event.MouseAdapter()
411 public void mousePressed(java.awt.event.MouseEvent evt)
413 if (!colourPanel.isGcol)
415 new UserDefinedColours(fr, ap.alignFrame);
419 FeatureColourChooser fcc = new FeatureColourChooser(
420 ap.alignFrame, name.getText());
421 dialog.transferFocus();
425 dialog.setVisible(true);
427 jalview.io.FeaturesFile ffile = new jalview.io.FeaturesFile();
431 // This ensures that the last sequence
432 // is refreshed and new features are rendered
434 lastFeatureAdded = name.getText().trim();
435 lastFeatureGroupAdded = source.getText().trim();
436 lastDescriptionAdded = description.getText().replace('\n', ' ');
439 if (lastFeatureGroupAdded != null && lastFeatureGroupAdded.length() < 1)
440 lastFeatureGroupAdded = null;
445 SequenceFeature sf = features[featureIndex];
448 sf.type = lastFeatureAdded;
449 sf.featureGroup = lastFeatureGroupAdded;
450 sf.description = lastDescriptionAdded;
451 if (!colourPanel.isGcol)
453 // update colour - otherwise its already done.
454 setColour(sf.type, colourPanel.getBackground());
458 sf.begin = Integer.parseInt(start.getText());
459 sf.end = Integer.parseInt(end.getText());
460 } catch (NumberFormatException ex)
464 ffile.parseDescriptionHTML(sf, false);
468 sequences[0].deleteFeature(sf);
474 if (dialog.accept && name.getText().length() > 0)
476 for (int i = 0; i < sequences.length; i++)
478 features[i].type = lastFeatureAdded;
479 features[i].featureGroup = lastFeatureGroupAdded;
480 features[i].description = lastDescriptionAdded;
481 sequences[i].addSequenceFeature(features[i]);
482 ffile.parseDescriptionHTML(features[i], false);
485 if (av.featuresDisplayed == null)
487 av.featuresDisplayed = new Hashtable();
490 if (featureGroups == null)
492 featureGroups = new Hashtable();
495 col = colourPanel.getBackground();
496 // setColour(lastFeatureAdded, fcol);
498 if (lastFeatureGroupAdded != null)
500 featureGroups.put(lastFeatureGroupAdded, new Boolean(true));
502 if (fcol instanceof Color)
504 setColour(lastFeatureAdded, fcol);
506 av.featuresDisplayed.put(lastFeatureAdded,
507 getFeatureStyle(lastFeatureAdded));
511 String[] tro = new String[renderOrder.length];
512 tro[0] = renderOrder[renderOrder.length - 1];
513 System.arraycopy(renderOrder, 0, tro, 1, renderOrder.length - 1);
518 // no update to the alignment
522 // refresh the alignment and the feature settings dialog
523 if (av.featureSettings != null)
525 av.featureSettings.refreshTable();
527 // findAllFeatures();
529 ap.paintAlignment(true);
534 public Color findFeatureColour(Color initialCol, SequenceI seq, int i)
537 if (!av.showSequenceFeatures)
543 sequenceFeatures = lastSeq.getSequenceFeatures();
544 if (sequenceFeatures == null)
549 sfSize = sequenceFeatures.length;
551 if (jalview.util.Comparison.isGap(lastSeq.getCharAt(i)))
556 currentColour = null;
558 drawSequence(null, lastSeq, lastSeq.findPosition(i), -1, -1);
560 if (currentColour == null)
565 return new Color(((Integer) currentColour).intValue());
569 * This is used by the Molecule Viewer to get the accurate colour of the
572 boolean overview = false;
597 // SequenceFeature sf;
600 SequenceFeature[] sequenceFeatures;
602 int sfSize, sfindex, spos, epos;
604 synchronized public void drawSequence(Graphics g, SequenceI seq,
605 int start, int end, int y1)
607 if (seq.getSequenceFeatures() == null
608 || seq.getSequenceFeatures().length == 0)
613 if (transparencySetter != null && g != null)
615 transparencySetter.setTransparency(g, transparency);
618 if (lastSeq == null || seq != lastSeq
619 || sequenceFeatures != seq.getSequenceFeatures())
622 sequenceFeatures = seq.getSequenceFeatures();
623 sfSize = sequenceFeatures.length;
626 if (av.featuresDisplayed == null || renderOrder == null)
629 if (av.featuresDisplayed.size() < 1)
634 sequenceFeatures = seq.getSequenceFeatures();
635 sfSize = sequenceFeatures.length;
639 spos = lastSeq.findPosition(start);
640 epos = lastSeq.findPosition(end);
643 fm = g.getFontMetrics();
647 for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++)
649 type = renderOrder[renderIndex];
650 if (!av.featuresDisplayed.containsKey(type))
655 // loop through all features in sequence to find
656 // current feature to render
657 for (sfindex = 0; sfindex < sfSize; sfindex++)
659 if (!sequenceFeatures[sfindex].type.equals(type))
664 if (featureGroups != null
665 && sequenceFeatures[sfindex].featureGroup != null
667 .containsKey(sequenceFeatures[sfindex].featureGroup)
668 && !((Boolean) featureGroups
669 .get(sequenceFeatures[sfindex].featureGroup))
676 && (sequenceFeatures[sfindex].getBegin() > epos || sequenceFeatures[sfindex]
684 if (sequenceFeatures[sfindex].begin <= start
685 && sequenceFeatures[sfindex].end >= start)
687 currentColour = new Integer(
688 getColour(sequenceFeatures[sfindex]).getRGB());// av.featuresDisplayed
689 // .get(sequenceFeatures[sfindex].type);
693 else if (sequenceFeatures[sfindex].type.equals("disulfide bond"))
696 renderFeature(g, seq,
697 seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
698 seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
699 getColour(sequenceFeatures[sfindex])
700 // new Color(((Integer) av.featuresDisplayed
701 // .get(sequenceFeatures[sfindex].type)).intValue())
703 renderFeature(g, seq,
704 seq.findIndex(sequenceFeatures[sfindex].end) - 1,
705 seq.findIndex(sequenceFeatures[sfindex].end) - 1,
706 getColour(sequenceFeatures[sfindex])
707 // new Color(((Integer) av.featuresDisplayed
708 // .get(sequenceFeatures[sfindex].type)).intValue())
714 if (showFeature(sequenceFeatures[sfindex]))
716 renderFeature(g, seq,
717 seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
718 seq.findIndex(sequenceFeatures[sfindex].end) - 1,
719 getColour(sequenceFeatures[sfindex]), start, end, y1);
726 if (transparencySetter != null && g != null)
728 transparencySetter.setTransparency(g, 1.0f);
736 void renderFeature(Graphics g, SequenceI seq, int fstart, int fend,
737 Color featureColour, int start, int end, int y1)
740 if (((fstart <= end) && (fend >= start)))
743 { // fix for if the feature we have starts before the sequence start,
744 fstart = start; // but the feature end is still valid!!
752 for (i = fstart; i <= fend; i++)
754 s = seq.getCharAt(i);
756 if (jalview.util.Comparison.isGap(s))
761 g.setColor(featureColour);
763 g.fillRect((i - start) * av.charWidth, y1, av.charWidth,
766 if (!av.validCharWidth)
771 g.setColor(Color.white);
772 charOffset = (av.charWidth - fm.charWidth(s)) / 2;
773 g.drawString(String.valueOf(s), charOffset
774 + (av.charWidth * (i - start)), (y1 + av.charHeight)
775 - av.charHeight / 5); // pady = height / 5;
781 Hashtable minmax = null;
784 * Called when alignment in associated view has new/modified features to
785 * discover and display.
788 public void featuresAdded()
795 * find all features on the alignment
797 void findAllFeatures()
799 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
801 av.featuresDisplayed = new Hashtable();
802 Vector allfeatures = new Vector();
803 minmax = new Hashtable();
804 AlignmentI alignment = av.getAlignment();
805 for (int i = 0; i < alignment.getHeight(); i++)
807 SequenceFeature[] features = alignment.getSequenceAt(i)
808 .getSequenceFeatures();
810 if (features == null)
816 while (index < features.length)
818 if (features[index].begin == 0 && features[index].end == 0)
823 if (!av.featuresDisplayed.containsKey(features[index].getType()))
825 if (getColour(features[index].getType()) == null)
827 featureColours.put(features[index].getType(),
828 ucs.createColourFromName(features[index].getType()));
831 av.featuresDisplayed.put(features[index].getType(), new Integer(
832 getColour(features[index].getType()).getRGB()));
833 allfeatures.addElement(features[index].getType());
835 if (features[index].score != Float.NaN)
837 int nonpos = features[index].getBegin() >= 1 ? 0 : 1;
838 float[][] mm = (float[][]) minmax.get(features[index].getType());
843 minmax.put(features[index].getType(), mm);
845 if (mm[nonpos] == null)
847 mm[nonpos] = new float[]
848 { features[index].score, features[index].score };
853 if (mm[nonpos][0] > features[index].score)
855 mm[nonpos][0] = features[index].score;
857 if (mm[nonpos][1] < features[index].score)
859 mm[nonpos][1] = features[index].score;
868 renderOrder = new String[allfeatures.size()];
869 Enumeration en = allfeatures.elements();
870 int i = allfeatures.size() - 1;
871 while (en.hasMoreElements())
873 renderOrder[i] = en.nextElement().toString();
879 * get a feature style object for the given type string. Creates a
880 * java.awt.Color for a featureType with no existing colourscheme. TODO:
881 * replace return type with object implementing standard abstract colour/style
885 * @return java.awt.Color or GraduatedColor
887 public Object getFeatureStyle(String featureType)
889 Object fc = featureColours.get(featureType);
892 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
893 Color col = ucs.createColourFromName(featureType);
894 featureColours.put(featureType, fc = col);
899 public Color getColour(String featureType)
901 Object fc = getFeatureStyle(featureType);
903 if (fc instanceof Color)
909 if (fc instanceof GraduatedColor)
911 return ((GraduatedColor) fc).getMaxColor();
914 throw new Error("Implementation Error: Unrecognised render object "
915 + fc.getClass() + " for features of type " + featureType);
920 * @param sequenceFeature
921 * @return true if feature is visible.
923 private boolean showFeature(SequenceFeature sequenceFeature)
925 Object fc = getFeatureStyle(sequenceFeature.type);
926 if (fc instanceof GraduatedColor)
928 return ((GraduatedColor) fc).isColored(sequenceFeature);
937 * implement graduated colouring for features with scores
940 * @return render colour for the given feature
942 public Color getColour(SequenceFeature feature)
944 Object fc = getFeatureStyle(feature.getType());
945 if (fc instanceof Color)
951 if (fc instanceof GraduatedColor)
953 return ((GraduatedColor) fc).findColor(feature);
956 throw new Error("Implementation Error: Unrecognised render object "
957 + fc.getClass() + " for features of type " + feature.getType());
960 public void setColour(String featureType, Object col)
963 // Color _col = (col instanceof Color) ? ((Color) col) : (col instanceof
964 // GraduatedColor) ? ((GraduatedColor) col).getMaxColor() : null;
965 // Object c = featureColours.get(featureType);
966 // if (c == null || c instanceof Color || (c instanceof GraduatedColor &&
967 // !((GraduatedColor)c).getMaxColor().equals(_col)))
969 featureColours.put(featureType, col);
973 public void setFeaturePriority(Object[][] data)
975 // The feature table will display high priority
976 // features at the top, but theses are the ones
977 // we need to render last, so invert the data
978 if (av.featuresDisplayed != null)
980 av.featuresDisplayed.clear();
984 * if (visibleNew) { if (av.featuresDisplayed != null) {
985 * av.featuresDisplayed.clear(); } else { av.featuresDisplayed = new
986 * Hashtable(); } } if (data == null) { return; }
989 renderOrder = new String[data.length];
993 for (int i = 0; i < data.length; i++)
995 String type = data[i][0].toString();
996 setColour(type, data[i][1]);
997 if (((Boolean) data[i][2]).booleanValue())
999 av.featuresDisplayed.put(type, new Integer(getColour(type)
1003 renderOrder[data.length - i - 1] = type;
1009 * @return a simple list of feature group names or null
1011 public String[] getGroups()
1014 if (featureGroups != null)
1016 String[] gps = new String[featureGroups.size()];
1017 Enumeration gn = featureGroups.keys();
1019 while (gn.hasMoreElements())
1021 gps[i++] = (String) gn.nextElement();
1029 * get visible or invisible groups
1032 * true to return visible groups, false to return hidden ones.
1033 * @return list of groups
1035 public String[] getGroups(boolean visible)
1038 if (featureGroups != null)
1040 Vector gp = new Vector();
1042 Enumeration gn = featureGroups.keys();
1043 while (gn.hasMoreElements())
1045 String nm = (String) gn.nextElement();
1046 Boolean state = (Boolean) featureGroups.get(nm);
1047 if (state.booleanValue() == visible)
1052 String[] gps = new String[gp.size()];
1056 while (gn.hasMoreElements())
1058 gps[i++] = (String) gn.nextElement();
1066 * set all feature groups in toset to be visible or invisible
1071 * the state of the named groups to set
1073 public void setGroupState(String[] toset, boolean visible)
1076 if (toset != null && toset.length > 0 && featureGroups != null)
1078 boolean rdrw = false;
1079 for (int i = 0; i < toset.length; i++)
1081 Object st = featureGroups.get(toset[i]);
1082 featureGroups.put(toset[i], new Boolean(visible));
1085 rdrw = rdrw || (visible != ((Boolean) st).booleanValue());
1090 if (this.av != null)
1091 if (this.av.featureSettings != null)
1093 av.featureSettings.rebuildGroups();
1094 this.av.featureSettings.resetTable(true);
1102 av.alignmentChanged(null);
1108 ArrayList<String> hiddenGroups = new ArrayList<String>();
1111 * analyse alignment for groups and hash tables (used to be embedded in
1112 * FeatureSettings.setTableData)
1114 * @return true if features are on the alignment
1116 public boolean buildGroupHash()
1118 boolean alignmentHasFeatures = false;
1119 if (featureGroups == null)
1121 featureGroups = new Hashtable();
1123 hiddenGroups = new ArrayList<String>();
1124 hiddenGroups.addAll(featureGroups.keySet());
1125 ArrayList allFeatures = new ArrayList();
1126 ArrayList allGroups = new ArrayList();
1127 SequenceFeature[] tmpfeatures;
1129 AlignmentI alignment = av.getAlignment();
1130 for (int i = 0; i < alignment.getHeight(); i++)
1132 if (alignment.getSequenceAt(i).getSequenceFeatures() == null)
1137 alignmentHasFeatures = true;
1139 tmpfeatures = alignment.getSequenceAt(i).getSequenceFeatures();
1141 while (index < tmpfeatures.length)
1143 if (tmpfeatures[index].getFeatureGroup() != null)
1145 group = tmpfeatures[index].featureGroup;
1146 // Remove group from the hiddenGroup list
1147 hiddenGroups.remove(group);
1148 if (!allGroups.contains(group))
1150 allGroups.add(group);
1152 boolean visible = true;
1153 if (featureGroups.containsKey(group))
1155 visible = ((Boolean) featureGroups.get(group)).booleanValue();
1159 featureGroups.put(group, new Boolean(visible));
1164 if (!allFeatures.contains(tmpfeatures[index].getType()))
1166 allFeatures.add(tmpfeatures[index].getType());
1172 return alignmentHasFeatures;
1176 * rebuild the featuresDisplayed and renderorder list based on the
1177 * featureGroups hash and any existing display state and force a repaint if
1180 * @return true if alignment has visible features
1182 public boolean buildFeatureHash()
1184 boolean alignmentHasFeatures = false;
1185 if (featureGroups == null)
1187 alignmentHasFeatures = buildGroupHash();
1189 if (!alignmentHasFeatures)
1191 Hashtable fdisp = av.featuresDisplayed;
1192 Vector allFeatures = new Vector();
1193 SequenceFeature[] tmpfeatures;
1195 AlignmentI alignment = av.getAlignment();
1196 for (int i = 0; i < alignment.getHeight(); i++)
1198 if (alignment.getSequenceAt(i).getSequenceFeatures() == null)
1203 alignmentHasFeatures = true;
1205 tmpfeatures = alignment.getSequenceAt(i).getSequenceFeatures();
1207 while (index < tmpfeatures.length)
1209 boolean visible = true;
1210 if (tmpfeatures[index].getFeatureGroup() != null)
1212 group = tmpfeatures[index].featureGroup;
1213 if (featureGroups.containsKey(group))
1215 visible = ((Boolean) featureGroups.get(group)).booleanValue();
1219 if (visible && !allFeatures.contains(tmpfeatures[index].getType()))
1221 allFeatures.addElement(tmpfeatures[index].getType());
1226 if (allFeatures.size() > 0)
1228 String[] neworder = new String[allFeatures.size()];
1229 int p = neworder.length - 1;
1230 for (int i = renderOrder.length - 1; i >= 0; i--)
1232 if (allFeatures.contains(renderOrder[i]))
1234 neworder[p--] = renderOrder[i];
1235 allFeatures.removeElement(renderOrder[i]);
1239 av.featuresDisplayed.remove(renderOrder[i]);
1242 for (int i = allFeatures.size() - 1; i > 0; i++)
1244 Object e = allFeatures.elementAt(i);
1247 neworder[p--] = (String) e;
1248 av.featuresDisplayed.put(e, getColour((String) e));
1251 renderOrder = neworder;
1255 return alignmentHasFeatures;
1260 * @return the displayed feature type as an array of strings
1262 protected String[] getDisplayedFeatureTypes()
1264 String[] typ = null;
1265 synchronized (renderOrder)
1267 typ = new String[renderOrder.length];
1268 System.arraycopy(renderOrder, 0, typ, 0, typ.length);
1269 for (int i = 0; i < typ.length; i++)
1271 if (av.featuresDisplayed.get(typ[i]) == null)
1281 class TransparencySetter
1283 void setTransparency(Graphics g, float value)
1285 Graphics2D g2 = (Graphics2D) g;
1286 g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,