@jbrowse/core 2.0.1 → 2.1.0
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.
- package/BaseFeatureWidget/BaseFeatureDetail.d.ts +6 -0
- package/BaseFeatureWidget/BaseFeatureDetail.js +313 -592
- package/BaseFeatureWidget/SequenceFeatureDetails.js +213 -479
- package/BaseFeatureWidget/index.js +88 -126
- package/BaseFeatureWidget/types.js +1 -4
- package/BaseFeatureWidget/util.js +40 -75
- package/CorePlugin.js +55 -94
- package/Plugin.js +9 -34
- package/PluginLoader.js +153 -422
- package/PluginManager.d.ts +17 -14
- package/PluginManager.js +377 -666
- package/ReExports/Attributes.js +3 -10
- package/ReExports/BaseCard.js +3 -10
- package/ReExports/DataGrid.js +5 -12
- package/ReExports/FeatureDetails.js +3 -10
- package/ReExports/index.js +6 -12
- package/ReExports/list.d.ts +5 -0
- package/ReExports/list.js +271 -7
- package/ReExports/material-ui-colors.js +15 -16
- package/ReExports/modules.d.ts +0 -1
- package/ReExports/modules.js +453 -798
- package/TextSearch/BaseResults.js +51 -123
- package/TextSearch/TextSearchManager.js +66 -144
- package/assemblyManager/assembly.js +280 -555
- package/assemblyManager/assemblyConfigSchema.js +47 -64
- package/assemblyManager/assemblyManager.js +126 -272
- package/assemblyManager/index.js +9 -22
- package/configuration/configurationSchema.js +167 -203
- package/configuration/configurationSlot.js +248 -326
- package/configuration/index.js +19 -35
- package/configuration/util.js +131 -173
- package/data_adapters/BaseAdapter.d.ts +2 -2
- package/data_adapters/BaseAdapter.js +132 -521
- package/data_adapters/CytobandAdapter.js +40 -126
- package/data_adapters/dataAdapterCache.js +77 -158
- package/package.json +4 -5
- package/pluggableElementTypes/AdapterType.js +24 -79
- package/pluggableElementTypes/AddTrackWorkflowType.d.ts +17 -0
- package/pluggableElementTypes/AddTrackWorkflowType.js +20 -0
- package/pluggableElementTypes/ConnectionType.js +22 -65
- package/pluggableElementTypes/DisplayType.js +35 -82
- package/pluggableElementTypes/InternetAccountType.js +23 -64
- package/pluggableElementTypes/PluggableElementBase.js +8 -20
- package/pluggableElementTypes/RpcMethodType.js +85 -427
- package/pluggableElementTypes/TextSearchAdapterType.js +16 -55
- package/pluggableElementTypes/TrackType.js +26 -70
- package/pluggableElementTypes/ViewType.js +21 -63
- package/pluggableElementTypes/WidgetType.js +21 -64
- package/pluggableElementTypes/index.d.ts +4 -3
- package/pluggableElementTypes/index.js +42 -125
- package/pluggableElementTypes/models/BaseConnectionModelFactory.js +28 -43
- package/pluggableElementTypes/models/BaseDisplayModel.js +58 -95
- package/pluggableElementTypes/models/BaseTrackModel.js +139 -199
- package/pluggableElementTypes/models/BaseViewModel.js +24 -40
- package/pluggableElementTypes/models/InternetAccountModel.js +116 -263
- package/pluggableElementTypes/models/baseConnectionConfig.js +14 -25
- package/pluggableElementTypes/models/baseInternetAccountConfig.js +29 -38
- package/pluggableElementTypes/models/baseTrackConfig.js +106 -133
- package/pluggableElementTypes/models/index.js +21 -70
- package/pluggableElementTypes/renderers/BoxRendererType.js +132 -291
- package/pluggableElementTypes/renderers/CircularChordRendererType.js +8 -38
- package/pluggableElementTypes/renderers/ComparativeServerSideRendererType.js +60 -192
- package/pluggableElementTypes/renderers/FeatureRendererType.d.ts +0 -2
- package/pluggableElementTypes/renderers/FeatureRendererType.js +89 -264
- package/pluggableElementTypes/renderers/RendererType.js +31 -105
- package/pluggableElementTypes/renderers/ServerSideRenderedContent.js +61 -72
- package/pluggableElementTypes/renderers/ServerSideRendererType.js +112 -265
- package/pluggableElementTypes/renderers/index.js +19 -62
- package/pluggableElementTypes/renderers/util/serializableFilterChain.js +27 -65
- package/rpc/BaseRpcDriver.js +169 -405
- package/rpc/MainThreadRpcDriver.js +27 -150
- package/rpc/RpcManager.js +58 -159
- package/rpc/WebWorkerRpcDriver.js +54 -171
- package/rpc/configSchema.js +25 -49
- package/rpc/coreRpcMethods.js +221 -959
- package/rpc/remoteAbortSignals.js +46 -70
- package/tsconfig.build.tsbuildinfo +1 -1
- package/ui/AboutDialog.js +106 -162
- package/ui/App.js +157 -242
- package/ui/AssemblySelector.js +59 -120
- package/ui/CascadingMenu.js +101 -196
- package/ui/ColorPicker.d.ts +16 -0
- package/ui/ColorPicker.js +97 -0
- package/ui/Drawer.js +28 -61
- package/ui/DrawerWidget.js +108 -202
- package/ui/DropDownMenu.js +60 -91
- package/ui/EditableTypography.js +87 -149
- package/ui/ErrorMessage.js +41 -56
- package/ui/FactoryResetDialog.js +24 -57
- package/ui/FatalErrorDialog.js +59 -91
- package/ui/FileSelector/FileSelector.js +123 -189
- package/ui/FileSelector/LocalFileChooser.js +44 -75
- package/ui/FileSelector/UrlChooser.js +17 -38
- package/ui/FileSelector/index.js +6 -12
- package/ui/Icons.js +45 -69
- package/ui/Logo.js +57 -110
- package/ui/Menu.js +232 -354
- package/ui/PrerenderedCanvas.js +63 -87
- package/ui/ResizeHandle.js +87 -116
- package/ui/ReturnToImportFormDialog.js +32 -63
- package/ui/SanitizedHTML.js +64 -47
- package/ui/Snackbar.js +74 -101
- package/ui/SnackbarModel.js +37 -51
- package/ui/Tooltip.js +49 -76
- package/ui/ViewContainer.js +113 -196
- package/ui/colors.d.ts +10 -0
- package/ui/colors.js +78 -0
- package/ui/index.js +51 -181
- package/ui/react-colorful.d.ts +17 -0
- package/ui/react-colorful.js +455 -0
- package/ui/theme.js +199 -247
- package/util/Base1DUtils.js +163 -202
- package/util/Base1DViewModel.js +121 -168
- package/util/QuickLRU.js +84 -332
- package/util/TimeTraveller.d.ts +19 -0
- package/util/TimeTraveller.js +86 -0
- package/util/aborting.js +49 -127
- package/util/analytics.js +91 -154
- package/util/blockTypes.js +106 -240
- package/util/calculateDynamicBlocks.js +98 -128
- package/util/calculateStaticBlocks.js +105 -125
- package/util/color/cssColorsLevel4.js +156 -160
- package/util/color/index.js +33 -55
- package/util/compositeMap.js +49 -333
- package/util/formatFastaStrings.js +9 -14
- package/util/idMaker.js +18 -31
- package/util/index.d.ts +7 -20
- package/util/index.js +742 -1188
- package/util/io/RemoteFileWithRangeCache.js +88 -257
- package/util/io/index.js +95 -169
- package/util/jexl.js +60 -115
- package/util/jexlStrings.js +24 -29
- package/util/layouts/BaseLayout.js +1 -4
- package/util/layouts/GranularRectLayout.js +388 -555
- package/util/layouts/MultiLayout.js +41 -109
- package/util/layouts/PrecomputedLayout.js +56 -112
- package/util/layouts/PrecomputedMultiLayout.js +22 -59
- package/util/layouts/SceneGraph.js +127 -197
- package/util/layouts/index.js +29 -66
- package/util/mst-reflection.js +55 -71
- package/util/offscreenCanvasPonyfill.js +66 -134
- package/util/offscreenCanvasUtils.d.ts +2 -7
- package/util/offscreenCanvasUtils.js +49 -146
- package/util/range.js +29 -40
- package/util/rxjs.js +20 -27
- package/util/simpleFeature.js +88 -152
- package/util/stats.js +91 -151
- package/util/tracks.js +130 -173
- package/util/types/index.js +110 -179
- package/util/types/mst.js +91 -146
- package/util/types/util.js +1 -4
- package/util/when.js +54 -101
- package/BaseFeatureWidget/SequenceFeatureDetails.test.js +0 -122
- package/BaseFeatureWidget/index.test.js +0 -69
- package/TextSearch/BaseResults.test.js +0 -42
- package/configuration/configurationSchema.test.js +0 -266
- package/configuration/configurationSlot.test.js +0 -69
- package/configuration/util.test.js +0 -39
- package/data_adapters/BaseAdapter.test.js +0 -200
- package/declare.d.js +0 -1
- package/pluggableElementTypes/RpcMethodType.test.js +0 -118
- package/pluggableElementTypes/renderers/declare.d.js +0 -1
- package/pluggableElementTypes/renderers/util/serializableFilterChain.test.js +0 -20
- package/rpc/BaseRpcDriver.test.js +0 -540
- package/rpc/declaration.d.js +0 -1
- package/ui/FatalErrorDialog.test.js +0 -82
- package/ui/SanitizedHTML.test.js +0 -36
- package/ui/theme.test.js +0 -92
- package/util/Base1DViewModel.test.js +0 -130
- package/util/calculateDynamicBlocks.test.js +0 -74
- package/util/calculateStaticBlocks.test.js +0 -297
- package/util/declare.d.js +0 -1
- package/util/formatFastaStrings.test.js +0 -40
- package/util/index.test.js +0 -213
- package/util/jexlStrings.test.js +0 -48
- package/util/layouts/GranularRectLayout.test.js +0 -99
- package/util/range.test.js +0 -64
- package/util/simpleFeature.test.js +0 -34
- package/util/stats.test.js +0 -172
|
@@ -1,26 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
-
|
|
5
|
-
Object.defineProperty(exports, "__esModule", {
|
|
6
|
-
value: true
|
|
7
|
-
});
|
|
8
|
-
exports.default = void 0;
|
|
9
|
-
|
|
10
|
-
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
11
|
-
|
|
12
|
-
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
13
|
-
|
|
14
|
-
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
|
|
15
|
-
|
|
16
|
-
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
17
|
-
|
|
18
|
-
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
19
|
-
|
|
20
|
-
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
21
|
-
|
|
22
|
-
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
23
|
-
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
3
|
/**
|
|
25
4
|
* Rectangle-layout manager that lays out rectangles using bitmaps at
|
|
26
5
|
* resolution that, for efficiency, may be somewhat lower than that of
|
|
@@ -29,573 +8,427 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
|
|
|
29
8
|
* bitmap resolution.
|
|
30
9
|
*/
|
|
31
10
|
// minimum excess size of the array at which we garbage collect
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
11
|
+
const minSizeToBotherWith = 10000;
|
|
12
|
+
const maxFeaturePitchWidth = 20000;
|
|
35
13
|
function segmentsIntersect(x1, x2, y1, y2) {
|
|
36
|
-
|
|
14
|
+
return x2 >= y1 && y2 >= x1;
|
|
37
15
|
}
|
|
38
|
-
|
|
39
16
|
// a single row in the layout
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
// (modified by pitchX, but we don't know that in this class)
|
|
50
|
-
// this.rowState.bits is the array of items in the layout row, indexed by (x - this.offset)
|
|
51
|
-
// this.rowState.min is the leftmost edge of all the rectangles we have in the layout
|
|
52
|
-
// this.rowState.max is the rightmost edge of all the rectangles we have in the layout
|
|
53
|
-
} // log(msg: string): void {
|
|
54
|
-
// // if (this.rowNumber === 0)
|
|
55
|
-
// // eslint-disable-next-line no-console
|
|
56
|
-
// console.log(`r${this.rowNumber}: ${msg}`)
|
|
57
|
-
// }
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
(0, _createClass2.default)(LayoutRow, [{
|
|
61
|
-
key: "setAllFilled",
|
|
62
|
-
value: function setAllFilled(data) {
|
|
63
|
-
this.allFilled = data;
|
|
17
|
+
class LayoutRow {
|
|
18
|
+
constructor() {
|
|
19
|
+
this.padding = 1;
|
|
20
|
+
this.widthLimit = 1000000;
|
|
21
|
+
// this.rowState.offset is the offset of the bits array relative to the genomic coordinates
|
|
22
|
+
// (modified by pitchX, but we don't know that in this class)
|
|
23
|
+
// this.rowState.bits is the array of items in the layout row, indexed by (x - this.offset)
|
|
24
|
+
// this.rowState.min is the leftmost edge of all the rectangles we have in the layout
|
|
25
|
+
// this.rowState.max is the rightmost edge of all the rectangles we have in the layout
|
|
64
26
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (!this.rowState) {
|
|
73
|
-
return undefined;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (this.rowState.min === undefined) {
|
|
77
|
-
return undefined;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (x < this.rowState.min) {
|
|
81
|
-
return undefined;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (x >= this.rowState.max) {
|
|
85
|
-
return undefined;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
var offset = x - this.rowState.offset; // if (offset < 0)
|
|
89
|
-
// debugger
|
|
90
|
-
// if (offset >= this.rowState.bits.length)
|
|
91
|
-
// debugger
|
|
92
|
-
|
|
93
|
-
return this.rowState.bits[offset];
|
|
27
|
+
// log(msg: string): void {
|
|
28
|
+
// // if (this.rowNumber === 0)
|
|
29
|
+
// // eslint-disable-next-line no-console
|
|
30
|
+
// console.log(`r${this.rowNumber}: ${msg}`)
|
|
31
|
+
// }
|
|
32
|
+
setAllFilled(data) {
|
|
33
|
+
this.allFilled = data;
|
|
94
34
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
35
|
+
getItemAt(x) {
|
|
36
|
+
if (this.allFilled) {
|
|
37
|
+
return this.allFilled;
|
|
38
|
+
}
|
|
39
|
+
if (!this.rowState) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
if (this.rowState.min === undefined) {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
if (x < this.rowState.min) {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
if (x >= this.rowState.max) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
const offset = x - this.rowState.offset;
|
|
52
|
+
// if (offset < 0)
|
|
53
|
+
// debugger
|
|
54
|
+
// if (offset >= this.rowState.bits.length)
|
|
55
|
+
// debugger
|
|
56
|
+
return this.rowState.bits[offset];
|
|
57
|
+
}
|
|
58
|
+
isRangeClear(left, right) {
|
|
59
|
+
if (this.allFilled) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
if (!this.rowState) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
const { min, max } = this.rowState;
|
|
66
|
+
if (right <= min || left >= max) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
// TODO: check right and middle before looping
|
|
70
|
+
const maxX = Math.min(max, right);
|
|
71
|
+
let x = Math.max(min, left);
|
|
72
|
+
for (; x < right && x < maxX; x += 1) {
|
|
73
|
+
if (this.getItemAt(x)) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
111
77
|
return true;
|
|
112
|
-
} // TODO: check right and middle before looping
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
var maxX = Math.min(max, right);
|
|
116
|
-
var x = Math.max(min, left);
|
|
117
|
-
|
|
118
|
-
for (; x < right && x < maxX; x += 1) {
|
|
119
|
-
if (this.getItemAt(x)) {
|
|
120
|
-
return false;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return true;
|
|
125
78
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}; // this.log(`initialize ${this.rowState.min} - ${this.rowState.max} (${this.rowState.bits.length})`)
|
|
79
|
+
initialize(left, right) {
|
|
80
|
+
// NOTE: this.rowState.min, this.rowState.max, and this.rowState.offset are interbase coordinates
|
|
81
|
+
const rectWidth = right - left;
|
|
82
|
+
return {
|
|
83
|
+
offset: left - rectWidth,
|
|
84
|
+
min: left,
|
|
85
|
+
max: right,
|
|
86
|
+
bits: new Array(3 * rectWidth),
|
|
87
|
+
};
|
|
88
|
+
// this.log(`initialize ${this.rowState.min} - ${this.rowState.max} (${this.rowState.bits.length})`)
|
|
137
89
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
this.rowState.bits[x] = data;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
if (left < this.rowState.min) {
|
|
191
|
-
this.rowState.min = left;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (right > this.rowState.max) {
|
|
195
|
-
this.rowState.max = right;
|
|
196
|
-
}
|
|
90
|
+
addRect(rect, data) {
|
|
91
|
+
const left = rect.l;
|
|
92
|
+
const right = rect.r + this.padding; // only padding on the right
|
|
93
|
+
if (!this.rowState) {
|
|
94
|
+
this.rowState = this.initialize(left, right);
|
|
95
|
+
}
|
|
96
|
+
// or check if we need to expand to the left and/or to the right
|
|
97
|
+
let oLeft = left - this.rowState.offset;
|
|
98
|
+
let oRight = right - this.rowState.offset;
|
|
99
|
+
const currLength = this.rowState.bits.length;
|
|
100
|
+
// expand rightward if necessary
|
|
101
|
+
if (oRight >= this.rowState.bits.length) {
|
|
102
|
+
const additionalLength = oRight + 1;
|
|
103
|
+
if (this.rowState.bits.length + additionalLength > this.widthLimit) {
|
|
104
|
+
console.warn('Layout width limit exceeded, discarding old layout. Please be more careful about discarding unused blocks.');
|
|
105
|
+
this.rowState = this.initialize(left, right);
|
|
106
|
+
}
|
|
107
|
+
else if (additionalLength > 0) {
|
|
108
|
+
this.rowState.bits = this.rowState.bits.concat(new Array(additionalLength));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// expand leftward if necessary
|
|
112
|
+
if (left < this.rowState.offset) {
|
|
113
|
+
// use math.min to avoid negative lengths
|
|
114
|
+
const additionalLength = Math.min(currLength - oLeft, this.rowState.offset);
|
|
115
|
+
if (this.rowState.bits.length + additionalLength > this.widthLimit) {
|
|
116
|
+
console.warn('Layout width limit exceeded, discarding old layout. Please be more careful about discarding unused blocks.');
|
|
117
|
+
this.rowState = this.initialize(left, right);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
this.rowState.bits = new Array(additionalLength).concat(this.rowState.bits);
|
|
121
|
+
this.rowState.offset -= additionalLength;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
oRight = right - this.rowState.offset;
|
|
125
|
+
oLeft = left - this.rowState.offset;
|
|
126
|
+
const w = oRight - oLeft;
|
|
127
|
+
if (w > maxFeaturePitchWidth) {
|
|
128
|
+
console.warn(`Layout X pitch set too low, feature spans ${w} bits in a single row.`, rect, data);
|
|
129
|
+
}
|
|
130
|
+
for (let x = oLeft; x < oRight; x += 1) {
|
|
131
|
+
this.rowState.bits[x] = data;
|
|
132
|
+
}
|
|
133
|
+
if (left < this.rowState.min) {
|
|
134
|
+
this.rowState.min = left;
|
|
135
|
+
}
|
|
136
|
+
if (right > this.rowState.max) {
|
|
137
|
+
this.rowState.max = right;
|
|
138
|
+
}
|
|
197
139
|
}
|
|
198
140
|
/**
|
|
199
141
|
* Given a range of interbase coordinates, deletes all data dealing with that range
|
|
200
142
|
*/
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
143
|
+
discardRange(left, right) {
|
|
144
|
+
if (this.allFilled) {
|
|
145
|
+
return;
|
|
146
|
+
} // allFilled is irrevocable currently
|
|
147
|
+
// if we have no data, do nothing
|
|
148
|
+
if (!this.rowState) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
// if doesn't overlap at all, do nothing
|
|
152
|
+
if (right <= this.rowState.min || left >= this.rowState.max) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
// if completely encloses range, discard everything
|
|
156
|
+
if (left <= this.rowState.min && right >= this.rowState.max) {
|
|
157
|
+
this.rowState = undefined;
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
// if overlaps left edge, adjust the min
|
|
161
|
+
if (right > this.rowState.min && left <= this.rowState.min) {
|
|
162
|
+
this.rowState.min = right;
|
|
163
|
+
}
|
|
164
|
+
// if overlaps right edge, adjust the max
|
|
165
|
+
if (left < this.rowState.max && right >= this.rowState.max) {
|
|
166
|
+
this.rowState.max = left;
|
|
167
|
+
}
|
|
168
|
+
// now trim the left, right, or both sides of the array
|
|
169
|
+
if (this.rowState.offset < this.rowState.min - minSizeToBotherWith &&
|
|
170
|
+
this.rowState.bits.length >
|
|
171
|
+
this.rowState.max + minSizeToBotherWith - this.rowState.offset) {
|
|
172
|
+
// trim both sides
|
|
173
|
+
const leftTrimAmount = this.rowState.min - this.rowState.offset;
|
|
174
|
+
const rightTrimAmount = this.rowState.bits.length -
|
|
175
|
+
1 -
|
|
176
|
+
(this.rowState.max - this.rowState.offset);
|
|
177
|
+
// if (rightTrimAmount <= 0) debugger
|
|
178
|
+
// if (leftTrimAmount <= 0) debugger
|
|
179
|
+
// this.log(`trim both sides, ${leftTrimAmount} from left, ${rightTrimAmount} from right`)
|
|
180
|
+
this.rowState.bits = this.rowState.bits.slice(leftTrimAmount, this.rowState.bits.length - rightTrimAmount);
|
|
181
|
+
this.rowState.offset += leftTrimAmount;
|
|
182
|
+
// if (this.rowState.offset > this.rowState.min) debugger
|
|
183
|
+
// if (this.rowState.bits.length <= this.rowState.max - this.rowState.offset) debugger
|
|
184
|
+
}
|
|
185
|
+
else if (this.rowState.offset < this.rowState.min - minSizeToBotherWith) {
|
|
186
|
+
// trim left side
|
|
187
|
+
const desiredOffset = this.rowState.min - Math.floor(minSizeToBotherWith / 2);
|
|
188
|
+
const trimAmount = desiredOffset - this.rowState.offset;
|
|
189
|
+
// this.log(`trim left side by ${trimAmount}`)
|
|
190
|
+
this.rowState.bits.splice(0, trimAmount);
|
|
191
|
+
this.rowState.offset += trimAmount;
|
|
192
|
+
// if (this.rowState.offset > this.rowState.min) debugger
|
|
193
|
+
// if (this.rowState.bits.length <= this.rowState.max - this.rowState.offset) debugger
|
|
194
|
+
}
|
|
195
|
+
else if (this.rowState.bits.length >
|
|
196
|
+
this.rowState.max - this.rowState.offset + minSizeToBotherWith) {
|
|
197
|
+
// trim right side
|
|
198
|
+
const desiredLength = this.rowState.max -
|
|
199
|
+
this.rowState.offset +
|
|
200
|
+
1 +
|
|
201
|
+
Math.floor(minSizeToBotherWith / 2);
|
|
202
|
+
// this.log(`trim right side by ${this.rowState.bits.length-desiredLength}`)
|
|
203
|
+
// if (desiredLength > this.rowState.bits.length) debugger
|
|
204
|
+
this.rowState.bits.length = desiredLength;
|
|
205
|
+
// if (this.rowState.offset > this.rowState.min) debugger
|
|
206
|
+
// if (this.rowState.bits.length <= this.rowState.max - this.rowState.offset) debugger
|
|
207
|
+
}
|
|
208
|
+
// if (this.rowState.offset > this.rowState.min) debugger
|
|
261
209
|
// if (this.rowState.bits.length <= this.rowState.max - this.rowState.offset) debugger
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
var oRight = Math.min(right, this.rowState.max) - this.rowState.offset;
|
|
273
|
-
|
|
274
|
-
for (var x = oLeft; x >= 0 && x < oRight; x += 1) {
|
|
275
|
-
this.rowState.bits[x] = undefined;
|
|
276
|
-
}
|
|
210
|
+
// if range now enclosed in the new bounds, loop through and clear the bits
|
|
211
|
+
const oLeft = Math.max(this.rowState.min, left) - this.rowState.offset;
|
|
212
|
+
// if (oLeft < 0) debugger
|
|
213
|
+
// if (oLeft >= this.rowState.bits.length) debugger
|
|
214
|
+
// if (oRight < 0) debugger
|
|
215
|
+
// if (oRight >= this.rowState.bits.length) debugger
|
|
216
|
+
const oRight = Math.min(right, this.rowState.max) - this.rowState.offset;
|
|
217
|
+
for (let x = oLeft; x >= 0 && x < oRight; x += 1) {
|
|
218
|
+
this.rowState.bits[x] = undefined;
|
|
219
|
+
}
|
|
277
220
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
(0, _classCallCheck2.default)(this, GranularRectLayout);
|
|
303
|
-
(0, _defineProperty2.default)(this, "pitchX", void 0);
|
|
304
|
-
(0, _defineProperty2.default)(this, "pitchY", void 0);
|
|
305
|
-
(0, _defineProperty2.default)(this, "hardRowLimit", void 0);
|
|
306
|
-
(0, _defineProperty2.default)(this, "bitmap", void 0);
|
|
307
|
-
(0, _defineProperty2.default)(this, "rectangles", void 0);
|
|
308
|
-
(0, _defineProperty2.default)(this, "maxHeightReached", void 0);
|
|
309
|
-
(0, _defineProperty2.default)(this, "maxHeight", void 0);
|
|
310
|
-
(0, _defineProperty2.default)(this, "displayMode", void 0);
|
|
311
|
-
(0, _defineProperty2.default)(this, "pTotalHeight", void 0);
|
|
312
|
-
this.pitchX = pitchX;
|
|
313
|
-
this.pitchY = pitchY;
|
|
314
|
-
this.hardRowLimit = hardRowLimit;
|
|
315
|
-
this.maxHeightReached = false;
|
|
316
|
-
this.displayMode = displayMode; // reduce the pitchY to try and pack the features tighter
|
|
317
|
-
|
|
318
|
-
if (this.displayMode === 'compact') {
|
|
319
|
-
this.pitchY = Math.round(this.pitchY / 4) || 1;
|
|
320
|
-
this.pitchX = Math.round(this.pitchX / 4) || 1;
|
|
221
|
+
}
|
|
222
|
+
class GranularRectLayout {
|
|
223
|
+
/*
|
|
224
|
+
*
|
|
225
|
+
* pitchX - layout grid pitch in the X direction
|
|
226
|
+
* pitchY - layout grid pitch in the Y direction
|
|
227
|
+
* maxHeight - maximum layout height, default Infinity (no max)
|
|
228
|
+
*/
|
|
229
|
+
constructor({ pitchX = 10, pitchY = 10, maxHeight = 10000, hardRowLimit = 10000, displayMode = 'normal', } = {}) {
|
|
230
|
+
this.pitchX = pitchX;
|
|
231
|
+
this.pitchY = pitchY;
|
|
232
|
+
this.hardRowLimit = hardRowLimit;
|
|
233
|
+
this.maxHeightReached = false;
|
|
234
|
+
this.displayMode = displayMode;
|
|
235
|
+
// reduce the pitchY to try and pack the features tighter
|
|
236
|
+
if (this.displayMode === 'compact') {
|
|
237
|
+
this.pitchY = Math.round(this.pitchY / 4) || 1;
|
|
238
|
+
this.pitchX = Math.round(this.pitchX / 4) || 1;
|
|
239
|
+
}
|
|
240
|
+
this.bitmap = [];
|
|
241
|
+
this.rectangles = new Map();
|
|
242
|
+
this.maxHeight = Math.ceil(maxHeight / this.pitchY);
|
|
243
|
+
this.pTotalHeight = 0; // total height, in units of bitmap squares (px/pitchY)
|
|
321
244
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
if (top > maxTop) {
|
|
374
|
-
rectangle.top = null;
|
|
375
|
-
this.rectangles.set(id, rectangle);
|
|
376
|
-
this.maxHeightReached = true;
|
|
377
|
-
return null;
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
rectangle.top = top;
|
|
382
|
-
this.addRectToBitmap(rectangle);
|
|
383
|
-
this.rectangles.set(id, rectangle);
|
|
384
|
-
this.pTotalHeight = Math.max(this.pTotalHeight || 0, top + pHeight);
|
|
385
|
-
return top * this.pitchY;
|
|
245
|
+
/**
|
|
246
|
+
* @returns top position for the rect, or Null if laying
|
|
247
|
+
* out the rect would exceed maxHeight
|
|
248
|
+
*/
|
|
249
|
+
addRect(id, left, right, height, data) {
|
|
250
|
+
// if we have already laid it out, return its layout
|
|
251
|
+
const storedRec = this.rectangles.get(id);
|
|
252
|
+
if (storedRec) {
|
|
253
|
+
if (storedRec.top === null) {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
// add it to the bitmap again, since that bitmap range may have been
|
|
257
|
+
// discarded
|
|
258
|
+
this.addRectToBitmap(storedRec);
|
|
259
|
+
return storedRec.top * this.pitchY;
|
|
260
|
+
}
|
|
261
|
+
const pLeft = Math.floor(left / this.pitchX);
|
|
262
|
+
const pRight = Math.floor(right / this.pitchX);
|
|
263
|
+
const pHeight = Math.ceil(height / this.pitchY);
|
|
264
|
+
const rectangle = {
|
|
265
|
+
id,
|
|
266
|
+
l: pLeft,
|
|
267
|
+
r: pRight,
|
|
268
|
+
top: null,
|
|
269
|
+
h: pHeight,
|
|
270
|
+
originalHeight: height,
|
|
271
|
+
data,
|
|
272
|
+
};
|
|
273
|
+
const maxTop = this.maxHeight - pHeight;
|
|
274
|
+
let top = 0;
|
|
275
|
+
if (this.displayMode !== 'collapse') {
|
|
276
|
+
for (; top <= maxTop; top += 1) {
|
|
277
|
+
if (!this.collides(rectangle, top)) {
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (top > maxTop) {
|
|
282
|
+
rectangle.top = null;
|
|
283
|
+
this.rectangles.set(id, rectangle);
|
|
284
|
+
this.maxHeightReached = true;
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
rectangle.top = top;
|
|
289
|
+
this.addRectToBitmap(rectangle);
|
|
290
|
+
this.rectangles.set(id, rectangle);
|
|
291
|
+
this.pTotalHeight = Math.max(this.pTotalHeight || 0, top + pHeight);
|
|
292
|
+
return top * this.pitchY;
|
|
386
293
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
return true;
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
return false;
|
|
294
|
+
collides(rect, top) {
|
|
295
|
+
const { bitmap } = this;
|
|
296
|
+
const maxY = top + rect.h;
|
|
297
|
+
for (let y = top; y < maxY; y += 1) {
|
|
298
|
+
const row = bitmap[y];
|
|
299
|
+
if (row && !row.isRangeClear(rect.l, rect.r)) {
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return false;
|
|
402
304
|
}
|
|
403
305
|
/**
|
|
404
306
|
* make a subarray if it does not exist
|
|
405
307
|
*/
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
row = new LayoutRow();
|
|
418
|
-
bitmap[y] = row;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
return row;
|
|
308
|
+
autovivifyRow(bitmap, y) {
|
|
309
|
+
let row = bitmap[y];
|
|
310
|
+
if (!row) {
|
|
311
|
+
if (y > this.hardRowLimit) {
|
|
312
|
+
throw new Error(`layout hard limit (${this.hardRowLimit * this.pitchY}px) exceeded, aborting layout`);
|
|
313
|
+
}
|
|
314
|
+
row = new LayoutRow();
|
|
315
|
+
bitmap[y] = row;
|
|
316
|
+
}
|
|
317
|
+
return row;
|
|
422
318
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
this.autovivifyRow(this.bitmap, _y).addRect(rect, data);
|
|
445
|
-
}
|
|
446
|
-
}
|
|
319
|
+
addRectToBitmap(rect) {
|
|
320
|
+
if (rect.top === null) {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
const data = rect.id;
|
|
324
|
+
const yEnd = rect.top + rect.h;
|
|
325
|
+
if (rect.r - rect.l > maxFeaturePitchWidth) {
|
|
326
|
+
// the rect is very big in relation to the view size, just pretend, for
|
|
327
|
+
// the purposes of layout, that it extends infinitely. this will cause
|
|
328
|
+
// weird layout if a user scrolls manually for a very, very long time
|
|
329
|
+
// along the genome at the same zoom level. but most users will not do
|
|
330
|
+
// that. hopefully.
|
|
331
|
+
for (let y = rect.top; y < yEnd; y += 1) {
|
|
332
|
+
this.autovivifyRow(this.bitmap, y).setAllFilled(data);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
for (let y = rect.top; y < yEnd; y += 1) {
|
|
337
|
+
this.autovivifyRow(this.bitmap, y).addRect(rect, data);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
447
340
|
}
|
|
448
341
|
/**
|
|
449
342
|
* Given a range of X coordinates, deletes all data dealing with
|
|
450
343
|
* the features.
|
|
451
344
|
*/
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
if (row) {
|
|
465
|
-
row.discardRange(pLeft, pRight);
|
|
466
|
-
}
|
|
467
|
-
}
|
|
345
|
+
discardRange(left, right) {
|
|
346
|
+
// console.log( 'discard', left, right );
|
|
347
|
+
const pLeft = Math.floor(left / this.pitchX);
|
|
348
|
+
const pRight = Math.floor(right / this.pitchX);
|
|
349
|
+
const { bitmap } = this;
|
|
350
|
+
for (let y = 0; y < bitmap.length; y += 1) {
|
|
351
|
+
const row = bitmap[y];
|
|
352
|
+
if (row) {
|
|
353
|
+
row.discardRange(pLeft, pRight);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
468
356
|
}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
value: function hasSeen(id) {
|
|
472
|
-
return this.rectangles.has(id);
|
|
357
|
+
hasSeen(id) {
|
|
358
|
+
return this.rectangles.has(id);
|
|
473
359
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
return
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
var pX = Math.floor(x / this.pitchX);
|
|
485
|
-
return row.getItemAt(pX);
|
|
360
|
+
getByCoord(x, y) {
|
|
361
|
+
const pY = Math.floor(y / this.pitchY);
|
|
362
|
+
const row = this.bitmap[pY];
|
|
363
|
+
if (!row) {
|
|
364
|
+
return undefined;
|
|
365
|
+
}
|
|
366
|
+
const pX = Math.floor(x / this.pitchX);
|
|
367
|
+
return row.getItemAt(pX);
|
|
486
368
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
return [r.l * this.pitchX, t, r.r * this.pitchX, t + r.originalHeight];
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
return undefined;
|
|
369
|
+
getByID(id) {
|
|
370
|
+
const r = this.rectangles.get(id);
|
|
371
|
+
if (r) {
|
|
372
|
+
const t = r.top * this.pitchY;
|
|
373
|
+
return [r.l * this.pitchX, t, r.r * this.pitchX, t + r.originalHeight];
|
|
374
|
+
}
|
|
375
|
+
return undefined;
|
|
498
376
|
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
var _this$rectangles$get;
|
|
503
|
-
|
|
504
|
-
return (_this$rectangles$get = this.rectangles.get(id)) === null || _this$rectangles$get === void 0 ? void 0 : _this$rectangles$get.data;
|
|
377
|
+
getDataByID(id) {
|
|
378
|
+
var _a;
|
|
379
|
+
return (_a = this.rectangles.get(id)) === null || _a === void 0 ? void 0 : _a.data;
|
|
505
380
|
}
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
}, {
|
|
510
|
-
key: "getTotalHeight",
|
|
511
|
-
value: function getTotalHeight() {
|
|
512
|
-
return this.pTotalHeight * this.pitchY;
|
|
381
|
+
cleanup() { }
|
|
382
|
+
getTotalHeight() {
|
|
383
|
+
return this.pTotalHeight * this.pitchY;
|
|
513
384
|
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
get: function get() {
|
|
517
|
-
return this.getTotalHeight();
|
|
385
|
+
get totalHeight() {
|
|
386
|
+
return this.getTotalHeight();
|
|
518
387
|
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
id = _ref3[0],
|
|
527
|
-
rect = _ref3[1];
|
|
528
|
-
|
|
529
|
-
var l = rect.l,
|
|
530
|
-
r = rect.r,
|
|
531
|
-
originalHeight = rect.originalHeight,
|
|
532
|
-
top = rect.top;
|
|
533
|
-
var t = (top || 0) * _this.pitchY;
|
|
534
|
-
var b = t + originalHeight;
|
|
535
|
-
return [id, [l * _this.pitchX, t, r * _this.pitchX, b]]; // left, top, right, bottom
|
|
536
|
-
}));
|
|
388
|
+
getRectangles() {
|
|
389
|
+
return new Map(Array.from(this.rectangles.entries()).map(([id, rect]) => {
|
|
390
|
+
const { l, r, originalHeight, top } = rect;
|
|
391
|
+
const t = (top || 0) * this.pitchY;
|
|
392
|
+
const b = t + originalHeight;
|
|
393
|
+
return [id, [l * this.pitchX, t, r * this.pitchX, b]]; // left, top, right, bottom
|
|
394
|
+
}));
|
|
537
395
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
if (rect.top === null) {
|
|
559
|
-
maxHeightReached = true;
|
|
560
|
-
} else {
|
|
561
|
-
var t = (top || 0) * this.pitchY;
|
|
562
|
-
var b = t + originalHeight;
|
|
563
|
-
var y1 = l * this.pitchX;
|
|
564
|
-
var y2 = r * this.pitchX;
|
|
565
|
-
var x1 = region.start;
|
|
566
|
-
var x2 = region.end; // add +/- pitchX to avoid resolution causing errors
|
|
567
|
-
|
|
568
|
-
if (segmentsIntersect(x1, x2, y1 - this.pitchX, y2 + this.pitchX)) {
|
|
569
|
-
regionRectangles[id] = [y1, t, y2, b];
|
|
396
|
+
serializeRegion(region) {
|
|
397
|
+
const regionRectangles = {};
|
|
398
|
+
let maxHeightReached = false;
|
|
399
|
+
for (const [id, rect] of this.rectangles.entries()) {
|
|
400
|
+
const { l, r, originalHeight, top } = rect;
|
|
401
|
+
if (rect.top === null) {
|
|
402
|
+
maxHeightReached = true;
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
const t = (top || 0) * this.pitchY;
|
|
406
|
+
const b = t + originalHeight;
|
|
407
|
+
const y1 = l * this.pitchX;
|
|
408
|
+
const y2 = r * this.pitchX;
|
|
409
|
+
const x1 = region.start;
|
|
410
|
+
const x2 = region.end;
|
|
411
|
+
// add +/- pitchX to avoid resolution causing errors
|
|
412
|
+
if (segmentsIntersect(x1, x2, y1 - this.pitchX, y2 + this.pitchX)) {
|
|
413
|
+
regionRectangles[id] = [y1, t, y2, b];
|
|
414
|
+
}
|
|
570
415
|
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
return {
|
|
580
|
-
rectangles: regionRectangles,
|
|
581
|
-
containsNoTransferables: true,
|
|
582
|
-
totalHeight: this.getTotalHeight(),
|
|
583
|
-
maxHeightReached: maxHeightReached
|
|
584
|
-
};
|
|
416
|
+
}
|
|
417
|
+
return {
|
|
418
|
+
rectangles: regionRectangles,
|
|
419
|
+
containsNoTransferables: true,
|
|
420
|
+
totalHeight: this.getTotalHeight(),
|
|
421
|
+
maxHeightReached,
|
|
422
|
+
};
|
|
585
423
|
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
maxHeightReached: this.maxHeightReached
|
|
595
|
-
};
|
|
424
|
+
toJSON() {
|
|
425
|
+
const rectangles = Object.fromEntries(this.getRectangles());
|
|
426
|
+
return {
|
|
427
|
+
rectangles,
|
|
428
|
+
containsNoTransferables: true,
|
|
429
|
+
totalHeight: this.getTotalHeight(),
|
|
430
|
+
maxHeightReached: this.maxHeightReached,
|
|
431
|
+
};
|
|
596
432
|
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
}();
|
|
600
|
-
|
|
601
|
-
exports.default = GranularRectLayout;
|
|
433
|
+
}
|
|
434
|
+
exports.default = GranularRectLayout;
|