Clover icon

Coverage Report

  1. Project Clover database Mon Nov 18 2024 09:38:20 GMT
  2. Package jalview.viewmodel

File AlignmentViewport.java

 

Coverage histogram

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

Code metrics

356
801
259
1
3,545
2,426
486
0.61
3.09
259
1.88

Classes

Class Line # Actions
AlignmentViewport 93 801 486
0.667372966.7%
 

Contributing tests

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