elementAt instead of get for 1.1 compatibility
[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 \r
67     sequenceHolderPanel.add(annotationPanel, BorderLayout.SOUTH);\r
68 \r
69     alabels = new AnnotationLabels(this);\r
70 \r
71     setAnnotationVisible(av.showAnnotation);\r
72 \r
73     idPanelHolder.add(idPanel, BorderLayout.CENTER);\r
74     idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);\r
75     annotationSpaceFillerHolder.add(alabels, BorderLayout.CENTER);\r
76     scalePanelHolder.add(scalePanel, BorderLayout.CENTER);\r
77     seqPanelHolder.add(seqPanel, BorderLayout.CENTER);\r
78 \r
79     fontChanged();\r
80     setScrollValues(0, 0);\r
81 \r
82     hscroll.addAdjustmentListener(this);\r
83     vscroll.addAdjustmentListener(this);\r
84 \r
85     addComponentListener(new ComponentAdapter()\r
86     {\r
87       public void componentResized(ComponentEvent evt)\r
88       {\r
89         setScrollValues(av.getStartRes(), av.getStartSeq());\r
90         repaint();\r
91       }\r
92     });\r
93 \r
94     Dimension d = calculateIdWidth();\r
95     idPanel.idCanvas.setSize(d);\r
96 \r
97     hscrollFillerPanel.setSize(d.width, annotationPanel.getSize().height);\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 \r
107   public void fontChanged()\r
108   {\r
109     // set idCanvas bufferedImage to null\r
110     // to prevent drawing old image\r
111     idPanel.idCanvas.image = null;\r
112     FontMetrics fm = getFontMetrics(av.getFont());\r
113 \r
114     scalePanel.setSize(new Dimension(10, av.charHeight + fm.getDescent()));\r
115     idwidthAdjuster.setSize(new Dimension(10, av.charHeight + fm.getDescent()));\r
116 \r
117     annotationPanel.image = null;\r
118     int ap = annotationPanel.adjustPanelHeight();\r
119     annotationPanel.repaint();\r
120     Dimension d = calculateIdWidth();\r
121     d.setSize(d.width + 4, seqPanel.seqCanvas.getSize().height);\r
122     alabels.setSize(d.width+4, ap );\r
123     idPanel.idCanvas.setSize(d);\r
124     hscrollFillerPanel.setSize(d);\r
125 \r
126     validate();\r
127     repaint();\r
128 \r
129     if(overviewPanel!=null)\r
130           overviewPanel.updateOverviewImage();\r
131   }\r
132 \r
133   public void setIdWidth(int w, int h)\r
134   {\r
135     idPanel.idCanvas.setSize(w, h);\r
136     idPanelHolder.setSize(w, idPanelHolder.getSize().height);\r
137     alabels.setSize(w, alabels.getSize().height);\r
138     validate();\r
139   }\r
140 \r
141   Dimension calculateIdWidth()\r
142   {\r
143     if (av.nullFrame == null)\r
144     {\r
145       av.nullFrame = new Frame();\r
146       av.nullFrame.addNotify();\r
147     }\r
148 \r
149     Graphics g = av.nullFrame.getGraphics();\r
150 \r
151     FontMetrics fm = g.getFontMetrics(av.font);\r
152     AlignmentI al = av.getAlignment();\r
153 \r
154     int i = 0;\r
155     int idWidth = 0;\r
156     String id;\r
157     while (i < al.getHeight() && al.getSequenceAt(i) != null)\r
158     {\r
159       SequenceI s = al.getSequenceAt(i);\r
160       id = s.getDisplayId(av.getShowJVSuffix());\r
161 \r
162       if (fm.stringWidth(id) > idWidth)\r
163       {\r
164         idWidth = fm.stringWidth(id);\r
165       }\r
166       i++;\r
167     }\r
168 \r
169     // Also check annotation label widths\r
170     i = 0;\r
171     if (al.getAlignmentAnnotation() != null)\r
172     {\r
173       fm = g.getFontMetrics(av.nullFrame.getFont());\r
174       while (i < al.getAlignmentAnnotation().length)\r
175       {\r
176         String label = al.getAlignmentAnnotation()[i].label;\r
177         if (fm.stringWidth(label) > idWidth)\r
178         {\r
179           idWidth = fm.stringWidth(label);\r
180         }\r
181         i++;\r
182       }\r
183     }\r
184 \r
185     return new Dimension(idWidth, idPanel.idCanvas.getSize().height);\r
186   }\r
187 \r
188   public void highlightSearchResults(SearchResults results)\r
189   {\r
190     seqPanel.seqCanvas.highlightSearchResults(results);\r
191 \r
192    // do we need to scroll the panel?\r
193     if (results != null)\r
194     {\r
195       SequenceI seq = results.getResultSequence(0);\r
196       int seqIndex = av.alignment.findIndex(seq);\r
197       int start = seq.findIndex(results.getResultStart(0)) - 1;\r
198       int end = seq.findIndex(results.getResultEnd(0)) - 1;\r
199 \r
200         if(!av.wrapAlignment)\r
201         {\r
202           if ( (av.getStartRes() > end)  || (av.getEndRes() < start) ||\r
203              ( (av.getStartSeq() > seqIndex) || (av.getEndSeq() < seqIndex)))\r
204           {\r
205             if (start > av.alignment.getWidth() - hextent)\r
206             {\r
207               start = av.alignment.getWidth() - hextent;\r
208               if (start < 0)\r
209                 start = 0;\r
210             }\r
211             if (seqIndex > av.alignment.getHeight() - vextent)\r
212             {\r
213               seqIndex = av.alignment.getHeight() - vextent;\r
214               if (seqIndex < 0)\r
215                 seqIndex = 0;\r
216             }\r
217             setScrollValues(start, seqIndex);\r
218           }\r
219         }\r
220         else\r
221         {\r
222           scrollToWrappedVisible(start);\r
223         }\r
224     }\r
225 \r
226     repaint();\r
227   }\r
228 \r
229   void scrollToWrappedVisible(int res)\r
230   {\r
231     int cwidth = seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);\r
232     if (res <= av.getStartRes() || res >= (av.getStartRes() + cwidth))\r
233     {\r
234       vscroll.setValue(res / cwidth);\r
235       av.startRes = vscroll.getValue() * cwidth;\r
236     }\r
237   }\r
238 \r
239 \r
240   public OverviewPanel getOverviewPanel()\r
241   {\r
242     return overviewPanel;\r
243   }\r
244 \r
245   public void setOverviewPanel(OverviewPanel op)\r
246   {\r
247     overviewPanel = op;\r
248   }\r
249 \r
250   public void setAnnotationVisible(boolean b)\r
251   {\r
252     if (!av.wrapAlignment)\r
253     {\r
254       annotationSpaceFillerHolder.setVisible(b);\r
255       annotationPanel.setVisible(b);\r
256     }\r
257     validate();\r
258     repaint();\r
259   }\r
260 \r
261   public void setWrapAlignment(boolean wrap)\r
262   {\r
263     av.startSeq = 0;\r
264     scalePanelHolder.setVisible(!wrap);\r
265 \r
266 \r
267     hscroll.setVisible(!wrap);\r
268     idwidthAdjuster.setVisible(!wrap);\r
269 \r
270     if (wrap)\r
271     {\r
272       annotationPanel.setVisible(false);\r
273       annotationSpaceFillerHolder.setVisible(false);\r
274     }\r
275     else if (av.showAnnotation)\r
276     {\r
277       annotationPanel.setVisible(true);\r
278       annotationSpaceFillerHolder.setVisible(true);\r
279     }\r
280 \r
281 \r
282     idSpaceFillerPanel1.setVisible(!wrap);\r
283 \r
284     fontChanged();//This is so that the scalePanel is resized correctly\r
285 \r
286     validate();\r
287     repaint();\r
288 \r
289   }\r
290 \r
291 \r
292   int hextent = 0;\r
293   int vextent = 0;\r
294 \r
295   // return value is true if the scroll is valid\r
296   public boolean scrollUp(boolean up)\r
297   {\r
298     if (up)\r
299     {\r
300       if (vscroll.getValue() < 1)\r
301       {\r
302         return false;\r
303       }\r
304       setScrollValues(hscroll.getValue(), vscroll.getValue()-1);\r
305     }\r
306     else\r
307     {\r
308       if (vextent + vscroll.getValue() >= av.getAlignment().getHeight())\r
309       {\r
310         return false;\r
311       }\r
312       setScrollValues(hscroll.getValue(), vscroll.getValue()+1);\r
313     }\r
314 \r
315     repaint();\r
316     return true;\r
317   }\r
318 \r
319   public boolean scrollRight(boolean right)\r
320   {\r
321     if (!right)\r
322     {\r
323       if (hscroll.getValue() < 1)\r
324       {\r
325         return false;\r
326       }\r
327       setScrollValues(hscroll.getValue()-1, vscroll.getValue());\r
328     }\r
329     else\r
330     {\r
331       if (hextent + hscroll.getValue() >= av.getAlignment().getWidth())\r
332       {\r
333         return false;\r
334       }\r
335       setScrollValues(hscroll.getValue()+1, vscroll.getValue());\r
336     }\r
337 \r
338     repaint();\r
339     return true;\r
340   }\r
341 \r
342   public void setScrollValues(int x, int y)\r
343   {\r
344     int width = av.alignment.getWidth();\r
345     int height = av.alignment.getHeight();\r
346 \r
347     if(av.hasHiddenColumns)\r
348      width = av.getColumnSelection().findColumnPosition(width);\r
349 \r
350     av.setStartRes(x);\r
351     av.setStartSeq(y);\r
352 \r
353     av.setEndRes( (x + (seqPanel.seqCanvas.getSize().width / av.charWidth)) -1);\r
354 \r
355     hextent = seqPanel.seqCanvas.getSize().width / av.charWidth;\r
356     vextent = seqPanel.seqCanvas.getSize().height / av.charHeight;\r
357 \r
358     if (hextent > width)\r
359     {\r
360       hextent = width;\r
361     }\r
362 \r
363     if (vextent > height)\r
364     {\r
365       vextent = height;\r
366     }\r
367 \r
368     if ( (hextent + x) > width)\r
369     {\r
370       x = width - hextent;\r
371     }\r
372 \r
373     if ( (vextent + y) > height)\r
374     {\r
375       y = height - vextent;\r
376     }\r
377 \r
378     if (y < 0)\r
379     {\r
380       y = 0;\r
381     }\r
382 \r
383     if (x < 0)\r
384     {\r
385       x = 0;\r
386     }\r
387 \r
388     int endSeq = y + vextent;\r
389     if (endSeq > av.alignment.getHeight())\r
390     {\r
391       endSeq = av.alignment.getHeight();\r
392     }\r
393 \r
394     av.setEndSeq(endSeq);\r
395     hscroll.setValues(x, hextent, 0, av.getAlignment().getWidth());\r
396     vscroll.setValues(y, vextent, 0, av.getAlignment().getHeight());\r
397 \r
398     if(overviewPanel!=null)\r
399           overviewPanel.setBoxPosition();\r
400 \r
401   }\r
402 \r
403   public void adjustmentValueChanged(AdjustmentEvent evt)\r
404   {\r
405     int oldX = av.getStartRes();\r
406     int oldY = av.getStartSeq();\r
407 \r
408 \r
409     if (evt==null || evt.getSource() == hscroll)\r
410     {\r
411       int x = hscroll.getValue();\r
412       av.setStartRes(x);\r
413       av.setEndRes(x + seqPanel.seqCanvas.getSize().width / av.getCharWidth() -\r
414                    1);\r
415     }\r
416 \r
417 \r
418     if (evt==null || evt.getSource() == vscroll)\r
419     {\r
420       int offy = vscroll.getValue();\r
421       if (av.getWrapAlignment())\r
422       {\r
423         int rowSize = seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.\r
424             seqCanvas.getSize().width);\r
425         av.setStartRes(vscroll.getValue() * rowSize);\r
426         av.setEndRes( (vscroll.getValue() + 1) * rowSize);\r
427       }\r
428       else\r
429       {\r
430         av.setStartSeq(offy);\r
431         av.setEndSeq(offy +\r
432                      seqPanel.seqCanvas.getSize().height / av.getCharHeight());\r
433       }\r
434     }\r
435 \r
436     if (overviewPanel != null)\r
437     {\r
438       overviewPanel.setBoxPosition();\r
439     }\r
440 \r
441     int scrollX = av.startRes - oldX;\r
442     int scrollY = av.startSeq - oldY;\r
443 \r
444     if (av.getWrapAlignment() || !fastPaint || MAC)\r
445     {\r
446       repaint();\r
447     }\r
448     else\r
449     {\r
450       // Make sure we're not trying to draw a panel\r
451       // larger than the visible window\r
452       if(scrollX>av.endRes-av.startRes)\r
453       {\r
454         scrollX = av.endRes - av.startRes;\r
455       }\r
456       else if(scrollX<av.startRes-av.endRes)\r
457         scrollX = av.startRes - av.endRes;\r
458 \r
459       idPanel.idCanvas.fastPaint(scrollY);\r
460       seqPanel.seqCanvas.fastPaint(scrollX,\r
461                                    scrollY);\r
462 \r
463       scalePanel.repaint();\r
464       if (av.getShowAnnotation())\r
465       {\r
466         annotationPanel.fastPaint(av.getStartRes() - oldX);\r
467       }\r
468     }\r
469 \r
470   }\r
471 \r
472   public void update(Graphics g)\r
473   {\r
474     paint(g);\r
475   }\r
476 \r
477   public void paint(Graphics g)\r
478   {\r
479     invalidate();\r
480     Dimension d = idPanel.idCanvas.getSize();\r
481     idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);\r
482     annotationSpaceFillerHolder.setSize(d.width,\r
483                                         annotationPanel.getSize().height);\r
484 \r
485     alabels.setSize(d.width, annotationPanel.getSize().height);\r
486 \r
487     if (av.getWrapAlignment())\r
488     {\r
489       int maxwidth = av.alignment.getWidth();\r
490 \r
491       if (av.hasHiddenColumns)\r
492         maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;\r
493 \r
494       int max = maxwidth /\r
495           seqPanel.seqCanvas.getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width) +\r
496           1;\r
497 \r
498       vscroll.setMaximum(max);\r
499       vscroll.setUnitIncrement(1);\r
500       vscroll.setVisibleAmount(1);\r
501     }\r
502     else\r
503     {\r
504       setScrollValues(av.getStartRes(), av.getStartSeq());\r
505     }\r
506 \r
507     alabels.repaint();\r
508 \r
509     seqPanel.seqCanvas.repaint();\r
510     scalePanel.repaint();\r
511     annotationPanel.repaint();\r
512     idPanel.idCanvas.repaint();\r
513 \r
514     if (getBounds() == g.getClipBounds())\r
515     {\r
516       if (overviewPanel != null)\r
517         overviewPanel.updateOverviewImage();\r
518     }\r
519 \r
520   }\r
521 \r
522   protected Panel sequenceHolderPanel = new Panel();\r
523   protected Scrollbar vscroll = new Scrollbar();\r
524   protected Scrollbar hscroll = new Scrollbar();\r
525   protected Panel seqPanelHolder = new Panel();\r
526   BorderLayout borderLayout1 = new BorderLayout();\r
527   BorderLayout borderLayout3 = new BorderLayout();\r
528   protected Panel scalePanelHolder = new Panel();\r
529   protected Panel idPanelHolder = new Panel();\r
530   BorderLayout borderLayout5 = new BorderLayout();\r
531   protected Panel idSpaceFillerPanel1 = new Panel();\r
532   public Panel annotationSpaceFillerHolder = new Panel();\r
533   BorderLayout borderLayout6 = new BorderLayout();\r
534   BorderLayout borderLayout7 = new BorderLayout();\r
535   Panel hscrollHolder = new Panel();\r
536   BorderLayout borderLayout10 = new BorderLayout();\r
537   protected Panel hscrollFillerPanel = new Panel();\r
538   BorderLayout borderLayout11 = new BorderLayout();\r
539   BorderLayout borderLayout4 = new BorderLayout();\r
540   BorderLayout borderLayout2 = new BorderLayout();\r
541 \r
542   private void jbInit() throws Exception {\r
543       //  idPanelHolder.setPreferredSize(new Dimension(70, 10));\r
544       this.setLayout(borderLayout7);\r
545 \r
546       //   sequenceHolderPanel.setPreferredSize(new Dimension(150, 150));\r
547       sequenceHolderPanel.setLayout(borderLayout3);\r
548       seqPanelHolder.setLayout(borderLayout1);\r
549       scalePanelHolder.setBackground(Color.white);\r
550 \r
551       // scalePanelHolder.setPreferredSize(new Dimension(10, 30));\r
552       scalePanelHolder.setLayout(borderLayout6);\r
553       idPanelHolder.setLayout(borderLayout5);\r
554       idSpaceFillerPanel1.setBackground(Color.white);\r
555 \r
556       //  idSpaceFillerPanel1.setPreferredSize(new Dimension(10, 30));\r
557       idSpaceFillerPanel1.setLayout(borderLayout11);\r
558       annotationSpaceFillerHolder.setBackground(Color.white);\r
559 \r
560       //  annotationSpaceFillerHolder.setPreferredSize(new Dimension(10, 80));\r
561       annotationSpaceFillerHolder.setLayout(borderLayout4);\r
562       hscroll.setOrientation(Scrollbar.HORIZONTAL);\r
563       hscrollHolder.setLayout(borderLayout10);\r
564       hscrollFillerPanel.setBackground(Color.white);\r
565 \r
566       //  hscrollFillerPanel.setPreferredSize(new Dimension(70, 10));\r
567       hscrollHolder.setBackground(Color.white);\r
568 \r
569       //    annotationScroller.setPreferredSize(new Dimension(10, 80));\r
570       //  this.setPreferredSize(new Dimension(220, 166));\r
571       seqPanelHolder.setBackground(Color.white);\r
572       idPanelHolder.setBackground(Color.white);\r
573       sequenceHolderPanel.add(scalePanelHolder, BorderLayout.NORTH);\r
574       sequenceHolderPanel.add(seqPanelHolder, BorderLayout.CENTER);\r
575       seqPanelHolder.add(vscroll, BorderLayout.EAST);\r
576 \r
577       //  Panel3.add(secondaryPanelHolder,  BorderLayout.SOUTH);\r
578       this.add(idPanelHolder, BorderLayout.WEST);\r
579       idPanelHolder.add(idSpaceFillerPanel1, BorderLayout.NORTH);\r
580       idPanelHolder.add(annotationSpaceFillerHolder, BorderLayout.SOUTH);\r
581       this.add(hscrollHolder, BorderLayout.SOUTH);\r
582       hscrollHolder.add(hscroll, BorderLayout.CENTER);\r
583       hscrollHolder.add(hscrollFillerPanel, BorderLayout.WEST);\r
584       this.add(sequenceHolderPanel, BorderLayout.CENTER);\r
585   }\r
586 \r
587 }\r