3293291368ceaf534386c011a500fba3824b4a33
[jalview.git] / src / jalview / viewmodel / AlignmentViewport.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3  * Copyright (C) 2014 The Jalview Authors
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
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.viewmodel;
22
23 import jalview.analysis.Conservation;
24 import jalview.api.AlignCalcManagerI;
25 import jalview.api.AlignViewportI;
26 import jalview.api.AlignmentViewPanel;
27 import jalview.api.FeaturesDisplayedI;
28 import jalview.api.ViewStyleI;
29 import jalview.datamodel.AlignmentAnnotation;
30 import jalview.datamodel.AlignmentI;
31 import jalview.datamodel.AlignmentView;
32 import jalview.datamodel.Annotation;
33 import jalview.datamodel.CigarArray;
34 import jalview.datamodel.ColumnSelection;
35 import jalview.datamodel.Sequence;
36 import jalview.datamodel.SequenceCollectionI;
37 import jalview.datamodel.SequenceGroup;
38 import jalview.datamodel.SequenceI;
39 import jalview.schemes.Blosum62ColourScheme;
40 import jalview.schemes.ColourSchemeI;
41 import jalview.schemes.PIDColourScheme;
42 import jalview.schemes.ResidueProperties;
43 import jalview.viewmodel.styles.ViewStyle;
44 import jalview.workers.AlignCalcManager;
45 import jalview.workers.ConsensusThread;
46 import jalview.workers.StrucConsensusThread;
47
48 import java.awt.Color;
49 import java.util.ArrayList;
50 import java.util.BitSet;
51 import java.util.HashMap;
52 import java.util.Hashtable;
53 import java.util.List;
54 import java.util.Map;
55 import java.util.Vector;
56
57 /**
58  * base class holding visualization and analysis attributes and common logic for
59  * an active alignment view displayed in the GUI
60  * 
61  * @author jimp
62  * 
63  */
64 public abstract class AlignmentViewport implements AlignViewportI,
65         ViewStyleI
66 {
67   protected ViewStyleI viewStyle = new ViewStyle();
68
69   /**
70    * A viewport that hosts the cDna view of this (protein), or vice versa (if
71    * set).
72    */
73   AlignViewportI codingComplement = null;
74
75   /**
76    * @param name
77    * @see jalview.api.ViewStyleI#setFontName(java.lang.String)
78    */
79   public void setFontName(String name)
80   {
81     viewStyle.setFontName(name);
82   }
83
84   /**
85    * @param style
86    * @see jalview.api.ViewStyleI#setFontStyle(int)
87    */
88   public void setFontStyle(int style)
89   {
90     viewStyle.setFontStyle(style);
91   }
92
93   /**
94    * @param size
95    * @see jalview.api.ViewStyleI#setFontSize(int)
96    */
97   public void setFontSize(int size)
98   {
99     viewStyle.setFontSize(size);
100   }
101
102   /**
103    * @return
104    * @see jalview.api.ViewStyleI#getFontStyle()
105    */
106   public int getFontStyle()
107   {
108     return viewStyle.getFontStyle();
109   }
110
111   /**
112    * @return
113    * @see jalview.api.ViewStyleI#getFontName()
114    */
115   public String getFontName()
116   {
117     return viewStyle.getFontName();
118   }
119
120   /**
121    * @return
122    * @see jalview.api.ViewStyleI#getFontSize()
123    */
124   public int getFontSize()
125   {
126     return viewStyle.getFontSize();
127   }
128
129   /**
130    * @param upperCasebold
131    * @see jalview.api.ViewStyleI#setUpperCasebold(boolean)
132    */
133   public void setUpperCasebold(boolean upperCasebold)
134   {
135     viewStyle.setUpperCasebold(upperCasebold);
136   }
137
138   /**
139    * @return
140    * @see jalview.api.ViewStyleI#isUpperCasebold()
141    */
142   public boolean isUpperCasebold()
143   {
144     return viewStyle.isUpperCasebold();
145   }
146
147   /**
148    * @return
149    * @see jalview.api.ViewStyleI#isSeqNameItalics()
150    */
151   public boolean isSeqNameItalics()
152   {
153     return viewStyle.isSeqNameItalics();
154   }
155
156   /**
157    * @param colourByReferenceSeq
158    * @see jalview.api.ViewStyleI#setColourByReferenceSeq(boolean)
159    */
160   public void setColourByReferenceSeq(boolean colourByReferenceSeq)
161   {
162     viewStyle.setColourByReferenceSeq(colourByReferenceSeq);
163   }
164
165   /**
166    * @param b
167    * @see jalview.api.ViewStyleI#setColourAppliesToAllGroups(boolean)
168    */
169   public void setColourAppliesToAllGroups(boolean b)
170   {
171     viewStyle.setColourAppliesToAllGroups(b);
172   }
173
174   /**
175    * @return
176    * @see jalview.api.ViewStyleI#getColourAppliesToAllGroups()
177    */
178   public boolean getColourAppliesToAllGroups()
179   {
180     return viewStyle.getColourAppliesToAllGroups();
181   }
182
183   /**
184    * @return
185    * @see jalview.api.ViewStyleI#getAbovePIDThreshold()
186    */
187   public boolean getAbovePIDThreshold()
188   {
189     return viewStyle.getAbovePIDThreshold();
190   }
191
192   /**
193    * @param inc
194    * @see jalview.api.ViewStyleI#setIncrement(int)
195    */
196   public void setIncrement(int inc)
197   {
198     viewStyle.setIncrement(inc);
199   }
200
201   /**
202    * @return
203    * @see jalview.api.ViewStyleI#getIncrement()
204    */
205   public int getIncrement()
206   {
207     return viewStyle.getIncrement();
208   }
209
210   /**
211    * @param b
212    * @see jalview.api.ViewStyleI#setConservationSelected(boolean)
213    */
214   public void setConservationSelected(boolean b)
215   {
216     viewStyle.setConservationSelected(b);
217   }
218
219   /**
220    * @param show
221    * @see jalview.api.ViewStyleI#setShowHiddenMarkers(boolean)
222    */
223   public void setShowHiddenMarkers(boolean show)
224   {
225     viewStyle.setShowHiddenMarkers(show);
226   }
227
228   /**
229    * @return
230    * @see jalview.api.ViewStyleI#getShowHiddenMarkers()
231    */
232   public boolean getShowHiddenMarkers()
233   {
234     return viewStyle.getShowHiddenMarkers();
235   }
236
237   /**
238    * @param b
239    * @see jalview.api.ViewStyleI#setScaleRightWrapped(boolean)
240    */
241   public void setScaleRightWrapped(boolean b)
242   {
243     viewStyle.setScaleRightWrapped(b);
244   }
245
246   /**
247    * @param b
248    * @see jalview.api.ViewStyleI#setScaleLeftWrapped(boolean)
249    */
250   public void setScaleLeftWrapped(boolean b)
251   {
252     viewStyle.setScaleLeftWrapped(b);
253   }
254
255   /**
256    * @param b
257    * @see jalview.api.ViewStyleI#setScaleAboveWrapped(boolean)
258    */
259   public void setScaleAboveWrapped(boolean b)
260   {
261     viewStyle.setScaleAboveWrapped(b);
262   }
263
264   /**
265    * @return
266    * @see jalview.api.ViewStyleI#getScaleLeftWrapped()
267    */
268   public boolean getScaleLeftWrapped()
269   {
270     return viewStyle.getScaleLeftWrapped();
271   }
272
273   /**
274    * @return
275    * @see jalview.api.ViewStyleI#getScaleAboveWrapped()
276    */
277   public boolean getScaleAboveWrapped()
278   {
279     return viewStyle.getScaleAboveWrapped();
280   }
281
282   /**
283    * @return
284    * @see jalview.api.ViewStyleI#getScaleRightWrapped()
285    */
286   public boolean getScaleRightWrapped()
287   {
288     return viewStyle.getScaleRightWrapped();
289   }
290
291   /**
292    * @param b
293    * @see jalview.api.ViewStyleI#setAbovePIDThreshold(boolean)
294    */
295   public void setAbovePIDThreshold(boolean b)
296   {
297     viewStyle.setAbovePIDThreshold(b);
298   }
299
300   /**
301    * @param thresh
302    * @see jalview.api.ViewStyleI#setThreshold(int)
303    */
304   public void setThreshold(int thresh)
305   {
306     viewStyle.setThreshold(thresh);
307   }
308
309   /**
310    * @return
311    * @see jalview.api.ViewStyleI#getThreshold()
312    */
313   public int getThreshold()
314   {
315     return viewStyle.getThreshold();
316   }
317
318   /**
319    * @return
320    * @see jalview.api.ViewStyleI#getShowJVSuffix()
321    */
322   public boolean getShowJVSuffix()
323   {
324     return viewStyle.getShowJVSuffix();
325   }
326
327   /**
328    * @param b
329    * @see jalview.api.ViewStyleI#setShowJVSuffix(boolean)
330    */
331   public void setShowJVSuffix(boolean b)
332   {
333     viewStyle.setShowJVSuffix(b);
334   }
335
336   /**
337    * @param state
338    * @see jalview.api.ViewStyleI#setWrapAlignment(boolean)
339    */
340   public void setWrapAlignment(boolean state)
341   {
342     viewStyle.setWrapAlignment(state);
343   }
344
345   /**
346    * @param state
347    * @see jalview.api.ViewStyleI#setShowText(boolean)
348    */
349   public void setShowText(boolean state)
350   {
351     viewStyle.setShowText(state);
352   }
353
354   /**
355    * @param state
356    * @see jalview.api.ViewStyleI#setRenderGaps(boolean)
357    */
358   public void setRenderGaps(boolean state)
359   {
360     viewStyle.setRenderGaps(state);
361   }
362
363   /**
364    * @return
365    * @see jalview.api.ViewStyleI#getColourText()
366    */
367   public boolean getColourText()
368   {
369     return viewStyle.getColourText();
370   }
371
372   /**
373    * @param state
374    * @see jalview.api.ViewStyleI#setColourText(boolean)
375    */
376   public void setColourText(boolean state)
377   {
378     viewStyle.setColourText(state);
379   }
380
381   /**
382    * @return
383    * @see jalview.api.ViewStyleI#getWrapAlignment()
384    */
385   public boolean getWrapAlignment()
386   {
387     return viewStyle.getWrapAlignment();
388   }
389
390   /**
391    * @return
392    * @see jalview.api.ViewStyleI#getShowText()
393    */
394   public boolean getShowText()
395   {
396     return viewStyle.getShowText();
397   }
398
399   /**
400    * @return
401    * @see jalview.api.ViewStyleI#getWrappedWidth()
402    */
403   public int getWrappedWidth()
404   {
405     return viewStyle.getWrappedWidth();
406   }
407
408   /**
409    * @param w
410    * @see jalview.api.ViewStyleI#setWrappedWidth(int)
411    */
412   public void setWrappedWidth(int w)
413   {
414     viewStyle.setWrappedWidth(w);
415   }
416
417   /**
418    * @return
419    * @see jalview.api.ViewStyleI#getCharHeight()
420    */
421   public int getCharHeight()
422   {
423     return viewStyle.getCharHeight();
424   }
425
426   /**
427    * @param h
428    * @see jalview.api.ViewStyleI#setCharHeight(int)
429    */
430   public void setCharHeight(int h)
431   {
432     viewStyle.setCharHeight(h);
433   }
434
435   /**
436    * @return
437    * @see jalview.api.ViewStyleI#getCharWidth()
438    */
439   public int getCharWidth()
440   {
441     return viewStyle.getCharWidth();
442   }
443
444   /**
445    * @param w
446    * @see jalview.api.ViewStyleI#setCharWidth(int)
447    */
448   public void setCharWidth(int w)
449   {
450     viewStyle.setCharWidth(w);
451   }
452
453   /**
454    * @return
455    * @see jalview.api.ViewStyleI#getShowBoxes()
456    */
457   public boolean getShowBoxes()
458   {
459     return viewStyle.getShowBoxes();
460   }
461
462   /**
463    * @return
464    * @see jalview.api.ViewStyleI#getShowUnconserved()
465    */
466   public boolean getShowUnconserved()
467   {
468     return viewStyle.getShowUnconserved();
469   }
470
471   /**
472    * @param showunconserved
473    * @see jalview.api.ViewStyleI#setShowUnconserved(boolean)
474    */
475   public void setShowUnconserved(boolean showunconserved)
476   {
477     viewStyle.setShowUnconserved(showunconserved);
478   }
479
480   /**
481    * @param default1
482    * @see jalview.api.ViewStyleI#setSeqNameItalics(boolean)
483    */
484   public void setSeqNameItalics(boolean default1)
485   {
486     viewStyle.setSeqNameItalics(default1);
487   }
488
489   /**
490    * @param selected
491    * @see jalview.api.ViewStyleI#setShowSeqFeaturesHeight(boolean)
492    */
493   public void setShowSeqFeaturesHeight(boolean selected)
494   {
495     viewStyle.setShowSeqFeaturesHeight(selected);
496   }
497
498   /**
499    * alignment displayed in the viewport. Please use get/setter
500    */
501   protected AlignmentI alignment;
502
503   @Override
504   public AlignmentI getAlignment()
505   {
506     return alignment;
507   }
508
509   @Override
510   public char getGapCharacter()
511   {
512     return alignment.getGapCharacter();
513   }
514
515   protected String sequenceSetID;
516
517   /**
518    * probably unused indicator that view is of a dataset rather than an
519    * alignment
520    */
521   protected boolean isDataset = false;
522
523   public void setDataset(boolean b)
524   {
525     isDataset = b;
526   }
527
528   public boolean isDataset()
529   {
530     return isDataset;
531   }
532
533
534   private Map<SequenceI, SequenceCollectionI> hiddenRepSequences;
535
536   protected ColumnSelection colSel = new ColumnSelection();
537
538   public boolean autoCalculateConsensus = true;
539
540   protected boolean autoCalculateStrucConsensus = true;
541
542   protected boolean ignoreGapsInConsensusCalculation = false;
543
544   protected ColourSchemeI globalColourScheme = null;
545
546
547   @Override
548   public void setGlobalColourScheme(ColourSchemeI cs)
549   {
550     // TODO: logic refactored from AlignFrame changeColour -
551     // autorecalc stuff should be changed to rely on the worker system
552     // check to see if we should implement a changeColour(cs) method rather than
553     // put th logic in here
554     // - means that caller decides if they want to just modify state and defer
555     // calculation till later or to do all calculations in thread.
556     // via changecolour
557     globalColourScheme = cs;
558     boolean recalc = false;
559     if (cs != null)
560     {
561       cs.setConservationApplied(recalc = getConservationSelected());
562       if (getAbovePIDThreshold() || cs instanceof PIDColourScheme
563               || cs instanceof Blosum62ColourScheme)
564       {
565         recalc = true;
566         cs.setThreshold(viewStyle.getThreshold(),
567                 ignoreGapsInConsensusCalculation);
568       }
569       else
570       {
571         cs.setThreshold(0, ignoreGapsInConsensusCalculation);
572       }
573       if (recalc)
574       {
575         cs.setConsensus(hconsensus);
576         cs.setConservation(hconservation);
577       }
578       cs.alignmentChanged(alignment, hiddenRepSequences);
579     }
580     if (getColourAppliesToAllGroups())
581     {
582       for (SequenceGroup sg : getAlignment().getGroups())
583       {
584         if (cs == null)
585         {
586           sg.cs = null;
587           continue;
588         }
589         sg.cs = cs.applyTo(sg, getHiddenRepSequences());
590         sg.setConsPercGaps(ConsPercGaps);
591         if (getAbovePIDThreshold() || cs instanceof PIDColourScheme
592                 || cs instanceof Blosum62ColourScheme)
593         {
594           sg.cs.setThreshold(viewStyle.getThreshold(),
595                   isIgnoreGapsConsensus());
596           recalc = true;
597         }
598         else
599         {
600           sg.cs.setThreshold(0, isIgnoreGapsConsensus());
601         }
602
603         if (getConservationSelected())
604         {
605           sg.cs.setConservationApplied(true);
606           recalc = true;
607         }
608         else
609         {
610           sg.cs.setConservation(null);
611           // sg.cs.setThreshold(0, getIgnoreGapsConsensus());
612         }
613         if (recalc)
614         {
615           sg.recalcConservation();
616         }
617         else
618         {
619           sg.cs.alignmentChanged(sg, hiddenRepSequences);
620         }
621       }
622     }
623
624   }
625
626   @Override
627   public ColourSchemeI getGlobalColourScheme()
628   {
629     return globalColourScheme;
630   }
631
632   protected AlignmentAnnotation consensus;
633
634   protected AlignmentAnnotation strucConsensus;
635
636   protected AlignmentAnnotation conservation;
637
638   protected AlignmentAnnotation quality;
639
640   protected AlignmentAnnotation[] groupConsensus;
641
642   protected AlignmentAnnotation[] groupConservation;
643
644   /**
645    * results of alignment consensus analysis for visible portion of view
646    */
647   protected Hashtable[] hconsensus = null;
648
649   /**
650    * results of secondary structure base pair consensus for visible portion of
651    * view
652    */
653   protected Hashtable[] hStrucConsensus = null;
654
655   protected Conservation hconservation = null;
656
657   @Override
658   public void setConservation(Conservation cons)
659   {
660     hconservation = cons;
661   }
662
663   /**
664    * percentage gaps allowed in a column before all amino acid properties should
665    * be considered unconserved
666    */
667   int ConsPercGaps = 25; // JBPNote : This should be a scalable property!
668
669   @Override
670   public int getConsPercGaps()
671   {
672     return ConsPercGaps;
673   }
674
675   @Override
676   public void setSequenceConsensusHash(Hashtable[] hconsensus)
677   {
678     this.hconsensus = hconsensus;
679
680   }
681
682   @Override
683   public Hashtable[] getSequenceConsensusHash()
684   {
685     return hconsensus;
686   }
687
688   @Override
689   public Hashtable[] getRnaStructureConsensusHash()
690   {
691     return hStrucConsensus;
692   }
693
694   @Override
695   public void setRnaStructureConsensusHash(Hashtable[] hStrucConsensus)
696   {
697     this.hStrucConsensus = hStrucConsensus;
698
699   }
700
701   @Override
702   public AlignmentAnnotation getAlignmentQualityAnnot()
703   {
704     return quality;
705   }
706
707   @Override
708   public AlignmentAnnotation getAlignmentConservationAnnotation()
709   {
710     return conservation;
711   }
712
713   @Override
714   public AlignmentAnnotation getAlignmentConsensusAnnotation()
715   {
716     return consensus;
717   }
718
719   @Override
720   public AlignmentAnnotation getAlignmentStrucConsensusAnnotation()
721   {
722     return strucConsensus;
723   }
724
725   protected AlignCalcManagerI calculator = new AlignCalcManager();
726
727   /**
728    * trigger update of conservation annotation
729    */
730   public void updateConservation(final AlignmentViewPanel ap)
731   {
732     // see note in mantis : issue number 8585
733     if (alignment.isNucleotide() || conservation == null
734             || !autoCalculateConsensus)
735     {
736       return;
737     }
738     if (calculator
739             .getRegisteredWorkersOfClass(jalview.workers.ConservationThread.class) == null)
740     {
741       calculator.registerWorker(new jalview.workers.ConservationThread(
742               this, ap));
743     }
744   }
745
746   /**
747    * trigger update of consensus annotation
748    */
749   public void updateConsensus(final AlignmentViewPanel ap)
750   {
751     // see note in mantis : issue number 8585
752     if (consensus == null || !autoCalculateConsensus)
753     {
754       return;
755     }
756     if (calculator.getRegisteredWorkersOfClass(ConsensusThread.class) == null)
757     {
758       calculator.registerWorker(new ConsensusThread(this, ap));
759     }
760   }
761
762   // --------START Structure Conservation
763   public void updateStrucConsensus(final AlignmentViewPanel ap)
764   {
765     if (autoCalculateStrucConsensus && strucConsensus == null
766             && alignment.isNucleotide() && alignment.hasRNAStructure())
767     {
768       // secondary structure has been added - so init the consensus line
769       initRNAStructure();
770     }
771
772     // see note in mantis : issue number 8585
773     if (strucConsensus == null || !autoCalculateStrucConsensus)
774     {
775       return;
776     }
777     if (calculator.getRegisteredWorkersOfClass(StrucConsensusThread.class) == null)
778     {
779       calculator.registerWorker(new StrucConsensusThread(this, ap));
780     }
781   }
782
783   public boolean isCalcInProgress()
784   {
785     return calculator.isWorking();
786   }
787
788   @Override
789   public boolean isCalculationInProgress(
790           AlignmentAnnotation alignmentAnnotation)
791   {
792     if (!alignmentAnnotation.autoCalculated)
793     {
794       return false;
795     }
796     if (calculator.workingInvolvedWith(alignmentAnnotation))
797     {
798       // System.err.println("grey out ("+alignmentAnnotation.label+")");
799       return true;
800     }
801     return false;
802   }
803
804   @Override
805   public boolean isClosed()
806   {
807     // TODO: check that this isClosed is only true after panel is closed, not
808     // before it is fully constructed.
809     return alignment == null;
810   }
811
812   @Override
813   public AlignCalcManagerI getCalcManager()
814   {
815     return calculator;
816   }
817
818   /**
819    * should conservation rows be shown for groups
820    */
821   protected boolean showGroupConservation = false;
822
823   /**
824    * should consensus rows be shown for groups
825    */
826   protected boolean showGroupConsensus = false;
827
828   /**
829    * should consensus profile be rendered by default
830    */
831   protected boolean showSequenceLogo = false;
832
833   /**
834    * should consensus profile be rendered normalised to row height
835    */
836   protected boolean normaliseSequenceLogo = false;
837
838   /**
839    * should consensus histograms be rendered by default
840    */
841   protected boolean showConsensusHistogram = true;
842
843   /**
844    * @return the showConsensusProfile
845    */
846   @Override
847   public boolean isShowSequenceLogo()
848   {
849     return showSequenceLogo;
850   }
851
852   /**
853    * @param showSequenceLogo
854    *          the new value
855    */
856   public void setShowSequenceLogo(boolean showSequenceLogo)
857   {
858     if (showSequenceLogo != this.showSequenceLogo)
859     {
860       // TODO: decouple settings setting from calculation when refactoring
861       // annotation update method from alignframe to viewport
862       this.showSequenceLogo = showSequenceLogo;
863       calculator.updateAnnotationFor(ConsensusThread.class);
864       calculator.updateAnnotationFor(StrucConsensusThread.class);
865     }
866     this.showSequenceLogo = showSequenceLogo;
867   }
868
869   /**
870    * @param showConsensusHistogram
871    *          the showConsensusHistogram to set
872    */
873   public void setShowConsensusHistogram(boolean showConsensusHistogram)
874   {
875     this.showConsensusHistogram = showConsensusHistogram;
876   }
877
878   /**
879    * @return the showGroupConservation
880    */
881   public boolean isShowGroupConservation()
882   {
883     return showGroupConservation;
884   }
885
886   /**
887    * @param showGroupConservation
888    *          the showGroupConservation to set
889    */
890   public void setShowGroupConservation(boolean showGroupConservation)
891   {
892     this.showGroupConservation = showGroupConservation;
893   }
894
895   /**
896    * @return the showGroupConsensus
897    */
898   public boolean isShowGroupConsensus()
899   {
900     return showGroupConsensus;
901   }
902
903   /**
904    * @param showGroupConsensus
905    *          the showGroupConsensus to set
906    */
907   public void setShowGroupConsensus(boolean showGroupConsensus)
908   {
909     this.showGroupConsensus = showGroupConsensus;
910   }
911
912   /**
913    * 
914    * @return flag to indicate if the consensus histogram should be rendered by
915    *         default
916    */
917   @Override
918   public boolean isShowConsensusHistogram()
919   {
920     return this.showConsensusHistogram;
921   }
922
923   /**
924    * when set, updateAlignment will always ensure sequences are of equal length
925    */
926   private boolean padGaps = false;
927
928   /**
929    * when set, alignment should be reordered according to a newly opened tree
930    */
931   public boolean sortByTree = false;
932
933
934   /**
935    * 
936    * 
937    * @return null or the currently selected sequence region
938    */
939   @Override
940   public SequenceGroup getSelectionGroup()
941   {
942     return selectionGroup;
943   }
944
945   /**
946    * Set the selection group for this window.
947    * 
948    * @param sg
949    *          - group holding references to sequences in this alignment view
950    * 
951    */
952   @Override
953   public void setSelectionGroup(SequenceGroup sg)
954   {
955     selectionGroup = sg;
956   }
957
958   public void setHiddenColumns(ColumnSelection colsel)
959   {
960     this.colSel = colsel;
961   }
962
963   @Override
964   public ColumnSelection getColumnSelection()
965   {
966     return colSel;
967   }
968
969   @Override
970   public void setColumnSelection(ColumnSelection colSel)
971   {
972     this.colSel = colSel;
973     if (colSel != null)
974     {
975       updateHiddenColumns();
976     }
977   }
978
979   /**
980    * 
981    * @return
982    */
983   @Override
984   public Map<SequenceI, SequenceCollectionI> getHiddenRepSequences()
985   {
986     return hiddenRepSequences;
987   }
988
989   @Override
990   public void setHiddenRepSequences(
991           Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
992   {
993     this.hiddenRepSequences = hiddenRepSequences;
994   }
995
996   @Override
997   public boolean hasHiddenColumns()
998   {
999     return colSel != null && colSel.hasHiddenColumns();
1000   }
1001
1002   public void updateHiddenColumns()
1003   {
1004     // this method doesn't really do anything now. But - it could, since a
1005     // column Selection could be in the process of modification
1006     // hasHiddenColumns = colSel.hasHiddenColumns();
1007   }
1008
1009   protected boolean hasHiddenRows = false;
1010
1011   @Override
1012   public boolean hasHiddenRows()
1013   {
1014     return hasHiddenRows;
1015   }
1016
1017   protected SequenceGroup selectionGroup;
1018
1019   public void setSequenceSetId(String newid)
1020   {
1021     if (sequenceSetID != null)
1022     {
1023       System.err
1024               .println("Warning - overwriting a sequenceSetId for a viewport!");
1025     }
1026     sequenceSetID = new String(newid);
1027   }
1028
1029   @Override
1030   public String getSequenceSetId()
1031   {
1032     if (sequenceSetID == null)
1033     {
1034       sequenceSetID = alignment.hashCode() + "";
1035     }
1036
1037     return sequenceSetID;
1038   }
1039
1040   /**
1041    * unique viewId for synchronizing state (e.g. with stored Jalview Project)
1042    * 
1043    */
1044   protected String viewId = null;
1045
1046   public String getViewId()
1047   {
1048     if (viewId == null)
1049     {
1050       viewId = this.getSequenceSetId() + "." + this.hashCode() + "";
1051     }
1052     return viewId;
1053   }
1054
1055   public void setIgnoreGapsConsensus(boolean b, AlignmentViewPanel ap)
1056   {
1057     ignoreGapsInConsensusCalculation = b;
1058     if (ap != null)
1059     {
1060       updateConsensus(ap);
1061       if (globalColourScheme != null)
1062       {
1063         globalColourScheme.setThreshold(globalColourScheme.getThreshold(),
1064                 ignoreGapsInConsensusCalculation);
1065       }
1066     }
1067
1068   }
1069
1070   private long sgrouphash = -1, colselhash = -1;
1071
1072   /**
1073    * checks current SelectionGroup against record of last hash value, and
1074    * updates record.
1075    * 
1076    * @param b
1077    *          update the record of last hash value
1078    * 
1079    * @return true if SelectionGroup changed since last call (when b is true)
1080    */
1081   public boolean isSelectionGroupChanged(boolean b)
1082   {
1083     int hc = (selectionGroup == null || selectionGroup.getSize() == 0) ? -1
1084             : selectionGroup.hashCode();
1085     if (hc != -1 && hc != sgrouphash)
1086     {
1087       if (b)
1088       {
1089         sgrouphash = hc;
1090       }
1091       return true;
1092     }
1093     return false;
1094   }
1095
1096   /**
1097    * checks current colsel against record of last hash value, and optionally
1098    * updates record.
1099    * 
1100    * @param b
1101    *          update the record of last hash value
1102    * @return true if colsel changed since last call (when b is true)
1103    */
1104   public boolean isColSelChanged(boolean b)
1105   {
1106     int hc = (colSel == null || colSel.size() == 0) ? -1 : colSel
1107             .hashCode();
1108     if (hc != -1 && hc != colselhash)
1109     {
1110       if (b)
1111       {
1112         colselhash = hc;
1113       }
1114       return true;
1115     }
1116     return false;
1117   }
1118
1119   @Override
1120   public boolean isIgnoreGapsConsensus()
1121   {
1122     return ignoreGapsInConsensusCalculation;
1123   }
1124
1125   // / property change stuff
1126
1127   // JBPNote Prolly only need this in the applet version.
1128   private final java.beans.PropertyChangeSupport changeSupport = new java.beans.PropertyChangeSupport(
1129           this);
1130
1131   protected boolean showConservation = true;
1132
1133   protected boolean showQuality = true;
1134
1135   protected boolean showConsensus = true;
1136
1137   private Map<SequenceI, Color> sequenceColours = new HashMap<SequenceI, Color>();
1138
1139   /**
1140    * Property change listener for changes in alignment
1141    * 
1142    * @param listener
1143    *          DOCUMENT ME!
1144    */
1145   public void addPropertyChangeListener(
1146           java.beans.PropertyChangeListener listener)
1147   {
1148     changeSupport.addPropertyChangeListener(listener);
1149   }
1150
1151   /**
1152    * DOCUMENT ME!
1153    * 
1154    * @param listener
1155    *          DOCUMENT ME!
1156    */
1157   public void removePropertyChangeListener(
1158           java.beans.PropertyChangeListener listener)
1159   {
1160     changeSupport.removePropertyChangeListener(listener);
1161   }
1162
1163   /**
1164    * Property change listener for changes in alignment
1165    * 
1166    * @param prop
1167    *          DOCUMENT ME!
1168    * @param oldvalue
1169    *          DOCUMENT ME!
1170    * @param newvalue
1171    *          DOCUMENT ME!
1172    */
1173   public void firePropertyChange(String prop, Object oldvalue,
1174           Object newvalue)
1175   {
1176     changeSupport.firePropertyChange(prop, oldvalue, newvalue);
1177   }
1178
1179   // common hide/show column stuff
1180
1181   public void hideSelectedColumns()
1182   {
1183     if (colSel.size() < 1)
1184     {
1185       return;
1186     }
1187
1188     colSel.hideSelectedColumns();
1189     setSelectionGroup(null);
1190
1191   }
1192
1193   public void hideColumns(int start, int end)
1194   {
1195     if (start == end)
1196     {
1197       colSel.hideColumns(start);
1198     }
1199     else
1200     {
1201       colSel.hideColumns(start, end);
1202     }
1203   }
1204
1205   public void showColumn(int col)
1206   {
1207     colSel.revealHiddenColumns(col);
1208
1209   }
1210
1211   public void showAllHiddenColumns()
1212   {
1213     colSel.revealAllHiddenColumns();
1214   }
1215
1216   // common hide/show seq stuff
1217   public void showAllHiddenSeqs()
1218   {
1219     if (alignment.getHiddenSequences().getSize() > 0)
1220     {
1221       if (selectionGroup == null)
1222       {
1223         selectionGroup = new SequenceGroup();
1224         selectionGroup.setEndRes(alignment.getWidth() - 1);
1225       }
1226       List<SequenceI> tmp = alignment.getHiddenSequences().showAll(
1227               hiddenRepSequences);
1228       for (SequenceI seq : tmp)
1229       {
1230         selectionGroup.addSequence(seq, false);
1231         setSequenceAnnotationsVisible(seq, true);
1232       }
1233
1234       hasHiddenRows = false;
1235       hiddenRepSequences = null;
1236
1237       firePropertyChange("alignment", null, alignment.getSequences());
1238       // used to set hasHiddenRows/hiddenRepSequences here, after the property
1239       // changed event
1240       sendSelection();
1241     }
1242   }
1243
1244   public void showSequence(int index)
1245   {
1246     List<SequenceI> tmp = alignment.getHiddenSequences().showSequence(
1247             index,
1248             hiddenRepSequences);
1249     if (tmp.size() > 0)
1250     {
1251       if (selectionGroup == null)
1252       {
1253         selectionGroup = new SequenceGroup();
1254         selectionGroup.setEndRes(alignment.getWidth() - 1);
1255       }
1256
1257       for (SequenceI seq : tmp)
1258       {
1259         selectionGroup.addSequence(seq, false);
1260         setSequenceAnnotationsVisible(seq, true);
1261       }
1262       // JBPNote: refactor: only update flag if we modified visiblity (used to
1263       // do this regardless)
1264       if (alignment.getHiddenSequences().getSize() < 1)
1265       {
1266         hasHiddenRows = false;
1267       }
1268       firePropertyChange("alignment", null, alignment.getSequences());
1269       sendSelection();
1270     }
1271   }
1272
1273   public void hideAllSelectedSeqs()
1274   {
1275     if (selectionGroup == null || selectionGroup.getSize() < 1)
1276     {
1277       return;
1278     }
1279
1280     SequenceI[] seqs = selectionGroup.getSequencesInOrder(alignment);
1281
1282     hideSequence(seqs);
1283
1284     setSelectionGroup(null);
1285   }
1286
1287   public void hideSequence(SequenceI[] seq)
1288   {
1289     if (seq != null)
1290     {
1291       for (int i = 0; i < seq.length; i++)
1292       {
1293         alignment.getHiddenSequences().hideSequence(seq[i]);
1294         setSequenceAnnotationsVisible(seq[i], false);
1295       }
1296       hasHiddenRows = true;
1297       firePropertyChange("alignment", null, alignment.getSequences());
1298     }
1299   }
1300
1301   /**
1302    * Set visibility for any annotations for the given sequence.
1303    * 
1304    * @param sequenceI
1305    */
1306   protected void setSequenceAnnotationsVisible(SequenceI sequenceI,
1307           boolean visible)
1308   {
1309     for (AlignmentAnnotation ann : alignment.getAlignmentAnnotation())
1310     {
1311       if (ann.sequenceRef == sequenceI)
1312       {
1313         ann.visible = visible;
1314       }
1315     }
1316   }
1317
1318   public void hideRepSequences(SequenceI repSequence, SequenceGroup sg)
1319   {
1320     int sSize = sg.getSize();
1321     if (sSize < 2)
1322     {
1323       return;
1324     }
1325
1326     if (hiddenRepSequences == null)
1327     {
1328       hiddenRepSequences = new Hashtable();
1329     }
1330
1331     hiddenRepSequences.put(repSequence, sg);
1332
1333     // Hide all sequences except the repSequence
1334     SequenceI[] seqs = new SequenceI[sSize - 1];
1335     int index = 0;
1336     for (int i = 0; i < sSize; i++)
1337     {
1338       if (sg.getSequenceAt(i) != repSequence)
1339       {
1340         if (index == sSize - 1)
1341         {
1342           return;
1343         }
1344
1345         seqs[index++] = sg.getSequenceAt(i);
1346       }
1347     }
1348     sg.setSeqrep(repSequence); // note: not done in 2.7applet
1349     sg.setHidereps(true); // note: not done in 2.7applet
1350     hideSequence(seqs);
1351
1352   }
1353
1354   public boolean isHiddenRepSequence(SequenceI seq)
1355   {
1356     return alignment.getSeqrep()==seq || (hiddenRepSequences != null
1357             && hiddenRepSequences.containsKey(seq));
1358   }
1359
1360   public SequenceGroup getRepresentedSequences(SequenceI seq)
1361   {
1362     return (SequenceGroup) (hiddenRepSequences == null ? null
1363             : hiddenRepSequences.get(seq));
1364   }
1365
1366   @Override
1367   public int adjustForHiddenSeqs(int alignmentIndex)
1368   {
1369     return alignment.getHiddenSequences().adjustForHiddenSeqs(
1370             alignmentIndex);
1371   }
1372
1373   @Override
1374   public void invertColumnSelection()
1375   {
1376     colSel.invertColumnSelection(0, alignment.getWidth());
1377   }
1378
1379
1380   @Override
1381   public SequenceI[] getSelectionAsNewSequence()
1382   {
1383     SequenceI[] sequences;
1384     // JBPNote: Need to test jalviewLite.getSelectedSequencesAsAlignmentFrom -
1385     // this was the only caller in the applet for this method
1386     // JBPNote: in applet, this method returned references to the alignment
1387     // sequences, and it did not honour the presence/absence of annotation
1388     // attached to the alignment (probably!)
1389     if (selectionGroup == null || selectionGroup.getSize() == 0)
1390     {
1391       sequences = alignment.getSequencesArray();
1392       AlignmentAnnotation[] annots = alignment.getAlignmentAnnotation();
1393       for (int i = 0; i < sequences.length; i++)
1394       {
1395         sequences[i] = new Sequence(sequences[i], annots); // construct new
1396         // sequence with
1397         // subset of visible
1398         // annotation
1399       }
1400     }
1401     else
1402     {
1403       sequences = selectionGroup.getSelectionAsNewSequences(alignment);
1404     }
1405
1406     return sequences;
1407   }
1408
1409
1410   @Override
1411   public SequenceI[] getSequenceSelection()
1412   {
1413     SequenceI[] sequences = null;
1414     if (selectionGroup != null)
1415     {
1416       sequences = selectionGroup.getSequencesInOrder(alignment);
1417     }
1418     if (sequences == null)
1419     {
1420       sequences = alignment.getSequencesArray();
1421     }
1422     return sequences;
1423   }
1424
1425
1426   @Override
1427   public CigarArray getViewAsCigars(
1428           boolean selectedRegionOnly)
1429   {
1430     return new CigarArray(alignment, colSel,
1431             (selectedRegionOnly ? selectionGroup : null));
1432   }
1433
1434
1435   @Override
1436   public jalview.datamodel.AlignmentView getAlignmentView(
1437           boolean selectedOnly)
1438   {
1439     return getAlignmentView(selectedOnly, false);
1440   }
1441
1442
1443   @Override
1444   public jalview.datamodel.AlignmentView getAlignmentView(
1445           boolean selectedOnly, boolean markGroups)
1446   {
1447     return new AlignmentView(alignment, colSel, selectionGroup,
1448             colSel != null && colSel.hasHiddenColumns(), selectedOnly,
1449             markGroups);
1450   }
1451
1452
1453   @Override
1454   public String[] getViewAsString(boolean selectedRegionOnly)
1455   {
1456     String[] selection = null;
1457     SequenceI[] seqs = null;
1458     int i, iSize;
1459     int start = 0, end = 0;
1460     if (selectedRegionOnly && selectionGroup != null)
1461     {
1462       iSize = selectionGroup.getSize();
1463       seqs = selectionGroup.getSequencesInOrder(alignment);
1464       start = selectionGroup.getStartRes();
1465       end = selectionGroup.getEndRes() + 1;
1466     }
1467     else
1468     {
1469       iSize = alignment.getHeight();
1470       seqs = alignment.getSequencesArray();
1471       end = alignment.getWidth();
1472     }
1473
1474     selection = new String[iSize];
1475     if (colSel != null && colSel.hasHiddenColumns())
1476     {
1477       selection = colSel.getVisibleSequenceStrings(start, end, seqs);
1478     }
1479     else
1480     {
1481       for (i = 0; i < iSize; i++)
1482       {
1483         selection[i] = seqs[i].getSequenceAsString(start, end);
1484       }
1485
1486     }
1487     return selection;
1488   }
1489
1490
1491   @Override
1492   public int[][] getVisibleRegionBoundaries(int min, int max)
1493   {
1494     Vector regions = new Vector();
1495     int start = min;
1496     int end = max;
1497
1498     do
1499     {
1500       if (colSel != null && colSel.hasHiddenColumns())
1501       {
1502         if (start == 0)
1503         {
1504           start = colSel.adjustForHiddenColumns(start);
1505         }
1506
1507         end = colSel.getHiddenBoundaryRight(start);
1508         if (start == end)
1509         {
1510           end = max;
1511         }
1512         if (end > max)
1513         {
1514           end = max;
1515         }
1516       }
1517
1518       regions.addElement(new int[]
1519       { start, end });
1520
1521       if (colSel != null && colSel.hasHiddenColumns())
1522       {
1523         start = colSel.adjustForHiddenColumns(end);
1524         start = colSel.getHiddenBoundaryLeft(start) + 1;
1525       }
1526     } while (end < max);
1527
1528     int[][] startEnd = new int[regions.size()][2];
1529
1530     regions.copyInto(startEnd);
1531
1532     return startEnd;
1533
1534   }
1535
1536   @Override
1537   public List<AlignmentAnnotation> getVisibleAlignmentAnnotation(boolean selectedOnly)
1538   {
1539     ArrayList<AlignmentAnnotation> ala = new ArrayList<AlignmentAnnotation>();
1540     AlignmentAnnotation[] aa;
1541     if ((aa=alignment.getAlignmentAnnotation())!=null)
1542     {
1543       for (AlignmentAnnotation annot:aa)
1544       {
1545         AlignmentAnnotation clone = new AlignmentAnnotation(annot);
1546         if (selectedOnly && selectionGroup!=null)
1547         {
1548           colSel.makeVisibleAnnotation(selectionGroup.getStartRes(), selectionGroup.getEndRes(),clone);
1549         } else {
1550           colSel.makeVisibleAnnotation(clone);
1551         }
1552         ala.add(clone);
1553       }
1554     }
1555     return ala;
1556   }
1557
1558
1559   @Override
1560   public boolean isPadGaps()
1561   {
1562     return padGaps;
1563   }
1564
1565
1566   @Override
1567   public void setPadGaps(boolean padGaps)
1568   {
1569     this.padGaps = padGaps;
1570   }
1571
1572   /**
1573    * apply any post-edit constraints and trigger any calculations needed after
1574    * an edit has been performed on the alignment
1575    * 
1576    * @param ap
1577    */
1578   @Override
1579   public void alignmentChanged(AlignmentViewPanel ap)
1580   {
1581     if (isPadGaps())
1582     {
1583       alignment.padGaps();
1584     }
1585     if (autoCalculateConsensus)
1586     {
1587       updateConsensus(ap);
1588     }
1589     if (hconsensus != null && autoCalculateConsensus)
1590     {
1591       updateConservation(ap);
1592     }
1593     if (autoCalculateStrucConsensus)
1594     {
1595       updateStrucConsensus(ap);
1596     }
1597
1598     // Reset endRes of groups if beyond alignment width
1599     int alWidth = alignment.getWidth();
1600     List<SequenceGroup> groups = alignment.getGroups();
1601     if (groups != null)
1602     {
1603       for (SequenceGroup sg : groups)
1604       {
1605         if (sg.getEndRes() > alWidth)
1606         {
1607           sg.setEndRes(alWidth - 1);
1608         }
1609       }
1610     }
1611
1612     if (selectionGroup != null && selectionGroup.getEndRes() > alWidth)
1613     {
1614       selectionGroup.setEndRes(alWidth - 1);
1615     }
1616
1617     resetAllColourSchemes();
1618     calculator.restartWorkers();
1619     // alignment.adjustSequenceAnnotations();
1620   }
1621
1622   /**
1623    * reset scope and do calculations for all applied colourschemes on alignment
1624    */
1625   void resetAllColourSchemes()
1626   {
1627     ColourSchemeI cs = globalColourScheme;
1628     if (cs != null)
1629     {
1630       cs.alignmentChanged(alignment, hiddenRepSequences);
1631
1632       cs.setConsensus(hconsensus);
1633       if (cs.conservationApplied())
1634       {
1635         cs.setConservation(Conservation.calculateConservation("All",
1636                 ResidueProperties.propHash, 3, alignment.getSequences(), 0,
1637                 alignment.getWidth(), false, getConsPercGaps(), false));
1638       }
1639     }
1640
1641     for (SequenceGroup sg : alignment.getGroups())
1642     {
1643       if (sg.cs != null)
1644       {
1645         sg.cs.alignmentChanged(sg, hiddenRepSequences);
1646       }
1647       sg.recalcConservation();
1648     }
1649   }
1650
1651   protected void initAutoAnnotation()
1652   {
1653     // TODO: add menu option action that nulls or creates consensus object
1654     // depending on if the user wants to see the annotation or not in a
1655     // specific alignment
1656
1657     if (hconsensus == null && !isDataset)
1658     {
1659       if (!alignment.isNucleotide())
1660       {
1661         initConservation();
1662         initQuality();
1663       }
1664       else
1665       {
1666         initRNAStructure();
1667       }
1668       initConsensus();
1669     }
1670   }
1671
1672   private void initConsensus()
1673   {
1674
1675     consensus = new AlignmentAnnotation("Consensus", "PID",
1676             new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
1677     consensus.hasText = true;
1678     consensus.autoCalculated = true;
1679
1680     if (showConsensus)
1681     {
1682       alignment.addAnnotation(consensus);
1683     }
1684   }
1685
1686   private void initConservation()
1687   {
1688     if (showConservation)
1689     {
1690       if (conservation == null)
1691       {
1692         conservation = new AlignmentAnnotation("Conservation",
1693                 "Conservation of total alignment less than "
1694                         + getConsPercGaps() + "% gaps", new Annotation[1],
1695                 0f, 11f, AlignmentAnnotation.BAR_GRAPH);
1696         conservation.hasText = true;
1697         conservation.autoCalculated = true;
1698         alignment.addAnnotation(conservation);
1699       }
1700     }
1701   }
1702
1703   private void initQuality()
1704   {
1705     if (showQuality)
1706     {
1707       if (quality == null)
1708       {
1709         quality = new AlignmentAnnotation("Quality",
1710                 "Alignment Quality based on Blosum62 scores",
1711                 new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH);
1712         quality.hasText = true;
1713         quality.autoCalculated = true;
1714         alignment.addAnnotation(quality);
1715       }
1716     }
1717   }
1718
1719   private void initRNAStructure()
1720   {
1721     if (alignment.hasRNAStructure() && strucConsensus == null)
1722     {
1723       strucConsensus = new AlignmentAnnotation("StrucConsensus", "PID",
1724               new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
1725       strucConsensus.hasText = true;
1726       strucConsensus.autoCalculated = true;
1727
1728       if (showConsensus)
1729       {
1730         alignment.addAnnotation(strucConsensus);
1731       }
1732     }
1733   }
1734
1735   /*
1736    * (non-Javadoc)
1737    * 
1738    * @see jalview.api.AlignViewportI#calcPanelHeight()
1739    */
1740   @Override
1741   public int calcPanelHeight()
1742   {
1743     // setHeight of panels
1744     AlignmentAnnotation[] aa = getAlignment().getAlignmentAnnotation();
1745     int height = 0;
1746     int charHeight = getCharHeight();
1747     if (aa != null)
1748     {
1749       BitSet graphgrp = new BitSet();
1750       for (int i = 0; i < aa.length; i++)
1751       {
1752         if (aa[i] == null)
1753         {
1754           System.err.println("Null annotation row: ignoring.");
1755           continue;
1756         }
1757         if (!aa[i].visible)
1758         {
1759           continue;
1760         }
1761         if (aa[i].graphGroup > -1)
1762         {
1763           if (graphgrp.get(aa[i].graphGroup))
1764           {
1765             continue;
1766           }
1767           else
1768           {
1769             graphgrp.set(aa[i].graphGroup);
1770           }
1771         }
1772         aa[i].height = 0;
1773
1774         if (aa[i].hasText)
1775         {
1776           aa[i].height += charHeight;
1777         }
1778
1779         if (aa[i].hasIcons)
1780         {
1781           aa[i].height += 16;
1782         }
1783
1784         if (aa[i].graph > 0)
1785         {
1786           aa[i].height += aa[i].graphHeight;
1787         }
1788
1789         if (aa[i].height == 0)
1790         {
1791           aa[i].height = 20;
1792         }
1793
1794         height += aa[i].height;
1795       }
1796     }
1797     if (height == 0)
1798     {
1799       // set minimum
1800       height = 20;
1801     }
1802     return height;
1803   }
1804
1805   @Override
1806   public void updateGroupAnnotationSettings(boolean applyGlobalSettings,
1807           boolean preserveNewGroupSettings)
1808   {
1809     boolean updateCalcs = false;
1810     boolean conv = isShowGroupConservation();
1811     boolean cons = isShowGroupConsensus();
1812     boolean showprf = isShowSequenceLogo();
1813     boolean showConsHist = isShowConsensusHistogram();
1814     boolean normLogo = isNormaliseSequenceLogo();
1815
1816     /**
1817      * TODO reorder the annotation rows according to group/sequence ordering on
1818      * alignment
1819      */
1820     boolean sortg = true;
1821
1822     // remove old automatic annotation
1823     // add any new annotation
1824
1825     // intersect alignment annotation with alignment groups
1826
1827     AlignmentAnnotation[] aan = alignment.getAlignmentAnnotation();
1828     List<SequenceGroup> oldrfs = new ArrayList<SequenceGroup>();
1829     if (aan != null)
1830     {
1831       for (int an = 0; an < aan.length; an++)
1832       {
1833         if (aan[an].autoCalculated && aan[an].groupRef != null)
1834         {
1835           oldrfs.add(aan[an].groupRef);
1836           alignment.deleteAnnotation(aan[an], false);
1837         }
1838       }
1839     }
1840     if (alignment.getGroups() != null)
1841     {
1842       for (SequenceGroup sg : alignment.getGroups())
1843       {
1844         updateCalcs = false;
1845         if (applyGlobalSettings
1846                 || (!preserveNewGroupSettings && !oldrfs.contains(sg)))
1847         {
1848           // set defaults for this group's conservation/consensus
1849           sg.setshowSequenceLogo(showprf);
1850           sg.setShowConsensusHistogram(showConsHist);
1851           sg.setNormaliseSequenceLogo(normLogo);
1852         }
1853         if (conv)
1854         {
1855           updateCalcs = true;
1856           alignment.addAnnotation(sg.getConservationRow(), 0);
1857         }
1858         if (cons)
1859         {
1860           updateCalcs = true;
1861           alignment.addAnnotation(sg.getConsensus(), 0);
1862         }
1863         // refresh the annotation rows
1864         if (updateCalcs)
1865         {
1866           sg.recalcConservation();
1867         }
1868       }
1869     }
1870     oldrfs.clear();
1871   }
1872   @Override
1873   public boolean isDisplayReferenceSeq()
1874   {
1875     return alignment.hasSeqrep() && viewStyle.isDisplayReferenceSeq();
1876   }
1877
1878   @Override
1879   public void setDisplayReferenceSeq(boolean displayReferenceSeq)
1880   {
1881     viewStyle.setDisplayReferenceSeq(displayReferenceSeq);
1882   }
1883
1884   @Override
1885   public boolean isColourByReferenceSeq()
1886   {
1887     return alignment.hasSeqrep() && viewStyle.isColourByReferenceSeq();
1888   }
1889
1890   @Override
1891   public Color getSequenceColour(SequenceI seq)
1892   {
1893     Color sqc = sequenceColours.get(seq);
1894     return (sqc == null ? Color.white : sqc);
1895   }
1896
1897   @Override
1898   public void setSequenceColour(SequenceI seq, Color col)
1899   {
1900     if (col == null)
1901     {
1902       sequenceColours.remove(seq);
1903     }
1904     else
1905     {
1906       sequenceColours.put(seq, col);
1907     }
1908   }
1909
1910   @Override
1911   public void updateSequenceIdColours()
1912   {
1913     for (SequenceGroup sg : alignment.getGroups())
1914     {
1915       if (sg.idColour != null)
1916       {
1917         for (SequenceI s : sg.getSequences(getHiddenRepSequences()))
1918         {
1919           sequenceColours.put(s, sg.idColour);
1920         }
1921       }
1922     }
1923   }
1924
1925   @Override
1926   public void clearSequenceColours()
1927   {
1928     sequenceColours.clear();
1929   };
1930
1931   @Override
1932   public AlignViewportI getCodingComplement()
1933   {
1934     return this.codingComplement;
1935   }
1936
1937   /**
1938    * Set this as the (cDna/protein) complement of the given viewport. Also
1939    * ensures the reverse relationship is set on the given viewport.
1940    */
1941   @Override
1942   public void setCodingComplement(AlignViewportI av)
1943   {
1944     if (this == av)
1945     {
1946       System.err.println("Ignoring recursive setCodingComplement request");
1947     }
1948     else
1949     {
1950       this.codingComplement = av;
1951       // avoid infinite recursion!
1952       if (av.getCodingComplement() != this)
1953       {
1954         av.setCodingComplement(this);
1955       }
1956     }
1957   }
1958
1959   @Override
1960   public boolean isNucleotide()
1961   {
1962     return getAlignment() == null ? false : getAlignment().isNucleotide();
1963   }
1964
1965   FeaturesDisplayedI featuresDisplayed = null;
1966
1967   @Override
1968   public FeaturesDisplayedI getFeaturesDisplayed()
1969   {
1970     return featuresDisplayed;
1971   }
1972
1973   @Override
1974   public void setFeaturesDisplayed(FeaturesDisplayedI featuresDisplayedI)
1975   {
1976     featuresDisplayed = featuresDisplayedI;
1977   }
1978
1979   @Override
1980   public boolean areFeaturesDisplayed()
1981   {
1982     return featuresDisplayed != null && featuresDisplayed.getRegisterdFeaturesCount()>0;
1983   }
1984
1985   /**
1986    * set the flag
1987    * 
1988    * @param b
1989    *          features are displayed if true
1990    */
1991   @Override
1992   public void setShowSequenceFeatures(boolean b)
1993   {
1994     viewStyle.setShowSequenceFeatures(b);
1995   }
1996   @Override
1997   public boolean isShowSequenceFeatures()
1998   {
1999     return viewStyle.isShowSequenceFeatures();
2000   }
2001
2002   @Override
2003   public void setShowSequenceFeaturesHeight(boolean selected)
2004   {
2005     viewStyle.setShowSeqFeaturesHeight(selected);
2006   }
2007
2008   @Override
2009   public boolean isShowSequenceFeaturesHeight()
2010   {
2011     return viewStyle.isShowSequenceFeaturesHeight();
2012   }
2013
2014
2015
2016   @Override
2017   public void setShowAnnotation(boolean b)
2018   {
2019     viewStyle.setShowAnnotation(b);
2020   }
2021
2022   @Override
2023   public boolean isShowAnnotation()
2024   {
2025     return viewStyle.isShowAnnotation();
2026   }
2027
2028   @Override
2029   public boolean isRightAlignIds()
2030   {
2031     return viewStyle.isRightAlignIds();
2032   }
2033
2034   @Override
2035   public void setRightAlignIds(boolean rightAlignIds)
2036   {
2037     viewStyle.setRightAlignIds(rightAlignIds);
2038   }
2039
2040   @Override
2041   public boolean getConservationSelected()
2042   {
2043     return viewStyle.getConservationSelected();
2044   }
2045
2046   @Override
2047   public void setShowBoxes(boolean state)
2048   {
2049     viewStyle.setShowBoxes(state);
2050   }
2051
2052   /**
2053    * @return
2054    * @see jalview.api.ViewStyleI#getTextColour()
2055    */
2056   public Color getTextColour()
2057   {
2058     return viewStyle.getTextColour();
2059   }
2060
2061   /**
2062    * @return
2063    * @see jalview.api.ViewStyleI#getTextColour2()
2064    */
2065   public Color getTextColour2()
2066   {
2067     return viewStyle.getTextColour2();
2068   }
2069
2070   /**
2071    * @return
2072    * @see jalview.api.ViewStyleI#getThresholdTextColour()
2073    */
2074   public int getThresholdTextColour()
2075   {
2076     return viewStyle.getThresholdTextColour();
2077   }
2078
2079   /**
2080    * @return
2081    * @see jalview.api.ViewStyleI#isConservationColourSelected()
2082    */
2083   public boolean isConservationColourSelected()
2084   {
2085     return viewStyle.isConservationColourSelected();
2086   }
2087
2088   /**
2089    * @return
2090    * @see jalview.api.ViewStyleI#isRenderGaps()
2091    */
2092   public boolean isRenderGaps()
2093   {
2094     return viewStyle.isRenderGaps();
2095   }
2096
2097   /**
2098    * @return
2099    * @see jalview.api.ViewStyleI#isShowColourText()
2100    */
2101   public boolean isShowColourText()
2102   {
2103     return viewStyle.isShowColourText();
2104   }
2105   /**
2106    * @return
2107    * @see jalview.api.ViewStyleI#isShowSeqFeaturesHeight()
2108    */
2109   public boolean isShowSeqFeaturesHeight()
2110   {
2111     return viewStyle.isShowSeqFeaturesHeight();
2112   }
2113
2114   /**
2115    * @param conservationColourSelected
2116    * @see jalview.api.ViewStyleI#setConservationColourSelected(boolean)
2117    */
2118   public void setConservationColourSelected(
2119           boolean conservationColourSelected)
2120   {
2121     viewStyle.setConservationColourSelected(conservationColourSelected);
2122   }
2123
2124   /**
2125    * @param showColourText
2126    * @see jalview.api.ViewStyleI#setShowColourText(boolean)
2127    */
2128   public void setShowColourText(boolean showColourText)
2129   {
2130     viewStyle.setShowColourText(showColourText);
2131   }
2132
2133   /**
2134    * @param textColour
2135    * @see jalview.api.ViewStyleI#setTextColour(java.awt.Color)
2136    */
2137   public void setTextColour(Color textColour)
2138   {
2139     viewStyle.setTextColour(textColour);
2140   }
2141
2142   /**
2143    * @param thresholdTextColour
2144    * @see jalview.api.ViewStyleI#setThresholdTextColour(int)
2145    */
2146   public void setThresholdTextColour(int thresholdTextColour)
2147   {
2148     viewStyle.setThresholdTextColour(thresholdTextColour);
2149   }
2150
2151   /**
2152    * @param textColour2
2153    * @see jalview.api.ViewStyleI#setTextColour2(java.awt.Color)
2154    */
2155   public void setTextColour2(Color textColour2)
2156   {
2157     viewStyle.setTextColour2(textColour2);
2158   }
2159
2160   @Override
2161   public ViewStyleI getViewStyle()
2162   {
2163     return new ViewStyle(viewStyle);
2164   }
2165
2166   @Override
2167   public void setViewStyle(ViewStyleI settingsForView)
2168   {
2169     viewStyle = new ViewStyle(settingsForView);
2170   }
2171
2172   @Override
2173   public boolean sameStyle(ViewStyleI them)
2174   {
2175     return viewStyle.sameStyle(them);
2176   }
2177
2178   /**
2179    * @return
2180    * @see jalview.api.ViewStyleI#getIdWidth()
2181    */
2182   public int getIdWidth()
2183   {
2184     return viewStyle.getIdWidth();
2185   }
2186
2187   /**
2188    * @param i
2189    * @see jalview.api.ViewStyleI#setIdWidth(int)
2190    */
2191   public void setIdWidth(int i)
2192   {
2193     viewStyle.setIdWidth(i);
2194   }
2195
2196   /**
2197    * @return
2198    * @see jalview.api.ViewStyleI#isCentreColumnLabels()
2199    */
2200   public boolean isCentreColumnLabels()
2201   {
2202     return viewStyle.isCentreColumnLabels();
2203   }
2204
2205   /**
2206    * @param centreColumnLabels
2207    * @see jalview.api.ViewStyleI#setCentreColumnLabels(boolean)
2208    */
2209   public void setCentreColumnLabels(boolean centreColumnLabels)
2210   {
2211     viewStyle.setCentreColumnLabels(centreColumnLabels);
2212   }
2213
2214   /**
2215    * @param showdbrefs
2216    * @see jalview.api.ViewStyleI#setShowDBRefs(boolean)
2217    */
2218   public void setShowDBRefs(boolean showdbrefs)
2219   {
2220     viewStyle.setShowDBRefs(showdbrefs);
2221   }
2222
2223   /**
2224    * @return
2225    * @see jalview.api.ViewStyleI#isShowDBRefs()
2226    */
2227   public boolean isShowDBRefs()
2228   {
2229     return viewStyle.isShowDBRefs();
2230   }
2231
2232   /**
2233    * @return
2234    * @see jalview.api.ViewStyleI#isShowNPFeats()
2235    */
2236   public boolean isShowNPFeats()
2237   {
2238     return viewStyle.isShowNPFeats();
2239   }
2240
2241   /**
2242    * @param shownpfeats
2243    * @see jalview.api.ViewStyleI#setShowNPFeats(boolean)
2244    */
2245   public void setShowNPFeats(boolean shownpfeats)
2246   {
2247     viewStyle.setShowNPFeats(shownpfeats);
2248   }
2249 }