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