JAL-975 - bespoke AACons settings object to save current service settings for the...
[jalview.git] / src / jalview / gui / AlignViewport.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
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 of the License, or (at your option) any later version.
10  * 
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 /*
19  * Jalview - A Sequence Alignment Editor and Viewer
20  * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
21  *
22  * This program is free software; you can redistribute it and/or
23  * modify it under the terms of the GNU General Public License
24  * as published by the Free Software Foundation; either version 2
25  * of the License, or (at your option) any later version.
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30  * GNU General Public License for more details.
31  *
32  * You should have received a copy of the GNU General Public License
33  * along with this program; if not, write to the Free Software
34  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
35  */
36 package jalview.gui;
37
38 import java.util.*;
39
40 import java.awt.*;
41
42 import jalview.analysis.*;
43 import jalview.api.AlignCalcManagerI;
44 import jalview.api.AlignViewportI;
45 import jalview.api.AlignmentViewPanel;
46 import jalview.api.OOMHandlerI;
47
48 import jalview.bin.*;
49
50 import jalview.datamodel.*;
51
52 import jalview.schemes.*;
53 import jalview.structure.SelectionSource;
54 import jalview.structure.StructureSelectionManager;
55 import jalview.structure.VamsasSource;
56 import jalview.viewmodel.AlignmentViewport;
57 import jalview.workers.AlignCalcManager;
58 import jalview.workers.ConsensusThread;
59 import jalview.workers.ConservationThread;
60 import jalview.workers.StrucConsensusThread;
61
62 /**
63  * DOCUMENT ME!
64  * 
65  * @author $author$
66  * @version $Revision: 1.141 $
67  */
68 public class AlignViewport extends AlignmentViewport implements SelectionSource, VamsasSource, AlignViewportI
69 {
70   int startRes;
71
72   int endRes;
73
74   int startSeq;
75
76   int endSeq;
77
78   boolean showJVSuffix = true;
79
80   boolean showText = true;
81
82   boolean showColourText = false;
83
84   boolean showBoxes = true;
85
86   boolean wrapAlignment = false;
87
88   boolean renderGaps = true;
89
90   boolean showSequenceFeatures = false;
91
92   boolean showAnnotation = true;
93
94   int charHeight;
95
96   int charWidth;
97
98   boolean validCharWidth;
99
100   int wrappedWidth;
101
102   Font font;
103
104   boolean seqNameItalics;
105
106
107   NJTree currentTree = null;
108
109   boolean scaleAboveWrapped = false;
110
111   boolean scaleLeftWrapped = true;
112
113   boolean scaleRightWrapped = true;
114
115   boolean showHiddenMarkers = true;
116
117   boolean cursorMode = false;
118
119   /**
120    * Keys are the feature types which are currently visible. Note: Values are
121    * not used!
122    */
123   Hashtable featuresDisplayed = null;
124
125   boolean antiAlias = false;
126
127   Rectangle explodedPosition;
128
129   String viewName;
130
131   boolean gatherViewsHere = false;
132
133   Stack historyList = new Stack();
134
135   Stack redoList = new Stack();
136
137   Hashtable sequenceColours;
138
139   int thresholdTextColour = 0;
140
141   Color textColour = Color.black;
142
143   Color textColour2 = Color.white;
144
145   boolean rightAlignIds = false;
146
147   /**
148    * Creates a new AlignViewport object.
149    * 
150    * @param al
151    *          alignment to view
152    */
153   public AlignViewport(AlignmentI al)
154   {
155     setAlignment(al);
156     init();
157   }
158
159   /**
160    * Create a new AlignViewport object with a specific sequence set ID
161    * 
162    * @param al
163    * @param seqsetid
164    *          (may be null - but potential for ambiguous constructor exception)
165    */
166   public AlignViewport(AlignmentI al, String seqsetid)
167   {
168     this(al, seqsetid, null);
169   }
170
171   public AlignViewport(AlignmentI al, String seqsetid, String viewid)
172   {
173     sequenceSetID = seqsetid;
174     viewId = viewid;
175     // TODO remove these once 2.4.VAMSAS release finished
176     if (Cache.log != null && Cache.log.isDebugEnabled() && seqsetid != null)
177     {
178       Cache.log.debug("Setting viewport's sequence set id : "
179               + sequenceSetID);
180     }
181     if (Cache.log != null && Cache.log.isDebugEnabled() && viewId != null)
182     {
183       Cache.log.debug("Setting viewport's view id : " + viewId);
184     }
185     setAlignment(al);
186     init();
187   }
188
189   /**
190    * Create a new AlignViewport with hidden regions
191    * 
192    * @param al
193    *          AlignmentI
194    * @param hiddenColumns
195    *          ColumnSelection
196    */
197   public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns)
198   {
199     setAlignment(al);
200     if (hiddenColumns != null)
201     {
202       this.colSel = hiddenColumns;
203       if (hiddenColumns.getHiddenColumns() != null
204               && hiddenColumns.getHiddenColumns().size() > 0)
205       {
206         hasHiddenColumns = true;
207       }
208       else
209       {
210         hasHiddenColumns = false;
211       }
212     }
213     init();
214   }
215
216   /**
217    * New viewport with hidden columns and an existing sequence set id
218    * 
219    * @param al
220    * @param hiddenColumns
221    * @param seqsetid
222    *          (may be null)
223    */
224   public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns,
225           String seqsetid)
226   {
227     this(al, hiddenColumns, seqsetid, null);
228   }
229
230   /**
231    * New viewport with hidden columns and an existing sequence set id and viewid
232    * 
233    * @param al
234    * @param hiddenColumns
235    * @param seqsetid
236    *          (may be null)
237    * @param viewid
238    *          (may be null)
239    */
240   public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns,
241           String seqsetid, String viewid)
242   {
243     sequenceSetID = seqsetid;
244     viewId = viewid;
245     // TODO remove these once 2.4.VAMSAS release finished
246     if (Cache.log != null && Cache.log.isDebugEnabled() && seqsetid != null)
247     {
248       Cache.log.debug("Setting viewport's sequence set id : "
249               + sequenceSetID);
250     }
251     if (Cache.log != null && Cache.log.isDebugEnabled() && viewId != null)
252     {
253       Cache.log.debug("Setting viewport's view id : " + viewId);
254     }
255     setAlignment(al);
256     if (hiddenColumns != null)
257     {
258       this.colSel = hiddenColumns;
259       if (hiddenColumns.getHiddenColumns() != null
260               && hiddenColumns.getHiddenColumns().size() > 0)
261       {
262         hasHiddenColumns = true;
263       }
264       else
265       {
266         hasHiddenColumns = false;
267       }
268     }
269     init();
270   }
271
272   void init()
273   {
274     this.startRes = 0;
275     this.endRes = alignment.getWidth() - 1;
276     this.startSeq = 0;
277     this.endSeq = alignment.getHeight() - 1;
278
279     antiAlias = Cache.getDefault("ANTI_ALIAS", false);
280
281     showJVSuffix = Cache.getDefault("SHOW_JVSUFFIX", true);
282     showAnnotation = Cache.getDefault("SHOW_ANNOTATIONS", true);
283
284     rightAlignIds = Cache.getDefault("RIGHT_ALIGN_IDS", false);
285     centreColumnLabels = Cache.getDefault("CENTRE_COLUMN_LABELS", false);
286     autoCalculateConsensus = Cache.getDefault("AUTO_CALC_CONSENSUS", true);
287
288     setPadGaps(Cache.getDefault("PAD_GAPS", true));
289     shownpfeats = Cache.getDefault("SHOW_NPFEATS_TOOLTIP", true);
290     showdbrefs = Cache.getDefault("SHOW_DBREFS_TOOLTIP", true);
291
292     String fontName = Cache.getDefault("FONT_NAME", "SansSerif");
293     String fontStyle = Cache.getDefault("FONT_STYLE", Font.PLAIN + "");
294     String fontSize = Cache.getDefault("FONT_SIZE", "10");
295
296     seqNameItalics = Cache.getDefault("ID_ITALICS", true);
297
298     int style = 0;
299
300     if (fontStyle.equals("bold"))
301     {
302       style = 1;
303     }
304     else if (fontStyle.equals("italic"))
305     {
306       style = 2;
307     }
308
309     setFont(new Font(fontName, style, Integer.parseInt(fontSize)));
310
311     alignment
312             .setGapCharacter(Cache.getDefault("GAP_SYMBOL", "-").charAt(0));
313
314     // We must set conservation and consensus before setting colour,
315     // as Blosum and Clustal require this to be done
316     if (hconsensus == null && !isDataset)
317     {
318       if (!alignment.isNucleotide())
319       {
320         showConservation=Cache.getDefault("SHOW_CONSERVATION", true);
321         showQuality=Cache.getDefault("SHOW_QUALITY", true);
322         showGroupConservation = Cache.getDefault("SHOW_GROUP_CONSERVATION",
323                 false);
324       } 
325       showConsensusHistogram = Cache.getDefault("SHOW_CONSENSUS_HISTOGRAM",
326               true);
327       showSequenceLogo = Cache.getDefault("SHOW_CONSENSUS_LOGO", false);
328       normaliseSequenceLogo = Cache.getDefault("NORMALISE_CONSENSUS_LOGO", false);
329       showGroupConsensus = Cache.getDefault("SHOW_GROUP_CONSENSUS", false);
330       showConsensus=Cache.getDefault("SHOW_IDENTITY", true);
331       consensus = new AlignmentAnnotation("Consensus", "PID",
332               new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
333       consensus.hasText = true;
334       consensus.autoCalculated = true;
335     }
336     initAutoAnnotation();
337     if (jalview.bin.Cache.getProperty("DEFAULT_COLOUR") != null)
338     {
339       globalColourScheme = ColourSchemeProperty.getColour(alignment,
340               jalview.bin.Cache.getProperty("DEFAULT_COLOUR"));
341
342       if (globalColourScheme instanceof UserColourScheme)
343       {
344         globalColourScheme = UserDefinedColours.loadDefaultColours();
345         ((UserColourScheme) globalColourScheme).setThreshold(0,
346                 getIgnoreGapsConsensus());
347       }
348
349       if (globalColourScheme != null)
350       {
351         globalColourScheme.setConsensus(hconsensus);
352       }
353     }
354
355     wrapAlignment = jalview.bin.Cache.getDefault("WRAP_ALIGNMENT", false);
356     showUnconserved = jalview.bin.Cache.getDefault("SHOW_UNCONSERVED",
357             false);
358     sortByTree = jalview.bin.Cache.getDefault("SORT_BY_TREE", false);
359     followSelection = jalview.bin.Cache.getDefault("FOLLOW_SELECTIONS",
360             true);
361   }
362
363   /**
364    * set the flag
365    * 
366    * @param b
367    *          features are displayed if true
368    */
369   public void setShowSequenceFeatures(boolean b)
370   {
371     showSequenceFeatures = b;
372   }
373
374   public boolean getShowSequenceFeatures()
375   {
376     return showSequenceFeatures;
377   }
378
379   /**
380    * centre columnar annotation labels in displayed alignment annotation TODO:
381    * add to jalviewXML and annotation display settings
382    */
383   boolean centreColumnLabels = false;
384
385   private boolean showdbrefs;
386
387   private boolean shownpfeats;
388
389   // --------END Structure Conservation
390
391   /**
392    * get the consensus sequence as displayed under the PID consensus annotation
393    * row.
394    * 
395    * @return consensus sequence as a new sequence object
396    */
397   public SequenceI getConsensusSeq()
398   {
399     if (consensus == null)
400     {
401       updateConsensus(null);
402     }
403     if (consensus == null)
404     {
405       return null;
406     }
407     StringBuffer seqs = new StringBuffer();
408     for (int i = 0; i < consensus.annotations.length; i++)
409     {
410       if (consensus.annotations[i] != null)
411       {
412         if (consensus.annotations[i].description.charAt(0) == '[')
413         {
414           seqs.append(consensus.annotations[i].description.charAt(1));
415         }
416         else
417         {
418           seqs.append(consensus.annotations[i].displayCharacter);
419         }
420       }
421     }
422
423     SequenceI sq = new Sequence("Consensus", seqs.toString());
424     sq.setDescription("Percentage Identity Consensus "
425             + ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
426     return sq;
427   }
428
429   /**
430    * DOCUMENT ME!
431    * 
432    * @return DOCUMENT ME!
433    */
434   public int getStartRes()
435   {
436     return startRes;
437   }
438
439   /**
440    * DOCUMENT ME!
441    * 
442    * @return DOCUMENT ME!
443    */
444   public int getEndRes()
445   {
446     return endRes;
447   }
448
449   /**
450    * DOCUMENT ME!
451    * 
452    * @return DOCUMENT ME!
453    */
454   public int getStartSeq()
455   {
456     return startSeq;
457   }
458
459   /**
460    * DOCUMENT ME!
461    * 
462    * @param res
463    *          DOCUMENT ME!
464    */
465   public void setStartRes(int res)
466   {
467     this.startRes = res;
468   }
469
470   /**
471    * DOCUMENT ME!
472    * 
473    * @param seq
474    *          DOCUMENT ME!
475    */
476   public void setStartSeq(int seq)
477   {
478     this.startSeq = seq;
479   }
480
481   /**
482    * DOCUMENT ME!
483    * 
484    * @param res
485    *          DOCUMENT ME!
486    */
487   public void setEndRes(int res)
488   {
489     if (res > (alignment.getWidth() - 1))
490     {
491       // log.System.out.println(" Corrected res from " + res + " to maximum " +
492       // (alignment.getWidth()-1));
493       res = alignment.getWidth() - 1;
494     }
495
496     if (res < 0)
497     {
498       res = 0;
499     }
500
501     this.endRes = res;
502   }
503
504   /**
505    * DOCUMENT ME!
506    * 
507    * @param seq
508    *          DOCUMENT ME!
509    */
510   public void setEndSeq(int seq)
511   {
512     if (seq > alignment.getHeight())
513     {
514       seq = alignment.getHeight();
515     }
516
517     if (seq < 0)
518     {
519       seq = 0;
520     }
521
522     this.endSeq = seq;
523   }
524
525   /**
526    * DOCUMENT ME!
527    * 
528    * @return DOCUMENT ME!
529    */
530   public int getEndSeq()
531   {
532     return endSeq;
533   }
534
535   /**
536    * DOCUMENT ME!
537    * 
538    * @param f
539    *          DOCUMENT ME!
540    */
541   public void setFont(Font f)
542   {
543     font = f;
544
545     Container c = new Container();
546
547     java.awt.FontMetrics fm = c.getFontMetrics(font);
548     setCharHeight(fm.getHeight());
549     setCharWidth(fm.charWidth('M'));
550     validCharWidth = true;
551   }
552
553   /**
554    * DOCUMENT ME!
555    * 
556    * @return DOCUMENT ME!
557    */
558   public Font getFont()
559   {
560     return font;
561   }
562
563   /**
564    * DOCUMENT ME!
565    * 
566    * @param w
567    *          DOCUMENT ME!
568    */
569   public void setCharWidth(int w)
570   {
571     this.charWidth = w;
572   }
573
574   /**
575    * DOCUMENT ME!
576    * 
577    * @return DOCUMENT ME!
578    */
579   public int getCharWidth()
580   {
581     return charWidth;
582   }
583
584   /**
585    * DOCUMENT ME!
586    * 
587    * @param h
588    *          DOCUMENT ME!
589    */
590   public void setCharHeight(int h)
591   {
592     this.charHeight = h;
593   }
594
595   /**
596    * DOCUMENT ME!
597    * 
598    * @return DOCUMENT ME!
599    */
600   public int getCharHeight()
601   {
602     return charHeight;
603   }
604
605   /**
606    * DOCUMENT ME!
607    * 
608    * @param w
609    *          DOCUMENT ME!
610    */
611   public void setWrappedWidth(int w)
612   {
613     this.wrappedWidth = w;
614   }
615
616   /**
617    * DOCUMENT ME!
618    * 
619    * @return DOCUMENT ME!
620    */
621   public int getWrappedWidth()
622   {
623     return wrappedWidth;
624   }
625
626   /**
627    * DOCUMENT ME!
628    * 
629    * @return DOCUMENT ME!
630    */
631   public AlignmentI getAlignment()
632   {
633     return alignment;
634   }
635
636   /**
637    * DOCUMENT ME!
638    * 
639    * @param align
640    *          DOCUMENT ME!
641    */
642   public void setAlignment(AlignmentI align)
643   {
644     if (alignment != null && alignment.getCodonFrames() != null)
645     {
646       StructureSelectionManager.getStructureSelectionManager(
647               Desktop.instance).removeMappings(alignment.getCodonFrames());
648     }
649     this.alignment = align;
650     if (alignment!=null && alignment.getCodonFrames() != null)
651     {
652       StructureSelectionManager.getStructureSelectionManager(
653               Desktop.instance).addMappings(alignment.getCodonFrames());
654     }
655   }
656
657   /**
658    * DOCUMENT ME!
659    * 
660    * @param state
661    *          DOCUMENT ME!
662    */
663   public void setWrapAlignment(boolean state)
664   {
665     wrapAlignment = state;
666   }
667
668   /**
669    * DOCUMENT ME!
670    * 
671    * @param state
672    *          DOCUMENT ME!
673    */
674   public void setShowText(boolean state)
675   {
676     showText = state;
677   }
678
679   /**
680    * DOCUMENT ME!
681    * 
682    * @param state
683    *          DOCUMENT ME!
684    */
685   public void setRenderGaps(boolean state)
686   {
687     renderGaps = state;
688   }
689
690   /**
691    * DOCUMENT ME!
692    * 
693    * @return DOCUMENT ME!
694    */
695   public boolean getColourText()
696   {
697     return showColourText;
698   }
699
700   /**
701    * DOCUMENT ME!
702    * 
703    * @param state
704    *          DOCUMENT ME!
705    */
706   public void setColourText(boolean state)
707   {
708     showColourText = state;
709   }
710
711   /**
712    * DOCUMENT ME!
713    * 
714    * @param state
715    *          DOCUMENT ME!
716    */
717   public void setShowBoxes(boolean state)
718   {
719     showBoxes = state;
720   }
721
722   /**
723    * DOCUMENT ME!
724    * 
725    * @return DOCUMENT ME!
726    */
727   public boolean getWrapAlignment()
728   {
729     return wrapAlignment;
730   }
731
732   /**
733    * DOCUMENT ME!
734    * 
735    * @return DOCUMENT ME!
736    */
737   public boolean getShowText()
738   {
739     return showText;
740   }
741
742   /**
743    * DOCUMENT ME!
744    * 
745    * @return DOCUMENT ME!
746    */
747   public boolean getShowBoxes()
748   {
749     return showBoxes;
750   }
751
752   /**
753    * DOCUMENT ME!
754    * 
755    * @return DOCUMENT ME!
756    */
757   public char getGapCharacter()
758   {
759     return getAlignment().getGapCharacter();
760   }
761
762   /**
763    * DOCUMENT ME!
764    * 
765    * @param gap
766    *          DOCUMENT ME!
767    */
768   public void setGapCharacter(char gap)
769   {
770     if (getAlignment() != null)
771     {
772       getAlignment().setGapCharacter(gap);
773     }
774   }
775
776   /**
777    * DOCUMENT ME!
778    * 
779    * @return DOCUMENT ME!
780    */
781   public ColumnSelection getColumnSelection()
782   {
783     return colSel;
784   }
785
786   /**
787    * DOCUMENT ME!
788    * 
789    * @param tree
790    *          DOCUMENT ME!
791    */
792   public void setCurrentTree(NJTree tree)
793   {
794     currentTree = tree;
795   }
796
797   /**
798    * DOCUMENT ME!
799    * 
800    * @return DOCUMENT ME!
801    */
802   public NJTree getCurrentTree()
803   {
804     return currentTree;
805   }
806
807   /**
808    * DOCUMENT ME!
809    * 
810    * @return DOCUMENT ME!
811    */
812   public boolean getShowJVSuffix()
813   {
814     return showJVSuffix;
815   }
816
817   /**
818    * DOCUMENT ME!
819    * 
820    * @param b
821    *          DOCUMENT ME!
822    */
823   public void setShowJVSuffix(boolean b)
824   {
825     showJVSuffix = b;
826   }
827
828   /**
829    * DOCUMENT ME!
830    * 
831    * @return DOCUMENT ME!
832    */
833   public boolean getShowAnnotation()
834   {
835     return showAnnotation;
836   }
837
838   /**
839    * DOCUMENT ME!
840    * 
841    * @param b
842    *          DOCUMENT ME!
843    */
844   public void setShowAnnotation(boolean b)
845   {
846     showAnnotation = b;
847   }
848
849   /**
850    * DOCUMENT ME!
851    * 
852    * @return DOCUMENT ME!
853    */
854   public boolean getScaleAboveWrapped()
855   {
856     return scaleAboveWrapped;
857   }
858
859   /**
860    * DOCUMENT ME!
861    * 
862    * @return DOCUMENT ME!
863    */
864   public boolean getScaleLeftWrapped()
865   {
866     return scaleLeftWrapped;
867   }
868
869   /**
870    * DOCUMENT ME!
871    * 
872    * @return DOCUMENT ME!
873    */
874   public boolean getScaleRightWrapped()
875   {
876     return scaleRightWrapped;
877   }
878
879   /**
880    * DOCUMENT ME!
881    * 
882    * @param b
883    *          DOCUMENT ME!
884    */
885   public void setScaleAboveWrapped(boolean b)
886   {
887     scaleAboveWrapped = b;
888   }
889
890   /**
891    * DOCUMENT ME!
892    * 
893    * @param b
894    *          DOCUMENT ME!
895    */
896   public void setScaleLeftWrapped(boolean b)
897   {
898     scaleLeftWrapped = b;
899   }
900
901   /**
902    * DOCUMENT ME!
903    * 
904    * @param b
905    *          DOCUMENT ME!
906    */
907   public void setScaleRightWrapped(boolean b)
908   {
909     scaleRightWrapped = b;
910   }
911
912
913   public void setDataset(boolean b)
914   {
915     isDataset = b;
916   }
917
918   public boolean isDataset()
919   {
920     return isDataset;
921   }
922
923
924
925   public boolean getShowHiddenMarkers()
926   {
927     return showHiddenMarkers;
928   }
929
930   public void setShowHiddenMarkers(boolean show)
931   {
932     showHiddenMarkers = show;
933   }
934
935   public Color getSequenceColour(SequenceI seq)
936   {
937     if (sequenceColours == null || !sequenceColours.containsKey(seq))
938     {
939       return Color.white;
940     }
941     else
942     {
943       return (Color) sequenceColours.get(seq);
944     }
945   }
946
947   public void setSequenceColour(SequenceI seq, Color col)
948   {
949     if (sequenceColours == null)
950     {
951       sequenceColours = new Hashtable();
952     }
953
954     if (col == null)
955     {
956       sequenceColours.remove(seq);
957     }
958     else
959     {
960       sequenceColours.put(seq, col);
961     }
962   }
963
964   /**
965    * returns the visible column regions of the alignment
966    * 
967    * @param selectedRegionOnly
968    *          true to just return the contigs intersecting with the selected
969    *          area
970    * @return
971    */
972   public int[] getViewAsVisibleContigs(boolean selectedRegionOnly)
973   {
974     int[] viscontigs = null;
975     int start = 0, end = 0;
976     if (selectedRegionOnly && selectionGroup != null)
977     {
978       start = selectionGroup.getStartRes();
979       end = selectionGroup.getEndRes() + 1;
980     }
981     else
982     {
983       end = alignment.getWidth();
984     }
985     viscontigs = colSel.getVisibleContigs(start, end);
986     return viscontigs;
987   }
988
989   /**
990    * get hash of undo and redo list for the alignment
991    * 
992    * @return long[] { historyList.hashCode, redoList.hashCode };
993    */
994   public long[] getUndoRedoHash()
995   {
996     // TODO: JAL-1126
997     if (historyList == null || redoList == null)
998       return new long[]
999       { -1, -1 };
1000     return new long[]
1001     { historyList.hashCode(), this.redoList.hashCode() };
1002   }
1003
1004   /**
1005    * test if a particular set of hashcodes are different to the hashcodes for
1006    * the undo and redo list.
1007    * 
1008    * @param undoredo
1009    *          the stored set of hashcodes as returned by getUndoRedoHash
1010    * @return true if the hashcodes differ (ie the alignment has been edited) or
1011    *         the stored hashcode array differs in size
1012    */
1013   public boolean isUndoRedoHashModified(long[] undoredo)
1014   {
1015     if (undoredo == null)
1016     {
1017       return true;
1018     }
1019     long[] cstate = getUndoRedoHash();
1020     if (cstate.length != undoredo.length)
1021     {
1022       return true;
1023     }
1024
1025     for (int i = 0; i < cstate.length; i++)
1026     {
1027       if (cstate[i] != undoredo[i])
1028       {
1029         return true;
1030       }
1031     }
1032     return false;
1033   }
1034
1035   public boolean getCentreColumnLabels()
1036   {
1037     return centreColumnLabels;
1038   }
1039
1040   public void setCentreColumnLabels(boolean centrecolumnlabels)
1041   {
1042     centreColumnLabels = centrecolumnlabels;
1043   }
1044
1045   public void updateSequenceIdColours()
1046   {
1047     if (sequenceColours == null)
1048     {
1049       sequenceColours = new Hashtable();
1050     }
1051     for (SequenceGroup sg:alignment.getGroups())
1052     {
1053       if (sg.idColour != null)
1054       {
1055         for (SequenceI s:sg.getSequences(getHiddenRepSequences()))
1056         {
1057           sequenceColours.put(s, sg.idColour);
1058         }
1059       }
1060     }
1061   }
1062
1063   /**
1064    * enable or disable the display of Database Cross References in the sequence
1065    * ID tooltip
1066    */
1067   public void setShowDbRefs(boolean show)
1068   {
1069     showdbrefs = show;
1070   }
1071
1072   /**
1073    * 
1074    * @return true if Database References are to be displayed on tooltips.
1075    */
1076   public boolean isShowDbRefs()
1077   {
1078     return showdbrefs;
1079   }
1080
1081   /**
1082    * 
1083    * @return true if Non-positional features are to be displayed on tooltips.
1084    */
1085   public boolean isShowNpFeats()
1086   {
1087     return shownpfeats;
1088   }
1089
1090   /**
1091    * enable or disable the display of Non-Positional sequence features in the
1092    * sequence ID tooltip
1093    * 
1094    * @param show
1095    */
1096   public void setShowNpFeats(boolean show)
1097   {
1098     shownpfeats = show;
1099   }
1100
1101   /**
1102    * 
1103    * @return true if view has hidden rows
1104    */
1105   public boolean hasHiddenRows()
1106   {
1107     return hasHiddenRows;
1108   }
1109
1110   /**
1111    * 
1112    * @return true if view has hidden columns
1113    */
1114   public boolean hasHiddenColumns()
1115   {
1116     return hasHiddenColumns;
1117   }
1118
1119   /**
1120    * when set, view will scroll to show the highlighted position
1121    */
1122   public boolean followHighlight = true;
1123
1124   /**
1125    * @return true if view should scroll to show the highlighted region of a
1126    *         sequence
1127    * @return
1128    */
1129   public boolean getFollowHighlight()
1130   {
1131     return followHighlight;
1132   }
1133
1134   public boolean followSelection = true;
1135
1136   /**
1137    * @return true if view selection should always follow the selections
1138    *         broadcast by other selection sources
1139    */
1140   public boolean getFollowSelection()
1141   {
1142     return followSelection;
1143   }
1144
1145   boolean showSeqFeaturesHeight;
1146
1147   public void sendSelection()
1148   {
1149     jalview.structure.StructureSelectionManager
1150             .getStructureSelectionManager(Desktop.instance).sendSelection(
1151                     new SequenceGroup(getSelectionGroup()),
1152                     new ColumnSelection(getColumnSelection()), this);
1153   }
1154
1155   public void setShowSequenceFeaturesHeight(boolean selected)
1156   {
1157     showSeqFeaturesHeight = selected;
1158   }
1159
1160   public boolean getShowSequenceFeaturesHeight()
1161   {
1162     return showSeqFeaturesHeight;
1163   }
1164
1165   /**
1166    * return the alignPanel containing the given viewport. Use this to get the
1167    * components currently handling the given viewport.
1168    * 
1169    * @param av
1170    * @return null or an alignPanel guaranteed to have non-null alignFrame
1171    *         reference
1172    */
1173   public AlignmentPanel getAlignPanel()
1174   {
1175     AlignmentPanel[] aps = PaintRefresher.getAssociatedPanels(this
1176             .getSequenceSetId());
1177     AlignmentPanel ap = null;
1178     for (int p = 0; aps != null && p < aps.length; p++)
1179     {
1180       if (aps[p].av == this)
1181       {
1182         return aps[p];
1183       }
1184     }
1185     return null;
1186   }
1187
1188   public boolean getSortByTree()
1189   {
1190     return sortByTree;
1191   }
1192
1193   public void setSortByTree(boolean sort)
1194   {
1195     sortByTree = sort;
1196   }
1197
1198   /**
1199    * synthesize a column selection if none exists so it covers the given
1200    * selection group. if wholewidth is false, no column selection is made if the
1201    * selection group covers the whole alignment width.
1202    * 
1203    * @param sg
1204    * @param wholewidth
1205    */
1206   public void expandColSelection(SequenceGroup sg, boolean wholewidth)
1207   {
1208     int sgs, sge;
1209     if (sg != null
1210             && (sgs = sg.getStartRes()) >= 0
1211             && sg.getStartRes() <= (sge = sg.getEndRes())
1212             && (colSel == null || colSel.getSelected() == null || colSel
1213                     .getSelected().size() == 0))
1214     {
1215       if (!wholewidth && alignment.getWidth() == (1 + sge - sgs))
1216       {
1217         // do nothing
1218         return;
1219       }
1220       if (colSel == null)
1221       {
1222         colSel = new ColumnSelection();
1223       }
1224       for (int cspos = sg.getStartRes(); cspos <= sg.getEndRes(); cspos++)
1225       {
1226         colSel.addElement(cspos);
1227       }
1228     }
1229   }
1230
1231   public StructureSelectionManager getStructureSelectionManager()
1232   {
1233     return StructureSelectionManager
1234             .getStructureSelectionManager(Desktop.instance);
1235   }
1236
1237   /**
1238    * 
1239    * @param pdbEntries
1240    * @return a series of SequenceI arrays, one for each PDBEntry, listing which
1241    *         sequence in the alignment holds a reference to it
1242    */
1243   public SequenceI[][] collateForPDB(PDBEntry[] pdbEntries)
1244   {
1245     ArrayList<SequenceI[]> seqvectors = new ArrayList<SequenceI[]>();
1246     for (PDBEntry pdb : pdbEntries)
1247     {
1248       ArrayList<SequenceI> seqs = new ArrayList<SequenceI>();
1249       for (int i = 0; i < alignment.getHeight(); i++)
1250       {
1251         Vector pdbs = alignment.getSequenceAt(i).getDatasetSequence()
1252                 .getPDBId();
1253         if (pdbs == null)
1254           continue;
1255         SequenceI sq;
1256         for (int p = 0; p < pdbs.size(); p++)
1257         {
1258           PDBEntry p1 = (PDBEntry) pdbs.elementAt(p);
1259           if (p1.getId().equals(pdb.getId()))
1260           {
1261             if (!seqs.contains(sq = alignment.getSequenceAt(i)))
1262               seqs.add(sq);
1263
1264             continue;
1265           }
1266         }
1267       }
1268       seqvectors.add(seqs.toArray(new SequenceI[seqs.size()]));
1269     }
1270     return seqvectors.toArray(new SequenceI[seqvectors.size()][]);
1271   }
1272
1273   
1274   public boolean isNormaliseSequenceLogo()
1275   {
1276     return normaliseSequenceLogo;
1277   }
1278
1279   public void setNormaliseSequenceLogo(boolean state)
1280   {
1281     normaliseSequenceLogo = state;
1282   }
1283
1284
1285   /**
1286    * 
1287    * @return true if alignment characters should be displayed 
1288    */
1289   public boolean isValidCharWidth()
1290   {
1291     return validCharWidth;
1292   }
1293   private jalview.ws.jws2.dm.AAConsSettings preferredAAConsSettings; 
1294
1295   public jalview.ws.jws2.dm.AAConsSettings getPreferredAAConsSettings()
1296   {
1297     return preferredAAConsSettings;
1298   }
1299   public void setPreferredAAConsSettings(jalview.ws.jws2.dm.AAConsSettings aaConsSettings)
1300   {
1301     preferredAAConsSettings=aaConsSettings;
1302   }
1303   
1304 }