mascot-vis 3.0.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/package.json +1 -2
  2. package/js/depGraphVis.js +0 -66
  3. package/src-new-ts/action/createElement.ts +0 -91
  4. package/src-new-ts/action/encode.js +0 -20
  5. package/src-new-ts/action/repeat.js +0 -128
  6. package/src-new-ts/action/traverseScene.js +0 -41
  7. package/src-new-ts/data/Network.js +0 -2
  8. package/src-new-ts/data/Scope.js +0 -135
  9. package/src-new-ts/data/Table.js +0 -263
  10. package/src-new-ts/data/Tree.js +0 -3
  11. package/src-new-ts/data/field.ts +0 -115
  12. package/src-new-ts/data/import.ts +0 -96
  13. package/src-new-ts/data/predicate.ts +0 -82
  14. package/src-new-ts/depgraph/DepGraph.js +0 -178
  15. package/src-new-ts/depgraph/Edge.js +0 -9
  16. package/src-new-ts/depgraph/SceneGraph2DepGraph.js +0 -110
  17. package/src-new-ts/depgraph/Signal.js +0 -12
  18. package/src-new-ts/depgraph/operator/BoundsEvaluator.js +0 -30
  19. package/src-new-ts/depgraph/operator/Dataflow.js +0 -41
  20. package/src-new-ts/depgraph/operator/DomainBuilder.js +0 -50
  21. package/src-new-ts/depgraph/updateDepGraph.js +0 -45
  22. package/src-new-ts/depgraph/variable/BoundsVar.js +0 -81
  23. package/src-new-ts/depgraph/variable/ChannelVar.js +0 -17
  24. package/src-new-ts/depgraph/variable/DataScopeVar.js +0 -12
  25. package/src-new-ts/depgraph/variable/DomainVar.js +0 -15
  26. package/src-new-ts/depgraph/variable/FieldVar.js +0 -17
  27. package/src-new-ts/depgraph/variable/LayoutParameter.js +0 -8
  28. package/src-new-ts/depgraph/variable/ScaleVar.js +0 -13
  29. package/src-new-ts/depgraph/variable/Variable.js +0 -39
  30. package/src-new-ts/element/gradient/LinearGradient.js +0 -37
  31. package/src-new-ts/element/group/Collection.js +0 -109
  32. package/src-new-ts/element/group/Group.js +0 -307
  33. package/src-new-ts/element/group/Scene.js +0 -98
  34. package/src-new-ts/element/mark/CircleMark.ts +0 -85
  35. package/src-new-ts/element/mark/Mark.ts +0 -233
  36. package/src-new-ts/element/mark/PathMark.js +0 -483
  37. package/src-new-ts/element/mark/Segment.js +0 -29
  38. package/src-new-ts/element/mark/Vertex.js +0 -118
  39. package/src-new-ts/encode/Scale.ts +0 -115
  40. package/src-new-ts/index.ts +0 -19
  41. package/src-new-ts/layout/Layout.ts +0 -3
  42. package/src-new-ts/render/CanvasRenderer.ts +0 -24
  43. package/src-new-ts/render/SVGRenderer.js +0 -316
  44. package/src-new-ts/util.ts +0 -3
  45. package/src-old/action/Classify.js +0 -53
  46. package/src-old/action/Densify.js +0 -199
  47. package/src-old/action/Partition.js +0 -531
  48. package/src-old/action/Repeat.js +0 -106
  49. package/src-old/action/Repopulate.js +0 -44
  50. package/src-old/action/Stratify.js +0 -156
  51. package/src-old/basic/Gradient.js +0 -37
  52. package/src-old/basic/Point.js +0 -51
  53. package/src-old/basic/Rectangle.js +0 -63
  54. package/src-old/bind/bindToAngle.js +0 -56
  55. package/src-old/bind/bindToAreaMark.js +0 -360
  56. package/src-old/bind/bindToColor.js +0 -114
  57. package/src-old/bind/bindToLink.js +0 -81
  58. package/src-old/bind/bindToPosition.js +0 -283
  59. package/src-old/bind/bindToRadialDistance.js +0 -62
  60. package/src-old/bind/bindToSize.js +0 -235
  61. package/src-old/bind/bindToText.js +0 -60
  62. package/src-old/bind/bindToThickness.js +0 -100
  63. package/src-old/constraint/AffixConstraint.js +0 -129
  64. package/src-old/constraint/AlignConstraint.js +0 -58
  65. package/src-old/core/Encoding.js +0 -336
  66. package/src-old/core/Scale.js +0 -322
  67. package/src-old/core/SceneLoader.js +0 -290
  68. package/src-old/core/SceneValidator.js +0 -232
  69. package/src-old/core/SpecExecutor.js +0 -113
  70. package/src-old/core/SpecGenerator.js +0 -350
  71. package/src-old/data/DataImporter.js +0 -64
  72. package/src-old/data/DataScope.js +0 -124
  73. package/src-old/data/DataTable.js +0 -338
  74. package/src-old/data/Network.js +0 -106
  75. package/src-old/data/Tree.js +0 -251
  76. package/src-old/data/transform/Bin.js +0 -46
  77. package/src-old/data/transform/Filter.js +0 -48
  78. package/src-old/data/transform/Groupby.js +0 -18
  79. package/src-old/data/transform/KDE.js +0 -58
  80. package/src-old/data/transform/Sort.js +0 -14
  81. package/src-old/data/transform/Split.js +0 -5
  82. package/src-old/data/transform/partition.js +0 -46
  83. package/src-old/history/UndoRedoStack +0 -0
  84. package/src-old/index.js +0 -271
  85. package/src-old/indexSVG.js +0 -259
  86. package/src-old/interaction/Interaction.js +0 -91
  87. package/src-old/interaction/MouseEvent.js +0 -8
  88. package/src-old/interaction/Selection.js +0 -9
  89. package/src-old/interaction/brush.js +0 -362
  90. package/src-old/item/Segment.js +0 -29
  91. package/src-old/item/Vertex.js +0 -118
  92. package/src-old/item/composite/Collection.js +0 -106
  93. package/src-old/item/composite/Glyph.js +0 -19
  94. package/src-old/item/composite/Group.js +0 -310
  95. package/src-old/item/composite/Scene.js +0 -1251
  96. package/src-old/item/mark/ArcPath.js +0 -181
  97. package/src-old/item/mark/AreaPath.js +0 -78
  98. package/src-old/item/mark/CirclePath.js +0 -102
  99. package/src-old/item/mark/EllipsePath.js +0 -5
  100. package/src-old/item/mark/Image.js +0 -101
  101. package/src-old/item/mark/LinkPath.js +0 -118
  102. package/src-old/item/mark/Mark.js +0 -163
  103. package/src-old/item/mark/Path.js +0 -494
  104. package/src-old/item/mark/PointText.js +0 -201
  105. package/src-old/item/mark/PolygonPath.js +0 -64
  106. package/src-old/item/mark/RectPath.js +0 -88
  107. package/src-old/item/mark/RingPath.js +0 -92
  108. package/src-old/item/refs/Axis.js +0 -362
  109. package/src-old/item/refs/EncodingAxis.js +0 -515
  110. package/src-old/item/refs/Gridlines.js +0 -144
  111. package/src-old/item/refs/LayoutAxis.js +0 -316
  112. package/src-old/item/refs/Legend.js +0 -273
  113. package/src-old/layout/Circular.js +0 -95
  114. package/src-old/layout/Force.js +0 -52
  115. package/src-old/layout/Grid.js +0 -423
  116. package/src-old/layout/Layout.js +0 -13
  117. package/src-old/layout/Packing.js +0 -56
  118. package/src-old/layout/Stack.js +0 -264
  119. package/src-old/layout/Strata.js +0 -88
  120. package/src-old/layout/Sugiyama.js +0 -59
  121. package/src-old/layout/TidyTree.js +0 -105
  122. package/src-old/layout/Treemap.js +0 -87
  123. package/src-old/renderer/SVGInteractionHandler.js +0 -241
  124. package/src-old/renderer/SVGRenderer.js +0 -325
  125. package/src-old/renderer/WebGLRenderer.js +0 -1097
  126. package/src-old/renderer/WebGLRenderer2.js +0 -249
  127. package/src-old/renderer/threejs/Line2.js +0 -18
  128. package/src-old/renderer/threejs/LineGeometry.js +0 -77
  129. package/src-old/renderer/threejs/LineMaterial.js +0 -605
  130. package/src-old/renderer/threejs/LineSegments2.js +0 -281
  131. package/src-old/renderer/threejs/LineSegmentsGeometry.js +0 -226
  132. package/src-old/renderer/threejs/Wireframe.js +0 -51
  133. package/src-old/renderer/threejs/WireframeGeometry2.js +0 -16
  134. package/src-old/scale/areaSize.js +0 -0
  135. package/src-old/scale/domain.js +0 -38
  136. package/src-old/util/Constants.js +0 -180
  137. package/src-old/util/DataUtil.js +0 -35
  138. package/src-old/util/ItemUtil.js +0 -586
  139. package/src-old/util/Numerical.js +0 -33
  140. package/tests/demo-tests/README.md +0 -80
  141. package/tests/demo-tests/SVG2PNG.js +0 -56
  142. package/tests/demo-tests/demos2CanvasPNGs.js +0 -69
  143. package/tests/demo-tests/demos2ScenesSVGs.js +0 -100
  144. package/tests/demo-tests/pathElementWorker.js +0 -91
  145. package/tests/demo-tests/pixelTest.js +0 -62
  146. package/tests/demo-tests/renderDemos.html +0 -132
  147. package/tests/demo-tests/serializationTest.js +0 -36
  148. package/tests/demo-tests/serializeDemos.html +0 -134
  149. package/tests/unit-tests/README.md +0 -4
  150. package/tests/unit-tests/jasmine-browser.json +0 -21
  151. package/tests/unit-tests/jasmine.json +0 -14
  152. package/tests/unit-tests/testSpec.js +0 -274
