3 * Jalview - A Sequence Alignment Editor and Viewer
4 * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20 package jalview.appletgui;
22 import jalview.datamodel.*;
34 public class FeatureRenderer
38 Hashtable featureColours = new Hashtable();
40 // A higher level for grouping features of a
42 Hashtable featureGroups = null;
44 // Holds web links for feature groups and feature types
45 // in the form label|link
46 Hashtable featureLinks = null;
49 // This is actually an Integer held in the hashtable,
50 // Retrieved using the key feature type
53 String [] renderOrder;
58 float transparency = 1f;
60 TransparencySetter transparencySetter = null;
63 * Creates a new FeatureRenderer object.
65 * @param av DOCUMENT ME!
67 public FeatureRenderer(AlignViewport av)
71 if(!System.getProperty("java.version").startsWith("1.1"))
72 transparencySetter = new TransparencySetter();
76 public void transferSettings(FeatureRenderer fr)
78 renderOrder = fr.renderOrder;
79 featureGroups = fr.featureGroups;
80 featureColours = fr.featureColours;
81 transparency = fr.transparency;
85 public Color findFeatureColour(Color initialCol, SequenceI seq, int i)
88 if(!av.showSequenceFeatures)
92 sequenceFeatures = lastSequence.getSequenceFeatures();
93 if(sequenceFeatures==null)
96 sfSize = sequenceFeatures.length;
98 if(jalview.util.Comparison.isGap(lastSequence.getCharAt(i)))
101 currentColour = null;
103 drawSequence(null, lastSequence, lastSequence.findPosition(i), -1,-1);
105 if(currentColour==null)
108 return new Color( ((Integer)currentColour).intValue() );
112 * This is used by the Molecule Viewer to get the accurate colour
113 * of the rendered sequence
115 boolean overview = false;
117 int white = Color.white.getRGB();
118 public int findFeatureColour(int initialCol, int seqIndex, int column)
120 if(!av.showSequenceFeatures)
123 if(seqIndex!=lastSequenceIndex)
125 lastSequence = av.alignment.getSequenceAt(seqIndex);
126 lastSequenceIndex = seqIndex;
127 sequenceFeatures = lastSequence.getSequenceFeatures();
128 if(sequenceFeatures==null)
131 sfSize = sequenceFeatures.length;
135 if(jalview.util.Comparison.isGap(lastSequence.getCharAt(column)))
136 return Color.white.getRGB();
138 currentColour = null;
140 drawSequence(null, lastSequence, lastSequence.findPosition(column), -1,-1);
142 if(currentColour==null)
145 return ((Integer)currentColour).intValue();
152 * @param g DOCUMENT ME!
153 * @param seq DOCUMENT ME!
154 * @param sg DOCUMENT ME!
155 * @param start DOCUMENT ME!
156 * @param end DOCUMENT ME!
157 * @param x1 DOCUMENT ME!
158 * @param y1 DOCUMENT ME!
159 * @param width DOCUMENT ME!
160 * @param height DOCUMENT ME!
163 // SequenceFeature sf;
164 int lastSequenceIndex=-1;
165 SequenceI lastSequence;
166 SequenceFeature [] sequenceFeatures;
167 int sfSize, sfindex, spos, epos;
169 public void drawSequence(Graphics g, SequenceI seq,
170 int start, int end, int y1)
172 if ( seq.getSequenceFeatures() == null
173 || seq.getSequenceFeatures().length==0)
176 if(transparencySetter!=null && g!=null)
178 transparencySetter.setTransparency(g, transparency);
181 if (av.featuresDisplayed == null || renderOrder==null)
184 if(av.featuresDisplayed.size()<1)
187 sequenceFeatures = seq.getSequenceFeatures();
188 sfSize = sequenceFeatures.length;
190 if(lastSequence==null || seq!=lastSequence)
193 sequenceFeatures = seq.getSequenceFeatures();
194 sfSize = sequenceFeatures.length;
198 spos = lastSequence.findPosition(start);
199 epos = lastSequence.findPosition(end);
201 fm = g.getFontMetrics();
204 for(int renderIndex=0; renderIndex<renderOrder.length; renderIndex++)
206 type = renderOrder[renderIndex];
207 if(!av.featuresDisplayed.containsKey(type))
210 // loop through all features in sequence to find
211 // current feature to render
212 for (sfindex = 0; sfindex < sfSize; sfindex++)
214 if (!sequenceFeatures[sfindex].type.equals(type))
217 if (featureGroups != null
218 && sequenceFeatures[sfindex].featureGroup != null
220 featureGroups.containsKey(sequenceFeatures[sfindex].featureGroup)
222 ! ( (Boolean) featureGroups.get(sequenceFeatures[sfindex].featureGroup)).
228 if (!overview && (sequenceFeatures[sfindex].getBegin() > epos
229 || sequenceFeatures[sfindex].getEnd() < spos))
234 if (sequenceFeatures[sfindex].begin <= start &&
235 sequenceFeatures[sfindex].end >= start)
237 currentColour = av.featuresDisplayed.get(sequenceFeatures[sfindex].
242 else if (sequenceFeatures[sfindex].type.equals("disulfide bond"))
245 renderFeature(g, seq,
246 seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
247 seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
248 new Color( ( (Integer) av.featuresDisplayed.get(
249 sequenceFeatures[sfindex].type)).intValue()),
251 renderFeature(g, seq,
252 seq.findIndex(sequenceFeatures[sfindex].end) - 1,
253 seq.findIndex(sequenceFeatures[sfindex].end) - 1,
254 new Color( ( (Integer) av.featuresDisplayed.get(
255 sequenceFeatures[sfindex].type)).intValue()),
260 renderFeature(g, seq,
261 seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
262 seq.findIndex(sequenceFeatures[sfindex].end) - 1,
263 getColour(sequenceFeatures[sfindex].type),
269 if(transparencySetter!=null && g!=null)
271 transparencySetter.setTransparency(g, 1.0f);
278 void renderFeature(Graphics g, SequenceI seq,
279 int fstart, int fend, Color featureColour, int start, int end, int y1)
282 if (((fstart <= end) && (fend >= start)))
285 { // fix for if the feature we have starts before the sequence start,
286 fstart = start; // but the feature end is still valid!!
294 for (i = fstart; i <= fend; i++)
296 s = seq.getSequence().charAt(i);
298 if (jalview.util.Comparison.isGap(s))
303 g.setColor(featureColour);
305 g.fillRect( (i - start) * av.charWidth, y1, av.charWidth, av.charHeight);
307 if(!av.validCharWidth)
310 g.setColor(Color.white);
311 charOffset = (av.charWidth - fm.charWidth(s)) / 2;
312 g.drawString(String.valueOf(s),
313 charOffset + (av.charWidth * (i - start)),
314 (y1 + av.charHeight) - av.charHeight / 5); //pady = height / 5;
320 void findAllFeatures()
322 jalview.schemes.UserColourScheme ucs = new
323 jalview.schemes.UserColourScheme();
325 av.featuresDisplayed = new Hashtable();
326 Vector allfeatures = new Vector();
327 for (int i = 0; i < av.alignment.getHeight(); i++)
329 SequenceFeature [] features = av.alignment.getSequenceAt(i).getSequenceFeatures();
331 if (features == null)
335 while (index < features.length)
337 if (!av.featuresDisplayed.containsKey(features[index].getType()))
339 if (getColour(features[index].getType()) == null)
341 featureColours.put(features[index].getType(),
342 ucs.createColourFromName(features[index].
347 av.featuresDisplayed.put(features[index].getType(),
348 new Integer( getColour(features[index].getType()).getRGB()) );
349 allfeatures.addElement(features[index].getType());
355 renderOrder = new String[allfeatures.size()];
356 Enumeration en = allfeatures.elements();
357 int i = allfeatures.size()-1;
358 while(en.hasMoreElements())
360 renderOrder[i] = en.nextElement().toString();
365 public Color getColour(String featureType)
367 return (Color)featureColours.get(featureType);
370 public void addNewFeature(String name, Color col)
373 setColour(name, col);
374 if(av.featuresDisplayed==null)
375 av.featuresDisplayed = new Hashtable();
378 av.featuresDisplayed.put(name, "NOGROUP");
381 public void setColour(String featureType, Color col)
383 featureColours.put(featureType, col);
386 public void setFeaturePriority(Object [][] data)
388 // The feature table will display high priority
389 // features at the top, but theses are the ones
390 // we need to render last, so invert the data
391 if(av.featuresDisplayed!=null)
392 av.featuresDisplayed.clear();
394 renderOrder = new String[data.length];
397 for (int i = 0; i < data.length; i++)
399 String type = data[i][0].toString();
400 setColour(type, (Color) data[i][1]);
401 if ( ( (Boolean) data[i][2]).booleanValue())
403 av.featuresDisplayed.put(type, new Integer(getColour(type).getRGB()));
406 renderOrder[data.length - i - 1] = type;
411 class TransparencySetter
413 void setTransparency(Graphics g, float value)
415 Graphics2D g2 = (Graphics2D) g;
417 AlphaComposite.getInstance(
418 AlphaComposite.SRC_OVER, value));