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(FeatureRenderer fr)
86 renderOrder = fr.renderOrder;
87 featureGroups = fr.featureGroups;
88 featureColours = fr.featureColours;
89 transparency = fr.transparency;
90 if (av != null && fr.av != null && fr.av != av)
92 if (fr.av.featuresDisplayed != null)
94 if (av.featuresDisplayed == null)
96 av.featuresDisplayed = new Hashtable();
100 av.featuresDisplayed.clear();
102 Enumeration en = fr.av.featuresDisplayed.keys();
103 while (en.hasMoreElements())
105 av.featuresDisplayed.put(en.nextElement(), Boolean.TRUE);
111 static String lastFeatureAdded;
113 static String lastFeatureGroupAdded;
115 static String lastDescriptionAdded;
117 int featureIndex = 0;
119 boolean deleteFeature = false;
121 FeatureColourPanel colourPanel;
123 class FeatureColourPanel extends Panel
127 private Color maxCol;
129 private boolean isColourByLabel, isGcol;
132 * render a feature style in the amend feature dialog box
134 public void updateColor(Object newcol)
137 Color bg, col = null;
138 GraduatedColor gcol = null;
140 if (newcol instanceof Color)
143 col = (Color) newcol;
146 else if (newcol instanceof GraduatedColor)
149 gcol = (GraduatedColor) newcol;
154 throw new Error(MessageManager.getString("error.invalid_colour_for_mycheckbox"));
158 setBackground(bg = col);
162 if (gcol.getThreshType() != AnnotationColourGradient.NO_THRESHOLD)
165 + ((gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD) ? "(>)"
168 if (isColourByLabel = gcol.isColourByLabel())
170 setBackground(bg = Color.white);
171 vlabel += " (by Label)";
175 setBackground(bg = gcol.getMinColor());
176 maxCol = gcol.getMaxColor();
189 public void paint(Graphics g)
191 Dimension d = getSize();
196 g.setColor(Color.white);
197 g.fillRect(d.width / 2, 0, d.width / 2, d.height);
198 g.setColor(Color.black);
199 Font f = new Font("Verdana", Font.PLAIN, 10);
201 g.drawString(MessageManager.getString("label.label"), 0, 0);
206 g.fillRect(d.width / 2, 0, d.width / 2, d.height);
214 boolean amendFeatures(final SequenceI[] sequences,
215 final SequenceFeature[] features, boolean newFeatures,
216 final AlignmentPanel ap)
218 Panel bigPanel = new Panel(new BorderLayout());
219 final TextField name = new TextField(16);
220 final TextField source = new TextField(16);
221 final TextArea description = new TextArea(3, 35);
222 final TextField start = new TextField(8);
223 final TextField end = new TextField(8);
224 final Choice overlaps;
225 Button deleteButton = new Button("Delete");
226 deleteFeature = false;
228 colourPanel = new FeatureColourPanel();
229 colourPanel.setSize(110, 15);
230 final FeatureRenderer fr = this;
232 Panel panel = new Panel(new GridLayout(3, 1));
234 featureIndex = 0; // feature to be amended.
237 // /////////////////////////////////////
238 // /MULTIPLE FEATURES AT SELECTED RESIDUE
239 if (!newFeatures && features.length > 1)
241 panel = new Panel(new GridLayout(4, 1));
243 tmp.add(new Label("Select Feature: "));
244 overlaps = new Choice();
245 for (int i = 0; i < features.length; i++)
247 String item = features[i].getType() + "/" + features[i].getBegin()
248 + "-" + features[i].getEnd();
250 if (features[i].getFeatureGroup() != null)
251 item += " (" + features[i].getFeatureGroup() + ")";
253 overlaps.addItem(item);
258 overlaps.addItemListener(new java.awt.event.ItemListener()
260 public void itemStateChanged(java.awt.event.ItemEvent e)
262 int index = overlaps.getSelectedIndex();
265 featureIndex = index;
266 name.setText(features[index].getType());
267 description.setText(features[index].getDescription());
268 source.setText(features[index].getFeatureGroup());
269 start.setText(features[index].getBegin() + "");
270 end.setText(features[index].getEnd() + "");
272 SearchResults highlight = new SearchResults();
273 highlight.addResult(sequences[0], features[index].getBegin(),
274 features[index].getEnd());
276 ap.seqPanel.seqCanvas.highlightSearchResults(highlight);
279 Object col = getFeatureStyle(name.getText());
282 col = new jalview.schemes.UserColourScheme()
283 .createColourFromName(name.getText());
286 colourPanel.updateColor(col);
293 // ////////////////////////////////////
297 tmp.add(new Label("Name: ", Label.RIGHT));
302 tmp.add(new Label("Group: ", Label.RIGHT));
307 tmp.add(new Label("Colour: ", Label.RIGHT));
308 tmp.add(colourPanel);
310 bigPanel.add(panel, BorderLayout.NORTH);
313 panel.add(new Label("Description: ", Label.RIGHT));
314 panel.add(new ScrollPane().add(description));
318 bigPanel.add(panel, BorderLayout.SOUTH);
321 panel.add(new Label(" Start:", Label.RIGHT));
323 panel.add(new Label(" End:", Label.RIGHT));
325 bigPanel.add(panel, BorderLayout.CENTER);
329 bigPanel.add(panel, BorderLayout.CENTER);
332 if (lastFeatureAdded == null)
334 if (features[0].type != null)
336 lastFeatureAdded = features[0].type;
340 lastFeatureAdded = "feature_1";
344 if (lastFeatureGroupAdded == null)
346 if (features[0].featureGroup != null)
348 lastFeatureGroupAdded = features[0].featureGroup;
352 lastFeatureAdded = "Jalview";
356 String title = newFeatures ? MessageManager.getString("label.create_new_sequence_features")
357 : MessageManager.formatMessage("label.amend_delete_features", new String[]{sequences[0].getName()});
359 final JVDialog dialog = new JVDialog(ap.alignFrame, title, true, 385,
362 dialog.setMainPanel(bigPanel);
366 name.setText(lastFeatureAdded);
367 source.setText(lastFeatureGroupAdded);
371 dialog.ok.setLabel(MessageManager.getString("label.amend"));
372 dialog.buttonPanel.add(deleteButton, 1);
373 deleteButton.addActionListener(new ActionListener()
375 public void actionPerformed(ActionEvent evt)
377 deleteFeature = true;
378 dialog.setVisible(false);
381 name.setText(features[0].getType());
382 source.setText(features[0].getFeatureGroup());
385 start.setText(features[0].getBegin() + "");
386 end.setText(features[0].getEnd() + "");
387 description.setText(features[0].getDescription());
388 Color col = getColour(name.getText());
391 col = new jalview.schemes.UserColourScheme()
392 .createColourFromName(name.getText());
394 Object fcol = getFeatureStyle(name.getText());
395 // simply display the feature color in a box
396 colourPanel.updateColor(fcol);
397 dialog.setResizable(true);
398 // TODO: render the graduated color in the box.
399 colourPanel.addMouseListener(new java.awt.event.MouseAdapter()
401 public void mousePressed(java.awt.event.MouseEvent evt)
403 if (!colourPanel.isGcol)
405 new UserDefinedColours(fr, ap.alignFrame);
409 FeatureColourChooser fcc = new FeatureColourChooser(
410 ap.alignFrame, name.getText());
411 dialog.transferFocus();
415 dialog.setVisible(true);
417 jalview.io.FeaturesFile ffile = new jalview.io.FeaturesFile();
421 // This ensures that the last sequence
422 // is refreshed and new features are rendered
424 lastFeatureAdded = name.getText().trim();
425 lastFeatureGroupAdded = source.getText().trim();
426 lastDescriptionAdded = description.getText().replace('\n', ' ');
429 if (lastFeatureGroupAdded != null && lastFeatureGroupAdded.length() < 1)
430 lastFeatureGroupAdded = null;
435 SequenceFeature sf = features[featureIndex];
438 sf.type = lastFeatureAdded;
439 sf.featureGroup = lastFeatureGroupAdded;
440 sf.description = lastDescriptionAdded;
441 if (!colourPanel.isGcol)
443 // update colour - otherwise its already done.
444 setColour(sf.type, colourPanel.getBackground());
448 sf.begin = Integer.parseInt(start.getText());
449 sf.end = Integer.parseInt(end.getText());
450 } catch (NumberFormatException ex)
454 ffile.parseDescriptionHTML(sf, false);
458 sequences[0].deleteFeature(sf);
464 if (dialog.accept && name.getText().length() > 0)
466 for (int i = 0; i < sequences.length; i++)
468 features[i].type = lastFeatureAdded;
469 features[i].featureGroup = lastFeatureGroupAdded;
470 features[i].description = lastDescriptionAdded;
471 sequences[i].addSequenceFeature(features[i]);
472 ffile.parseDescriptionHTML(features[i], false);
475 if (av.featuresDisplayed == null)
477 av.featuresDisplayed = new Hashtable();
480 if (featureGroups == null)
482 featureGroups = new Hashtable();
485 col = colourPanel.getBackground();
486 // setColour(lastFeatureAdded, fcol);
488 if (lastFeatureGroupAdded != null)
490 featureGroups.put(lastFeatureGroupAdded, new Boolean(true));
492 if (fcol instanceof Color)
494 setColour(lastFeatureAdded, fcol);
496 av.featuresDisplayed.put(lastFeatureAdded,
497 getFeatureStyle(lastFeatureAdded));
501 String[] tro = new String[renderOrder.length];
502 tro[0] = renderOrder[renderOrder.length - 1];
503 System.arraycopy(renderOrder, 0, tro, 1, renderOrder.length - 1);
508 // no update to the alignment
512 // refresh the alignment and the feature settings dialog
513 if (av.featureSettings != null)
515 av.featureSettings.refreshTable();
517 // findAllFeatures();
519 ap.paintAlignment(true);
524 public Color findFeatureColour(Color initialCol, SequenceI seq, int i)
527 if (!av.showSequenceFeatures)
533 sequenceFeatures = lastSeq.getSequenceFeatures();
534 if (sequenceFeatures == null)
539 sfSize = sequenceFeatures.length;
541 if (jalview.util.Comparison.isGap(lastSeq.getCharAt(i)))
546 currentColour = null;
548 drawSequence(null, lastSeq, lastSeq.findPosition(i), -1, -1);
550 if (currentColour == null)
555 return new Color(((Integer) currentColour).intValue());
559 * This is used by the Molecule Viewer to get the accurate colour of the
562 boolean overview = false;
587 // SequenceFeature sf;
590 SequenceFeature[] sequenceFeatures;
592 int sfSize, sfindex, spos, epos;
594 synchronized public void drawSequence(Graphics g, SequenceI seq,
595 int start, int end, int y1)
597 if (seq.getSequenceFeatures() == null
598 || seq.getSequenceFeatures().length == 0)
603 if (transparencySetter != null && g != null)
605 transparencySetter.setTransparency(g, transparency);
608 if (lastSeq == null || seq != lastSeq
609 || sequenceFeatures != seq.getSequenceFeatures())
612 sequenceFeatures = seq.getSequenceFeatures();
613 sfSize = sequenceFeatures.length;
616 if (av.featuresDisplayed == null || renderOrder == null)
619 if (av.featuresDisplayed.size() < 1)
624 sequenceFeatures = seq.getSequenceFeatures();
625 sfSize = sequenceFeatures.length;
629 spos = lastSeq.findPosition(start);
630 epos = lastSeq.findPosition(end);
633 fm = g.getFontMetrics();
637 for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++)
639 type = renderOrder[renderIndex];
640 if (!av.featuresDisplayed.containsKey(type))
645 // loop through all features in sequence to find
646 // current feature to render
647 for (sfindex = 0; sfindex < sfSize; sfindex++)
649 if (!sequenceFeatures[sfindex].type.equals(type))
654 if (featureGroups != null
655 && sequenceFeatures[sfindex].featureGroup != null
657 .containsKey(sequenceFeatures[sfindex].featureGroup)
658 && !((Boolean) featureGroups
659 .get(sequenceFeatures[sfindex].featureGroup))
666 && (sequenceFeatures[sfindex].getBegin() > epos || sequenceFeatures[sfindex]
674 if (sequenceFeatures[sfindex].begin <= start
675 && sequenceFeatures[sfindex].end >= start)
677 currentColour = new Integer(
678 getColour(sequenceFeatures[sfindex]).getRGB());// av.featuresDisplayed
679 // .get(sequenceFeatures[sfindex].type);
683 else if (sequenceFeatures[sfindex].type.equals("disulfide bond"))
686 renderFeature(g, seq,
687 seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
688 seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
689 getColour(sequenceFeatures[sfindex])
690 // new Color(((Integer) av.featuresDisplayed
691 // .get(sequenceFeatures[sfindex].type)).intValue())
693 renderFeature(g, seq,
694 seq.findIndex(sequenceFeatures[sfindex].end) - 1,
695 seq.findIndex(sequenceFeatures[sfindex].end) - 1,
696 getColour(sequenceFeatures[sfindex])
697 // new Color(((Integer) av.featuresDisplayed
698 // .get(sequenceFeatures[sfindex].type)).intValue())
704 if (showFeature(sequenceFeatures[sfindex]))
706 renderFeature(g, seq,
707 seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
708 seq.findIndex(sequenceFeatures[sfindex].end) - 1,
709 getColour(sequenceFeatures[sfindex]), start, end, y1);
716 if (transparencySetter != null && g != null)
718 transparencySetter.setTransparency(g, 1.0f);
726 void renderFeature(Graphics g, SequenceI seq, int fstart, int fend,
727 Color featureColour, int start, int end, int y1)
730 if (((fstart <= end) && (fend >= start)))
733 { // fix for if the feature we have starts before the sequence start,
734 fstart = start; // but the feature end is still valid!!
742 for (i = fstart; i <= fend; i++)
744 s = seq.getCharAt(i);
746 if (jalview.util.Comparison.isGap(s))
751 g.setColor(featureColour);
753 g.fillRect((i - start) * av.charWidth, y1, av.charWidth,
756 if (!av.validCharWidth)
761 g.setColor(Color.white);
762 charOffset = (av.charWidth - fm.charWidth(s)) / 2;
763 g.drawString(String.valueOf(s), charOffset
764 + (av.charWidth * (i - start)), (y1 + av.charHeight)
765 - av.charHeight / 5); // pady = height / 5;
771 Hashtable minmax = null;
774 * Called when alignment in associated view has new/modified features to
775 * discover and display.
778 public void featuresAdded()
785 * find all features on the alignment
787 void findAllFeatures()
789 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
791 av.featuresDisplayed = new Hashtable();
792 Vector allfeatures = new Vector();
793 minmax = new Hashtable();
794 AlignmentI alignment = av.getAlignment();
795 for (int i = 0; i < alignment.getHeight(); i++)
797 SequenceFeature[] features = alignment.getSequenceAt(i)
798 .getSequenceFeatures();
800 if (features == null)
806 while (index < features.length)
808 if (features[index].begin == 0 && features[index].end == 0)
813 if (!av.featuresDisplayed.containsKey(features[index].getType()))
815 if (getColour(features[index].getType()) == null)
817 featureColours.put(features[index].getType(),
818 ucs.createColourFromName(features[index].getType()));
821 av.featuresDisplayed.put(features[index].getType(), new Integer(
822 getColour(features[index].getType()).getRGB()));
823 allfeatures.addElement(features[index].getType());
825 if (features[index].score != Float.NaN)
827 int nonpos = features[index].getBegin() >= 1 ? 0 : 1;
828 float[][] mm = (float[][]) minmax.get(features[index].getType());
833 minmax.put(features[index].getType(), mm);
835 if (mm[nonpos] == null)
837 mm[nonpos] = new float[]
838 { features[index].score, features[index].score };
843 if (mm[nonpos][0] > features[index].score)
845 mm[nonpos][0] = features[index].score;
847 if (mm[nonpos][1] < features[index].score)
849 mm[nonpos][1] = features[index].score;
858 renderOrder = new String[allfeatures.size()];
859 Enumeration en = allfeatures.elements();
860 int i = allfeatures.size() - 1;
861 while (en.hasMoreElements())
863 renderOrder[i] = en.nextElement().toString();
869 * get a feature style object for the given type string. Creates a
870 * java.awt.Color for a featureType with no existing colourscheme. TODO:
871 * replace return type with object implementing standard abstract colour/style
875 * @return java.awt.Color or GraduatedColor
877 public Object getFeatureStyle(String featureType)
879 Object fc = featureColours.get(featureType);
882 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
883 Color col = ucs.createColourFromName(featureType);
884 featureColours.put(featureType, fc = col);
889 public Color getColour(String featureType)
891 Object fc = getFeatureStyle(featureType);
893 if (fc instanceof Color)
899 if (fc instanceof GraduatedColor)
901 return ((GraduatedColor) fc).getMaxColor();
904 throw new Error(MessageManager.formatMessage("error.implementation_error_unrecognised_render_object_for_features_type", new String[]{fc.getClass().getCanonicalName(),featureType}));
909 * @param sequenceFeature
910 * @return true if feature is visible.
912 private boolean showFeature(SequenceFeature sequenceFeature)
914 Object fc = getFeatureStyle(sequenceFeature.type);
915 if (fc instanceof GraduatedColor)
917 return ((GraduatedColor) fc).isColored(sequenceFeature);
926 * implement graduated colouring for features with scores
929 * @return render colour for the given feature
931 public Color getColour(SequenceFeature feature)
933 Object fc = getFeatureStyle(feature.getType());
934 if (fc instanceof Color)
940 if (fc instanceof GraduatedColor)
942 return ((GraduatedColor) fc).findColor(feature);
945 throw new Error("Implementation Error: Unrecognised render object "
946 + fc.getClass() + " for features of type " + feature.getType());
949 public void setColour(String featureType, Object col)
952 // Color _col = (col instanceof Color) ? ((Color) col) : (col instanceof
953 // GraduatedColor) ? ((GraduatedColor) col).getMaxColor() : null;
954 // Object c = featureColours.get(featureType);
955 // if (c == null || c instanceof Color || (c instanceof GraduatedColor &&
956 // !((GraduatedColor)c).getMaxColor().equals(_col)))
958 featureColours.put(featureType, col);
962 public void setFeaturePriority(Object[][] data)
964 // The feature table will display high priority
965 // features at the top, but theses are the ones
966 // we need to render last, so invert the data
967 if (av.featuresDisplayed != null)
969 av.featuresDisplayed.clear();
973 * if (visibleNew) { if (av.featuresDisplayed != null) {
974 * av.featuresDisplayed.clear(); } else { av.featuresDisplayed = new
975 * Hashtable(); } } if (data == null) { return; }
978 renderOrder = new String[data.length];
982 for (int i = 0; i < data.length; i++)
984 String type = data[i][0].toString();
985 setColour(type, data[i][1]);
986 if (((Boolean) data[i][2]).booleanValue())
988 av.featuresDisplayed.put(type, new Integer(getColour(type)
992 renderOrder[data.length - i - 1] = type;
998 * @return a simple list of feature group names or null
1000 public String[] getGroups()
1003 if (featureGroups != null)
1005 String[] gps = new String[featureGroups.size()];
1006 Enumeration gn = featureGroups.keys();
1008 while (gn.hasMoreElements())
1010 gps[i++] = (String) gn.nextElement();
1018 * get visible or invisible groups
1021 * true to return visible groups, false to return hidden ones.
1022 * @return list of groups
1024 public String[] getGroups(boolean visible)
1027 if (featureGroups != null)
1029 Vector gp = new Vector();
1031 Enumeration gn = featureGroups.keys();
1032 while (gn.hasMoreElements())
1034 String nm = (String) gn.nextElement();
1035 Boolean state = (Boolean) featureGroups.get(nm);
1036 if (state.booleanValue() == visible)
1041 String[] gps = new String[gp.size()];
1045 while (gn.hasMoreElements())
1047 gps[i++] = (String) gn.nextElement();
1055 * set all feature groups in toset to be visible or invisible
1060 * the state of the named groups to set
1062 public void setGroupState(String[] toset, boolean visible)
1065 if (toset != null && toset.length > 0 && featureGroups != null)
1067 boolean rdrw = false;
1068 for (int i = 0; i < toset.length; i++)
1070 Object st = featureGroups.get(toset[i]);
1071 featureGroups.put(toset[i], new Boolean(visible));
1074 rdrw = rdrw || (visible != ((Boolean) st).booleanValue());
1079 if (this.av != null)
1080 if (this.av.featureSettings != null)
1082 av.featureSettings.rebuildGroups();
1083 this.av.featureSettings.resetTable(true);
1091 av.alignmentChanged(null);
1097 ArrayList<String> hiddenGroups = new ArrayList<String>();
1100 * analyse alignment for groups and hash tables (used to be embedded in
1101 * FeatureSettings.setTableData)
1103 * @return true if features are on the alignment
1105 public boolean buildGroupHash()
1107 boolean alignmentHasFeatures = false;
1108 if (featureGroups == null)
1110 featureGroups = new Hashtable();
1112 hiddenGroups = new ArrayList<String>();
1113 hiddenGroups.addAll(featureGroups.keySet());
1114 ArrayList allFeatures = new ArrayList();
1115 ArrayList allGroups = new ArrayList();
1116 SequenceFeature[] tmpfeatures;
1118 AlignmentI alignment = av.getAlignment();
1119 for (int i = 0; i < alignment.getHeight(); i++)
1121 if (alignment.getSequenceAt(i).getSequenceFeatures() == null)
1126 alignmentHasFeatures = true;
1128 tmpfeatures = alignment.getSequenceAt(i).getSequenceFeatures();
1130 while (index < tmpfeatures.length)
1132 if (tmpfeatures[index].getFeatureGroup() != null)
1134 group = tmpfeatures[index].featureGroup;
1135 // Remove group from the hiddenGroup list
1136 hiddenGroups.remove(group);
1137 if (!allGroups.contains(group))
1139 allGroups.add(group);
1141 boolean visible = true;
1142 if (featureGroups.containsKey(group))
1144 visible = ((Boolean) featureGroups.get(group)).booleanValue();
1148 featureGroups.put(group, new Boolean(visible));
1153 if (!allFeatures.contains(tmpfeatures[index].getType()))
1155 allFeatures.add(tmpfeatures[index].getType());
1161 return alignmentHasFeatures;
1165 * rebuild the featuresDisplayed and renderorder list based on the
1166 * featureGroups hash and any existing display state and force a repaint if
1169 * @return true if alignment has visible features
1171 public boolean buildFeatureHash()
1173 boolean alignmentHasFeatures = false;
1174 if (featureGroups == null)
1176 alignmentHasFeatures = buildGroupHash();
1178 if (!alignmentHasFeatures)
1180 Hashtable fdisp = av.featuresDisplayed;
1181 Vector allFeatures = new Vector();
1182 SequenceFeature[] tmpfeatures;
1184 AlignmentI alignment = av.getAlignment();
1185 for (int i = 0; i < alignment.getHeight(); i++)
1187 if (alignment.getSequenceAt(i).getSequenceFeatures() == null)
1192 alignmentHasFeatures = true;
1194 tmpfeatures = alignment.getSequenceAt(i).getSequenceFeatures();
1196 while (index < tmpfeatures.length)
1198 boolean visible = true;
1199 if (tmpfeatures[index].getFeatureGroup() != null)
1201 group = tmpfeatures[index].featureGroup;
1202 if (featureGroups.containsKey(group))
1204 visible = ((Boolean) featureGroups.get(group)).booleanValue();
1208 if (visible && !allFeatures.contains(tmpfeatures[index].getType()))
1210 allFeatures.addElement(tmpfeatures[index].getType());
1215 if (allFeatures.size() > 0)
1217 String[] neworder = new String[allFeatures.size()];
1218 int p = neworder.length - 1;
1219 for (int i = renderOrder.length - 1; i >= 0; i--)
1221 if (allFeatures.contains(renderOrder[i]))
1223 neworder[p--] = renderOrder[i];
1224 allFeatures.removeElement(renderOrder[i]);
1228 av.featuresDisplayed.remove(renderOrder[i]);
1231 for (int i = allFeatures.size() - 1; i > 0; i++)
1233 Object e = allFeatures.elementAt(i);
1236 neworder[p--] = (String) e;
1237 av.featuresDisplayed.put(e, getColour((String) e));
1240 renderOrder = neworder;
1244 return alignmentHasFeatures;
1249 * @return the displayed feature type as an array of strings
1251 protected String[] getDisplayedFeatureTypes()
1253 String[] typ = null;
1254 synchronized (renderOrder)
1256 typ = new String[renderOrder.length];
1257 System.arraycopy(renderOrder, 0, typ, 0, typ.length);
1258 for (int i = 0; i < typ.length; i++)
1260 if (av.featuresDisplayed.get(typ[i]) == null)
1270 class TransparencySetter
1272 void setTransparency(Graphics g, float value)
1274 Graphics2D g2 = (Graphics2D) g;
1275 g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,