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