Formatting
[jalview.git] / src / jalview / gui / FeatureRenderer.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.gui;\r
20 \r
21 import java.util.*;\r
22 \r
23 import java.awt.*;\r
24 import java.awt.event.*;\r
25 import java.awt.image.*;\r
26 import javax.swing.*;\r
27 \r
28 import jalview.datamodel.*;\r
29 \r
30 /**\r
31  * DOCUMENT ME!\r
32  *\r
33  * @author $author$\r
34  * @version $Revision$\r
35  */\r
36 public class FeatureRenderer\r
37 {\r
38   AlignViewport av;\r
39   Color resBoxColour;\r
40   float transparency = 1.0f;\r
41   FontMetrics fm;\r
42   int charOffset;\r
43 \r
44   Hashtable featureColours = new Hashtable();\r
45 \r
46   // A higher level for grouping features of a\r
47   // particular type\r
48   Hashtable featureGroups = null;\r
49 \r
50   // This is actually an Integer held in the hashtable,\r
51   // Retrieved using the key feature type\r
52   Object currentColour;\r
53 \r
54   String[] renderOrder;\r
55 \r
56   /**\r
57    * Creates a new FeatureRenderer object.\r
58    *\r
59    * @param av DOCUMENT ME!\r
60    */\r
61   public FeatureRenderer(AlignViewport av)\r
62   {\r
63     this.av = av;\r
64   }\r
65 \r
66   public void transferSettings(FeatureRenderer fr)\r
67   {\r
68     renderOrder = fr.renderOrder;\r
69     featureGroups = fr.featureGroups;\r
70     featureColours = fr.featureColours;\r
71     transparency = fr.transparency;\r
72   }\r
73 \r
74   BufferedImage offscreenImage;\r
75   boolean offscreenRender = false;\r
76   public Color findFeatureColour(Color initialCol, SequenceI seq, int res)\r
77   {\r
78     return new Color(findFeatureColour(initialCol.getRGB(),\r
79                                        seq, res));\r
80   }\r
81 \r
82   /**\r
83    * This is used by the Molecule Viewer and Overview to\r
84    * get the accurate colourof the rendered sequence\r
85    */\r
86   public int findFeatureColour(int initialCol, SequenceI seq, int column)\r
87   {\r
88     if (!av.showSequenceFeatures)\r
89     {\r
90       return initialCol;\r
91     }\r
92 \r
93     if (seq != lastSeq)\r
94     {\r
95       lastSeq = seq;\r
96       sequenceFeatures = lastSeq.getDatasetSequence().getSequenceFeatures();\r
97       if (sequenceFeatures == null)\r
98       {\r
99         return initialCol;\r
100       }\r
101 \r
102       sfSize = sequenceFeatures.length;\r
103     }\r
104 \r
105     if (jalview.util.Comparison.isGap(lastSeq.getCharAt(column)))\r
106     {\r
107       return Color.white.getRGB();\r
108     }\r
109 \r
110     //Only bother making an offscreen image if transparency is applied\r
111     if (transparency != 1.0f && offscreenImage == null)\r
112     {\r
113       offscreenImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);\r
114     }\r
115 \r
116     currentColour = null;\r
117 \r
118     offscreenRender = true;\r
119 \r
120     if (offscreenImage != null)\r
121     {\r
122       offscreenImage.setRGB(0, 0, initialCol);\r
123       drawSequence(offscreenImage.getGraphics(),\r
124                    lastSeq,\r
125                    column, column, 0);\r
126 \r
127       return offscreenImage.getRGB(0, 0);\r
128     }\r
129     else\r
130     {\r
131       drawSequence(null,\r
132                    lastSeq,\r
133                    lastSeq.findPosition(column),\r
134                    -1, -1);\r
135 \r
136       if (currentColour == null)\r
137       {\r
138         return initialCol;\r
139       }\r
140       else\r
141       {\r
142         return ( (Integer) currentColour).intValue();\r
143       }\r
144     }\r
145 \r
146   }\r
147 \r
148   /**\r
149    * DOCUMENT ME!\r
150    *\r
151    * @param g DOCUMENT ME!\r
152    * @param seq DOCUMENT ME!\r
153    * @param sg DOCUMENT ME!\r
154    * @param start DOCUMENT ME!\r
155    * @param end DOCUMENT ME!\r
156    * @param x1 DOCUMENT ME!\r
157    * @param y1 DOCUMENT ME!\r
158    * @param width DOCUMENT ME!\r
159    * @param height DOCUMENT ME!\r
160    */\r
161   // String type;\r
162   // SequenceFeature sf;\r
163   SequenceI lastSeq;\r
164   SequenceFeature[] sequenceFeatures;\r
165   int sfSize, sfindex, spos, epos;\r
166 \r
167   public void drawSequence(Graphics g, SequenceI seq,\r
168                            int start, int end, int y1)\r
169   {\r
170     if (seq.getDatasetSequence().getSequenceFeatures() == null\r
171         || seq.getDatasetSequence().getSequenceFeatures().length == 0)\r
172     {\r
173       return;\r
174     }\r
175 \r
176     if (g != null)\r
177     {\r
178       fm = g.getFontMetrics();\r
179     }\r
180 \r
181     if (av.featuresDisplayed == null\r
182         || renderOrder == null\r
183         || newFeatureAdded)\r
184     {\r
185       findAllFeatures();\r
186       if (av.featuresDisplayed.size() < 1)\r
187       {\r
188         return;\r
189       }\r
190 \r
191       sequenceFeatures = seq.getDatasetSequence().getSequenceFeatures();\r
192       sfSize = sequenceFeatures.length;\r
193     }\r
194 \r
195     if (lastSeq == null || seq != lastSeq)\r
196     {\r
197       lastSeq = seq;\r
198       sequenceFeatures = seq.getDatasetSequence().getSequenceFeatures();\r
199       sfSize = sequenceFeatures.length;\r
200     }\r
201 \r
202     if (transparency != 1 && g != null)\r
203     {\r
204       Graphics2D g2 = (Graphics2D) g;\r
205       g2.setComposite(\r
206           AlphaComposite.getInstance(\r
207               AlphaComposite.SRC_OVER, transparency));\r
208     }\r
209 \r
210     if (!offscreenRender)\r
211     {\r
212       spos = lastSeq.findPosition(start);\r
213       epos = lastSeq.findPosition(end);\r
214     }\r
215 \r
216     String type;\r
217     for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++)\r
218     {\r
219       type = renderOrder[renderIndex];\r
220 \r
221       if (type == null || !av.featuresDisplayed.containsKey(type))\r
222       {\r
223         continue;\r
224       }\r
225 \r
226       // loop through all features in sequence to find\r
227       // current feature to render\r
228       for (sfindex = 0; sfindex < sfSize; sfindex++)\r
229       {\r
230         if (sequenceFeatures.length <= sfindex)\r
231         {\r
232           continue;\r
233         }\r
234         if (!sequenceFeatures[sfindex].type.equals(type))\r
235         {\r
236           continue;\r
237         }\r
238 \r
239         if (featureGroups != null\r
240             && sequenceFeatures[sfindex].featureGroup != null\r
241             &&\r
242             featureGroups.containsKey(sequenceFeatures[sfindex].featureGroup)\r
243             &&\r
244             ! ( (Boolean) featureGroups.get(sequenceFeatures[sfindex].\r
245                                             featureGroup)).\r
246             booleanValue())\r
247         {\r
248           continue;\r
249         }\r
250 \r
251         if (!offscreenRender && (sequenceFeatures[sfindex].getBegin() > epos\r
252                                  || sequenceFeatures[sfindex].getEnd() < spos))\r
253         {\r
254           continue;\r
255         }\r
256 \r
257         if (offscreenRender && offscreenImage == null)\r
258         {\r
259           if (sequenceFeatures[sfindex].begin <= start &&\r
260               sequenceFeatures[sfindex].end >= start)\r
261           {\r
262             currentColour = av.featuresDisplayed.get(sequenceFeatures[sfindex].\r
263                 type);\r
264           }\r
265         }\r
266         else if (sequenceFeatures[sfindex].type.equals("disulfide bond"))\r
267         {\r
268 \r
269           renderFeature(g, seq,\r
270                         seq.findIndex(sequenceFeatures[sfindex].begin) - 1,\r
271                         seq.findIndex(sequenceFeatures[sfindex].begin) - 1,\r
272                         new Color( ( (Integer) av.featuresDisplayed.get(\r
273                             sequenceFeatures[sfindex].type)).intValue()),\r
274                         start, end, y1);\r
275           renderFeature(g, seq,\r
276                         seq.findIndex(sequenceFeatures[sfindex].end) - 1,\r
277                         seq.findIndex(sequenceFeatures[sfindex].end) - 1,\r
278                         new Color( ( (Integer) av.featuresDisplayed.get(\r
279                             sequenceFeatures[sfindex].type)).intValue()),\r
280                         start, end, y1);\r
281 \r
282         }\r
283         else\r
284         {\r
285           renderFeature(g, seq,\r
286                         seq.findIndex(sequenceFeatures[sfindex].begin) - 1,\r
287                         seq.findIndex(sequenceFeatures[sfindex].end) - 1,\r
288                         getColour(sequenceFeatures[sfindex].type),\r
289                         start, end, y1);\r
290         }\r
291 \r
292       }\r
293 \r
294     }\r
295 \r
296     if (transparency != 1.0f && g != null)\r
297     {\r
298       Graphics2D g2 = (Graphics2D) g;\r
299       g2.setComposite(\r
300           AlphaComposite.getInstance(\r
301               AlphaComposite.SRC_OVER, 1.0f));\r
302     }\r
303   }\r
304 \r
305   char s;\r
306   int i;\r
307   void renderFeature(Graphics g, SequenceI seq,\r
308                      int fstart, int fend, Color featureColour, int start,\r
309                      int end, int y1)\r
310   {\r
311 \r
312     if ( ( (fstart <= end) && (fend >= start)))\r
313     {\r
314       if (fstart < start)\r
315       { // fix for if the feature we have starts before the sequence start,\r
316         fstart = start; // but the feature end is still valid!!\r
317       }\r
318 \r
319       if (fend >= end)\r
320       {\r
321         fend = end;\r
322       }\r
323       int pady = (y1 + av.charHeight) - av.charHeight / 5;\r
324       for (i = fstart; i <= fend; i++)\r
325       {\r
326         s = seq.getCharAt(i);\r
327 \r
328         if (jalview.util.Comparison.isGap(s))\r
329         {\r
330           continue;\r
331         }\r
332 \r
333         g.setColor(featureColour);\r
334 \r
335         g.fillRect( (i - start) * av.charWidth, y1, av.charWidth, av.charHeight);\r
336 \r
337         if (offscreenRender || !av.validCharWidth)\r
338         {\r
339           continue;\r
340         }\r
341 \r
342         g.setColor(Color.white);\r
343         charOffset = (av.charWidth - fm.charWidth(s)) / 2;\r
344         g.drawString(String.valueOf(s),\r
345                      charOffset + (av.charWidth * (i - start)),\r
346                      pady);\r
347 \r
348       }\r
349     }\r
350   }\r
351 \r
352   boolean newFeatureAdded = false;\r
353 \r
354   public void featuresAdded()\r
355   {\r
356     findAllFeatures();\r
357   }\r
358 \r
359   boolean findingFeatures = false;\r
360   synchronized void findAllFeatures()\r
361   {\r
362     newFeatureAdded = false;\r
363 \r
364     if (findingFeatures)\r
365     {\r
366       newFeatureAdded = true;\r
367       return;\r
368     }\r
369 \r
370     findingFeatures = true;\r
371     jalview.schemes.UserColourScheme ucs = new\r
372         jalview.schemes.UserColourScheme();\r
373 \r
374     if (av.featuresDisplayed == null)\r
375     {\r
376       av.featuresDisplayed = new Hashtable();\r
377     }\r
378 \r
379     av.featuresDisplayed.clear();\r
380 \r
381     Vector allfeatures = new Vector();\r
382     for (int i = 0; i < av.alignment.getHeight(); i++)\r
383     {\r
384       SequenceFeature[] features\r
385           = av.alignment.getSequenceAt(i).getDatasetSequence().\r
386           getSequenceFeatures();\r
387 \r
388       if (features == null)\r
389       {\r
390         continue;\r
391       }\r
392 \r
393       int index = 0;\r
394       while (index < features.length)\r
395       {\r
396         if (!av.featuresDisplayed.containsKey(features[index].getType()))\r
397         {\r
398           if (! (features[index].begin == 0 && features[index].end == 0))\r
399           {\r
400             // If beginning and end are 0, the feature is for the whole sequence\r
401             // and we don't want to render the feature in the normal way\r
402 \r
403             if (getColour(features[index].getType()) == null)\r
404             {\r
405               featureColours.put(features[index].getType(),\r
406                                  ucs.createColourFromName(features[index].\r
407                   getType()));\r
408             }\r
409 \r
410             av.featuresDisplayed.put(features[index].getType(),\r
411                                      new Integer(getColour(features[index].\r
412                 getType()).getRGB()));\r
413             allfeatures.addElement(features[index].getType());\r
414           }\r
415         }\r
416         index++;\r
417       }\r
418     }\r
419 \r
420     renderOrder = new String[allfeatures.size()];\r
421     Enumeration en = allfeatures.elements();\r
422     int i = allfeatures.size() - 1;\r
423     while (en.hasMoreElements())\r
424     {\r
425       renderOrder[i] = en.nextElement().toString();\r
426       i--;\r
427     }\r
428 \r
429     findingFeatures = false;\r
430   }\r
431 \r
432   public Color getColour(String featureType)\r
433   {\r
434     Color colour = (Color) featureColours.get(featureType);\r
435     return colour;\r
436   }\r
437 \r
438   static String lastFeatureAdded;\r
439   static String lastFeatureGroupAdded;\r
440   static String lastDescriptionAdded;\r
441 \r
442   public boolean createNewFeatures(SequenceI[] sequences,\r
443                                    SequenceFeature[] features)\r
444   {\r
445     return amendFeatures(sequences, features, true, null);\r
446   }\r
447 \r
448   int featureIndex = 0;\r
449   boolean amendFeatures(final SequenceI[] sequences,\r
450                         final SequenceFeature[] features,\r
451                         boolean newFeatures,\r
452                         final AlignmentPanel ap)\r
453   {\r
454     JPanel bigPanel = new JPanel(new BorderLayout());\r
455     final JComboBox name = new JComboBox();\r
456     final JComboBox source = new JComboBox();\r
457     final JTextArea description = new JTextArea(3, 25);\r
458     final JSpinner start = new JSpinner();\r
459     final JSpinner end = new JSpinner();\r
460     start.setPreferredSize(new Dimension(80, 20));\r
461     end.setPreferredSize(new Dimension(80, 20));\r
462     final JPanel colour = new JPanel();\r
463     colour.setBorder(BorderFactory.createEtchedBorder());\r
464     colour.setMaximumSize(new Dimension(40, 10));\r
465     colour.addMouseListener(new MouseAdapter()\r
466     {\r
467       public void mousePressed(MouseEvent evt)\r
468       {\r
469         colour.setBackground(\r
470             JColorChooser.showDialog(Desktop.desktop,\r
471                                      "Select Feature Colour",\r
472                                      colour.getBackground()));\r
473       }\r
474     });\r
475 \r
476     JPanel panel = new JPanel(new GridLayout(3, 2));\r
477     panel.add(new JLabel("Sequence Feature Name: ", JLabel.RIGHT));\r
478     panel.add(name);\r
479     panel.add(new JLabel("Feature Group: ", JLabel.RIGHT));\r
480     panel.add(source);\r
481     panel.add(new JLabel("Feature Colour: ", JLabel.RIGHT));\r
482     JPanel tmp = new JPanel();\r
483     tmp.add(colour);\r
484     colour.setPreferredSize(new Dimension(150, 15));\r
485     panel.add(tmp);\r
486     name.setEditable(true);\r
487     source.setEditable(true);\r
488 \r
489     bigPanel.add(panel, BorderLayout.NORTH);\r
490     panel = new JPanel();\r
491     panel.add(new JLabel("Description: ", JLabel.RIGHT));\r
492     description.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));\r
493     description.setLineWrap(true);\r
494     panel.add(new JScrollPane(description));\r
495 \r
496     if (!newFeatures)\r
497     {\r
498       bigPanel.add(panel, BorderLayout.SOUTH);\r
499 \r
500       panel = new JPanel();\r
501       panel.add(new JLabel(" Start:", JLabel.RIGHT));\r
502       panel.add(start);\r
503       panel.add(new JLabel("  End:", JLabel.RIGHT));\r
504       panel.add(end);\r
505       bigPanel.add(panel, BorderLayout.CENTER);\r
506     }\r
507     else\r
508     {\r
509       bigPanel.add(panel, BorderLayout.CENTER);\r
510     }\r
511 \r
512     if (lastFeatureAdded == null)\r
513     {\r
514       if (features[0].type != null)\r
515       {\r
516         lastFeatureAdded = features[0].type;\r
517       }\r
518       else\r
519       {\r
520         lastFeatureAdded = "feature_1";\r
521       }\r
522     }\r
523 \r
524     if (lastFeatureGroupAdded == null)\r
525     {\r
526       if (features[0].featureGroup != null)\r
527       {\r
528         lastFeatureGroupAdded = features[0].featureGroup;\r
529       }\r
530       else\r
531       {\r
532         lastFeatureAdded = "Jalview";\r
533       }\r
534     }\r
535 \r
536     Enumeration en;\r
537     if (featureGroups != null)\r
538     {\r
539       en = featureGroups.keys();\r
540       while (en.hasMoreElements())\r
541       {\r
542         source.addItem(en.nextElement().toString());\r
543       }\r
544     }\r
545 \r
546     if (newFeatures)\r
547     {\r
548       if (av.featuresDisplayed != null)\r
549       {\r
550         en = av.featuresDisplayed.keys();\r
551         while (en.hasMoreElements())\r
552         {\r
553           name.addItem(en.nextElement().toString());\r
554         }\r
555       }\r
556 \r
557       name.setSelectedItem(lastFeatureAdded);\r
558       source.setSelectedItem(lastFeatureGroupAdded);\r
559       description.setText(\r
560           lastDescriptionAdded == null ?\r
561           features[0].description : lastDescriptionAdded);\r
562 \r
563       if (getColour(lastFeatureAdded) != null)\r
564       {\r
565         colour.setBackground(getColour(lastFeatureAdded));\r
566       }\r
567       else\r
568       {\r
569         colour.setBackground(new Color(60, 160, 115));\r
570       }\r
571 \r
572     }\r
573     else if (!newFeatures)\r
574     {\r
575       featureIndex = 0;\r
576       for (int f = 0; f < features.length; f++)\r
577       {\r
578         name.addItem(features[f].getType().toString());\r
579       }\r
580 \r
581       description.setText(features[0].getDescription());\r
582       source.setSelectedItem(features[0].getFeatureGroup());\r
583       start.setValue(new Integer(features[0].getBegin()));\r
584       end.setValue(new Integer(features[0].getEnd()));\r
585       colour.setBackground(\r
586           getColour(name.getSelectedItem().toString()));\r
587       name.addItemListener(new ItemListener()\r
588       {\r
589         public void itemStateChanged(ItemEvent e)\r
590         {\r
591           int index = name.getSelectedIndex();\r
592           if (index != -1)\r
593           {\r
594             featureIndex = index;\r
595             description.setText(features[index].getDescription());\r
596             source.setSelectedItem(features[index].getFeatureGroup());\r
597             start.setValue(new Integer(features[index].getBegin()));\r
598             end.setValue(new Integer(features[index].getEnd()));\r
599             colour.setBackground(\r
600                 getColour(name.getSelectedItem().toString()));\r
601 \r
602             SearchResults highlight = new SearchResults();\r
603             highlight.addResult(sequences[0],\r
604                                 features[index].getBegin(),\r
605                                 features[index].getEnd());\r
606 \r
607             ap.seqPanel.seqCanvas.highlightSearchResults(highlight);\r
608 \r
609           }\r
610           Color col = getColour(name.getSelectedItem().toString());\r
611           if (col == null)\r
612           {\r
613             col = new\r
614                 jalview.schemes.UserColourScheme()\r
615                 .createColourFromName(name.getSelectedItem().toString());\r
616           }\r
617 \r
618           colour.setBackground(col);\r
619         }\r
620       });\r
621 \r
622     }\r
623 \r
624     Object[] options;\r
625     if (!newFeatures)\r
626     {\r
627       options = new Object[]\r
628           {\r
629           "Amend", "Delete", "Cancel"};\r
630     }\r
631     else\r
632     {\r
633       options = new Object[]\r
634           {\r
635           "OK", "Cancel"};\r
636     }\r
637 \r
638     String title = newFeatures ? "Create New Sequence Feature(s)" :\r
639         "Amend/Delete Features for "\r
640         + sequences[0].getName();\r
641 \r
642     int reply = JOptionPane.showInternalOptionDialog(Desktop.desktop,\r
643         bigPanel,\r
644         title,\r
645         JOptionPane.YES_NO_CANCEL_OPTION,\r
646         JOptionPane.QUESTION_MESSAGE,\r
647         null,\r
648         options, "OK");\r
649 \r
650     jalview.io.FeaturesFile ffile = new jalview.io.FeaturesFile();\r
651 \r
652     if (reply == JOptionPane.OK_OPTION\r
653         && name.getSelectedItem() != null\r
654         && source.getSelectedItem() != null)\r
655     {\r
656       //This ensures that the last sequence\r
657       //is refreshed and new features are rendered\r
658       lastSeq = null;\r
659       lastFeatureAdded = name.getSelectedItem().toString();\r
660       lastFeatureGroupAdded = source.getSelectedItem().toString();\r
661       lastDescriptionAdded = description.getText().replaceAll("\n", " ");\r
662     }\r
663 \r
664     if (!newFeatures)\r
665     {\r
666       SequenceFeature sf = features[featureIndex];\r
667 \r
668       if (reply == JOptionPane.NO_OPTION)\r
669       {\r
670         sequences[0].getDatasetSequence().deleteFeature(sf);\r
671       }\r
672       else if (reply == JOptionPane.YES_OPTION)\r
673       {\r
674         sf.type = lastFeatureAdded;\r
675         sf.featureGroup = lastFeatureGroupAdded;\r
676         sf.description = lastDescriptionAdded;\r
677         setColour(sf.type, colour.getBackground());\r
678         try\r
679         {\r
680           sf.begin = ( (Integer) start.getValue()).intValue();\r
681           sf.end = ( (Integer) end.getValue()).intValue();\r
682         }\r
683         catch (NumberFormatException ex)\r
684         {}\r
685 \r
686         ffile.parseDescriptionHTML(sf, false);\r
687       }\r
688     }\r
689     else\r
690     {\r
691       if (reply == JOptionPane.OK_OPTION\r
692           && name.getSelectedItem() != null\r
693           && source.getSelectedItem() != null)\r
694       {\r
695         for (int i = 0; i < sequences.length; i++)\r
696         {\r
697           features[i].type = lastFeatureAdded;\r
698           features[i].featureGroup = lastFeatureGroupAdded;\r
699           features[i].description = lastDescriptionAdded;\r
700           sequences[i].addSequenceFeature(features[i]);\r
701           ffile.parseDescriptionHTML(features[i], false);\r
702         }\r
703 \r
704         if (av.featuresDisplayed == null)\r
705         {\r
706           av.featuresDisplayed = new Hashtable();\r
707         }\r
708 \r
709         if (featureGroups == null)\r
710         {\r
711           featureGroups = new Hashtable();\r
712         }\r
713 \r
714         featureGroups.put(lastFeatureGroupAdded, new Boolean(true));\r
715 \r
716         Color col = colour.getBackground();\r
717         setColour(lastFeatureAdded, colour.getBackground());\r
718 \r
719         av.featuresDisplayed.put(lastFeatureGroupAdded,\r
720                                  new Integer(col.getRGB()));\r
721 \r
722         findAllFeatures();\r
723 \r
724         return true;\r
725       }\r
726       else\r
727       {\r
728         return false;\r
729       }\r
730     }\r
731 \r
732     if (name.getSelectedIndex() == -1)\r
733     {\r
734       findAllFeatures();\r
735     }\r
736 \r
737     return true;\r
738   }\r
739 \r
740   public void setColour(String featureType, Color col)\r
741   {\r
742     featureColours.put(featureType, col);\r
743   }\r
744 \r
745   public void setTransparency(float value)\r
746   {\r
747     transparency = value;\r
748   }\r
749 \r
750   public float getTransparency()\r
751   {\r
752     return transparency;\r
753   }\r
754 \r
755   public void setFeaturePriority(Object[][] data)\r
756   {\r
757     // The feature table will display high priority\r
758     // features at the top, but theses are the ones\r
759     // we need to render last, so invert the data\r
760     if (av.featuresDisplayed != null)\r
761     {\r
762       av.featuresDisplayed.clear();\r
763     }\r
764     else\r
765     {\r
766       av.featuresDisplayed = new Hashtable();\r
767     }\r
768 \r
769     renderOrder = new String[data.length];\r
770 \r
771     if (data.length > 0)\r
772     {\r
773       for (int i = 0; i < data.length; i++)\r
774       {\r
775         String type = data[i][0].toString();\r
776         setColour(type, (Color) data[i][1]);\r
777         if ( ( (Boolean) data[i][2]).booleanValue())\r
778         {\r
779           av.featuresDisplayed.put(type, new Integer(getColour(type).getRGB()));\r
780         }\r
781 \r
782         renderOrder[data.length - i - 1] = type;\r
783       }\r
784     }\r
785 \r
786   }\r
787 \r
788 }\r