Hidden representatives moved from sequence to viewport
[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(null).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                 SequenceI s = av.alignment.getSequenceAt(i);\r
275                 if (av.hasHiddenRows)\r
276                 {\r
277                   setHiddenFont(s);\r
278                 }\r
279                 else\r
280                   gg.setFont(italic);\r
281 \r
282                 drawIdString(gg, s, i, 0, ypos);\r
283               }\r
284 \r
285                 if(labels!=null && av.showAnnotation)\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         else\r
294         {\r
295           //No need to hang on to labels if we're not wrapped\r
296           labels = null;\r
297 \r
298           //Now draw the id strings\r
299           int panelWidth = getWidth();\r
300           int xPos = 0;\r
301 \r
302             SequenceI sequence;\r
303             //Now draw the id strings\r
304             for (int i = starty; i < endy; i++)\r
305             {\r
306               sequence = av.alignment.getSequenceAt(i);\r
307 \r
308               if(sequence==null)\r
309                 continue;\r
310 \r
311               if (av.hasHiddenRows)\r
312               {\r
313                 setHiddenFont(sequence);\r
314               }\r
315 \r
316                 // Selected sequence colours\r
317                 if ( (searchResults != null) &&\r
318                     searchResults.contains(sequence))\r
319                 {\r
320                   currentColor = Color.black;\r
321                   currentTextColor = Color.white;\r
322                 }\r
323                 else if ( (av.getSelectionGroup() != null) &&\r
324                          av.getSelectionGroup().getSequences(null).contains(\r
325                              sequence))\r
326                 {\r
327                   currentColor = Color.lightGray;\r
328                   currentTextColor = Color.black;\r
329                 }\r
330                 else\r
331                 {\r
332                   currentColor = av.getSequenceColour(sequence);\r
333                   currentTextColor = Color.black;\r
334                 }\r
335 \r
336                 gg.setColor(currentColor);\r
337 \r
338                 gg.fillRect(0, (i - starty) * av.charHeight, getWidth(),\r
339                             av.charHeight);\r
340 \r
341                 gg.setColor(currentTextColor);\r
342 \r
343                 String string = sequence.getDisplayId( av.getShowJVSuffix());\r
344 \r
345 \r
346                 if(av.rightAlignIds)\r
347                 {\r
348                   xPos = panelWidth - fm.stringWidth(string) - 4;\r
349                 }\r
350 \r
351                 gg.drawString(string, xPos,\r
352                     (((i - starty) * av.charHeight) + av.charHeight) -\r
353                     (av.charHeight / 5));\r
354 \r
355                if(av.hasHiddenRows && av.showHiddenMarkers)\r
356                  drawMarker(i, starty, 0);\r
357 \r
358             }\r
359 \r
360         }\r
361     }\r
362 \r
363     void drawMarker(int i, int starty, int yoffset)\r
364     {\r
365 \r
366       SequenceI [] hseqs = av.alignment.getHiddenSequences().hiddenSequences;\r
367       //Use this method here instead of calling hiddenSeq adjust\r
368       //3 times.\r
369       int hSize = hseqs.length;\r
370 \r
371       int hiddenIndex = i;\r
372       int lastIndex = i - 1;\r
373       int nextIndex = i + 1;\r
374 \r
375       for(int j=0; j<hSize; j++)\r
376       {\r
377         if (hseqs[j] != null)\r
378         {\r
379           if(j-1<hiddenIndex)\r
380             hiddenIndex++;\r
381           if(j-1<lastIndex)\r
382             lastIndex++;\r
383           if(j-1<nextIndex)\r
384             nextIndex++;\r
385         }\r
386       }\r
387 \r
388       boolean below = (hiddenIndex > lastIndex + 1);\r
389       boolean above = (nextIndex > hiddenIndex+1);\r
390 \r
391 \r
392         gg.setColor(Color.blue);\r
393         if(below)\r
394         {\r
395           gg.fillPolygon(new int[]\r
396                          {getWidth()- av.charHeight,\r
397                          getWidth()- av.charHeight,\r
398                          getWidth()},\r
399                          new int[]\r
400                          {\r
401                          (i - starty) * av.charHeight +yoffset,\r
402                          (i - starty) * av.charHeight +yoffset+ av.charHeight / 4,\r
403                          (i - starty) * av.charHeight+yoffset\r
404           }, 3);\r
405         }\r
406         if(above)\r
407         {\r
408           gg.fillPolygon(new int[]\r
409                         {getWidth()- av.charHeight,\r
410                         getWidth()- av.charHeight,\r
411                         getWidth() },\r
412                         new int[]\r
413                         {\r
414                         (i - starty+1) * av.charHeight +yoffset,\r
415                         (i - starty+1) * av.charHeight +yoffset- av.charHeight / 4,\r
416                         (i - starty+1) * av.charHeight +yoffset\r
417          }, 3);\r
418 \r
419         }\r
420     }\r
421 \r
422     void setHiddenFont(SequenceI seq)\r
423     {\r
424       Font italic = new Font(av.getFont().getName(), Font.ITALIC,\r
425                              av.getFont().getSize());\r
426       Font bold = new Font(av.getFont().getName(), Font.BOLD,\r
427                            av.getFont().getSize());\r
428 \r
429 \r
430       if (av.hiddenRepSequences!=null &&\r
431           av.hiddenRepSequences.containsKey(seq))\r
432         gg.setFont(bold);\r
433       else\r
434         gg.setFont(italic);\r
435     }\r
436 \r
437     /**\r
438      * DOCUMENT ME!\r
439      *\r
440      * @param found DOCUMENT ME!\r
441      */\r
442     public void setHighlighted(java.util.Vector found)\r
443     {\r
444         searchResults = found;\r
445         repaint();\r
446     }\r
447 }\r