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