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