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