Should call deselectAll when escape pressed
[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.datamodel.*;\r
26 \r
27 public class AlignmentPanel extends Panel implements AdjustmentListener\r
28 {\r
29 \r
30   AlignViewport av;\r
31   OverviewPanel overviewPanel;\r
32   SeqPanel seqPanel;\r
33   IdPanel idPanel;\r
34   IdwidthAdjuster idwidthAdjuster;\r
35   public AlignFrame alignFrame;\r
36   ScalePanel scalePanel;\r
37   AnnotationPanel annotationPanel;\r
38   AnnotationLabels alabels;\r
39 \r
40   // this value is set false when selection area being dragged\r
41   boolean fastPaint = true;\r
42 \r
43   boolean MAC = false;\r
44 \r
45   public AlignmentPanel(AlignFrame af, final AlignViewport av)\r
46   {\r
47     try\r
48     {\r
49       jbInit();\r
50     }\r
51     catch (Exception e)\r
52     {\r
53       e.printStackTrace();\r
54     }\r
55 \r
56     if(System.getProperty("os.name").startsWith("Mac"))\r
57       MAC = true;\r
58 \r
59     alignFrame = af;\r
60     this.av = av;\r
61     seqPanel = new SeqPanel(av, this);\r
62     idPanel = new IdPanel(av, this);\r
63     scalePanel = new ScalePanel(av, this);\r
64     idwidthAdjuster = new IdwidthAdjuster(this);\r
65     annotationPanel = new AnnotationPanel(this);\r
66     alabels = new AnnotationLabels(this);\r
67 \r
68     idPanelHolder.add(idPanel, BorderLayout.CENTER);\r
69     idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);\r
70     annotationScroller.add(annotationPanel);\r
71     annotationSpaceFillerHolder.add(alabels, BorderLayout.CENTER);\r
72     scalePanelHolder.add(scalePanel, BorderLayout.CENTER);\r
73     seqPanelHolder.add(seqPanel, BorderLayout.CENTER);\r
74 \r
75     fontChanged();\r
76     setScrollValues(0, 0);\r
77 \r
78     hscroll.addAdjustmentListener(this);\r
79     vscroll.addAdjustmentListener(this);\r
80 \r
81     seqPanel.seqCanvas.addKeyListener(new MyKeyAdapter());\r
82     idPanel.idCanvas.addKeyListener(new MyKeyAdapter());\r
83 \r
84     addComponentListener(new ComponentAdapter()\r
85     {\r
86       public void componentResized(ComponentEvent evt)\r
87       {\r
88         setScrollValues(av.getStartRes(), av.getStartSeq());\r
89         repaint();\r
90       }\r
91     });\r
92 \r
93     Dimension d = calculateIdWidth();\r
94     idPanel.idCanvas.setSize(d);\r
95 \r
96     hscrollFillerPanel.setSize(d.width, annotationPanel.getSize().height);\r
97     annotationScroller.setSize(annotationPanel.getSize());\r
98 \r
99     idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);\r
100     annotationSpaceFillerHolder.setSize(d.width,\r
101                                         annotationPanel.getSize().height);\r
102     alabels.setSize(d.width, annotationPanel.getSize().height);\r
103 \r
104   }\r
105 \r
106   class MyKeyAdapter\r
107       extends KeyAdapter\r
108   {\r
109     public void keyPressed(KeyEvent evt)\r
110     {\r
111       // System.out.println(evt.getKeyCode()); log.\r
112       switch (evt.getKeyCode())\r
113       {\r
114         case 27: // escape key\r
115           alignFrame.deselectAllSequenceMenuItem_actionPerformed(null);\r
116           break;\r
117         case KeyEvent.VK_X:\r
118           if (evt.isControlDown())\r
119           {\r
120             alignFrame.cut_actionPerformed(null);\r
121           }\r
122           break;\r
123         case KeyEvent.VK_C:\r
124           if (evt.isControlDown())\r
125           {\r
126             alignFrame.copy_actionPerformed(null);\r
127           }\r
128           break;\r
129         case KeyEvent.VK_V:\r
130           if (evt.isControlDown())\r
131           {\r
132             alignFrame.paste(true);\r
133           }\r
134           break;\r
135         case KeyEvent.VK_A:\r
136           if (evt.isControlDown())\r
137           {\r
138             alignFrame.selectAllSequenceMenuItem_actionPerformed(null);\r
139           }\r
140           break;\r
141         case KeyEvent.VK_DOWN:\r
142           alignFrame.moveSelectedSequences(false);\r
143           break;\r
144         case KeyEvent.VK_UP:\r
145           alignFrame.moveSelectedSequences(true);\r
146           break;\r
147         case KeyEvent.VK_F:\r
148           if (evt.isControlDown())\r
149           {\r
150             alignFrame.findMenuItem_actionPerformed(null);\r
151           }\r
152           break;\r
153         case KeyEvent.VK_BACK_SPACE:\r
154         case KeyEvent.VK_DELETE:\r
155           alignFrame.cut_actionPerformed(null);\r
156           break;\r
157 \r
158       }\r
159     }\r
160   }\r
161 \r
162   public void fontChanged()\r
163   {\r
164     // set idCanvas bufferedImage to null\r
165     // to prevent drawing old image\r
166     FontMetrics fm = getFontMetrics(av.getFont());\r
167 \r
168     scalePanel.setSize(new Dimension(10, av.charHeight + fm.getDescent()));\r
169     idwidthAdjuster.setSize(new Dimension(10, av.charHeight + fm.getDescent()));\r
170 \r
171     annotationPanel.adjustPanelHeight();\r
172     annotationPanel.repaint();\r
173     Dimension d = calculateIdWidth();\r
174     d.setSize(d.width + 4, seqPanel.seqCanvas.getSize().height);\r
175     idPanel.idCanvas.setSize(d);\r
176     hscrollFillerPanel.setSize(d);\r
177 \r
178     alignFrame.pack();\r
179 \r
180     if(overviewPanel!=null)\r
181           overviewPanel.updateOverviewImage();\r
182   }\r
183 \r
184   public void setIdWidth(int w, int h)\r
185   {\r
186     idPanel.idCanvas.setSize(w, h);\r
187     idPanelHolder.setSize(w, idPanelHolder.getSize().height);\r
188     alabels.setSize(w, alabels.getSize().height);\r
189     validate();\r
190   }\r
191 \r
192   Dimension calculateIdWidth()\r
193   {\r
194     Frame frame = new Frame();\r
195     frame.addNotify();\r
196     Graphics g = frame.getGraphics();\r
197     if (g == null)\r
198     {\r
199       Frame f = new Frame();\r
200       f.addNotify();\r
201       g = f.getGraphics();\r
202     }\r
203 \r
204     FontMetrics fm = g.getFontMetrics(av.font);\r
205     AlignmentI al = av.getAlignment();\r
206 \r
207     int i = 0;\r
208     int idWidth = 0;\r
209     String id;\r
210     while (i < al.getHeight() && al.getSequenceAt(i) != null)\r
211     {\r
212       SequenceI s = al.getSequenceAt(i);\r
213       id = s.getDisplayId(av.getShowJVSuffix());\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     if (!av.wrapAlignment)\r
275     {\r
276       annotationSpaceFillerHolder.setVisible(b);\r
277       annotationScroller.setVisible(b);\r
278     }\r
279     validate();\r
280     repaint();\r
281   }\r
282 \r
283   public void setWrapAlignment(boolean wrap)\r
284   {\r
285     av.startSeq = 0;\r
286     scalePanelHolder.setVisible(!wrap);\r
287     hscroll.setVisible(!wrap);\r
288     idwidthAdjuster.setVisible(!wrap);\r
289 \r
290     if (wrap)\r
291     {\r
292       annotationScroller.setVisible(false);\r
293       annotationSpaceFillerHolder.setVisible(false);\r
294     }\r
295     else if (av.showAnnotation)\r
296     {\r
297       annotationScroller.setVisible(true);\r
298       annotationSpaceFillerHolder.setVisible(true);\r
299     }\r
300 \r
301     idSpaceFillerPanel1.setVisible(!wrap);\r
302 \r
303     validate();\r
304     repaint();\r
305 \r
306   }\r
307 \r
308 \r
309   int hextent = 0;\r
310   int vextent = 0;\r
311 \r
312   // return value is true if the scroll is valid\r
313   public boolean scrollUp(boolean up)\r
314   {\r
315     if (up)\r
316     {\r
317       if (vscroll.getValue() < 1)\r
318       {\r
319         return false;\r
320       }\r
321       fastPaint = false;\r
322       vscroll.setValue(vscroll.getValue() - 1);\r
323     }\r
324     else\r
325     {\r
326       if (vextent + vscroll.getValue() >= av.getAlignment().getHeight())\r
327       {\r
328         return false;\r
329       }\r
330       fastPaint = false;\r
331       vscroll.setValue(vscroll.getValue() + 1);\r
332     }\r
333     fastPaint = true;\r
334     return true;\r
335   }\r
336 \r
337   public boolean scrollRight(boolean right)\r
338   {\r
339 \r
340     if (right)\r
341     {\r
342       if (hscroll.getValue() < 1)\r
343       {\r
344         return false;\r
345       }\r
346       fastPaint = false;\r
347       hscroll.setValue(hscroll.getValue() - 1);\r
348     }\r
349     else\r
350     {\r
351       if (hextent + hscroll.getValue() >= av.getAlignment().getWidth())\r
352       {\r
353         return false;\r
354       }\r
355       fastPaint = false;\r
356       hscroll.setValue(hscroll.getValue() + 1);\r
357     }\r
358     fastPaint = true;\r
359     return true;\r
360   }\r
361 \r
362   public void setScrollValues(int x, int y)\r
363   {\r
364 \r
365     av.setStartRes(x);\r
366     av.setStartSeq(y);\r
367     av.setEndRes(x + seqPanel.seqCanvas.getSize().width / av.getCharWidth() - 1);\r
368 \r
369     hextent = seqPanel.seqCanvas.getSize().width / av.charWidth;\r
370     vextent = seqPanel.seqCanvas.getSize().height / av.charHeight;\r
371 \r
372     if (hextent > av.alignment.getWidth())\r
373     {\r
374       hextent = av.alignment.getWidth();\r
375     }\r
376     if (vextent > av.alignment.getHeight())\r
377     {\r
378       vextent = av.alignment.getHeight();\r
379     }\r
380 \r
381     if (hextent + x > av.getAlignment().getWidth())\r
382     {\r
383       x = av.getAlignment().getWidth() - hextent;\r
384     }\r
385 \r
386     if (vextent + y > av.getAlignment().getHeight())\r
387     {\r
388       y = av.getAlignment().getHeight() - vextent;\r
389     }\r
390 \r
391     if (y < 0)\r
392     {\r
393       y = 0;\r
394     }\r
395 \r
396     if (x < 0)\r
397     {\r
398       x = 0;\r
399     }\r
400 \r
401     int endSeq = y + vextent;\r
402     if (endSeq > av.alignment.getHeight())\r
403     {\r
404       endSeq = av.alignment.getHeight();\r
405     }\r
406 \r
407     av.setEndSeq(endSeq);\r
408     hscroll.setValues(x, hextent, 0, av.getAlignment().getWidth());\r
409     vscroll.setValues(y, vextent, 0, av.getAlignment().getHeight());\r
410 \r
411   }\r
412 \r
413   public void adjustmentValueChanged(AdjustmentEvent evt)\r
414   {\r
415     int oldX = av.getStartRes();\r
416     int oldY = av.getStartSeq();\r
417 \r
418     if (evt.getSource() == hscroll)\r
419     {\r
420       int x = hscroll.getValue();\r
421       av.setStartRes(x);\r
422       av.setEndRes(x + seqPanel.seqCanvas.getSize().width / av.getCharWidth() -\r
423                    1);\r
424     }\r
425 \r
426     if (evt.getSource() == vscroll)\r
427     {\r
428       int offy = vscroll.getValue();\r
429       if (av.getWrapAlignment())\r
430       {\r
431         int rowSize = seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.\r
432             seqCanvas.getSize().width);\r
433         av.setStartRes(vscroll.getValue() * rowSize);\r
434         av.setEndRes( (vscroll.getValue() + 1) * rowSize);\r
435       }\r
436       else\r
437       {\r
438         av.setStartSeq(offy);\r
439         av.setEndSeq(offy +\r
440                      seqPanel.seqCanvas.getSize().height / av.getCharHeight());\r
441       }\r
442     }\r
443 \r
444     if (overviewPanel != null)\r
445     {\r
446       overviewPanel.setBoxPosition();\r
447     }\r
448 \r
449     if (av.getWrapAlignment() || !fastPaint || MAC)\r
450     {\r
451       repaint();\r
452     }\r
453     else\r
454     {\r
455       idPanel.idCanvas.fastPaint(av.getStartSeq() - oldY);\r
456       seqPanel.seqCanvas.fastPaint(av.getStartRes() - oldX,\r
457                                    av.getStartSeq() - oldY);\r
458 \r
459       scalePanel.repaint();\r
460       if (av.getShowAnnotation())\r
461       {\r
462         annotationPanel.fastPaint(av.getStartRes() - oldX);\r
463       }\r
464     }\r
465 \r
466   }\r
467 \r
468   public void update(Graphics g)\r
469   {\r
470     paint(g);\r
471   }\r
472 \r
473   public void paint(Graphics g)\r
474   {\r
475     Dimension d = idPanel.idCanvas.getSize();\r
476     idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);\r
477     annotationSpaceFillerHolder.setSize(d.width,\r
478                                         annotationPanel.getSize().height);\r
479 \r
480     alabels.setSize(d.width, annotationPanel.getSize().height);\r
481 \r
482     if (av.getWrapAlignment())\r
483     {\r
484       int max = av.alignment.getWidth() /\r
485           seqPanel.seqCanvas.\r
486           getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width) +1;\r
487       vscroll.setMaximum(max);\r
488       vscroll.setUnitIncrement(1);\r
489       vscroll.setVisibleAmount(1);\r
490     }\r
491     else\r
492     {\r
493       setScrollValues(av.getStartRes(), av.getStartSeq());\r
494     }\r
495 \r
496     alabels.repaint();\r
497     idPanel.idCanvas.repaint();\r
498     seqPanel.seqCanvas.repaint();\r
499     scalePanel.repaint();\r
500     annotationPanel.repaint();\r
501 \r
502     if (getBounds() == g.getClipBounds())\r
503     {\r
504       if (overviewPanel != null)\r
505         overviewPanel.updateOverviewImage();\r
506     }\r
507 \r
508   }\r
509 \r
510   protected Panel sequenceHolderPanel = new Panel();\r
511   protected Scrollbar vscroll = new Scrollbar();\r
512   protected Scrollbar hscroll = new Scrollbar();\r
513   protected Panel seqPanelHolder = new Panel();\r
514   BorderLayout borderLayout1 = new BorderLayout();\r
515   BorderLayout borderLayout3 = new BorderLayout();\r
516   protected Panel scalePanelHolder = new Panel();\r
517   protected Panel idPanelHolder = new Panel();\r
518   BorderLayout borderLayout5 = new BorderLayout();\r
519   protected Panel idSpaceFillerPanel1 = new Panel();\r
520   public Panel annotationSpaceFillerHolder = new Panel();\r
521   BorderLayout borderLayout6 = new BorderLayout();\r
522   BorderLayout borderLayout7 = new BorderLayout();\r
523   Panel hscrollHolder = new Panel();\r
524   BorderLayout borderLayout10 = new BorderLayout();\r
525   protected Panel hscrollFillerPanel = new Panel();\r
526   BorderLayout borderLayout11 = new BorderLayout();\r
527   public Panel annotationScroller = new Panel();\r
528   BorderLayout borderLayout4 = new BorderLayout();\r
529   BorderLayout borderLayout2 = new BorderLayout();\r
530 \r
531   private void jbInit() throws Exception {\r
532       //  idPanelHolder.setPreferredSize(new Dimension(70, 10));\r
533       this.setLayout(borderLayout7);\r
534 \r
535       //   sequenceHolderPanel.setPreferredSize(new Dimension(150, 150));\r
536       sequenceHolderPanel.setLayout(borderLayout3);\r
537       seqPanelHolder.setLayout(borderLayout1);\r
538       scalePanelHolder.setBackground(Color.white);\r
539 \r
540       // scalePanelHolder.setPreferredSize(new Dimension(10, 30));\r
541       scalePanelHolder.setLayout(borderLayout6);\r
542       idPanelHolder.setLayout(borderLayout5);\r
543       idSpaceFillerPanel1.setBackground(Color.white);\r
544 \r
545       //  idSpaceFillerPanel1.setPreferredSize(new Dimension(10, 30));\r
546       idSpaceFillerPanel1.setLayout(borderLayout11);\r
547       annotationSpaceFillerHolder.setBackground(Color.white);\r
548 \r
549       //  annotationSpaceFillerHolder.setPreferredSize(new Dimension(10, 80));\r
550       annotationSpaceFillerHolder.setLayout(borderLayout4);\r
551       hscroll.setOrientation(Scrollbar.HORIZONTAL);\r
552       hscrollHolder.setLayout(borderLayout10);\r
553       hscrollFillerPanel.setBackground(Color.white);\r
554 \r
555       //  hscrollFillerPanel.setPreferredSize(new Dimension(70, 10));\r
556       hscrollHolder.setBackground(Color.white);\r
557 \r
558       //    annotationScroller.setPreferredSize(new Dimension(10, 80));\r
559       //  this.setPreferredSize(new Dimension(220, 166));\r
560       seqPanelHolder.setBackground(Color.white);\r
561       idPanelHolder.setBackground(Color.white);\r
562       annotationScroller.setLayout(borderLayout2);\r
563       sequenceHolderPanel.add(scalePanelHolder, BorderLayout.NORTH);\r
564       sequenceHolderPanel.add(seqPanelHolder, BorderLayout.CENTER);\r
565       seqPanelHolder.add(vscroll, BorderLayout.EAST);\r
566       sequenceHolderPanel.add(annotationScroller, BorderLayout.SOUTH);\r
567 \r
568       //  Panel3.add(secondaryPanelHolder,  BorderLayout.SOUTH);\r
569       this.add(idPanelHolder, BorderLayout.WEST);\r
570       idPanelHolder.add(idSpaceFillerPanel1, BorderLayout.NORTH);\r
571       idPanelHolder.add(annotationSpaceFillerHolder, BorderLayout.SOUTH);\r
572       this.add(hscrollHolder, BorderLayout.SOUTH);\r
573       hscrollHolder.add(hscroll, BorderLayout.CENTER);\r
574       hscrollHolder.add(hscrollFillerPanel, BorderLayout.WEST);\r
575       this.add(sequenceHolderPanel, BorderLayout.CENTER);\r
576   }\r
577 \r
578 }\r