Clover icon

Coverage Report

  1. Project Clover database Wed Nov 12 2025 13:01:44 GMT
  2. Package jalview.viewmodel

File AlignmentViewport.java

 

Coverage histogram

../../img/srcFileCovDistChart8.png
22% of files have more coverage

Code metrics

356
808
258
1
3,542
2,430
486
0.6
3.13
258
1.88

Classes

Class Line # Actions
AlignmentViewport 91 808 486
0.7651195576.5%
 

Contributing tests

This file is covered by 360 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ 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 java.awt.Color;
24    import java.beans.PropertyChangeSupport;
25    import java.util.ArrayDeque;
26    import java.util.ArrayList;
27    import java.util.BitSet;
28    import java.util.Deque;
29    import java.util.HashMap;
30    import java.util.Hashtable;
31    import java.util.Iterator;
32    import java.util.List;
33    import java.util.Map;
34   
35    import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
36    import jalview.analysis.AlignmentUtils;
37    import jalview.analysis.Conservation;
38    import jalview.analysis.TreeModel;
39    import jalview.api.AlignCalcManagerI;
40    import jalview.api.AlignExportSettingsI;
41    import jalview.api.AlignViewportI;
42    import jalview.api.AlignmentViewPanel;
43    import jalview.api.FeaturesDisplayedI;
44    import jalview.api.ViewStyleI;
45    import jalview.bin.Console;
46    import jalview.commands.CommandI;
47    import jalview.datamodel.AlignedCodonFrame;
48    import jalview.datamodel.AlignmentAnnotation;
49    import jalview.datamodel.AlignmentExportData;
50    import jalview.datamodel.AlignmentI;
51    import jalview.datamodel.AlignmentView;
52    import jalview.datamodel.Annotation;
53    import jalview.datamodel.ColumnSelection;
54    import jalview.datamodel.ContactListI;
55    import jalview.datamodel.ContactMatrixI;
56    import jalview.datamodel.HiddenColumns;
57    import jalview.datamodel.HiddenSequences;
58    import jalview.datamodel.ProfilesI;
59    import jalview.datamodel.SearchResultsI;
60    import jalview.datamodel.Sequence;
61    import jalview.datamodel.SequenceCollectionI;
62    import jalview.datamodel.SequenceGroup;
63    import jalview.datamodel.SequenceI;
64    import jalview.gui.QuitHandler;
65    import jalview.project.Jalview2XML;
66    import jalview.renderer.ResidueShader;
67    import jalview.renderer.ResidueShaderI;
68    import jalview.schemes.ColourSchemeI;
69    import jalview.structure.CommandListener;
70    import jalview.structure.StructureSelectionManager;
71    import jalview.structure.VamsasSource;
72    import jalview.util.Comparison;
73    import jalview.util.Constants;
74    import jalview.util.MapList;
75    import jalview.util.MappingUtils;
76    import jalview.util.MessageManager;
77    import jalview.viewmodel.styles.ViewStyle;
78    import jalview.workers.AlignCalcManager;
79    import jalview.workers.ComplementConsensusThread;
80    import jalview.workers.ConsensusThread;
81    import jalview.workers.SecondaryStructureConsensusThread;
82    import jalview.workers.StrucConsensusThread;
83   
84    /**
85    * base class holding visualization and analysis attributes and common logic for
86    * an active alignment view displayed in the GUI
87    *
88    * @author jimp
89    *
90    */
 
