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