2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
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 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
17 * The Jalview Authors are detailed in the 'AUTHORS' file.
19 package jalview.appletgui;
25 import java.awt.event.*;
27 import jalview.datamodel.*;
28 import jalview.schemes.AnnotationColourGradient;
29 import jalview.schemes.GraduatedColor;
30 import jalview.util.MessageManager;
38 public class FeatureRenderer implements jalview.api.FeatureRenderer
42 Hashtable featureColours = new Hashtable();
44 // A higher level for grouping features of a
46 Hashtable featureGroups = null;
48 // Holds web links for feature groups and feature types
49 // in the form label|link
50 Hashtable featureLinks = null;
52 // This is actually an Integer held in the hashtable,
53 // Retrieved using the key feature type
62 float transparency = 1f;
64 TransparencySetter transparencySetter = null;
67 * Creates a new FeatureRenderer object.
72 public FeatureRenderer(AlignViewport av)
76 if (!System.getProperty("java.version").startsWith("1.1"))
78 transparencySetter = new TransparencySetter();
82 public void transferSettings(jalview.api.FeatureRenderer _fr)
84 if (_fr instanceof FeatureRenderer)
86 FeatureRenderer fr = (FeatureRenderer) _fr;
87 renderOrder = fr.renderOrder;
88 featureGroups = fr.featureGroups;
89 featureColours = fr.featureColours;
90 transparency = fr.transparency;
91 if (av != null && fr.av != null && fr.av != av)
93 if (fr.av.featuresDisplayed != null)
95 if (av.featuresDisplayed == null)
97 av.featuresDisplayed = new Hashtable();
101 av.featuresDisplayed.clear();
103 Enumeration en = fr.av.featuresDisplayed.keys();
104 while (en.hasMoreElements())
106 av.featuresDisplayed.put(en.nextElement(), Boolean.TRUE);
114 "Implementation error: cannot port feature settings from implementation of type "
115 + _fr.getClass() + " to " + getClass());
119 static String lastFeatureAdded;
121 static String lastFeatureGroupAdded;
123 static String lastDescriptionAdded;
125 int featureIndex = 0;
127 boolean deleteFeature = false;
129 FeatureColourPanel colourPanel;
131 class FeatureColourPanel extends Panel
135 private Color maxCol;
137 private boolean isColourByLabel, isGcol;
140 * render a feature style in the amend feature dialog box
142 public void updateColor(Object newcol)
145 Color bg, col = null;
146 GraduatedColor gcol = null;
148 if (newcol instanceof Color)
151 col = (Color) newcol;
154 else if (newcol instanceof GraduatedColor)
157 gcol = (GraduatedColor) newcol;
162 throw new Error("Invalid color for MyCheckBox");
166 setBackground(bg = col);
170 if (gcol.getThreshType() != AnnotationColourGradient.NO_THRESHOLD)
173 + ((gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD) ? "(>)"
176 if (isColourByLabel = gcol.isColourByLabel())
178 setBackground(bg = Color.white);
179 vlabel += " (by Label)";
183 setBackground(bg = gcol.getMinColor());
184 maxCol = gcol.getMaxColor();
197 public void paint(Graphics g)
199 Dimension d = getSize();
204 g.setColor(Color.white);
205 g.fillRect(d.width / 2, 0, d.width / 2, d.height);
206 g.setColor(Color.black);
207 Font f = new Font("Verdana", Font.PLAIN, 10);
209 g.drawString(MessageManager.getString("label.label"), 0, 0);
214 g.fillRect(d.width / 2, 0, d.width / 2, d.height);
222 boolean amendFeatures(final SequenceI[] sequences,
223 final SequenceFeature[] features, boolean newFeatures,
224 final AlignmentPanel ap)
226 Panel bigPanel = new Panel(new BorderLayout());
227 final TextField name = new TextField(16);
228 final TextField source = new TextField(16);
229 final TextArea description = new TextArea(3, 35);
230 final TextField start = new TextField(8);
231 final TextField end = new TextField(8);
232 final Choice overlaps;
233 Button deleteButton = new Button("Delete");
234 deleteFeature = false;
236 colourPanel = new FeatureColourPanel();
237 colourPanel.setSize(110, 15);
238 final FeatureRenderer fr = this;
240 Panel panel = new Panel(new GridLayout(3, 1));
242 featureIndex = 0; // feature to be amended.
245 // /////////////////////////////////////
246 // /MULTIPLE FEATURES AT SELECTED RESIDUE
247 if (!newFeatures && features.length > 1)
249 panel = new Panel(new GridLayout(4, 1));
251 tmp.add(new Label("Select Feature: "));
252 overlaps = new Choice();
253 for (int i = 0; i < features.length; i++)
255 String item = features[i].getType() + "/" + features[i].getBegin()
256 + "-" + features[i].getEnd();
258 if (features[i].getFeatureGroup() != null)
259 item += " (" + features[i].getFeatureGroup() + ")";
261 overlaps.addItem(item);
266 overlaps.addItemListener(new java.awt.event.ItemListener()
268 public void itemStateChanged(java.awt.event.ItemEvent e)
270 int index = overlaps.getSelectedIndex();
273 featureIndex = index;
274 name.setText(features[index].getType());
275 description.setText(features[index].getDescription());
276 source.setText(features[index].getFeatureGroup());
277 start.setText(features[index].getBegin() + "");
278 end.setText(features[index].getEnd() + "");
280 SearchResults highlight = new SearchResults();
281 highlight.addResult(sequences[0], features[index].getBegin(),
282 features[index].getEnd());
284 ap.seqPanel.seqCanvas.highlightSearchResults(highlight);
287 Object col = getFeatureStyle(name.getText());
290 col = new jalview.schemes.UserColourScheme()
291 .createColourFromName(name.getText());
294 colourPanel.updateColor(col);
301 // ////////////////////////////////////
305 tmp.add(new Label("Name: ", Label.RIGHT));
310 tmp.add(new Label("Group: ", Label.RIGHT));
315 tmp.add(new Label("Colour: ", Label.RIGHT));
316 tmp.add(colourPanel);
318 bigPanel.add(panel, BorderLayout.NORTH);
321 panel.add(new Label("Description: ", Label.RIGHT));
322 panel.add(new ScrollPane().add(description));
326 bigPanel.add(panel, BorderLayout.SOUTH);
329 panel.add(new Label(" Start:", Label.RIGHT));
331 panel.add(new Label(" End:", Label.RIGHT));
333 bigPanel.add(panel, BorderLayout.CENTER);
337 bigPanel.add(panel, BorderLayout.CENTER);
340 if (lastFeatureAdded == null)
342 if (features[0].type != null)
344 lastFeatureAdded = features[0].type;
348 lastFeatureAdded = "feature_1";
352 if (lastFeatureGroupAdded == null)
354 if (features[0].featureGroup != null)
356 lastFeatureGroupAdded = features[0].featureGroup;
360 lastFeatureAdded = "Jalview";
364 String title = newFeatures ? "Create New Sequence Feature(s)"
365 : "Amend/Delete Features for " + sequences[0].getName();
367 final JVDialog dialog = new JVDialog(ap.alignFrame, title, true, 385,
370 dialog.setMainPanel(bigPanel);
374 name.setText(lastFeatureAdded);
375 source.setText(lastFeatureGroupAdded);
379 dialog.ok.setLabel(MessageManager.getString("label.amend"));
380 dialog.buttonPanel.add(deleteButton, 1);
381 deleteButton.addActionListener(new ActionListener()
383 public void actionPerformed(ActionEvent evt)
385 deleteFeature = true;
386 dialog.setVisible(false);
389 name.setText(features[0].getType());
390 source.setText(features[0].getFeatureGroup());
393 start.setText(features[0].getBegin() + "");
394 end.setText(features[0].getEnd() + "");
395 description.setText(features[0].getDescription());
396 Color col = getColour(name.getText());
399 col = new jalview.schemes.UserColourScheme()
400 .createColourFromName(name.getText());
402 Object fcol = getFeatureStyle(name.getText());
403 // simply display the feature color in a box
404 colourPanel.updateColor(fcol);
405 dialog.setResizable(true);
406 // TODO: render the graduated color in the box.
407 colourPanel.addMouseListener(new java.awt.event.MouseAdapter()
409 public void mousePressed(java.awt.event.MouseEvent evt)
411 if (!colourPanel.isGcol)
413 new UserDefinedColours(fr, ap.alignFrame);
417 FeatureColourChooser fcc = new FeatureColourChooser(
418 ap.alignFrame, name.getText());
419 dialog.transferFocus();
423 dialog.setVisible(true);
425 jalview.io.FeaturesFile ffile = new jalview.io.FeaturesFile();
429 // This ensures that the last sequence
430 // is refreshed and new features are rendered
432 lastFeatureAdded = name.getText().trim();
433 lastFeatureGroupAdded = source.getText().trim();
434 lastDescriptionAdded = description.getText().replace('\n', ' ');
437 if (lastFeatureGroupAdded != null && lastFeatureGroupAdded.length() < 1)
438 lastFeatureGroupAdded = null;
443 SequenceFeature sf = features[featureIndex];
446 sf.type = lastFeatureAdded;
447 sf.featureGroup = lastFeatureGroupAdded;
448 sf.description = lastDescriptionAdded;
449 if (!colourPanel.isGcol)
451 // update colour - otherwise its already done.
452 setColour(sf.type, colourPanel.getBackground());
456 sf.begin = Integer.parseInt(start.getText());
457 sf.end = Integer.parseInt(end.getText());
458 } catch (NumberFormatException ex)
462 ffile.parseDescriptionHTML(sf, false);
466 sequences[0].deleteFeature(sf);
472 if (dialog.accept && name.getText().length() > 0)
474 for (int i = 0; i < sequences.length; i++)
476 features[i].type = lastFeatureAdded;
477 features[i].featureGroup = lastFeatureGroupAdded;
478 features[i].description = lastDescriptionAdded;
479 sequences[i].addSequenceFeature(features[i]);
480 ffile.parseDescriptionHTML(features[i], false);
483 if (av.featuresDisplayed == null)
485 av.featuresDisplayed = new Hashtable();
488 if (featureGroups == null)
490 featureGroups = new Hashtable();
493 col = colourPanel.getBackground();
494 // setColour(lastFeatureAdded, fcol);
496 if (lastFeatureGroupAdded != null)
498 featureGroups.put(lastFeatureGroupAdded, new Boolean(true));
500 if (fcol instanceof Color)
502 setColour(lastFeatureAdded, fcol);
504 av.featuresDisplayed.put(lastFeatureAdded,
505 getFeatureStyle(lastFeatureAdded));
509 String[] tro = new String[renderOrder.length];
510 tro[0] = renderOrder[renderOrder.length - 1];
511 System.arraycopy(renderOrder, 0, tro, 1, renderOrder.length - 1);
516 // no update to the alignment
520 // refresh the alignment and the feature settings dialog
521 if (av.featureSettings != null)
523 av.featureSettings.refreshTable();
525 // findAllFeatures();
527 ap.paintAlignment(true);
532 public Color findFeatureColour(Color initialCol, SequenceI seq, int i)
535 if (!av.showSequenceFeatures)
541 sequenceFeatures = lastSeq.getSequenceFeatures();
542 if (sequenceFeatures == null)
547 sfSize = sequenceFeatures.length;
549 if (jalview.util.Comparison.isGap(lastSeq.getCharAt(i)))
554 currentColour = null;
556 drawSequence(null, lastSeq, lastSeq.findPosition(i), -1, -1);
558 if (currentColour == null)
563 return new Color(((Integer) currentColour).intValue());
567 * This is used by the Molecule Viewer to get the accurate colour of the
570 boolean overview = false;
595 // SequenceFeature sf;
598 SequenceFeature[] sequenceFeatures;
600 int sfSize, sfindex, spos, epos;
602 synchronized public void drawSequence(Graphics g, SequenceI seq,
603 int start, int end, int y1)
605 if (seq.getSequenceFeatures() == null
606 || seq.getSequenceFeatures().length == 0)
611 if (transparencySetter != null && g != null)
613 transparencySetter.setTransparency(g, transparency);
616 if (lastSeq == null || seq != lastSeq
617 || sequenceFeatures != seq.getSequenceFeatures())
620 sequenceFeatures = seq.getSequenceFeatures();
621 sfSize = sequenceFeatures.length;
624 if (av.featuresDisplayed == null || renderOrder == null)
627 if (av.featuresDisplayed.size() < 1)
632 sequenceFeatures = seq.getSequenceFeatures();
633 sfSize = sequenceFeatures.length;
637 spos = lastSeq.findPosition(start);
638 epos = lastSeq.findPosition(end);
641 fm = g.getFontMetrics();
645 for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++)
647 type = renderOrder[renderIndex];
648 if (!av.featuresDisplayed.containsKey(type))
653 // loop through all features in sequence to find
654 // current feature to render
655 for (sfindex = 0; sfindex < sfSize; sfindex++)
657 if (!sequenceFeatures[sfindex].type.equals(type))
662 if (featureGroups != null
663 && sequenceFeatures[sfindex].featureGroup != null
665 .containsKey(sequenceFeatures[sfindex].featureGroup)
666 && !((Boolean) featureGroups
667 .get(sequenceFeatures[sfindex].featureGroup))
674 && (sequenceFeatures[sfindex].getBegin() > epos || sequenceFeatures[sfindex]
682 if (sequenceFeatures[sfindex].begin <= start
683 && sequenceFeatures[sfindex].end >= start)
685 currentColour = new Integer(
686 getColour(sequenceFeatures[sfindex]).getRGB());// av.featuresDisplayed
687 // .get(sequenceFeatures[sfindex].type);
691 else if (sequenceFeatures[sfindex].type.equals("disulfide bond"))
694 renderFeature(g, seq,
695 seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
696 seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
697 getColour(sequenceFeatures[sfindex])
698 // new Color(((Integer) av.featuresDisplayed
699 // .get(sequenceFeatures[sfindex].type)).intValue())
701 renderFeature(g, seq,
702 seq.findIndex(sequenceFeatures[sfindex].end) - 1,
703 seq.findIndex(sequenceFeatures[sfindex].end) - 1,
704 getColour(sequenceFeatures[sfindex])
705 // new Color(((Integer) av.featuresDisplayed
706 // .get(sequenceFeatures[sfindex].type)).intValue())
712 if (showFeature(sequenceFeatures[sfindex]))
714 renderFeature(g, seq,
715 seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
716 seq.findIndex(sequenceFeatures[sfindex].end) - 1,
717 getColour(sequenceFeatures[sfindex]), start, end, y1);
724 if (transparencySetter != null && g != null)
726 transparencySetter.setTransparency(g, 1.0f);
734 void renderFeature(Graphics g, SequenceI seq, int fstart, int fend,
735 Color featureColour, int start, int end, int y1)
738 if (((fstart <= end) && (fend >= start)))
741 { // fix for if the feature we have starts before the sequence start,
742 fstart = start; // but the feature end is still valid!!
750 for (i = fstart; i <= fend; i++)
752 s = seq.getCharAt(i);
754 if (jalview.util.Comparison.isGap(s))
759 g.setColor(featureColour);
761 g.fillRect((i - start) * av.charWidth, y1, av.charWidth,
764 if (!av.validCharWidth)
769 g.setColor(Color.white);
770 charOffset = (av.charWidth - fm.charWidth(s)) / 2;
771 g.drawString(String.valueOf(s), charOffset
772 + (av.charWidth * (i - start)), (y1 + av.charHeight)
773 - av.charHeight / 5); // pady = height / 5;
779 Hashtable minmax = null;
782 * Called when alignment in associated view has new/modified features to
783 * discover and display.
786 public void featuresAdded()
793 * find all features on the alignment
795 void findAllFeatures()
797 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
799 av.featuresDisplayed = new Hashtable();
800 Vector allfeatures = new Vector();
801 minmax = new Hashtable();
802 AlignmentI alignment = av.getAlignment();
803 for (int i = 0; i < alignment.getHeight(); i++)
805 SequenceFeature[] features = alignment.getSequenceAt(i)
806 .getSequenceFeatures();
808 if (features == null)
814 while (index < features.length)
816 if (features[index].begin == 0 && features[index].end == 0)
821 if (!av.featuresDisplayed.containsKey(features[index].getType()))
823 if (getColour(features[index].getType()) == null)
825 featureColours.put(features[index].getType(),
826 ucs.createColourFromName(features[index].getType()));
829 av.featuresDisplayed.put(features[index].getType(), new Integer(
830 getColour(features[index].getType()).getRGB()));
831 allfeatures.addElement(features[index].getType());
833 if (features[index].score != Float.NaN)
835 int nonpos = features[index].getBegin() >= 1 ? 0 : 1;
836 float[][] mm = (float[][]) minmax.get(features[index].getType());
841 minmax.put(features[index].getType(), mm);
843 if (mm[nonpos] == null)
845 mm[nonpos] = new float[]
846 { features[index].score, features[index].score };
851 if (mm[nonpos][0] > features[index].score)
853 mm[nonpos][0] = features[index].score;
855 if (mm[nonpos][1] < features[index].score)
857 mm[nonpos][1] = features[index].score;
866 renderOrder = new String[allfeatures.size()];
867 Enumeration en = allfeatures.elements();
868 int i = allfeatures.size() - 1;
869 while (en.hasMoreElements())
871 renderOrder[i] = en.nextElement().toString();
877 * get a feature style object for the given type string. Creates a
878 * java.awt.Color for a featureType with no existing colourscheme. TODO:
879 * replace return type with object implementing standard abstract colour/style
883 * @return java.awt.Color or GraduatedColor
885 public Object getFeatureStyle(String featureType)
887 Object fc = featureColours.get(featureType);
890 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
891 Color col = ucs.createColourFromName(featureType);
892 featureColours.put(featureType, fc = col);
897 public Color getColour(String featureType)
899 Object fc = getFeatureStyle(featureType);
901 if (fc instanceof Color)
907 if (fc instanceof GraduatedColor)
909 return ((GraduatedColor) fc).getMaxColor();
912 throw new Error("Implementation Error: Unrecognised render object "
913 + fc.getClass() + " for features of type " + featureType);
918 * @param sequenceFeature
919 * @return true if feature is visible.
921 private boolean showFeature(SequenceFeature sequenceFeature)
923 Object fc = getFeatureStyle(sequenceFeature.type);
924 if (fc instanceof GraduatedColor)
926 return ((GraduatedColor) fc).isColored(sequenceFeature);
935 * implement graduated colouring for features with scores
938 * @return render colour for the given feature
940 public Color getColour(SequenceFeature feature)
942 Object fc = getFeatureStyle(feature.getType());
943 if (fc instanceof Color)
949 if (fc instanceof GraduatedColor)
951 return ((GraduatedColor) fc).findColor(feature);
954 throw new Error("Implementation Error: Unrecognised render object "
955 + fc.getClass() + " for features of type " + feature.getType());
958 public void setColour(String featureType, Object col)
961 // Color _col = (col instanceof Color) ? ((Color) col) : (col instanceof
962 // GraduatedColor) ? ((GraduatedColor) col).getMaxColor() : null;
963 // Object c = featureColours.get(featureType);
964 // if (c == null || c instanceof Color || (c instanceof GraduatedColor &&
965 // !((GraduatedColor)c).getMaxColor().equals(_col)))
967 featureColours.put(featureType, col);
971 public void setFeaturePriority(Object[][] data)
973 // The feature table will display high priority
974 // features at the top, but theses are the ones
975 // we need to render last, so invert the data
976 if (av.featuresDisplayed != null)
978 av.featuresDisplayed.clear();
982 * if (visibleNew) { if (av.featuresDisplayed != null) {
983 * av.featuresDisplayed.clear(); } else { av.featuresDisplayed = new
984 * Hashtable(); } } if (data == null) { return; }
987 renderOrder = new String[data.length];
991 for (int i = 0; i < data.length; i++)
993 String type = data[i][0].toString();
994 setColour(type, data[i][1]);
995 if (((Boolean) data[i][2]).booleanValue())
997 av.featuresDisplayed.put(type, new Integer(getColour(type)
1001 renderOrder[data.length - i - 1] = type;
1007 * @return a simple list of feature group names or null
1009 public String[] getGroups()
1012 if (featureGroups != null)
1014 String[] gps = new String[featureGroups.size()];
1015 Enumeration gn = featureGroups.keys();
1017 while (gn.hasMoreElements())
1019 gps[i++] = (String) gn.nextElement();
1027 * get visible or invisible groups
1030 * true to return visible groups, false to return hidden ones.
1031 * @return list of groups
1033 public String[] getGroups(boolean visible)
1036 if (featureGroups != null)
1038 Vector gp = new Vector();
1040 Enumeration gn = featureGroups.keys();
1041 while (gn.hasMoreElements())
1043 String nm = (String) gn.nextElement();
1044 Boolean state = (Boolean) featureGroups.get(nm);
1045 if (state.booleanValue() == visible)
1050 String[] gps = new String[gp.size()];
1054 while (gn.hasMoreElements())
1056 gps[i++] = (String) gn.nextElement();
1064 * set all feature groups in toset to be visible or invisible
1069 * the state of the named groups to set
1071 public void setGroupState(String[] toset, boolean visible)
1074 if (toset != null && toset.length > 0 && featureGroups != null)
1076 boolean rdrw = false;
1077 for (int i = 0; i < toset.length; i++)
1079 Object st = featureGroups.get(toset[i]);
1080 featureGroups.put(toset[i], new Boolean(visible));
1083 rdrw = rdrw || (visible != ((Boolean) st).booleanValue());
1088 if (this.av != null)
1089 if (this.av.featureSettings != null)
1091 av.featureSettings.rebuildGroups();
1092 this.av.featureSettings.resetTable(true);
1100 av.alignmentChanged(null);
1106 ArrayList<String> hiddenGroups = new ArrayList<String>();
1109 * analyse alignment for groups and hash tables (used to be embedded in
1110 * FeatureSettings.setTableData)
1112 * @return true if features are on the alignment
1114 public boolean buildGroupHash()
1116 boolean alignmentHasFeatures = false;
1117 if (featureGroups == null)
1119 featureGroups = new Hashtable();
1121 hiddenGroups = new ArrayList<String>();
1122 hiddenGroups.addAll(featureGroups.keySet());
1123 ArrayList allFeatures = new ArrayList();
1124 ArrayList allGroups = new ArrayList();
1125 SequenceFeature[] tmpfeatures;
1127 AlignmentI alignment = av.getAlignment();
1128 for (int i = 0; i < alignment.getHeight(); i++)
1130 if (alignment.getSequenceAt(i).getSequenceFeatures() == null)
1135 alignmentHasFeatures = true;
1137 tmpfeatures = alignment.getSequenceAt(i).getSequenceFeatures();
1139 while (index < tmpfeatures.length)
1141 if (tmpfeatures[index].getFeatureGroup() != null)
1143 group = tmpfeatures[index].featureGroup;
1144 // Remove group from the hiddenGroup list
1145 hiddenGroups.remove(group);
1146 if (!allGroups.contains(group))
1148 allGroups.add(group);
1150 boolean visible = true;
1151 if (featureGroups.containsKey(group))
1153 visible = ((Boolean) featureGroups.get(group)).booleanValue();
1157 featureGroups.put(group, new Boolean(visible));
1162 if (!allFeatures.contains(tmpfeatures[index].getType()))
1164 allFeatures.add(tmpfeatures[index].getType());
1170 return alignmentHasFeatures;
1174 * rebuild the featuresDisplayed and renderorder list based on the
1175 * featureGroups hash and any existing display state and force a repaint if
1178 * @return true if alignment has visible features
1180 public boolean buildFeatureHash()
1182 boolean alignmentHasFeatures = false;
1183 if (featureGroups == null)
1185 alignmentHasFeatures = buildGroupHash();
1187 if (!alignmentHasFeatures)
1189 Hashtable fdisp = av.featuresDisplayed;
1190 Vector allFeatures = new Vector();
1191 SequenceFeature[] tmpfeatures;
1193 AlignmentI alignment = av.getAlignment();
1194 for (int i = 0; i < alignment.getHeight(); i++)
1196 if (alignment.getSequenceAt(i).getSequenceFeatures() == null)
1201 alignmentHasFeatures = true;
1203 tmpfeatures = alignment.getSequenceAt(i).getSequenceFeatures();
1205 while (index < tmpfeatures.length)
1207 boolean visible = true;
1208 if (tmpfeatures[index].getFeatureGroup() != null)
1210 group = tmpfeatures[index].featureGroup;
1211 if (featureGroups.containsKey(group))
1213 visible = ((Boolean) featureGroups.get(group)).booleanValue();
1217 if (visible && !allFeatures.contains(tmpfeatures[index].getType()))
1219 allFeatures.addElement(tmpfeatures[index].getType());
1224 if (allFeatures.size() > 0)
1226 String[] neworder = new String[allFeatures.size()];
1227 int p = neworder.length - 1;
1228 for (int i = renderOrder.length - 1; i >= 0; i--)
1230 if (allFeatures.contains(renderOrder[i]))
1232 neworder[p--] = renderOrder[i];
1233 allFeatures.removeElement(renderOrder[i]);
1237 av.featuresDisplayed.remove(renderOrder[i]);
1240 for (int i = allFeatures.size() - 1; i > 0; i++)
1242 Object e = allFeatures.elementAt(i);
1245 neworder[p--] = (String) e;
1246 av.featuresDisplayed.put(e, getColour((String) e));
1249 renderOrder = neworder;
1253 return alignmentHasFeatures;
1258 * @return the displayed feature type as an array of strings
1260 protected String[] getDisplayedFeatureTypes()
1262 String[] typ = null;
1263 synchronized (renderOrder)
1265 typ = new String[renderOrder.length];
1266 System.arraycopy(renderOrder, 0, typ, 0, typ.length);
1267 for (int i = 0; i < typ.length; i++)
1269 if (av.featuresDisplayed.get(typ[i]) == null)
1279 class TransparencySetter
1281 void setTransparency(Graphics g, float value)
1283 Graphics2D g2 = (Graphics2D) g;
1284 g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,