91    public abstract class AlignmentViewport
92    implements AlignViewportI, CommandListener, VamsasSource
93    {
94    protected ViewportRanges ranges;
95   
96    protected ViewStyleI viewStyle = new ViewStyle();
97   
98    /**
99    * A viewport that hosts the cDna view of this (protein), or vice versa (if
100    * set).
101    */
102    AlignViewportI codingComplement = null;
103   
104    FeaturesDisplayedI featuresDisplayed = null;
105   
106    protected Deque<CommandI> historyList = new ArrayDeque<>();
107   
108    protected Deque<CommandI> redoList = new ArrayDeque<>();
109   
110    /**
111    * used to determine if quit should be confirmed
112    */
113    private boolean savedUpToDate = false;
114   
115    /**
116    * alignment displayed in the viewport. Please use get/setter
117    */
118    protected AlignmentI alignment;
119   
 
120  535 toggle public AlignmentViewport(AlignmentI al)
121    {
122  535 setAlignment(al);
123  535 ranges = new ViewportRanges(al);
124    }
125   
126    /**
127    * @param name
128    * @see jalview.api.ViewStyleI#setFontName(java.lang.String)
129    */
 
130  0 toggle @Override
131    public void setFontName(String name)
132    {
133  0 viewStyle.setFontName(name);
134    }
135   
136    /**
137    * @param style
138    * @see jalview.api.ViewStyleI#setFontStyle(int)
139    */
 
140  0 toggle @Override
141    public void setFontStyle(int style)
142    {
143  0 viewStyle.setFontStyle(style);
144    }
145   
146    /**
147    * @param size
148    * @see jalview.api.ViewStyleI#setFontSize(int)
149    */
 
150  0 toggle @Override
151    public void setFontSize(int size)
152    {
153  0 viewStyle.setFontSize(size);
154    }
155   
156    /**
157    * @return
158    * @see jalview.api.ViewStyleI#getFontStyle()
159    */
 
160  0 toggle @Override
161    public int getFontStyle()
162    {
163  0 return viewStyle.getFontStyle();
164    }
165   
166    /**
167    * @return
168    * @see jalview.api.ViewStyleI#getFontName()
169    */
 
170  0 toggle @Override
171    public String getFontName()
172    {
173  0 return viewStyle.getFontName();
174    }
175   
176    /**
177    * @return
178    * @see jalview.api.ViewStyleI#getFontSize()
179    */
 
180  0 toggle @Override
181    public int getFontSize()
182    {
183  0 return viewStyle.getFontSize();
184    }
185   
186    /**
187    * @param upperCasebold
188    * @see jalview.api.ViewStyleI#setUpperCasebold(boolean)
189    */
 
190  0 toggle @Override
191    public void setUpperCasebold(boolean upperCasebold)
192    {
193  0 viewStyle.setUpperCasebold(upperCasebold);
194    }
195   
196    /**
197    * @return
198    * @see jalview.api.ViewStyleI#isUpperCasebold()
199    */
 
200  0 toggle @Override
201    public boolean isUpperCasebold()
202    {
203  0 return viewStyle.isUpperCasebold();
204    }
205   
206    /**
207    * @return
208    * @see jalview.api.ViewStyleI#isSeqNameItalics()
209    */
 
210  3055 toggle @Override
211    public boolean isSeqNameItalics()
212    {
213  3055 return viewStyle.isSeqNameItalics();
214    }
215   
216    /**
217    * @param colourByReferenceSeq
218    * @see jalview.api.ViewStyleI#setColourByReferenceSeq(boolean)
219    */
 
220  10 toggle @Override
221    public void setColourByReferenceSeq(boolean colourByReferenceSeq)
222    {
223  10 viewStyle.setColourByReferenceSeq(colourByReferenceSeq);
224    }
225   
226    /**
227    * @param b
228    * @see jalview.api.ViewStyleI#setColourAppliesToAllGroups(boolean)
229    */
 
230  728 toggle @Override
231    public void setColourAppliesToAllGroups(boolean b)
232    {
233  728 viewStyle.setColourAppliesToAllGroups(b);
234    }
235   
236    /**
237    * @return
238    * @see jalview.api.ViewStyleI#getColourAppliesToAllGroups()
239    */
 
240  1008 toggle @Override
241    public boolean getColourAppliesToAllGroups()
242    {
243  1008 return viewStyle.getColourAppliesToAllGroups();
244    }
245   
246    /**
247    * @return
248    * @see jalview.api.ViewStyleI#getAbovePIDThreshold()
249    */
 
250  915 toggle @Override
251    public boolean getAbovePIDThreshold()
252    {
253  915 return viewStyle.getAbovePIDThreshold();
254    }
255   
 
256  915 toggle @Override
257    public boolean getByConsensusSecondaryStructureSelected()
258    {
259  915 return viewStyle.getByConsensusSecondaryStructureSelected();
260    }
261   
 
262  89 toggle public void setShowStructureProvider(boolean b)
263    {
264  89 viewStyle.setShowStructureProvider(b);
265    }
266   
 
267  6924 toggle public boolean isShowStructureProvider()
268    {
269  6924 return viewStyle.isShowStructureProvider();
270    }
271   
272    /**
273    * @param inc
274    * @see jalview.api.ViewStyleI#setIncrement(int)
275    */
 
276  89 toggle @Override
277    public void setIncrement(int inc)
278    {
279  89 viewStyle.setIncrement(inc);
280    }
281   
282    /**
283    * @return
284    * @see jalview.api.ViewStyleI#getIncrement()
285    */
 
286  0 toggle @Override
287    public int getIncrement()
288    {
289  0 return viewStyle.getIncrement();
290    }
291   
292    /**
293    * @param inc
294    * @see jalview.api.ViewStyleI#setConsensusSecondaryStructureThreshold(int)
295    */
 
296  89 toggle @Override
297    public void setConsensusSecondaryStructureThreshold(int val)
298    {
299  89 viewStyle.setConsensusSecondaryStructureThreshold(val);
300    }
301   
302    /**
303    * @return
304    * @see jalview.api.ViewStyleI#getConsensusSecondaryStructureThreshold()
305    */
 
306  0 toggle @Override
307    public int getConsensusSecondaryStructureThreshold()
308    {
309  0 return viewStyle.getConsensusSecondaryStructureThreshold();
310    }
311   
312    /**
313    * @param b
314    * @see jalview.api.ViewStyleI#setConservationSelected(boolean)
315    */
 
316  97 toggle @Override
317    public void setConservationSelected(boolean b)
318    {
319  97 viewStyle.setConservationSelected(b);
320    }
321   
322    /**
323    * @param show
324    * @see jalview.api.ViewStyleI#setShowHiddenMarkers(boolean)
325    */
 
326  0 toggle @Override
327    public void setShowHiddenMarkers(boolean show)
328    {
329  0 viewStyle.setShowHiddenMarkers(show);
330    }
331   
332    /**
333    * @return
334    * @see jalview.api.ViewStyleI#getShowHiddenMarkers()
335    */
 
336  4644 toggle @Override
337    public boolean getShowHiddenMarkers()
338    {
339  4644 return viewStyle.getShowHiddenMarkers();
340    }
341   
342    /**
343    * @param b
344    * @see jalview.api.ViewStyleI#setScaleRightWrapped(boolean)
345    */
 
346  9 toggle @Override
347    public void setScaleRightWrapped(boolean b)
348    {
349  9 viewStyle.setScaleRightWrapped(b);
350    }
351   
352    /**
353    * @param b
354    * @see jalview.api.ViewStyleI#setScaleLeftWrapped(boolean)
355    */
 
356  11 toggle @Override
357    public void setScaleLeftWrapped(boolean b)
358    {
359  11 viewStyle.setScaleLeftWrapped(b);
360    }
361   
362    /**
363    * @param b
364    * @see jalview.api.ViewStyleI#setScaleAboveWrapped(boolean)
365    */
 
366  9 toggle @Override
367    public void setScaleAboveWrapped(boolean b)
368    {
369  9 viewStyle.setScaleAboveWrapped(b);
370    }
371   
372    /**
373    * @return
374    * @see jalview.api.ViewStyleI#getScaleLeftWrapped()
375    */
 
376  1133 toggle @Override
377    public boolean getScaleLeftWrapped()
378    {
379  1133 return viewStyle.getScaleLeftWrapped();
380    }
381   
382    /**
383    * @return
384    * @see jalview.api.ViewStyleI#getScaleAboveWrapped()
385    */
 
386  781 toggle @Override
387    public boolean getScaleAboveWrapped()
388    {
389  781 return viewStyle.getScaleAboveWrapped();
390    }
391   
392    /**
393    * @return
394    * @see jalview.api.ViewStyleI#getScaleRightWrapped()
395    */
 
396  1818 toggle @Override
397    public boolean getScaleRightWrapped()
398    {
399  1818 return viewStyle.getScaleRightWrapped();
400    }
401   
402    /**
403    * @param b
404    * @see jalview.api.ViewStyleI#setAbovePIDThreshold(boolean)
405    */
 
406  98 toggle @Override
407    public void setAbovePIDThreshold(boolean b)
408    {
409  98 viewStyle.setAbovePIDThreshold(b);
410    }
411   
 
412  89 toggle @Override
413    public void setByConsensusSecondaryStructureSelected(boolean b)
414    {
415  89 viewStyle.setByConsensusSecondaryStructureSelected(b);
416    }
417   
418    /**
419    * @param thresh
420    * @see jalview.api.ViewStyleI#setThreshold(int)
421    */
 
422  110 toggle @Override
423    public void setThreshold(int thresh)
424    {
425  110 viewStyle.setThreshold(thresh);
426    }
427   
428    /**
429    * @return
430    * @see jalview.api.ViewStyleI#getThreshold()
431    */
 
432  0 toggle @Override
433    public int getThreshold()
434    {
435  0 return viewStyle.getThreshold();
436    }
437   
438    /**
439    * @return
440    * @see jalview.api.ViewStyleI#getShowJVSuffix()
441    */
 
442  48230 toggle @Override
443    public boolean getShowJVSuffix()
444    {
445  48230 return viewStyle.getShowJVSuffix();
446    }
447   
448    /**
449    * @param b
450    * @see jalview.api.ViewStyleI#setShowJVSuffix(boolean)
451    */
 
452  90 toggle @Override
453    public void setShowJVSuffix(boolean b)
454    {
455  90 viewStyle.setShowJVSuffix(b);
456    }
457   
458    /**
459    * @param state
460    * @see jalview.api.ViewStyleI#setWrapAlignment(boolean)
461    */
 
462  101 toggle @Override
463    public void setWrapAlignment(boolean state)
464    {
465  101 viewStyle.setWrapAlignment(state);
466  101 ranges.setWrappedMode(state);
467    }
468   
469    /**
470    * @param state
471    * @see jalview.api.ViewStyleI#setShowText(boolean)
472    */
 
473  89 toggle @Override
474    public void setShowText(boolean state)
475    {
476  89 viewStyle.setShowText(state);
477    }
478   
479    /**
480    * @param state
481    * @see jalview.api.ViewStyleI#setRenderGaps(boolean)
482    */
 
483  89 toggle @Override
484    public void setRenderGaps(boolean state)
485    {
486  89 viewStyle.setRenderGaps(state);
487    }
488   
489    /**
490    * @return
491    * @see jalview.api.ViewStyleI#getColourText()
492    */
 
493  458140 toggle @Override
494    public boolean getColourText()
495    {
496  458140 return viewStyle.getColourText();
497    }
498   
499    /**
500    * @param state
501    * @see jalview.api.ViewStyleI#setColourText(boolean)
502    */
 
503  89 toggle @Override
504    public void setColourText(boolean state)
505    {
506  89 viewStyle.setColourText(state);
507    }
508   
509    /**
510    * @return
511    * @see jalview.api.ViewStyleI#getWrapAlignment()
512    */
 
513  31480 toggle @Override
514    public boolean getWrapAlignment()
515    {
516  31480 return viewStyle.getWrapAlignment();
517    }
518   
519    /**
520    * @return
521    * @see jalview.api.ViewStyleI#getShowText()
522    */
 
523  458846 toggle @Override
524    public boolean getShowText()
525    {
526  458846 return viewStyle.getShowText();
527    }
528   
529    /**
530    * @return
531    * @see jalview.api.ViewStyleI#getWrappedWidth()
532    */
 
533  2 toggle @Override
534    public int getWrappedWidth()
535    {
536  2 return viewStyle.getWrappedWidth();
537    }
538   
539    /**
540    * @param w
541    * @see jalview.api.ViewStyleI#setWrappedWidth(int)
542    */
 
543  710 toggle @Override
544    public void setWrappedWidth(int w)
545    {
546  710 viewStyle.setWrappedWidth(w);
547    }
548   
549    /**
550    * @return
551    * @see jalview.api.ViewStyleI#getCharHeight()
552    */
 
553  105068 toggle @Override
554    public int getCharHeight()
555    {
556  105068 return viewStyle.getCharHeight();
557    }
558   
559    /**
560    * @param h
561    * @see jalview.api.ViewStyleI#setCharHeight(int)
562    */
 
563  627 toggle @Override
564    public void setCharHeight(int h)
565    {
566  627 viewStyle.setCharHeight(h);
567    }
568   
569    /**
570    * @return
571    * @see jalview.api.ViewStyleI#getCharWidth()
572    */
 
573  1344217 toggle @Override
574    public int getCharWidth()
575    {
576  1344219 return viewStyle.getCharWidth();
577    }
578   
579    /**
580    * @param w
581    * @see jalview.api.ViewStyleI#setCharWidth(int)
582    */
 
583  630 toggle @Override
584    public void setCharWidth(int w)
585    {
586  630 viewStyle.setCharWidth(w);
587    }
588   
589    /**
590    * @return
591    * @see jalview.api.ViewStyleI#getShowBoxes()
592    */
 
593  532262 toggle @Override
594    public boolean getShowBoxes()
595    {
596  532265 return viewStyle.getShowBoxes();
597    }
598   
599    /**
600    * @return
601    * @see jalview.api.ViewStyleI#getShowUnconserved()
602    */
 
603  457546 toggle @Override
604    public boolean getShowUnconserved()
605    {
606  457546 return viewStyle.getShowUnconserved();
607    }
608   
609    /**
610    * @param showunconserved
611    * @see jalview.api.ViewStyleI#setShowUnconserved(boolean)
612    */
 
613  89 toggle @Override
614    public void setShowUnconserved(boolean showunconserved)
615    {
616  89 viewStyle.setShowUnconserved(showunconserved);
617    }
618   
619    /**
620    * @param default1
621    * @see jalview.api.ViewStyleI#setSeqNameItalics(boolean)
622    */
 
623  0 toggle @Override
624    public void setSeqNameItalics(boolean default1)
625    {
626  0 viewStyle.setSeqNameItalics(default1);
627    }
628   
 
629  239860 toggle @Override
630    public AlignmentI getAlignment()
631    {
632  239858 return alignment;
633    }
634   
 
635  0 toggle @Override
636    public char getGapCharacter()
637    {
638  0 return alignment.getGapCharacter();
639    }
640   
641    protected String sequenceSetID;
642   
643    /**
644    * probably unused indicator that view is of a dataset rather than an
645    * alignment
646    */
647    protected boolean isDataset = false;
648   
 
649  0 toggle public void setDataset(boolean b)
650    {
651  0 isDataset = b;
652    }
653   
 
654  505 toggle public boolean isDataset()
655    {
656  505 return isDataset;
657    }
658   
659    private Map<SequenceI, SequenceCollectionI> hiddenRepSequences;
660   
661    protected ColumnSelection colSel = new ColumnSelection();
662   
663    public boolean autoCalculateConsensus = true;
664   
665    protected boolean autoCalculateStrucConsensus = true;
666   
667    protected boolean ignoreGapsInConsensusCalculation = false;
668   
669    protected ResidueShaderI residueShading = new ResidueShader();
670   
 
671  285 toggle @Override
672    public void setGlobalColourScheme(ColourSchemeI cs)
673    {
674    // TODO: logic refactored from AlignFrame changeColour -
675    // TODO: autorecalc stuff should be changed to rely on the worker system
676    // check to see if we should implement a changeColour(cs) method rather than
677    // put the logic in here
678    // - means that caller decides if they want to just modify state and defer
679    // calculation till later or to do all calculations in thread.
680    // via changecolour
681   
682    /*
683    * only instantiate alignment colouring once, thereafter update it;
684    * this means that any conservation or PID threshold settings
685    * persist when the alignment colour scheme is changed
686    */
687  285 if (residueShading == null)
688    {
689  0 residueShading = new ResidueShader(viewStyle);
690    }
691  285 residueShading.setColourScheme(cs);
692   
693    // TODO: do threshold and increment belong in ViewStyle or ResidueShader?
694    // ...problem: groups need these, but do not currently have a ViewStyle
695   
696  285 if (cs != null)
697    {
698  88 if (getConservationSelected())
699    {
700  15 residueShading.setConservation(hconservation);
701    }
702    /*
703    * reset conservation flag in case just set to false if
704    * Conservation was null (calculation still in progress)
705    */
706  88 residueShading.setConservationApplied(getConservationSelected());
707  88 residueShading.alignmentChanged(alignment, hiddenRepSequences);
708    }
709   
710    /*
711    * if 'apply colour to all groups' is selected... do so
712    * (but don't transfer any colour threshold settings to groups)
713    */
714  285 if (getColourAppliesToAllGroups())
715    {
716  89 for (SequenceGroup sg : getAlignment().getGroups())
717    {
718    /*
719    * retain any colour thresholds per group while
720    * changing choice of colour scheme (JAL-2386)
721    */
722  9 sg.setColourScheme(cs == null ? null : cs.getInstance(this, sg));
723  9 if (cs != null)
724    {
725  8 sg.getGroupColourScheme().alignmentChanged(sg,
726    hiddenRepSequences);
727    }
728    }
729    }
730    }
731   
 
732  1471 toggle @Override
733    public ColourSchemeI getGlobalColourScheme()
734    {
735  1471 return residueShading == null ? null : residueShading.getColourScheme();
736    }
737   
 
738  537375 toggle @Override
739    public ResidueShaderI getResidueShading()
740    {
741  537377 return residueShading;
742    }
743   
744    protected AlignmentAnnotation consensus;
745   
746    protected List<AlignmentAnnotation> secondaryStructureConsensus;
747   
748    protected AlignmentAnnotation complementConsensus;
749   
750    protected AlignmentAnnotation gapcounts;
751   
752    protected AlignmentAnnotation strucConsensus;
753   
754    protected AlignmentAnnotation conservation;
755   
756    protected AlignmentAnnotation quality;
757   
758    protected AlignmentAnnotation[] groupConsensus;
759   
760    protected AlignmentAnnotation[] groupSSConsensus;
761   
762    protected AlignmentAnnotation[] groupConservation;
763   
764    /**
765    * results of alignment consensus analysis for visible portion of view
766    */
767    protected ProfilesI hconsensus = null;
768   
769    protected Map<String, ProfilesI> hSSConsensusProfileMap = null;
770   
771   
772    /**
773    * results of cDNA complement consensus visible portion of view
774    */
775    protected Hashtable<String, Object>[] hcomplementConsensus = null;
776   
777    /**
778    * results of secondary structure base pair consensus for visible portion of
779    * view
780    */
781    protected Hashtable<String, Object>[] hStrucConsensus = null;
782   
783    protected Conservation hconservation = null;
784   
 
785  1473 toggle @Override
786    public void setConservation(Conservation cons)
787    {
788  1473 hconservation = cons;
789    }
790   
 
791  1926 toggle @Override
792    public List<String> getSecondaryStructureSources()
793    {
794  1926 return viewStyle.getSecondaryStructureSources();
795    }
796   
 
797  1391 toggle @Override
798    public void setSecondaryStructureSources(
799    List<String> secondaryStructureSources)
800    {
801  1391 viewStyle.setSecondaryStructureSources(secondaryStructureSources);
802    }
803   
 
804  535 toggle protected void setSecondaryStructureSources(AlignmentAnnotation[] aa)
805    {
806  535 List<String> sources = null;
807   
808  535 if (aa != null)
809    {
810  443 sources = AlignmentUtils.extractSSSourceInAlignmentAnnotation(aa);
811  443 if (sources != null)
812    {
813  443 sources.add(0, Constants.SS_ALL_PROVIDERS);
814  443 viewStyle.setSecondaryStructureSources(sources);
815    }
816    }
817    }
818   
819    /**
820    * percentage gaps allowed in a column before all amino acid properties should
821    * be considered unconserved
822    */
823    int ConsPercGaps = 25; // JBPNote : This should be a scalable property!
824   
 
825  2443 toggle @Override
826    public int getConsPercGaps()
827    {
828  2443 return ConsPercGaps;
829    }
830   
 
831  1356 toggle @Override
832    public void setSequenceConsensusHash(ProfilesI hconsensus)
833    {
834  1356 this.hconsensus = hconsensus;
835    }
836   
 
837  1391 toggle @Override
838    public void setSequenceSSConsensusHash(
839    Map<String, ProfilesI> hSSConsensusProfileMap)
840    {
841  1391 this.hSSConsensusProfileMap = hSSConsensusProfileMap;
842    }
843   
 
844  5 toggle @Override
845    public void setComplementConsensusHash(
846    Hashtable<String, Object>[] hconsensus)
847    {
848  5 this.hcomplementConsensus = hconsensus;
849    }
850   
 
851  3859 toggle @Override
852    public ProfilesI getSequenceConsensusHash()
853    {
854  3859 return hconsensus;
855    }
856   
 
857  3891 toggle @Override
858    public Map<String, ProfilesI> getSequenceSSConsensusHash()
859    {
860  3891 return hSSConsensusProfileMap;
861    }
862   
 
863  2399 toggle @Override
864    public Hashtable<String, Object>[] getComplementConsensusHash()
865    {
866  2399 return hcomplementConsensus;
867    }
868   
 
869  2398 toggle @Override
870    public Hashtable<String, Object>[] getRnaStructureConsensusHash()
871    {
872  2398 return hStrucConsensus;
873    }
874   
 
875  4 toggle @Override
876    public void setRnaStructureConsensusHash(
877    Hashtable<String, Object>[] hStrucConsensus)
878    {
879  4 this.hStrucConsensus = hStrucConsensus;
880   
881    }
882   
 
883  2218 toggle @Override
884    public AlignmentAnnotation getAlignmentQualityAnnot()
885    {
886  2218 return quality;
887    }
888   
 
889  3164 toggle @Override
890    public AlignmentAnnotation getAlignmentConservationAnnotation()
891    {
892  3164 return conservation;
893    }
894   
 
895  7249 toggle @Override
896    public AlignmentAnnotation getAlignmentConsensusAnnotation()
897    {
898  7249 return consensus;
899    }
900   
 
901  6724 toggle @Override
902    public List<AlignmentAnnotation> getAlignmentSecondaryStructureConsensusAnnotation()
903    {
904  6724 return secondaryStructureConsensus;
905    }
906   
 
907  4209 toggle @Override
908    public AlignmentAnnotation getAlignmentGapAnnotation()
909    {
910  4209 return gapcounts;
911    }
912   
 
913  2409 toggle @Override
914    public AlignmentAnnotation getComplementConsensusAnnotation()
915    {
916  2409 return complementConsensus;
917    }
918   
 
919  2398 toggle @Override
920    public AlignmentAnnotation getAlignmentStrucConsensusAnnotation()
921    {
922  2398 return strucConsensus;
923    }
924   
925    protected AlignCalcManagerI calculator = new AlignCalcManager();
926   
927    /**
928    * trigger update of conservation annotation
929    */
 
930  1351 toggle public void updateConservation(final AlignmentViewPanel ap)
931    {
932    // see note in mantis : issue number 8585
933  1351 if (alignment.isNucleotide()
934    || (conservation == null && quality == null)
935    || !autoCalculateConsensus)
936    {
937  282 return;
938    }
939  1069 if (calculator.getRegisteredWorkersOfClass(
940    jalview.workers.ConservationThread.class) == null)
941    {
942  541 calculator.registerWorker(
943    new jalview.workers.ConservationThread(this, ap));
944    }
945    }
946   
947    /**
948    * trigger update of consensus annotation
949    */
 
950  1382 toggle public void updateConsensus(final AlignmentViewPanel ap)
951    {
952    // see note in mantis : issue number 8585
953  1382 if (consensus == null || !autoCalculateConsensus)
954    {
955  0 return;
956    }
957  1382 if (calculator
958    .getRegisteredWorkersOfClass(ConsensusThread.class) == null)
959    {
960  524 calculator.registerWorker(new ConsensusThread(this, ap));
961    }
962   
963    /*
964    * A separate thread to compute cDNA consensus for a protein alignment
965    * which has mapping to cDNA
966    */
967  1382 final AlignmentI al = this.getAlignment();
968  1382 if (!al.isNucleotide() && al.getCodonFrames() != null
969    && !al.getCodonFrames().isEmpty())
970    {
971    /*
972    * fudge - check first for protein-to-nucleotide mappings
973    * (we don't want to do this for protein-to-protein)
974    */
975  5 boolean doConsensus = false;
976  5 for (AlignedCodonFrame mapping : al.getCodonFrames())
977    {
978    // TODO hold mapping type e.g. dna-to-protein in AlignedCodonFrame?
979  5 MapList[] mapLists = mapping.getdnaToProt();
980    // mapLists can be empty if project load has not finished resolving seqs
981  5 if (mapLists.length > 0 && mapLists[0].getFromRatio() == 3)
982    {
983  5 doConsensus = true;
984  5 break;
985    }
986    }
987  5 if (doConsensus)
988    {
989  5 if (calculator.getRegisteredWorkersOfClass(
990    ComplementConsensusThread.class) == null)
991    {
992  4 calculator
993    .registerWorker(new ComplementConsensusThread(this, ap));
994    }
995    }
996    }
997    }
998   
999    /**
1000    * trigger update of Secondary Structure consensus annotation
1001    */
 
1002  1382 toggle public void updateSecondaryStructureConsensus(final AlignmentViewPanel ap)
1003    {
1004    // see note in mantis : issue number 8585
1005  1382 if (secondaryStructureConsensus == null || !autoCalculateConsensus)
1006    {
1007  0 return;
1008    }
1009  1382 List<String> ssSources = viewStyle.getSecondaryStructureSources();
1010  1382 if (secondaryStructureConsensus.size() != ssSources.size())
1011    {
1012   
1013  91 for (String source : ssSources)
1014    {
1015  114 boolean ssConsensusForSourcePresent = false;
1016  114 for (AlignmentAnnotation aa : secondaryStructureConsensus)
1017    {
1018  46 if (aa.description.startsWith(source))
1019    {
1020  23 ssConsensusForSourcePresent = true;
1021  23 break;
1022    }
1023    }
1024   
1025  114 if (!ssConsensusForSourcePresent)
1026    {
1027  91 AlignmentAnnotation ssConsensus = new AlignmentAnnotation(
1028    MessageManager.getString("label.ssconsensus_label") + " "
1029    + source,
1030    source + " "
1031    + MessageManager
1032    .getString("label.ssconsensus_descr"),
1033    new Annotation[1], 0f, 100f,
1034    AlignmentAnnotation.BAR_GRAPH);
1035   
1036  91 ssConsensus.hasText = true;
1037  91 ssConsensus.autoCalculated = true;
1038  91 secondaryStructureConsensus.add(ssConsensus);
1039  91 if (showSSConsensus)
1040    {
1041  0 alignment.addAnnotation(ssConsensus);
1042   
1043    }
1044    }
1045    }
1046    }
1047  1382 if (calculator.getRegisteredWorkersOfClass(
1048    SecondaryStructureConsensusThread.class) == null)
1049    {
1050  548 calculator.registerWorker(
1051    new SecondaryStructureConsensusThread(this, ap));
1052    }
1053  1382 ap.adjustAnnotationHeight();
1054   
1055    }
1056   
1057    // --------START Structure Conservation
 
1058  1379 toggle public void updateStrucConsensus(final AlignmentViewPanel ap)
1059    {
1060  1379 if (autoCalculateStrucConsensus && strucConsensus == null
1061    && alignment.isNucleotide() && alignment.hasRNAStructure())
1062    {
1063    // secondary structure has been added - so init the consensus line
1064  0 initRNAStructure();
1065    }
1066   
1067    // see note in mantis : issue number 8585
1068  1379 if (strucConsensus == null || !autoCalculateStrucConsensus)
1069    {
1070  1375 return;
1071    }
1072  4 if (calculator.getRegisteredWorkersOfClass(
1073    StrucConsensusThread.class) == null)
1074    {
1075  2 calculator.registerWorker(new StrucConsensusThread(this, ap));
1076    }
1077    }
1078   
 
1079  2894 toggle public boolean isCalcInProgress()
1080    {
1081  2894 return calculator.isWorking();
1082    }
1083   
 
1084  8931 toggle @Override
1085    public boolean isCalculationInProgress(
1086    AlignmentAnnotation alignmentAnnotation)
1087    {
1088  8931 if (!alignmentAnnotation.autoCalculated)
1089    {
1090  0 return false;
1091    }
1092  8931 if (calculator.workingInvolvedWith(alignmentAnnotation))
1093    {
1094    // jalview.bin.Console.errPrintln("grey out
1095    // ("+alignmentAnnotation.label+")");
1096  356 return true;
1097    }
1098  8575 return false;
1099    }
1100   
 
1101  804 toggle public void setAlignment(AlignmentI align)
1102    {
1103  804 this.alignment = align;
1104    }
1105   
1106    /**
1107    * Clean up references when this viewport is closed
1108    */
 
1109  269 toggle @Override
1110    public void dispose()
1111    {
1112    /*
1113    * defensively null out references to large objects in case
1114    * this object is not garbage collected (as if!)
1115    */
1116  269 consensus = null;
1117  269 complementConsensus = null;
1118  269 strucConsensus = null;
1119  269 secondaryStructureConsensus = null;
1120  269 conservation = null;
1121  269 quality = null;
1122  269 groupConsensus = null;
1123  269 groupConservation = null;
1124  269 hconsensus = null;
1125  269 hconservation = null;
1126  269 hcomplementConsensus = null;
1127  269 gapcounts = null;
1128  269 calculator = null;
1129  269 residueShading = null; // may hold a reference to Consensus
1130  269 changeSupport = null;
1131  269 ranges = null;
1132  269 currentTree = null;
1133  269 selectionGroup = null;
1134  269 colSel = null;
1135  269 setAlignment(null);
1136    }
1137   
 
1138  5728 toggle @Override
1139    public boolean isClosed()
1140    {
1141    // TODO: check that this isClosed is only true after panel is closed, not
1142    // before it is fully constructed.
1143  5728 return alignment == null;
1144    }
1145   
 
1146  4027 toggle @Override
1147    public AlignCalcManagerI getCalcManager()
1148    {
1149  4027 return calculator;
1150    }
1151   
1152    /**
1153    * should conservation rows be shown for groups
1154    */
1155    protected boolean showGroupConservation = false;
1156   
1157    /**
1158    * should consensus rows be shown for groups
1159    */
1160    protected boolean showGroupConsensus = false;
1161   
1162    protected boolean showGroupSSConsensus = false;
1163   
1164    /**
1165    * should consensus profile be rendered by default
1166    */
1167    protected boolean showSequenceLogo = false;
1168   
1169    /**
1170    * should consensus profile be rendered normalised to row height
1171    */
1172    protected boolean normaliseSequenceLogo = false;
1173   
1174    /**
1175    * should consensus histograms be rendered by default
1176    */
1177    protected boolean showConsensusHistogram = true;
1178   
1179    /**
1180    * @return the showConsensusProfile
1181    */
 
1182  6093 toggle @Override
1183    public boolean isShowSequenceLogo()
1184    {
1185  6093 return showSequenceLogo;
1186    }
1187   
1188    /**
1189    * @param showSequenceLogo
1190    * the new value
1191    */
 
1192  89 toggle public void setShowSequenceLogo(boolean showSequenceLogo)
1193    {
1194  89 if (showSequenceLogo != this.showSequenceLogo)
1195    {
1196    // TODO: decouple settings setting from calculation when refactoring
1197    // annotation update method from alignframe to viewport
1198  20 this.showSequenceLogo = showSequenceLogo;
1199  20 calculator.updateAnnotationFor(ConsensusThread.class);
1200  20 calculator.updateAnnotationFor(ComplementConsensusThread.class);
1201  20 calculator.updateAnnotationFor(StrucConsensusThread.class);
1202   
1203    // to do
1204   
1205  20 calculator
1206    .updateAnnotationFor(SecondaryStructureConsensusThread.class);
1207    }
1208  89 this.showSequenceLogo = showSequenceLogo;
1209    }
1210   
1211    /**
1212    * @param showConsensusHistogram
1213    * the showConsensusHistogram to set
1214    */
 
1215  89 toggle public void setShowConsensusHistogram(boolean showConsensusHistogram)
1216    {
1217  89 this.showConsensusHistogram = showConsensusHistogram;
1218    }
1219   
1220    /**
1221    * @return the showGroupConservation
1222    */
 
1223  890 toggle public boolean isShowGroupConservation()
1224    {
1225  890 return showGroupConservation;
1226    }
1227   
1228    /**
1229    * @param showGroupConservation
1230    * the showGroupConservation to set
1231    */
 
1232  89 toggle public void setShowGroupConservation(boolean showGroupConservation)
1233    {
1234  89 this.showGroupConservation = showGroupConservation;
1235    }
1236   
1237    /**
1238    * @return the showGroupConsensus
1239    */
 
1240  890 toggle public boolean isShowGroupConsensus()
1241    {
1242  890 return showGroupConsensus;
1243    }
1244   
 
1245  890 toggle public boolean isShowGroupSSConsensus()
1246    {
1247  890 return showGroupSSConsensus;
1248    }
1249   
1250    /**
1251    * @param showGroupConsensus
1252    * the showGroupConsensus to set
1253    */
 
1254  89 toggle public void setShowGroupConsensus(boolean showGroupConsensus)
1255    {
1256  89 this.showGroupConsensus = showGroupConsensus;
1257    }
1258   
 
1259  89 toggle public void setShowGroupSSConsensus(boolean showGroupSSConsensus)
1260    {
1261  89 this.showGroupSSConsensus = showGroupSSConsensus;
1262    }
1263   
1264    /**
1265    * @param showSSConsensus
1266    * the showSSConsensus to set
1267    */
 
1268  0 toggle public void setShowSSConsensus(boolean showSSConsensus)
1269    {
1270  0 this.showSSConsensus = showSSConsensus;
1271    }
1272   
1273    /**
1274    *
1275    * @return flag to indicate if the consensus histogram should be rendered by
1276    * default
1277    */
 
1278  3284 toggle @Override
1279    public boolean isShowConsensusHistogram()
1280    {
1281  3284 return this.showConsensusHistogram;
1282    }
1283   
1284    /**
1285    * when set, updateAlignment will always ensure sequences are of equal length
1286    */
1287    private boolean padGaps = false;
1288   
1289    /**
1290    * when set, alignment should be reordered according to a newly opened tree
1291    */
1292    public boolean sortByTree = false;
1293   
1294    /**
1295    *
1296    *
1297    * @return null or the currently selected sequence region
1298    */
 
1299  30011 toggle @Override
1300    public SequenceGroup getSelectionGroup()
1301    {
1302  30011 return selectionGroup;
1303    }
1304   
1305    /**
1306    * Set the selection group for this window. Also sets the current alignment as
1307    * the context for the group, if it does not already have one.
1308    * @param sg
1309    * - group holding references to sequences in this alignment view
1310    *
1311    */
 
1312  150 toggle @Override
1313    public void setSelectionGroup(SequenceGroup sg)
1314    {
1315  150 selectionGroup = sg;
1316  150 if (sg != null && sg.getContext() == null)
1317    {
1318  37 sg.setContext(alignment);
1319    }
1320    }
1321   
 
1322  1 toggle public void setHiddenColumns(HiddenColumns hidden)
1323    {
1324  1 this.alignment.setHiddenColumns(hidden);
1325    }
1326   
 
1327  4827 toggle @Override
1328    public ColumnSelection getColumnSelection()
1329    {
1330  4827 return colSel;
1331    }
1332   
 
1333  13 toggle @Override
1334    public void setColumnSelection(ColumnSelection colSel)
1335    {
1336  13 this.colSel = colSel;
1337  13 if (colSel != null)
1338    {
1339  13 updateHiddenColumns();
1340    }
1341  13 isColSelChanged(true);
1342    }
1343   
1344    /**
1345    *
1346    * @return
1347    */
 
1348  32 toggle @Override
1349    public Map<SequenceI, SequenceCollectionI> getHiddenRepSequences()
1350    {
1351  32 return hiddenRepSequences;
1352    }
1353   
 
1354  0 toggle @Override
1355    public void setHiddenRepSequences(
1356    Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
1357    {
1358  0 this.hiddenRepSequences = hiddenRepSequences;
1359    }
1360   
 
1361  0 toggle @Override
1362    public boolean hasSelectedColumns()
1363    {
1364  0 ColumnSelection columnSelection = getColumnSelection();
1365  0 return columnSelection != null && columnSelection.hasSelectedColumns();
1366    }
1367   
 
1368  8367 toggle @Override
1369    public boolean hasHiddenColumns()
1370    {
1371  8367 return alignment.getHiddenColumns() != null
1372    && alignment.getHiddenColumns().hasHiddenColumns();
1373    }
1374   
 
1375  14 toggle public void updateHiddenColumns()
1376    {
1377    // this method doesn't really do anything now. But - it could, since a
1378    // column Selection could be in the process of modification
1379    // hasHiddenColumns = colSel.hasHiddenColumns();
1380    }
1381   
 
1382  4719 toggle @Override
1383    public boolean hasHiddenRows()
1384    {
1385  4719 return alignment.getHiddenSequences().getSize() > 0;
1386    }
1387   
1388    protected SequenceGroup selectionGroup;
1389   
 
1390  89 toggle public void setSequenceSetId(String newid)
1391    {
1392  89 if (sequenceSetID != null)
1393    {
1394  89 jalview.bin.Console.errPrintln(
1395    "Warning - overwriting a sequenceSetId for a viewport!");
1396    }
1397  89 sequenceSetID = new String(newid);
1398    }
1399   
 
1400  5974 toggle @Override
1401    public String getSequenceSetId()
1402    {
1403  5974 if (sequenceSetID == null)
1404    {
1405  387 sequenceSetID = alignment.hashCode() + "";
1406    }
1407   
1408  5974 return sequenceSetID;
1409    }
1410   
1411    /**
1412    * unique viewId for synchronizing state (e.g. with stored Jalview Project)
1413    *
1414    */
1415    protected String viewId = null;
1416   
 
1417  623 toggle @Override
1418    public String getViewId()
1419    {
1420  623 if (viewId == null)
1421    {
1422  319 viewId = this.getSequenceSetId() + "." + this.hashCode() + "";
1423    }
1424  623 return viewId;
1425    }
1426   
 
1427  92 toggle public void setIgnoreGapsConsensus(boolean b, AlignmentViewPanel ap)
1428    {
1429  92 ignoreGapsInConsensusCalculation = b;
1430  92 if (ap != null)
1431    {
1432  3 updateConsensus(ap);
1433  3 updateSecondaryStructureConsensus(ap);
1434  3 if (residueShading != null)
1435    {
1436  3 residueShading.setThreshold(residueShading.getThreshold(),
1437    ignoreGapsInConsensusCalculation);
1438    }
1439    }
1440   
1441    }
1442   
1443    private long sgrouphash = -1, colselhash = -1;
1444   
1445    /**
1446    * checks current SelectionGroup against record of last hash value, and
1447    * updates record.
1448    *
1449    * @param b
1450    * update the record of last hash value
1451    *
1452    * @return true if SelectionGroup changed since last call (when b is true)
1453    */
 
1454  177 toggle public boolean isSelectionGroupChanged(boolean b)
1455    {
1456  177 int hc = (selectionGroup == null || selectionGroup.getSize() == 0) ? -1
1457    : selectionGroup.hashCode();
1458  177 if (hc != -1 && hc != sgrouphash)
1459    {
1460  9 if (b)
1461    {
1462  9 sgrouphash = hc;
1463    }
1464  9 return true;
1465    }
1466  168 return false;
1467    }
1468   
1469    /**
1470    * checks current colsel against record of last hash value, and optionally
1471    * updates record.
1472    *
1473    * @param b
1474    * update the record of last hash value
1475    * @return true if colsel changed since last call (when b is true)
1476    */
 
1477  181 toggle public boolean isColSelChanged(boolean b)
1478    {
1479  181 int hc = (colSel == null || colSel.isEmpty()) ? -1 : colSel.hashCode();
1480  181 if (hc != -1 && hc != colselhash)
1481    {
1482  17 if (b)
1483    {
1484  17 colselhash = hc;
1485    }
1486  17 return true;
1487    }
1488  164 return false;
1489    }
1490   
 
1491  5273 toggle @Override
1492    public boolean isIgnoreGapsConsensus()
1493    {
1494  5273 return ignoreGapsInConsensusCalculation;
1495    }
1496   
1497    // property change stuff
1498    // JBPNote Prolly only need this in the applet version.
1499    private PropertyChangeSupport changeSupport = new PropertyChangeSupport(
1500    this);
1501   
1502    protected boolean showConservation = true;
1503   
1504    protected boolean showQuality = true;
1505   
1506    protected boolean showConsensus = true;
1507   
1508    protected boolean showSSConsensus = true;
1509   
1510    protected boolean showOccupancy = true;
1511   
1512    private Map<SequenceI, Color> sequenceColours = new HashMap<>();
1513   
1514    private Map<AlignmentAnnotation, Color> annotationColours = new HashMap<>();
1515   
1516    protected SequenceAnnotationOrder sortAnnotationsBy = null;
1517   
1518    protected boolean showAutocalculatedAbove;
1519   
1520    /**
1521    * when set, view will scroll to show the highlighted position
1522    */
1523    private boolean followHighlight = true;
1524   
1525    /**
1526    * Property change listener for changes in alignment
1527    *
1528    * @param listener
1529    * DOCUMENT ME!
1530    */
 
1531  523 toggle public void addPropertyChangeListener(
1532    java.beans.PropertyChangeListener listener)
1533    {
1534  523 changeSupport.addPropertyChangeListener(listener);
1535    }
1536   
1537    /**
1538    * DOCUMENT ME!
1539    *
1540    * @param listener
1541    * DOCUMENT ME!
1542    */
 
1543  286 toggle public void removePropertyChangeListener(
1544    java.beans.PropertyChangeListener listener)
1545    {
1546  286 if (changeSupport != null)
1547    {
1548  285 changeSupport.removePropertyChangeListener(listener);
1549    }
1550    }
1551   
1552    /**
1553    * Property change listener for changes in alignment
1554    *
1555    * @param prop
1556    * DOCUMENT ME!
1557    * @param oldvalue
1558    * DOCUMENT ME!
1559    * @param newvalue
1560    * DOCUMENT ME!
1561    */
 
1562  78 toggle public void firePropertyChange(String prop, Object oldvalue,
1563    Object newvalue)
1564    {
1565  78 changeSupport.firePropertyChange(prop, oldvalue, newvalue);
1566    }
1567   
 
1568  0 toggle @Override
1569    public void notifyAlignmentChanged()
1570    {
1571  0 firePropertyChange("alignment", null, alignment);
1572    }
1573   
1574    // common hide/show column stuff
1575   
 
1576  6 toggle public void hideSelectedColumns()
1577    {
1578  6 if (colSel.isEmpty())
1579    {
1580  2 return;
1581    }
1582   
1583  4 colSel.hideSelectedColumns(alignment);
1584  4 setSelectionGroup(null);
1585  4 isColSelChanged(true);
1586    }
1587   
 
1588  71 toggle public void hideColumns(int start, int end)
1589    {
1590  71 if (start == end)
1591    {
1592  2 colSel.hideSelectedColumns(start, alignment.getHiddenColumns());
1593    }
1594    else
1595    {
1596  69 alignment.getHiddenColumns().hideColumns(start, end);
1597    }
1598  71 isColSelChanged(true);
1599    }
1600   
 
1601  1 toggle public void showColumn(int col)
1602    {
1603  1 alignment.getHiddenColumns().revealHiddenColumns(col, colSel);
1604  1 isColSelChanged(true);
1605    }
1606   
 
1607  5 toggle public void showAllHiddenColumns()
1608    {
1609  5 alignment.getHiddenColumns().revealAllHiddenColumns(colSel);
1610  5 isColSelChanged(true);
1611    }
1612   
1613    // common hide/show seq stuff
 
1614  1 toggle public void showAllHiddenSeqs()
1615    {
1616  1 int startSeq = ranges.getStartSeq();
1617  1 int endSeq = ranges.getEndSeq();
1618   
1619  1 if (alignment.getHiddenSequences().getSize() > 0)
1620    {
1621  1 if (selectionGroup == null)
1622    {
1623  0 selectionGroup = new SequenceGroup();
1624  0 selectionGroup.setEndRes(alignment.getWidth() - 1);
1625    }
1626  1 List<SequenceI> tmp = alignment.getHiddenSequences()
1627    .showAll(hiddenRepSequences);
1628  1 for (SequenceI seq : tmp)
1629    {
1630  2 selectionGroup.addSequence(seq, false);
1631  2 setSequenceAnnotationsVisible(seq, true);
1632    }
1633   
1634  1 hiddenRepSequences = null;
1635   
1636  1 ranges.setStartEndSeq(startSeq, endSeq + tmp.size());
1637   
1638  1 firePropertyChange("alignment", null, alignment.getSequences());
1639    // used to set hasHiddenRows/hiddenRepSequences here, after the property
1640    // changed event
1641  1 sendSelection();
1642    }
1643    }
1644   
 
1645  2 toggle public void showSequence(int index)
1646    {
1647  2 int startSeq = ranges.getStartSeq();
1648  2 int endSeq = ranges.getEndSeq();
1649   
1650  2 List<SequenceI> tmp = alignment.getHiddenSequences().showSequence(index,
1651    hiddenRepSequences);
1652  2 if (tmp.size() > 0)
1653    {
1654  2 if (selectionGroup == null)
1655    {
1656  2 selectionGroup = new SequenceGroup();
1657  2 selectionGroup.setEndRes(alignment.getWidth() - 1);
1658    }
1659   
1660  2 for (SequenceI seq : tmp)
1661    {
1662  3 selectionGroup.addSequence(seq, false);
1663  3 setSequenceAnnotationsVisible(seq, true);
1664    }
1665   
1666  2 ranges.setStartEndSeq(startSeq, endSeq + tmp.size());
1667   
1668  2 firePropertyChange("alignment", null, alignment.getSequences());
1669  2 sendSelection();
1670    }
1671    }
1672   
 
1673  0 toggle public void hideAllSelectedSeqs()
1674    {
1675  0 if (selectionGroup == null || selectionGroup.getSize() < 1)
1676    {
1677  0 return;
1678    }
1679   
1680  0 SequenceI[] seqs = selectionGroup.getSequencesInOrder(alignment);
1681   
1682  0 hideSequence(seqs);
1683   
1684  0 setSelectionGroup(null);
1685    }
1686   
 
1687  54 toggle public void hideSequence(SequenceI[] seq)
1688    {
1689    /*
1690    * cache offset to first visible sequence
1691    */
1692  54 int startSeq = ranges.getStartSeq();
1693   
1694  54 if (seq != null)
1695    {
1696  252 for (int i = 0; i < seq.length; i++)
1697    {
1698  198 alignment.getHiddenSequences().hideSequence(seq[i]);
1699  198 setSequenceAnnotationsVisible(seq[i], false);
1700    }
1701  54 ranges.setStartSeq(startSeq);
1702  54 firePropertyChange("alignment", null, alignment.getSequences());
1703    }
1704    }
1705   
1706    /**
1707    * Hides the specified sequence, or the sequences it represents
1708    *
1709    * @param sequence
1710    * the sequence to hide, or keep as representative
1711    * @param representGroup
1712    * if true, hide the current selection group except for the
1713    * representative sequence
1714    */
 
1715  3 toggle public void hideSequences(SequenceI sequence, boolean representGroup)
1716    {
1717  3 if (selectionGroup == null || selectionGroup.getSize() < 1)
1718    {
1719  0 hideSequence(new SequenceI[] { sequence });
1720  0 return;
1721    }
1722   
1723  3 if (representGroup)
1724    {
1725  3 hideRepSequences(sequence, selectionGroup);
1726  3 setSelectionGroup(null);
1727  3 return;
1728    }
1729   
1730  0 int gsize = selectionGroup.getSize();
1731  0 SequenceI[] hseqs = selectionGroup.getSequences()
1732    .toArray(new SequenceI[gsize]);
1733   
1734  0 hideSequence(hseqs);
1735  0 setSelectionGroup(null);
1736  0 sendSelection();
1737    }
1738   
1739    /**
1740    * Set visibility for any annotations for the given sequence.
1741    *
1742    * @param sequenceI
1743    */
 
1744  203 toggle protected void setSequenceAnnotationsVisible(SequenceI sequenceI,
1745    boolean visible)
1746    {
1747  203 AlignmentAnnotation[] anns = alignment.getAlignmentAnnotation();
1748  203 if (anns != null)
1749    {
1750  203 for (AlignmentAnnotation ann : anns)
1751    {
1752  1033 if (ann.sequenceRef == sequenceI)
1753    {
1754  0 ann.visible = visible;
1755    }
1756    }
1757    }
1758    }
1759   
 
1760  5 toggle public void hideRepSequences(SequenceI repSequence, SequenceGroup sg)
1761    {
1762  5 int sSize = sg.getSize();
1763  5 if (sSize < 2)
1764    {
1765  0 return;
1766    }
1767   
1768  5 if (hiddenRepSequences == null)
1769    {
1770  5 hiddenRepSequences = new Hashtable<>();
1771    }
1772   
1773  5 hiddenRepSequences.put(repSequence, sg);
1774   
1775    // Hide all sequences except the repSequence
1776  5 SequenceI[] seqs = new SequenceI[sSize - 1];
1777  5 int index = 0;
1778  16 for (int i = 0; i < sSize; i++)
1779    {
1780  11 if (sg.getSequenceAt(i) != repSequence)
1781    {
1782  6 if (index == sSize - 1)
1783    {
1784  0 return;
1785    }
1786   
1787  6 seqs[index++] = sg.getSequenceAt(i);
1788    }
1789    }
1790  5 sg.setSeqrep(repSequence); // note: not done in 2.7applet
1791  5 sg.setHidereps(true); // note: not done in 2.7applet
1792  5 hideSequence(seqs);
1793   
1794    }
1795   
1796    /**
1797    *
1798    * @return null or the current reference sequence
1799    */
 
1800  0 toggle public SequenceI getReferenceSeq()
1801    {
1802  0 return alignment.getSeqrep();
1803    }
1804   
1805    /**
1806    * @param seq
1807    * @return true iff seq is the reference for the alignment
1808    */
 
1809  3098 toggle public boolean isReferenceSeq(SequenceI seq)
1810    {
1811  3098 return alignment.getSeqrep() == seq;
1812    }
1813   
1814    /**
1815    *
1816    * @param seq
1817    * @return true if there are sequences represented by this sequence that are
1818    * currently hidden
1819    */
 
1820  3217 toggle public boolean isHiddenRepSequence(SequenceI seq)
1821    {
1822  3217 return (hiddenRepSequences != null
1823    && hiddenRepSequences.containsKey(seq));
1824    }
1825   
1826    /**
1827    *
1828    * @param seq
1829    * @return null or a sequence group containing the sequences that seq
1830    * represents
1831    */
 
1832  2 toggle public SequenceGroup getRepresentedSequences(SequenceI seq)
1833    {
1834  2 return (SequenceGroup) (hiddenRepSequences == null ? null
1835    : hiddenRepSequences.get(seq));
1836    }
1837   
 
1838  0 toggle @Override
1839    public int adjustForHiddenSeqs(int alignmentIndex)
1840    {
1841  0 return alignment.getHiddenSequences()
1842    .adjustForHiddenSeqs(alignmentIndex);
1843    }
1844   
 
1845  0 toggle @Override
1846    public void invertColumnSelection()
1847    {
1848  0 colSel.invertColumnSelection(0, alignment.getWidth(), alignment);
1849  0 isColSelChanged(true);
1850    }
1851   
 
1852  4 toggle @Override
1853    public SequenceI[] getSelectionAsNewSequence()
1854    {
1855  4 SequenceI[] sequences;
1856    // JBPNote: Need to test jalviewLite.getSelectedSequencesAsAlignmentFrom -
1857    // this was the only caller in the applet for this method
1858    // JBPNote: in applet, this method returned references to the alignment
1859    // sequences, and it did not honour the presence/absence of annotation
1860    // attached to the alignment (probably!)
1861  4 if (selectionGroup == null || selectionGroup.getSize() == 0)
1862    {
1863  2 sequences = alignment.getSequencesArray();
1864  2 AlignmentAnnotation[] annots = alignment.getAlignmentAnnotation();
1865  4 for (int i = 0; i < sequences.length; i++)
1866    {
1867    // construct new sequence with subset of visible annotation
1868  2 sequences[i] = new Sequence(sequences[i], annots);
1869    }
1870    }
1871    else
1872    {
1873  2 sequences = selectionGroup.getSelectionAsNewSequences(alignment);
1874    }
1875   
1876  4 return sequences;
1877    }
1878   
 
1879  28 toggle @Override
1880    public SequenceI[] getSequenceSelection()
1881    {
1882  28 SequenceI[] sequences = null;
1883  28 if (selectionGroup != null)
1884    {
1885  4 sequences = selectionGroup.getSequencesInOrder(alignment);
1886    }
1887  28 if (sequences == null)
1888    {
1889  24 sequences = alignment.getSequencesArray();
1890    }
1891  28 return sequences;
1892    }
1893   
 
1894  25 toggle @Override
1895    public jalview.datamodel.AlignmentView getAlignmentView(
1896    boolean selectedOnly)
1897    {
1898  25 return getAlignmentView(selectedOnly, false);
1899    }
1900   
 
1901  26 toggle @Override
1902    public jalview.datamodel.AlignmentView getAlignmentView(
1903    boolean selectedOnly, boolean markGroups)
1904    {
1905  26 return new AlignmentView(alignment, alignment.getHiddenColumns(),
1906    selectionGroup,
1907    alignment.getHiddenColumns() != null
1908    && alignment.getHiddenColumns().hasHiddenColumns(),
1909    selectedOnly, markGroups);
1910    }
1911   
 
1912  24 toggle @Override
1913    public String[] getViewAsString(boolean selectedRegionOnly)
1914    {
1915  24 return getViewAsString(selectedRegionOnly, true);
1916    }
1917   
 
1918  24 toggle @Override
1919    public String[] getViewAsString(boolean selectedRegionOnly,
1920    boolean exportHiddenSeqs)
1921    {
1922  24 String[] selection = null;
1923  24 SequenceI[] seqs = null;
1924  24 int i, iSize;
1925  24 int start = 0, end = 0;
1926  24 if (selectedRegionOnly && selectionGroup != null)
1927    {
1928  0 iSize = selectionGroup.getSize();
1929  0 seqs = selectionGroup.getSequencesInOrder(alignment);
1930  0 start = selectionGroup.getStartRes();
1931  0 end = selectionGroup.getEndRes() + 1;
1932    }
1933    else
1934    {
1935  24 if (hasHiddenRows() && exportHiddenSeqs)
1936    {
1937  0 AlignmentI fullAlignment = alignment.getHiddenSequences()
1938    .getFullAlignment();
1939  0 iSize = fullAlignment.getHeight();
1940  0 seqs = fullAlignment.getSequencesArray();
1941  0 end = fullAlignment.getWidth();
1942    }
1943    else
1944    {
1945  24 iSize = alignment.getHeight();
1946  24 seqs = alignment.getSequencesArray();
1947  24 end = alignment.getWidth();
1948    }
1949    }
1950   
1951  24 selection = new String[iSize];
1952  24 if (alignment.getHiddenColumns() != null
1953    && alignment.getHiddenColumns().hasHiddenColumns())
1954    {
1955  206 for (i = 0; i < iSize; i++)
1956    {
1957  188 Iterator<int[]> blocks = alignment.getHiddenColumns()
1958    .getVisContigsIterator(start, end + 1, false);
1959  188 selection[i] = seqs[i].getSequenceStringFromIterator(blocks);
1960    }
1961    }
1962    else
1963    {
1964  36 for (i = 0; i < iSize; i++)
1965    {
1966  30 selection[i] = seqs[i].getSequenceAsString(start, end);
1967    }
1968   
1969    }
1970  24 return selection;
1971    }
1972   
 
1973  0 toggle @Override
1974    public List<int[]> getVisibleRegionBoundaries(int min, int max)
1975    {
1976  0 ArrayList<int[]> regions = new ArrayList<>();
1977  0 int start = min;
1978  0 int end = max;
1979   
1980  0 do
1981    {
1982  0 HiddenColumns hidden = alignment.getHiddenColumns();
1983  0 if (hidden != null && hidden.hasHiddenColumns())
1984    {
1985  0 if (start == 0)
1986    {
1987  0 start = hidden.visibleToAbsoluteColumn(start);
1988    }
1989   
1990  0 end = hidden.getNextHiddenBoundary(false, start);
1991  0 if (start == end)
1992    {
1993  0 end = max;
1994    }
1995  0 if (end > max)
1996    {
1997  0 end = max;
1998    }
1999    }
2000   
2001  0 regions.add(new int[] { start, end });
2002   
2003  0 if (hidden != null && hidden.hasHiddenColumns())
2004    {
2005  0 start = hidden.visibleToAbsoluteColumn(end);
2006  0 start = hidden.getNextHiddenBoundary(true, start) + 1;
2007    }
2008  0 } while (end < max);
2009   
2010    // int[][] startEnd = new int[regions.size()][2];
2011   
2012  0 return regions;
2013    }
2014   
 
2015  1 toggle @Override
2016    public List<AlignmentAnnotation> getVisibleAlignmentAnnotation(
2017    boolean selectedOnly)
2018    {
2019  1 ArrayList<AlignmentAnnotation> ala = new ArrayList<>();
2020  1 AlignmentAnnotation[] aa;
2021  ? if ((aa = alignment.getAlignmentAnnotation()) != null)
2022    {
2023  1 for (AlignmentAnnotation annot : aa)
2024    {
2025  4 AlignmentAnnotation clone = new AlignmentAnnotation(annot);
2026  4 if (selectedOnly && selectionGroup != null)
2027    {
2028  4 clone.makeVisibleAnnotation(selectionGroup.getStartRes(),
2029    selectionGroup.getEndRes(), alignment.getHiddenColumns());
2030    }
2031    else
2032    {
2033  0 clone.makeVisibleAnnotation(alignment.getHiddenColumns());
2034    }
2035  4 ala.add(clone);
2036    }
2037    }
2038  1 return ala;
2039    }
2040   
 
2041  2086 toggle @Override
2042    public boolean isPadGaps()
2043    {
2044  2086 return padGaps;
2045    }
2046   
 
2047  535 toggle @Override
2048    public void setPadGaps(boolean padGaps)
2049    {
2050  535 this.padGaps = padGaps;
2051    }
2052   
2053    /**
2054    * apply any post-edit constraints and trigger any calculations needed after
2055    * an edit has been performed on the alignment
2056    *
2057    * @param ap
2058    */
 
2059  895 toggle @Override
2060    public void alignmentChanged(AlignmentViewPanel ap)
2061    {
2062  895 if (isPadGaps())
2063    {
2064  513 alignment.padGaps();
2065    }
2066  895 if (autoCalculateConsensus)
2067    {
2068  895 updateConsensus(ap);
2069  895 updateSecondaryStructureConsensus(ap);
2070    }
2071  895 if (hconsensus != null && autoCalculateConsensus)
2072    {
2073  867 updateConservation(ap);
2074    }
2075  895 if (autoCalculateStrucConsensus)
2076    {
2077  895 updateStrucConsensus(ap);
2078    }
2079   
2080    // Reset endRes of groups if beyond alignment width
2081  895 int alWidth = alignment.getWidth();
2082  895 List<SequenceGroup> groups = alignment.getGroups();
2083  895 if (groups != null)
2084    {
2085  895 for (SequenceGroup sg : groups)
2086    {
2087  187 if (sg.getEndRes() > alWidth)
2088    {
2089  0 sg.setEndRes(alWidth - 1);
2090    }
2091    }
2092    }
2093   
2094  895 if (selectionGroup != null && selectionGroup.getEndRes() > alWidth)
2095    {
2096  0 selectionGroup.setEndRes(alWidth - 1);
2097    }
2098   
2099  895 updateAllColourSchemes();
2100  895 calculator.restartWorkers();
2101    // alignment.adjustSequenceAnnotations();
2102    }
2103   
2104    /**
2105    * reset scope and do calculations for all applied colourschemes on alignment
2106    */
 
2107  895 toggle void updateAllColourSchemes()
2108    {
2109  895 ResidueShaderI rs = residueShading;
2110  895 if (rs != null)
2111    {
2112  895 rs.alignmentChanged(alignment, hiddenRepSequences);
2113   
2114  895 rs.setConsensus(hconsensus);
2115  895 if (rs.conservationApplied())
2116    {
2117  3 rs.setConservation(Conservation.calculateConservation("All",
2118    alignment.getSequences(), 0, alignment.getWidth(), false,
2119    getConsPercGaps(), false));
2120    }
2121    }
2122   
2123  895 for (SequenceGroup sg : alignment.getGroups())
2124    {
2125  187 if (sg.cs != null)
2126    {
2127  187 sg.cs.alignmentChanged(sg, hiddenRepSequences);
2128    }
2129  187 sg.recalcConservation();
2130    }
2131    }
2132   
 
2133  535 toggle protected void initAutoAnnotation()
2134    {
2135    // TODO: add menu option action that nulls or creates consensus object
2136    // depending on if the user wants to see the annotation or not in a
2137    // specific alignment
2138   
2139  535 if (hconsensus == null && !isDataset)
2140    {
2141  535 if (!alignment.isNucleotide())
2142    {
2143  424 initConservation();
2144  424 initQuality();
2145    }
2146    else
2147    {
2148  111 initRNAStructure();
2149    }
2150  535 consensus = new AlignmentAnnotation("Consensus",
2151    MessageManager.getString("label.consensus_descr"),
2152    new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
2153  535 setSecondaryStructureSources(alignment.getAlignmentAnnotation());
2154   
2155  535 List<String> secondaryStructureSources = getSecondaryStructureSources();
2156  535 boolean singleProvider = false;
2157   
2158  535 if (secondaryStructureSources != null)
2159    {
2160  535 if(secondaryStructureSources.size() == 2)
2161    {
2162  18 singleProvider = true; //Single provider if size is 2 (All, Provider 1)
2163    }
2164   
2165  535 AlignmentUtils.assignColorsForSecondaryStructureProviders(secondaryStructureSources);
2166   
2167  535 secondaryStructureConsensus = new ArrayList<AlignmentAnnotation>();
2168  535 for (String ssSource : secondaryStructureSources)
2169    {
2170   
2171  477 AlignmentAnnotation ssConsensus = new AlignmentAnnotation(
2172    MessageManager.getString("label.ssconsensus_label") + " "
2173    + ssSource,
2174    ssSource + " "
2175    + MessageManager
2176    .getString("label.ssconsensus_descr"),
2177    new Annotation[1], 0f, 100f,
2178    AlignmentAnnotation.BAR_GRAPH);
2179  477 ssConsensus.autoCalculated=true;
2180  477 ssConsensus.hasData=false;
2181  477 ssConsensus.hasText=true;
2182    // Hide global ss consensus for all providers if only one provider is present
2183  477 ssConsensus.visible = ssSource.equals(Constants.SS_ALL_PROVIDERS) && singleProvider ? false : true;
2184   
2185  477 secondaryStructureConsensus.add(ssConsensus);
2186    }
2187   
2188    }
2189   
2190  535 initConsensus(consensus);
2191  535 initSSConsensus(secondaryStructureConsensus);
2192  535 initGapCounts();
2193  535 initComplementConsensus();
2194    }
2195    }
2196   
2197    /**
2198    * If this is a protein alignment and there are mappings to cDNA, adds the
2199    * cDNA consensus annotation and returns true, else returns false.
2200    */
 
2201  545 toggle public boolean initComplementConsensus()
2202    {
2203  545 if (!alignment.isNucleotide())
2204    {
2205  433 final List<AlignedCodonFrame> codonMappings = alignment
2206    .getCodonFrames();
2207  433 if (codonMappings != null && !codonMappings.isEmpty())
2208    {
2209  4 boolean doConsensus = false;
2210  4 for (AlignedCodonFrame mapping : codonMappings)
2211    {
2212    // TODO hold mapping type e.g. dna-to-protein in AlignedCodonFrame?
2213  4 MapList[] mapLists = mapping.getdnaToProt();
2214    // mapLists can be empty if project load has not finished resolving
2215    // seqs
2216  4 if (mapLists.length > 0 && mapLists[0].getFromRatio() == 3)
2217    {
2218  4 doConsensus = true;
2219  4 break;
2220    }
2221    }
2222  4 if (doConsensus)
2223    {
2224  4 Iterable<AlignmentAnnotation> annots = alignment
2225    .findAnnotations(null, null, "cDNA Consensus");
2226  4 if (annots != null && (complementConsensus == null))
2227    {
2228  4 for (AlignmentAnnotation ann : annots)
2229    {
2230  0 if (ann.autoCalculated)
2231    {
2232  0 complementConsensus = ann;
2233    }
2234    }
2235    }
2236  4 if (complementConsensus == null)
2237    {
2238  4 complementConsensus = new AlignmentAnnotation("cDNA Consensus",
2239    MessageManager
2240    .getString("label.complement_consensus_descr"),
2241    new Annotation[1], 0f, 100f,
2242    AlignmentAnnotation.BAR_GRAPH);
2243  4 initConsensus(complementConsensus);
2244    }
2245  4 return true;
2246    }
2247    }
2248    }
2249  541 return false;
2250    }
2251   
 
2252  539 toggle private void initConsensus(AlignmentAnnotation aa)
2253    {
2254  539 aa.hasText = true;
2255  539 aa.autoCalculated = true;
2256   
2257  539 if (showConsensus)
2258    {
2259  538 alignment.addAnnotation(aa);
2260    }
2261    }
2262   
 
2263  535 toggle private void initSSConsensus(
2264    List<AlignmentAnnotation> secondaryStructureConsensuses)
2265    {
2266  535 if (secondaryStructureConsensuses == null)
2267    {
2268  0 return;
2269    }
2270  535 for (AlignmentAnnotation aa : secondaryStructureConsensuses)
2271    {
2272  477 aa.hasText = true;
2273  477 aa.autoCalculated = true;
2274   
2275  477 if (showSSConsensus)
2276    {
2277  0 alignment.addAnnotation(aa);
2278    }
2279   
2280    }
2281    }
2282   
2283    // these should be extracted from the view model - style and settings for
2284    // derived annotation
 
2285  535 toggle private void initGapCounts()
2286    {
2287  535 if (showOccupancy)
2288    {
2289  531 gapcounts = new AlignmentAnnotation("Occupancy",
2290    MessageManager.getString("label.occupancy_descr"),
2291    new Annotation[1], 0f, alignment.getHeight(),
2292    AlignmentAnnotation.BAR_GRAPH);
2293  531 gapcounts.hasText = true;
2294  531 gapcounts.autoCalculated = true;
2295  531 gapcounts.scaleColLabel = true;
2296  531 gapcounts.graph = AlignmentAnnotation.BAR_GRAPH;
2297   
2298  531 alignment.addAnnotation(gapcounts);
2299    }
2300    }
2301   
 
2302  424 toggle private void initConservation()
2303    {
2304  424 if (showConservation)
2305    {
2306  423 if (conservation == null)
2307    {
2308  423 conservation = new AlignmentAnnotation("Conservation",
2309    MessageManager.formatMessage("label.conservation_descr",
2310    getConsPercGaps()),
2311    new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH);
2312  423 conservation.hasText = true;
2313  423 conservation.autoCalculated = true;
2314  423 alignment.addAnnotation(conservation);
2315    }
2316    }
2317    }
2318   
 
2319  424 toggle private void initQuality()
2320    {
2321  424 if (showQuality)
2322    {
2323  424 if (quality == null)
2324    {
2325  424 quality = new AlignmentAnnotation("Quality",
2326    MessageManager.getString("label.quality_descr"),
2327    new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH);
2328  424 quality.hasText = true;
2329  424 quality.autoCalculated = true;
2330  424 alignment.addAnnotation(quality);
2331    }
2332    }
2333    }
2334   
 
2335  111 toggle private void initRNAStructure()
2336    {
2337  111 if (alignment.hasRNAStructure() && strucConsensus == null)
2338    {
2339  2 strucConsensus = new AlignmentAnnotation("StrucConsensus",
2340    MessageManager.getString("label.strucconsensus_descr"),
2341    new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
2342  2 strucConsensus.hasText = true;
2343  2 strucConsensus.autoCalculated = true;
2344   
2345  2 if (showConsensus)
2346    {
2347  2 alignment.addAnnotation(strucConsensus);
2348    }
2349    }
2350    }
2351   
2352    /*
2353    * (non-Javadoc)
2354    *
2355    * @see jalview.api.AlignViewportI#calcPanelHeight()
2356    */
 
2357  5321 toggle @Override
2358    public int calcPanelHeight()
2359    {
2360    // setHeight of panels
2361  5322 AlignmentAnnotation[] anns = getAlignment().getAlignmentAnnotation();
2362  5322 int height = 0;
2363  5322 int charHeight = getCharHeight();
2364  5322 if (anns != null)
2365    {
2366  5322 BitSet graphgrp = new BitSet();
2367  5322 for (AlignmentAnnotation aa : anns)
2368    {
2369  27699 if (aa == null)
2370    {
2371  0 jalview.bin.Console.errPrintln("Null annotation row: ignoring.");
2372  0 continue;
2373    }
2374  27698 if (!aa.isForDisplay())
2375    {
2376  4109 continue;
2377    }
2378  23589 if (aa.graphGroup > -1)
2379    {
2380  390 if (graphgrp.get(aa.graphGroup))
2381    {
2382  195 continue;
2383    }
2384    else
2385    {
2386  195 graphgrp.set(aa.graphGroup);
2387    }
2388    }
2389  23394 aa.height = 0;
2390   
2391  23395 if (aa.hasText)
2392    {
2393  20226 aa.height += charHeight;
2394    }
2395   
2396  23394 if (aa.hasIcons)
2397    {
2398  1781 aa.height += 16;
2399    }
2400   
2401  23395 if (aa.graph > 0)
2402    {
2403  21050 aa.height += aa.graphHeight + 20;
2404    }
2405   
2406  23395 if (aa.height == 0)
2407    {
2408  158 aa.height = 20;
2409    }
2410   
2411  23395 height += aa.height;
2412    }
2413    }
2414  5322 if (height == 0)
2415    {
2416    // set minimum
2417  23 height = 20;
2418    }
2419  5322 return height;
2420    }
2421   
 
2422  135 toggle @Override
2423    public void updateGroupAnnotationSettings(boolean applyGlobalSettings,
2424    boolean preserveNewGroupSettings)
2425    {
2426  135 boolean updateCalcs = false;
2427  135 boolean conv = isShowGroupConservation();
2428  135 boolean cons = isShowGroupConsensus();
2429  135 boolean sscons = isShowGroupSSConsensus();
2430  135 boolean showprf = isShowSequenceLogo();
2431  135 boolean showConsHist = isShowConsensusHistogram();
2432  135 boolean normLogo = isNormaliseSequenceLogo();
2433   
2434    /**
2435    * TODO reorder the annotation rows according to group/sequence ordering on
2436    * alignment
2437    */
2438    // boolean sortg = true;
2439   
2440    // remove old automatic annotation
2441    // add any new annotation
2442   
2443    // intersect alignment annotation with alignment groups
2444   
2445  135 AlignmentAnnotation[] aan = alignment.getAlignmentAnnotation();
2446  135 List<SequenceGroup> oldrfs = new ArrayList<>();
2447  135 if (aan != null)
2448    {
2449  1375 for (int an = 0; an < aan.length; an++)
2450    {
2451  1240 if (aan[an].autoCalculated && aan[an].groupRef != null)
2452    {
2453  0 oldrfs.add(aan[an].groupRef);
2454  0 alignment.deleteAnnotation(aan[an], false);
2455    }
2456    }
2457    }
2458  135 if (alignment.getGroups() != null)
2459    {
2460  135 for (SequenceGroup sg : alignment.getGroups())
2461    {
2462  70 updateCalcs = false;
2463  70 if (applyGlobalSettings
2464    || (!preserveNewGroupSettings && !oldrfs.contains(sg)))
2465    {
2466    // set defaults for this group's conservation/consensus
2467  11 sg.setshowSequenceLogo(showprf);
2468  11 sg.setShowConsensusHistogram(showConsHist);
2469  11 sg.setNormaliseSequenceLogo(normLogo);
2470    }
2471  70 if (conv)
2472    {
2473  0 updateCalcs = true;
2474  0 alignment.addAnnotation(sg.getConservationRow(), 0);
2475    }
2476  70 if (cons)
2477    {
2478  24 updateCalcs = true;
2479  24 alignment.addAnnotation(sg.getConsensus(), 0);
2480    }
2481  70 if (sscons)
2482    {
2483  0 updateCalcs = true;
2484  0 List<String> secondaryStructureSources = getSecondaryStructureSources();
2485  0 if (secondaryStructureSources != null)
2486    {
2487  0 List<AlignmentAnnotation> ssAa = sg
2488    .getSSConsensus(secondaryStructureSources);
2489  0 if (ssAa != null)
2490    {
2491  0 for (AlignmentAnnotation aa : ssAa)
2492    {
2493    // Setting annotation visibility to true for the secondary
2494    // structure consensus for all providers
2495  0 if (aa.label.contains(Constants.SS_ALL_PROVIDERS))
2496    {
2497  0 aa.visible = true;
2498    }
2499  0 alignment.addAnnotation(aa, 0);
2500    }
2501    }
2502    }
2503    }
2504    // refresh the annotation rows
2505  70 if (updateCalcs)
2506    {
2507  24 sg.recalcConservation();
2508    }
2509    }
2510    }
2511  135 oldrfs.clear();
2512    }
2513   
 
2514  26318 toggle @Override
2515    public boolean isDisplayReferenceSeq()
2516    {
2517  26318 return alignment.hasSeqrep() && viewStyle.isDisplayReferenceSeq();
2518    }
2519   
 
2520  10 toggle @Override
2521    public void setDisplayReferenceSeq(boolean displayReferenceSeq)
2522    {
2523  10 viewStyle.setDisplayReferenceSeq(displayReferenceSeq);
2524    }
2525   
 
2526  5 toggle @Override
2527    public boolean isColourByReferenceSeq()
2528    {
2529  5 return alignment.hasSeqrep() && viewStyle.isColourByReferenceSeq();
2530    }
2531   
 
2532  36330 toggle @Override
2533    public Color getSequenceColour(SequenceI seq)
2534    {
2535  36330 Color sqc = sequenceColours.get(seq);
2536  36330 return (sqc == null ? Color.white : sqc);
2537    }
2538   
 
2539  1303 toggle @Override
2540    public void setSequenceColour(SequenceI seq, Color col)
2541    {
2542  1303 if (col == null)
2543    {
2544  0 sequenceColours.remove(seq);
2545    }
2546    else
2547    {
2548  1303 sequenceColours.put(seq, col);
2549    }
2550    }
2551   
 
2552  9 toggle @Override
2553    public void updateSequenceIdColours()
2554    {
2555  9 for (SequenceGroup sg : alignment.getGroups())
2556    {
2557  5 if (sg.idColour != null)
2558    {
2559  0 for (SequenceI s : sg.getSequences(getHiddenRepSequences()))
2560    {
2561  0 sequenceColours.put(s, sg.idColour);
2562    }
2563    }
2564    }
2565    }
2566   
 
2567  1 toggle @Override
2568    public void clearSequenceColours()
2569    {
2570  1 sequenceColours.clear();
2571    }
2572   
2573   
 
2574  0 toggle @Override
2575    public Color getAnnotationColour(AlignmentAnnotation annot)
2576    {
2577  0 Color annotColor = annotationColours.get(annot);
2578  0 return (annotColor == null ? Color.white : annotColor);
2579    }
2580   
 
2581  12 toggle @Override
2582    public void setAnnotationColour(AlignmentAnnotation annot, Color col)
2583    {
2584  12 if (col == null)
2585    {
2586  0 annotationColours.remove(annot);
2587  0 annot.setAnnotationGroupColour(Color.WHITE);
2588    }
2589    else
2590    {
2591  12 annotationColours.put(annot, col);
2592  12 annot.setAnnotationGroupColour(col);
2593    }
2594    }
2595   
 
2596  1261 toggle @Override
2597    public void updateAnnotationColours()
2598    {
2599  1261 for (SequenceGroup sg : alignment.getGroups())
2600    {
2601  930 if (sg.idColour != null)
2602    {
2603  925 for (AlignmentAnnotation annot : sg.getAlignmentAnnotation())
2604    {
2605  384 annotationColours.put(annot, sg.idColour);
2606  384 annot.setAnnotationGroupColour(sg.idColour);
2607    }
2608    }
2609    }
2610    }
2611   
 
2612  1 toggle @Override
2613    public void clearAnnotationColours()
2614    {
2615  1 for (AlignmentAnnotation annot : annotationColours.keySet())
2616    {
2617  4 annot.setAnnotationGroupColour(Color.WHITE);
2618    }
2619  1 annotationColours.clear();
2620    }
2621   
 
2622  0 toggle @Override
2623    public Map<AlignmentAnnotation, Color> getAnnotationColours()
2624    {
2625  0 return annotationColours;
2626    }
2627   
 
2628  0 toggle @Override
2629    public void setAnnotationColours(
2630    Map<AlignmentAnnotation, Color> annotationColours)
2631    {
2632  0 this.annotationColours = annotationColours;
2633    }
2634   
 
2635  1208 toggle @Override
2636    public AlignViewportI getCodingComplement()
2637    {
2638  1208 return this.codingComplement;
2639    }
2640   
2641    /**
2642    * Set this as the (cDna/protein) complement of the given viewport. Also
2643    * ensures the reverse relationship is set on the given viewport.
2644    */
 
2645  6 toggle @Override
2646    public void setCodingComplement(AlignViewportI av)
2647    {
2648  6 if (this == av)
2649    {
2650  0 jalview.bin.Console
2651    .errPrintln("Ignoring recursive setCodingComplement request");
2652    }
2653    else
2654    {
2655  6 this.codingComplement = av;
2656    // avoid infinite recursion!
2657  6 if (av.getCodingComplement() != this)
2658    {
2659  3 av.setCodingComplement(this);
2660    }
2661    }
2662    }
2663   
 
2664  25 toggle @Override
2665    public boolean isNucleotide()
2666    {
2667  25 return getAlignment() == null ? false : getAlignment().isNucleotide();
2668    }
2669   
 
2670  1363417 toggle @Override
2671    public FeaturesDisplayedI getFeaturesDisplayed()
2672    {
2673  1363422 return featuresDisplayed;
2674    }
2675   
 
2676  129 toggle @Override
2677    public void setFeaturesDisplayed(FeaturesDisplayedI featuresDisplayedI)
2678    {
2679  129 featuresDisplayed = featuresDisplayedI;
2680    }
2681   
 
2682  83 toggle @Override
2683    public boolean areFeaturesDisplayed()
2684    {
2685  83 return featuresDisplayed != null
2686    && featuresDisplayed.getRegisteredFeaturesCount() > 0;
2687    }
2688   
2689    /**
2690    * set the flag
2691    *
2692    * @param b
2693    * features are displayed if true
2694    */
 
2695  149 toggle @Override
2696    public void setShowSequenceFeatures(boolean b)
2697    {
2698  149 viewStyle.setShowSequenceFeatures(b);
2699    }
2700   
 
2701  517099 toggle @Override
2702    public boolean isShowSequenceFeatures()
2703    {
2704  517181 return viewStyle.isShowSequenceFeatures();
2705    }
2706   
 
2707  0 toggle @Override
2708    public void setShowSequenceFeaturesHeight(boolean selected)
2709    {
2710  0 viewStyle.setShowSequenceFeaturesHeight(selected);
2711    }
2712   
 
2713  0 toggle @Override
2714    public boolean isShowSequenceFeaturesHeight()
2715    {
2716  0 return viewStyle.isShowSequenceFeaturesHeight();
2717    }
2718   
 
2719  715 toggle @Override
2720    public void setShowAnnotation(boolean b)
2721    {
2722  715 viewStyle.setShowAnnotation(b);
2723    }
2724   
 
2725  4733 toggle @Override
2726    public boolean isShowAnnotation()
2727    {
2728  4733 return viewStyle.isShowAnnotation();
2729    }
2730   
 
2731  18670 toggle @Override
2732    public boolean isRightAlignIds()
2733    {
2734  18670 return viewStyle.isRightAlignIds();
2735    }
2736   
 
2737  624 toggle @Override
2738    public void setRightAlignIds(boolean rightAlignIds)
2739    {
2740  624 viewStyle.setRightAlignIds(rightAlignIds);
2741    }
2742   
 
2743  1091 toggle @Override
2744    public boolean getConservationSelected()
2745    {
2746  1091 return viewStyle.getConservationSelected();
2747    }
2748   
 
2749  89 toggle @Override
2750    public void setShowBoxes(boolean state)
2751    {
2752  89 viewStyle.setShowBoxes(state);
2753    }
2754   
2755    /**
2756    * @return
2757    * @see jalview.api.ViewStyleI#getTextColour()
2758    */
 
2759  650412 toggle @Override
2760    public Color getTextColour()
2761    {
2762  650413 return viewStyle.getTextColour();
2763    }
2764   
2765    /**
2766    * @return
2767    * @see jalview.api.ViewStyleI#getTextColour2()
2768    */
 
2769  48 toggle @Override
2770    public Color getTextColour2()
2771    {
2772  48 return viewStyle.getTextColour2();
2773    }
2774   
2775    /**
2776    * @return
2777    * @see jalview.api.ViewStyleI#getThresholdTextColour()
2778    */
 
2779  458135 toggle @Override
2780    public int getThresholdTextColour()
2781    {
2782  458135 return viewStyle.getThresholdTextColour();
2783    }
2784   
2785    /**
2786    * @return
2787    * @see jalview.api.ViewStyleI#isConservationColourSelected()
2788    */
 
2789  0 toggle @Override
2790    public boolean isConservationColourSelected()
2791    {
2792  0 return viewStyle.isConservationColourSelected();
2793    }
2794   
2795    /**
2796    * @return
2797    * @see jalview.api.ViewStyleI#isRenderGaps()
2798    */
 
2799  3256 toggle @Override
2800    public boolean isRenderGaps()
2801    {
2802  3256 return viewStyle.isRenderGaps();
2803    }
2804   
2805    /**
2806    * @return
2807    * @see jalview.api.ViewStyleI#isShowColourText()
2808    */
 
2809  707 toggle @Override
2810    public boolean isShowColourText()
2811    {
2812  707 return viewStyle.isShowColourText();
2813    }
2814   
2815    /**
2816    * @param conservationColourSelected
2817    * @see jalview.api.ViewStyleI#setConservationColourSelected(boolean)
2818    */
 
2819  0 toggle @Override
2820    public void setConservationColourSelected(
2821    boolean conservationColourSelected)
2822    {
2823  0 viewStyle.setConservationColourSelected(conservationColourSelected);
2824    }
2825   
2826    /**
2827    * @param showColourText
2828    * @see jalview.api.ViewStyleI#setShowColourText(boolean)
2829    */
 
2830  0 toggle @Override
2831    public void setShowColourText(boolean showColourText)
2832    {
2833  0 viewStyle.setShowColourText(showColourText);
2834    }
2835   
2836    /**
2837    * @param textColour
2838    * @see jalview.api.ViewStyleI#setTextColour(java.awt.Color)
2839    */
 
2840  89 toggle @Override
2841    public void setTextColour(Color textColour)
2842    {
2843  89 viewStyle.setTextColour(textColour);
2844    }
2845   
2846    /**
2847    * @param thresholdTextColour
2848    * @see jalview.api.ViewStyleI#setThresholdTextColour(int)
2849    */
 
2850  89 toggle @Override
2851    public void setThresholdTextColour(int thresholdTextColour)
2852    {
2853  89 viewStyle.setThresholdTextColour(thresholdTextColour);
2854    }
2855   
2856    /**
2857    * @param textColour2
2858    * @see jalview.api.ViewStyleI#setTextColour2(java.awt.Color)
2859    */
 
2860  89 toggle @Override
2861    public void setTextColour2(Color textColour2)
2862    {
2863  89 viewStyle.setTextColour2(textColour2);
2864    }
2865   
 
2866  149 toggle @Override
2867    public ViewStyleI getViewStyle()
2868    {
2869  149 return new ViewStyle(viewStyle);
2870    }
2871   
 
2872  90 toggle @Override
2873    public void setViewStyle(ViewStyleI settingsForView)
2874    {
2875  90 viewStyle = new ViewStyle(settingsForView);
2876  90 if (residueShading != null)
2877    {
2878  90 residueShading.setConservationApplied(
2879    settingsForView.isConservationColourSelected());
2880    }
2881    }
2882   
 
2883  0 toggle @Override
2884    public boolean sameStyle(ViewStyleI them)
2885    {
2886  0 return viewStyle.sameStyle(them);
2887    }
2888   
2889    /**
2890    * @return
2891    * @see jalview.api.ViewStyleI#getIdWidth()
2892    */
 
2893  6671 toggle @Override
2894    public int getIdWidth()
2895    {
2896  6671 return viewStyle.getIdWidth();
2897    }
2898   
2899    /**
2900    * @param i
2901    * @see jalview.api.ViewStyleI#setIdWidth(int)
2902    */
 
2903  1038 toggle @Override
2904    public void setIdWidth(int i)
2905    {
2906  1038 viewStyle.setIdWidth(i);
2907    }
2908   
2909    /**
2910    * @return
2911    * @see jalview.api.ViewStyleI#isCentreColumnLabels()
2912    */
 
2913  707 toggle @Override
2914    public boolean isCentreColumnLabels()
2915    {
2916  707 return viewStyle.isCentreColumnLabels();
2917    }
2918   
2919    /**
2920    * @param centreColumnLabels
2921    * @see jalview.api.ViewStyleI#setCentreColumnLabels(boolean)
2922    */
 
2923  624 toggle @Override
2924    public void setCentreColumnLabels(boolean centreColumnLabels)
2925    {
2926  624 viewStyle.setCentreColumnLabels(centreColumnLabels);
2927    }
2928   
2929    /**
2930    * @param showdbrefs
2931    * @see jalview.api.ViewStyleI#setShowDBRefs(boolean)
2932    */
 
2933  624 toggle @Override
2934    public void setShowDBRefs(boolean showdbrefs)
2935    {
2936  624 viewStyle.setShowDBRefs(showdbrefs);
2937    }
2938   
2939    /**
2940    * @return
2941    * @see jalview.api.ViewStyleI#isShowDBRefs()
2942    */
 
2943  755 toggle @Override
2944    public boolean isShowDBRefs()
2945    {
2946  755 return viewStyle.isShowDBRefs();
2947    }
2948   
2949    /**
2950    * @return
2951    * @see jalview.api.ViewStyleI#isShowNPFeats()
2952    */
 
2953  755 toggle @Override
2954    public boolean isShowNPFeats()
2955    {
2956  755 return viewStyle.isShowNPFeats();
2957    }
2958   
2959    /**
2960    * @param shownpfeats
2961    * @see jalview.api.ViewStyleI#setShowNPFeats(boolean)
2962    */
 
2963  624 toggle @Override
2964    public void setShowNPFeats(boolean shownpfeats)
2965    {
2966  624 viewStyle.setShowNPFeats(shownpfeats);
2967    }
2968   
2969    public abstract StructureSelectionManager getStructureSelectionManager();
2970   
2971    /**
2972    * Add one command to the command history list.
2973    *
2974    * @param command
2975    */
 
2976  1 toggle public void addToHistoryList(CommandI command)
2977    {
2978  1 if (this.historyList != null)
2979    {
2980  1 this.historyList.push(command);
2981  1 broadcastCommand(command, false);
2982  1 setSavedUpToDate(false);
2983  1 Jalview2XML.setStateSavedUpToDate(false);
2984    }
2985    }
2986   
 
2987  1 toggle protected void broadcastCommand(CommandI command, boolean undo)
2988    {
2989  1 getStructureSelectionManager().commandPerformed(command, undo,
2990    getVamsasSource());
2991    }
2992   
2993    /**
2994    * Add one command to the command redo list.
2995    *
2996    * @param command
2997    */
 
2998  0 toggle public void addToRedoList(CommandI command)
2999    {
3000  0 if (this.redoList != null)
3001    {
3002  0 this.redoList.push(command);
3003    }
3004  0 broadcastCommand(command, true);
3005    }
3006   
3007    /**
3008    * Clear the command redo list.
3009    */
 
3010  1 toggle public void clearRedoList()
3011    {
3012  1 if (this.redoList != null)
3013    {
3014  1 this.redoList.clear();
3015    }
3016    }
3017   
 
3018  53 toggle public void setHistoryList(Deque<CommandI> list)
3019    {
3020  53 this.historyList = list;
3021    }
3022   
 
3023  1659 toggle public Deque<CommandI> getHistoryList()
3024    {
3025  1659 return this.historyList;
3026    }
3027   
 
3028  53 toggle public void setRedoList(Deque<CommandI> list)
3029    {
3030  53 this.redoList = list;
3031    }
3032   
 
3033  1656 toggle public Deque<CommandI> getRedoList()
3034    {
3035  1656 return this.redoList;
3036    }
3037   
 
3038  1 toggle @Override
3039    public VamsasSource getVamsasSource()
3040    {
3041  1 return this;
3042    }
3043   
 
3044  7648 toggle public SequenceAnnotationOrder getSortAnnotationsBy()
3045    {
3046  7648 return sortAnnotationsBy;
3047    }
3048   
 
3049  0 toggle public void setSortAnnotationsBy(
3050    SequenceAnnotationOrder sortAnnotationsBy)
3051    {
3052  0 this.sortAnnotationsBy = sortAnnotationsBy;
3053    }
3054   
 
3055  7648 toggle public boolean isShowAutocalculatedAbove()
3056    {
3057  7648 return showAutocalculatedAbove;
3058    }
3059   
 
3060  479 toggle public void setShowAutocalculatedAbove(boolean showAutocalculatedAbove)
3061    {
3062  479 this.showAutocalculatedAbove = showAutocalculatedAbove;
3063    }
3064   
 
3065  3 toggle @Override
3066    public boolean isScaleProteinAsCdna()
3067    {
3068  3 return viewStyle.isScaleProteinAsCdna();
3069    }
3070   
 
3071  0 toggle @Override
3072    public void setScaleProteinAsCdna(boolean b)
3073    {
3074  0 viewStyle.setScaleProteinAsCdna(b);
3075    }
3076   
 
3077  0 toggle @Override
3078    public boolean isProteinFontAsCdna()
3079    {
3080  0 return viewStyle.isProteinFontAsCdna();
3081    }
3082   
 
3083  0 toggle @Override
3084    public void setProteinFontAsCdna(boolean b)
3085    {
3086  0 viewStyle.setProteinFontAsCdna(b);
3087    }
3088   
 
3089  89 toggle @Override
3090    public void setShowComplementFeatures(boolean b)
3091    {
3092  89 viewStyle.setShowComplementFeatures(b);
3093    }
3094   
 
3095  516668 toggle @Override
3096    public boolean isShowComplementFeatures()
3097    {
3098  516746 return viewStyle.isShowComplementFeatures();
3099    }
3100   
 
3101  89 toggle @Override
3102    public void setShowComplementFeaturesOnTop(boolean b)
3103    {
3104  89 viewStyle.setShowComplementFeaturesOnTop(b);
3105    }
3106   
 
3107  49 toggle @Override
3108    public boolean isShowComplementFeaturesOnTop()
3109    {
3110  49 return viewStyle.isShowComplementFeaturesOnTop();
3111    }
3112   
3113    /**
3114    * @return true if view should scroll to show the highlighted region of a
3115    * sequence
3116    * @return
3117    */
 
3118  51 toggle @Override
3119    public final boolean isFollowHighlight()
3120    {
3121  51 return followHighlight;
3122    }
3123   
 
3124  89 toggle @Override
3125    public final void setFollowHighlight(boolean b)
3126    {
3127  89 this.followHighlight = b;
3128    }
3129   
 
3130  40162 toggle @Override
3131    public ViewportRanges getRanges()
3132    {
3133  40162 return ranges;
3134    }
3135   
3136    /**
3137    * Helper method to populate the SearchResults with the location in the
3138    * complementary alignment to scroll to, in order to match this one.
3139    *
3140    * @param sr
3141    * the SearchResults to add to
3142    * @return the offset (below top of visible region) of the matched sequence
3143    */
 
3144  770 toggle protected int findComplementScrollTarget(SearchResultsI sr)
3145    {
3146  770 final AlignViewportI complement = getCodingComplement();
3147  770 if (complement == null || !complement.isFollowHighlight())
3148    {
3149  768 return 0;
3150    }
3151  2 boolean iAmProtein = !getAlignment().isNucleotide();
3152  2 AlignmentI proteinAlignment = iAmProtein ? getAlignment()
3153    : complement.getAlignment();
3154  2 if (proteinAlignment == null)
3155    {
3156  0 return 0;
3157    }
3158  2 final List<AlignedCodonFrame> mappings = proteinAlignment
3159    .getCodonFrames();
3160   
3161    /*
3162    * Heuristic: find the first mapped sequence (if any) with a non-gapped
3163    * residue in the middle column of the visible region. Scroll the
3164    * complementary alignment to line up the corresponding residue.
3165    */
3166  2 int seqOffset = 0;
3167  2 SequenceI sequence = null;
3168   
3169    /*
3170    * locate 'middle' column (true middle if an odd number visible, left of
3171    * middle if an even number visible)
3172    */
3173  2 int middleColumn = ranges.getStartRes()
3174    + (ranges.getEndRes() - ranges.getStartRes()) / 2;
3175  2 final HiddenSequences hiddenSequences = getAlignment()
3176    .getHiddenSequences();
3177   
3178    /*
3179    * searching to the bottom of the alignment gives smoother scrolling across
3180    * all gapped visible regions
3181    */
3182  2 int lastSeq = alignment.getHeight() - 1;
3183  2 List<AlignedCodonFrame> seqMappings = null;
3184  2 for (int seqNo = ranges
3185  2 .getStartSeq(); seqNo <= lastSeq; seqNo++, seqOffset++)
3186    {
3187  2 sequence = getAlignment().getSequenceAt(seqNo);
3188  2 if (hiddenSequences != null && hiddenSequences.isHidden(sequence))
3189    {
3190  0 continue;
3191    }
3192  2 if (Comparison.isGap(sequence.getCharAt(middleColumn)))
3193    {
3194  0 continue;
3195    }
3196  2 seqMappings = MappingUtils.findMappingsForSequenceAndOthers(sequence,
3197    mappings,
3198    getCodingComplement().getAlignment().getSequences());
3199  2 if (!seqMappings.isEmpty())
3200    {
3201  2 break;
3202    }
3203    }
3204   
3205  2 if (sequence == null || seqMappings == null || seqMappings.isEmpty())
3206    {
3207    /*
3208    * No ungapped mapped sequence in middle column - do nothing
3209    */
3210  0 return 0;
3211    }
3212  2 MappingUtils.addSearchResults(sr, sequence,
3213    sequence.findPosition(middleColumn), seqMappings);
3214  2 return seqOffset;
3215    }
3216   
3217    /**
3218    * synthesize a column selection if none exists so it covers the given
3219    * selection group. if wholewidth is false, no column selection is made if the
3220    * selection group covers the whole alignment width.
3221    *
3222    * @param sg
3223    * @param wholewidth
3224    */
 
3225  0 toggle public void expandColSelection(SequenceGroup sg, boolean wholewidth)
3226    {
3227  0 int sgs, sge;
3228  0 if (sg != null && (sgs = sg.getStartRes()) >= 0
3229    && sg.getStartRes() <= (sge = sg.getEndRes())
3230    && !this.hasSelectedColumns())
3231    {
3232  0 if (!wholewidth && alignment.getWidth() == (1 + sge - sgs))
3233    {
3234    // do nothing
3235  0 return;
3236    }
3237  0 if (colSel == null)
3238    {
3239  0 colSel = new ColumnSelection();
3240    }
3241  0 for (int cspos = sg.getStartRes(); cspos <= sg.getEndRes(); cspos++)
3242    {
3243  0 colSel.addElement(cspos);
3244    }
3245    }
3246    }
3247   
3248    /**
3249    * hold status of current selection group - defined on alignment or not.
3250    */
3251    private boolean selectionIsDefinedGroup = false;
3252   
 
3253  0 toggle @Override
3254    public boolean isSelectionDefinedGroup()
3255    {
3256  0 if (selectionGroup == null)
3257    {
3258  0 return false;
3259    }
3260  0 if (isSelectionGroupChanged(true))
3261    {
3262  0 selectionIsDefinedGroup = false;
3263  0 List<SequenceGroup> gps = alignment.getGroups();
3264  0 if (gps == null || gps.size() == 0)
3265    {
3266  0 selectionIsDefinedGroup = false;
3267    }
3268    else
3269    {
3270  0 selectionIsDefinedGroup = gps.contains(selectionGroup);
3271    }
3272    }
3273  0 return selectionGroup.isDefined() || selectionIsDefinedGroup;
3274    }
3275   
3276    /**
3277    * null, or currently highlighted results on this view
3278    */
3279    private SearchResultsI searchResults = null;
3280   
3281    protected TreeModel currentTree = null;
3282   
 
3283  11500 toggle @Override
3284    public boolean hasSearchResults()
3285    {
3286  11500 return searchResults != null;
3287    }
3288   
 
3289  7 toggle @Override
3290    public void setSearchResults(SearchResultsI results)
3291    {
3292  7 searchResults = results;
3293    }
3294   
 
3295  50 toggle @Override
3296    public SearchResultsI getSearchResults()
3297    {
3298  50 return searchResults;
3299    }
3300   
 
3301  4834 toggle @Override
3302    public ContactListI getContactList(AlignmentAnnotation _aa, int column)
3303    {
3304  4834 return alignment.getContactListFor(_aa, column);
3305    }
3306   
 
3307  152 toggle @Override
3308    public ContactMatrixI getContactMatrix(
3309    AlignmentAnnotation alignmentAnnotation)
3310    {
3311  152 return alignment.getContactMatrixFor(alignmentAnnotation);
3312    }
3313   
3314    /**
3315    * get the consensus sequence as displayed under the PID consensus annotation
3316    * row.
3317    *
3318    * @return consensus sequence as a new sequence object
3319    */
 
3320  1 toggle public SequenceI getConsensusSeq()
3321    {
3322  1 if (consensus == null)
3323    {
3324  0 updateConsensus(null);
3325    }
3326  1 if (consensus == null)
3327    {
3328  0 return null;
3329    }
3330  1 StringBuffer seqs = new StringBuffer();
3331  4 for (int i = 0; i < consensus.annotations.length; i++)
3332    {
3333  3 Annotation annotation = consensus.annotations[i];
3334  3 if (annotation != null)
3335    {
3336  3 String description = annotation.description;
3337  3 if (description != null && description.startsWith("["))
3338    {
3339    // consensus is a tie - just pick the first one
3340  1 seqs.append(description.charAt(1));
3341    }
3342    else
3343    {
3344  2 seqs.append(annotation.displayCharacter);
3345    }
3346    }
3347    }
3348   
3349  1 SequenceI sq = new Sequence("Consensus", seqs.toString());
3350  1 sq.setDescription("Percentage Identity Consensus "
3351  1 + ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
3352  1 return sq;
3353    }
3354   
3355    // to do jal-4386
 
3356  0 toggle public SequenceI getSSConsensusSeq()
3357    {
3358  0 if (secondaryStructureConsensus == null)
3359    {
3360  0 updateSecondaryStructureConsensus(null);
3361    }
3362  0 if (secondaryStructureConsensus == null)
3363    {
3364  0 return null;
3365    }
3366  0 StringBuffer seqs = new StringBuffer();
3367    // for (int i = 0; i < secondaryStructureConsensus.annotations.length; i++)
3368    // {
3369    // Annotation annotation = secondaryStructureConsensus.annotations[i];
3370    // if (annotation != null)
3371    // {
3372    // String description = annotation.description;
3373    // if (description != null && description.startsWith("["))
3374    // {
3375    // // consensus is a tie - just pick the first one
3376    // seqs.append(description.charAt(1));
3377    // }
3378    // else
3379    // {
3380    // seqs.append(annotation.displayCharacter);
3381    // }
3382    // }
3383    // }
3384   
3385  0 SequenceI sq = new Sequence("Sec Str Consensus", seqs.toString());
3386  0 sq.setDescription("Percentage Identity Sec Str Consensus "
3387  0 + ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
3388  0 return sq;
3389    }
3390   
 
3391  24 toggle @Override
3392    public void setCurrentTree(TreeModel tree)
3393    {
3394  24 currentTree = tree;
3395    }
3396   
 
3397  54 toggle @Override
3398    public TreeModel getCurrentTree()
3399    {
3400  54 return currentTree;
3401    }
3402   
 
3403  121 toggle @Override
3404    public AlignmentExportData getAlignExportData(
3405    AlignExportSettingsI options)
3406    {
3407  121 AlignmentI alignmentToExport = null;
3408  121 String[] omitHidden = null;
3409  121 alignmentToExport = null;
3410   
3411  121 if (hasHiddenColumns() && !options.isExportHiddenColumns())
3412    {
3413  0 omitHidden = getViewAsString(false,
3414    options.isExportHiddenSequences());
3415    }
3416   
3417  121 int[] alignmentStartEnd = new int[2];
3418  121 if (hasHiddenRows() && options.isExportHiddenSequences())
3419    {
3420  0 alignmentToExport = getAlignment().getHiddenSequences()
3421    .getFullAlignment();
3422    }
3423    else
3424    {
3425  121 alignmentToExport = getAlignment();
3426    }
3427  121 alignmentStartEnd = getAlignment().getHiddenColumns()
3428    .getVisibleStartAndEndIndex(alignmentToExport.getWidth());
3429  121 AlignmentExportData ed = new AlignmentExportData(alignmentToExport,
3430    omitHidden, alignmentStartEnd);
3431  121 return ed;
3432    }
3433   
3434    /**
3435    * flag set to indicate if structure views might be out of sync with sequences
3436    * in the alignment
3437    */
3438   
3439    private boolean needToUpdateStructureViews = false;
3440   
 
3441  0 toggle @Override
3442    public boolean isUpdateStructures()
3443    {
3444  0 return needToUpdateStructureViews;
3445    }
3446   
 
3447  3 toggle @Override
3448    public void setUpdateStructures(boolean update)
3449    {
3450  3 needToUpdateStructureViews = update;
3451    }
3452   
 
3453  2175 toggle @Override
3454    public boolean needToUpdateStructureViews()
3455    {
3456  2175 boolean update = needToUpdateStructureViews;
3457  2175 needToUpdateStructureViews = false;
3458  2175 return update;
3459    }
3460   
 
3461  2 toggle @Override
3462    public void addSequenceGroup(SequenceGroup sequenceGroup)
3463    {
3464  2 alignment.addGroup(sequenceGroup);
3465   
3466  2 Color col = sequenceGroup.idColour;
3467  2 if (col != null)
3468    {
3469  2 col = col.brighter();
3470   
3471  2 for (SequenceI sq : sequenceGroup.getSequences())
3472    {
3473  15 setSequenceColour(sq, col);
3474    }
3475   
3476  2 List<AlignmentAnnotation> annotations = sequenceGroup.getAnnotationsFromTree();
3477  2 if (annotations != null) {
3478  2 for (AlignmentAnnotation annot : annotations) {
3479  4 setAnnotationColour(annot, col);
3480    }
3481    }
3482    }
3483   
3484  2 if (codingComplement != null)
3485    {
3486  0 SequenceGroup mappedGroup = MappingUtils
3487    .mapSequenceGroup(sequenceGroup, this, codingComplement);
3488  0 if (mappedGroup.getSequences().size() > 0)
3489    {
3490  0 codingComplement.getAlignment().addGroup(mappedGroup);
3491   
3492  0 if (col != null)
3493    {
3494  0 for (SequenceI seq : mappedGroup.getSequences())
3495    {
3496  0 codingComplement.setSequenceColour(seq, col);
3497    }
3498    }
3499    }
3500    // propagate the structure view update flag according to our own setting
3501  0 codingComplement.setUpdateStructures(needToUpdateStructureViews);
3502    }
3503    }
3504   
 
3505  34 toggle @Override
3506    public Iterator<int[]> getViewAsVisibleContigs(boolean selectedRegionOnly)
3507    {
3508  34 int start = 0;
3509  34 int end = 0;
3510  34 if (selectedRegionOnly && selectionGroup != null)
3511    {
3512  4 start = selectionGroup.getStartRes();
3513  4 end = selectionGroup.getEndRes() + 1;
3514    }
3515    else
3516    {
3517  30 end = alignment.getWidth();
3518    }
3519  34 return (alignment.getHiddenColumns().getVisContigsIterator(start, end,
3520    false));
3521    }
3522   
 
3523  133 toggle public void setSavedUpToDate(boolean s)
3524    {
3525  133 setSavedUpToDate(s, QuitHandler.Message.UNSAVED_CHANGES);
3526    }
3527   
 
3528  475 toggle public void setSavedUpToDate(boolean s, QuitHandler.Message m)
3529    {
3530  475 Console.debug(
3531    "Setting " + this.getViewId() + " setSavedUpToDate to " + s);
3532  475 savedUpToDate = s;
3533  475 QuitHandler.setMessage(m);
3534    }
3535   
 
3536  4 toggle public boolean savedUpToDate()
3537    {
3538  4 Console.debug("Returning " + this.getViewId() + " savedUpToDate value: "
3539    + savedUpToDate);
3540  4 return savedUpToDate;
3541    }
3542    }