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