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