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