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