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