2 * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)
3 * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 package jalview.appletgui;
25 import java.awt.event.*;
27 import jalview.appletgui.FeatureSettings.MyCheckbox;
28 import jalview.datamodel.*;
29 import jalview.schemes.AnnotationColourGradient;
30 import jalview.schemes.GraduatedColor;
38 public class 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(FeatureRenderer fr)
84 renderOrder = fr.renderOrder;
85 featureGroups = fr.featureGroups;
86 featureColours = fr.featureColours;
87 transparency = fr.transparency;
90 static String lastFeatureAdded;
92 static String lastFeatureGroupAdded;
94 static String lastDescriptionAdded;
98 boolean deleteFeature = false;
100 FeatureColourPanel colourPanel;
101 class FeatureColourPanel extends Panel {
104 private Color maxCol;
105 private boolean isColourByLabel,isGcol;
107 * render a feature style in the amend feature dialog box
109 public void updateColor(Object newcol)
113 GraduatedColor gcol=null;
115 if (newcol instanceof Color)
118 col = (Color) newcol;
121 else if (newcol instanceof GraduatedColor)
124 gcol = (GraduatedColor) newcol;
129 throw new Error("Invalid color for MyCheckBox");
133 setBackground(bg=col);
137 if (gcol.getThreshType()!=AnnotationColourGradient.NO_THRESHOLD)
139 vlabel += " "+((gcol.getThreshType()==AnnotationColourGradient.ABOVE_THRESHOLD) ? "(>)" : "(<)");
141 if (isColourByLabel=gcol.isColourByLabel()) {
142 setBackground(bg=Color.white);
143 vlabel += " (by Label)";
145 setBackground(bg=gcol.getMinColor());
146 maxCol = gcol.getMaxColor();
153 FeatureColourPanel() {
156 public void paint(Graphics g)
158 int width=getWidth(),height=getHeight();
162 g.setColor(Color.white);
163 g.fillRect(width/2, 0,width/2, height);
164 g.setColor(Color.black);
165 Font f=new Font("Verdana", Font.PLAIN,
168 g.drawString("Label", 0, 0);
173 g.fillRect(width/2, 0,width/2, height);
181 boolean amendFeatures(final SequenceI[] sequences,
182 final SequenceFeature[] features, boolean newFeatures,
183 final AlignmentPanel ap)
185 Panel bigPanel = new Panel(new BorderLayout());
186 final TextField name = new TextField(16);
187 final TextField source = new TextField(16);
188 final TextArea description = new TextArea(3, 35);
189 final TextField start = new TextField(8);
190 final TextField end = new TextField(8);
191 final Choice overlaps;
192 Button deleteButton = new Button("Delete");
193 deleteFeature = false;
195 colourPanel = new FeatureColourPanel();
196 colourPanel.setSize(110, 15);
197 final FeatureRenderer fr = this;
199 Panel panel = new Panel(new GridLayout(3, 1));
201 featureIndex = 0; // feature to be amended.
204 // /////////////////////////////////////
205 // /MULTIPLE FEATURES AT SELECTED RESIDUE
206 if (!newFeatures && features.length > 1)
208 panel = new Panel(new GridLayout(4, 1));
210 tmp.add(new Label("Select Feature: "));
211 overlaps = new Choice();
212 for (int i = 0; i < features.length; i++)
214 String item = features[i].getType() + "/" + features[i].getBegin()
215 + "-" + features[i].getEnd();
217 if (features[i].getFeatureGroup() != null)
218 item += " (" + features[i].getFeatureGroup() + ")";
220 overlaps.addItem(item);
225 overlaps.addItemListener(new java.awt.event.ItemListener()
227 public void itemStateChanged(java.awt.event.ItemEvent e)
229 int index = overlaps.getSelectedIndex();
232 featureIndex = index;
233 name.setText(features[index].getType());
234 description.setText(features[index].getDescription());
235 source.setText(features[index].getFeatureGroup());
236 start.setText(features[index].getBegin() + "");
237 end.setText(features[index].getEnd() + "");
239 SearchResults highlight = new SearchResults();
240 highlight.addResult(sequences[0], features[index].getBegin(),
241 features[index].getEnd());
243 ap.seqPanel.seqCanvas.highlightSearchResults(highlight);
246 Color col = getColour(name.getText());
249 col = new jalview.schemes.UserColourScheme()
250 .createColourFromName(name.getText());
253 colourPanel.updateColor(col);
260 // ////////////////////////////////////
264 tmp.add(new Label("Name: ", Label.RIGHT));
269 tmp.add(new Label("Group: ", Label.RIGHT));
274 tmp.add(new Label("Colour: ", Label.RIGHT));
275 tmp.add(colourPanel);
277 bigPanel.add(panel, BorderLayout.NORTH);
280 panel.add(new Label("Description: ", Label.RIGHT));
281 panel.add(new ScrollPane().add(description));
285 bigPanel.add(panel, BorderLayout.SOUTH);
288 panel.add(new Label(" Start:", Label.RIGHT));
290 panel.add(new Label(" End:", Label.RIGHT));
292 bigPanel.add(panel, BorderLayout.CENTER);
296 bigPanel.add(panel, BorderLayout.CENTER);
299 if (lastFeatureAdded == null)
301 if (features[0].type != null)
303 lastFeatureAdded = features[0].type;
307 lastFeatureAdded = "feature_1";
311 if (lastFeatureGroupAdded == null)
313 if (features[0].featureGroup != null)
315 lastFeatureGroupAdded = features[0].featureGroup;
319 lastFeatureAdded = "Jalview";
323 String title = newFeatures ? "Create New Sequence Feature(s)"
324 : "Amend/Delete Features for " + sequences[0].getName();
326 final JVDialog dialog = new JVDialog(ap.alignFrame, title, true, 385,
329 dialog.setMainPanel(bigPanel);
333 name.setText(lastFeatureAdded);
334 source.setText(lastFeatureGroupAdded);
338 dialog.ok.setLabel("Amend");
339 dialog.buttonPanel.add(deleteButton, 1);
340 deleteButton.addActionListener(new ActionListener()
342 public void actionPerformed(ActionEvent evt)
344 deleteFeature = true;
345 dialog.setVisible(false);
348 name.setText(features[0].getType());
349 source.setText(features[0].getFeatureGroup());
352 start.setText(features[0].getBegin() + "");
353 end.setText(features[0].getEnd() + "");
354 description.setText(features[0].getDescription());
355 Color col = getColour(name.getText());
358 col = new jalview.schemes.UserColourScheme()
359 .createColourFromName(name.getText());
361 Object fcol = getFeatureStyle(name.getText());
362 // simply display the feature color in a box
363 colourPanel.updateColor(fcol);
364 dialog.setResizable(true);
365 // TODO: render the graduated color in the box.
366 if (fcol instanceof Color)
368 colourPanel.addMouseListener(new java.awt.event.MouseAdapter()
370 public void mousePressed(java.awt.event.MouseEvent evt)
372 new UserDefinedColours(fr, ap.alignFrame);
379 colourPanel.addMouseListener(new java.awt.event.MouseAdapter()
381 public void mousePressed(java.awt.event.MouseEvent evt)
383 FeatureColourChooser fcc = new FeatureColourChooser(ap.alignFrame, name.getText());
384 fcc.setFocusable(true);
385 dialog.transferFocus();
389 dialog.setVisible(true);
391 jalview.io.FeaturesFile ffile = new jalview.io.FeaturesFile();
395 // This ensures that the last sequence
396 // is refreshed and new features are rendered
398 lastFeatureAdded = name.getText().trim();
399 lastFeatureGroupAdded = source.getText().trim();
400 lastDescriptionAdded = description.getText().replace('\n', ' ');
403 if (lastFeatureGroupAdded != null && lastFeatureGroupAdded.length() < 1)
404 lastFeatureGroupAdded = null;
409 SequenceFeature sf = features[featureIndex];
412 sf.type = lastFeatureAdded;
413 sf.featureGroup = lastFeatureGroupAdded;
414 sf.description = lastDescriptionAdded;
415 if (fcol instanceof Color) {
416 // update colour - otherwise its already done.
417 setColour(sf.type, colourPanel.getBackground());
421 sf.begin = Integer.parseInt(start.getText());
422 sf.end = Integer.parseInt(end.getText());
423 } catch (NumberFormatException ex)
427 ffile.parseDescriptionHTML(sf, false);
431 sequences[0].deleteFeature(sf);
437 if (dialog.accept && name.getText().length() > 0)
439 for (int i = 0; i < sequences.length; i++)
441 features[i].type = lastFeatureAdded;
442 features[i].featureGroup = lastFeatureGroupAdded;
443 features[i].description = lastDescriptionAdded;
444 sequences[i].addSequenceFeature(features[i]);
445 ffile.parseDescriptionHTML(features[i], false);
448 if (av.featuresDisplayed == null)
450 av.featuresDisplayed = new Hashtable();
453 if (featureGroups == null)
455 featureGroups = new Hashtable();
458 col = colourPanel.getBackground();
459 //setColour(lastFeatureAdded, fcol);
461 if (lastFeatureGroupAdded != null)
463 featureGroups.put(lastFeatureGroupAdded, new Boolean(true));
465 if (fcol instanceof Color) {
466 setColour(lastFeatureAdded, fcol);
468 av.featuresDisplayed.put(lastFeatureAdded,
469 getFeatureStyle(lastFeatureAdded));
473 String[] tro = new String[renderOrder.length];
474 tro[0] = renderOrder[renderOrder.length - 1];
475 System.arraycopy(renderOrder, 0, tro, 1, renderOrder.length - 1);
478 ap.paintAlignment(true);
488 // findAllFeatures();
490 ap.paintAlignment(true);
495 public Color findFeatureColour(Color initialCol, SequenceI seq, int i)
498 if (!av.showSequenceFeatures)
504 sequenceFeatures = lastSeq.getSequenceFeatures();
505 if (sequenceFeatures == null)
510 sfSize = sequenceFeatures.length;
512 if (jalview.util.Comparison.isGap(lastSeq.getCharAt(i)))
517 currentColour = null;
519 drawSequence(null, lastSeq, lastSeq.findPosition(i), -1, -1);
521 if (currentColour == null)
526 return new Color(((Integer) currentColour).intValue());
530 * This is used by the Molecule Viewer to get the accurate colour of the
533 boolean overview = false;
558 // SequenceFeature sf;
561 SequenceFeature[] sequenceFeatures;
563 int sfSize, sfindex, spos, epos;
565 synchronized public void drawSequence(Graphics g, SequenceI seq,
566 int start, int end, int y1)
568 if (seq.getSequenceFeatures() == null
569 || seq.getSequenceFeatures().length == 0)
574 if (transparencySetter != null && g != null)
576 transparencySetter.setTransparency(g, transparency);
579 if (lastSeq == null || seq != lastSeq
580 || sequenceFeatures != seq.getSequenceFeatures())
583 sequenceFeatures = seq.getSequenceFeatures();
584 sfSize = sequenceFeatures.length;
587 if (av.featuresDisplayed == null || renderOrder == null)
590 if (av.featuresDisplayed.size() < 1)
595 sequenceFeatures = seq.getSequenceFeatures();
596 sfSize = sequenceFeatures.length;
600 spos = lastSeq.findPosition(start);
601 epos = lastSeq.findPosition(end);
604 fm = g.getFontMetrics();
608 for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++)
610 type = renderOrder[renderIndex];
611 if (!av.featuresDisplayed.containsKey(type))
616 // loop through all features in sequence to find
617 // current feature to render
618 for (sfindex = 0; sfindex < sfSize; sfindex++)
620 if (!sequenceFeatures[sfindex].type.equals(type))
625 if (featureGroups != null
626 && sequenceFeatures[sfindex].featureGroup != null
628 .containsKey(sequenceFeatures[sfindex].featureGroup)
629 && !((Boolean) featureGroups
630 .get(sequenceFeatures[sfindex].featureGroup))
637 && (sequenceFeatures[sfindex].getBegin() > epos || sequenceFeatures[sfindex]
645 if (sequenceFeatures[sfindex].begin <= start
646 && sequenceFeatures[sfindex].end >= start)
648 currentColour = new Integer(
649 getColour(sequenceFeatures[sfindex]).getRGB());// av.featuresDisplayed
650 // .get(sequenceFeatures[sfindex].type);
654 else if (sequenceFeatures[sfindex].type.equals("disulfide bond"))
657 renderFeature(g, seq, seq
658 .findIndex(sequenceFeatures[sfindex].begin) - 1, seq
659 .findIndex(sequenceFeatures[sfindex].begin) - 1,
660 getColour(sequenceFeatures[sfindex])
661 // new Color(((Integer) av.featuresDisplayed
662 // .get(sequenceFeatures[sfindex].type)).intValue())
664 renderFeature(g, seq, seq
665 .findIndex(sequenceFeatures[sfindex].end) - 1, seq
666 .findIndex(sequenceFeatures[sfindex].end) - 1,
667 getColour(sequenceFeatures[sfindex])
668 // new Color(((Integer) av.featuresDisplayed
669 // .get(sequenceFeatures[sfindex].type)).intValue())
675 if (showFeature(sequenceFeatures[sfindex]))
676 { renderFeature(g, seq, seq
677 .findIndex(sequenceFeatures[sfindex].begin) - 1, seq
678 .findIndex(sequenceFeatures[sfindex].end) - 1,
679 getColour(sequenceFeatures[sfindex]), start, end, y1);
686 if (transparencySetter != null && g != null)
688 transparencySetter.setTransparency(g, 1.0f);
696 void renderFeature(Graphics g, SequenceI seq, int fstart, int fend,
697 Color featureColour, int start, int end, int y1)
700 if (((fstart <= end) && (fend >= start)))
703 { // fix for if the feature we have starts before the sequence start,
704 fstart = start; // but the feature end is still valid!!
712 for (i = fstart; i <= fend; i++)
714 s = seq.getCharAt(i);
716 if (jalview.util.Comparison.isGap(s))
721 g.setColor(featureColour);
723 g.fillRect((i - start) * av.charWidth, y1, av.charWidth,
726 if (!av.validCharWidth)
731 g.setColor(Color.white);
732 charOffset = (av.charWidth - fm.charWidth(s)) / 2;
733 g.drawString(String.valueOf(s), charOffset
734 + (av.charWidth * (i - start)), (y1 + av.charHeight)
735 - av.charHeight / 5); // pady = height / 5;
741 Hashtable minmax = null;
743 void findAllFeatures()
745 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
747 av.featuresDisplayed = new Hashtable();
748 Vector allfeatures = new Vector();
749 minmax = new Hashtable();
751 for (int i = 0; i < av.alignment.getHeight(); i++)
753 SequenceFeature[] features = av.alignment.getSequenceAt(i)
754 .getSequenceFeatures();
756 if (features == null)
762 while (index < features.length)
764 if (features[index].begin == 0 && features[index].end == 0)
769 if (!av.featuresDisplayed.containsKey(features[index].getType()))
771 if (getColour(features[index].getType()) == null)
773 featureColours.put(features[index].getType(), ucs
774 .createColourFromName(features[index].getType()));
777 av.featuresDisplayed.put(features[index].getType(), new Integer(
778 getColour(features[index].getType()).getRGB()));
779 allfeatures.addElement(features[index].getType());
781 if (features[index].score != Float.NaN)
783 int nonpos = features[index].getBegin() >= 1 ? 0 : 1;
784 float[][] mm = (float[][]) minmax.get(features[index].getType());
789 minmax.put(features[index].getType(), mm);
791 if (mm[nonpos] == null)
793 mm[nonpos] = new float[]
794 { features[index].score, features[index].score };
799 if (mm[nonpos][0] > features[index].score)
801 mm[nonpos][0] = features[index].score;
803 if (mm[nonpos][1] < features[index].score)
805 mm[nonpos][1] = features[index].score;
814 renderOrder = new String[allfeatures.size()];
815 Enumeration en = allfeatures.elements();
816 int i = allfeatures.size() - 1;
817 while (en.hasMoreElements())
819 renderOrder[i] = en.nextElement().toString();
825 * get a feature style object for the given type string. Creates a
826 * java.awt.Color for a featureType with no existing colourscheme. TODO:
827 * replace return type with object implementing standard abstract colour/style
831 * @return java.awt.Color or GraduatedColor
833 public Object getFeatureStyle(String featureType)
835 Object fc = featureColours.get(featureType);
838 jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
839 Color col = ucs.createColourFromName(featureType);
840 featureColours.put(featureType, fc = col);
845 public Color getColour(String featureType)
847 Object fc = getFeatureStyle(featureType);
849 if (fc instanceof Color)
855 if (fc instanceof GraduatedColor)
857 return ((GraduatedColor) fc).getMaxColor();
860 throw new Error("Implementation Error: Unrecognised render object "
861 + fc.getClass() + " for features of type " + featureType);
865 * @param sequenceFeature
866 * @return true if feature is visible.
868 private boolean showFeature(SequenceFeature sequenceFeature)
870 Object fc = getFeatureStyle(sequenceFeature.type);
871 if (fc instanceof GraduatedColor)
873 return ((GraduatedColor) fc).isColored(sequenceFeature);
874 } else { return true; }
878 * implement graduated colouring for features with scores
881 * @return render colour for the given feature
883 public Color getColour(SequenceFeature feature)
885 Object fc = getFeatureStyle(feature.getType());
886 if (fc instanceof Color)
892 if (fc instanceof GraduatedColor)
894 return ((GraduatedColor) fc).findColor(feature);
897 throw new Error("Implementation Error: Unrecognised render object "
898 + fc.getClass() + " for features of type " + feature.getType());
901 public void setColour(String featureType, Object col)
904 // Color _col = (col instanceof Color) ? ((Color) col) : (col instanceof
905 // GraduatedColor) ? ((GraduatedColor) col).getMaxColor() : null;
906 // Object c = featureColours.get(featureType);
907 // if (c == null || c instanceof Color || (c instanceof GraduatedColor &&
908 // !((GraduatedColor)c).getMaxColor().equals(_col)))
910 featureColours.put(featureType, col);
914 public void setFeaturePriority(Object[][] data)
916 // The feature table will display high priority
917 // features at the top, but theses are the ones
918 // we need to render last, so invert the data
919 if (av.featuresDisplayed != null)
921 av.featuresDisplayed.clear();
925 * if (visibleNew) { if (av.featuresDisplayed != null) {
926 * av.featuresDisplayed.clear(); } else { av.featuresDisplayed = new
927 * Hashtable(); } } if (data == null) { return; }
930 renderOrder = new String[data.length];
934 for (int i = 0; i < data.length; i++)
936 String type = data[i][0].toString();
937 setColour(type, data[i][1]);
938 if (((Boolean) data[i][2]).booleanValue())
940 av.featuresDisplayed.put(type, new Integer(getColour(type)
944 renderOrder[data.length - i - 1] = type;
950 * @return a simple list of feature group names or null
952 public String[] getGroups()
955 if (featureGroups != null)
957 String[] gps = new String[featureGroups.size()];
958 Enumeration gn = featureGroups.keys();
960 while (gn.hasMoreElements())
962 gps[i++] = (String) gn.nextElement();
970 * get visible or invisible groups
973 * true to return visible groups, false to return hidden ones.
974 * @return list of groups
976 public String[] getGroups(boolean visible)
979 if (featureGroups != null)
981 Vector gp = new Vector();
983 Enumeration gn = featureGroups.keys();
984 while (gn.hasMoreElements())
986 String nm = (String) gn.nextElement();
987 Boolean state = (Boolean) featureGroups.get(nm);
988 if (state.booleanValue() == visible)
993 String[] gps = new String[gp.size()];
997 while (gn.hasMoreElements())
999 gps[i++] = (String) gn.nextElement();
1007 * set all feature groups in toset to be visible or invisible
1012 * the state of the named groups to set
1014 public void setGroupState(String[] toset, boolean visible)
1017 if (toset != null && toset.length > 0 && featureGroups != null)
1019 boolean rdrw = false;
1020 for (int i = 0; i < toset.length; i++)
1022 Object st = featureGroups.get(toset[i]);
1025 featureGroups.put(toset[i], new Boolean(visible));
1026 rdrw = rdrw || (visible != ((Boolean) st).booleanValue());
1031 if (this.av != null)
1032 if (this.av.featureSettings != null)
1034 av.featureSettings.rebuildGroups();
1035 this.av.featureSettings.resetTable(true);
1043 av.alignmentChanged(null);
1050 * analyse alignment for groups and hash tables (used to be embedded in
1051 * FeatureSettings.setTableData)
1053 * @return true if features are on the alignment
1055 public boolean buildGroupHash()
1057 boolean alignmentHasFeatures = false;
1058 if (featureGroups == null)
1060 featureGroups = new Hashtable();
1062 Vector allFeatures = new Vector();
1063 Vector allGroups = new Vector();
1064 SequenceFeature[] tmpfeatures;
1066 for (int i = 0; i < av.alignment.getHeight(); i++)
1068 if (av.alignment.getSequenceAt(i).getSequenceFeatures() == null)
1073 alignmentHasFeatures = true;
1075 tmpfeatures = av.alignment.getSequenceAt(i).getSequenceFeatures();
1077 while (index < tmpfeatures.length)
1079 if (tmpfeatures[index].getFeatureGroup() != null)
1081 group = tmpfeatures[index].featureGroup;
1082 if (!allGroups.contains(group))
1084 allGroups.addElement(group);
1086 boolean visible = true;
1087 if (featureGroups.containsKey(group))
1089 visible = ((Boolean) featureGroups.get(group)).booleanValue();
1093 featureGroups.put(group, new Boolean(visible));
1098 if (!allFeatures.contains(tmpfeatures[index].getType()))
1100 allFeatures.addElement(tmpfeatures[index].getType());
1106 return alignmentHasFeatures;
1110 * rebuild the featuresDisplayed and renderorder list based on the
1111 * featureGroups hash and any existing display state and force a repaint if
1114 * @return true if alignment has visible features
1116 public boolean buildFeatureHash()
1118 boolean alignmentHasFeatures = false;
1119 if (featureGroups == null)
1121 alignmentHasFeatures = buildGroupHash();
1123 if (!alignmentHasFeatures)
1125 Hashtable fdisp = av.featuresDisplayed;
1126 Vector allFeatures = new Vector();
1127 SequenceFeature[] tmpfeatures;
1129 for (int i = 0; i < av.alignment.getHeight(); i++)
1131 if (av.alignment.getSequenceAt(i).getSequenceFeatures() == null)
1136 alignmentHasFeatures = true;
1138 tmpfeatures = av.alignment.getSequenceAt(i).getSequenceFeatures();
1140 while (index < tmpfeatures.length)
1142 boolean visible = true;
1143 if (tmpfeatures[index].getFeatureGroup() != null)
1145 group = tmpfeatures[index].featureGroup;
1146 if (featureGroups.containsKey(group))
1148 visible = ((Boolean) featureGroups.get(group)).booleanValue();
1152 if (visible && !allFeatures.contains(tmpfeatures[index].getType()))
1154 allFeatures.addElement(tmpfeatures[index].getType());
1159 if (allFeatures.size() > 0)
1161 String[] neworder = new String[allFeatures.size()];
1162 int p = neworder.length - 1;
1163 for (int i = renderOrder.length - 1; i >= 0; i--)
1165 if (allFeatures.contains(renderOrder[i]))
1167 neworder[p--] = renderOrder[i];
1168 allFeatures.removeElement(renderOrder[i]);
1172 av.featuresDisplayed.remove(renderOrder[i]);
1175 for (int i = allFeatures.size() - 1; i > 0; i++)
1177 Object e = allFeatures.elementAt(i);
1180 neworder[p--] = (String) e;
1181 av.featuresDisplayed.put(e, getColour((String) e));
1184 renderOrder = neworder;
1188 return alignmentHasFeatures;
1193 * @return the displayed feature type as an array of strings
1195 protected String[] getDisplayedFeatureTypes()
1197 String[] typ = null;
1198 synchronized (renderOrder)
1200 typ = new String[renderOrder.length];
1201 System.arraycopy(renderOrder, 0, typ, 0, typ.length);
1202 for (int i = 0; i < typ.length; i++)
1204 if (av.featuresDisplayed.get(typ[i]) == null)
1214 class TransparencySetter
1216 void setTransparency(Graphics g, float value)
1218 Graphics2D g2 = (Graphics2D) g;
1219 g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,