Set startSeq 0 if wrap alignment
[jalview.git] / src / jalview / appletgui / AlignmentPanel.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 \r
20 package jalview.appletgui;\r
21 \r
22 import java.awt.*;\r
23 import java.awt.event.*;\r
24 \r
25 import jalview.analysis.*;\r
26 import jalview.datamodel.*;\r
27 import jalview.jbappletgui.*;\r
28 import jalview.schemes.*;\r
29 \r
30 public class AlignmentPanel\r
31     extends GAlignmentPanel implements AdjustmentListener\r
32 {\r
33 \r
34   AlignViewport av;\r
35   OverviewPanel overviewPanel;\r
36   SeqPanel seqPanel;\r
37   IdPanel idPanel;\r
38   IdwidthAdjuster idwidthAdjuster;\r
39   public AlignFrame alignFrame;\r
40   ScalePanel scalePanel;\r
41   AnnotationPanel annotationPanel;\r
42   AnnotationLabels alabels;\r
43 \r
44   // this value is set false when selection area being dragged\r
45   boolean fastPaint = true;\r
46 \r
47   boolean MAC = false;\r
48 \r
49   public AlignmentPanel(AlignFrame af, final AlignViewport av)\r
50   {\r
51     if(System.getProperty("os.name").startsWith("Mac"))\r
52       MAC = true;\r
53 \r
54     alignFrame = af;\r
55     this.av = av;\r
56     seqPanel = new SeqPanel(av, this);\r
57     idPanel = new IdPanel(av, this);\r
58     scalePanel = new ScalePanel(av, this);\r
59     idwidthAdjuster = new IdwidthAdjuster(this);\r
60     annotationPanel = new AnnotationPanel(this);\r
61     alabels = new AnnotationLabels(this);\r
62 \r
63     idPanelHolder.add(idPanel, BorderLayout.CENTER);\r
64     idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);\r
65     annotationScroller.add(annotationPanel);\r
66     annotationSpaceFillerHolder.add(alabels, BorderLayout.CENTER);\r
67     scalePanelHolder.add(scalePanel, BorderLayout.CENTER);\r
68     seqPanelHolder.add(seqPanel, BorderLayout.CENTER);\r
69 \r
70     fontChanged();\r
71     setScrollValues(0, 0);\r
72 \r
73     hscroll.addAdjustmentListener(this);\r
74     vscroll.addAdjustmentListener(this);\r
75 \r
76     seqPanel.seqCanvas.addKeyListener(new MyKeyAdapter());\r
77     idPanel.idCanvas.addKeyListener(new MyKeyAdapter());\r
78 \r
79     addComponentListener(new ComponentAdapter()\r
80     {\r
81       public void componentResized(ComponentEvent evt)\r
82       {\r
83         setScrollValues(av.getStartRes(), av.getStartSeq());\r
84         repaint();\r
85       }\r
86     });\r
87 \r
88     Dimension d = calculateIdWidth();\r
89     idPanel.idCanvas.setSize(d);\r
90 \r
91     hscrollFillerPanel.setSize(d.width, annotationPanel.getSize().height);\r
92     annotationScroller.setSize(annotationPanel.getSize());\r
93 \r
94     idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);\r
95     annotationSpaceFillerHolder.setSize(d.width,\r
96                                         annotationPanel.getSize().height);\r
97     alabels.setSize(d.width, annotationPanel.getSize().height);\r
98 \r
99   }\r
100 \r
101   class MyKeyAdapter\r
102       extends KeyAdapter\r
103   {\r
104     public void keyPressed(KeyEvent evt)\r
105     {\r
106       // System.out.println(evt.getKeyCode()); log.\r
107       switch (evt.getKeyCode())\r
108       {\r
109         case 27: // escape key\r
110           av.setSelectionGroup(null);\r
111           alignFrame.alignPanel.repaint();\r
112           break;\r
113         case KeyEvent.VK_X:\r
114           if (evt.isControlDown())\r
115           {\r
116             alignFrame.cut_actionPerformed(null);\r
117           }\r
118           break;\r
119         case KeyEvent.VK_C:\r
120           if (evt.isControlDown())\r
121           {\r
122             alignFrame.copy_actionPerformed(null);\r
123           }\r
124           break;\r
125         case KeyEvent.VK_V:\r
126           if (evt.isControlDown())\r
127           {\r
128             alignFrame.paste(true);\r
129           }\r
130           break;\r
131         case KeyEvent.VK_A:\r
132           if (evt.isControlDown())\r
133           {\r
134             alignFrame.selectAllSequenceMenuItem_actionPerformed(null);\r
135           }\r
136           break;\r
137         case KeyEvent.VK_DOWN:\r
138           alignFrame.moveSelectedSequences(false);\r
139           break;\r
140         case KeyEvent.VK_UP:\r
141           alignFrame.moveSelectedSequences(true);\r
142           break;\r
143         case KeyEvent.VK_F:\r
144           if (evt.isControlDown())\r
145           {\r
146             alignFrame.findMenuItem_actionPerformed(null);\r
147           }\r
148           break;\r
149         case KeyEvent.VK_BACK_SPACE:\r
150         case KeyEvent.VK_DELETE:\r
151           alignFrame.cut_actionPerformed(null);\r
152           break;\r
153 \r
154       }\r
155     }\r
156   }\r
157 \r
158   public void fontChanged()\r
159   {\r
160     // set idCanvas bufferedImage to null\r
161     // to prevent drawing old image\r
162     FontMetrics fm = getFontMetrics(av.getFont());\r
163 \r
164     scalePanel.setSize(new Dimension(10, av.charHeight + fm.getDescent()));\r
165     idwidthAdjuster.setSize(new Dimension(10, av.charHeight + fm.getDescent()));\r
166 \r
167     annotationPanel.adjustPanelHeight();\r
168     annotationPanel.repaint();\r
169     Dimension d = calculateIdWidth();\r
170     d.setSize(d.width + 4, seqPanel.seqCanvas.getSize().height);\r
171     idPanel.idCanvas.setSize(d);\r
172     hscrollFillerPanel.setSize(d);\r
173 \r
174     alignFrame.pack();\r
175   }\r
176 \r
177   public void setIdWidth(int w, int h)\r
178   {\r
179     idPanel.idCanvas.setSize(w, h);\r
180     idPanelHolder.setSize(w, idPanelHolder.getSize().height);\r
181     alabels.setSize(w, alabels.getSize().height);\r
182     validate();\r
183   }\r
184 \r
185   Dimension calculateIdWidth()\r
186   {\r
187     Frame frame = new Frame();\r
188     frame.addNotify();\r
189     Graphics g = frame.getGraphics();\r
190     if (g == null)\r
191     {\r
192       Frame f = new Frame();\r
193       f.addNotify();\r
194       g = f.getGraphics();\r
195     }\r
196 \r
197     FontMetrics fm = g.getFontMetrics(av.font);\r
198     AlignmentI al = av.getAlignment();\r
199 \r
200     int i = 0;\r
201     int idWidth = 0;\r
202     String id;\r
203     while (i < al.getHeight() && al.getSequenceAt(i) != null)\r
204     {\r
205       SequenceI s = al.getSequenceAt(i);\r
206       if (av.getShowFullId())\r
207       {\r
208         id = s.getDisplayId();\r
209       }\r
210       else\r
211       {\r
212         id = s.getName();\r
213       }\r
214 \r
215       if (fm.stringWidth(id) > idWidth)\r
216       {\r
217         idWidth = fm.stringWidth(id);\r
218       }\r
219       i++;\r
220     }\r
221 \r
222     // Also check annotation label widths\r
223     i = 0;\r
224     if (al.getAlignmentAnnotation() != null)\r
225     {\r
226       fm = g.getFontMetrics(frame.getFont());\r
227       while (i < al.getAlignmentAnnotation().length)\r
228       {\r
229         String label = al.getAlignmentAnnotation()[i].label;\r
230         if (fm.stringWidth(label) > idWidth)\r
231         {\r
232           idWidth = fm.stringWidth(label);\r
233         }\r
234         i++;\r
235       }\r
236     }\r
237 \r
238     return new Dimension(idWidth, idPanel.idCanvas.getSize().height);\r
239   }\r
240 \r
241   public void highlightSearchResults(int[] results)\r
242   {\r
243     seqPanel.seqCanvas.highlightSearchResults(results);\r
244 \r
245     // do we need to scroll the panel?\r
246     if (results != null)\r
247     {\r
248       SequenceI seq = av.alignment.getSequenceAt(results[0]);\r
249       int start = seq.findIndex(results[1]) - 1;\r
250       int end = seq.findIndex(results[2]) - 1;\r
251       if (av.getStartRes() > start\r
252           || av.getEndRes() < end\r
253           || (av.getStartSeq() > results[0]\r
254               || av.getEndSeq() < results[0]))\r
255       {\r
256         setScrollValues(start, results[0]);\r
257       }\r
258     }\r
259 \r
260   }\r
261 \r
262   public OverviewPanel getOverviewPanel()\r
263   {\r
264     return overviewPanel;\r
265   }\r
266 \r
267   public void setOverviewPanel(OverviewPanel op)\r
268   {\r
269     overviewPanel = op;\r
270   }\r
271 \r
272   public void setAnnotationVisible(boolean b)\r
273   {\r
274     annotationSpaceFillerHolder.setVisible(b);\r
275     annotationScroller.setVisible(b);\r
276     validate();\r
277     repaint();\r
278   }\r
279 \r
280   public void setWrapAlignment(boolean wrap)\r
281   {\r
282     av.startSeq = 0;\r
283     scalePanelHolder.setVisible(!wrap);\r
284     hscroll.setVisible(!wrap);\r
285     idwidthAdjuster.setVisible(!wrap);\r
286 \r
287     av.setShowAnnotation(!wrap);\r
288     annotationScroller.setVisible(!wrap);\r
289     annotationSpaceFillerHolder.setVisible(!wrap);\r
290     idSpaceFillerPanel1.setVisible(!wrap);\r
291 \r
292     validate();\r
293     repaint();\r
294 \r
295   }\r
296 \r
297 \r
298   int hextent = 0;\r
299   int vextent = 0;\r
300 \r
301   // return value is true if the scroll is valid\r
302   public boolean scrollUp(boolean up)\r
303   {\r
304     if (up)\r
305     {\r
306       if (vscroll.getValue() < 1)\r
307       {\r
308         return false;\r
309       }\r
310       fastPaint = false;\r
311       vscroll.setValue(vscroll.getValue() - 1);\r
312     }\r
313     else\r
314     {\r
315       if (vextent + vscroll.getValue() >= av.getAlignment().getHeight())\r
316       {\r
317         return false;\r
318       }\r
319       fastPaint = false;\r
320       vscroll.setValue(vscroll.getValue() + 1);\r
321     }\r
322     fastPaint = true;\r
323     return true;\r
324   }\r
325 \r
326   public boolean scrollRight(boolean right)\r
327   {\r
328 \r
329     if (right)\r
330     {\r
331       if (hscroll.getValue() < 1)\r
332       {\r
333         return false;\r
334       }\r
335       fastPaint = false;\r
336       hscroll.setValue(hscroll.getValue() - 1);\r
337     }\r
338     else\r
339     {\r
340       if (hextent + hscroll.getValue() >= av.getAlignment().getWidth())\r
341       {\r
342         return false;\r
343       }\r
344       fastPaint = false;\r
345       hscroll.setValue(hscroll.getValue() + 1);\r
346     }\r
347     fastPaint = true;\r
348     return true;\r
349   }\r
350 \r
351   public void setScrollValues(int x, int y)\r
352   {\r
353 \r
354     av.setStartRes(x);\r
355     av.setStartSeq(y);\r
356     av.setEndRes(x + seqPanel.seqCanvas.getSize().width / av.getCharWidth() - 1);\r
357 \r
358     hextent = seqPanel.seqCanvas.getSize().width / av.charWidth;\r
359     vextent = seqPanel.seqCanvas.getSize().height / av.charHeight;\r
360 \r
361     if (hextent > av.alignment.getWidth())\r
362     {\r
363       hextent = av.alignment.getWidth();\r
364     }\r
365     if (vextent > av.alignment.getHeight())\r
366     {\r
367       vextent = av.alignment.getHeight();\r
368     }\r
369 \r
370     if (hextent + x > av.getAlignment().getWidth())\r
371     {\r
372       x = av.getAlignment().getWidth() - hextent;\r
373     }\r
374 \r
375     if (vextent + y > av.getAlignment().getHeight())\r
376     {\r
377       y = av.getAlignment().getHeight() - vextent;\r
378     }\r
379 \r
380     if (y < 0)\r
381     {\r
382       y = 0;\r
383     }\r
384 \r
385     if (x < 0)\r
386     {\r
387       x = 0;\r
388     }\r
389 \r
390     int endSeq = y + vextent;\r
391     if (endSeq > av.alignment.getHeight())\r
392     {\r
393       endSeq = av.alignment.getHeight();\r
394     }\r
395 \r
396     av.setEndSeq(endSeq);\r
397     hscroll.setValues(x, hextent, 0, av.getAlignment().getWidth());\r
398     vscroll.setValues(y, vextent, 0, av.getAlignment().getHeight());\r
399 \r
400   }\r
401 \r
402   public void adjustmentValueChanged(AdjustmentEvent evt)\r
403   {\r
404     int oldX = av.getStartRes();\r
405     int oldY = av.getStartSeq();\r
406 \r
407     if (evt.getSource() == hscroll)\r
408     {\r
409       int x = hscroll.getValue();\r
410       av.setStartRes(x);\r
411       av.setEndRes(x + seqPanel.seqCanvas.getSize().width / av.getCharWidth() -\r
412                    1);\r
413     }\r
414 \r
415     if (evt.getSource() == vscroll)\r
416     {\r
417       int offy = vscroll.getValue();\r
418       if (av.getWrapAlignment())\r
419       {\r
420         int rowSize = seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.\r
421             seqCanvas.getSize().width);\r
422         av.setStartRes(vscroll.getValue() * rowSize);\r
423         av.setEndRes( (vscroll.getValue() + 1) * rowSize);\r
424       }\r
425       else\r
426       {\r
427         av.setStartSeq(offy);\r
428         av.setEndSeq(offy +\r
429                      seqPanel.seqCanvas.getSize().height / av.getCharHeight());\r
430       }\r
431     }\r
432 \r
433     if (overviewPanel != null)\r
434     {\r
435       overviewPanel.setBoxPosition();\r
436     }\r
437 \r
438     if (av.getWrapAlignment() || !fastPaint || MAC)\r
439     {\r
440       repaint();\r
441     }\r
442     else\r
443     {\r
444       idPanel.idCanvas.fastPaint(av.getStartSeq() - oldY);\r
445       seqPanel.seqCanvas.fastPaint(av.getStartRes() - oldX,\r
446                                    av.getStartSeq() - oldY);\r
447 \r
448       scalePanel.repaint();\r
449       if (av.getShowAnnotation())\r
450       {\r
451         annotationPanel.fastPaint(av.getStartRes() - oldX);\r
452       }\r
453     }\r
454 \r
455   }\r
456 \r
457   public void update(Graphics g)\r
458   {\r
459     paint(g);\r
460   }\r
461 \r
462   public void paint(Graphics g)\r
463   {\r
464     Dimension d = idPanel.idCanvas.getSize();\r
465     idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);\r
466     annotationSpaceFillerHolder.setSize(d.width,\r
467                                         annotationPanel.getSize().height);\r
468     alabels.setSize(d.width, annotationPanel.getSize().height);\r
469 \r
470     alabels.repaint();\r
471     idPanel.idCanvas.repaint();\r
472     seqPanel.seqCanvas.repaint();\r
473     scalePanel.repaint();\r
474     annotationPanel.repaint();\r
475 \r
476     if (av.getWrapAlignment())\r
477     {\r
478       int max = av.alignment.getWidth() /\r
479           seqPanel.seqCanvas.\r
480           getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);\r
481       vscroll.setMaximum(max);\r
482       vscroll.setUnitIncrement(1);\r
483       vscroll.setVisibleAmount(1);\r
484     }\r
485     else\r
486     {\r
487       setScrollValues(av.getStartRes(), av.getStartSeq());\r
488     }\r
489 \r
490   }\r
491 }\r