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