fix scrolltoposition behaviour and new alignmentPanel api
[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   public void setWrapAlignment(boolean wrap)
386   {
387     av.startSeq = 0;
388     av.startRes = 0;
389     scalePanelHolder.setVisible(!wrap);
390
391     hscroll.setVisible(!wrap);
392     idwidthAdjuster.setVisible(!wrap);
393
394     if (wrap)
395     {
396       annotationPanelHolder.setVisible(false);
397       annotationSpaceFillerHolder.setVisible(false);
398     }
399     else if (av.showAnnotation)
400     {
401       annotationPanelHolder.setVisible(true);
402       annotationSpaceFillerHolder.setVisible(true);
403     }
404
405     idSpaceFillerPanel1.setVisible(!wrap);
406
407     fontChanged(); // This is so that the scalePanel is resized correctly
408
409     validate();
410     repaint();
411
412   }
413
414   int hextent = 0;
415
416   int vextent = 0;
417
418   // return value is true if the scroll is valid
419   public boolean scrollUp(boolean up)
420   {
421     if (up)
422     {
423       if (vscroll.getValue() < 1)
424       {
425         return false;
426       }
427       setScrollValues(hscroll.getValue(), vscroll.getValue() - 1);
428     }
429     else
430     {
431       if (vextent + vscroll.getValue() >= av.getAlignment().getHeight())
432       {
433         return false;
434       }
435       setScrollValues(hscroll.getValue(), vscroll.getValue() + 1);
436     }
437
438     repaint();
439     return true;
440   }
441
442   public boolean scrollRight(boolean right)
443   {
444     if (!right)
445     {
446       if (hscroll.getValue() < 1)
447       {
448         return false;
449       }
450       setScrollValues(hscroll.getValue() - 1, vscroll.getValue());
451     }
452     else
453     {
454       if (hextent + hscroll.getValue() >= av.getAlignment().getWidth())
455       {
456         return false;
457       }
458       setScrollValues(hscroll.getValue() + 1, vscroll.getValue());
459     }
460
461     repaint();
462     return true;
463   }
464
465   public void setScrollValues(int x, int y)
466   {
467     int width = av.alignment.getWidth();
468     int height = av.alignment.getHeight();
469
470     if (av.hasHiddenColumns)
471     {
472       width = av.getColumnSelection().findColumnPosition(width);
473     }
474
475     av.setStartRes(x);
476     av.setEndRes((x + (seqPanel.seqCanvas.getSize().width / av.charWidth)) - 1);
477
478     hextent = seqPanel.seqCanvas.getSize().width / av.charWidth;
479     vextent = seqPanel.seqCanvas.getSize().height / av.charHeight;
480     
481     if (hextent > width)
482     {
483       hextent = width;
484     }
485
486     if (vextent > height)
487     {
488       vextent = height;
489     }
490
491     if ((hextent + x) > width)
492     {
493       x = width - hextent;
494     }
495
496     if ((vextent + y) > height)
497     {
498       y = height - vextent;
499     }
500
501     if (y < 0)
502     {
503       y = 0;
504     }
505
506     if (x < 0)
507     {
508       x = 0;
509     }
510
511     av.setStartSeq(y);
512
513     int endSeq = y + vextent;
514     if (endSeq > av.alignment.getHeight())
515     {
516       endSeq = av.alignment.getHeight();
517     }
518
519     av.setEndSeq(endSeq);
520     hscroll.setValues(x, hextent, 0, width);
521     vscroll.setValues(y, vextent, 0, height);
522
523     if (overviewPanel != null)
524     {
525       overviewPanel.setBoxPosition();
526     }
527
528   }
529
530   public void adjustmentValueChanged(AdjustmentEvent evt)
531   {
532     int oldX = av.getStartRes();
533     int oldY = av.getStartSeq();
534
535     if (evt == null || evt.getSource() == apvscroll)
536     {
537       annotationPanel.setScrollOffset(apvscroll.getValue());
538       alabels.setScrollOffset(apvscroll.getValue());
539       // annotationPanel.image=null;
540       // alabels.image=null;
541       // alabels.repaint();
542       // annotationPanel.repaint();
543     }
544     if (evt == null || evt.getSource() == hscroll)
545     {
546       int x = hscroll.getValue();
547       av.setStartRes(x);
548       av.setEndRes(x + seqPanel.seqCanvas.getSize().width
549               / av.getCharWidth() - 1);
550     }
551
552     if (evt == null || evt.getSource() == vscroll)
553     {
554       int offy = vscroll.getValue();
555       if (av.getWrapAlignment())
556       {
557         int rowSize = seqPanel.seqCanvas
558                 .getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);
559         av.setStartRes(vscroll.getValue() * rowSize);
560         av.setEndRes((vscroll.getValue() + 1) * rowSize);
561       }
562       else
563       {
564         av.setStartSeq(offy);
565         av.setEndSeq(offy + seqPanel.seqCanvas.getSize().height
566                 / av.getCharHeight());
567       }
568     }
569
570     if (overviewPanel != null)
571     {
572       overviewPanel.setBoxPosition();
573     }
574
575     int scrollX = av.startRes - oldX;
576     int scrollY = av.startSeq - oldY;
577
578     if (av.getWrapAlignment() || !fastPaint || av.MAC)
579     {
580       repaint();
581     }
582     else
583     {
584       // Make sure we're not trying to draw a panel
585       // larger than the visible window
586       if (scrollX > av.endRes - av.startRes)
587       {
588         scrollX = av.endRes - av.startRes;
589       }
590       else if (scrollX < av.startRes - av.endRes)
591       {
592         scrollX = av.startRes - av.endRes;
593       }
594
595       idPanel.idCanvas.fastPaint(scrollY);
596       seqPanel.seqCanvas.fastPaint(scrollX, scrollY);
597
598       scalePanel.repaint();
599       if (av.getShowAnnotation())
600       {
601         annotationPanel.fastPaint(av.getStartRes() - oldX);
602       }
603     }
604
605   }
606
607   public void paintAlignment(boolean updateOverview)
608   {
609     repaint();
610
611     if (updateOverview)
612     {
613       jalview.structure.StructureSelectionManager
614               .getStructureSelectionManager().sequenceColoursChanged(this);
615
616       if (overviewPanel != null)
617       {
618         overviewPanel.updateOverviewImage();
619       }
620     }
621   }
622
623   public void update(Graphics g)
624   {
625     paint(g);
626   }
627
628   public void paint(Graphics g)
629   {
630     invalidate();
631     Dimension d = idPanel.idCanvas.getSize();
632     idPanel.idCanvas.setSize(d.width, seqPanel.seqCanvas.getSize().height);
633     
634     if (av.getWrapAlignment())
635     {
636       int maxwidth = av.alignment.getWidth();
637
638       if (av.hasHiddenColumns)
639       {
640         maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
641       }
642
643       int canvasWidth = seqPanel.seqCanvas
644               .getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);
645
646       if (canvasWidth > 0)
647       {
648         int max = maxwidth / canvasWidth;
649         vscroll.setMaximum(1 + max);
650         vscroll.setUnitIncrement(1);
651         vscroll.setVisibleAmount(1);
652       }
653     }
654     else
655     {
656       setScrollValues(av.getStartRes(), av.getStartSeq());
657     }
658
659     alabels.repaint();
660
661     seqPanel.seqCanvas.repaint();
662     scalePanel.repaint();
663     annotationPanel.repaint();
664     idPanel.idCanvas.repaint();
665   }
666
667   protected Panel sequenceHolderPanel = new Panel();
668
669   protected Scrollbar vscroll = new Scrollbar();
670
671   protected Scrollbar hscroll = new Scrollbar();
672
673   protected Panel seqPanelHolder = new Panel();
674
675   BorderLayout borderLayout1 = new BorderLayout();
676
677   BorderLayout borderLayout3 = new BorderLayout();
678
679   protected Panel scalePanelHolder = new Panel();
680
681   protected Panel idPanelHolder = new Panel();
682
683   BorderLayout borderLayout5 = new BorderLayout();
684
685   protected Panel idSpaceFillerPanel1 = new Panel();
686
687   public Panel annotationSpaceFillerHolder = new Panel();
688
689   BorderLayout borderLayout6 = new BorderLayout();
690
691   BorderLayout borderLayout7 = new BorderLayout();
692
693   Panel hscrollHolder = new Panel();
694
695   BorderLayout borderLayout10 = new BorderLayout();
696
697   protected Panel hscrollFillerPanel = new Panel();
698
699   BorderLayout borderLayout11 = new BorderLayout();
700
701   BorderLayout borderLayout4 = new BorderLayout();
702
703   BorderLayout borderLayout2 = new BorderLayout();
704
705   Panel annotationPanelHolder = new Panel();
706
707   protected Scrollbar apvscroll = new Scrollbar();
708
709   BorderLayout borderLayout12 = new BorderLayout();
710
711   private void jbInit() throws Exception
712   {
713     // idPanelHolder.setPreferredSize(new Dimension(70, 10));
714     this.setLayout(borderLayout7);
715
716     //sequenceHolderPanel.setPreferredSize(new Dimension(150, 150));
717     sequenceHolderPanel.setLayout(borderLayout3);
718     seqPanelHolder.setLayout(borderLayout1);
719     scalePanelHolder.setBackground(Color.white);
720
721     // scalePanelHolder.setPreferredSize(new Dimension(10, 30));
722     scalePanelHolder.setLayout(borderLayout6);
723     idPanelHolder.setLayout(borderLayout5);
724     idSpaceFillerPanel1.setBackground(Color.white);
725
726     // idSpaceFillerPanel1.setPreferredSize(new Dimension(10, 30));
727     idSpaceFillerPanel1.setLayout(borderLayout11);
728     annotationSpaceFillerHolder.setBackground(Color.white);
729
730     // annotationSpaceFillerHolder.setPreferredSize(new Dimension(10, 80));
731     annotationSpaceFillerHolder.setLayout(borderLayout4);
732     hscroll.setOrientation(Scrollbar.HORIZONTAL);
733     hscrollHolder.setLayout(borderLayout10);
734     hscrollFillerPanel.setBackground(Color.white);
735     apvscroll.setOrientation(Scrollbar.VERTICAL);
736     apvscroll.setVisible(true);
737     apvscroll.addAdjustmentListener(this);
738
739     annotationPanelHolder.setBackground(Color.white);
740     annotationPanelHolder.setLayout(borderLayout12);
741     annotationPanelHolder.add(apvscroll, BorderLayout.EAST);
742     // hscrollFillerPanel.setPreferredSize(new Dimension(70, 10));
743     hscrollHolder.setBackground(Color.white);
744
745     // annotationScroller.setPreferredSize(new Dimension(10, 80));
746     // this.setPreferredSize(new Dimension(220, 166));
747     seqPanelHolder.setBackground(Color.white);
748     idPanelHolder.setBackground(Color.white);
749     sequenceHolderPanel.add(scalePanelHolder, BorderLayout.NORTH);
750     sequenceHolderPanel.add(seqPanelHolder, BorderLayout.CENTER);
751     seqPanelHolder.add(vscroll, BorderLayout.EAST);
752
753     // Panel3.add(secondaryPanelHolder, BorderLayout.SOUTH);
754     this.add(idPanelHolder, BorderLayout.WEST);
755     idPanelHolder.add(idSpaceFillerPanel1, BorderLayout.NORTH);
756     idPanelHolder.add(annotationSpaceFillerHolder, BorderLayout.SOUTH);
757     this.add(hscrollHolder, BorderLayout.SOUTH);
758     hscrollHolder.add(hscroll, BorderLayout.CENTER);
759     hscrollHolder.add(hscrollFillerPanel, BorderLayout.WEST);
760     this.add(sequenceHolderPanel, BorderLayout.CENTER);
761   }
762
763   /**
764    * hides or shows dynamic annotation rows based on groups and av state flags
765    */
766   public void updateAnnotation()
767   {
768     updateAnnotation(false);
769   }
770
771   public void updateAnnotation(boolean applyGlobalSettings)
772   {
773     // TODO: this should be merged with other annotation update stuff - that
774     // sits on AlignViewport
775     boolean updateCalcs = false;
776     boolean conv = av.isShowGroupConservation();
777     boolean cons = av.isShowGroupConsensus();
778     boolean showprf = av.isShowSequenceLogo();
779     boolean showConsHist = av.isShowConsensusHistogram();
780
781     boolean sortg = true;
782
783     // remove old automatic annotation
784     // add any new annotation
785
786     Vector gr = av.alignment.getGroups(); // OrderedBy(av.alignment.getSequencesArray());
787     // intersect alignment annotation with alignment groups
788
789     AlignmentAnnotation[] aan = av.alignment.getAlignmentAnnotation();
790     Hashtable oldrfs = new Hashtable();
791     if (aan != null)
792     {
793       for (int an = 0; an < aan.length; an++)
794       {
795         if (aan[an].autoCalculated && aan[an].groupRef != null)
796         {
797           oldrfs.put(aan[an].groupRef, aan[an].groupRef);
798           av.alignment.deleteAnnotation(aan[an]);
799           aan[an] = null;
800         }
801       }
802     }
803     SequenceGroup sg;
804     if (gr != null)
805     {
806       for (int g = 0; g < gr.size(); g++)
807       {
808         updateCalcs = false;
809         sg = (SequenceGroup) gr.elementAt(g);
810         if (applyGlobalSettings || !oldrfs.containsKey(sg))
811         {
812           // set defaults for this group's conservation/consensus
813           sg.setshowSequenceLogo(showprf);
814           sg.setShowConsensusHistogram(showConsHist);
815         }
816         if (conv)
817         {
818           updateCalcs = true;
819           av.alignment.addAnnotation(sg.getConservationRow(), 0);
820         }
821         if (cons)
822         {
823           updateCalcs = true;
824           av.alignment.addAnnotation(sg.getConsensus(), 0);
825         }
826         // refresh the annotation rows
827         if (updateCalcs)
828         {
829           sg.recalcConservation();
830         }
831       }
832     }
833     oldrfs.clear();
834     adjustAnnotationHeight();
835   }
836
837   /**
838    * automatically adjust annotation panel height for new annotation whilst
839    * ensuring the alignment is still visible.
840    */
841   public void adjustAnnotationHeight()
842   {
843     // TODO: display vertical annotation scrollbar if necessary
844     // this is called after loading new annotation onto alignment
845     if (alignFrame.getSize().height == 0)
846     {
847       System.out.println("NEEDS FIXING");
848     }
849     fontChanged();
850     validateAnnotationDimensions(true);
851     apvscroll.addNotify();
852     hscroll.addNotify();
853     validate();
854     addNotify();
855     repaint();
856   }
857   /**
858    * calculate the annotation dimensions and refresh slider values accordingly.
859    * need to do repaints/notifys afterwards. 
860    */
861   protected void validateAnnotationDimensions(boolean adjustPanelHeight) {
862     int height = annotationPanel.calcPanelHeight();
863     if (hscroll.isVisible())
864     {
865       height += hscroll.getPreferredSize().height;
866     }
867     int mheight = height;
868     // sets initial preferred height
869     if ((height+40) > getSize().height / 2)
870     {
871       height = getSize().height / 2;
872     }
873     if (!adjustPanelHeight)
874     {
875       // maintain same window layout whilst updating sliders
876       height=seqPanelHolder.getSize().height;
877     }
878     Dimension d=seqPanelHolder.getSize(),e=idPanel.getSize(); 
879     annotationPanel.setSize(new Dimension(d.width,height));
880     alabels.setSize(e.width,height);
881     annotationSpaceFillerHolder.setSize(new Dimension(e.width, height));
882     annotationPanelHolder.setSize(new Dimension(d.width, height));
883     seqPanelHolder.setSize(d.width,d.height-height);
884     int s=apvscroll.getValue();
885     if (s>mheight-height)
886     {
887       s = 0;
888     }
889     apvscroll.setValues(apvscroll.getValue(), height, 0, mheight);
890     annotationPanel.setScrollOffset(apvscroll.getValue());
891     alabels.setScrollOffset(apvscroll.getValue());
892   }
893
894   @Override
895   public AlignmentI getAlignment()
896   {
897     return av.alignment;
898   }
899
900 }