Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.viewmodel

File AlignmentViewport.java

 

Coverage histogram

../../img/srcFileCovDistChart7.png
28% of files have more coverage

Code metrics

290
654
219
1
2,989
1,998
410
0.63
2.99
219
1.87

Classes

Class Line # Actions
AlignmentViewport 83 654 410 343
0.7050730670.5%
 

Contributing tests

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