added PropertyChangeListeners for alignviewport.alignment.sequences
[jalview.git] / src / jalview / gui / AlignViewport.java
1 package jalview.gui;\r
2 \r
3 import java.awt.*;\r
4 import jalview.analysis.*;\r
5 import jalview.analysis.NJTree;\r
6 import jalview.datamodel.*;\r
7 import jalview.schemes.*;\r
8 import java.util.*;\r
9 import jalview.bin.Cache;\r
10 \r
11 public class AlignViewport\r
12 {\r
13   int startRes;\r
14   int endRes;\r
15 \r
16   int startSeq;\r
17   int endSeq;\r
18 \r
19   boolean showFullId = false;\r
20   boolean showText=true;\r
21   boolean showColourText=false;\r
22   boolean showBoxes=true;\r
23   boolean wrapAlignment=false;\r
24   boolean renderGaps = true;\r
25   boolean showSequenceFeatures = false;\r
26   boolean showAnnotation = true;\r
27   boolean showConservation = true;\r
28   boolean showQuality = true;\r
29   boolean showIdentity = true;\r
30 \r
31   boolean colourAppliesToAllGroups = true;\r
32   ColourSchemeI globalColourScheme = null;\r
33   boolean conservationColourSelected = false;\r
34   boolean abovePIDThreshold = false;\r
35 \r
36   SequenceGroup selectionGroup = new SequenceGroup();\r
37 \r
38 \r
39   int             charHeight;\r
40   int             charWidth;\r
41   int             chunkWidth;\r
42   int             chunkHeight;\r
43 \r
44   Font            font = new Font("SansSerif",Font.PLAIN,10);\r
45   AlignmentI      alignment;\r
46 \r
47   ColumnSelection colSel = new ColumnSelection();\r
48 \r
49   int threshold;\r
50   int increment;\r
51 \r
52   NJTree currentTree = null;\r
53 \r
54   boolean scaleAboveWrapped = false;\r
55   boolean scaleLeftWrapped  = true;\r
56   boolean scaleRightWrapped = true;\r
57 \r
58 \r
59   public AlignViewport(AlignmentI al)\r
60   {\r
61     setAlignment(al);\r
62     this.startRes = 0;\r
63     this.endRes = al.getWidth()-1;\r
64     this.startSeq = 0;\r
65     this.endSeq = al.getHeight()-1;\r
66 \r
67     updateFromPreferences();\r
68 \r
69   }\r
70 \r
71   public void updateFromPreferences()\r
72   {\r
73     showFullId = Preferences.showFullId;\r
74     showAnnotation = Preferences.showAnnotation;\r
75     showConservation = Preferences.showConservation;\r
76     showQuality = Preferences.showQuality;\r
77     showIdentity = Preferences.showIdentity;\r
78     showFullId = Preferences.showFullId;\r
79     String fontName = Preferences.fontName;\r
80     String fontStyle = Preferences.fontStyle;\r
81     String fontSize = Cache.getProperty("FONT_SIZE");\r
82     if (fontName != null && fontStyle != null && fontSize != null)\r
83     {\r
84       int style = 0;\r
85       if(fontStyle.equals("bold"))\r
86         style = 1;\r
87       else if(fontStyle.equals("italic"))\r
88         style = 2;\r
89       setFont(new Font(fontName, style, Integer.parseInt(fontSize)));\r
90     }\r
91     else\r
92       setFont(font);\r
93 \r
94     alignment.setGapCharacter(Preferences.gapSymbol);\r
95 \r
96     // We must set conservation and consensus before setting colour,\r
97     // as Blosum and Clustal require this to be done\r
98     updateConservation();\r
99     updateConsensus();\r
100     if(Preferences.defaultColour!=null)\r
101     {\r
102       globalColourScheme = ColourSchemeProperty.getColour(alignment, Preferences.defaultColour);\r
103       if(globalColourScheme!=null)\r
104         globalColourScheme.setConsensus( vconsensus );\r
105    }\r
106 \r
107  }\r
108 \r
109  public void showSequenceFeatures(boolean b)\r
110  {\r
111    showSequenceFeatures = b;\r
112  }\r
113 \r
114   public Vector vconsensus;\r
115   AlignmentAnnotation consensus;\r
116   AlignmentAnnotation conservation;\r
117   AlignmentAnnotation quality;\r
118 \r
119   public int ConsPercGaps = 25; // JBPNote : This should be a scalable property!\r
120 \r
121   public void updateConservation()\r
122   {\r
123     Conservation cons = new jalview.analysis.Conservation("All",\r
124         jalview.schemes.ResidueProperties.propHash, 3,\r
125         alignment.getSequences(), 0,\r
126         alignment.getWidth()-1);\r
127     cons.calculate();\r
128     cons.verdict(false, ConsPercGaps);\r
129     cons.findQuality();\r
130     int alWidth = alignment.getWidth();\r
131     Annotation [] annotations = new Annotation[alWidth];\r
132     Annotation [] qannotations = new Annotation[alWidth];\r
133     String sequence = cons.getConsSequence().getSequence();\r
134     float minR,minG,minB, maxR,maxG,maxB;\r
135     minR = 0.3f;\r
136     minG = 0.0f;\r
137     minB = 0f;\r
138     maxR = 1.0f-minR; maxG=0.9f-minG; maxB=0f-minB; // scalable range for colouring both Conservation and Quality\r
139     float min = 0f;\r
140     float max = 11f;\r
141     float qmin = cons.qualityRange[0].floatValue();\r
142     float qmax = cons.qualityRange[1].floatValue();\r
143 \r
144     for (int i = 0; i < alWidth; i++)\r
145     {\r
146       float value = 0;\r
147       try\r
148         {\r
149           value = Integer.parseInt(sequence.charAt(i) + "");\r
150         }\r
151       catch (Exception ex)\r
152         {\r
153           if (sequence.charAt(i) == '*') value = 11;\r
154           if (sequence.charAt(i) == '+') value = 10;\r
155         }\r
156       float vprop = value-min;\r
157       vprop/=max;\r
158       annotations[i] = new Annotation(sequence.charAt(i) + "",\r
159                                       "Conservation graph", ' ', value, new Color(minR+maxR*vprop, minG+maxG*vprop, minB+maxB*vprop));\r
160       // Quality calc\r
161       value = ((Double) cons.quality.get(i)).floatValue();\r
162       vprop = value - qmin;\r
163       vprop/=qmax;\r
164       qannotations[i] = new Annotation(" ",\r
165                                       String.valueOf(value), ' ', value, new Color(minR+maxR*vprop, minG+maxG*vprop, minB+maxB*vprop));\r
166     }\r
167 \r
168     if(conservation==null)\r
169     {\r
170       conservation = new AlignmentAnnotation("Conservation",\r
171                                              "Conservation of total alignment less than "+ConsPercGaps+"% gaps",\r
172                                              annotations,\r
173                                              0f, // cons.qualityRange[0].floatValue(),\r
174                                              11f, // cons.qualityRange[1].floatValue()\r
175                                              1);\r
176       if(showConservation)\r
177       alignment.addAnnotation(conservation);\r
178       quality = new AlignmentAnnotation("Quality",\r
179                                         "Alignment Quality based on Blosum62 scores",\r
180                                         qannotations,\r
181                                         cons.qualityRange[0].floatValue(),\r
182                                         cons.qualityRange[1].floatValue(),\r
183                                         1);\r
184       if(showQuality)\r
185         alignment.addAnnotation(quality);\r
186     }\r
187     else {\r
188       conservation.annotations = annotations;\r
189       quality.annotations = qannotations;\r
190       quality.graphMax = cons.qualityRange[1].floatValue();\r
191     }\r
192 \r
193 \r
194   }\r
195 \r
196   public void updateConsensus()\r
197   {\r
198     Annotation [] annotations = new Annotation[alignment.getWidth()];\r
199 \r
200     // this routine prevents vconsensus becoming a new object each time\r
201     // consenus is calculated. Important for speed of Blosum62\r
202     // and PID colouring of alignment\r
203     if(vconsensus == null)\r
204         vconsensus = alignment.getAAFrequency();\r
205     else\r
206     {\r
207         Vector temp = alignment.getAAFrequency();\r
208         vconsensus.clear();\r
209         Enumeration e = temp.elements();\r
210         while(e.hasMoreElements())\r
211         {\r
212           vconsensus.add(e.nextElement());\r
213         }\r
214     }\r
215     Hashtable hash = null;\r
216     for (int i = 0; i<alignment.getWidth(); i++)\r
217     {\r
218         hash = (Hashtable) vconsensus.elementAt(i);\r
219         float value = Float.parseFloat(hash.get("maxCount").toString());\r
220         value /= Float.parseFloat(hash.get("size").toString());\r
221 \r
222         value *= 100;\r
223         String maxRes = hash.get("maxResidue")+" ";\r
224         String mouseOver = hash.get("maxResidue")+" ";\r
225         if(maxRes.length()>2)\r
226         {\r
227           mouseOver = "["+maxRes+"] ";\r
228           maxRes = "+ ";\r
229         }\r
230 \r
231         mouseOver += (int)value+"%";\r
232         annotations[i] = new Annotation(maxRes, mouseOver, ' ', value);\r
233 \r
234     }\r
235 \r
236      if(consensus==null)\r
237      {\r
238        consensus = new AlignmentAnnotation("Consensus",\r
239                                            "PID", annotations, 0f, 100f, 1);\r
240        if(showIdentity)\r
241          alignment.addAnnotation(consensus);\r
242      }\r
243      else\r
244        consensus.annotations = annotations;\r
245 \r
246   }\r
247 \r
248 \r
249   public SequenceGroup getSelectionGroup()\r
250   {\r
251     return selectionGroup;\r
252   }\r
253 \r
254   public void setSelectionGroup(SequenceGroup sg)\r
255   {\r
256     selectionGroup = sg;\r
257   }\r
258 \r
259 \r
260  public boolean getConservationSelected()\r
261  {\r
262    return conservationColourSelected;\r
263  }\r
264 \r
265  public void setConservationSelected(boolean b)\r
266  {\r
267    conservationColourSelected = b;\r
268  }\r
269 \r
270  public boolean getAbovePIDThreshold()\r
271  {\r
272    return abovePIDThreshold;\r
273  }\r
274 \r
275  public void setAbovePIDThreshold(boolean b)\r
276  {\r
277    abovePIDThreshold = b;\r
278  }\r
279 \r
280   public int getStartRes() {\r
281     return startRes;\r
282   }\r
283 \r
284   public int getEndRes() {\r
285     return endRes;\r
286   }\r
287 \r
288   public int getStartSeq() {\r
289     return startSeq;\r
290   }\r
291 \r
292   public void setGlobalColourScheme(ColourSchemeI cs)\r
293   {\r
294      globalColourScheme = cs;\r
295   }\r
296 \r
297   public ColourSchemeI getGlobalColourScheme()\r
298   {\r
299     return globalColourScheme;\r
300   }\r
301 \r
302 \r
303   public void setStartRes(int res) {\r
304     this.startRes = res;\r
305   }\r
306   public void setStartSeq(int seq) {\r
307     this.startSeq = seq;\r
308   }\r
309   public void setEndRes(int res) {\r
310     if (res > alignment.getWidth()-1) {\r
311       System.out.println(" Corrected res from " + res + " to maximum " + (alignment.getWidth()-1));\r
312        res = alignment.getWidth()-1;\r
313     }\r
314     if (res < 0) {\r
315       res = 0;\r
316     }\r
317     this.endRes = res;\r
318   }\r
319   public void setEndSeq(int seq) {\r
320     if (seq > alignment.getHeight()) {\r
321       seq = alignment.getHeight();\r
322     }\r
323     if (seq < 0) {\r
324       seq = 0;\r
325     }\r
326     this.endSeq = seq;\r
327   }\r
328   public int getEndSeq() {\r
329     return endSeq;\r
330   }\r
331 \r
332   public void setFont(Font f) {\r
333     font = f;\r
334     javax.swing.JFrame temp = new javax.swing.JFrame();\r
335     temp.addNotify();\r
336     java.awt.FontMetrics fm = temp.getGraphics().getFontMetrics(font);\r
337     setCharHeight(fm.getHeight());\r
338     setCharWidth(fm.charWidth('M'));\r
339   }\r
340 \r
341   public Font getFont() {\r
342     return font;\r
343   }\r
344   public void setCharWidth(int w) {\r
345     this.charWidth = w;\r
346   }\r
347   public int getCharWidth() {\r
348     return charWidth;\r
349   }\r
350   public void setCharHeight(int h) {\r
351     this.charHeight = h;\r
352   }\r
353   public int getCharHeight() {\r
354     return charHeight;\r
355   }\r
356   public void setChunkWidth(int w) {\r
357     this.chunkWidth = w;\r
358   }\r
359   public int getChunkWidth() {\r
360     return chunkWidth;\r
361   }\r
362   public void setChunkHeight(int h) {\r
363     this.chunkHeight = h;\r
364   }\r
365   public int getChunkHeight() {\r
366     return chunkHeight;\r
367   }\r
368   public AlignmentI getAlignment() {\r
369     return alignment;\r
370   }\r
371   public void setAlignment(AlignmentI align) {\r
372     this.alignment = align;\r
373   }\r
374 \r
375   public void setWrapAlignment(boolean state) {\r
376     wrapAlignment = state;\r
377   }\r
378   public void setShowText(boolean state) {\r
379     showText = state;\r
380   }\r
381 \r
382   public void setRenderGaps(boolean state){\r
383     renderGaps = state;\r
384   }\r
385 \r
386 \r
387   public boolean getColourText()\r
388   {\r
389     return showColourText;\r
390   }\r
391 \r
392   public void setColourText(boolean state)\r
393   {\r
394     showColourText = state;\r
395   }\r
396 \r
397   public void setShowBoxes(boolean state) {\r
398     showBoxes = state;\r
399   }\r
400 \r
401   public boolean getWrapAlignment() {\r
402       return wrapAlignment;\r
403   }\r
404   public boolean getShowText() {\r
405     return showText;\r
406   }\r
407   public boolean getShowBoxes() {\r
408     return showBoxes;\r
409   }\r
410 \r
411   public char getGapCharacter() {\r
412     return getAlignment().getGapCharacter();\r
413   }\r
414   public void setGapCharacter(char gap) {\r
415     if (getAlignment() != null) {\r
416       getAlignment().setGapCharacter(gap);\r
417     }\r
418   }\r
419   public void setThreshold(int thresh) {\r
420     threshold = thresh;\r
421   }\r
422   public int getThreshold() {\r
423     return threshold;\r
424   }\r
425   public void setIncrement(int inc) {\r
426     increment = inc;\r
427   }\r
428   public int getIncrement() {\r
429     return increment;\r
430   }\r
431   public int getIndex(int y) {\r
432     int y1     = 0;\r
433     int starty = getStartSeq();\r
434     int endy   = getEndSeq();\r
435 \r
436     for (int i = starty; i <= endy; i++) {\r
437       if (i < alignment.getHeight() && alignment.getSequenceAt(i) != null) {\r
438         int y2 = y1 + getCharHeight();\r
439 \r
440         if (y>=y1 && y <=y2) {\r
441           return i;\r
442         }\r
443         y1  = y2;\r
444       } else {\r
445         return -1;\r
446       }\r
447     }\r
448     return -1;\r
449   }\r
450 \r
451   public ColumnSelection getColumnSelection() {\r
452     return colSel;\r
453   }\r
454 \r
455   public void resetSeqLimits(int height) {\r
456     setEndSeq(height/getCharHeight());\r
457   }\r
458   public void setCurrentTree(NJTree tree) {\r
459       currentTree = tree;\r
460   }\r
461   public NJTree getCurrentTree() {\r
462     return currentTree;\r
463   }\r
464 \r
465   public void setColourAppliesToAllGroups(boolean b)\r
466   {   colourAppliesToAllGroups = b; }\r
467 \r
468   public boolean getColourAppliesToAllGroups()\r
469   {return colourAppliesToAllGroups; }\r
470 \r
471   public boolean getShowFullId()\r
472   {\r
473     return showFullId;\r
474   }\r
475 \r
476   public void setShowFullId(boolean b)\r
477   {\r
478     showFullId = b;\r
479   }\r
480 \r
481   public boolean getShowAnnotation()\r
482   {\r
483     return showAnnotation;\r
484   }\r
485 \r
486   public void setShowAnnotation(boolean b)\r
487   {\r
488     showAnnotation = b;\r
489   }\r
490 \r
491   public boolean getScaleAboveWrapped()\r
492   { return scaleAboveWrapped;}\r
493 \r
494   public boolean getScaleLeftWrapped()\r
495   { return scaleLeftWrapped; }\r
496 \r
497   public boolean getScaleRightWrapped()\r
498   { return scaleRightWrapped; }\r
499 \r
500   public void setScaleAboveWrapped(boolean b)\r
501   { scaleAboveWrapped = b; }\r
502 \r
503   public void setScaleLeftWrapped(boolean b)\r
504   { scaleLeftWrapped = b; }\r
505 \r
506   public void setScaleRightWrapped(boolean b)\r
507   { scaleRightWrapped = b; }\r
508   // JBPNote Prolly only need this in the applet version.\r
509   private java.beans.PropertyChangeSupport changeSupport = new java.beans.PropertyChangeSupport(this);\r
510   public void addPropertyChangeListener(java.beans.PropertyChangeListener listener) {\r
511     changeSupport.addPropertyChangeListener(listener);\r
512   }\r
513 \r
514   public void removePropertyChangeListener(java.beans.PropertyChangeListener listener) {\r
515     changeSupport.removePropertyChangeListener(listener);\r
516   }\r
517   public void firePropertyChange(String prop, Object oldvalue, Object newvalue) {\r
518     changeSupport.firePropertyChange(prop, oldvalue, newvalue);\r
519   }\r
520 }\r