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