@@ -1,1251 +0,0 @@
1
- import Group from "./Group";
2
- import { ItemType, Errors, LayoutType, ConstraintType, DataType, Warnings, Orientation } from "../../util/Constants";
3
- import { findItems, getParents, canAlign, getPeers, getEncodingKey, getClosestLayout, getPeersGroupedByParent, isPath, isGuide, isMark, ItemCounter, getAllChildren } from "../../util/ItemUtil";
4
- import { validateField } from "../../util/DataUtil";
5
- import { repeatItem, repeatNodeLink } from "../../action/Repeat";
6
- import { divideItem } from "../../action/Partition";
7
- import { densifyItem } from "../../action/Densify";
8
- import Mark from "../mark/Mark";
9
- import RectPath from "../mark/RectPath";
10
- import CirclePath from "../mark/CirclePath";
11
- import Path from "../mark/Path";
12
- import { bindToSize } from "../../bind/bindToSize";
13
- import { bindToPosition } from "../../bind/bindToPosition";
14
- import { bindToRadialDistance } from "../../bind/bindToRadialDistance";
15
- import { bindToColor } from "../../bind/bindToColor";
16
- import { bindToAngle } from "../../bind/bindToAngle"
17
- import { bindToAreaMark } from "../../bind/bindToAreaMark";
18
- import { bindToText } from "../../bind/bindToText";
19
- import Encoding from "../../core/Encoding";
20
- import DataTable from "../../data/DataTable";
21
- import EncodingAxis from "../refs/EncodingAxis";
22
- import LayoutAxis from "../refs/LayoutAxis";
23
- import Legend from "../refs/Legend";
24
- import Glyph from "./Glyph";
25
- import AreaPath from "../mark/AreaPath";
26
- import RingPath from "../mark/RingPath";
27
- import PolygonPath from "../mark/PolygonPath";
28
- import AlignConstraint from "../../constraint/AlignConstraint";
29
- import AffixConstraint from "../../constraint/AffixConstraint";
30
- import PointText from "../mark/PointText";
31
- import Gridlines from "../refs/Gridlines";
32
- import Collection from "./Collection";
33
- import DataScope from "../../data/DataScope";
34
- import ArcPath from "../mark/ArcPath";
35
- import Image from "../mark/Image";
36
- import LinkPath from "../mark/LinkPath";
37
- import { bindToLink } from "../../bind/bindToLink";
38
- import SceneValidator from "../../core/SceneValidator";
39
- import { repopulateItem } from "../../action/Repopulate";
40
- import { bindToThickness } from "../../bind/bindToThickness";
41
- import Tree from "../../data/Tree";
42
- import { stratifyItem } from "../../action/Stratify";
43
- import { classifiable, classifyCollectionChildren } from "../../action/Classify";
44
-
45
-
46
- export default class Scene extends Group {
47
-
48
- constructor(args) {
49
- super();
50
- if (args && args.fillColor) {
51
- this.fillColor = args.fillColor;
52
- }
53
- this.type = ItemType.Scene;
54
- this._id = this.type + ItemCounter[this.type]++;
55
- //this.cellAlign = {};
56
- this._encodings = {};
57
- this.constraints = {};
58
- this._itemMap = {};
59
- this._interactions = [];
60
- this._interactionsObj = {};
61
- }
62
-
63
- clear() {
64
- this.removeAll();
65
- this._encodings = {};
66
- this.constraints = {};
67
- this._itemMap = {};
68
- }
69
-
70
- group(children) {
71
- let g = new Group();
72
- g.classId = g.id;
73
- this.addChild(g);
74
- if (children && children.length > 0)
75
- for (let c of children)
76
- g.addChild(c);
77
- this._itemMap[g.id] = g;
78
- return g;
79
- }
80
-
81
- mark(type, param) {
82
- let args = param === undefined ? {} : param;
83
- let m = null;
84
- args.type = type;
85
- switch (type) {
86
- case ItemType.Rect: {
87
- if (!("top" in args))
88
- args.top = 0;
89
- if (!("left" in args))
90
- args.left = 0;
91
- if (!("width" in args))
92
- args.width = 100;
93
- if (!("height" in args))
94
- args.height = 100;
95
- let top = args["top"], left = args["left"], width = args["width"], height = args["height"];
96
- args.vertices = [[left, top], [left + width, top], [left + width, top + height], [left, top + height]];
97
- delete args["top"];
98
- delete args["left"];
99
- delete args["width"];
100
- delete args["height"];
101
- if (!("fillColor" in args)) {
102
- args.fillColor = "none";
103
- }
104
- m = new RectPath(args);
105
- break;
106
- }
107
- case ItemType.Area:
108
- if (args !== undefined && "x1" in args && "y1" in args && "x2" in args && "y2" in args) {
109
- let x1 = args["x1"], y1 = args["y1"], x2 = args["x2"], y2 = args["y2"];
110
- // args.vertices contains all the vertices on two boundary lines
111
- args.vertices = [[x1, y1], [x2, y1], [x2, y2], [x1, y2]];
112
- delete args["x1"];
113
- delete args["y1"];
114
- delete args["x2"];
115
- delete args["y2"];
116
- }
117
- m = new AreaPath(args);
118
- break;
119
- case ItemType.Line: {
120
- //it is possible to create a skeleton line without x1, y1, x2, y2 args, e.g. when duplicating
121
- if (args !== undefined && "x1" in args && "y1" in args && "x2" in args && "y2" in args) {
122
- let x1 = args["x1"], y1 = args["y1"], x2 = args["x2"], y2 = args["y2"];
123
- args.vertices = [[x1, y1], [x2, y2]];
124
- //remove x1, y1, x2, y2 and compute these values at rendering time
125
- //so that we don't have to keep track of them when the line is transformed
126
- delete args["x1"];
127
- delete args["y1"];
128
- delete args["x2"];
129
- delete args["y2"];
130
- }
131
- m = new Path(args);
132
- m.type = ItemType.Line;
133
- break;
134
- }
135
- case ItemType.Path:
136
- m = new Path(args);
137
- break;
138
- case ItemType.Circle:
139
- m = new CirclePath(args);
140
- break;
141
- case ItemType.Ring:
142
- m = new RingPath(args);
143
- break;
144
- case ItemType.Arc:
145
- case ItemType.Pie:
146
- m = new ArcPath(args);
147
- break;
148
- case ItemType.Polygon:
149
- m = new PolygonPath(args);
150
- break;
151
- // case ItemType.Pie:
152
- // args.innerRadius = 0;
153
- // if ("radius" in args) {
154
- // args.outerRadius = args.radius;
155
- // }
156
- // m = new ArcPath(args);
157
- // break;
158
- case "text":
159
- case ItemType.PointText:
160
- if (!("anchor" in args))
161
- args["anchor"] = ["center", "middle"];
162
- m = new PointText(args);
163
- break;
164
- case ItemType.Image:
165
- m = new Image(args);
166
- break;
167
- case ItemType.Link:
168
- m = new LinkPath(args);
169
- break;
170
- default:
171
- break;
172
- }
173
- if (m !== null) {
174
- if ("id" in args)
175
- m.id = args.id;
176
- else
177
- m.id = m.type + ItemCounter[m.type]++;
178
- m.classId = m.id;
179
- this.addChild(m);
180
- this._itemMap[m.id] = m;
181
- }
182
- return m;
183
- }
184
-
185
- glyph(...args) {
186
- let g = new Glyph(args);
187
- g.classId = g.id;
188
- this.addChild(g);
189
- this._itemMap[g.id] = g;
190
- return g;
191
- }
192
-
193
- collection() {
194
- let c = new Collection();
195
- this.addChild(c);
196
- this._itemMap[c.id] = c;
197
- return c;
198
- }
199
-
200
- attach(item, table) {
201
- item.dataScope = new DataScope(table);
202
- }
203
-
204
- repeat(item, data, param) {
205
- if (!item || data === undefined) {
206
- throw Errors.INCOMPLETE_REPEAT_INFO;
207
- }
208
-
209
- if (data.nodeTable && data.linkTable) {
210
- if (!Array.isArray(item) || item.length !== 2)
211
- throw Errors.REPEAT_NODE_LINK;
212
- return repeatNodeLink(this, item[0], item[1], data);
213
- } else {
214
- let args = param ? param : {},
215
- field = args["field"] ? args["field"] : DataTable.RowID,
216
- callback = args["callback"];
217
-
218
- validateField(field, data);
219
-
220
- let collection = repeatItem(this, item, field, data, callback);
221
- if (args.layout)
222
- collection.layout = args.layout;
223
- return collection;
224
- }
225
- }
226
-
227
- repopulate(item, table, param) {
228
- if (!item || table === undefined) {
229
- throw Errors.INCOMPLETE_REPEAT_INFO;
230
- }
231
-
232
- let args = param ? param : {},
233
- field = args["field"] ? args["field"] : DataTable.RowID;
234
-
235
- validateField(field, table);
236
- repopulateItem(this, item, field, table);
237
- }
238
-
239
- densify(item, table, param) {
240
- if (!item || table === undefined) {
241
- throw Errors.INCOMPLETE_PARTITION_INFO;
242
- }
243
-
244
- let args = param ? param : {},
245
- orientation = args["orientation"],
246
- field = args["field"] ? args["field"] : DataTable.RowID,
247
- //following two are for circle densification
248
- startAngle = "startAngle" in args ? args["startAngle"] : 90,
249
- direction = 'direction' in args ? args["direction"] : "clockwise",
250
- callback = args["callback"];
251
-
252
- validateField(field, table);
253
-
254
- let newItem = densifyItem(this, item, orientation, field, table, callback, startAngle, direction);
255
- SceneValidator.markDensified(item, newItem);
256
- return newItem;
257
- }
258
-
259
- stratify(item, data, param) {
260
- if (!(data instanceof Tree)) {
261
- throw Errors.STRATIFY_WITHOUT_TREE;
262
- }
263
-
264
- if (item.type !== ItemType.Circle && item.type !== ItemType.Rect) {
265
- throw Errors.STRATIFY_WRONG_ITEM;
266
- }
267
-
268
- let args = param ? param : {},
269
- direction = args["direction"],
270
- size = args["size"];
271
-
272
- let collection = stratifyItem(this, item, direction, size, data);
273
- //SceneValidator.markDivided(item, collection);
274
- return collection;
275
- }
276
-
277
- divide(item, data, param) {
278
- if (!item || data == undefined) {
279
- throw Errors.INCOMPLETE_PARTITION_INFO;
280
- }
281
-
282
- let args = param ? param : {},
283
- orientation = args["orientation"],
284
- field = args["field"] ? args["field"] : DataTable.RowID,
285
- callback = args["callback"];
286
-
287
- validateField(field, data);
288
-
289
- let collection = divideItem(this, item, orientation, field, data, callback);
290
- if (args.layout)
291
- collection.layout = args.layout;
292
-
293
- SceneValidator.markDivided(item, collection);
294
- return collection;
295
- }
296
-
297
- classify(item, param) {
298
- if (!classifiable(item)) {
299
- throw Errors.CANNOT_CLASSIFY + item.type;
300
- }
301
-
302
- let args = param ? param : {},
303
- field = args["field"] ? args["field"] : DataTable.RowID,
304
- dt = item.firstChild.dataScope.dataTable,
305
- layout = args.layout;
306
- validateField(field, dt);
307
-
308
- classifyCollectionChildren(this, item, field, layout);
309
-
310
- //SceneValidator.markDivided(item, collection);
311
- return item;
312
- }
313
-
314
- _validateEncodeArgs(item, args) {
315
- if (!item || !("channel" in args) || !("field" in args)) {
316
- throw Errors.INCOMPLETE_BINDING_INFO;
317
- }
318
-
319
- let field = args["field"];
320
-
321
- //check if can apply encoding
322
- if (item.type == "vertex" || item.type == "segment") {
323
- if (!item.parent.dataScope && !item.dataScope) {
324
- throw Errors.BIND_WITHOUT_DATASCOPE;
325
- }
326
- } else if (!item.dataScope) {
327
- throw Errors.BIND_WITHOUT_DATASCOPE;
328
- }
329
-
330
-
331
- let datatable = args.table ? args.table : item.dataScope ? item.dataScope._dt : item.parent.dataScope._dt;
332
-
333
- let ft = datatable.getFieldType(field);
334
- if (args.channel === "fillGradient" && [DataType.String, DataType.Boolean, DataType.Date].indexOf(ft) >= 0)
335
- throw Errors.UNSUPPORTED_FIELDTYPE + args.channel + ": " + ft;
336
-
337
- validateField(field, datatable);
338
- //todo: validate channel
339
- }
340
-
341
- //supports encoding one single item or an array of items (which will use the same scale)
342
- encode(itm, args) {
343
- let arr = Array.isArray(itm) ? itm : [itm];
344
- let encs = [], scale;
345
- for (let item of arr) {
346
- let items;
347
- if ([ItemType.Pie, ItemType.Arc].indexOf(itm.type) >= 0 && args.channel === "angle") {
348
- let parent = itm.parent;
349
- if (parent.type === ItemType.Collection && parent.layout && parent.layout.orientation === Orientation.Angular) {
350
- encs.push(this._encodeWithinCollection(item, args));
351
- continue;
352
- }
353
- }
354
- this._validateEncodeArgs(item, args);
355
- if (item.type == "vertex" && item.parent.type == ItemType.Area) {
356
- let areas = getPeers(item.parent, this);
357
- items = [];
358
- let firstHalf = item.parent.vertices.indexOf(item) < item.parent.vertices.length / 2;
359
- for (let area of areas) {
360
- items = firstHalf ? items.concat(area.vertices.slice(0, area.vertices.length / 2)) : items.concat(area.vertices.slice(area.vertices.length / 2));
361
- }
362
- } else {
363
- items = getPeers(item, this);
364
- }
365
- if (items.length === 1 && items[0].type === ItemType.Area && (args.channel === "x" || args.channel === "y")) {
366
- console.warn("Only 1 " + item.type + " found, cannot encode " + args.field);
367
- return;
368
- }
369
- if (!args.scale && scale) {
370
- args.scale = scale;
371
- }
372
- let enc = this._doEncode(items, args);
373
- if (!scale)
374
- scale = enc.scale;
375
- encs.push(enc);
376
- }
377
-
378
- return encs.length > 1 ? encs : encs[0];
379
- }
380
-
381
- _doEncode(items, args) {
382
- let item = items[0],
383
- channel = args["channel"],
384
- field = args["field"];
385
-
386
- if (!("datatable" in args))
387
- args.datatable = item.dataScope ? item.dataScope.dataTable : item.parent.dataScope.dataTable;
388
- if (!("aggregator" in args))
389
- args.aggregator = "mean";
390
- if (!("flipScale" in args))
391
- args.flipScale = false;
392
- if (!("includeZero" in args))
393
- args.includeZero = false;
394
- if (!("scaleType" in args))
395
- args.scaleType = "linear";
396
-
397
- let encoding = new Encoding(items, this, channel, field, args);
398
- switch (channel) {
399
- case "width":
400
- case "height":
401
- case "radius":
402
- case "outerRadius":
403
- case "innerRadius":
404
- case "area":
405
- case "fontSize":
406
- if (item.type == ItemType.Area)
407
- bindToAreaMark(encoding);
408
- else
409
- bindToSize(encoding);
410
- break;
411
- case "strokeWidth":
412
- if (item.type == ItemType.Link)
413
- bindToLink(encoding);
414
- else
415
- bindToSize(encoding);
416
- break;
417
- case "x":
418
- case "y":
419
- bindToPosition(encoding);
420
- // if (item.type == ItemType.Area)
421
- // bindToAreaMark(encoding);
422
- // else
423
- // bindToPosition(encoding);
424
- break;
425
- case "fillColor":
426
- case "strokeColor":
427
- bindToColor(encoding);
428
- break;
429
- case "fillGradient":
430
- if (item.type === ItemType.Area)
431
- bindToAreaMark(encoding);
432
- break;
433
- case "angle":
434
- bindToAngle(encoding);
435
- break;
436
- case "text":
437
- bindToText(encoding);
438
- break;
439
- case "radialDistance":
440
- // encoding.x = item.parent.x;
441
- // encoding.y = item.parent.y;
442
- // encoding.radius = item.parent.radius;
443
- bindToRadialDistance(encoding);
444
- break;
445
- case "thickness":
446
- bindToThickness(encoding);
447
- break;
448
- default:
449
- break;
450
- }
451
-
452
- if (!("_remember" in args) || args._remember == true)
453
- this._registerBinding(encoding);
454
-
455
- if (channel.indexOf("Color") < 0)
456
- this._updateAncestorBounds(item, encoding.items);
457
-
458
- return encoding;
459
- }
460
-
461
- _encodeWithinCollection(item, args) {
462
- this._validateEncodeArgs(item, args);
463
- let peersByGroup = getPeersGroupedByParent(item, this);
464
- let encs = [];
465
- for (let g of peersByGroup) {
466
- let enc = this._doEncode(g, args);
467
- encs.push(enc);
468
- }
469
- return encs;
470
- }
471
-
472
- getPeers(item) {
473
- return getPeers(item, this);
474
- }
475
-
476
- find(predicates) {
477
- return findItems(this, predicates);
478
- }
479
-
480
- align(items, direction) {
481
- //TODO: check the existing constraints and encodings and see if there's any conflict
482
- //if so, do nothing and return false
483
- if (!canAlign(items, direction, this)) return false;
484
- let c = new AlignConstraint(items, direction);
485
- if (c.id in this.constraints) {
486
- console.warn('constraint has been added');
487
- return false;
488
- }
489
- this.constraints[c.id] = c;
490
- c.apply();
491
- this._updateAncestorBounds(items[0]);
492
- }
493
-
494
- removeAllConstraints() {
495
- this.constraints = {};
496
- }
497
-
498
- removeConstraint(c) {
499
- delete this.constraints[c.id];
500
- }
501
-
502
- getRelatedConstraints(items) {
503
- let cstrs = [];
504
- for (let cid in this.constraints) {
505
- let c = this.constraints[cid];
506
- switch (c.type) {
507
- case ConstraintType.Align:
508
- if (c._itemIds === items.map(d => d.classId).sort().join("_"))
509
- cstrs.push(c);
510
- break;
511
- case ConstraintType.Affix:
512
- break;
513
- default:
514
- break;
515
- }
516
- }
517
- return cstrs;
518
- }
519
-
520
- // alignInCell(item, direction) {
521
- // //TODO replace grid.vertCellAlignment and grid.horzCellAlignment
522
- // }
523
-
524
- affix(item, baseItem, channel, param) {
525
- let args = param ? param : {},
526
- offset = "offset" in args ? args.offset : 0,
527
- itemAnchor = "itemAnchor" in args ? args.itemAnchor : (channel == "x" || channel == "angle") ? "center" : "middle",
528
- baseAnchor = "baseAnchor" in args ? args.baseAnchor : (channel == "x" || channel == "angle") ? "center" : "middle";
529
- let c = new AffixConstraint(item, baseItem, this, channel, itemAnchor, baseAnchor, offset);
530
- if (c.id in this.constraints) {
531
- //TODO: throw warning the constraint has been added, return false;
532
- }
533
- this.constraints[c.id] = c;
534
- c.apply();
535
- }
536
-
537
- //arguments include a channel (x, y, width, height for now)
538
- //optional arguments include orientation, x-coordinate, y-coordinate, tickFormat, strokeColor,
539
- axis(channel, field, params) {
540
- //need to figure out if item has the corresponding encoding, or if item position is determined by layout
541
- let args = params ? params : {}, enc = args.item ? this.getEncodingByItem(args.item, channel) : this.getEncodingByField(field, channel);
542
- if (enc && enc.field === field) {
543
- if (enc.datatable.getFieldType(field) === DataType.Date && !("labelFormat" in args)) {
544
- args.labelFormat = "%m/%d/%y";
545
- }
546
- if (enc.channel === "width") {
547
- let existingChannels = this.children.filter(d => d.type === ItemType.Axis).map(d => d.channel);
548
- if (!("orientation" in args))
549
- args.orientation = existingChannels.indexOf("x") >= 0 ? "top" : "bottom";
550
- } else if (enc.channel === "height") {
551
- let existingChannels = this.children.filter(d => d.type === ItemType.Axis).map(d => d.channel);
552
- if (!("orientation" in args))
553
- args.orientation = existingChannels.indexOf("y") >= 0 ? "right" : "left";
554
- }
555
- let axis = new EncodingAxis(enc, args.item ? args.item : enc.anyItem, args);
556
- if ("tickValues" in args) {
557
- axis.tickValues = args["tickValues"];
558
- axis.labelValues = args["tickValues"];
559
- } else {
560
- axis.tickValues = enc._inferTickValues();
561
- axis.labelValues = enc._inferTickValues();
562
- }
563
- //TODO: need to remove axis when encoding changes or axis is removed
564
- enc._axes.push(axis);
565
-
566
- this.addChildAt(axis, 0);
567
- this._itemMap[axis.id] = axis;
568
- this._updateBounds();
569
- return axis;
570
- }
571
-
572
- //TODO: find out item from the field
573
- let item = args.item ? args.item : findItems(this, [{ "field": field }])[0];
574
- if (item === undefined) {
575
- console.warn(Warnings.INCORRECT_AXIS_INFO + field);
576
- return;
577
- }
578
- let layout = getClosestLayout(item);
579
- if (!layout || (layout.type !== LayoutType.Grid && layout.type !== LayoutType.Stack)) return;
580
-
581
- if (layout && (channel == "x" || channel == "y")) {
582
- let group = layout.group,
583
- groups = getPeers(group, this);
584
- let axis, classId;
585
- //TODO: think about how to specify if mutliple axes need to be created properly
586
- // if (args.item)
587
- // groups = [args.item.parent];
588
- for (let c of groups) {
589
- let itm = findItems(c, [{ "field": field }])[0];
590
- let items = getPeers(itm, c);
591
- if (itm.dataScope.dataTable.getFieldType(field) === DataType.Date && !("labelFormat" in args)) {
592
- args.labelFormat = "%m/%d/%y";
593
- }
594
- axis = new LayoutAxis(items, c.layout, channel, field, args);
595
- if (classId == undefined)
596
- classId = axis.id;
597
- axis.classId = classId;
598
- this.addChildAt(axis, 0);
599
- this._itemMap[axis.id] = axis;
600
- // break;
601
- }
602
- this._updateBounds();
603
- return axis;
604
- } else {
605
- console.warn(Warnings.INCORRECT_AXIS_INFO + field);
606
- }
607
- }
608
-
609
- getRelatedAxes(item) {
610
- let axes = [];
611
- if (isGuide(item))
612
- return axes;
613
- for (let c of this.children) {
614
- if (c.type !== ItemType.Axis) continue;
615
- if (c.matches(item)) {
616
- axes.push(c);
617
- continue;
618
- }
619
- //handle layout axis for small multiples
620
- let p = c._item, found = false;
621
- while (p.children && p.children.length > 0) {
622
- for (let ic of p.children) {
623
- if (ic.classId === getEncodingKey(item).split("_")[0]) {
624
- found = true;
625
- axes.push(c);
626
- break;
627
- }
628
- }
629
- if (found) break;
630
- else p = p.children[0];
631
- }
632
-
633
- //handle axis if the updated item is a group/collection
634
- let allChildren = getAllChildren(item);
635
- let map = {};
636
- for (let i of allChildren) {
637
- if (i.classId in map) continue;
638
- map[i.classId] = i;
639
- }
640
- let toCheck = Object.values(map);
641
- for (let i of toCheck) {
642
- if (c.matches(i)) {
643
- axes.push(c);
644
- break;
645
- }
646
- }
647
- // while (p.children && p.children.length > 0) {
648
- // for (let ic of p.children) {
649
- // if (c.matches(ic)) {
650
- // found = true;
651
- // axes.push(c);
652
- // break;
653
- // }
654
- // }
655
- // if (found) break;
656
- // else p = p.children[0];
657
- // }
658
- }
659
- return axes;
660
- }
661
-
662
- removeItem(itm) {
663
- if (!isGuide(itm)) {
664
- let encodings = this.getRelatedEncodings(itm);
665
- for (let enc of encodings) {
666
- this.removeEncoding(enc);
667
- }
668
- //TODO: remove relevant graphical constraints
669
- let axes = this.getRelatedAxes(itm);
670
- for (let a of axes)
671
- this.removeItem(a);
672
- for (let g of this.getRelatedGridlines(itm))
673
- this.removeItem(g);
674
- }
675
- delete this._itemMap[itm.id];
676
- this.removeChild(itm);
677
- this._updateBounds();
678
- }
679
-
680
- //this is used to handle item deletion, assuming that item's parent is scene
681
- getRelatedEncodings(item) {
682
- let encodingKeys = [];
683
- let itm = item;
684
- while (itm) {
685
- encodingKeys.push(getEncodingKey(itm));
686
- if (itm.type == ItemType.Collection) {
687
- itm = itm.firstChild;
688
- } else if (itm.type == ItemType.Glyph) {
689
- for (let c of itm.children) {
690
- encodingKeys.push(getEncodingKey(c));
691
- }
692
- itm = undefined;
693
- } else {
694
- itm = undefined;
695
- }
696
- }
697
- let keys = Object.keys(this._encodings), encodings = [];
698
- for (let k of keys) {
699
- let itemKey = k.split("_")[0];
700
- if (encodingKeys.indexOf(itemKey) >= 0) {
701
- for (let channel in this._encodings[k])
702
- encodings.push(this._encodings[k][channel]);
703
- }
704
- }
705
- return encodings;
706
- }
707
-
708
- removeAllEncodings() {
709
- this._encodings = {};
710
- this.removeAllItemsByType(ItemType.Axis);
711
- this.removeAllItemsByType(ItemType.Legend);
712
- this.removeAllItemsByType(ItemType.Gridlines);
713
- }
714
-
715
- removeEncoding(enc) {
716
- let key = getEncodingKey(enc.anyItem);
717
- delete this._encodings[key][enc.channel];
718
- if (Object.keys(this._encodings[key]).length === 0)
719
- delete this._encodings[key];
720
- let toRemove = [];
721
- for (let c of this.children) {
722
- if (isGuide(c) && c.encoding && c.encoding === enc) {
723
- toRemove.push(c);
724
- }
725
- }
726
- for (let a of toRemove) {
727
- this.removeItem(a);
728
- }
729
- this._updateBounds();
730
- }
731
-
732
- removeAllItemsByType(type) {
733
- let toRemove = [];
734
- for (let a of this.children) {
735
- if (a.type === type) {
736
- toRemove.push(a);
737
- }
738
- }
739
- for (let i of toRemove)
740
- this.removeItem(i);
741
- this._updateBounds();
742
- }
743
-
744
- reCreateRelatedAxes(item) {
745
- let axes = this.getRelatedAxes(item);
746
- let layoutAxisClassIds = [];
747
- axes.forEach(a => {
748
- let args = a.toJSON().args;
749
- if (args.item)
750
- args.item = this.getItem(args.item);
751
- delete args["tickValues"];
752
- delete args["labelValues"];
753
- this.removeItem(a);
754
- if (a instanceof LayoutAxis) {
755
- if (layoutAxisClassIds.indexOf(a.classId) < 0) {
756
- this.axis(a.channel, a.field, args);
757
- layoutAxisClassIds.push(a.classId);
758
- }
759
- } else {
760
- this.axis(a.channel, a.field, args);
761
- }
762
- //toCreate.push({channel: a.channel, field: a.field, args: a.args});
763
- });
764
- this._updateBounds();
765
- }
766
-
767
- reCreateRelatedLegends(item) {
768
- let lgds = this.getRelatedLegends(item);
769
- lgds.forEach(a => {
770
- let args = a.toJSON().args;
771
- if (args.item)
772
- args.item = this.getItem(args.item);
773
- this.removeItem(a);
774
- this.legend(a.channel, a.field, args);
775
- });
776
- this._updateBounds();
777
- }
778
-
779
- legend(channel, field, param) {
780
- let args = param ? param : {};
781
- let enc = this.getEncodingByField(field, channel);
782
- if (!enc)
783
- throw Errors.INCORRECT_LEGEND_INFO + field;
784
-
785
- if (!("x" in args))
786
- args["x"] = 100;
787
- if (!("y" in args))
788
- args["y"] = 100;
789
- let legend = new Legend(enc, args);
790
- this.addChild(legend);
791
- this._itemMap[legend.id] = legend;
792
- this._updateBounds();
793
- return legend;
794
- }
795
-
796
- gridlines(channel, field, params) {
797
- let enc = this.getEncodingByField(field, channel), args = params ? params : {};
798
- if (!enc) return false;
799
- let gl = new Gridlines(enc, args.item ? args.item : enc.anyItem, args);
800
-
801
- if ("values" in args) {
802
- gl.values = args["values"];
803
- } else {
804
- gl.values = enc._inferTickValues();
805
- }
806
-
807
- this.addChildAt(gl, 0);
808
- this._itemMap[gl.id] = gl;
809
- this._updateBounds();
810
- return gl;
811
- }
812
-
813
- getRelatedLegends(item) {
814
- let lg = [];
815
- if (isGuide(item)) return lg;
816
- for (let c of this.children) {
817
- if (c.type !== ItemType.Legend) continue;
818
- if (c.matches(item)) {
819
- lg.push(c);
820
- continue;
821
- }
822
- }
823
- return lg;
824
- }
825
-
826
- getRelatedGridlines(item) {
827
- let gl = [];
828
- if (isGuide(item))
829
- return gl;
830
- for (let c of this.children) {
831
- if (c.type !== ItemType.Gridlines) continue;
832
- if (c.matches(item)) {
833
- gl.push(c);
834
- continue;
835
- }
836
- //handle layout axis for small multiples
837
- let p = c._item, found = false;
838
- while (p.children && p.children.length > 0) {
839
- for (let ic of p.children) {
840
- if (ic.classId === item.classId) {
841
- found = true;
842
- gl.push(c);
843
- break;
844
- }
845
- }
846
- if (found) break;
847
- else p = p.children[0];
848
- }
849
-
850
- //handle axis if the updated item is a group/collection
851
- let allChildren = getAllChildren(item);
852
- let map = {};
853
- for (let i of allChildren) {
854
- if (i.classId in map) continue;
855
- map[i.classId] = i;
856
- }
857
- let toCheck = Object.values(map);
858
- for (let i of toCheck) {
859
- if (c.matches(i)) {
860
- gl.push(c);
861
- break;
862
- }
863
- }
864
- // p = item, found = false;
865
- // while (p.children && p.children.length > 0) {
866
- // for (let ic of p.children) {
867
- // if (c.matches(ic)) {
868
- // found = true;
869
- // gl.push(c);
870
- // break;
871
- // }
872
- // }
873
- // if (found) break;
874
- // else p = p.children[0];
875
- // }
876
- }
877
- return gl;
878
- }
879
-
880
- propagate(item, method, ...args) {
881
- let peers = getPeers(item, this);
882
- for (let p of peers)
883
- p[method](...args);
884
- }
885
-
886
- getEncodingByItem(item, channel) {
887
- let enc = this._encodings[getEncodingKey(item)];
888
- if (enc && enc[channel]) {
889
- return enc[channel];
890
- } else
891
- return null;
892
- }
893
-
894
- getEncodingByField(field, channel) {
895
- for (let itmKey in this._encodings) {
896
- let enc = this._encodings[itmKey];
897
- if (enc[channel] && enc[channel].field == field)
898
- return enc[channel];
899
- }
900
- return null;
901
- }
902
-
903
- //item can be a mark, a group, a vertex or a segment
904
- positionBound(item, channel) {
905
- let enc = this.getEncodingByItem(item, channel);
906
- if (enc)
907
- return enc;
908
- else if (isPath(item)) {
909
- for (let key in this._encodings) {
910
- let classId = key.split("_")[0];
911
- if (classId === item.classId && channel in this._encodings[key])
912
- return this._encodings[key][channel];
913
- }
914
- }
915
- else
916
- return null;
917
- }
918
-
919
- sizeBound(mark, channel) {
920
- let enc = this.getEncodingByItem(mark, channel);
921
- if (enc)
922
- return enc;
923
- if (isPath(mark)) {
924
- let dep = channel === "width" ? ["area"] : channel === "height" ? ["area"] : channel === "radius" ? ["area"] : ["width", "height"],
925
- dep2 = channel === "width" ? ["x"] : channel === "height" ? ["y"] : ["x", "y"];
926
- for (let key in this._encodings) {
927
- let classId = key.split("_")[0];
928
- if (key.indexOf("_") < 0) {
929
- for (let c of dep) {
930
- if (classId === mark.classId && c in this._encodings[key])
931
- return this._encodings[key][c];
932
- }
933
- } else {
934
- for (let c of dep2) {
935
- if (classId === mark.classId && c in this._encodings[key])
936
- return this._encodings[key][c];
937
- }
938
- }
939
- }
940
- }
941
- return null;
942
- }
943
-
944
- setProperties(item, args) {
945
- let result = {}, peers;
946
- for (let p in args)
947
- result[p] = true;
948
-
949
- if (Object.values(LayoutType).indexOf(item.type) > -1 && item.group) {
950
- peers = getPeers(item.group, this);
951
- for (let coll of peers) {
952
- for (let p in args) {
953
- coll.layout[p] = args[p];
954
- }
955
- }
956
- } else {
957
- peers = getPeers(item, this);
958
- if (item.type === "vertex") {
959
- //TODO: validate the property names in args
960
- for (let vertex of peers) {
961
- for (let p in args) {
962
- vertex[p] = args[p];
963
- }
964
- }
965
- } else if (item instanceof Mark) {
966
- for (let p in args) {
967
- //TODO: validate p is a legit property, check if p is bound by data
968
- if ((p === "x" || p === "y") && this.positionBound(item, p)) {
969
- result[p] = false;
970
- continue;
971
- }
972
- if ((p === "width" || p === "height" || p === "radius") && this.sizeBound(item, p)) {
973
- //result[p] = false;
974
- let enc = this.getEncodingByItem(item, p);
975
- if (!enc && p == "radius") enc = this.getEncodingByItem(item, "area");
976
- let re = enc.scale.rangeExtent * args[p] / item[p];
977
- enc.scale.rangeExtent = re;
978
- continue;
979
- }
980
- if ((item.type === ItemType.Rect || item.type === ItemType.Line) && (p === "width" || p === "height")) {
981
- if (p === "width")
982
- peers.forEach(d => d.resize(args[p], d.bounds.height, args["xRef"]));
983
- else
984
- peers.forEach(d => d.resize(d.bounds.width, args[p], undefined, args["yRef"]));
985
- } else if (item.type == ItemType.Circle && p == "radius") {
986
- peers.forEach(d => d.resize(args[p] * 2, args[p] * 2, args["xRef"], args["yRef"]));
987
- } else {
988
- peers.forEach(d => d[p] = args[p]);
989
- }
990
- }
991
-
992
- } else if (item.type == "collection" || item.type == "group") {
993
- for (let c of peers) {
994
- for (let p in args) {
995
- c[p] = (p === "layout" && args[p] !== undefined) ? args[p].clone() : args[p];
996
- }
997
- //c._updateBounds();
998
- }
999
- }
1000
- }
1001
-
1002
- //invoke SceneValidator accordingly
1003
- let props = Object.keys(result).filter(d => result[d]);
1004
- let sizeProps = ["width", "height", "fontSize", "area", "radius"];
1005
- for (let s of sizeProps) {
1006
- if (props.indexOf(s) >= 0 && isMark(item)) {
1007
- SceneValidator.itemResized(item, peers);
1008
- break;
1009
- }
1010
- }
1011
-
1012
- if (props.indexOf("baseline") >= 0 && item.type === ItemType.Area)
1013
- SceneValidator.areaRebased(item, peers);
1014
-
1015
- let layoutProps = ["layout", "rowGap", "colGap", "numRows", "numCols", "orientation", "vertCellAlignment", "horzCellAlignment", "direction", "childrenOrder"];
1016
- let changed = props.filter(d => layoutProps.indexOf(d) >= 0);
1017
- if (changed.length > 0)
1018
- SceneValidator.layoutChanged(peers[0], peers, changed);
1019
-
1020
- return result;
1021
- //TODO: relayout if needed (typically Layout or setProperty should happen before encoding)
1022
- }
1023
-
1024
- _canTranslate(item) {
1025
- let r = { x: true, y: true };
1026
- if (item.type == ItemType.Axis) {
1027
- if (item.channel === "x" || item.channel === "width")
1028
- r.x = false;
1029
- else if (item.channel === "y" || item.channel === "height")
1030
- r.y = false;
1031
- return r;
1032
- }
1033
- if (item.parent.type === ItemType.Collection && item.parent.layout) {
1034
- r.x = false;
1035
- r.y = false;
1036
- }
1037
- if (this.positionBound(item, "x"))
1038
- r.x = false;
1039
- if (this.positionBound(item, "y"))
1040
- r.y = false;
1041
- //TODO: check constraints, handle vertices and
1042
- return r;
1043
- }
1044
-
1045
- //always check canTranslate before calling this method
1046
- translate(item, dx, dy) {
1047
- let ct = this._canTranslate(item);
1048
- if (!ct.x && !ct.y) return ct;
1049
- const adx = ct.x ? dx : 0, ady = ct.y ? dy : 0;
1050
- item._doTranslate(adx, ady);
1051
- this._updateAncestorBounds(item);
1052
- SceneValidator.itemTranslated(item, adx, ady);
1053
- return ct;
1054
- }
1055
-
1056
- _updateAncestorBounds(cpnt, cpntPeers) {
1057
- let peers = cpntPeers ? cpntPeers : getPeers(cpnt, this);
1058
- let parents = getParents(peers);
1059
-
1060
- while (parents.length > 0) {
1061
- for (let p of parents) {
1062
- if (p.children && p.children.length > 0) {
1063
- p._updateBounds();
1064
- } else if (p.vertices) {
1065
- p._updateBounds();
1066
- }
1067
- }
1068
- parents = getParents(parents);
1069
- }
1070
- }
1071
-
1072
- /**
1073
- ** should only be used in Scene methods
1074
- **/
1075
-
1076
- _reapplyConstraints(item) {
1077
- let itm = item, itms = [item];
1078
- while (itm.children) {
1079
- if (itm.type == ItemType.Collection) {
1080
- itms.push(itm.firstChild);
1081
- } else { //glyph or group
1082
- itms = itms.concat(itm.children);
1083
- }
1084
- itm = itm.firstChild;
1085
- }
1086
-
1087
- itm = item.parent;
1088
- while (itm && itm.type !== ItemType.Scene) {
1089
- itms.push(itm);
1090
- itm = itm.parent;
1091
- }
1092
-
1093
- const classIds = itms.map(d => d.classId);
1094
-
1095
- for (let c in this.constraints) {
1096
- const cstr = this.constraints[c];
1097
- switch (cstr.type) {
1098
- case ConstraintType.Affix:
1099
- if (classIds.indexOf(cstr.item.classId) >= 0 || classIds.indexOf(cstr.baseItem.classId) >= 0)
1100
- cstr.apply();
1101
- break;
1102
- case ConstraintType.Align:
1103
- for (let itm of cstr.items) {
1104
- if (classIds.indexOf(itm.classId) >= 0) {
1105
- cstr.apply();
1106
- break;
1107
- }
1108
- }
1109
- break;
1110
- default:
1111
- break;
1112
- }
1113
- }
1114
- }
1115
-
1116
- _relayoutAncestors(cpnt, cpntPeers) {
1117
- let peers = cpntPeers ? cpntPeers : getPeers(cpnt, this);
1118
- let parents = getParents(peers);
1119
- while (parents.length > 0) {
1120
- for (let p of parents) {
1121
- if (p.layout) {
1122
- p.layout.run();
1123
- }
1124
- if (p.children && p.children.length > 0) {
1125
- p._updateBounds();
1126
- }
1127
- if (p.vertices) {
1128
- p._updateBounds();
1129
- }
1130
- }
1131
- parents = getParents(parents);
1132
- }
1133
- }
1134
-
1135
- _reapplySizeBindings(compnt) {
1136
- let sizeChannels = ["width", "height"];
1137
- for (let classId in this._encodings) {
1138
- if (compnt.classId != classId) continue;
1139
- let encodings = this._encodings[classId];
1140
- //TODO: re-use bindSpec and adjust scale accordingly
1141
- let peers = findItems(this, [{ "classId": classId }]);
1142
- for (let channel of sizeChannels) {
1143
- let encoding = encodings[channel];
1144
- if (!encoding) continue;
1145
- encoding.run();
1146
- }
1147
- this._relayoutAncestors(peers[0], peers);
1148
- }
1149
- }
1150
-
1151
- _registerBinding(enc) {
1152
- let encodings = this._encodings;
1153
- let key = getEncodingKey(enc.anyItem);
1154
- if (!(key in encodings))
1155
- encodings[key] = {};
1156
- encodings[key][enc.channel] = enc;
1157
- return true;
1158
- }
1159
-
1160
- toJSON() {
1161
- let json = super.toJSON();
1162
- if (this.fillColor)
1163
- json.fillColor = this.fillColor;
1164
- let scales = {};
1165
- json.encodings = [];
1166
- json.itemCounter = ItemCounter;
1167
- for (let classId in this._encodings) {
1168
- for (let channel in this._encodings[classId]) {
1169
- let e = this._encodings[classId][channel];
1170
- json.encodings.push(e.toJSON());
1171
- if (e.scale && !(e.scale.id in scales)) {
1172
- scales[e.scale.id] = e.scale.toJSON();
1173
- }
1174
- }
1175
- }
1176
- json.scales = scales;
1177
- json.constraints = {};
1178
- for (let c in this.constraints)
1179
- json.constraints[c] = this.constraints[c].toJSON();
1180
- json.tables = {};
1181
- let tables = this.getDataTables();
1182
- for (let t in tables) {
1183
- json.tables[t] = tables[t].toJSON();
1184
- }
1185
- return json;
1186
- }
1187
-
1188
- //get data tables used in this scene's encodings
1189
- getDataTables() {
1190
- let tables = {};
1191
- for (let classId in this._encodings) {
1192
- for (let channel in this._encodings[classId]) {
1193
- let e = this._encodings[classId][channel];
1194
- if (!(e.datatable.id in tables)) {
1195
- tables[e.datatable.id] = e.datatable;
1196
- }
1197
- }
1198
- }
1199
- for (let c of this.children) {
1200
- if (isGuide(c)) continue;
1201
- if (c.dataScope) {
1202
- tables[c.dataScope.dataTable.id] = c.dataScope.dataTable;
1203
- break;
1204
- } else if (c.children && c.children.length > 0) {
1205
- let itm = c.firstChild;
1206
- while (itm) {
1207
- if (itm.dataScope) {
1208
- tables[itm.dataScope.dataTable.id] = itm.dataScope.dataTable;
1209
- break;
1210
- } else if (itm.children && itm.children.length > 0) {
1211
- itm = itm.firstChild
1212
- } else {
1213
- itm = undefined;
1214
- }
1215
- }
1216
- }
1217
- }
1218
- return tables;
1219
- }
1220
-
1221
- //handles marks, groups, vertices and segments
1222
- getItem(id) {
1223
- let markId = id.split("_")[0];
1224
- if (id.indexOf("_v_") > 0) {
1225
- let idx = parseInt(id.split("_v_")[1]);
1226
- return this._itemMap[markId].vertices.find(d => d._id === idx);
1227
- } else if (id.indexOf("_s_") > 0) {
1228
- let idx = parseInt(id.split("_s_")[1]);
1229
- return this._itemMap[markId].segments.find(d => d._id === idx);
1230
- } else {
1231
- return this._itemMap[id];
1232
- }
1233
- }
1234
-
1235
- addInteraction(obj) {
1236
- // let i = new Interaction(listener, eventType, selDef, targetDef);
1237
- this._interactions.push(obj);
1238
- this._interactionsObj[obj['event']] = obj;
1239
- }
1240
-
1241
- get encodings() {
1242
- let r = [];
1243
- for (let itmKey in this._encodings) {
1244
- let enc = this._encodings[itmKey];
1245
- for (let channel in enc) {
1246
- r.push(enc[channel]);
1247
- }
1248
- }
1249
- return r;
1250
- }
1251
- }