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;
37 public class FeatureRenderer implements jalview.api.FeatureRenderer
41 Hashtable featureColours = new Hashtable();
43 // A higher level for grouping features of a
45 Hashtable featureGroups = null;
47 // Holds web links for feature groups and feature types
48 // in the form label|link
49 Hashtable featureLinks = null;
51 // This is actually an Integer held in the hashtable,
52 // Retrieved using the key feature type
61 float transparency = 1f;
63 TransparencySetter transparencySetter = null;
66 * Creates a new FeatureRenderer object.
71 public FeatureRenderer(AlignViewport av)
75 if (!System.getProperty("java.version").startsWith("1.1"))
77 transparencySetter = new TransparencySetter();
81 public void transferSettings(FeatureRenderer fr)
83 renderOrder = fr.renderOrder;
84 featureGroups = fr.featureGroups;
85 featureColours = fr.featureColours;
86 transparency = fr.transparency;
87 if (av != null && fr.av != null && fr.av != av)
89 if (fr.av.featuresDisplayed != null)
91 if (av.featuresDisplayed == null)
93 av.featuresDisplayed = new Hashtable();
97 av.featuresDisplayed.clear();
99 Enumeration en = fr.av.featuresDisplayed.keys();
100 while (en.hasMoreElements())
102 av.featuresDisplayed.put(en.nextElement(), Boolean.TRUE);
108 static String lastFeatureAdded;
110 static String lastFeatureGroupAdded;
112 static String lastDescriptionAdded;
114 int featureIndex = 0;
116 boolean deleteFeature = false;
118 FeatureColourPanel colourPanel;
120 class FeatureColourPanel extends Panel
124 private Color maxCol;
126 private boolean isColourByLabel, isGcol;
129 * render a feature style in the amend feature dialog box
131 public void updateColor(Object newcol)
134 Color bg, col = null;
135 GraduatedColor gcol = null;
137 if (newcol instanceof Color)
140 col = (Color) newcol;
143 else if (newcol instanceof GraduatedColor)
146 gcol = (GraduatedColor) newcol;
151 throw new Error("Invalid color for MyCheckBox");
155 setBackground(bg = col);
159 if (gcol.getThreshType() != AnnotationColourGradient.NO_THRESHOLD)
162 + ((gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD) ? "(>)"
165 if (isColourByLabel = gcol.isColourByLabel())
167 setBackground(bg = Color.white);
168 vlabel += " (by Label)";
172 setBackground(bg = gcol.getMinColor());
173 maxCol = gcol.getMaxColor();
186 public void paint(Graphics g)
188 Dimension d = getSize();
193 g.setColor(Color.white);
194 g.fillRect(d.width / 2, 0, d.width / 2, d.height);
195 g.setColor(Color.black);
196 Font f = new Font("Verdana", Font.PLAIN, 10);
198 g.drawString("Label", 0, 0);
203 g.fillRect(d.width / 2, 0, d.width / 2, d.height);
211 boolean amendFeatures(final SequenceI[] sequences,
212 final SequenceFeature[] features, boolean newFeatures,
213 final AlignmentPanel ap)
215 Panel bigPanel = new Panel(new BorderLayout());
216 final TextField name = new TextField(16);
217 final TextField source = new TextField(16);
218 final TextArea description = new TextArea(3, 35);
219 final TextField start = new TextField(8);
220 final TextField end = new TextField(8);
221 final Choice overlaps;
222 Button deleteButton = new Button("Delete");
223 deleteFeature = false;
225 colourPanel = new FeatureColourPanel();
226 colourPanel.setSize(110, 15);
227 final FeatureRenderer fr = this;
229 Panel panel = new Panel(new GridLayout(3, 1));
231 featureIndex = 0; // feature to be amended.
234 // /////////////////////////////////////
235 // /MULTIPLE FEATURES AT SELECTED RESIDUE
236 if (!newFeatures && features.length > 1)
238 panel = new Panel(new GridLayout(4, 1));
240 tmp.add(new Label("Select Feature: "));
241 overlaps = new Choice();
242 for (int i = 0; i < features.length; i++)
244 String item = features[i].getType() + "/" + features[i].getBegin()
245 + "-" + features[i].getEnd();
247 if (features[i].getFeatureGroup() != null)
248 item += " (" + features[i].getFeatureGroup() + ")";
250 overlaps.addItem(item);
255 overlaps.addItemListener(new java.awt.event.ItemListener()
257 public void itemStateChanged(java.awt.event.ItemEvent e)
259 int index = overlaps.getSelectedIndex();
262 featureIndex = index;
263 name.setText(features[index].getType());
264 description.setText(features[index].getDescription());
265 source.setText(features[index].getFeatureGroup());
266 start.setText(features[index].getBegin() + "");
267 end.setText(features[index].getEnd() + "");
269 SearchResults highlight = new SearchResults();
270 highlight.addResult(sequences[0], features[index].getBegin(),
271 features[index].getEnd());
273 ap.seqPanel.seqCanvas.highlightSearchResults(highlight);
276 Object col = getFeatureStyle(name.getText());
279 col = new jalview.schemes.UserColourScheme()
280 .createColourFromName(name.getText());
283 colourPanel.updateColor(col);
290 // ////////////////////////////////////
294 tmp.add(new Label("Name: ", Label.RIGHT));
299 tmp.add(new Label("Group: ", Label.RIGHT));
304 tmp.add(new Label("Colour: ", Label.RIGHT));
305 tmp.add(colourPanel);
307 bigPanel.add(panel, BorderLayout.NORTH);
310 panel.add(new Label("Description: ", Label.RIGHT));
311 panel.add(new ScrollPane().add(description));
315 bigPanel.add(panel, BorderLayout.SOUTH);
318 panel.add(new Label(" Start:", Label.RIGHT));
320 panel.add(new Label(" End:", Label.RIGHT));
322 bigPanel.add(panel, BorderLayout.CENTER);
326 bigPanel.add(panel, BorderLayout.CENTER);
329 if (lastFeatureAdded == null)
331 if (features[0].type != null)
333 lastFeatureAdded = features[0].type;
337 lastFeatureAdded = "feature_1";
341 if (lastFeatureGroupAdded == null)
343 if (features[0].featureGroup != null)
345 lastFeatureGroupAdded = features[0].featureGroup;
349 lastFeatureAdded = "Jalview";
353 String title = newFeatures ? "Create New Sequence Feature(s)"
354 : "Amend/Delete Features for " + sequences[0].getName();
356 final JVDialog dialog = new JVDialog(ap.alignFrame, title, true, 385,
359 dialog.setMainPanel(bigPanel);
363 name.setText(lastFeatureAdded);
364 source.setText(lastFeatureGroupAdded);
368 dialog.ok.setLabel("Amend");
369 dialog.buttonPanel.add(deleteButton, 1);
370 deleteButton.addActionListener(new ActionListener()
372 public void actionPerformed(ActionEvent evt)
374 deleteFeature = true;
375 dialog.setVisible(false);
378 name.setText(features[0].getType());
379 source.setText(features[0].getFeatureGroup());
382 start.setText(features[0].getBegin() + "");
383 end.setText(features[0].getEnd() + "");
384 description.setText(features[0].getDescription());
385 Color col = getColour(name.getText());
388 col = new jalview.schemes.UserColourScheme()
389 .createColourFromName(name.getText());
391 Object fcol = getFeatureStyle(name.getText());
392 // simply display the feature color in a box
393 colourPanel.updateColor(fcol);
394 dialog.setResizable(true);
395 // TODO: render the graduated color in the box.
396 colourPanel.addMouseListener(new java.awt.event.MouseAdapter()
398 public void mousePressed(java.awt.event.MouseEvent evt)
400 if (!colourPanel.isGcol)
402 new UserDefinedColours(fr, ap.alignFrame);
406 FeatureColourChooser fcc = new FeatureColourChooser(
407 ap.alignFrame, name.getText());
408 dialog.transferFocus();
412 dialog.setVisible(true);
414 jalview.io.FeaturesFile ffile = new jalview.io.FeaturesFile();
418 // This ensures that the last sequence
419 // is refreshed and new features are rendered
421 lastFeatureAdded = name.getText().trim();
422 lastFeatureGroupAdded = source.getText().trim();
423 lastDescriptionAdded = description.getText().replace('\n', ' ');
426 if (lastFeatureGroupAdded != null && lastFeatureGroupAdded.length() < 1)
427 lastFeatureGroupAdded = null;
432 SequenceFeature sf = features[featureIndex];
435 sf.type = lastFeatureAdded;
436 sf.featureGroup = lastFeatureGroupAdded;
437 sf.description = lastDescriptionAdded;
438 if (!colourPanel.isGcol)
440 // update colour - otherwise its already done.
441 setColour(sf.type, colourPanel.getBackground());
445 sf.begin = Integer.parseInt(start.getText());
446 sf.end = Integer.parseInt(end.getText());
447 } catch (NumberFormatException ex)
451 ffile.parseDescriptionHTML(sf, false);
455 sequences[0].deleteFeature(sf);
461 if (dialog.accept && name.getText().length() > 0)
463 for (int i = 0; i < sequences.length; i++)
465 features[i].type = lastFeatureAdded;
466 features[i].featureGroup = lastFeatureGroupAdded;
467 features[i].description = lastDescriptionAdded;
468 sequences[i].addSequenceFeature(features[i]);
469 ffile.parseDescriptionHTML(features[i], false);
472 if (av.featuresDisplayed == null)
474 av.featuresDisplayed = new Hashtable();
477 if (featureGroups == null)
479 featureGroups = new Hashtable();
482 col = colourPanel.getBackground();
483 // setColour(lastFeatureAdded, fcol);
485 if (lastFeatureGroupAdded != null)
487 featureGroups.put(lastFeatureGroupAdded, new Boolean(true));
489 if (fcol instanceof Color)
491 setColour(lastFeatureAdded, fcol);
493 av.featuresDisplayed.put(lastFeatureAdded,
494 getFeatureStyle(lastFeatureAdded));
498 String[] tro = new String[renderOrder.length];
499 tro[0] = renderOrder[renderOrder.length - 1];
500 System.arraycopy(renderOrder, 0, tro, 1, renderOrder.length - 1);
505 // no update to the alignment
509 // refresh the alignment and the feature settings dialog
510 if (av.featureSettings != null)
512 av.featureSettings.refreshTable();
514 // findAllFeatures();
516 ap.paintAlignment(true);
521 public Color findFeatureColour(Color initialCol, SequenceI seq, int i)
524 if (!av.showSequenceFeatures)
530 sequenceFeatures = lastSeq.getSequenceFeatures();
531 if (sequenceFeatures == null)
536 sfSize = sequenceFeatures.length;
538 if (jalview.util.Comparison.isGap(lastSeq.getCharAt(i)))
543 currentColour = null;
545 drawSequence(null, lastSeq, lastSeq.findPosition(i), -1, -1);
547 if (currentColour == null)
552 return new Color(((Integer) currentColour).intValue());
556 * This is used by the Molecule Viewer to get the accurate colour of the
559 boolean overview = false;
584 // SequenceFeature sf;
587 SequenceFeature[] sequenceFeatures;
589 int sfSize, sfindex, spos, epos;
591 synchronized public void drawSequence(Graphics g, SequenceI seq,
592 int start, int end, int y1)
594 if (seq.getSequenceFeatures() == null
595 || seq.getSequenceFeatures().length == 0)
600 if (transparencySetter != null && g != null)
602 transparencySetter.setTransparency(g, transparency);
605 if (lastSeq == null || seq != lastSeq
606 || sequenceFeatures != seq.getSequenceFeatures())
609 sequenceFeatures = seq.getSequenceFeatures();
610 sfSize = sequenceFeatures.length;
613 if (av.featuresDisplayed == null || renderOrder == null)
616 if (av.featuresDisplayed.size() < 1)
621 sequenceFeatures = seq.getSequenceFeatures();
622 sfSize = sequenceFeatures.length;
626 spos = lastSeq.findPosition(start);
627 epos = lastSeq.findPosition(end);
630 fm = g.getFontMetrics();
634 for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++)
636 type = renderOrder[renderIndex];
637 if (!av.featuresDisplayed.containsKey(type))
642 // loop through all features in sequence to find
643 // current feature to render
644 for (sfindex = 0; sfindex < sfSize; sfindex++)
646 if (!sequenceFeatures[sfindex].type.equals(type))
651 if (featureGroups != null
652 && sequenceFeatures[sfindex].featureGroup != null
654 .containsKey(sequenceFeatures[sfindex].featureGroup)
655 && !((Boolean) featureGroups
656 .get(sequenceFeatures[sfindex].featureGroup))
663 && (sequenceFeatures[sfindex].getBegin() > epos || sequenceFeatures[sfindex]
671 if (sequenceFeatures[sfindex].begin <= start
672 && sequenceFeatures[sfindex].end >= start)
674 currentColour = new Integer(
675 getColour(sequenceFeatures[sfindex]).getRGB());// av.featuresDisplayed
676 // .get(sequenceFeatures[sfindex].type);
680 else if (sequenceFeatures[sfindex].type.equals("disulfide bond"))
683 renderFeature(g, seq,
684 seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
685 seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
686 getColour(sequenceFeatures[sfindex])
687 // new Color(((Integer) av.featuresDisplayed
688 // .get(sequenceFeatures[sfindex].type)).intValue())
690 renderFeature(g, seq,
691 seq.findIndex(sequenceFeatures[sfindex].end) - 1,
692 seq.findIndex(sequenceFeatures[sfindex].end) - 1,
693 getColour(sequenceFeatures[sfindex])
694 // new Color(((Integer) av.featuresDisplayed
695 // .get(sequenceFeatures[sfindex].type)).intValue())
701 if (showFeature(sequenceFeatures[sfindex]))
703 renderFeature(g, seq,
704 seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
705 seq.findIndex(sequenceFeatures[sfindex].end) - 1,
706 getColour(sequenceFeatures[sfindex]), start, end, y1);
713 if (transparencySetter != null && g != null)
715 transparencySetter.setTransparency(g, 1.0f);
723 void renderFeature(Graphics g, SequenceI seq, int fstart, int fend,
724 Color featureColour, int start, int end, int y1)
727 if (((fstart <= end) && (fend >= start)))
730 { // fix for if the feature we have starts before the sequence start,
731 fstart = start; // but the feature end is still valid!!
739 for (i = fstart; i <= fend; i++)
741 s = seq.getCharAt(i);
743 if (jalview.util.Comparison.isGap(s))
748 g.setColor(featureColour);
750 g.fillRect((i - start) * av.charWidth, y1, av.charWidth,
753 if (!av.validCharWidth)
758 g.setColor(Color.white);
759 charOffset = (av.charWidth - fm.charWidth(s)) / 2;
760 g.drawString(String.valueOf(s), charOffset
761 + (av.charWidth * (i - start)), (y1 + av.charHeight)
762 - av.charHeight / 5); // pady = height / 5;
768 Hashtable minmax = null;
771 * Called when alignment in associated view has new/modified features to
772 * discover and display.
775 public void featuresAdded()
782 * find all features on the alignment
784 void findAllFeatures()
786 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
788 av.featuresDisplayed = new Hashtable();
789 Vector allfeatures = new Vector();
790 minmax = new Hashtable();
791 AlignmentI alignment = av.getAlignment();
792 for (int i = 0; i < alignment.getHeight(); i++)
794 SequenceFeature[] features = alignment.getSequenceAt(i)
795 .getSequenceFeatures();
797 if (features == null)
803 while (index < features.length)
805 if (features[index].begin == 0 && features[index].end == 0)
810 if (!av.featuresDisplayed.containsKey(features[index].getType()))
812 if (getColour(features[index].getType()) == null)
814 featureColours.put(features[index].getType(),
815 ucs.createColourFromName(features[index].getType()));
818 av.featuresDisplayed.put(features[index].getType(), new Integer(
819 getColour(features[index].getType()).getRGB()));
820 allfeatures.addElement(features[index].getType());
822 if (features[index].score != Float.NaN)
824 int nonpos = features[index].getBegin() >= 1 ? 0 : 1;
825 float[][] mm = (float[][]) minmax.get(features[index].getType());
830 minmax.put(features[index].getType(), mm);
832 if (mm[nonpos] == null)
834 mm[nonpos] = new float[]
835 { features[index].score, features[index].score };
840 if (mm[nonpos][0] > features[index].score)
842 mm[nonpos][0] = features[index].score;
844 if (mm[nonpos][1] < features[index].score)
846 mm[nonpos][1] = features[index].score;
855 renderOrder = new String[allfeatures.size()];
856 Enumeration en = allfeatures.elements();
857 int i = allfeatures.size() - 1;
858 while (en.hasMoreElements())
860 renderOrder[i] = en.nextElement().toString();
866 * get a feature style object for the given type string. Creates a
867 * java.awt.Color for a featureType with no existing colourscheme. TODO:
868 * replace return type with object implementing standard abstract colour/style
872 * @return java.awt.Color or GraduatedColor
874 public Object getFeatureStyle(String featureType)
876 Object fc = featureColours.get(featureType);
879 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
880 Color col = ucs.createColourFromName(featureType);
881 featureColours.put(featureType, fc = col);
886 public Color getColour(String featureType)
888 Object fc = getFeatureStyle(featureType);
890 if (fc instanceof Color)
896 if (fc instanceof GraduatedColor)
898 return ((GraduatedColor) fc).getMaxColor();
901 throw new Error("Implementation Error: Unrecognised render object "
902 + fc.getClass() + " for features of type " + featureType);
907 * @param sequenceFeature
908 * @return true if feature is visible.
910 private boolean showFeature(SequenceFeature sequenceFeature)
912 Object fc = getFeatureStyle(sequenceFeature.type);
913 if (fc instanceof GraduatedColor)
915 return ((GraduatedColor) fc).isColored(sequenceFeature);
924 * implement graduated colouring for features with scores
927 * @return render colour for the given feature
929 public Color getColour(SequenceFeature feature)
931 Object fc = getFeatureStyle(feature.getType());
932 if (fc instanceof Color)
938 if (fc instanceof GraduatedColor)
940 return ((GraduatedColor) fc).findColor(feature);
943 throw new Error("Implementation Error: Unrecognised render object "
944 + fc.getClass() + " for features of type " + feature.getType());
947 public void setColour(String featureType, Object col)
950 // Color _col = (col instanceof Color) ? ((Color) col) : (col instanceof
951 // GraduatedColor) ? ((GraduatedColor) col).getMaxColor() : null;
952 // Object c = featureColours.get(featureType);
953 // if (c == null || c instanceof Color || (c instanceof GraduatedColor &&
954 // !((GraduatedColor)c).getMaxColor().equals(_col)))
956 featureColours.put(featureType, col);
960 public void setFeaturePriority(Object[][] data)
962 // The feature table will display high priority
963 // features at the top, but theses are the ones
964 // we need to render last, so invert the data
965 if (av.featuresDisplayed != null)
967 av.featuresDisplayed.clear();
971 * if (visibleNew) { if (av.featuresDisplayed != null) {
972 * av.featuresDisplayed.clear(); } else { av.featuresDisplayed = new
973 * Hashtable(); } } if (data == null) { return; }
976 renderOrder = new String[data.length];
980 for (int i = 0; i < data.length; i++)
982 String type = data[i][0].toString();
983 setColour(type, data[i][1]);
984 if (((Boolean) data[i][2]).booleanValue())
986 av.featuresDisplayed.put(type, new Integer(getColour(type)
990 renderOrder[data.length - i - 1] = type;
996 * @return a simple list of feature group names or null
998 public String[] getGroups()
1001 if (featureGroups != null)
1003 String[] gps = new String[featureGroups.size()];
1004 Enumeration gn = featureGroups.keys();
1006 while (gn.hasMoreElements())
1008 gps[i++] = (String) gn.nextElement();
1016 * get visible or invisible groups
1019 * true to return visible groups, false to return hidden ones.
1020 * @return list of groups
1022 public String[] getGroups(boolean visible)
1025 if (featureGroups != null)
1027 Vector gp = new Vector();
1029 Enumeration gn = featureGroups.keys();
1030 while (gn.hasMoreElements())
1032 String nm = (String) gn.nextElement();
1033 Boolean state = (Boolean) featureGroups.get(nm);
1034 if (state.booleanValue() == visible)
1039 String[] gps = new String[gp.size()];
1043 while (gn.hasMoreElements())
1045 gps[i++] = (String) gn.nextElement();
1053 * set all feature groups in toset to be visible or invisible
1058 * the state of the named groups to set
1060 public void setGroupState(String[] toset, boolean visible)
1063 if (toset != null && toset.length > 0 && featureGroups != null)
1065 boolean rdrw = false;
1066 for (int i = 0; i < toset.length; i++)
1068 Object st = featureGroups.get(toset[i]);
1069 featureGroups.put(toset[i], new Boolean(visible));
1072 rdrw = rdrw || (visible != ((Boolean) st).booleanValue());
1077 if (this.av != null)
1078 if (this.av.featureSettings != null)
1080 av.featureSettings.rebuildGroups();
1081 this.av.featureSettings.resetTable(true);
1089 av.alignmentChanged(null);
1095 ArrayList<String> hiddenGroups = new ArrayList<String>();
1098 * analyse alignment for groups and hash tables (used to be embedded in
1099 * FeatureSettings.setTableData)
1101 * @return true if features are on the alignment
1103 public boolean buildGroupHash()
1105 boolean alignmentHasFeatures = false;
1106 if (featureGroups == null)
1108 featureGroups = new Hashtable();
1110 hiddenGroups = new ArrayList<String>();
1111 hiddenGroups.addAll(featureGroups.keySet());
1112 ArrayList allFeatures = new ArrayList();
1113 ArrayList allGroups = new ArrayList();
1114 SequenceFeature[] tmpfeatures;
1116 AlignmentI alignment = av.getAlignment();
1117 for (int i = 0; i < alignment.getHeight(); i++)
1119 if (alignment.getSequenceAt(i).getSequenceFeatures() == null)
1124 alignmentHasFeatures = true;
1126 tmpfeatures = alignment.getSequenceAt(i).getSequenceFeatures();
1128 while (index < tmpfeatures.length)
1130 if (tmpfeatures[index].getFeatureGroup() != null)
1132 group = tmpfeatures[index].featureGroup;
1133 // Remove group from the hiddenGroup list
1134 hiddenGroups.remove(group);
1135 if (!allGroups.contains(group))
1137 allGroups.add(group);
1139 boolean visible = true;
1140 if (featureGroups.containsKey(group))
1142 visible = ((Boolean) featureGroups.get(group)).booleanValue();
1146 featureGroups.put(group, new Boolean(visible));
1151 if (!allFeatures.contains(tmpfeatures[index].getType()))
1153 allFeatures.add(tmpfeatures[index].getType());
1159 return alignmentHasFeatures;
1163 * rebuild the featuresDisplayed and renderorder list based on the
1164 * featureGroups hash and any existing display state and force a repaint if
1167 * @return true if alignment has visible features
1169 public boolean buildFeatureHash()
1171 boolean alignmentHasFeatures = false;
1172 if (featureGroups == null)
1174 alignmentHasFeatures = buildGroupHash();
1176 if (!alignmentHasFeatures)
1178 Hashtable fdisp = av.featuresDisplayed;
1179 Vector allFeatures = new Vector();
1180 SequenceFeature[] tmpfeatures;
1182 AlignmentI alignment = av.getAlignment();
1183 for (int i = 0; i < alignment.getHeight(); i++)
1185 if (alignment.getSequenceAt(i).getSequenceFeatures() == null)
1190 alignmentHasFeatures = true;
1192 tmpfeatures = alignment.getSequenceAt(i).getSequenceFeatures();
1194 while (index < tmpfeatures.length)
1196 boolean visible = true;
1197 if (tmpfeatures[index].getFeatureGroup() != null)
1199 group = tmpfeatures[index].featureGroup;
1200 if (featureGroups.containsKey(group))
1202 visible = ((Boolean) featureGroups.get(group)).booleanValue();
1206 if (visible && !allFeatures.contains(tmpfeatures[index].getType()))
1208 allFeatures.addElement(tmpfeatures[index].getType());
1213 if (allFeatures.size() > 0)
1215 String[] neworder = new String[allFeatures.size()];
1216 int p = neworder.length - 1;
1217 for (int i = renderOrder.length - 1; i >= 0; i--)
1219 if (allFeatures.contains(renderOrder[i]))
1221 neworder[p--] = renderOrder[i];
1222 allFeatures.removeElement(renderOrder[i]);
1226 av.featuresDisplayed.remove(renderOrder[i]);
1229 for (int i = allFeatures.size() - 1; i > 0; i++)
1231 Object e = allFeatures.elementAt(i);
1234 neworder[p--] = (String) e;
1235 av.featuresDisplayed.put(e, getColour((String) e));
1238 renderOrder = neworder;
1242 return alignmentHasFeatures;
1247 * @return the displayed feature type as an array of strings
1249 protected String[] getDisplayedFeatureTypes()
1251 String[] typ = null;
1252 synchronized (renderOrder)
1254 typ = new String[renderOrder.length];
1255 System.arraycopy(renderOrder, 0, typ, 0, typ.length);
1256 for (int i = 0; i < typ.length; i++)
1258 if (av.featuresDisplayed.get(typ[i]) == null)
1268 class TransparencySetter
1270 void setTransparency(Graphics g, float value)
1272 Graphics2D g2 = (Graphics2D) g;
1273 g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,