@datagrok/helm 2.3.4 → 2.4.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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/helm",
3
3
  "friendlyName": "Helm",
4
- "version": "2.3.4",
4
+ "version": "2.4.1",
5
5
  "author": {
6
6
  "name": "Oleksandra Serhiienko",
7
7
  "email": "oserhiienko@datagrok.ai"
@@ -16,7 +16,7 @@
16
16
  "css/helm.css"
17
17
  ],
18
18
  "dependencies": {
19
- "@datagrok-libraries/bio": "^5.42.6",
19
+ "@datagrok-libraries/bio": "^5.42.9",
20
20
  "@datagrok-libraries/chem-meta": "^1.2.5",
21
21
  "@datagrok-libraries/utils": "^4.2.19",
22
22
  "cash-dom": "^8.1.1",
@@ -26,17 +26,18 @@
26
26
  "wu": "latest"
27
27
  },
28
28
  "devDependencies": {
29
- "@datagrok-libraries/helm-web-editor": "^1.1.6",
30
- "@datagrok-libraries/js-draw-lite": "^0.0.4",
31
- "@datagrok/bio": "^2.13.3",
29
+ "@datagrok-libraries/helm-web-editor": "^1.1.8",
30
+ "@datagrok-libraries/js-draw-lite": "^0.0.6",
31
+ "@datagrok/bio": "^2.14.1",
32
32
  "@datagrok/chem": "^1.9.2",
33
33
  "@types/node": "17.0.45",
34
34
  "@types/wu": "latest",
35
- "@typescript-eslint/eslint-plugin": "^5.11.0",
36
- "@typescript-eslint/parser": "^5.11.0",
35
+ "@typescript-eslint/eslint-plugin": "^7.16.0",
36
+ "@typescript-eslint/parser": "^7.16.0",
37
37
  "datagrok-tools": "latest",
38
38
  "eslint": "^8.18.0",
39
39
  "eslint-config-google": "^0.14.0",
40
+ "eslint-plugin-rxjs": "^5.0.3",
40
41
  "path": "^0.12.7",
41
42
  "source-map-loader": "^4.0.1",
42
43
  "ts-loader": "^9.2.6",
@@ -4,19 +4,19 @@ import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import wu from 'wu';
6
6
 
7
- import {HelmType, ISeqMonomer, Mol} from '@datagrok-libraries/bio/src/helm/types';
7
+ import {HelmMol, ISeqMonomer} from '@datagrok-libraries/bio/src/helm/types';
8
8
 
9
9
  import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
10
10
  import {getGridCellRendererBack} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
11
11
 
12
12
  import {findMonomers, parseHelm, removeGapsFromHelm} from './utils';
13
13
  import {HelmMonomerPlacer} from './helm-monomer-placer';
14
- import {getHoveredMonomerFallback, getHoveredMonomerFromEditorMol} from './utils/get-hovered';
15
- import {JSDraw2HelmModule} from './types';
14
+ import {getHoveredMonomerFallback, getHoveredMonomerFromEditorMol, getSeqMonomerFromHelmAtom} from './utils/get-hovered';
15
+ import {JSDraw2Module} from './types';
16
16
 
17
17
  import {_package} from './package';
18
18
 
19
- declare const JSDraw2: JSDraw2HelmModule;
19
+ declare const JSDraw2: JSDraw2Module;
20
20
 
21
21
  const enum tempTAGS {
22
22
  helmSumMaxLengthWords = 'helm-sum-maxLengthWords',
@@ -50,12 +50,13 @@ export class HelmCellRenderer extends DG.GridCellRenderer {
50
50
  const argsY = e.offsetY - gcb.y;
51
51
 
52
52
  const monomerLib = _package.monomerLib;
53
- const editorMol: Mol<HelmType> | null = helmPlacer.getEditorMol(gridCell.tableRowIndex!);
53
+ const editorMol: HelmMol | null = helmPlacer.getEditorMol(gridCell.tableRowIndex!);
54
54
  let seqMonomer: ISeqMonomer | null;
55
55
  let missedMonomers: Set<string> = new Set<string>(); // of .size = 0
56
- if (editorMol)
57
- seqMonomer = getHoveredMonomerFromEditorMol(argsX, argsY, editorMol, gridCell.bounds.height);
58
- else {
56
+ if (editorMol) {
57
+ const hoveredAtom = getHoveredMonomerFromEditorMol(argsX, argsY, editorMol, gridCell.bounds.height);
58
+ seqMonomer = hoveredAtom ? getSeqMonomerFromHelmAtom(hoveredAtom) : null;
59
+ } else {
59
60
  const seq: string = !gridCell.cell.value ? '' : removeGapsFromHelm(gridCell.cell.value as string);
60
61
  const monomerList = parseHelm(seq);
61
62
  missedMonomers = findMonomers(monomerList, monomerLib);
@@ -3,23 +3,26 @@ import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import {
6
- App, Atom, HelmType, GetMonomerFunc, GetMonomerResType, HelmString, HelmMol
6
+ App, Atom, HelmType, GetMonomerFunc, GetMonomerResType, HelmString, HelmMol,
7
+ MonomerExplorer, TabDescType, MonomersFuncs, MonomerSetType, HelmAtom, ISeqMonomer, PolymerType, MonomerType, type DojoType
7
8
  } from '@datagrok-libraries/bio/src/helm/types';
8
-
9
+ import {HelmTypes, MonomerTypes, PolymerTypes} from '@datagrok-libraries/bio/src/helm/consts';
9
10
  import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
10
11
  import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
11
- import {IHelmHelper, IInputInitOptions} from '@datagrok-libraries/bio/src/helm/helm-helper';
12
+ import {HelmInputBase, IHelmHelper, IHelmInputInitOptions} from '@datagrok-libraries/bio/src/helm/helm-helper';
12
13
  import {IHelmWebEditor} from '@datagrok-libraries/bio/src/helm/types';
13
- import {IMonomerLib} from '@datagrok-libraries/bio/src/types/index';
14
+ import {IMonomerLib, IMonomerLinkData, IMonomerSetPlaceholder} from '@datagrok-libraries/bio/src/types/index';
15
+ import {HelmTabKeys, IHelmDrawOptions} from '@datagrok-libraries/helm-web-editor/src/types/org-helm';
14
16
 
15
17
  import {HelmWebEditor} from './helm-web-editor';
16
18
  import {OrgHelmModule, ScilModule} from './types';
17
19
  import {getWebEditorMonomer} from './utils/get-monomer';
18
20
  import {HelmInput} from './widgets/helm-input';
21
+ import {getHoveredMonomerFromEditorMol} from './utils/get-hovered';
19
22
 
20
23
  import {_package} from './package';
21
24
 
22
-
25
+ declare const dojo: DojoType;
23
26
  declare const scil: ScilModule;
24
27
  declare const org: OrgHelmModule;
25
28
 
@@ -34,9 +37,9 @@ export class HelmHelper implements IHelmHelper {
34
37
  throw new Error(`HelmHelper must be a single.`);
35
38
  }
36
39
 
37
- createHelmInput(name?: string, options?: IInputInitOptions<HelmMol>): DG.InputBase<HelmMol> {
40
+ createHelmInput(name?: string, options?: IHelmInputInitOptions): HelmInputBase {
38
41
  try {
39
- const monomerLib: IMonomerLib = _package.libHelper.getBioLib();
42
+ const monomerLib: IMonomerLib = _package.libHelper!.getMonomerLib();
40
43
  return HelmInput.create(this, monomerLib, name, options);
41
44
  } catch (err: any) {
42
45
  const [errMsg, errStack] = errInfo(err);
@@ -45,8 +48,8 @@ export class HelmHelper implements IHelmHelper {
45
48
  }
46
49
  }
47
50
 
48
- createHelmWebEditor(host?: HTMLDivElement): IHelmWebEditor {
49
- return new HelmWebEditor(host);
51
+ createHelmWebEditor(host?: HTMLDivElement, drawOptions?: Partial<IHelmDrawOptions>): IHelmWebEditor {
52
+ return new HelmWebEditor(host, drawOptions);
50
53
  }
51
54
 
52
55
  createWebEditorApp(host: HTMLDivElement, helm: string): App {
@@ -59,7 +62,36 @@ export class HelmHelper implements IHelmHelper {
59
62
  mexmonomerstab: true,
60
63
  sequenceviewonly: false,
61
64
  mexfavoritefirst: true,
62
- mexfilter: true
65
+ mexfilter: true,
66
+ // currentTabKey: HelmTabKeys.Helm,
67
+ overrideTabs: (tabs: Partial<TabDescType>[]): Partial<TabDescType>[] => {
68
+ const res: Partial<TabDescType>[] = [...tabs,
69
+ {caption: 'Placeholders', tabkey: 'placeholders'},
70
+ ];
71
+ return res;
72
+ },
73
+ onShowTab: (mex: MonomerExplorer, div: HTMLDivElement, key: string): void => {
74
+ switch (key) {
75
+ case 'placeholders': {
76
+ this.onShowTabPlaceholders(mex, div);
77
+ break;
78
+ }
79
+ case 'placeholders-meta': {
80
+ this.onShowTabPlaceholdersMeta(mex, div);
81
+ break;
82
+ }
83
+ case 'placeholders-sets': {
84
+ this.onShowTabPlaceholdersSets(mex, div);
85
+ break;
86
+ }
87
+ }
88
+ dojo.connect(div, 'onmousedown', function(e: MouseEvent) {
89
+ mex.select(e);
90
+ });
91
+ dojo.connect(div, 'ondblclick', function(e: MouseEvent) {
92
+ mex.dblclick(e);
93
+ });
94
+ }
63
95
  });
64
96
  const sizes = webEditorApp.calculateSizes();
65
97
  webEditorApp.canvas!.resize(sizes.rightwidth - 100, sizes.topheight - 210);
@@ -70,55 +102,215 @@ export class HelmHelper implements IHelmHelper {
70
102
  scil.apply(webEditorApp.properties!.parent.style, s);
71
103
  webEditorApp.structureview!.resize(sizes.rightwidth, sizes.bottomheight + webEditorApp.toolbarheight);
72
104
  webEditorApp.mex!.resize(sizes.topheight - 80);
73
- setTimeout(() => {
74
- webEditorApp.canvas!.helm!.setSequence(helm, 'HELM');
75
- }, 200);
105
+ webEditorApp.canvas?.setHelm(helm);
76
106
  return webEditorApp;
77
107
  }
78
108
 
109
+ // -- MonomerExplorer.onShowTab --
110
+
111
+ public onShowTabPlaceholders(mex: MonomerExplorer, div: HTMLDivElement): void {
112
+ const d = scil.Utils.createElement(div, 'div', null, {paddingTop: '5px'});
113
+
114
+ /* eslint-disable max-len*/
115
+ // if (this.options.canvastoolbar == false) {
116
+ // const b = scil.Utils.createElement(d, 'div', '<img src=\'' + scil.Utils.imgSrc('helm/arrow.png') + '\' style=\'vertical-align:middle\'>Mouse Pointer', {cursor: 'pointer', padding: '2px', border: 'solid 1px gray', margin: '5px'});
117
+ // scil.connect(b, 'onclick', function() {
118
+ // mex.plugin.jsd.doCmd('lasso');
119
+ // });
120
+ // }
121
+ /* eslint-enable max-len*/
122
+
123
+ const phTabs: Partial<TabDescType>[] = [];
124
+ phTabs.push({caption: 'Meta', tabkey: 'placeholders-meta'});
125
+ phTabs.push({caption: 'Sets', tabkey: 'placeholders-sets'});
126
+ const placeholdersTabs = new scil.Tabs(d, {
127
+ onShowTab(td: HTMLTableCellElement) {
128
+ mex.onShowTab(td);
129
+ },
130
+ tabpadding: '5px 2px 1px 2px',
131
+ tabs: phTabs,
132
+ marginBottom: `0`,
133
+ });
134
+ }
135
+
136
+ public onShowTabPlaceholdersMeta(mex: MonomerExplorer, div: HTMLDivElement): void {
137
+
138
+ }
139
+
140
+ public onShowTabPlaceholdersSets(mex: MonomerExplorer, div: HTMLDivElement): void {
141
+ const monomerSets = _package.libHelper!.getMonomerSets();
142
+
143
+ const phSet: { [polymerType: string]: { [helmType: string]: IMonomerSetPlaceholder[] } } = {};
144
+ for (const ph of monomerSets.placeholders) {
145
+ let ofPolymerTypeSet = phSet[ph.polymerType];
146
+ if (!ofPolymerTypeSet) ofPolymerTypeSet = phSet[ph.polymerType] = {};
147
+
148
+ const phHelmType = this.toHelmType(ph.polymerType, ph.monomerType);
149
+ let phList = ofPolymerTypeSet[phHelmType];
150
+ if (!phList) phList = ofPolymerTypeSet[phHelmType] = [];
151
+ phList.push(ph);
152
+ }
153
+
154
+ const fillPlaceholders = (
155
+ parentDiv: HTMLDivElement, phList: IMonomerSetPlaceholder[], helmType: HelmType
156
+ ): void => {
157
+ for (const ph of phList) {
158
+ const phDiv = mex.createMonomerDiv(parentDiv, ph.symbol, helmType);
159
+ ui.tooltip.bind(phDiv, () => {
160
+ const phTooltipDiv = ui.div([
161
+ ui.table(ph.monomerLinks, (ml: IMonomerLinkData, idx: number) => {
162
+ return [ml.symbol, ml.source];
163
+ }, ['Symbol', 'Library source'])
164
+ ]);
165
+ return phTooltipDiv;
166
+ });
167
+ }
168
+ };
169
+
170
+ const polymerTypes: [string, PolymerType][] = [
171
+ ['Chem', PolymerTypes.CHEM],
172
+ ['Peptide', PolymerTypes.PEPTIDE],
173
+ ['RNA', PolymerTypes.RNA],
174
+ ['Blob', PolymerTypes.BLOB],
175
+ ['G', PolymerTypes.G],
176
+ ];
177
+ const polymerTypeAcc = ui.accordion();
178
+ for (const [name, polymerType] of polymerTypes) {
179
+ if (polymerType in phSet) {
180
+ polymerTypeAcc.addPane(name, () => {
181
+ const polymerTypeDiv = ui.div();
182
+ const ofPolymerTypeSet = phSet[polymerType];
183
+ if (Object.keys(ofPolymerTypeSet).length == 1) {
184
+ const [helmType, phList] = Object.entries(ofPolymerTypeSet)[0];
185
+ fillPlaceholders(polymerTypeDiv, phList, helmType as HelmType);
186
+ } else {
187
+ const helmTypeAcc = ui.accordion();
188
+ for (const [helmTypeName, helmType] of Object.entries(HelmTypes)) {
189
+ if (helmType in ofPolymerTypeSet) {
190
+ helmTypeAcc.addPane(helmTypeName, () => {
191
+ const helmTypeDiv = ui.div();
192
+
193
+ const phList = ofPolymerTypeSet[helmType];
194
+ fillPlaceholders(helmTypeDiv, phList, helmType as HelmType);
195
+
196
+ return helmTypeDiv;
197
+ });
198
+ }
199
+ }
200
+ polymerTypeDiv.appendChild(helmTypeAcc.root);
201
+ }
202
+ return polymerTypeDiv;
203
+ }, true, undefined, false);
204
+ }
205
+ }
206
+ div.appendChild(polymerTypeAcc.root);
207
+ }
208
+
79
209
  // -- GetMonomer --
80
210
 
81
- public originalGetMonomer: GetMonomerFunc | null = null;
211
+ public originalMonomersFuncs: MonomersFuncs | null = null;
82
212
 
83
- public revertOriginalGetMonomer(): GetMonomerFunc {
213
+ public revertOriginalMonomersFuncs(): MonomersFuncs {
84
214
  const logPrefix = `Helm: revertOriginalGetMonomer()`;
85
- if (this.originalGetMonomer === null)
215
+ if (this.originalMonomersFuncs === null)
86
216
  throw new Error('Unable to revert original getMonomer');
87
217
 
88
218
  const monomers = org.helm.webeditor.Monomers;
89
- const overriddenGetMonomer = monomers.getMonomer = this.originalGetMonomer;
90
- this.originalGetMonomer = null;
91
- return overriddenGetMonomer;
219
+ const overriddenMonomersFuncs: MonomersFuncs = {
220
+ getMonomer: monomers.getMonomer,
221
+ getMonomerSet: monomers.getMonomerSet,
222
+ };
223
+
224
+ monomers.getMonomer = this.originalMonomersFuncs.getMonomer;
225
+ monomers.getMonomerSet = this.originalMonomersFuncs.getMonomerSet;
226
+ this.originalMonomersFuncs = null;
227
+
228
+ return overriddenMonomersFuncs;
92
229
  }
93
230
 
94
- public overrideGetMonomer(getMonomer: GetMonomerFunc): GetMonomerFunc {
95
- const logPrefix = `Helm: overrideGetMonomer()`;
231
+ public overrideMonomersFuncs(monomersFuncs: MonomersFuncs): MonomersFuncs {
232
+ const logPrefix = `Helm: HelmHelper.overrideGetMonomer()`;
96
233
 
97
- if (this.originalGetMonomer != null)
98
- throw new Error('');
234
+ if (this.originalMonomersFuncs != null)
235
+ throw new Error(`${logPrefix}, originalGetMonomer is overridden already`);
99
236
 
100
237
  const monomers = org.helm.webeditor.Monomers;
101
- this.originalGetMonomer = monomers.getMonomer.bind(monomers);
102
- monomers.getMonomer = getMonomer;
103
- return this.originalGetMonomer!;
238
+ this.originalMonomersFuncs = {
239
+ getMonomer: monomers.getMonomer.bind(monomers),
240
+ getMonomerSet: monomers.getMonomerSet.bind(monomers),
241
+ };
242
+ monomers.getMonomer = monomersFuncs.getMonomer;
243
+ monomers.getMonomerSet = monomersFuncs.getMonomerSet;
244
+ return this.originalMonomersFuncs!;
104
245
  }
105
246
 
106
- public buildGetMonomerFromLib(monomerLib: IMonomerLib): GetMonomerFunc {
247
+ public buildMonomersFuncsFromLib(monomerLib: IMonomerLib): MonomersFuncs {
107
248
  const logPrefix = `Helm: HelmHelper.buildGetMonomerFromLib()`;
108
- return (a: Atom<HelmType> | HelmType, name?: string): GetMonomerResType => {
109
- const logPrefixInt = `${logPrefix}, org.helm.webeditor.Monomers.getMonomer()`;
110
- try {
111
- // logger.debug(`${logPrefixInt}, a: ${JSON.stringify(a, helmJsonReplacer)}, name: '${name}'`);
112
-
113
- // Creates monomers in lib
114
- const dgWem = getWebEditorMonomer(monomerLib, a, name);
115
-
116
- return dgWem; //dgWem;
117
- } catch (err) {
118
- const [errMsg, errStack] = errInfo(err);
119
- this.logger.error(`${logPrefixInt}, Error: ${errMsg}`, undefined, errStack);
120
- throw err;
249
+
250
+ return {
251
+ getMonomer: (a: HelmAtom | HelmType, name?: string): GetMonomerResType => {
252
+ const logPrefixInt = `${logPrefix}, org.helm.webeditor.Monomers.getMonomer()`;
253
+ try {
254
+ // logger.debug(`${logPrefixInt}, a: ${JSON.stringify(a, helmJsonReplacer)}, name: '${name}'`);
255
+
256
+ // Creates monomers in lib
257
+ const dgWem = getWebEditorMonomer(monomerLib, a, name);
258
+
259
+ return dgWem; //dgWem;
260
+ } catch (err) {
261
+ const [errMsg, errStack] = errInfo(err);
262
+ this.logger.error(`${logPrefixInt}, Error: ${errMsg}`, undefined, errStack);
263
+ throw err;
264
+ }
265
+ },
266
+ getMonomerSet: (a: HelmAtom | HelmType | null): MonomerSetType | null => {
267
+ // if (a == null)
268
+ // return null;
269
+ // const atom = a as HelmAtom;
270
+ // if (atom.T === 'ATOM')
271
+ // a = atom.biotype();
272
+ // return monomerLib.getMonomerSet(a as HelmType);
273
+ return this.originalMonomersFuncs!.getMonomerSet(a);
121
274
  }
122
275
  };
123
276
  }
277
+
278
+ // helm2type(seqM: ISeqMonomer): HelmType {
279
+ // if (seqM.polymerType == "PEPTIDE")
280
+ // return org.helm.webeditor.HELM.AA;
281
+ // else if (seqM.polymerType == "CHEM")
282
+ // return org.helm.webeditor.HELM.CHEM;
283
+ // else if (seqM.polymerType == "RNA") {
284
+ // if (seqM.mt == "Branch")
285
+ // return org.helm.webeditor.HELM.BASE;
286
+ // if (seqM.mt == "Backbone") {
287
+ // if (seqM.na == "P" || seqM.na == "p")
288
+ // return org.helm.webeditor.HELM.LINKER;
289
+ // else
290
+ // return org.helm.webeditor.HELM.SUGAR;
291
+ // }
292
+ // }
293
+ // throw new Error(`Not supported seq monomer ${JSON.stringify(seqM)}.`);
294
+ // }
295
+ private toHelmType(polymerType: PolymerType, monomerType: MonomerType, naturalAnalog?: string) {
296
+ if (polymerType == PolymerTypes.PEPTIDE)
297
+ return org.helm.webeditor.HELM.AA;
298
+ else if (polymerType == PolymerTypes.CHEM)
299
+ return org.helm.webeditor.HELM.CHEM;
300
+ else if (polymerType == PolymerTypes.RNA) {
301
+ if (monomerType == MonomerTypes.BRANCH)
302
+ return org.helm.webeditor.HELM.BASE;
303
+ if (monomerType == MonomerTypes.BACKBONE) {
304
+ if (naturalAnalog == 'P' || naturalAnalog == 'p')
305
+ return org.helm.webeditor.HELM.LINKER;
306
+ else
307
+ return org.helm.webeditor.HELM.SUGAR;
308
+ }
309
+ }
310
+ throw new Error(`Not supported monomer polymerType: '${polymerType}', monomerType: '${monomerType}'.`);
311
+ }
312
+
313
+ public getHoveredAtom(x: number, y: number, mol: HelmMol, height: number): HelmAtom | null {
314
+ return getHoveredMonomerFromEditorMol(x, y, mol, height);
315
+ }
124
316
  }
@@ -73,7 +73,7 @@ export class HelmMonomerPlacer extends CellRendererBackBase<string> {
73
73
  // -- Handle events --
74
74
 
75
75
  private monomerLibOnChanged(_value: any): void {
76
- this.reset();
76
+ this.dirty = true;
77
77
  this.invalidateGrid();
78
78
  }
79
79
 
@@ -6,19 +6,19 @@ import {Unsubscribable} from 'rxjs';
6
6
 
7
7
  import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
8
8
  import {
9
- App, Editor, HelmType, IHelmWebEditor
9
+ App, Editor, HelmType, IHelmWebEditor, HelmEditor, IHelmDrawOptions
10
10
  } from '@datagrok-libraries/bio/src/helm/types';
11
11
 
12
- import {JSDraw2HelmModule, OrgHelmModule, ScilModule} from './types';
12
+ import {JSDraw2Module, OrgHelmModule, ScilModule} from './types';
13
13
 
14
14
  import {_package} from './package';
15
15
 
16
16
  declare const scil: ScilModule;
17
- declare const JSDraw2: JSDraw2HelmModule;
17
+ declare const JSDraw2: JSDraw2Module;
18
18
  declare const org: OrgHelmModule;
19
19
 
20
20
  export class HelmWebEditor implements IHelmWebEditor {
21
- editor: Editor<HelmType>;
21
+ editor: HelmEditor;
22
22
  host: HTMLDivElement;
23
23
 
24
24
  w = 200;
@@ -27,10 +27,19 @@ export class HelmWebEditor implements IHelmWebEditor {
27
27
 
28
28
  constructor(
29
29
  host?: HTMLDivElement,
30
+ drawOptions?: Partial<IHelmDrawOptions>,
30
31
  private logger: ILogger = _package.logger
31
32
  ) {
32
33
  this.host = host ?? ui.div([], {style: {width: `${this.w}px`, height: `${this.h}px`}});
33
- this.editor = new JSDraw2.Editor(this.host, {width: this.w, height: this.h, viewonly: true});
34
+
35
+ const styleBackup = {width: this.host.style.width, height: this.host.style.height, overflow: this.host.style.overflow};
36
+ this.editor = new JSDraw2.Editor(this.host, {
37
+ width: this.w, height: this.h, viewonly: true,
38
+ drawOptions: drawOptions
39
+ });
40
+ this.host.style.width = styleBackup.width;
41
+ this.host.style.height = styleBackup.height;
42
+ this.host.style.overflow = styleBackup.overflow;
34
43
 
35
44
  this.subs = [];
36
45
  this.subs.push(ui.onSizeChanged(this.host).subscribe(this.hostOnSizeChanged.bind(this)));
@@ -40,38 +49,19 @@ export class HelmWebEditor implements IHelmWebEditor {
40
49
  return `Helm: HelmWebEditor<#>`;
41
50
  }
42
51
 
43
- private hostOnSizeChanged(_: any): void {
44
- const logPrefix = `${this.toLog()}.hostOnSizeChanged()`;
45
- this.logger.debug(`${logPrefix}`);
46
- this.editor.setSize(this.host.clientWidth, this.host.clientHeight);
52
+ private lastSize: { width: number, height: number } = {width: -1, height: -1};
53
+
54
+ private hostOnSizeChanged(value: any): void {
55
+ const size = {width: value.target.clientWidth, height: value.target.clientHeight};
56
+ if (this.lastSize.width != size.width || this.lastSize.height != size.height) {
57
+ const logPrefix = `${this.toLog()}.hostOnSizeChanged()`;
58
+ this.logger.debug(`${logPrefix}`);
59
+ this.editor.setSize(this.host.clientWidth, this.host.clientHeight);
60
+ }
61
+ this.lastSize = size;
47
62
  }
48
63
 
49
64
  resizeEditor(w: number, h: number) {
50
65
  this.editor.setSize(w, h);
51
66
  }
52
67
  }
53
-
54
- export function buildWebEditorApp(view: HTMLDivElement): App {
55
- org.helm.webeditor.MolViewer.molscale = 0.8;
56
- const app = new org.helm.webeditor.App(view, {
57
- showabout: false,
58
- mexfontsize: '90%',
59
- mexrnapinontab: true,
60
- topmargin: 20,
61
- mexmonomerstab: true,
62
- sequenceviewonly: false,
63
- mexfavoritefirst: true,
64
- mexfilter: true
65
- });
66
- const sizes = app.calculateSizes();
67
- app.canvas!.resize(sizes.rightwidth - 100, sizes.topheight - 210);
68
- let s = {width: sizes.rightwidth - 100 + 'px', height: sizes.bottomheight + 'px'};
69
- scil.apply(app.sequence.style, s);
70
- scil.apply(app.notation!.style, s);
71
- s = {width: sizes.rightwidth + 'px', height: (sizes.bottomheight + app.toolbarheight) + 'px'};
72
- scil.apply(app.properties!.parent.style, s);
73
- app.structureview!.resize(sizes.rightwidth, sizes.bottomheight + app.toolbarheight);
74
- app.mex!.resize(sizes.topheight - 80);
75
-
76
- return app;
77
- }
@@ -5,6 +5,7 @@ import * as DG from 'datagrok-api/dg';
5
5
  import {Unsubscribable} from 'rxjs';
6
6
 
7
7
  import {delay, timeout} from '@datagrok-libraries/utils/src/test';
8
+ import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
8
9
  import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
9
10
  import {
10
11
  DojoType, DojoxType, HweWindow, IOrgHelmWebEditor, Monomers
@@ -13,7 +14,6 @@ import {HelmServiceBase} from '@datagrok-libraries/bio/src/viewers/helm-service'
13
14
  import {IMonomerLib} from '@datagrok-libraries/bio/src/types';
14
15
  import {LoggerWrapper} from '@datagrok-libraries/bio/src/utils/logger';
15
16
  import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
16
- import {errorToConsole} from '@datagrok-libraries/utils/src/to-console';
17
17
 
18
18
  import {HelmHelper} from './helm-helper';
19
19
  import {HelmService} from './utils/helm-service';
@@ -31,7 +31,7 @@ type DojoConfigWindowType = {
31
31
  dojoConfig: {
32
32
  packages?: (string | { name: string, location: string })[],
33
33
  deps?: string[], callback: Function, has?: any, parseOnLoad?: boolean, async?: boolean | string, locale?: string,
34
- };
34
+ },
35
35
  };
36
36
  type HelmWindowType = {
37
37
  $helmService?: HelmServiceBase,
@@ -51,7 +51,6 @@ export async function initHelmLoadAndPatchDojo(): Promise<void> {
51
51
  /** get the text width in pixels */
52
52
  const pi = DG.TaskBarProgressIndicator.create('Loading Helm Web Editor ...');
53
53
  try {
54
- await delay(2000);
55
54
  const requireBackup = window.require;
56
55
 
57
56
  // dojo.window','dojo.io.script','dojo.io.iframe','dojo.dom','dojox.gfx','dojox.gfx.svg','dojox.gfx.shape','dojox.charting'
@@ -107,9 +106,7 @@ export async function initHelmLoadAndPatchDojo(): Promise<void> {
107
106
  'dijit/form/DropDownButton', 'dijit/layout/AccordionContainer', 'dijit/form/ComboButton',
108
107
  'dijit/layout/StackController', 'dijit/layout/StackContainer',
109
108
  ],
110
- (...args: any[]) => {
111
- resolve();
112
- });
109
+ (...args: any[]) => { resolve(); });
113
110
  });
114
111
  } finally {
115
112
  // TODO: Check interference with NGL
@@ -180,9 +177,9 @@ export const helmJsonReplacer = (key: string, value: any): any => {
180
177
  };
181
178
 
182
179
  export class HelmPackage extends DG.Package {
183
- public alertOriginal: (s: string) => void;
180
+ public alertOriginal: ((s: string) => void) | null = null;
184
181
  public readonly helmHelper: HelmHelper;
185
- public libHelper: IMonomerLibHelper;
182
+ public libHelper!: IMonomerLibHelper;
186
183
 
187
184
  constructor(opts: { debug: boolean } = {debug: false}) {
188
185
  super();
@@ -234,7 +231,7 @@ export class HelmPackage extends DG.Package {
234
231
 
235
232
  this.logger.debug(`${logPrefix}, this.getMonomerOriginal stored`);
236
233
 
237
- this.helmHelper.overrideGetMonomer(this.helmHelper.buildGetMonomerFromLib(this.monomerLib));
234
+ this.helmHelper.overrideMonomersFuncs(this.helmHelper.buildMonomersFuncsFromLib(this.monomerLib));
238
235
 
239
236
  // @ts-ignore, intercept with proxy to observe access and usage
240
237
  org.helm.webeditor.Monomers = new class {
@@ -281,20 +278,15 @@ export class HelmPackage extends DG.Package {
281
278
  public get monomerLib(): IMonomerLib {
282
279
  if (!this.libHelper)
283
280
  throw new Error(`Helm: _package.libHelper is not initialized yet`);
284
- return this.libHelper.getBioLib();
281
+ return this.libHelper.getMonomerLib();
285
282
  }
286
283
 
287
- private _monomerLibSub: Unsubscribable;
288
-
289
- async initMonomerLibHelper(): Promise<void> {
290
- if (!!this.libHelper)
291
- throw new Error(`Helm: _package.libHelper is initialized already`);
292
-
293
- this.libHelper = await getMonomerLibHelper();
294
- }
284
+ private _monomerLibSub?: Unsubscribable;
295
285
 
296
286
  /** Requires both Bio & HELMWebEditor initialized */
297
- async initMonomerLib(): Promise<void> {
287
+ initMonomerLib(libHelper: IMonomerLibHelper): void {
288
+ this.libHelper = libHelper;
289
+
298
290
  const lib = this.monomerLib;
299
291
  rewriteLibraries(lib); // initHelm()
300
292
  this._monomerLibSub = lib.onChanged
@@ -306,7 +298,7 @@ export class HelmPackage extends DG.Package {
306
298
  monomerLibOnChangedHandler(): void {
307
299
  const logPrefix = `Helm: _package.monomerLibOnChangedHandler()`;
308
300
  try {
309
- const libSummary = this.monomerLib.getSummaryObj();
301
+ const libSummary = this.monomerLib!.getSummaryObj();
310
302
  const isLibEmpty = Object.keys(libSummary).length == 0;
311
303
  const libSummaryLog = isLibEmpty ? 'empty' : Object.entries(libSummary)
312
304
  .map(([pt, count]) => `${pt}: ${count}`)