|
30 | 30 | thisNode.left = construct_tree(head(lst))
|
31 | 31 | }
|
32 | 32 | } else if (is_function(head(lst))) { // draw the function object
|
33 |
| - if (perms.indexOf(head(lst)) > -1) { // check if function has been drawn |
34 |
| - thisNode.leftid = perms.indexOf(head(lst)) |
35 |
| - } else { |
36 |
| - thisNode.left = construct_function(head(lst)) |
37 |
| - } |
| 33 | + if (perms.indexOf(head(lst)) > -1) { // check if function has been drawn |
| 34 | + thisNode.leftid = perms.indexOf(head(lst)) |
| 35 | + } else { |
| 36 | + thisNode.left = construct_function(head(lst)) |
| 37 | + } |
38 | 38 | } else {
|
39 |
| - // otherwise, it's a data item |
| 39 | + // otherwise, it's a data item |
40 | 40 | thisNode.data = head(lst)
|
41 | 41 | }
|
42 | 42 | // similarly for right subtree.
|
|
47 | 47 | thisNode.right = construct_tree(tail(lst))
|
48 | 48 | }
|
49 | 49 | } else if (is_function(tail(lst))) {
|
50 |
| - if (perms.indexOf(tail(lst)) > -1) { |
51 |
| - thisNode.rightid = perms.indexOf(tail(lst)) |
52 |
| - } else { |
53 |
| - thisNode.right = construct_function(tail(lst)) |
54 |
| - } |
| 50 | + if (perms.indexOf(tail(lst)) > -1) { |
| 51 | + thisNode.rightid = perms.indexOf(tail(lst)) |
| 52 | + } else { |
| 53 | + thisNode.right = construct_function(tail(lst)) |
| 54 | + } |
55 | 55 | } else {
|
56 | 56 | thisNode.data2 = tail(lst)
|
57 | 57 | }
|
|
182 | 182 | // if it's left child is part of a cycle and it's been drawn, link back to that node instead
|
183 | 183 | } else if (node.leftid != null) {
|
184 | 184 | backwardLeftEdge(x, y, nodelist[node.leftid].getX(), nodelist[node.leftid].getY(), layer)
|
| 185 | + } else if ((node.data === null) && !!node.isFunction) { |
| 186 | + var nullbox = new NodeEmptyHead_list(x, y) |
| 187 | + nullbox.put(layer) |
185 | 188 | }
|
186 | 189 |
|
187 | 190 | // similarly for right child
|
|
227 | 230 | this.drawLeft(node.left, x, y, layer)
|
228 | 231 | } else if (node.leftid != null) {
|
229 | 232 | backwardLeftEdge(x, y, nodelist[node.leftid].getX(), nodelist[node.leftid].getY(), layer)
|
| 233 | + } else if ((node.data === null) && !node.isFunction) { |
| 234 | + var nullbox = new NodeEmptyHead_list(x, y) |
| 235 | + nullbox.put(layer) |
230 | 236 | }
|
231 | 237 | if (node.right !== null) {
|
232 | 238 | this.drawRight(node.right, x, y, layer)
|
|
266 | 272 | this.drawLeft(node.left, x, y, layer)
|
267 | 273 | } else if (node.leftid != null) {
|
268 | 274 | backwardLeftEdge(x, y, nodelist[node.leftid].getX(), nodelist[node.leftid].getY(), layer)
|
| 275 | + } else if ((node.data === null) && !node.isFunction) { |
| 276 | + var nullbox = new NodeEmptyHead_list(x, y) |
| 277 | + nullbox.put(layer) |
269 | 278 | }
|
270 | 279 | if (node.right !== null) {
|
271 | 280 | this.drawRight(node.right, x, y, layer)
|
|
354 | 363 | /**
|
355 | 364 | * Try to fit any data into the box. If not possible, assign a number and log it in the console.
|
356 | 365 | */
|
357 |
| - function toText(data, full) { |
| 366 | + function toText(data, full) { |
358 | 367 | if (full) {
|
359 | 368 | return '' + data
|
360 | 369 | } else {
|
361 | 370 | var type = typeof data
|
362 | 371 | if (type === 'function' || type === 'object') {
|
363 | 372 | return false
|
364 |
| - } else { |
| 373 | + } else if (type === "string") { |
365 | 374 | var str = '' + data
|
366 | 375 | if (str.length > 5) {
|
367 | 376 | return false
|
368 | 377 | } else {
|
369 |
| - return str |
| 378 | + return '"' + str + '"' |
370 | 379 | }
|
| 380 | + } else { |
| 381 | + return '' + data |
371 | 382 | }
|
372 | 383 | }
|
373 | 384 | }
|
|
504 | 515 | }
|
505 | 516 |
|
506 | 517 | /**
|
507 |
| - * Connects a NodeBox to it's parent at x,y by using line segments with arrow head |
| 518 | + * Connects a NodeBox to its parent at x,y by using line segments with arrow head |
508 | 519 | */
|
509 | 520 | NodeBox.prototype.connectTo = function(x, y) {
|
510 | 521 | // starting point
|
|
762 | 773 | x1 + tcon.boxWidth * 3 / 4,
|
763 | 774 | y1 + tcon.boxSpacingY * 3 / 4,
|
764 | 775 | x1 + tcon.boxWidth * 3 / 4,
|
765 |
| - y2 - tcon.boxSpacingY * 3 / 8, |
| 776 | + y2 - tcon.boxSpacingY * 3 / 8 + 7, |
766 | 777 | x2 + tcon.boxWidth / 4 + tcon.arrowSpaceH,
|
767 |
| - y2 - tcon.boxSpacingY * 3 / 8, |
| 778 | + y2 - tcon.boxSpacingY * 3 / 8 + 7, |
768 | 779 | x2 + tcon.boxWidth / 4 + tcon.arrowSpaceH,
|
769 | 780 | y2 - tcon.arrowSpace
|
770 | 781 | ]
|
|
855 | 866 | return this.image
|
856 | 867 | }
|
857 | 868 |
|
| 869 | + /** |
| 870 | + * Complements a NodeBox when the head is an empty box. |
| 871 | + */ |
| 872 | + function NodeEmptyHead_list(x, y) { |
| 873 | + var null_box = new Kinetic.Line({ |
| 874 | + x: x - tcon.boxWidth / 2, |
| 875 | + y: y, |
| 876 | + points: [ |
| 877 | + tcon.boxWidth * tcon.vertBarPos, |
| 878 | + tcon.boxHeight, |
| 879 | + tcon.boxWidth * tcon.vertBarPos, |
| 880 | + 0, |
| 881 | + tcon.boxWidth, |
| 882 | + 0, |
| 883 | + tcon.boxWidth * tcon.vertBarPos, |
| 884 | + tcon.boxHeight, |
| 885 | + tcon.boxWidth, |
| 886 | + tcon.boxHeight, |
| 887 | + tcon.boxWidth, |
| 888 | + 0 |
| 889 | + ], |
| 890 | + strokeWidth: tcon.strokeWidth - 1, |
| 891 | + stroke: 'white' |
| 892 | + }) |
| 893 | + this.image = null_box |
| 894 | + } |
| 895 | + |
| 896 | + /** |
| 897 | + * Adds it to a container |
| 898 | + */ |
| 899 | + NodeEmptyHead_list.prototype.put = function(container) { |
| 900 | + container.add(this.image) |
| 901 | + } |
| 902 | + |
| 903 | + NodeEmptyHead_list.prototype.getRaw = function() { |
| 904 | + return this.image |
| 905 | + } |
| 906 | + |
858 | 907 | // A list of layers drawn, used for history
|
859 | 908 | var layerList = []
|
860 | 909 | // ID of the current layer shown. Avoid changing this value externally as layer is not updated.
|
|
982 | 1031 | const existing = [];
|
983 | 1032 |
|
984 | 1033 | function helper(xs) {
|
985 |
| - if ((!is_pair(xs) && !is_array(xs)) || is_null(xs)) { |
| 1034 | + if ((!is_pair(xs) && !is_function(xs)) || is_null(xs)) { |
986 | 1035 | return 0;
|
987 | 1036 | } else {
|
988 | 1037 | let leftHeight;
|
989 | 1038 | let rightHeight;
|
990 | 1039 | if (existing.includes(xs[0])
|
991 |
| - || (!is_pair(xs[0]) && (!is_array(xs[0])))) { |
| 1040 | + || (!is_pair(xs[0]) && !is_function(xs[0]))) { |
992 | 1041 | leftHeight = 0;
|
993 | 1042 | } else {
|
994 | 1043 | existing.push(xs[0]);
|
995 | 1044 | leftHeight = helper(xs[0]);
|
996 | 1045 | }
|
997 | 1046 | if (existing.includes(xs[1])
|
998 |
| - || (!is_pair(xs[1]) && (!is_array(xs[1])))) { |
| 1047 | + || (!is_pair(xs[1]) && !is_function(xs[1]))) { |
999 | 1048 | rightHeight = 0;
|
1000 | 1049 | } else {
|
1001 | 1050 | existing.push(xs[1]);
|
|
1017 | 1066 | const existing = [];
|
1018 | 1067 |
|
1019 | 1068 | function helper(xs) {
|
1020 |
| - if ((!is_pair(xs) && !is_array(xs)) || is_null(xs)) { |
| 1069 | + if ((!is_pair(xs) && !is_function(xs)) || is_null(xs)) { |
1021 | 1070 | return 0;
|
1022 | 1071 | } else {
|
1023 | 1072 | let leftWidth;
|
1024 | 1073 | let rightWidth;
|
1025 | 1074 | if (existing.includes(xs[0])
|
1026 |
| - || (!is_pair(xs[0]) && (!is_array(xs[0])))) { |
| 1075 | + || (!is_pair(xs[0]) && !is_function(xs[0]))) { |
1027 | 1076 | leftWidth = 0;
|
1028 | 1077 | } else {
|
1029 | 1078 | existing.push(xs[0]);
|
1030 | 1079 | leftWidth = helper(xs[0]);
|
1031 | 1080 | }
|
1032 | 1081 | if (existing.includes(xs[1])
|
1033 |
| - || (!is_pair(xs[1]) && (!is_array(xs[1])))) { |
| 1082 | + || (!is_pair(xs[1]) && !is_function(xs[1]))) { |
1034 | 1083 | rightWidth = 0;
|
1035 | 1084 | } else {
|
1036 | 1085 | existing.push(xs[1]);
|
|
0 commit comments