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