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