update author list in license for (JAL-826)
[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       int seqIndex = av.alignment.findIndex(results);
290       if (seqIndex == -1)
291       {
292         return false;
293       }
294       SequenceI seq = av.alignment.getSequenceAt(seqIndex);
295       int[] r = results.getResults(seq, 0,av.alignment.getWidth());
296       if (r == null)
297       {
298         if (av.applet.debug) {// DEBUG
299           System.out.println("DEBUG: scroll didn't happen - results not within alignment : "+seq.getStart()+","+seq.getEnd());
300         }
301         return false;
302       }
303       if (av.applet.debug) {
304         // DEBUG
305         /*System.out.println("DEBUG: scroll: start=" + r[0]
306                 + " av.getStartRes()=" + av.getStartRes() + " end=" + r[1]
307                 + " seq.end=" + seq.getEnd() + " av.getEndRes()="
308                 + av.getEndRes() + " hextent=" + hextent);
309          */
310       }
311       int start = r[0];
312       int end = r[1];
313       if (start < 0)
314       {
315         return false;
316       }
317       if (end == seq.getEnd())
318       {
319         return false;
320       }
321       return scrollTo(start, end, seqIndex, false, redrawOverview);
322     }
323     return true;
324   }
325   public boolean scrollTo(int ostart, int end, int seqIndex, boolean scrollToNearest, boolean redrawOverview)
326   {
327             int startv, endv, starts, ends, width;
328
329           int start=-1;
330     if (av.hasHiddenColumns)
331     {
332       start = av.getColumnSelection().findColumnPosition(ostart);
333       end = av.getColumnSelection().findColumnPosition(end);
334       if (start == end)
335       {
336         if (!scrollToNearest && !av.colSel.isVisible(ostart))
337         {
338           // don't scroll - position isn't visible
339           return false;
340         }
341       }
342     }
343     else
344     {
345       start = ostart;
346     }
347     if (!av.wrapAlignment)
348     {
349           /*
350           int spos=av.getStartRes(),sqpos=av.getStartSeq();
351           if ((startv = av.getStartRes()) >= start)
352           {
353                   spos=start-1;
354 //                seqIn
355 //            setScrollValues(start - 1, seqIndex);
356           }
357           else if ((endv = av.getEndRes()) <= end)
358           {
359 //            setScrollValues(spos=startv + 1 + end - endv, seqIndex);
360                   spos=startv + 1 + end - endv;
361           }
362           else if ((starts = av.getStartSeq()) > seqIndex)
363           {
364             setScrollValues(av.getStartRes(), seqIndex);
365           }
366           else if ((ends = av.getEndSeq()) <= seqIndex)
367           {
368             setScrollValues(av.getStartRes(), starts + seqIndex - ends + 1);
369           }
370
371           /* */
372         if ((av.getStartRes() > end)
373                 || (av.getEndRes() < start)
374                 || ((av.getStartSeq() > seqIndex) || (av.getEndSeq() < seqIndex)))
375         {
376           if (start > av.alignment.getWidth() - hextent)
377           {
378             start = av.alignment.getWidth() - hextent;
379             if (start < 0)
380             {
381               start = 0;
382             }
383
384           }
385           if (seqIndex > av.alignment.getHeight() - vextent)
386           {
387             seqIndex = av.alignment.getHeight() - vextent;
388             if (seqIndex < 0)
389             {
390               seqIndex = 0;
391             }
392           }
393           // System.out.println("trying to scroll to: "+start+" "+seqIndex);
394           setScrollValues(start, seqIndex);
395         }/**/
396       }
397       else
398       {
399         scrollToWrappedVisible(start);
400       }
401     if (redrawOverview && overviewPanel != null)
402     {
403       overviewPanel.setBoxPosition();
404     }
405     paintAlignment(redrawOverview);
406     return true;
407   }
408
409   void scrollToWrappedVisible(int res)
410   {
411     int cwidth = seqPanel.seqCanvas
412             .getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);
413     if (res <= av.getStartRes() || res >= (av.getStartRes() + cwidth))
414     {
415       vscroll.setValue(res / cwidth);
416       av.startRes = vscroll.getValue() * cwidth;
417     }
418   }
419
420   public OverviewPanel getOverviewPanel()
421   {
422     return overviewPanel;
423   }
424
425   public void setOverviewPanel(OverviewPanel op)
426   {
427     overviewPanel = op;
428   }
429
430   public void setAnnotationVisible(boolean b)
431   {
432     if (!av.wrapAlignment)
433     {
434       annotationSpaceFillerHolder.setVisible(b);
435       annotationPanelHolder.setVisible(b);
436     }
437     validate();
438     repaint();
439   }
440   
441   /**
442    * automatically adjust annotation panel height for new annotation whilst
443    * ensuring the alignment is still visible.
444    */
445   public void adjustAnnotationHeight()
446   {
447     // TODO: display vertical annotation scrollbar if necessary
448     // this is called after loading new annotation onto alignment
449     if (alignFrame.getSize().height == 0)
450     {
451       System.out.println("NEEDS FIXING");
452     }
453     fontChanged();
454     validateAnnotationDimensions(true);
455     apvscroll.addNotify();
456     hscroll.addNotify();
457     validate();
458     paintAlignment(true);
459   }
460   /**
461    * calculate the annotation dimensions and refresh slider values accordingly.
462    * need to do repaints/notifys afterwards. 
463    */
464   protected void validateAnnotationDimensions(boolean adjustPanelHeight) {
465     boolean modified=false;
466     int height = annotationPanel.calcPanelHeight();
467     int minsize=0;
468     if (hscroll.isVisible())
469     {
470       height += (minsize=hscroll.getPreferredSize().height);
471     }
472     if (apvscroll.isVisible()) {
473       minsize+=apvscroll.getPreferredSize().height;
474     }
475     int mheight = height;
476     Dimension d=sequenceHolderPanel.getSize(),e=idPanel.getSize(); 
477     int seqandannot=d.height-scalePanelHolder.getSize().height;
478     // sets initial preferred height
479     if ((height+40) > seqandannot / 2)
480     {
481       height = seqandannot / 2;
482     }
483     if (!adjustPanelHeight)
484     {
485       // maintain same window layout whilst updating sliders
486       height=annotationPanelHolder.getSize().height;
487     }
488             
489     if (seqandannot-height<5)
490     {
491       height = seqandannot;
492     }
493     annotationPanel.setSize(new Dimension(d.width,height));
494     alabels.setSize(new Dimension(e.width,height));
495     annotationSpaceFillerHolder.setSize(new Dimension(e.width, height));
496     annotationPanelHolder.setSize(new Dimension(d.width, height));
497     seqPanelHolder.setSize(d.width,seqandannot-height);
498     seqPanel.seqCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);
499     int s=apvscroll.getValue();
500     if (s>mheight-height)
501     {
502       s = 0;
503     }
504     apvscroll.setValues(s, height, 0, mheight);
505     annotationPanel.setScrollOffset(apvscroll.getValue());
506     alabels.setScrollOffset(apvscroll.getValue());
507   }
508   
509   public void setWrapAlignment(boolean wrap)
510   {
511     av.startSeq = 0;
512     av.startRes = 0;
513     scalePanelHolder.setVisible(!wrap);
514
515     hscroll.setVisible(!wrap);
516     idwidthAdjuster.setVisible(!wrap);
517
518     if (wrap)
519     {
520       annotationPanelHolder.setVisible(false);
521       annotationSpaceFillerHolder.setVisible(false);
522     }
523     else if (av.showAnnotation)
524     {
525       annotationPanelHolder.setVisible(true);
526       annotationSpaceFillerHolder.setVisible(true);
527     }
528
529     idSpaceFillerPanel1.setVisible(!wrap);
530
531     fontChanged(); // This is so that the scalePanel is resized correctly
532
533     validate();
534     repaint();
535
536   }
537
538   int hextent = 0;
539
540   int vextent = 0;
541
542   // return value is true if the scroll is valid
543   public boolean scrollUp(boolean up)
544   {
545     if (up)
546     {
547       if (vscroll.getValue() < 1)
548       {
549         return false;
550       }
551       setScrollValues(hscroll.getValue(), vscroll.getValue() - 1);
552     }
553     else
554     {
555       if (vextent + vscroll.getValue() >= av.getAlignment().getHeight())
556       {
557         return false;
558       }
559       setScrollValues(hscroll.getValue(), vscroll.getValue() + 1);
560     }
561
562     repaint();
563     return true;
564   }
565
566   public boolean scrollRight(boolean right)
567   {
568     if (!right)
569     {
570       if (hscroll.getValue() < 1)
571       {
572         return false;
573       }
574       setScrollValues(hscroll.getValue() - 1, vscroll.getValue());
575     }
576     else
577     {
578       if (hextent + hscroll.getValue() >= av.getAlignment().getWidth())
579       {
580         return false;
581       }
582       setScrollValues(hscroll.getValue() + 1, vscroll.getValue());
583     }
584
585     repaint();
586     return true;
587   }
588
589   public void setScrollValues(int x, int y)
590   {
591     int width = av.alignment.getWidth();
592     int height = av.alignment.getHeight();
593
594     if (av.hasHiddenColumns)
595     {
596       width = av.getColumnSelection().findColumnPosition(width);
597     }
598     if (x<0) { x = 0; };
599
600     hextent = seqPanel.seqCanvas.getSize().width / av.charWidth;
601     vextent = seqPanel.seqCanvas.getSize().height / av.charHeight;
602     
603     if (hextent > width)
604     {
605       hextent = width;
606     }
607
608     if (vextent > height)
609     {
610       vextent = height;
611     }
612
613     if ((hextent + x) > width)
614     {
615       System.err.println("hextent was "+hextent+" and x was "+x);
616
617       x = width - hextent;
618     }
619
620     if ((vextent + y) > height)
621     {
622       y = height - vextent;
623     }
624
625     if (y < 0)
626     {
627       y = 0;
628     }
629
630     if (x < 0)
631     {
632       System.err.println("x was "+x);
633       x = 0;
634     }
635
636     av.setStartSeq(y);
637
638     int endSeq = y + vextent;
639     if (endSeq > av.alignment.getHeight())
640     {
641       endSeq = av.alignment.getHeight();
642     }
643
644     av.setEndSeq(endSeq);
645     av.setStartRes(x);
646     av.setEndRes((x + (seqPanel.seqCanvas.getSize().width / av.charWidth)) - 1);
647
648     hscroll.setValues(x, hextent, 0, width);
649     vscroll.setValues(y, vextent, 0, height);
650
651     if (overviewPanel != null)
652     {
653       overviewPanel.setBoxPosition();
654     }
655     sendViewPosition();
656
657
658   }
659
660   public void adjustmentValueChanged(AdjustmentEvent evt)
661   {
662     int oldX = av.getStartRes();
663     int oldY = av.getStartSeq();
664
665     if (evt == null || evt.getSource() == apvscroll)
666     {
667       annotationPanel.setScrollOffset(apvscroll.getValue());
668       alabels.setScrollOffset(apvscroll.getValue());
669       // annotationPanel.image=null;
670       // alabels.image=null;
671       // alabels.repaint();
672       // annotationPanel.repaint();
673     }
674     if (evt == null || evt.getSource() == hscroll)
675     {
676       int x = hscroll.getValue();
677       av.setStartRes(x);
678       av.setEndRes(x + seqPanel.seqCanvas.getSize().width
679               / av.getCharWidth() - 1);
680     }
681
682     if (evt == null || evt.getSource() == vscroll)
683     {
684       int offy = vscroll.getValue();
685       if (av.getWrapAlignment())
686       {
687         int rowSize = seqPanel.seqCanvas
688                 .getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);
689         av.setStartRes(vscroll.getValue() * rowSize);
690         av.setEndRes((vscroll.getValue() + 1) * rowSize);
691       }
692       else
693       {
694         av.setStartSeq(offy);
695         av.setEndSeq(offy + seqPanel.seqCanvas.getSize().height
696                 / av.getCharHeight());
697       }
698     }
699
700     if (overviewPanel != null)
701     {
702       overviewPanel.setBoxPosition();
703     }
704
705     int scrollX = av.startRes - oldX;
706     int scrollY = av.startSeq - oldY;
707
708     if (av.getWrapAlignment() || !fastPaint || av.MAC)
709     {
710       repaint();
711     }
712     else
713     {
714       // Make sure we're not trying to draw a panel
715       // larger than the visible window
716       if (scrollX > av.endRes - av.startRes)
717       {
718         scrollX = av.endRes - av.startRes;
719       }
720       else if (scrollX < av.startRes - av.endRes)
721       {
722         scrollX = av.startRes - av.endRes;
723       }
724
725       idPanel.idCanvas.fastPaint(scrollY);
726       seqPanel.seqCanvas.fastPaint(scrollX, scrollY);
727
728       scalePanel.repaint();
729       if (av.getShowAnnotation())
730       {
731         annotationPanel.fastPaint(av.getStartRes() - oldX);
732       }
733     }
734     sendViewPosition();
735
736   }
737   private void sendViewPosition()
738   {
739     StructureSelectionManager.getStructureSelectionManager(av.applet).sendViewPosition(this, av.startRes, av.endRes, av.startSeq, av.endSeq);
740   }
741
742   public void paintAlignment(boolean updateOverview)
743   {
744     repaint();
745
746     if (updateOverview)
747     {
748       jalview.structure.StructureSelectionManager
749               .getStructureSelectionManager(av.applet).sequenceColoursChanged(this);
750
751       if (overviewPanel != null)
752       {
753         overviewPanel.updateOverviewImage();
754       }
755     }
756   }
757
758   public void update(Graphics g)
759   {
760     paint(g);
761   }
762
763   public void paint(Graphics g)
764   {
765     invalidate();
766     Dimension d = idPanel.idCanvas.getSize();
767     idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);
768     
769     if (av.getWrapAlignment())
770     {
771       int maxwidth = av.alignment.getWidth();
772
773       if (av.hasHiddenColumns)
774       {
775         maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
776       }
777
778       int canvasWidth = seqPanel.seqCanvas
779               .getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);
780
781       if (canvasWidth > 0)
782       {
783         int max = maxwidth / canvasWidth;
784         vscroll.setMaximum(1 + max);
785         vscroll.setUnitIncrement(1);
786         vscroll.setVisibleAmount(1);
787       }
788     }
789     else
790     {
791       setScrollValues(av.getStartRes(), av.getStartSeq());
792     }
793
794     alabels.repaint();
795
796     seqPanel.seqCanvas.repaint();
797     scalePanel.repaint();
798     annotationPanel.repaint();
799     idPanel.idCanvas.repaint();
800   }
801
802   protected Panel sequenceHolderPanel = new Panel();
803
804   protected Scrollbar vscroll = new Scrollbar();
805
806   protected Scrollbar hscroll = new Scrollbar();
807
808   protected Panel seqPanelHolder = new Panel();
809
810   BorderLayout borderLayout1 = new BorderLayout();
811
812   BorderLayout borderLayout3 = new BorderLayout();
813
814   protected Panel scalePanelHolder = new Panel();
815
816   protected Panel idPanelHolder = new Panel();
817
818   BorderLayout borderLayout5 = new BorderLayout();
819
820   protected Panel idSpaceFillerPanel1 = new Panel();
821
822   public Panel annotationSpaceFillerHolder = new Panel();
823
824   BorderLayout borderLayout6 = new BorderLayout();
825
826   BorderLayout borderLayout7 = new BorderLayout();
827
828   Panel hscrollHolder = new Panel();
829
830   BorderLayout borderLayout10 = new BorderLayout();
831
832   protected Panel hscrollFillerPanel = new Panel();
833
834   BorderLayout borderLayout11 = new BorderLayout();
835
836   BorderLayout borderLayout4 = new BorderLayout();
837
838   BorderLayout borderLayout2 = new BorderLayout();
839
840   Panel annotationPanelHolder = new Panel();
841
842   protected Scrollbar apvscroll = new Scrollbar();
843
844   BorderLayout borderLayout12 = new BorderLayout();
845
846   private void jbInit() throws Exception
847   {
848     // idPanelHolder.setPreferredSize(new Dimension(70, 10));
849     this.setLayout(borderLayout7);
850
851     //sequenceHolderPanel.setPreferredSize(new Dimension(150, 150));
852     sequenceHolderPanel.setLayout(borderLayout3);
853     seqPanelHolder.setLayout(borderLayout1);
854     scalePanelHolder.setBackground(Color.white);
855
856     // scalePanelHolder.setPreferredSize(new Dimension(10, 30));
857     scalePanelHolder.setLayout(borderLayout6);
858     idPanelHolder.setLayout(borderLayout5);
859     idSpaceFillerPanel1.setBackground(Color.white);
860
861     // idSpaceFillerPanel1.setPreferredSize(new Dimension(10, 30));
862     idSpaceFillerPanel1.setLayout(borderLayout11);
863     annotationSpaceFillerHolder.setBackground(Color.white);
864
865     // annotationSpaceFillerHolder.setPreferredSize(new Dimension(10, 80));
866     annotationSpaceFillerHolder.setLayout(borderLayout4);
867     hscroll.setOrientation(Scrollbar.HORIZONTAL);
868     hscrollHolder.setLayout(borderLayout10);
869     hscrollFillerPanel.setBackground(Color.white);
870     apvscroll.setOrientation(Scrollbar.VERTICAL);
871     apvscroll.setVisible(true);
872     apvscroll.addAdjustmentListener(this);
873
874     annotationPanelHolder.setBackground(Color.white);
875     annotationPanelHolder.setLayout(borderLayout12);
876     annotationPanelHolder.add(apvscroll, BorderLayout.EAST);
877     // hscrollFillerPanel.setPreferredSize(new Dimension(70, 10));
878     hscrollHolder.setBackground(Color.white);
879
880     // annotationScroller.setPreferredSize(new Dimension(10, 80));
881     // this.setPreferredSize(new Dimension(220, 166));
882     seqPanelHolder.setBackground(Color.white);
883     idPanelHolder.setBackground(Color.white);
884     sequenceHolderPanel.add(scalePanelHolder, BorderLayout.NORTH);
885     sequenceHolderPanel.add(seqPanelHolder, BorderLayout.CENTER);
886     seqPanelHolder.add(vscroll, BorderLayout.EAST);
887
888     // Panel3.add(secondaryPanelHolder, BorderLayout.SOUTH);
889     this.add(idPanelHolder, BorderLayout.WEST);
890     idPanelHolder.add(idSpaceFillerPanel1, BorderLayout.NORTH);
891     idPanelHolder.add(annotationSpaceFillerHolder, BorderLayout.SOUTH);
892     this.add(hscrollHolder, BorderLayout.SOUTH);
893     hscrollHolder.add(hscroll, BorderLayout.CENTER);
894     hscrollHolder.add(hscrollFillerPanel, BorderLayout.WEST);
895     this.add(sequenceHolderPanel, BorderLayout.CENTER);
896   }
897
898   /**
899    * hides or shows dynamic annotation rows based on groups and av state flags
900    */
901   public void updateAnnotation()
902   {
903     updateAnnotation(false);
904   }
905
906   public void updateAnnotation(boolean applyGlobalSettings)
907   {
908     // TODO: this should be merged with other annotation update stuff - that
909     // sits on AlignViewport
910     boolean updateCalcs = false;
911     boolean conv = av.isShowGroupConservation();
912     boolean cons = av.isShowGroupConsensus();
913     boolean showprf = av.isShowSequenceLogo();
914     boolean showConsHist = av.isShowConsensusHistogram();
915
916     boolean sortg = true;
917
918     // remove old automatic annotation
919     // add any new annotation
920
921     Vector gr = av.alignment.getGroups(); // OrderedBy(av.alignment.getSequencesArray());
922     // intersect alignment annotation with alignment groups
923
924     AlignmentAnnotation[] aan = av.alignment.getAlignmentAnnotation();
925     Hashtable oldrfs = new Hashtable();
926     if (aan != null)
927     {
928       for (int an = 0; an < aan.length; an++)
929       {
930         if (aan[an].autoCalculated && aan[an].groupRef != null)
931         {
932           oldrfs.put(aan[an].groupRef, aan[an].groupRef);
933           av.alignment.deleteAnnotation(aan[an]);
934           aan[an] = null;
935         }
936       }
937     }
938     SequenceGroup sg;
939     if (gr != null)
940     {
941       for (int g = 0; g < gr.size(); g++)
942       {
943         updateCalcs = false;
944         sg = (SequenceGroup) gr.elementAt(g);
945         if (applyGlobalSettings || !oldrfs.containsKey(sg))
946         {
947           // set defaults for this group's conservation/consensus
948           sg.setshowSequenceLogo(showprf);
949           sg.setShowConsensusHistogram(showConsHist);
950         }
951         if (conv)
952         {
953           updateCalcs = true;
954           av.alignment.addAnnotation(sg.getConservationRow(), 0);
955         }
956         if (cons)
957         {
958           updateCalcs = true;
959           av.alignment.addAnnotation(sg.getConsensus(), 0);
960         }
961         // refresh the annotation rows
962         if (updateCalcs)
963         {
964           sg.recalcConservation();
965         }
966       }
967     }
968     oldrfs.clear();
969     adjustAnnotationHeight();
970   }
971
972   @Override
973   public AlignmentI getAlignment()
974   {
975     return av.alignment;
976   }
977   @Override
978   public StructureSelectionManager getStructureSelectionManager()
979   {
980     return StructureSelectionManager.getStructureSelectionManager(av.applet);
981   }
982
983 }