JAL-1807 Bob's JalviewJS prototype first commit
[jalviewjs.git] / bin / jalview / appletgui / TreeCanvas.js
1 Clazz.declarePackage ("jalview.appletgui");\r
2 Clazz.load (["awt2swing.Panel", "java.awt.event.MouseListener", "$.MouseMotionListener", "java.util.Hashtable"], "jalview.appletgui.TreeCanvas", ["jalview.analysis.Conservation", "jalview.appletgui.PaintRefresher", "jalview.datamodel.SequenceGroup", "$.SequenceI", "$.SequenceNode", "jalview.schemes.ColourSchemeProperty", "$.ResidueProperties", "$.UserColourScheme", "jalview.util.Format", "$.MappingUtils", "java.awt.Color", "$.Dimension", "$.Point", "$.Rectangle", "java.util.Vector"], function () {\r
3 c$ = Clazz.decorateAsClass (function () {\r
4 this.tree = null;\r
5 this.scrollPane = null;\r
6 this.av = null;\r
7 this.$font = null;\r
8 this.fitToWindow = true;\r
9 this.showDistances = false;\r
10 this.showBootstrap = false;\r
11 this.markPlaceholders = false;\r
12 this.offx = 20;\r
13 this.offy = 0;\r
14 this.threshold = 0;\r
15 this.longestName = null;\r
16 this.labelLength = -1;\r
17 this.nameHash = null;\r
18 this.nodeHash = null;\r
19 this.highlightNode = null;\r
20 this.ap = null;\r
21 Clazz.instantialize (this, arguments);\r
22 }, jalview.appletgui, "TreeCanvas", awt2swing.Panel, [java.awt.event.MouseListener, java.awt.event.MouseMotionListener]);\r
23 Clazz.prepareFields (c$, function () {\r
24 this.nameHash =  new java.util.Hashtable ();\r
25 this.nodeHash =  new java.util.Hashtable ();\r
26 });\r
27 Clazz.makeConstructor (c$, \r
28 function (ap, scroller) {\r
29 Clazz.superConstructor (this, jalview.appletgui.TreeCanvas, []);\r
30 this.ap = ap;\r
31 this.av = ap.av;\r
32 this.$font = this.av.getFont ();\r
33 this.scrollPane = scroller;\r
34 this.addMouseListener (this);\r
35 this.addMouseMotionListener (this);\r
36 this.setLayout (null);\r
37 jalview.appletgui.PaintRefresher.Register (this, this.av.getSequenceSetId ());\r
38 }, "jalview.appletgui.AlignmentPanel,awt2swing.ScrollPane");\r
39 Clazz.defineMethod (c$, "treeSelectionChanged", \r
40 function (sequence) {\r
41 var selected = this.av.getSelectionGroup ();\r
42 if (selected == null) {\r
43 selected =  new jalview.datamodel.SequenceGroup ();\r
44 this.av.setSelectionGroup (selected);\r
45 }selected.setEndRes (this.av.getAlignment ().getWidth () - 1);\r
46 selected.addOrRemove (sequence, true);\r
47 }, "jalview.datamodel.SequenceI");\r
48 Clazz.defineMethod (c$, "setTree", \r
49 function (tree) {\r
50 this.tree = tree;\r
51 tree.findHeight (tree.getTopNode ());\r
52 var leaves = tree.findLeaves (tree.getTopNode (),  new java.util.Vector ());\r
53 var has_placeholders = false;\r
54 this.longestName = "";\r
55 for (var i = 0; i < leaves.size (); i++) {\r
56 var lf = leaves.elementAt (i);\r
57 if (lf.isPlaceholder ()) {\r
58 has_placeholders = true;\r
59 }if (this.longestName.length < (lf.element ()).getName ().length) {\r
60 this.longestName = " * " + (lf.element ()).getName ();\r
61 }}\r
62 this.setMarkPlaceholders (has_placeholders);\r
63 }, "jalview.analysis.NJTree");\r
64 Clazz.defineMethod (c$, "drawNode", \r
65 function (g, node, chunk, scale, width, offx, offy) {\r
66 if (node == null) {\r
67 return;\r
68 }if (node.left () == null && node.right () == null) {\r
69 var height = node.height;\r
70 var dist = node.dist;\r
71 var xstart = Clazz.floatToInt ((height - dist) * scale) + offx;\r
72 var xend = Clazz.floatToInt (height * scale) + offx;\r
73 var ypos = Clazz.floatToInt (node.ycount * chunk) + offy;\r
74 if (Clazz.instanceOf (node.element (), jalview.datamodel.SequenceI)) {\r
75 var seq = node.element ();\r
76 if (this.av.getSequenceColour (seq) === java.awt.Color.white) {\r
77 g.setColor (java.awt.Color.black);\r
78 } else {\r
79 g.setColor (this.av.getSequenceColour (seq).darker ());\r
80 }} else {\r
81 g.setColor (java.awt.Color.black);\r
82 }g.drawLine (xstart, ypos, xend, ypos);\r
83 var nodeLabel = "";\r
84 if (this.showDistances && node.dist > 0) {\r
85 nodeLabel =  new jalview.util.Format ("%-.2f").formDouble (node.dist);\r
86 }if (this.showBootstrap) {\r
87 var btstrap = node.getBootstrap ();\r
88 if (btstrap > -1) {\r
89 if (this.showDistances) {\r
90 nodeLabel = nodeLabel + " : ";\r
91 }nodeLabel = nodeLabel + String.valueOf (node.getBootstrap ());\r
92 }}if (!nodeLabel.equals ("")) {\r
93 g.drawString (nodeLabel, xstart + 2, ypos - 2);\r
94 }var name = (this.markPlaceholders && node.isPlaceholder ()) ? (" * " + node.getName ()) : node.getName ();\r
95 var fm = g.getFontMetrics (this.$font);\r
96 var charWidth = fm.stringWidth (name) + 3;\r
97 var charHeight = fm.getHeight ();\r
98 var rect =  new java.awt.Rectangle (xend + 10, ypos - charHeight, charWidth, charHeight);\r
99 this.nameHash.put (node.element (), rect);\r
100 var selected = this.av.getSelectionGroup ();\r
101 if (selected != null && selected.getSequences (null).contains (node.element ())) {\r
102 g.setColor (java.awt.Color.gray);\r
103 g.fillRect (xend + 10, ypos - charHeight + 3, charWidth, charHeight);\r
104 g.setColor (java.awt.Color.white);\r
105 }g.drawString (name, xend + 10, ypos);\r
106 g.setColor (java.awt.Color.black);\r
107 } else {\r
108 this.drawNode (g, node.left (), chunk, scale, width, offx, offy);\r
109 this.drawNode (g, node.right (), chunk, scale, width, offx, offy);\r
110 var height = node.height;\r
111 var dist = node.dist;\r
112 var xstart = Clazz.floatToInt ((height - dist) * scale) + offx;\r
113 var xend = Clazz.floatToInt (height * scale) + offx;\r
114 var ypos = Clazz.floatToInt (node.ycount * chunk) + offy;\r
115 g.setColor (node.color.darker ());\r
116 g.drawLine (xstart, ypos, xend, ypos);\r
117 if (node === this.highlightNode) {\r
118 g.fillRect (xend - 3, ypos - 3, 6, 6);\r
119 } else {\r
120 g.fillRect (xend - 2, ypos - 2, 4, 4);\r
121 }var ystart = Clazz.floatToInt ((node.left ()).ycount * chunk) + offy;\r
122 var yend = Clazz.floatToInt ((node.right ()).ycount * chunk) + offy;\r
123 var pos =  new java.awt.Rectangle (xend - 2, ypos - 2, 5, 5);\r
124 this.nodeHash.put (node, pos);\r
125 g.drawLine (Clazz.floatToInt (height * scale) + offx, ystart, Clazz.floatToInt (height * scale) + offx, yend);\r
126 var nodeLabel = "";\r
127 if (this.showDistances && (node.dist > 0)) {\r
128 nodeLabel =  new jalview.util.Format ("%-.2f").formDouble (node.dist);\r
129 }if (this.showBootstrap) {\r
130 var btstrap = node.getBootstrap ();\r
131 if (btstrap > -1) {\r
132 if (this.showDistances) {\r
133 nodeLabel = nodeLabel + " : ";\r
134 }nodeLabel = nodeLabel + String.valueOf (node.getBootstrap ());\r
135 }}if (!nodeLabel.equals ("")) {\r
136 g.drawString (nodeLabel, xstart + 2, ypos - 2);\r
137 }}}, "java.awt.Graphics,jalview.datamodel.SequenceNode,~N,~N,~N,~N,~N");\r
138 Clazz.defineMethod (c$, "findElement", \r
139 function (x, y) {\r
140 var keys = this.nameHash.keys ();\r
141 while (keys.hasMoreElements ()) {\r
142 var ob = keys.nextElement ();\r
143 var rect = this.nameHash.get (ob);\r
144 if (x >= rect.x && x <= (rect.x + rect.width) && y >= rect.y && y <= (rect.y + rect.height)) {\r
145 return ob;\r
146 }}\r
147 keys = this.nodeHash.keys ();\r
148 while (keys.hasMoreElements ()) {\r
149 var ob = keys.nextElement ();\r
150 var rect = this.nodeHash.get (ob);\r
151 if (x >= rect.x && x <= (rect.x + rect.width) && y >= rect.y && y <= (rect.y + rect.height)) {\r
152 return ob;\r
153 }}\r
154 return null;\r
155 }, "~N,~N");\r
156 Clazz.defineMethod (c$, "pickNodes", \r
157 function (pickBox) {\r
158 var width = this.getSize ().width;\r
159 var height = this.getSize ().height;\r
160 var top = this.tree.getTopNode ();\r
161 var wscale = (width * .8 - this.offx * 2) / this.tree.getMaxHeight ();\r
162 if (top.count == 0) {\r
163 top.count = (top.left ()).count + (top.right ()).count;\r
164 }var chunk = (height - this.offy) / top.count;\r
165 this.pickNode (pickBox, top, chunk, wscale, width, this.offx, this.offy);\r
166 }, "java.awt.Rectangle");\r
167 Clazz.defineMethod (c$, "pickNode", \r
168 function (pickBox, node, chunk, scale, width, offx, offy) {\r
169 if (node == null) {\r
170 return;\r
171 }if (node.left () == null && node.right () == null) {\r
172 var height = node.height;\r
173 var xend = Clazz.floatToInt (height * scale) + offx;\r
174 var ypos = Clazz.floatToInt (node.ycount * chunk) + offy;\r
175 if (pickBox.contains ( new java.awt.Point (xend, ypos))) {\r
176 if (Clazz.instanceOf (node.element (), jalview.datamodel.SequenceI)) {\r
177 var seq = node.element ();\r
178 var sg = this.av.getSelectionGroup ();\r
179 if (sg != null) {\r
180 sg.addOrRemove (seq, true);\r
181 }}}} else {\r
182 this.pickNode (pickBox, node.left (), chunk, scale, width, offx, offy);\r
183 this.pickNode (pickBox, node.right (), chunk, scale, width, offx, offy);\r
184 }}, "java.awt.Rectangle,jalview.datamodel.SequenceNode,~N,~N,~N,~N,~N");\r
185 Clazz.defineMethod (c$, "setColor", \r
186 function (node, c) {\r
187 if (node == null) {\r
188 return;\r
189 }if (node.left () == null && node.right () == null) {\r
190 node.color = c;\r
191 if (Clazz.instanceOf (node.element (), jalview.datamodel.SequenceI)) {\r
192 this.av.setSequenceColour (node.element (), c);\r
193 }} else {\r
194 node.color = c;\r
195 this.setColor (node.left (), c);\r
196 this.setColor (node.right (), c);\r
197 }}, "jalview.datamodel.SequenceNode,java.awt.Color");\r
198 Clazz.overrideMethod (c$, "update", \r
199 function (g) {\r
200 this.paint (g);\r
201 }, "java.awt.Graphics");\r
202 Clazz.overrideMethod (c$, "paintComponent", \r
203 function (g) {\r
204 if (this.tree == null) {\r
205 return;\r
206 }if (this.nameHash.size () == 0) {\r
207 this.repaint ();\r
208 }var width = this.scrollPane.getSize ().width;\r
209 var height = this.scrollPane.getSize ().height;\r
210 if (!this.fitToWindow) {\r
211 height = g.getFontMetrics (this.$font).getHeight () * this.nameHash.size ();\r
212 }if (this.getSize ().width > width) {\r
213 this.setSize ( new java.awt.Dimension (width, height));\r
214 this.scrollPane.validate ();\r
215 return;\r
216 }this.setSize ( new java.awt.Dimension (width, height));\r
217 g.setFont (this.$font);\r
218 this.draw (g, width, height);\r
219 this.validate ();\r
220 }, "java.awt.Graphics");\r
221 Clazz.defineMethod (c$, "draw", \r
222 function (g, width, height) {\r
223 this.offy = this.$font.getSize () + 10;\r
224 g.setColor (java.awt.Color.white);\r
225 g.fillRect (0, 0, width, height);\r
226 this.labelLength = g.getFontMetrics (this.$font).stringWidth (this.longestName) + 20;\r
227 var wscale = (width - this.labelLength - this.offx * 2) / this.tree.getMaxHeight ();\r
228 var top = this.tree.getTopNode ();\r
229 if (top.count == 0) {\r
230 top.count = (top.left ()).count + (top.right ()).count;\r
231 }var chunk = (height - this.offy) / top.count;\r
232 this.drawNode (g, this.tree.getTopNode (), chunk, wscale, width, this.offx, this.offy);\r
233 if (this.threshold != 0) {\r
234 if (this.av.getCurrentTree () === this.tree) {\r
235 g.setColor (java.awt.Color.red);\r
236 } else {\r
237 g.setColor (java.awt.Color.gray);\r
238 }var x = Clazz.floatToInt (this.threshold * (this.getSize ().width - this.labelLength - 2 * this.offx) + this.offx);\r
239 g.drawLine (x, 0, x, this.getSize ().height);\r
240 }}, "java.awt.Graphics,~N,~N");\r
241 Clazz.overrideMethod (c$, "mouseReleased", \r
242 function (e) {\r
243 }, "java.awt.event.MouseEvent");\r
244 Clazz.overrideMethod (c$, "mouseEntered", \r
245 function (e) {\r
246 }, "java.awt.event.MouseEvent");\r
247 Clazz.overrideMethod (c$, "mouseExited", \r
248 function (e) {\r
249 }, "java.awt.event.MouseEvent");\r
250 Clazz.overrideMethod (c$, "mouseClicked", \r
251 function (evt) {\r
252 if (this.highlightNode != null) {\r
253 if (evt.getClickCount () > 1) {\r
254 this.tree.swapNodes (this.highlightNode);\r
255 this.tree.reCount (this.tree.getTopNode ());\r
256 this.tree.findHeight (this.tree.getTopNode ());\r
257 } else {\r
258 var leaves =  new java.util.Vector ();\r
259 this.tree.findLeaves (this.highlightNode, leaves);\r
260 for (var i = 0; i < leaves.size (); i++) {\r
261 var seq = (leaves.elementAt (i)).element ();\r
262 this.treeSelectionChanged (seq);\r
263 }\r
264 }jalview.appletgui.PaintRefresher.Refresh (this, this.av.getSequenceSetId ());\r
265 this.repaint ();\r
266 this.av.sendSelection ();\r
267 }}, "java.awt.event.MouseEvent");\r
268 Clazz.overrideMethod (c$, "mouseDragged", \r
269 function (ect) {\r
270 }, "java.awt.event.MouseEvent");\r
271 Clazz.overrideMethod (c$, "mouseMoved", \r
272 function (evt) {\r
273 this.av.setCurrentTree (this.tree);\r
274 var ob = this.findElement (evt.getX (), evt.getY ());\r
275 if (Clazz.instanceOf (ob, jalview.datamodel.SequenceNode)) {\r
276 this.highlightNode = ob;\r
277 this.repaint ();\r
278 } else {\r
279 if (this.highlightNode != null) {\r
280 this.highlightNode = null;\r
281 this.repaint ();\r
282 }}}, "java.awt.event.MouseEvent");\r
283 Clazz.overrideMethod (c$, "mousePressed", \r
284 function (e) {\r
285 this.av.setCurrentTree (this.tree);\r
286 var x = e.getX ();\r
287 var y = e.getY ();\r
288 var ob = this.findElement (x, y);\r
289 if (Clazz.instanceOf (ob, jalview.datamodel.SequenceI)) {\r
290 this.treeSelectionChanged (ob);\r
291 jalview.appletgui.PaintRefresher.Refresh (this, this.av.getSequenceSetId ());\r
292 this.repaint ();\r
293 this.av.sendSelection ();\r
294 return;\r
295 } else if (!(Clazz.instanceOf (ob, jalview.datamodel.SequenceNode))) {\r
296 if (this.tree.getMaxHeight () != 0) {\r
297 this.threshold = (x - this.offx) / (this.getSize ().width - this.labelLength - 2 * this.offx);\r
298 this.tree.getGroups ().removeAllElements ();\r
299 this.tree.groupNodes (this.tree.getTopNode (), this.threshold);\r
300 this.setColor (this.tree.getTopNode (), java.awt.Color.black);\r
301 this.av.setSelectionGroup (null);\r
302 this.av.getAlignment ().deleteAllGroups ();\r
303 this.av.clearSequenceColours ();\r
304 var codingComplement = this.av.getCodingComplement ();\r
305 if (codingComplement != null) {\r
306 codingComplement.setSelectionGroup (null);\r
307 codingComplement.getAlignment ().deleteAllGroups ();\r
308 codingComplement.clearSequenceColours ();\r
309 }this.colourGroups ();\r
310 }}jalview.appletgui.PaintRefresher.Refresh (this, this.av.getSequenceSetId ());\r
311 this.repaint ();\r
312 }, "java.awt.event.MouseEvent");\r
313 Clazz.defineMethod (c$, "colourGroups", \r
314 function () {\r
315 for (var i = 0; i < this.tree.getGroups ().size (); i++) {\r
316 var col =  new java.awt.Color (Clazz.doubleToInt (Math.random () * 255), Clazz.doubleToInt (Math.random () * 255), Clazz.doubleToInt (Math.random () * 255));\r
317 this.setColor (this.tree.getGroups ().elementAt (i), col.brighter ());\r
318 var l = this.tree.findLeaves (this.tree.getGroups ().elementAt (i),  new java.util.Vector ());\r
319 var sequences =  new java.util.Vector ();\r
320 for (var j = 0; j < l.size (); j++) {\r
321 var s1 = (l.elementAt (j)).element ();\r
322 if (!sequences.contains (s1)) {\r
323 sequences.addElement (s1);\r
324 }}\r
325 var cs = null;\r
326 var sg =  new jalview.datamodel.SequenceGroup (sequences, "", cs, true, true, false, 0, this.av.getAlignment ().getWidth () - 1);\r
327 if (this.av.getGlobalColourScheme () != null) {\r
328 if (Clazz.instanceOf (this.av.getGlobalColourScheme (), jalview.schemes.UserColourScheme)) {\r
329 cs =  new jalview.schemes.UserColourScheme ((this.av.getGlobalColourScheme ()).getColours ());\r
330 } else {\r
331 cs = jalview.schemes.ColourSchemeProperty.getColour (sg, jalview.schemes.ColourSchemeProperty.getColourName (this.av.getGlobalColourScheme ()));\r
332 }if (cs != null) {\r
333 cs.setThreshold (this.av.getGlobalColourScheme ().getThreshold (), this.av.isIgnoreGapsConsensus ());\r
334 }}sg.cs = cs;\r
335 sg.setName ("JTreeGroup:" + sg.hashCode ());\r
336 sg.setIdColour (col);\r
337 if (this.av.getGlobalColourScheme () != null && this.av.getGlobalColourScheme ().conservationApplied ()) {\r
338 var c =  new jalview.analysis.Conservation ("Group", jalview.schemes.ResidueProperties.propHash, 3, sg.getSequences (null), sg.getStartRes (), sg.getEndRes ());\r
339 c.calculate ();\r
340 c.verdict (false, this.av.getConsPercGaps ());\r
341 cs.setConservation (c);\r
342 sg.cs = cs;\r
343 }this.av.getAlignment ().addGroup (sg);\r
344 this.av.getAlignment ().addGroup (sg);\r
345 var codingComplement = this.av.getCodingComplement ();\r
346 if (codingComplement != null) {\r
347 var mappedGroup = jalview.util.MappingUtils.mapSequenceGroup (sg, this.av, codingComplement);\r
348 if (mappedGroup.getSequences ().size () > 0) {\r
349 codingComplement.getAlignment ().addGroup (mappedGroup);\r
350 for (var seq, $seq = mappedGroup.getSequences ().iterator (); $seq.hasNext () && ((seq = $seq.next ()) || true);) {\r
351 codingComplement.setSequenceColour (seq, col);\r
352 }\r
353 }}}\r
354 this.ap.updateAnnotation ();\r
355 if (this.av.getCodingComplement () != null) {\r
356 (this.av.getCodingComplement ()).firePropertyChange ("alignment", null, this.ap.av.getAlignment ().getSequences ());\r
357 }});\r
358 Clazz.defineMethod (c$, "setShowDistances", \r
359 function (state) {\r
360 this.showDistances = state;\r
361 this.repaint ();\r
362 }, "~B");\r
363 Clazz.defineMethod (c$, "setShowBootstrap", \r
364 function (state) {\r
365 this.showBootstrap = state;\r
366 this.repaint ();\r
367 }, "~B");\r
368 Clazz.defineMethod (c$, "setMarkPlaceholders", \r
369 function (state) {\r
370 this.markPlaceholders = state;\r
371 this.repaint ();\r
372 }, "~B");\r
373 Clazz.defineStatics (c$,\r
374 "PLACEHOLDER", " * ");\r
375 });\r