Clover icon

Coverage Report

  1. Project Clover database Thu Nov 27 2025 17:07:57 GMT
  2. Package jalview.viewmodel

File AlignmentViewport.java

 

Coverage histogram

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

Code metrics

356
811
258
1
3,547
2,435
486
0.6
3.14
258
1.88

Classes

Class Line # Actions
AlignmentViewport 92 811 486
0.762105376.2%
 

Contributing tests

This file is covered by 312 tests. .

Source view

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