@datagrok/helm 2.1.33 → 2.2.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/.eslintrc.json +1 -1
- package/CHANGELOG.md +23 -0
- package/dist/package-test.js +1 -1
- package/dist/package-test.js.map +1 -1
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/package.json +6 -6
- package/src/cell-renderer.ts +17 -153
- package/src/helm-helper.ts +9 -10
- package/src/helm-monomer-placer.ts +18 -66
- package/src/helm-web-editor.ts +5 -2
- package/src/package-test.ts +1 -0
- package/src/package-utils.ts +17 -0
- package/src/package.ts +75 -25
- package/src/tests/helm-service-tests.ts +97 -0
- package/src/tests/properties-widget-tests.ts +4 -2
- package/src/tests/renderers-tests.ts +97 -22
- package/src/types/dojo.ts +3 -0
- package/src/utils/dummy-monomer.ts +69 -0
- package/src/utils/get-hovered.ts +115 -0
- package/src/utils/helm-grid-cell-renderer.ts +201 -0
- package/src/utils/helm-service.ts +157 -0
- package/src/utils/index.ts +7 -7
- package/webpack.config.js +7 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/helm",
|
|
3
3
|
"friendlyName": "Helm",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.2.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Oleksandra Serhiienko",
|
|
7
7
|
"email": "oserhiienko@datagrok.ai"
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
"https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js",
|
|
13
13
|
"helm/JSDraw/Scilligence.JSDraw2.Lite.js",
|
|
14
14
|
"helm/JSDraw/Scilligence.JSDraw2.Resources.js",
|
|
15
|
-
"helm/JSDraw/Pistoia.HELM
|
|
15
|
+
"helm/JSDraw/Pistoia.HELM.js"
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@datagrok-libraries/bio": "^5.
|
|
18
|
+
"@datagrok-libraries/bio": "^5.41.0",
|
|
19
19
|
"@datagrok-libraries/chem-meta": "^1.2.5",
|
|
20
|
-
"@datagrok-libraries/utils": "^4.2.
|
|
20
|
+
"@datagrok-libraries/utils": "^4.2.2",
|
|
21
21
|
"cash-dom": "^8.1.1",
|
|
22
22
|
"datagrok-api": "^1.17.0",
|
|
23
23
|
"dayjs": "^1.10.6",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"@typescript-eslint/parser": "^5.11.0",
|
|
38
38
|
"eslint": "^8.18.0",
|
|
39
39
|
"eslint-config-google": "^0.14.0",
|
|
40
|
-
"@datagrok/bio": "^2.12.
|
|
41
|
-
"@datagrok/chem": "^1.9.
|
|
40
|
+
"@datagrok/bio": "^2.12.17",
|
|
41
|
+
"@datagrok/chem": "^1.9.2"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"link-all": "npm link @datagrok-libraries/chem-meta datagrok-api @datagrok-libraries/utils @datagrok-libraries/bio",
|
package/src/cell-renderer.ts
CHANGED
|
@@ -2,14 +2,16 @@ import * as grok from 'datagrok-api/grok';
|
|
|
2
2
|
import * as ui from 'datagrok-api/ui';
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
|
+
import * as JSDraw2 from 'JSDraw2';
|
|
5
6
|
import wu from 'wu';
|
|
6
7
|
|
|
7
8
|
import {printLeftOrCentered} from '@datagrok-libraries/bio/src/utils/cell-renderer';
|
|
8
9
|
import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
|
|
9
10
|
|
|
10
11
|
import {findMonomers, parseHelm, removeGapsFromHelm} from './utils';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
12
|
+
import {HelmMonomerPlacer, ISeqMonomer} from './helm-monomer-placer';
|
|
13
|
+
import {getHoveredMonomerFallback, getHoveredMonomerFromEditorMol} from './utils/get-hovered';
|
|
14
|
+
import {getGridCellRendererBack} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
|
|
13
15
|
|
|
14
16
|
// import {_package} from './package'; // NullError: method not found: '_package' on null
|
|
15
17
|
|
|
@@ -20,147 +22,6 @@ const enum tempTAGS {
|
|
|
20
22
|
helmPlacer = 'bio-helmPlacer',
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
function getSeqMonomerFromHelm(
|
|
24
|
-
helmPrefix: string, symbol: string, monomerLib: IMonomerLib
|
|
25
|
-
): ISeqMonomer {
|
|
26
|
-
let resSeqMonomer: ISeqMonomer | undefined = undefined;
|
|
27
|
-
for (const polymerType of monomerLib.getPolymerTypes()) {
|
|
28
|
-
if (helmPrefix.startsWith(polymerType))
|
|
29
|
-
resSeqMonomer = {symbol: symbol, polymerType: polymerType};
|
|
30
|
-
}
|
|
31
|
-
if (!resSeqMonomer)
|
|
32
|
-
throw new Error(`Monomer not found for symbol = '${symbol}' and helmPrefix = '${helmPrefix}'.`);
|
|
33
|
-
return resSeqMonomer;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function getSeqMonomerFromHelmAtom(atom: IEditorMolAtom): ISeqMonomer {
|
|
37
|
-
let polymerType: string | undefined = undefined;
|
|
38
|
-
// @ts-ignore
|
|
39
|
-
switch (atom.bio.type) {
|
|
40
|
-
case 'HELM_BASE':
|
|
41
|
-
case 'HELM_SUGAR': // r - ribose, d - deoxyribose
|
|
42
|
-
case 'HELM_LINKER': // p - phosphate
|
|
43
|
-
polymerType = 'RNA';
|
|
44
|
-
break;
|
|
45
|
-
case 'HELM_AA':
|
|
46
|
-
polymerType = 'PEPTIDE';
|
|
47
|
-
break;
|
|
48
|
-
default:
|
|
49
|
-
polymerType = 'PEPTIDE';
|
|
50
|
-
}
|
|
51
|
-
return {symbol: atom.elem, polymerType: polymerType};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function getHoveredMonomerFromEditor(
|
|
55
|
-
argsX: number, argsY: number, gridCell: DG.GridCell, editor: IEditor
|
|
56
|
-
): ISeqMonomer | null {
|
|
57
|
-
let hoveredSeqMonomer: ISeqMonomer | null = null;
|
|
58
|
-
|
|
59
|
-
/** @return {[number, number]} [atom, distance] */
|
|
60
|
-
function getNearest(excluded: (number | undefined)[]): [number | undefined, number | undefined] {
|
|
61
|
-
let atom: number | undefined = undefined;
|
|
62
|
-
let distance: number | undefined = undefined;
|
|
63
|
-
for (let atomI = 0; atomI < editor.m.atoms.length; ++atomI) {
|
|
64
|
-
if (!excluded.includes(atomI)) {
|
|
65
|
-
const aX: number = editor.m.atoms[atomI].p.x;
|
|
66
|
-
const aY: number = editor.m.atoms[atomI].p.y;
|
|
67
|
-
const distanceToAtomI: number = Math.sqrt((argsX - aX) ** 2 + (argsY - aY) ** 2);
|
|
68
|
-
if (distance === undefined || distance > distanceToAtomI) {
|
|
69
|
-
atom = atomI;
|
|
70
|
-
distance = distanceToAtomI;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return [atom, distance];
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const [firstAtomI, firstDistance] = getNearest([]);
|
|
78
|
-
const [secondAtomI, secondDistance] = getNearest([firstAtomI]);
|
|
79
|
-
|
|
80
|
-
// for (let atomI = 0; atomI < editor.m.atoms.length; ++atomI) {
|
|
81
|
-
// const aX: number = editor.m.atoms[atomI].p.x;
|
|
82
|
-
// const aY: number = editor.m.atoms[atomI].p.y;
|
|
83
|
-
// const distanceToAtomI: number = Math.sqrt((argsX - aX) ** 2 + (argsY - aY) ** 2);
|
|
84
|
-
// if (firstDistance === undefined || firstDistance > distanceToAtomI) {
|
|
85
|
-
// secondAtomI = firstAtomI;
|
|
86
|
-
// firstAtomI = atomI;
|
|
87
|
-
//
|
|
88
|
-
// secondDistance = firstDistance;
|
|
89
|
-
// firstDistance = distanceToAtomI;
|
|
90
|
-
// }
|
|
91
|
-
// }
|
|
92
|
-
|
|
93
|
-
if (firstAtomI !== undefined && firstDistance !== undefined) {
|
|
94
|
-
const firstAtom = editor.m.atoms[firstAtomI];
|
|
95
|
-
const firstSeqMonomer = getSeqMonomerFromHelmAtom(firstAtom);
|
|
96
|
-
if (secondAtomI !== undefined && secondDistance !== undefined) {
|
|
97
|
-
if (firstDistance < secondDistance * 0.45)
|
|
98
|
-
hoveredSeqMonomer = firstSeqMonomer;
|
|
99
|
-
} else {
|
|
100
|
-
if (firstDistance < 0.35 * gridCell.bounds.height)
|
|
101
|
-
hoveredSeqMonomer = firstSeqMonomer;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return hoveredSeqMonomer;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function getHoveredMonomerFallback(
|
|
108
|
-
argsX: number, _argsY: number, gridCell: DG.GridCell, helmPlacer: HelmMonomerPlacer
|
|
109
|
-
): ISeqMonomer | null {
|
|
110
|
-
let hoveredSeqMonomer: ISeqMonomer | null = null;
|
|
111
|
-
const [allParts, lengths, sumLengths] = helmPlacer.getCellAllPartsLengths(gridCell.tableRowIndex!);
|
|
112
|
-
const maxIndex = Object.values(lengths).length - 1;
|
|
113
|
-
let left = 0;
|
|
114
|
-
let right = maxIndex;
|
|
115
|
-
let found = false;
|
|
116
|
-
let iterCount: number = 0;
|
|
117
|
-
|
|
118
|
-
let mid = 0;
|
|
119
|
-
if (argsX > sumLengths[0]) {
|
|
120
|
-
while (!found && iterCount < sumLengths.length) {
|
|
121
|
-
mid = Math.floor((right + left) / 2);
|
|
122
|
-
if (argsX >= sumLengths[mid] && argsX <= sumLengths[mid + 1]) {
|
|
123
|
-
left = mid;
|
|
124
|
-
found = true;
|
|
125
|
-
} else if (argsX < sumLengths[mid])
|
|
126
|
-
right = mid - 1;
|
|
127
|
-
else if (argsX > sumLengths[mid + 1])
|
|
128
|
-
left = mid + 1;
|
|
129
|
-
|
|
130
|
-
if (left == right)
|
|
131
|
-
found = true;
|
|
132
|
-
|
|
133
|
-
iterCount++;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
left = (argsX >= sumLengths[left]) ? left : left - 1; // correct left to between sumLengths
|
|
137
|
-
if (left >= 0)
|
|
138
|
-
hoveredSeqMonomer = getSeqMonomerFromHelm(allParts[0], allParts[left], helmPlacer.monomerLib);
|
|
139
|
-
return hoveredSeqMonomer;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
type RendererGridCellTemp = {
|
|
143
|
-
[Temps.helmMonomerPlacer]: HelmMonomerPlacer;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
function getRendererGridCellTemp(gridCell: DG.GridCell
|
|
147
|
-
): [DG.GridColumn | null, DG.Column | null, RendererGridCellTemp] {
|
|
148
|
-
/** Primarily store/get MonomerPlacer at GridColumn, fallback at (Table) Column for scatter plot tooltip */
|
|
149
|
-
let temp: RendererGridCellTemp | null = null;
|
|
150
|
-
|
|
151
|
-
let gridCol: DG.GridColumn | null = null;
|
|
152
|
-
try { gridCol = gridCell.gridColumn; } catch { gridCol = null; }
|
|
153
|
-
temp = gridCol ? gridCol.temp as RendererGridCellTemp : null;
|
|
154
|
-
|
|
155
|
-
let tableCol: DG.Column | null = null;
|
|
156
|
-
if (!temp) {
|
|
157
|
-
try { tableCol = gridCell.cell.column; } catch { tableCol = null; }
|
|
158
|
-
temp = tableCol ? tableCol.temp as RendererGridCellTemp : null;
|
|
159
|
-
}
|
|
160
|
-
if (temp === null) throw new Error(`Monomer placer store (GridColumn or Column) not found.`);
|
|
161
|
-
return [gridCol, tableCol, temp];
|
|
162
|
-
}
|
|
163
|
-
|
|
164
25
|
/** Helm cell renderer in case of no missed monomer draws with JSDraw2.Editor (webeditor),
|
|
165
26
|
* in case of missed monomers presented, draws linear sequences aligned in width per monomer.
|
|
166
27
|
*/
|
|
@@ -175,8 +36,9 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
175
36
|
|
|
176
37
|
onMouseMove(gridCell: DG.GridCell, e: MouseEvent): void {
|
|
177
38
|
try {
|
|
178
|
-
const [_gridCol, tableCol, temp] =
|
|
179
|
-
|
|
39
|
+
const [_gridCol, tableCol, temp] =
|
|
40
|
+
getGridCellRendererBack<string, HelmMonomerPlacer>(gridCell);
|
|
41
|
+
const helmPlacer = temp['rendererBack'];
|
|
180
42
|
/* Can not do anything without tableColumn */
|
|
181
43
|
if (!tableCol) return;
|
|
182
44
|
|
|
@@ -184,11 +46,11 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
184
46
|
const argsX = e.offsetX - gcb.x;
|
|
185
47
|
const argsY = e.offsetY - gcb.y;
|
|
186
48
|
|
|
187
|
-
const
|
|
49
|
+
const editorMol: JSDraw2.IEditorMol | null = helmPlacer.getEditorMol(gridCell.tableRowIndex!);
|
|
188
50
|
let seqMonomer: ISeqMonomer | null;
|
|
189
51
|
let missedMonomers: Set<string> = new Set<string>(); // of .size = 0
|
|
190
|
-
if (
|
|
191
|
-
seqMonomer =
|
|
52
|
+
if (editorMol)
|
|
53
|
+
seqMonomer = getHoveredMonomerFromEditorMol(argsX, argsY, gridCell, editorMol);
|
|
192
54
|
else {
|
|
193
55
|
const seq: string = !gridCell.cell.value ? '' : removeGapsFromHelm(gridCell.cell.value as string);
|
|
194
56
|
const monomerList = parseHelm(seq);
|
|
@@ -246,11 +108,12 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
246
108
|
) {
|
|
247
109
|
g.save();
|
|
248
110
|
try {
|
|
249
|
-
const [gridCol, tableCol, temp] =
|
|
111
|
+
const [gridCol, tableCol, temp] =
|
|
112
|
+
getGridCellRendererBack<string, HelmMonomerPlacer>(gridCell);
|
|
250
113
|
/* Can not do anything without tableColumn containing temp */
|
|
251
114
|
if (!tableCol) return;
|
|
252
|
-
let helmPlacer = temp[
|
|
253
|
-
if (!helmPlacer) helmPlacer = temp[
|
|
115
|
+
let helmPlacer = temp['rendererBack'];
|
|
116
|
+
if (!helmPlacer) helmPlacer = temp['rendererBack'] = new HelmMonomerPlacer(gridCol, tableCol);
|
|
254
117
|
|
|
255
118
|
const grid = gridCell.gridRow !== -1 ? gridCell.grid : undefined;
|
|
256
119
|
const missedColor = 'red';
|
|
@@ -275,8 +138,9 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
|
|
|
275
138
|
}
|
|
276
139
|
|
|
277
140
|
// Recreate editor to avoid hanging in window.dojox.gfx.svg.Text.prototype.getTextWidth
|
|
278
|
-
const editor = new JSDraw2.Editor(host,
|
|
279
|
-
|
|
141
|
+
const editor = new JSDraw2.Editor(host,
|
|
142
|
+
{width: w, height: h, skin: 'w8', viewonly: true});
|
|
143
|
+
helmPlacer.setEditorMol(gridCell.tableRowIndex!, editor.m);
|
|
280
144
|
|
|
281
145
|
helmPlacer.skipCell(gridCell.tableRowIndex!);
|
|
282
146
|
return;
|
package/src/helm-helper.ts
CHANGED
|
@@ -2,8 +2,12 @@ import * as grok from 'datagrok-api/grok';
|
|
|
2
2
|
import * as ui from 'datagrok-api/ui';
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
|
+
import * as scil from 'scil';
|
|
6
|
+
import * as org from 'org';
|
|
7
|
+
|
|
5
8
|
import {IHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
|
|
6
|
-
import {IHelmWebEditor
|
|
9
|
+
import {IHelmWebEditor} from '@datagrok-libraries/bio/src/helm/types';
|
|
10
|
+
|
|
7
11
|
import {HelmWebEditor} from './helm-web-editor';
|
|
8
12
|
|
|
9
13
|
type HelmHelperWindowType = Window & {
|
|
@@ -16,11 +20,9 @@ export class HelmHelper implements IHelmHelper {
|
|
|
16
20
|
return new HelmWebEditor();
|
|
17
21
|
}
|
|
18
22
|
|
|
19
|
-
createWebEditorApp(host: HTMLDivElement, helm: string): IWebEditorApp {
|
|
20
|
-
// @ts-ignore
|
|
23
|
+
createWebEditorApp(host: HTMLDivElement, helm: string): org.helm.IWebEditorApp {
|
|
21
24
|
org.helm.webeditor.MolViewer.molscale = 0.8;
|
|
22
|
-
|
|
23
|
-
const webEditorApp = new scil.helm.App(host, {
|
|
25
|
+
const webEditorApp: org.helm.IWebEditorApp = new org.helm.webeditor.App(host, {
|
|
24
26
|
showabout: false,
|
|
25
27
|
mexfontsize: '90%',
|
|
26
28
|
mexrnapinontab: true,
|
|
@@ -29,16 +31,13 @@ export class HelmHelper implements IHelmHelper {
|
|
|
29
31
|
sequenceviewonly: false,
|
|
30
32
|
mexfavoritefirst: true,
|
|
31
33
|
mexfilter: true
|
|
32
|
-
})
|
|
34
|
+
});
|
|
33
35
|
const sizes = webEditorApp.calculateSizes();
|
|
34
36
|
webEditorApp.canvas.resize(sizes.rightwidth - 100, sizes.topheight - 210);
|
|
35
|
-
let s = {width: sizes.rightwidth - 100 + 'px', height: sizes.bottomheight + 'px'};
|
|
36
|
-
//@ts-ignore
|
|
37
|
+
let s: Partial<CSSStyleDeclaration> = {width: sizes.rightwidth - 100 + 'px', height: sizes.bottomheight + 'px'};
|
|
37
38
|
scil.apply(webEditorApp.sequence.style, s);
|
|
38
|
-
//@ts-ignore
|
|
39
39
|
scil.apply(webEditorApp.notation.style, s);
|
|
40
40
|
s = {width: sizes.rightwidth + 'px', height: (sizes.bottomheight + webEditorApp.toolbarheight) + 'px'};
|
|
41
|
-
//@ts-ignore
|
|
42
41
|
scil.apply(webEditorApp.properties.parent.style, s);
|
|
43
42
|
webEditorApp.structureview.resize(sizes.rightwidth, sizes.bottomheight + webEditorApp.toolbarheight);
|
|
44
43
|
webEditorApp.mex.resize(sizes.topheight - 80);
|
|
@@ -2,94 +2,46 @@ import * as grok from 'datagrok-api/grok';
|
|
|
2
2
|
import * as ui from 'datagrok-api/ui';
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
|
+
import * as org from 'org';
|
|
6
|
+
import * as JSDraw2 from 'JSDraw2';
|
|
5
7
|
import wu from 'wu';
|
|
6
|
-
import {Unsubscribable} from 'rxjs';
|
|
7
8
|
|
|
8
9
|
import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types/index';
|
|
10
|
+
import {CellRendererBackBase} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
|
|
9
11
|
|
|
10
12
|
import {getParts, parseHelm} from './utils';
|
|
11
13
|
|
|
12
14
|
import {_package, getMonomerLib} from './package';
|
|
13
15
|
|
|
14
|
-
export const enum Temps {
|
|
15
|
-
helmMonomerPlacer = 'bio-helmMonomerPlacer',
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface IEditor {
|
|
19
|
-
get m(): IEditorMol;
|
|
20
|
-
|
|
21
|
-
redraw(): void;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface IEditorMol {
|
|
25
|
-
get atoms(): IEditorMolAtom[];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface IEditorMolAtom {
|
|
29
|
-
get p(): IEditorPoint;
|
|
30
|
-
|
|
31
|
-
get elem(): string;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface IEditorPoint {
|
|
35
|
-
get x(): number;
|
|
36
|
-
|
|
37
|
-
get y(): number;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
16
|
export interface ISeqMonomer {
|
|
41
17
|
polymerType: string
|
|
42
18
|
symbol: string,
|
|
43
19
|
}
|
|
44
20
|
|
|
45
|
-
export class HelmMonomerPlacer {
|
|
46
|
-
private readonly grid: DG.Grid | null;
|
|
21
|
+
export class HelmMonomerPlacer extends CellRendererBackBase<string> {
|
|
47
22
|
public readonly monomerLib: IMonomerLib;
|
|
48
23
|
|
|
49
24
|
private _allPartsList: (string[] | null)[];
|
|
50
25
|
private _lengthsList: (number[] | null)[];
|
|
51
|
-
private
|
|
26
|
+
private _editorMolList: (JSDraw2.IEditorMol | null)[];
|
|
52
27
|
|
|
53
28
|
public monomerCharWidth: number = 7;
|
|
54
29
|
public leftPadding: number = 5;
|
|
55
30
|
public monomerTextSizeMap: { [p: string]: TextMetrics } = {};
|
|
56
31
|
|
|
57
|
-
private subs: Unsubscribable[] = [];
|
|
58
|
-
|
|
59
32
|
public constructor(
|
|
60
|
-
|
|
61
|
-
|
|
33
|
+
gridCol: DG.GridColumn | null,
|
|
34
|
+
tableCol: DG.Column<string>
|
|
62
35
|
) {
|
|
63
|
-
|
|
64
|
-
this.reset();
|
|
65
|
-
if (this.grid) {
|
|
66
|
-
this.subs.push(this.col.dataFrame.onDataChanged.subscribe(() => {
|
|
67
|
-
try {
|
|
68
|
-
this.reset();
|
|
69
|
-
} catch (err: any) {
|
|
70
|
-
console.error(err);
|
|
71
|
-
}
|
|
72
|
-
}));
|
|
73
|
-
this.subs.push(grok.events.onViewRemoved.subscribe((view: DG.View) => {
|
|
74
|
-
try {
|
|
75
|
-
if (this.grid && this.grid.view?.id === view.id) this.destroy();
|
|
76
|
-
} catch (err: any) {
|
|
77
|
-
console.error(err);
|
|
78
|
-
}
|
|
79
|
-
}));
|
|
80
|
-
}
|
|
36
|
+
super(gridCol, tableCol, _package.logger);
|
|
81
37
|
this.monomerLib = getMonomerLib();
|
|
82
38
|
this.subs.push(this.monomerLib.onChanged.subscribe(this.monomerLibOnChanged.bind(this)));
|
|
83
39
|
}
|
|
84
40
|
|
|
85
|
-
|
|
86
|
-
this._allPartsList = new Array<string[] | null>(this.
|
|
87
|
-
this._lengthsList = new Array<number[] | null>(this.
|
|
88
|
-
this.
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
private destroy(): void {
|
|
92
|
-
for (const sub of this.subs) sub.unsubscribe();
|
|
41
|
+
protected override reset(): void {
|
|
42
|
+
this._allPartsList = new Array<string[] | null>(this.tableCol.length).fill(null);
|
|
43
|
+
this._lengthsList = new Array<number[] | null>(this.tableCol.length).fill(null);
|
|
44
|
+
this._editorMolList = new Array<JSDraw2.IEditorMol | null>(this.tableCol.length).fill(null);
|
|
93
45
|
}
|
|
94
46
|
|
|
95
47
|
/** Skips cell for the fallback rendering */
|
|
@@ -112,7 +64,7 @@ export class HelmMonomerPlacer {
|
|
|
112
64
|
private getCellMonomerLengthsForSeq(rowIdx: number): [string[], number[]] {
|
|
113
65
|
let allParts: string[] | null = this._allPartsList![rowIdx];
|
|
114
66
|
if (allParts === null) {
|
|
115
|
-
const seq = this.
|
|
67
|
+
const seq = this.tableCol.get(rowIdx);
|
|
116
68
|
allParts = this._allPartsList![rowIdx] = getAllParts(seq);
|
|
117
69
|
}
|
|
118
70
|
|
|
@@ -145,15 +97,15 @@ export class HelmMonomerPlacer {
|
|
|
145
97
|
|
|
146
98
|
private monomerLibOnChanged(_value: any): void {
|
|
147
99
|
this.reset();
|
|
148
|
-
|
|
100
|
+
this.invalidateGrid();
|
|
149
101
|
}
|
|
150
102
|
|
|
151
|
-
public
|
|
152
|
-
this.
|
|
103
|
+
public setEditorMol(tableRowIndex: number, editorMol: JSDraw2.IEditorMol) {
|
|
104
|
+
this._editorMolList![tableRowIndex] = editorMol.clone(false);
|
|
153
105
|
}
|
|
154
106
|
|
|
155
|
-
public
|
|
156
|
-
return this.
|
|
107
|
+
public getEditorMol(tableRowIndex: number): JSDraw2.IEditorMol | null {
|
|
108
|
+
return this._editorMolList![tableRowIndex];
|
|
157
109
|
}
|
|
158
110
|
}
|
|
159
111
|
|
package/src/helm-web-editor.ts
CHANGED
|
@@ -2,11 +2,14 @@ import * as grok from 'datagrok-api/grok';
|
|
|
2
2
|
import * as ui from 'datagrok-api/ui';
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
|
+
import * as JSDraw2 from 'JSDraw2';
|
|
6
|
+
|
|
5
7
|
import {IHelmWebEditor} from '@datagrok-libraries/bio/src/helm/types';
|
|
6
8
|
|
|
7
9
|
export class HelmWebEditor implements IHelmWebEditor {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
editor: JSDraw2.Editor;
|
|
11
|
+
host: HTMLDivElement;
|
|
12
|
+
|
|
10
13
|
w = 200;
|
|
11
14
|
h = 100;
|
|
12
15
|
|
package/src/package-test.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {runTests, tests, TestContext} from '@datagrok-libraries/utils/src/test';
|
|
|
5
5
|
|
|
6
6
|
import './tests/helm-tests.ts';
|
|
7
7
|
import './tests/findMonomers-tests';
|
|
8
|
+
import './tests/helm-service-tests';
|
|
8
9
|
import './tests/renderers-tests';
|
|
9
10
|
import './tests/get-molfiles';
|
|
10
11
|
import './tests/properties-widget-tests';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as ui from 'datagrok-api/ui';
|
|
2
|
+
import * as grok from 'datagrok-api/grok';
|
|
3
|
+
import * as DG from 'datagrok-api/dg';
|
|
4
|
+
|
|
5
|
+
import {HelmServiceBase} from '@datagrok-libraries/bio/src/viewers/helm-service';
|
|
6
|
+
import {HelmService} from './utils/helm-service';
|
|
7
|
+
|
|
8
|
+
type HelmWindowType = Window & {
|
|
9
|
+
$helmService?: HelmServiceBase,
|
|
10
|
+
}
|
|
11
|
+
declare const window: HelmWindowType;
|
|
12
|
+
|
|
13
|
+
export function _getHelmService(): HelmServiceBase {
|
|
14
|
+
let res = window.$helmService;
|
|
15
|
+
if (!res) res = window.$helmService = new HelmService();
|
|
16
|
+
return res;
|
|
17
|
+
}
|