applied copyright 2008
[jalview.git] / src / jalview / appletgui / SequenceRenderer.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
3  * Copyright (C) 2008 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  * 
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.
9  * 
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.
14  * 
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
18  */
19 package jalview.appletgui;
20
21 import java.awt.*;
22
23 import jalview.datamodel.*;
24 import jalview.schemes.*;
25
26 public class SequenceRenderer
27 {
28   AlignViewport av;
29   FontMetrics fm;
30   boolean renderGaps = true;
31   SequenceGroup currentSequenceGroup = null;
32   SequenceGroup[] allGroups = null;
33   Color resBoxColour;
34   Graphics graphics;
35   boolean forOverview = false;
36
37   public SequenceRenderer(AlignViewport av)
38   {
39     this.av = av;
40   }
41
42   /**
43    * DOCUMENT ME!
44    *
45    * @param b DOCUMENT ME!
46    */
47   public void prepare(Graphics g, boolean renderGaps)
48   {
49     graphics = g;
50     fm = g.getFontMetrics();
51
52     this.renderGaps = renderGaps;
53   }
54
55   public Color getResidueBoxColour(SequenceI seq, int i)
56   {
57     allGroups = av.alignment.findAllGroups(seq);
58
59     if (inCurrentSequenceGroup(i))
60     {
61       if (currentSequenceGroup.getDisplayBoxes())
62       {
63         getBoxColour(currentSequenceGroup.cs, seq, i);
64       }
65     }
66     else if (av.getShowBoxes())
67     {
68       getBoxColour(av.globalColourScheme, seq, i);
69     }
70
71     return resBoxColour;
72   }
73
74   void getBoxColour(ColourSchemeI cs, SequenceI seq, int i)
75   {
76     if (cs != null)
77     {
78       resBoxColour = cs.findColour(seq.getCharAt(i), i);
79     }
80     else if (forOverview && !jalview.util.Comparison.isGap(seq.getCharAt(i)))
81     {
82       resBoxColour = Color.lightGray;
83     }
84     else
85     {
86       resBoxColour = Color.white;
87     }
88
89   }
90
91   public Color findSequenceColour(SequenceI seq, int i)
92   {
93     allGroups = av.alignment.findAllGroups(seq);
94     drawBoxes(seq, i, i, 0);
95     return resBoxColour;
96   }
97
98   public void drawSequence(SequenceI seq, SequenceGroup[] sg,
99                            int start, int end, int y1)
100   {
101     if (seq == null)
102     {
103       return;
104     }
105
106     allGroups = sg;
107
108     drawBoxes(seq, start, end, y1);
109
110     if (av.validCharWidth)
111     {
112       drawText(seq, start, end, y1);
113     }
114   }
115
116   public void drawBoxes(SequenceI seq, int start, int end, int y1)
117   {
118     int i = start;
119     int length = seq.getLength();
120
121     int curStart = -1;
122     int curWidth = av.charWidth;
123
124     Color tempColour = null;
125     while (i <= end)
126     {
127       resBoxColour = Color.white;
128       if (i < length)
129       {
130         if (inCurrentSequenceGroup(i))
131         {
132           if (currentSequenceGroup.getDisplayBoxes())
133           {
134             getBoxColour(currentSequenceGroup.cs, seq, i);
135           }
136         }
137         else if (av.getShowBoxes())
138         {
139           getBoxColour(av.getGlobalColourScheme(), seq, i);
140         }
141       }
142
143       if (resBoxColour != tempColour)
144       {
145         if (tempColour != null)
146         {
147           graphics.fillRect(av.charWidth * (curStart - start), y1, curWidth,
148                             av.charHeight);
149         }
150         graphics.setColor(resBoxColour);
151
152         curStart = i;
153         curWidth = av.charWidth;
154         tempColour = resBoxColour;
155
156       }
157       else
158       {
159         curWidth += av.charWidth;
160       }
161
162       i++;
163     }
164
165     graphics.fillRect(av.charWidth * (curStart - start), y1, curWidth,
166                       av.charHeight);
167   }
168
169   public void drawText(SequenceI seq, int start, int end, int y1)
170   {
171     Font boldFont = null;
172     boolean bold = false;
173     if (av.upperCasebold)
174     {
175       boldFont = new Font(av.getFont().getName(), Font.BOLD, av.charHeight);
176
177       graphics.setFont(av.getFont());
178     }
179
180     y1 += av.charHeight - av.charHeight / 5; // height/5 replaces pady
181
182     int charOffset = 0;
183
184     // Need to find the sequence position here.
185     if (end + 1 >= seq.getLength())
186     {
187       end = seq.getLength() - 1;
188     }
189
190     char s = ' ';
191
192     for (int i = start; i <= end; i++)
193     {
194       graphics.setColor(Color.black);
195
196       s = seq.getCharAt(i);
197       if (!renderGaps && jalview.util.Comparison.isGap(s))
198       {
199         continue;
200       }
201
202       if (inCurrentSequenceGroup(i))
203       {
204         if (!currentSequenceGroup.getDisplayText())
205         {
206           continue;
207         }
208
209         if (currentSequenceGroup.getColourText())
210         {
211           getBoxColour(currentSequenceGroup.cs, seq, i);
212           graphics.setColor(resBoxColour.darker());
213         }
214       }
215       else
216       {
217         if (!av.getShowText())
218         {
219           continue;
220         }
221
222         if (av.getColourText())
223         {
224           getBoxColour(av.getGlobalColourScheme(), seq, i);
225           if (av.getShowBoxes())
226           {
227             graphics.setColor(resBoxColour.darker());
228           }
229           else
230           {
231             graphics.setColor(resBoxColour);
232           }
233         }
234       }
235
236       if (av.upperCasebold)
237       {
238         fm = graphics.getFontMetrics();
239         if ('A' <= s && s <= 'Z')
240         {
241           if (!bold)
242           {
243
244             graphics.setFont(boldFont);
245           }
246           bold = true;
247         }
248         else if (bold)
249         {
250           graphics.setFont(av.font);
251           bold = false;
252         }
253
254       }
255
256       charOffset = (av.charWidth - fm.charWidth(s)) / 2;
257       graphics.drawString(String.valueOf(s),
258                           charOffset + av.charWidth * (i - start),
259                           y1);
260     }
261
262   }
263
264   boolean inCurrentSequenceGroup(int res)
265   {
266     if (allGroups == null)
267     {
268       return false;
269     }
270
271     for (int i = 0; i < allGroups.length; i++)
272     {
273       if (allGroups[i].getStartRes() <= res && allGroups[i].getEndRes() >= res)
274       {
275         currentSequenceGroup = allGroups[i];
276         return true;
277       }
278     }
279
280     return false;
281   }
282
283   public void drawHighlightedText(SequenceI seq, int start, int end, int x1,
284                                   int y1)
285   {
286     int pady = av.charHeight / 5;
287     int charOffset = 0;
288     graphics.setColor(Color.black);
289     graphics.fillRect(x1, y1, av.charWidth * (end - start + 1), av.charHeight);
290     graphics.setColor(Color.white);
291
292     char s = '~';
293     // Need to find the sequence position here.
294     if (av.validCharWidth)
295     {
296       for (int i = start; i <= end; i++)
297       {
298         if (i < seq.getLength())
299         {
300           s = seq.getCharAt(i);
301         }
302
303         charOffset = (av.charWidth - fm.charWidth(s)) / 2;
304         graphics.drawString(String.valueOf(s),
305                             charOffset + x1 + av.charWidth * (i - start),
306                             y1 + av.charHeight - pady);
307       }
308     }
309   }
310
311   public void drawCursor(SequenceI seq, int res, int x1, int y1)
312   {
313     int pady = av.charHeight / 5;
314     int charOffset = 0;
315     graphics.setColor(Color.black);
316     graphics.fillRect(x1, y1, av.charWidth, av.charHeight);
317     graphics.setColor(Color.white);
318
319     graphics.setColor(Color.white);
320
321     char s = seq.getCharAt(res);
322     if (av.validCharWidth)
323     {
324
325       charOffset = (av.charWidth - fm.charWidth(s)) / 2;
326       graphics.drawString(String.valueOf(s),
327                           charOffset + x1,
328                           (y1 + av.charHeight) - pady);
329     }
330   }
331
332 }