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