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