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