validCharWidth moved to viewport
[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 prepare(Graphics g, boolean renderGaps)\r
61     {\r
62         graphics = g;\r
63         fm = g.getFontMetrics();\r
64         monospacedFont = fm.getStringBounds("M",g).getWidth()==fm.getStringBounds("|",g).getWidth();\r
65         this.renderGaps = renderGaps;\r
66     }\r
67 \r
68 \r
69     public Color getResidueBoxColour(SequenceI seq, int i)\r
70     {\r
71       allGroups = av.alignment.findAllGroups(seq);\r
72 \r
73       if (inCurrentSequenceGroup(i))\r
74       {\r
75         if (currentSequenceGroup.getDisplayBoxes())\r
76         {\r
77           getBoxColour(currentSequenceGroup.cs, seq, i);\r
78         }\r
79       }\r
80       else if (av.getShowBoxes())\r
81       {\r
82           getBoxColour(av.globalColourScheme, seq, i);\r
83       }\r
84 \r
85       return resBoxColour;\r
86     }\r
87 \r
88 \r
89     /**\r
90      * DOCUMENT ME!\r
91      *\r
92      * @param cs DOCUMENT ME!\r
93      * @param seq DOCUMENT ME!\r
94      * @param i DOCUMENT ME!\r
95      */\r
96     void getBoxColour(ColourSchemeI cs, SequenceI seq, int i)\r
97     {\r
98         if (cs != null)\r
99         {\r
100             resBoxColour = cs.findColour(seq.getSequence(i, i + 1), i);\r
101         }\r
102         else if(forOverview && !jalview.util.Comparison.isGap(seq.getCharAt(i)))\r
103         {\r
104             resBoxColour = Color.lightGray;\r
105         }\r
106         else\r
107         {\r
108           resBoxColour = Color.white;\r
109         }\r
110     }\r
111 \r
112     /**\r
113      * DOCUMENT ME!\r
114      *\r
115      * @param g DOCUMENT ME!\r
116      * @param seq DOCUMENT ME!\r
117      * @param sg DOCUMENT ME!\r
118      * @param start DOCUMENT ME!\r
119      * @param end DOCUMENT ME!\r
120      * @param x1 DOCUMENT ME!\r
121      * @param y1 DOCUMENT ME!\r
122      * @param width DOCUMENT ME!\r
123      * @param height DOCUMENT ME!\r
124      */\r
125     public void drawSequence(SequenceI seq, SequenceGroup[] sg,\r
126         int start, int end, int y1)\r
127     {\r
128         allGroups = sg;\r
129 \r
130         drawBoxes(seq, start, end, y1);\r
131 \r
132         if (av.validCharWidth)\r
133           drawText(seq, start, end, y1);\r
134     }\r
135 \r
136     /**\r
137      * DOCUMENT ME!\r
138      *\r
139      * @param seq DOCUMENT ME!\r
140      * @param start DOCUMENT ME!\r
141      * @param end DOCUMENT ME!\r
142      * @param x1 DOCUMENT ME!\r
143      * @param y1 DOCUMENT ME!\r
144      * @param width DOCUMENT ME!\r
145      * @param height DOCUMENT ME!\r
146      */\r
147     public synchronized void drawBoxes(SequenceI seq, int start, int end, int y1)\r
148     {\r
149       int i = start;\r
150       int length = seq.getLength();\r
151 \r
152       int curStart = -1;\r
153       int curWidth = av.charWidth;\r
154 \r
155       Color tempColour = null;\r
156 \r
157       while (i <= end)\r
158       {\r
159         resBoxColour = Color.white;\r
160 \r
161         if (i < length)\r
162         {\r
163           if (inCurrentSequenceGroup(i))\r
164           {\r
165             if (currentSequenceGroup.getDisplayBoxes())\r
166             {\r
167               getBoxColour(currentSequenceGroup.cs, seq, i);\r
168             }\r
169           }\r
170           else if (av.getShowBoxes())\r
171           {\r
172             getBoxColour(av.globalColourScheme, seq, i);\r
173           }\r
174 \r
175         }\r
176 \r
177           if (resBoxColour != tempColour)\r
178           {\r
179               if (tempColour != null)\r
180               {\r
181                   graphics.fillRect( av.charWidth * (curStart - start), y1,\r
182                       curWidth, av.charHeight);\r
183               }\r
184 \r
185               graphics.setColor(resBoxColour);\r
186 \r
187               curStart = i;\r
188               curWidth = av.charWidth;\r
189               tempColour = resBoxColour;\r
190           }\r
191           else\r
192           {\r
193               curWidth += av.charWidth;\r
194           }\r
195 \r
196           i++;\r
197       }\r
198 \r
199       graphics.fillRect( av.charWidth * (curStart - start), y1, curWidth,\r
200           av.charHeight);\r
201 \r
202     }\r
203 \r
204     /**\r
205      * DOCUMENT ME!\r
206      *\r
207      * @param seq DOCUMENT ME!\r
208      * @param start DOCUMENT ME!\r
209      * @param end DOCUMENT ME!\r
210      * @param x1 DOCUMENT ME!\r
211      * @param y1 DOCUMENT ME!\r
212      * @param width DOCUMENT ME!\r
213      * @param height DOCUMENT ME!\r
214      */\r
215     public void drawText(SequenceI seq, int start, int end, int y1)\r
216     {\r
217       y1 += av.charHeight - av.charHeight / 5; // height/5 replaces pady\r
218       int charOffset = 0;\r
219       char s;\r
220 \r
221         if(end+1>=seq.getLength())\r
222           end = seq.getLength()-1;\r
223         graphics.setColor(Color.black);\r
224 \r
225 \r
226         if(monospacedFont && av.showText && allGroups.length==0 && !av.getColourText())\r
227         {\r
228           if(av.renderGaps)\r
229           graphics.drawString(seq.getSequence(start, end + 1), 0, y1);\r
230          else\r
231          {\r
232            char gap = av.getGapCharacter();\r
233            graphics.drawString( seq.getSequence(start, end+1).replace(gap, ' '), 0, y1);\r
234          }\r
235         }\r
236         else\r
237         {\r
238           for (int i = start; i <= end; i++)\r
239           {\r
240             graphics.setColor(Color.black);\r
241             s = seq.getCharAt(i);\r
242             if (!renderGaps && jalview.util.Comparison.isGap(s))\r
243             {\r
244               continue;\r
245             }\r
246 \r
247             if (inCurrentSequenceGroup(i))\r
248             {\r
249               if (!currentSequenceGroup.getDisplayText())\r
250               {\r
251                 continue;\r
252               }\r
253 \r
254               if (currentSequenceGroup.getColourText())\r
255               {\r
256                 getBoxColour(currentSequenceGroup.cs, seq, i);\r
257                 graphics.setColor(resBoxColour.darker());\r
258               }\r
259             }\r
260             else\r
261             {\r
262               if (!av.getShowText())\r
263               {\r
264                 continue;\r
265               }\r
266 \r
267               if (av.getColourText())\r
268               {\r
269                 getBoxColour(av.globalColourScheme, seq, i);\r
270 \r
271                 if (av.getShowBoxes())\r
272                 {\r
273                   graphics.setColor(resBoxColour.darker());\r
274                 }\r
275                 else\r
276                 {\r
277                   graphics.setColor(resBoxColour);\r
278                 }\r
279               }\r
280             }\r
281 \r
282             charOffset = (av.charWidth - fm.charWidth(s)) / 2;\r
283 \r
284           //  System.out.print(s);\r
285             graphics.drawString(String.valueOf(s),\r
286                                 charOffset + av.charWidth * (i - start),\r
287                                 y1);\r
288 \r
289           }\r
290         //  System.out.println("\n");\r
291         }\r
292     }\r
293 \r
294     /**\r
295      * DOCUMENT ME!\r
296      *\r
297      * @param res DOCUMENT ME!\r
298      *\r
299      * @return DOCUMENT ME!\r
300      */\r
301     boolean inCurrentSequenceGroup(int res)\r
302     {\r
303         if (allGroups == null)\r
304         {\r
305             return false;\r
306         }\r
307 \r
308         for (int i = 0; i < allGroups.length; i++)\r
309         {\r
310             if ((allGroups[i].getStartRes() <= res) &&\r
311                     (allGroups[i].getEndRes() >= res))\r
312             {\r
313                 currentSequenceGroup = allGroups[i];\r
314 \r
315                 return true;\r
316             }\r
317         }\r
318 \r
319         return false;\r
320     }\r
321 \r
322     /**\r
323      * DOCUMENT ME!\r
324      *\r
325      * @param seq DOCUMENT ME!\r
326      * @param start DOCUMENT ME!\r
327      * @param end DOCUMENT ME!\r
328      * @param x1 DOCUMENT ME!\r
329      * @param y1 DOCUMENT ME!\r
330      * @param width DOCUMENT ME!\r
331      * @param height DOCUMENT ME!\r
332      */\r
333     public void drawHighlightedText(SequenceI seq, int start, int end, int x1, int y1)\r
334     {\r
335         int pady = av.charHeight / 5;\r
336         int charOffset = 0;\r
337         graphics.setColor(Color.BLACK);\r
338         graphics.fillRect(x1, y1, av.charWidth * (end - start + 1), av.charHeight);\r
339         graphics.setColor(Color.white);\r
340 \r
341         char s = '~';\r
342 \r
343         // Need to find the sequence position here.\r
344         if(av.validCharWidth)\r
345         {\r
346           for (int i = start; i <= end; i++)\r
347           {\r
348             if (i < seq.getLength())\r
349             {\r
350               s = seq.getSequence().charAt(i);\r
351             }\r
352 \r
353             charOffset = (av.charWidth - fm.charWidth(s)) / 2;\r
354             graphics.drawString(String.valueOf(s),\r
355                                 charOffset + x1 + (av.charWidth * (i - start)),\r
356                                 (y1 + av.charHeight) - pady);\r
357           }\r
358         }\r
359     }\r
360 \r
361     public void drawCursor(SequenceI seq, int res, int x1, int y1)\r
362     {\r
363       int pady = av.charHeight / 5;\r
364       int charOffset = 0;\r
365       graphics.setColor(Color.black);\r
366       graphics.fillRect(x1, y1, av.charWidth, av.charHeight);\r
367 \r
368       if(av.validCharWidth)\r
369       {\r
370         graphics.setColor(Color.white);\r
371 \r
372         char s = seq.getCharAt(res);\r
373 \r
374         charOffset = (av.charWidth - fm.charWidth(s)) / 2;\r
375         graphics.drawString(String.valueOf(s),\r
376                             charOffset + x1,\r
377                             (y1 + av.charHeight) - pady);\r
378       }\r
379 \r
380     }\r
381 }\r