a90425f3694fa586cd5a2e1386694d71ddec6bf3
[jalview.git] / src / jalview / appletgui / AlignmentPanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3  * Copyright (C) 2014 The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.appletgui;
22
23 import jalview.api.AlignmentViewPanel;
24 import jalview.datamodel.AlignmentI;
25 import jalview.datamodel.SearchResults;
26 import jalview.datamodel.SequenceI;
27 import jalview.structure.StructureSelectionManager;
28
29 import java.awt.BorderLayout;
30 import java.awt.Color;
31 import java.awt.Dimension;
32 import java.awt.FontMetrics;
33 import java.awt.Frame;
34 import java.awt.Graphics;
35 import java.awt.Panel;
36 import java.awt.Scrollbar;
37 import java.awt.event.AdjustmentEvent;
38 import java.awt.event.AdjustmentListener;
39 import java.awt.event.ComponentAdapter;
40 import java.awt.event.ComponentEvent;
41
42 public class AlignmentPanel extends Panel implements AdjustmentListener,
43         AlignmentViewPanel
44 {
45
46   public AlignViewport av;
47
48   OverviewPanel overviewPanel;
49
50   SeqPanel seqPanel;
51
52   IdPanel idPanel;
53
54   IdwidthAdjuster idwidthAdjuster;
55
56   public AlignFrame alignFrame;
57
58   ScalePanel scalePanel;
59
60   AnnotationPanel annotationPanel;
61
62   AnnotationLabels alabels;
63
64   // this value is set false when selection area being dragged
65   boolean fastPaint = true;
66
67   public void finalize()
68   {
69     alignFrame = null;
70     av = null;
71     seqPanel = null;
72     seqPanelHolder = null;
73     sequenceHolderPanel = null;
74     scalePanel = null;
75     scalePanelHolder = null;
76     annotationPanel = null;
77     annotationPanelHolder = null;
78     annotationSpaceFillerHolder = null;
79   }
80
81   public AlignmentPanel(AlignFrame af, final AlignViewport av)
82   {
83     try
84     {
85       jbInit();
86     } catch (Exception e)
87     {
88       e.printStackTrace();
89     }
90
91     alignFrame = af;
92     this.av = av;
93     seqPanel = new SeqPanel(av, this);
94     idPanel = new IdPanel(av, this);
95     scalePanel = new ScalePanel(av, this);
96     idwidthAdjuster = new IdwidthAdjuster(this);
97     annotationPanel = new AnnotationPanel(this);
98     annotationPanelHolder.add(annotationPanel, BorderLayout.CENTER);
99
100     sequenceHolderPanel.add(annotationPanelHolder, BorderLayout.SOUTH);
101     alabels = new AnnotationLabels(this);
102
103     setAnnotationVisible(av.showAnnotation);
104
105     idPanelHolder.add(idPanel, BorderLayout.CENTER);
106     idSpaceFillerPanel1.add(idwidthAdjuster, BorderLayout.CENTER);
107     annotationSpaceFillerHolder.add(alabels, BorderLayout.CENTER);
108     scalePanelHolder.add(scalePanel, BorderLayout.CENTER);
109     seqPanelHolder.add(seqPanel, BorderLayout.CENTER);
110
111     fontChanged();
112     setScrollValues(0, 0);
113
114     apvscroll.addAdjustmentListener(this);
115     hscroll.addAdjustmentListener(this);
116     vscroll.addAdjustmentListener(this);
117
118     addComponentListener(new ComponentAdapter()
119     {
120       public void componentResized(ComponentEvent evt)
121       {
122         setScrollValues(av.getStartRes(), av.getStartSeq());
123         if (getSize().height > 0
124                 && annotationPanelHolder.getSize().height > 0)
125         {
126           validateAnnotationDimensions(false);
127         }
128         repaint();
129       }
130
131     });
132
133     Dimension d = calculateIdWidth();
134     idPanel.idCanvas.setSize(d);
135
136     hscrollFillerPanel.setSize(d.width, annotationPanel.getSize().height);
137
138     idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);
139     annotationSpaceFillerHolder.setSize(d.width,
140             annotationPanel.getSize().height);
141     alabels.setSize(d.width, annotationPanel.getSize().height);
142     final AlignmentPanel ap = this;
143     av.addPropertyChangeListener(new java.beans.PropertyChangeListener()
144     {
145       public void propertyChange(java.beans.PropertyChangeEvent evt)
146       {
147         if (evt.getPropertyName().equals("alignment"))
148         {
149           PaintRefresher.Refresh(ap, av.getSequenceSetId(), true, true);
150           alignmentChanged();
151         }
152       }
153     });
154   }
155
156   public SequenceRenderer getSequenceRenderer()
157   {
158     return seqPanel.seqCanvas.sr;
159   }
160
161   public FeatureRenderer getFeatureRenderer()
162   {
163     return seqPanel.seqCanvas.fr;
164   }
165
166   public void alignmentChanged()
167   {
168     av.alignmentChanged(this);
169
170     if (overviewPanel != null)
171     {
172       overviewPanel.updateOverviewImage();
173     }
174
175     alignFrame.updateEditMenuBar();
176
177     repaint();
178   }
179
180   public void fontChanged()
181   {
182     // set idCanvas bufferedImage to null
183     // to prevent drawing old image
184     idPanel.idCanvas.image = null;
185     FontMetrics fm = getFontMetrics(av.getFont());
186
187     scalePanel.setSize(new Dimension(10, av.charHeight + fm.getDescent()));
188     idwidthAdjuster.setSize(new Dimension(10, av.charHeight
189             + fm.getDescent()));
190     av.updateSequenceIdColours();
191     annotationPanel.image = null;
192     int ap = annotationPanel.adjustPanelHeight(false);
193     Dimension d = calculateIdWidth();
194     d.setSize(d.width + 4, seqPanel.seqCanvas.getSize().height);
195     alabels.setSize(d.width + 4, ap);
196
197     idPanel.idCanvas.setSize(d);
198     hscrollFillerPanel.setSize(d);
199
200     validateAnnotationDimensions(false);
201     annotationPanel.repaint();
202     validate();
203     repaint();
204
205     if (overviewPanel != null)
206     {
207       overviewPanel.updateOverviewImage();
208     }
209   }
210
211   public void setIdWidth(int w, int h)
212   {
213     idPanel.idCanvas.setSize(w, h);
214     idPanelHolder.setSize(w, idPanelHolder.getSize().height);
215     annotationSpaceFillerHolder.setSize(w,
216             annotationSpaceFillerHolder.getSize().height);
217     alabels.setSize(w, alabels.getSize().height);
218     validate();
219   }
220
221   Dimension calculateIdWidth()
222   {
223     if (av.nullFrame == null)
224     {
225       av.nullFrame = new Frame();
226       av.nullFrame.addNotify();
227     }
228
229     Graphics g = av.nullFrame.getGraphics();
230
231     FontMetrics fm = g.getFontMetrics(av.font);
232     AlignmentI al = av.getAlignment();
233
234     int i = 0;
235     int idWidth = 0;
236     String id;
237     while (i < al.getHeight() && al.getSequenceAt(i) != null)
238     {
239       SequenceI s = al.getSequenceAt(i);
240       id = s.getDisplayId(av.getShowJVSuffix());
241
242       if (fm.stringWidth(id) > idWidth)
243       {
244         idWidth = fm.stringWidth(id);
245       }
246       i++;
247     }
248
249     // Also check annotation label widths
250     i = 0;
251     if (al.getAlignmentAnnotation() != null)
252     {
253       fm = g.getFontMetrics(av.nullFrame.getFont());
254       while (i < al.getAlignmentAnnotation().length)
255       {
256         String label = al.getAlignmentAnnotation()[i].label;
257         if (fm.stringWidth(label) > idWidth)
258         {
259           idWidth = fm.stringWidth(label);
260         }
261         i++;
262       }
263     }
264
265     return new Dimension(idWidth, idPanel.idCanvas.getSize().height);
266   }
267
268   /**
269    * Highlight the given results on the alignment.
270    * 
271    */
272   public void highlightSearchResults(SearchResults results)
273   {
274     scrollToPosition(results);
275     seqPanel.seqCanvas.highlightSearchResults(results);
276   }
277
278   /**
279    * scroll the view to show the position of the highlighted region in results
280    * (if any) and redraw the overview
281    * 
282    * @param results
283    * @return false if results were not found
284    */
285   public boolean scrollToPosition(SearchResults results)
286   {
287     return scrollToPosition(results, true);
288   }
289
290   /**
291    * scroll the view to show the position of the highlighted region in results
292    * (if any)
293    * 
294    * @param results
295    * @param redrawOverview
296    *          - when set, the overview will be recalculated (takes longer)
297    * @return false if results were not found
298    */
299   public boolean scrollToPosition(SearchResults results,
300           boolean redrawOverview)
301   {
302
303     // do we need to scroll the panel?
304     if (results != null && results.getSize() > 0)
305     {
306       AlignmentI alignment = av.getAlignment();
307       int seqIndex = alignment.findIndex(results);
308       if (seqIndex == -1)
309       {
310         return false;
311       }
312       SequenceI seq = alignment.getSequenceAt(seqIndex);
313       int[] r = results.getResults(seq, 0, alignment.getWidth());
314       if (r == null)
315       {
316         if (av.applet.debug)
317         {// DEBUG
318           System.out
319                   .println("DEBUG: scroll didn't happen - results not within alignment : "
320                           + seq.getStart() + "," + seq.getEnd());
321         }
322         return false;
323       }
324       if (av.applet.debug)
325       {
326         // DEBUG
327         /*
328          * System.out.println("DEBUG: scroll: start=" + r[0] +
329          * " av.getStartRes()=" + av.getStartRes() + " end=" + r[1] +
330          * " seq.end=" + seq.getEnd() + " av.getEndRes()=" + av.getEndRes() +
331          * " hextent=" + hextent);
332          */
333       }
334       int start = r[0];
335       int end = r[1];
336       if (start < 0)
337       {
338         return false;
339       }
340       if (end == seq.getEnd())
341       {
342         return false;
343       }
344       return scrollTo(start, end, seqIndex, false, redrawOverview);
345     }
346     return true;
347   }
348
349   public boolean scrollTo(int ostart, int end, int seqIndex,
350           boolean scrollToNearest, boolean redrawOverview)
351   {
352     int startv, endv, starts, ends, width;
353
354     int start = -1;
355     if (av.hasHiddenColumns())
356     {
357       start = av.getColumnSelection().findColumnPosition(ostart);
358       end = av.getColumnSelection().findColumnPosition(end);
359       if (start == end)
360       {
361         if (!scrollToNearest && !av.getColumnSelection().isVisible(ostart))
362         {
363           // don't scroll - position isn't visible
364           return false;
365         }
366       }
367     }
368     else
369     {
370       start = ostart;
371     }
372     if (!av.wrapAlignment)
373     {
374       /*
375        * int spos=av.getStartRes(),sqpos=av.getStartSeq(); if ((startv =
376        * av.getStartRes()) >= start) { spos=start-1; // seqIn //
377        * setScrollValues(start - 1, seqIndex); } else if ((endv =
378        * av.getEndRes()) <= end) { // setScrollValues(spos=startv + 1 + end -
379        * endv, seqIndex); spos=startv + 1 + end - endv; } else if ((starts =
380        * av.getStartSeq()) > seqIndex) { setScrollValues(av.getStartRes(),
381        * seqIndex); } else if ((ends = av.getEndSeq()) <= seqIndex) {
382        * setScrollValues(av.getStartRes(), starts + seqIndex - ends + 1); }
383        * 
384        * /*
385        */
386       if ((av.getStartRes() > end)
387               || (av.getEndRes() < start)
388               || ((av.getStartSeq() > seqIndex) || (av.getEndSeq() < seqIndex)))
389       {
390         if (start > av.getAlignment().getWidth() - hextent)
391         {
392           start = av.getAlignment().getWidth() - hextent;
393           if (start < 0)
394           {
395             start = 0;
396           }
397
398         }
399         if (seqIndex > av.getAlignment().getHeight() - vextent)
400         {
401           seqIndex = av.getAlignment().getHeight() - vextent;
402           if (seqIndex < 0)
403           {
404             seqIndex = 0;
405           }
406         }
407         // System.out.println("trying to scroll to: "+start+" "+seqIndex);
408         setScrollValues(start, seqIndex);
409       }/**/
410     }
411     else
412     {
413       scrollToWrappedVisible(start);
414     }
415     if (redrawOverview && overviewPanel != null)
416     {
417       overviewPanel.setBoxPosition();
418     }
419     paintAlignment(redrawOverview);
420     return true;
421   }
422
423   void scrollToWrappedVisible(int res)
424   {
425     int cwidth = seqPanel.seqCanvas
426             .getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);
427     if (res <= av.getStartRes() || res >= (av.getStartRes() + cwidth))
428     {
429       vscroll.setValue(res / cwidth);
430       av.startRes = vscroll.getValue() * cwidth;
431     }
432   }
433
434   public OverviewPanel getOverviewPanel()
435   {
436     return overviewPanel;
437   }
438
439   public void setOverviewPanel(OverviewPanel op)
440   {
441     overviewPanel = op;
442   }
443
444   public void setAnnotationVisible(boolean b)
445   {
446     if (!av.wrapAlignment)
447     {
448       annotationSpaceFillerHolder.setVisible(b);
449       annotationPanelHolder.setVisible(b);
450     }
451     else
452     {
453       annotationSpaceFillerHolder.setVisible(false);
454       annotationPanelHolder.setVisible(false);
455     }
456     validate();
457     repaint();
458   }
459
460   /**
461    * automatically adjust annotation panel height for new annotation whilst
462    * ensuring the alignment is still visible.
463    */
464   public void adjustAnnotationHeight()
465   {
466     // TODO: display vertical annotation scrollbar if necessary
467     // this is called after loading new annotation onto alignment
468     if (alignFrame.getSize().height == 0)
469     {
470       System.out.println("NEEDS FIXING");
471     }
472     fontChanged();
473     validateAnnotationDimensions(true);
474     apvscroll.addNotify();
475     hscroll.addNotify();
476     validate();
477     paintAlignment(true);
478   }
479
480   /**
481    * calculate the annotation dimensions and refresh slider values accordingly.
482    * need to do repaints/notifys afterwards.
483    */
484   protected void validateAnnotationDimensions(boolean adjustPanelHeight)
485   {
486     boolean modified = false;
487     int height = av.calcPanelHeight();
488     int minsize = 0;
489     if (hscroll.isVisible())
490     {
491       height += (minsize = hscroll.getPreferredSize().height);
492     }
493     if (apvscroll.isVisible())
494     {
495       minsize += apvscroll.getPreferredSize().height;
496     }
497     int mheight = height;
498     Dimension d = sequenceHolderPanel.getSize(), e = idPanel.getSize();
499     int seqandannot = d.height - scalePanelHolder.getSize().height;
500
501     if (adjustPanelHeight)
502     {
503       // NOTE: this logic is different in the application. Need a better
504       // algorithm to define behaviour
505       // sets initial preferred height
506       // try and set height according to alignment
507       float sscaling = (float) ((av.getCharHeight() * av.getAlignment()
508               .getHeight()) / (1.0 * mheight));
509       if (sscaling > 0.5)
510       {
511         // if the alignment is too big then
512         // default is 0.5 split
513         height = seqandannot / 2;
514       }
515       else
516       {
517         // otherwise just set the panel so that one row of sequence is visible
518         height = -av.getCharHeight() * 1
519                 + (int) (seqandannot * (1 - sscaling));
520       }
521     }
522     else
523     {
524       // maintain same window layout whilst updating sliders
525       height = annotationPanelHolder.getSize().height;
526     }
527
528     if (seqandannot - height < 5)
529     {
530       height = seqandannot;
531     }
532     annotationPanel.setSize(new Dimension(d.width, height));
533     alabels.setSize(new Dimension(e.width, height));
534     annotationSpaceFillerHolder.setSize(new Dimension(e.width, height));
535     annotationPanelHolder.setSize(new Dimension(d.width, height));
536     // seqPanelHolder.setSize(d.width, seqandannot - height);
537     seqPanel.seqCanvas
538             .setSize(d.width, seqPanel.seqCanvas.getSize().height);
539     int s = apvscroll.getValue();
540     if (s > mheight - height)
541     {
542       s = 0;
543     }
544     apvscroll.setValues(s, height, 0, mheight);
545     annotationPanel.setScrollOffset(apvscroll.getValue(), false);
546     alabels.setScrollOffset(apvscroll.getValue(), false);
547   }
548
549   public void setWrapAlignment(boolean wrap)
550   {
551     av.startSeq = 0;
552     av.startRes = 0;
553     scalePanelHolder.setVisible(!wrap);
554
555     hscroll.setVisible(!wrap);
556     idwidthAdjuster.setVisible(!wrap);
557
558     if (wrap)
559     {
560       annotationPanelHolder.setVisible(false);
561       annotationSpaceFillerHolder.setVisible(false);
562     }
563     else if (av.showAnnotation)
564     {
565       annotationPanelHolder.setVisible(true);
566       annotationSpaceFillerHolder.setVisible(true);
567     }
568
569     idSpaceFillerPanel1.setVisible(!wrap);
570
571     fontChanged(); // This is so that the scalePanel is resized correctly
572
573     validate();
574     sequenceHolderPanel.validate();
575     repaint();
576
577   }
578
579   int hextent = 0;
580
581   int vextent = 0;
582
583   // return value is true if the scroll is valid
584   public boolean scrollUp(boolean up)
585   {
586     if (up)
587     {
588       if (vscroll.getValue() < 1)
589       {
590         return false;
591       }
592       setScrollValues(hscroll.getValue(), vscroll.getValue() - 1);
593     }
594     else
595     {
596       if (vextent + vscroll.getValue() >= av.getAlignment().getHeight())
597       {
598         return false;
599       }
600       setScrollValues(hscroll.getValue(), vscroll.getValue() + 1);
601     }
602
603     repaint();
604     return true;
605   }
606
607   public boolean scrollRight(boolean right)
608   {
609     if (!right)
610     {
611       if (hscroll.getValue() < 1)
612       {
613         return false;
614       }
615       setScrollValues(hscroll.getValue() - 1, vscroll.getValue());
616     }
617     else
618     {
619       if (hextent + hscroll.getValue() >= av.getAlignment().getWidth())
620       {
621         return false;
622       }
623       setScrollValues(hscroll.getValue() + 1, vscroll.getValue());
624     }
625
626     repaint();
627     return true;
628   }
629
630   public void setScrollValues(int x, int y)
631   {
632     int width = av.getAlignment().getWidth();
633     int height = av.getAlignment().getHeight();
634
635     if (av.hasHiddenColumns())
636     {
637       width = av.getColumnSelection().findColumnPosition(width);
638     }
639     if (x < 0)
640     {
641       x = 0;
642     }
643     ;
644
645     hextent = seqPanel.seqCanvas.getSize().width / av.charWidth;
646     vextent = seqPanel.seqCanvas.getSize().height / av.charHeight;
647
648     if (hextent > width)
649     {
650       hextent = width;
651     }
652
653     if (vextent > height)
654     {
655       vextent = height;
656     }
657
658     if ((hextent + x) > width)
659     {
660       System.err.println("hextent was " + hextent + " and x was " + x);
661
662       x = width - hextent;
663     }
664
665     if ((vextent + y) > height)
666     {
667       y = height - vextent;
668     }
669
670     if (y < 0)
671     {
672       y = 0;
673     }
674
675     if (x < 0)
676     {
677       System.err.println("x was " + x);
678       x = 0;
679     }
680
681     av.setStartSeq(y);
682
683     int endSeq = y + vextent;
684     if (endSeq > av.getAlignment().getHeight())
685     {
686       endSeq = av.getAlignment().getHeight();
687     }
688
689     av.setEndSeq(endSeq);
690     av.setStartRes(x);
691     av.setEndRes((x + (seqPanel.seqCanvas.getSize().width / av.charWidth)) - 1);
692
693     hscroll.setValues(x, hextent, 0, width);
694     vscroll.setValues(y, vextent, 0, height);
695
696     if (overviewPanel != null)
697     {
698       overviewPanel.setBoxPosition();
699     }
700     sendViewPosition();
701
702   }
703
704   public void adjustmentValueChanged(AdjustmentEvent evt)
705   {
706     int oldX = av.getStartRes();
707     int oldY = av.getStartSeq();
708
709     if (evt == null || evt.getSource() == apvscroll)
710     {
711       annotationPanel.setScrollOffset(apvscroll.getValue(), false);
712       alabels.setScrollOffset(apvscroll.getValue(), false);
713       // annotationPanel.image=null;
714       // alabels.image=null;
715       // alabels.repaint();
716       // annotationPanel.repaint();
717     }
718     if (evt == null || evt.getSource() == hscroll)
719     {
720       int x = hscroll.getValue();
721       av.setStartRes(x);
722       av.setEndRes(x + seqPanel.seqCanvas.getSize().width
723               / av.getCharWidth() - 1);
724     }
725
726     if (evt == null || evt.getSource() == vscroll)
727     {
728       int offy = vscroll.getValue();
729       if (av.getWrapAlignment())
730       {
731         int rowSize = seqPanel.seqCanvas
732                 .getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);
733         av.setStartRes(vscroll.getValue() * rowSize);
734         av.setEndRes((vscroll.getValue() + 1) * rowSize);
735       }
736       else
737       {
738         av.setStartSeq(offy);
739         av.setEndSeq(offy + seqPanel.seqCanvas.getSize().height
740                 / av.getCharHeight());
741       }
742     }
743
744     if (overviewPanel != null)
745     {
746       overviewPanel.setBoxPosition();
747     }
748
749     int scrollX = av.startRes - oldX;
750     int scrollY = av.startSeq - oldY;
751
752     if (av.getWrapAlignment() || !fastPaint || av.MAC)
753     {
754       repaint();
755     }
756     else
757     {
758       // Make sure we're not trying to draw a panel
759       // larger than the visible window
760       if (scrollX > av.endRes - av.startRes)
761       {
762         scrollX = av.endRes - av.startRes;
763       }
764       else if (scrollX < av.startRes - av.endRes)
765       {
766         scrollX = av.startRes - av.endRes;
767       }
768
769       idPanel.idCanvas.fastPaint(scrollY);
770       seqPanel.seqCanvas.fastPaint(scrollX, scrollY);
771
772       scalePanel.repaint();
773       if (av.getShowAnnotation())
774       {
775         annotationPanel.fastPaint(av.getStartRes() - oldX);
776       }
777     }
778     sendViewPosition();
779
780   }
781
782   private void sendViewPosition()
783   {
784     StructureSelectionManager.getStructureSelectionManager(av.applet)
785             .sendViewPosition(this, av.startRes, av.endRes, av.startSeq,
786                     av.endSeq);
787   }
788
789   public void paintAlignment(boolean updateOverview)
790   {
791     repaint();
792
793     if (updateOverview)
794     {
795       jalview.structure.StructureSelectionManager
796               .getStructureSelectionManager(av.applet)
797               .sequenceColoursChanged(this);
798
799       if (overviewPanel != null)
800       {
801         overviewPanel.updateOverviewImage();
802       }
803     }
804   }
805
806   public void update(Graphics g)
807   {
808     paint(g);
809   }
810
811   public void paint(Graphics g)
812   {
813     invalidate();
814     Dimension d = idPanel.idCanvas.getSize();
815     idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);
816
817     if (av.getWrapAlignment())
818     {
819       int maxwidth = av.getAlignment().getWidth();
820
821       if (av.hasHiddenColumns())
822       {
823         maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
824       }
825
826       int canvasWidth = seqPanel.seqCanvas
827               .getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);
828
829       if (canvasWidth > 0)
830       {
831         int max = maxwidth / canvasWidth;
832         vscroll.setMaximum(1 + max);
833         vscroll.setUnitIncrement(1);
834         vscroll.setVisibleAmount(1);
835       }
836     }
837     else
838     {
839       setScrollValues(av.getStartRes(), av.getStartSeq());
840     }
841
842     seqPanel.seqCanvas.repaint();
843     idPanel.idCanvas.repaint();
844     if (!av.wrapAlignment)
845     {
846       if (av.showAnnotation)
847       {
848         alabels.repaint();
849         annotationPanel.repaint();
850       }
851       scalePanel.repaint();
852     }
853
854   }
855
856   protected Panel sequenceHolderPanel = new Panel();
857
858   protected Scrollbar vscroll = new Scrollbar();
859
860   protected Scrollbar hscroll = new Scrollbar();
861
862   protected Panel seqPanelHolder = new Panel();
863
864   BorderLayout borderLayout1 = new BorderLayout();
865
866   BorderLayout borderLayout3 = new BorderLayout();
867
868   protected Panel scalePanelHolder = new Panel();
869
870   protected Panel idPanelHolder = new Panel();
871
872   BorderLayout borderLayout5 = new BorderLayout();
873
874   protected Panel idSpaceFillerPanel1 = new Panel();
875
876   public Panel annotationSpaceFillerHolder = new Panel();
877
878   BorderLayout borderLayout6 = new BorderLayout();
879
880   BorderLayout borderLayout7 = new BorderLayout();
881
882   Panel hscrollHolder = new Panel();
883
884   BorderLayout borderLayout10 = new BorderLayout();
885
886   protected Panel hscrollFillerPanel = new Panel();
887
888   BorderLayout borderLayout11 = new BorderLayout();
889
890   BorderLayout borderLayout4 = new BorderLayout();
891
892   BorderLayout borderLayout2 = new BorderLayout();
893
894   Panel annotationPanelHolder = new Panel();
895
896   protected Scrollbar apvscroll = new Scrollbar();
897
898   BorderLayout borderLayout12 = new BorderLayout();
899
900   private void jbInit() throws Exception
901   {
902     // idPanelHolder.setPreferredSize(new Dimension(70, 10));
903     this.setLayout(borderLayout7);
904
905     // sequenceHolderPanel.setPreferredSize(new Dimension(150, 150));
906     sequenceHolderPanel.setLayout(borderLayout3);
907     seqPanelHolder.setLayout(borderLayout1);
908     scalePanelHolder.setBackground(Color.white);
909
910     // scalePanelHolder.setPreferredSize(new Dimension(10, 30));
911     scalePanelHolder.setLayout(borderLayout6);
912     idPanelHolder.setLayout(borderLayout5);
913     idSpaceFillerPanel1.setBackground(Color.white);
914
915     // idSpaceFillerPanel1.setPreferredSize(new Dimension(10, 30));
916     idSpaceFillerPanel1.setLayout(borderLayout11);
917     annotationSpaceFillerHolder.setBackground(Color.white);
918
919     // annotationSpaceFillerHolder.setPreferredSize(new Dimension(10, 80));
920     annotationSpaceFillerHolder.setLayout(borderLayout4);
921     hscroll.setOrientation(Scrollbar.HORIZONTAL);
922     hscrollHolder.setLayout(borderLayout10);
923     hscrollFillerPanel.setBackground(Color.white);
924     apvscroll.setOrientation(Scrollbar.VERTICAL);
925     apvscroll.setVisible(true);
926     apvscroll.addAdjustmentListener(this);
927
928     annotationPanelHolder.setBackground(Color.white);
929     annotationPanelHolder.setLayout(borderLayout12);
930     annotationPanelHolder.add(apvscroll, BorderLayout.EAST);
931     // hscrollFillerPanel.setPreferredSize(new Dimension(70, 10));
932     hscrollHolder.setBackground(Color.white);
933
934     // annotationScroller.setPreferredSize(new Dimension(10, 80));
935     // this.setPreferredSize(new Dimension(220, 166));
936     seqPanelHolder.setBackground(Color.white);
937     idPanelHolder.setBackground(Color.white);
938     sequenceHolderPanel.add(scalePanelHolder, BorderLayout.NORTH);
939     sequenceHolderPanel.add(seqPanelHolder, BorderLayout.CENTER);
940     seqPanelHolder.add(vscroll, BorderLayout.EAST);
941
942     // Panel3.add(secondaryPanelHolder, BorderLayout.SOUTH);
943     this.add(idPanelHolder, BorderLayout.WEST);
944     idPanelHolder.add(idSpaceFillerPanel1, BorderLayout.NORTH);
945     idPanelHolder.add(annotationSpaceFillerHolder, BorderLayout.SOUTH);
946     this.add(hscrollHolder, BorderLayout.SOUTH);
947     hscrollHolder.add(hscroll, BorderLayout.CENTER);
948     hscrollHolder.add(hscrollFillerPanel, BorderLayout.WEST);
949     this.add(sequenceHolderPanel, BorderLayout.CENTER);
950   }
951
952   /**
953    * hides or shows dynamic annotation rows based on groups and av state flags
954    */
955   public void updateAnnotation()
956   {
957     updateAnnotation(false);
958   }
959
960   public void updateAnnotation(boolean applyGlobalSettings)
961   {
962     updateAnnotation(applyGlobalSettings, false);
963   }
964
965   public void updateAnnotation(boolean applyGlobalSettings,
966           boolean preserveNewGroupSettings)
967   {
968     av.updateGroupAnnotationSettings(applyGlobalSettings,
969             preserveNewGroupSettings);
970     adjustAnnotationHeight();
971   }
972
973   @Override
974   public AlignmentI getAlignment()
975   {
976     return av.getAlignment();
977   }
978
979   @Override
980   public String getViewName()
981   {
982     return getName();
983   }
984
985   @Override
986   public StructureSelectionManager getStructureSelectionManager()
987   {
988     return StructureSelectionManager
989             .getStructureSelectionManager(av.applet);
990   }
991
992   @Override
993   public void raiseOOMWarning(String string, OutOfMemoryError error)
994   {
995     // TODO: JAL-960
996     System.err.println("Out of memory whilst '" + string + "'");
997     error.printStackTrace();
998   }
999
1000 }