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