Clover icon

Coverage Report

  1. Project Clover database Thu Nov 7 2024 17:01:39 GMT
  2. Package jalview.viewmodel

File AlignmentViewport.java

 

Coverage histogram

../../img/srcFileCovDistChart0.png
0% of files have more coverage

Code metrics

326
745
247
1
3,320
2,262
460
0.62
3.02
247
1.86

Classes

Class Line # Actions
AlignmentViewport 89 745 460
0.00%
 

Contributing tests

No tests hitting this source file were found.

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