b2a5ede4432814a78eb35cc665fddb58ab85c9be
[jalview.git] / src / jalview / gui / IdCanvas.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2006 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 java.awt.*;\r
24 import java.awt.image.*;\r
25 \r
26 import javax.swing.*;\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 IdCanvas extends JPanel\r
36 {\r
37     protected AlignViewport av;\r
38     protected boolean showScores = true;\r
39     protected int maxIdLength = -1;\r
40     protected String maxIdStr = null;\r
41     BufferedImage image;\r
42     Graphics2D gg;\r
43     int imgHeight = 0;\r
44     boolean fastPaint = false;\r
45     java.util.Vector searchResults;\r
46     FontMetrics fm;\r
47     AnnotationLabels labels = null;\r
48     AnnotationPanel ap;\r
49 \r
50     /**\r
51      * Creates a new IdCanvas object.\r
52      *\r
53      * @param av DOCUMENT ME!\r
54      */\r
55     public IdCanvas(AlignViewport av)\r
56     {\r
57         setLayout(new BorderLayout());\r
58         this.av = av;\r
59         PaintRefresher.Register(this, av.getSequenceSetId());\r
60     }\r
61 \r
62     /**\r
63      * DOCUMENT ME!\r
64      *\r
65      * @param gg DOCUMENT ME!\r
66      * @param s DOCUMENT ME!\r
67      * @param i DOCUMENT ME!\r
68      * @param starty DOCUMENT ME!\r
69      * @param ypos DOCUMENT ME!\r
70      */\r
71     public void drawIdString(Graphics2D gg, SequenceI s, int i, int starty, int ypos)\r
72     {\r
73         int xPos = 0;\r
74         int panelWidth = getWidth();\r
75         int charHeight = av.charHeight;\r
76 \r
77         if ((searchResults != null) && searchResults.contains(s))\r
78         {\r
79             gg.setColor(Color.black);\r
80             gg.fillRect(0, ((i - starty) * charHeight) + ypos, getWidth(),\r
81                 charHeight);\r
82             gg.setColor(Color.white);\r
83         }\r
84         else if ((av.getSelectionGroup() != null) &&\r
85                 av.getSelectionGroup().getSequences(false).contains(s))\r
86         {\r
87             gg.setColor(Color.lightGray);\r
88             gg.fillRect(0, ((i - starty) * charHeight) + ypos, getWidth(),\r
89                 charHeight);\r
90             gg.setColor(Color.white);\r
91         }\r
92         else\r
93         {\r
94             gg.setColor(av.getSequenceColour(s));\r
95             gg.fillRect(0, ((i - starty) * charHeight) + ypos, getWidth(),\r
96                 charHeight);\r
97             gg.setColor(Color.black);\r
98         }\r
99 \r
100         if (av.rightAlignIds)\r
101         {\r
102           xPos = panelWidth - fm.stringWidth(\r
103               s.getDisplayId(av.getShowJVSuffix())\r
104               ) - 4;\r
105         }\r
106 \r
107         gg.drawString( s.getDisplayId(av.getShowJVSuffix()),\r
108                     xPos, (((i - starty + 1) * charHeight) + ypos) - (charHeight / 5));\r
109 \r
110         if (av.hasHiddenRows && av.showHiddenMarkers)\r
111           drawMarker(i, starty, ypos);\r
112 \r
113 \r
114     }\r
115 \r
116     /**\r
117      * DOCUMENT ME!\r
118      *\r
119      * @param vertical DOCUMENT ME!\r
120      */\r
121     public void fastPaint(int vertical)\r
122     {\r
123         if (gg == null)\r
124         {\r
125             repaint();\r
126 \r
127             return;\r
128         }\r
129 \r
130         gg.copyArea(0, 0, getWidth(), imgHeight, 0, -vertical * av.charHeight);\r
131 \r
132         int ss = av.startSeq;\r
133         int es = av.endSeq;\r
134         int transY = 0;\r
135 \r
136         if (vertical > 0) // scroll down\r
137         {\r
138             ss = es - vertical;\r
139 \r
140             if (ss < av.startSeq)\r
141             { // ie scrolling too fast, more than a page at a time\r
142                 ss = av.startSeq;\r
143             }\r
144             else\r
145             {\r
146                 transY = imgHeight - (vertical * av.charHeight);\r
147             }\r
148         }\r
149         else if (vertical < 0)\r
150         {\r
151             es = ss - vertical;\r
152 \r
153             if (es > av.endSeq)\r
154             {\r
155                 es = av.endSeq;\r
156             }\r
157         }\r
158 \r
159         gg.translate(0, transY);\r
160 \r
161         drawIds(ss, es);\r
162 \r
163         gg.translate(0, -transY);\r
164 \r
165         fastPaint = true;\r
166         repaint();\r
167     }\r
168 \r
169     /**\r
170      * DOCUMENT ME!\r
171      *\r
172      * @param g DOCUMENT ME!\r
173      */\r
174     public void paintComponent(Graphics g)\r
175     {\r
176         g.setColor(Color.white);\r
177         g.fillRect(0, 0, getWidth(), getHeight());\r
178 \r
179         if (fastPaint)\r
180         {\r
181             fastPaint = false;\r
182             g.drawImage(image, 0, 0, this);\r
183 \r
184             return;\r
185         }\r
186 \r
187         int oldHeight = imgHeight;\r
188 \r
189         imgHeight = getHeight();\r
190         imgHeight -= (imgHeight % av.charHeight);\r
191 \r
192         if (imgHeight < 1)\r
193         {\r
194             return;\r
195         }\r
196 \r
197         if(oldHeight!=imgHeight || image.getWidth(this)!=getWidth())\r
198         {\r
199           image = new BufferedImage(getWidth(), imgHeight,\r
200                                     BufferedImage.TYPE_INT_RGB);\r
201         }\r
202 \r
203         gg = (Graphics2D) image.getGraphics();\r
204 \r
205         //Fill in the background\r
206         gg.setColor(Color.white);\r
207         gg.fillRect(0, 0, getWidth(), imgHeight);\r
208 \r
209         drawIds(av.getStartSeq(), av.endSeq);\r
210 \r
211         g.drawImage(image, 0, 0, this);\r
212     }\r
213 \r
214     /**\r
215      * DOCUMENT ME!\r
216      *\r
217      * @param starty DOCUMENT ME!\r
218      * @param endy DOCUMENT ME!\r
219      */\r
220     void drawIds(int starty, int endy)\r
221     {\r
222       Font italic = new Font(av.getFont().getName(), Font.ITALIC,\r
223                              av.getFont().getSize());\r
224 \r
225       gg.setFont(italic);\r
226       fm = gg.getFontMetrics();\r
227 \r
228       if (av.antiAlias)\r
229         gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,\r
230                             RenderingHints.VALUE_ANTIALIAS_ON);\r
231 \r
232         Color currentColor = Color.white;\r
233         Color currentTextColor = Color.black;\r
234 \r
235         if (av.getWrapAlignment())\r
236         {\r
237           int maxwidth = av.alignment.getWidth();\r
238           int alheight = av.alignment.getHeight();\r
239 \r
240           if (av.hasHiddenColumns)\r
241             maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;\r
242 \r
243           int annotationHeight = 0;\r
244 \r
245 \r
246           if(av.showAnnotation)\r
247           {\r
248             if (ap == null)\r
249               ap = new AnnotationPanel(av);\r
250 \r
251             annotationHeight = ap.adjustPanelHeight();\r
252             if (labels == null)\r
253               labels = new AnnotationLabels(av);\r
254           }\r
255 \r
256           int hgap = av.charHeight;\r
257           if (av.scaleAboveWrapped)\r
258             hgap += av.charHeight;\r
259 \r
260           int cHeight = alheight * av.charHeight\r
261               + hgap\r
262               + annotationHeight;\r
263 \r
264           int rowSize = av.getEndRes() - av.getStartRes();\r
265 \r
266 \r
267             // Draw the rest of the panels\r
268             for (int ypos = hgap, row = av.startRes;\r
269                     (ypos <= getHeight()) && (row < maxwidth);\r
270                     ypos += cHeight, row += rowSize)\r
271             {\r
272               for (int i = starty; i < alheight; i++)\r
273               {\r
274                 if (av.hasHiddenRows)\r
275                 {\r
276                   setHiddenFont(i);\r
277                 }\r
278                 else\r
279                   gg.setFont(italic);\r
280 \r
281                 SequenceI s = av.alignment.getSequenceAt(i);\r
282                 drawIdString(gg, s, i, 0, ypos);\r
283               }\r
284 \r
285                 if(labels!=null)\r
286                 {\r
287                   gg.translate(0, ypos+(alheight * av.charHeight));\r
288                   labels.drawComponent(gg, getWidth());\r
289                   gg.translate(0, -ypos-(alheight * av.charHeight));\r
290                 }\r
291 \r
292 \r
293             }\r
294         }\r
295         else\r
296         {\r
297           //Now draw the id strings\r
298           int panelWidth = getWidth();\r
299           int xPos = 0;\r
300 \r
301             SequenceI sequence;\r
302             //Now draw the id strings\r
303             for (int i = starty; i < endy; i++)\r
304             {\r
305               sequence = av.alignment.getSequenceAt(i);\r
306 \r
307               if(sequence==null)\r
308                 continue;\r
309 \r
310               if (av.hasHiddenRows)\r
311               {\r
312                 setHiddenFont(i);\r
313               }\r
314 \r
315                 // Selected sequence colours\r
316                 if ( (searchResults != null) &&\r
317                     searchResults.contains(sequence))\r
318                 {\r
319                   currentColor = Color.black;\r
320                   currentTextColor = Color.white;\r
321                 }\r
322                 else if ( (av.getSelectionGroup() != null) &&\r
323                          av.getSelectionGroup().getSequences(false).contains(\r
324                              sequence))\r
325                 {\r
326                   currentColor = Color.lightGray;\r
327                   currentTextColor = Color.black;\r
328                 }\r
329                 else\r
330                 {\r
331                   currentColor = av.getSequenceColour(sequence);\r
332                   currentTextColor = Color.black;\r
333                 }\r
334 \r
335                 gg.setColor(currentColor);\r
336 \r
337                 gg.fillRect(0, (i - starty) * av.charHeight, getWidth(),\r
338                             av.charHeight);\r
339 \r
340                 gg.setColor(currentTextColor);\r
341 \r
342                 String string = sequence.getDisplayId( av.getShowJVSuffix());\r
343 \r
344 \r
345                 if(av.rightAlignIds)\r
346                 {\r
347                   xPos = panelWidth - fm.stringWidth(string) - 4;\r
348                 }\r
349 \r
350                 gg.drawString(string, xPos,\r
351                     (((i - starty) * av.charHeight) + av.charHeight) -\r
352                     (av.charHeight / 5));\r
353 \r
354                if(av.hasHiddenRows && av.showHiddenMarkers)\r
355                  drawMarker(i, starty, 0);\r
356 \r
357             }\r
358 \r
359         }\r
360     }\r
361 \r
362     void drawMarker(int i, int starty, int yoffset)\r
363     {\r
364 \r
365       SequenceI [] hseqs = av.alignment.getHiddenSequences().hiddenSequences;\r
366       //Use this method here instead of calling hiddenSeq adjust\r
367       //3 times.\r
368       int hSize = hseqs.length;\r
369 \r
370       int hiddenIndex = i;\r
371       int lastIndex = i - 1;\r
372       int nextIndex = i + 1;\r
373 \r
374       for(int j=0; j<hSize; j++)\r
375       {\r
376         if (hseqs[j] != null)\r
377         {\r
378           if(j-1<hiddenIndex)\r
379             hiddenIndex++;\r
380           if(j-1<lastIndex)\r
381             lastIndex++;\r
382           if(j-1<nextIndex)\r
383             nextIndex++;\r
384         }\r
385       }\r
386 \r
387       boolean below = (hiddenIndex > lastIndex + 1);\r
388       boolean above = (nextIndex > hiddenIndex+1);\r
389 \r
390 \r
391         gg.setColor(Color.blue);\r
392         if(below)\r
393         {\r
394           gg.fillPolygon(new int[]\r
395                          {getWidth()- av.charHeight,\r
396                          getWidth()- av.charHeight,\r
397                          getWidth()},\r
398                          new int[]\r
399                          {\r
400                          (i - starty) * av.charHeight +yoffset,\r
401                          (i - starty) * av.charHeight +yoffset+ av.charHeight / 4,\r
402                          (i - starty) * av.charHeight+yoffset\r
403           }, 3);\r
404         }\r
405         if(above)\r
406         {\r
407           gg.fillPolygon(new int[]\r
408                         {getWidth()- av.charHeight,\r
409                         getWidth()- av.charHeight,\r
410                         getWidth() },\r
411                         new int[]\r
412                         {\r
413                         (i - starty+1) * av.charHeight +yoffset,\r
414                         (i - starty+1) * av.charHeight +yoffset- av.charHeight / 4,\r
415                         (i - starty+1) * av.charHeight +yoffset\r
416          }, 3);\r
417 \r
418         }\r
419     }\r
420 \r
421     void setHiddenFont(int i)\r
422     {\r
423       Font italic = new Font(av.getFont().getName(), Font.ITALIC,\r
424                              av.getFont().getSize());\r
425       Font bold = new Font(av.getFont().getName(), Font.BOLD,\r
426                            av.getFont().getSize());\r
427 \r
428 \r
429       if (av.alignment.getSequenceAt(i)!=null\r
430           && av.alignment.getSequenceAt(i).getHiddenSequences() != null)\r
431         gg.setFont(bold);\r
432       else\r
433         gg.setFont(italic);\r
434     }\r
435 \r
436     /**\r
437      * DOCUMENT ME!\r
438      *\r
439      * @param found DOCUMENT ME!\r
440      */\r
441     public void setHighlighted(java.util.Vector found)\r
442     {\r
443         searchResults = found;\r
444         repaint();\r
445     }\r
446 }\r