@datagrok/helm 2.5.3 → 2.5.5

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.
@@ -8,22 +8,24 @@ import {HelmType, ISeqMonomer, Mol} from '@datagrok-libraries/bio/src/helm/types
8
8
  import {
9
9
  CellRendererBackAsyncBase, RenderServiceBase
10
10
  } from '@datagrok-libraries/bio/src/utils/cell-renderer-async-base';
11
- import {HelmAux, HelmProps} from '@datagrok-libraries/bio/src/viewers/helm-service';
12
- import {_getHelmService} from '../package-utils';
11
+ import {HelmAux, HelmProps, HelmServiceBase} from '@datagrok-libraries/bio/src/viewers/helm-service';
13
12
  import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
14
13
  import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
15
14
  import {getGridCellColTemp} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
16
- import {IMonomerLib} from '@datagrok-libraries/bio/src/types/index';
15
+ import {getMonomerLibHelper} from '@datagrok-libraries/bio/src/monomer-works/monomer-utils';
16
+ import {IMonomerLibBase} from '@datagrok-libraries/bio/src/types/index';
17
17
  import {execMonomerHoverLinks} from '@datagrok-libraries/bio/src/monomer-works/monomer-hover';
18
+ import {MmcrTemps} from '@datagrok-libraries/bio/src/utils/cell-renderer-consts';
18
19
 
19
20
  import {getHoveredMonomerFromEditorMol, getSeqMonomerFromHelmAtom} from './get-hovered';
20
21
 
21
- import {_package} from '../package';
22
+ import {_package, getHelmService} from '../package';
22
23
 
23
24
  export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProps, HelmAux> {
24
25
  private _auxList: (HelmAux | null)[];
25
26
 
26
- private monomerLib: IMonomerLib | null = null;
27
+ private sysMonomerLib: IMonomerLibBase | null = null;
28
+ private helmRenderService: HelmServiceBase | null = null;
27
29
 
28
30
  // eslint-disable-next-line max-len
29
31
  private readonly uuid: string = wu.repeat(1).map(() => Math.floor((Math.random() * 36)).toString(36)).take(4).toArray().join('');
@@ -35,23 +37,48 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
35
37
  super(gridCol, tableCol, _package.logger, true);
36
38
  }
37
39
 
40
+ public async init(): Promise<void> {
41
+ await Promise.all([
42
+ (async () => {
43
+ const libHelper = await getMonomerLibHelper();
44
+ this.sysMonomerLib = libHelper.getMonomerLib();
45
+ })(),
46
+ (async () => {
47
+ this.helmRenderService = await getHelmService();
48
+ })(),
49
+ ]);
50
+
51
+ this.subs.push(this.sysMonomerLib!.onChanged.subscribe(() => {
52
+ this.dirty = true;
53
+ this.invalidateGrid();
54
+ }));
55
+
56
+ this.dirty = true;
57
+ this.invalidateGrid();
58
+ }
59
+
60
+ protected getMonomerLib(): IMonomerLibBase {
61
+ return this.tableCol.temp[MmcrTemps.overriddenLibrary] ?? this.sysMonomerLib;
62
+ }
63
+
38
64
  protected override reset(): void {
39
65
  const logPrefix = `${this.toLog()}.reset()`;
40
66
  this.logger.debug(`${logPrefix}, start`);
41
67
  super.reset();
42
68
  this._auxList = new Array<HelmAux | null>(this.tableCol.length).fill(null);
43
- if (this.gridCol && this.gridCol.dart) this.gridCol.grid?.invalidate();
69
+ this.invalidateGrid();
44
70
  this.logger.debug(`${logPrefix}, end`);
45
71
  }
46
72
 
47
- protected override getRenderService(): RenderServiceBase<HelmProps, HelmAux> {
48
- return _getHelmService();
73
+ protected override getRenderService(): RenderServiceBase<HelmProps, HelmAux> | null {
74
+ return this.helmRenderService;
49
75
  }
50
76
 
51
77
  protected override getRenderTaskProps(
52
78
  gridCell: DG.GridCell, backColor: number, width: number, height: number,
53
79
  ): HelmProps {
54
- return new HelmProps(gridCell.cell.value, backColor, width, height);
80
+ const monomerLib = this.getMonomerLib();
81
+ return new HelmProps(gridCell.cell.value, monomerLib, backColor, width, height);
55
82
  }
56
83
 
57
84
  protected override storeAux(gridCell: DG.GridCell, aux: HelmAux): void {
@@ -133,7 +160,7 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
133
160
  let seqMonomer: ISeqMonomer | null = null;
134
161
  if (hoveredAtom) {
135
162
  seqMonomer = getSeqMonomerFromHelmAtom(hoveredAtom);
136
- const monomerLib = _package.monomerLib;
163
+ const monomerLib = this.tableCol.temp[MmcrTemps.overriddenLibrary] ?? _package.monomerLib;
137
164
  const tooltipEl = monomerLib ? monomerLib.getTooltip(seqMonomer.biotype, seqMonomer.symbol) :
138
165
  ui.divText('Monomer library is not available');
139
166
  ui.tooltip.show(tooltipEl, e.x + 16, e.y + 16);
@@ -149,30 +176,23 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
149
176
  execMonomerHoverLinks(gridCell, null);
150
177
  }
151
178
 
152
- public override render(g: CanvasRenderingContext2D,
153
- x: number, y: number, w: number, h: number,
154
- gridCell: DG.GridCell, cellStyle: DG.GridCellStyle) {
155
- if (!this.monomerLib) {
156
- this.monomerLib = _package.monomerLib;
157
- if (this.monomerLib)
158
- this.subs.push(this.monomerLib.onChanged.subscribe(this.monomerLibOnChanged.bind(this)));
159
- }
160
- super.render(g, x, y, w, h, gridCell, cellStyle);
161
- }
179
+ // public override render(g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number,
180
+ // gridCell: DG.GridCell, cellStyle: DG.GridCellStyle
181
+ // ) {
182
+ // super.render(g, x, y, w, h, gridCell, cellStyle);
183
+ // }
162
184
 
163
185
  // -- Handle events --
164
186
 
165
- private monomerLibOnChanged(_value: any): void {
166
- this.dirty = true;
167
- this.invalidateGrid();
168
- }
169
-
170
187
  static getOrCreate(gridCell: DG.GridCell): HelmGridCellRendererBack {
171
188
  const [gridCol, tableCol, temp] =
172
189
  getGridCellColTemp<string, HelmGridCellRendererBack>(gridCell);
173
190
 
174
191
  let res: HelmGridCellRendererBack = temp.rendererBack;
175
- if (!res) res = temp.rendererBack = new HelmGridCellRendererBack(gridCol, tableCol);
192
+ if (!res) {
193
+ res = temp.rendererBack = new HelmGridCellRendererBack(gridCol, tableCol);
194
+ res.init().then(() => {});
195
+ }
176
196
  return res;
177
197
  }
178
198
  }
@@ -4,8 +4,9 @@ import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import $ from 'cash-dom';
6
6
  import {Subject, Unsubscribable} from 'rxjs';
7
+ import {LRUCache} from 'lru-cache';
7
8
 
8
- import {HelmEditor, HelmType, IHelmDrawOptions} from '@datagrok-libraries/bio/src/helm/types';
9
+ import {HelmEditor, HelmType, IHelmEditorOptions} from '@datagrok-libraries/bio/src/helm/types';
9
10
  import {RenderTask} from '@datagrok-libraries/bio/src/utils/cell-renderer-async-base';
10
11
  import {HelmAux, HelmProps, HelmServiceBase} from '@datagrok-libraries/bio/src/viewers/helm-service';
11
12
  import {svgToImage} from '@datagrok-libraries/utils/src/svg';
@@ -19,7 +20,9 @@ declare const JSDraw2: JSDraw2Module;
19
20
  export class HelmService extends HelmServiceBase {
20
21
  private readonly hostDiv: HTMLDivElement;
21
22
 
22
- private editor!: HelmEditor;
23
+ private readonly editorLruCache: LRUCache<string, HelmEditor>;
24
+
25
+ // private editor!: HelmEditor;
23
26
  private image: HTMLImageElement | null = null;
24
27
 
25
28
  constructor() {
@@ -34,27 +37,43 @@ export class HelmService extends HelmServiceBase {
34
37
  this.hostDiv.style.height = '0px';
35
38
  this.hostDiv.style.visibility = 'hidden';
36
39
  document.body.appendChild(this.hostDiv);
40
+
41
+ this.editorLruCache = new LRUCache<string, HelmEditor>({max: 20});
37
42
  }
38
43
 
39
44
  protected override toLog(): string {
40
45
  return `Helm: ${super.toLog()}`;
41
46
  }
42
47
 
48
+ private getEditor(props: HelmProps): HelmEditor {
49
+ const editorKey = props.monomerLib.source;
50
+
51
+ let resEditor: HelmEditor | undefined = this.editorLruCache.get(editorKey);
52
+ if (!resEditor) {
53
+ const getMonomerFuncs = _package.helmHelper.buildMonomersFuncsFromLib(props.monomerLib);
54
+ resEditor = new JSDraw2.Editor<HelmType, IHelmEditorOptions>(this.hostDiv, {
55
+ width: props.width, height: props.height, skin: 'w8', viewonly: true,
56
+ drawOptions: {getMonomer: getMonomerFuncs.getMonomer},
57
+ });
58
+ this.editorLruCache.set(editorKey, resEditor);
59
+ }
60
+ return resEditor;
61
+ }
62
+
43
63
  protected override async requestRender(
44
64
  key: keyof any | undefined, task: RenderTask<HelmProps, HelmAux>, renderHandler: (aux: HelmAux) => void
45
65
  ): Promise<[Unsubscribable, number, () => void]> {
46
66
  const logPrefix = `${this.toLog()}.requestRender()`;
47
67
  this.logger.debug(`${logPrefix}, start, ` + `key: ${key?.toString()}`);
48
68
  const emptyCanvasHash: number = 0;
69
+ const monomerLib = task.props.monomerLib;
70
+
71
+ const editor = this.getEditor(task.props);
49
72
 
50
- if (!this.editor) {
51
- this.editor = new JSDraw2.Editor<HelmType, IHelmDrawOptions>(this.hostDiv,
52
- {width: task.props.width, height: task.props.height, skin: 'w8', viewonly: true});
53
- }
54
73
  const lST = window.performance.now();
55
- this.editor.options.width = task.props.width;
56
- this.editor.options.height = task.props.height;
57
- this.editor.resize(task.props.width, task.props.height);
74
+ editor.options.width = task.props.width;
75
+ editor.options.height = task.props.height;
76
+ editor.resize(task.props.width, task.props.height);
58
77
  const helmStr = task.props.helm;
59
78
  if (helmStr) {
60
79
  // getMonomerOverrideAndLogAlert(
@@ -65,14 +84,14 @@ export class HelmService extends HelmServiceBase {
65
84
  // this.editor.setData(helmStr, 'helm');
66
85
  // }, this.logger);
67
86
  this.logger.debug(`${logPrefix}, editor.setData( '${helmStr}' )`);
68
- this.editor.setData(helmStr, 'helm');
87
+ editor.setData(helmStr, 'helm');
69
88
  }
70
89
  if (!helmStr)
71
- this.editor.reset();
90
+ editor.reset();
72
91
 
73
- const bBox = (this.editor.div.children[0] as SVGSVGElement).getBBox();
92
+ const bBox = (editor.div.children[0] as SVGSVGElement).getBBox();
74
93
  const aux: HelmAux = {
75
- mol: this.editor.m.clone(false),
94
+ mol: editor.m.clone(false),
76
95
  bBox: new DG.Rect(bBox.x, bBox.y, bBox.width + 2, bBox.height + 2) /* adjust for clipping right/bottom */,
77
96
  cBox: new DG.Rect(0, 0, task.props.width, task.props.height),
78
97
  };
@@ -7,7 +7,7 @@ import {fromEvent, Observable, Unsubscribable} from 'rxjs';
7
7
 
8
8
  import {IMonomerLibBase} from '@datagrok-libraries/bio/src/types/index';
9
9
  import {HelmInputBase, IHelmHelper, IHelmInputInitOptions} from '@datagrok-libraries/bio/src/helm/helm-helper';
10
- import {HelmAtom, HelmMol, HelmString, IHelmWebEditor} from '@datagrok-libraries/bio/src/helm/types';
10
+ import {HelmAtom, HelmMol, HelmString, IHelmEditorOptions, IHelmWebEditor} from '@datagrok-libraries/bio/src/helm/types';
11
11
 
12
12
  import {defaultErrorHandler} from '../utils/err-info';
13
13
  import {getHoveredMonomerFromEditorMol, getSeqMonomerFromHelmAtom} from '../utils/get-hovered';
@@ -86,7 +86,7 @@ export class HelmInput extends HelmInputBase {
86
86
  style: {width: '100%', height: '100%', overflow: 'hidden'},
87
87
  });
88
88
  this.viewer = this.helmHelper.createHelmWebEditor(this.viewerHost, {
89
- monomerNumbering: MonomerNumberingTypes.continuous
89
+ drawOptions: {monomerNumbering: MonomerNumberingTypes.continuous},
90
90
  });
91
91
 
92
92
  this.editHintDiv = ui.divH([
@@ -4,12 +4,14 @@ import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import $ from 'cash-dom';
6
6
 
7
- import {SeqHandler} from '@datagrok-libraries/bio/src/utils/seq-handler';
7
+ import {ISeqHandler} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
8
8
  import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
9
9
 
10
10
  import {JSDraw2Module} from '../types';
11
11
  import {removeGapsFromHelm} from '../utils';
12
12
 
13
+ import {_package} from '../package';
14
+
13
15
  declare const JSDraw2: JSDraw2Module;
14
16
 
15
17
  export class SeqPropertiesError extends Error {
@@ -18,7 +20,7 @@ export class SeqPropertiesError extends Error {
18
20
  }
19
21
  }
20
22
 
21
- export function getPropertiesDict(seq: string, sh: SeqHandler): {} {
23
+ export function getPropertiesDict(seq: string, sh: ISeqHandler): {} {
22
24
  const host = ui.div([], {style: {width: '0', height: '0'}});
23
25
  document.documentElement.appendChild(host);
24
26
  try {
@@ -48,7 +50,7 @@ export function getPropertiesDict(seq: string, sh: SeqHandler): {} {
48
50
 
49
51
 
50
52
  export function getPropertiesWidget(value: DG.SemanticValue<string>): DG.Widget {
51
- const sh = SeqHandler.forColumn(value.cell.column as DG.Column<string>);
53
+ const sh = _package.seqHelper.getSeqHandler(value.cell.column as DG.Column<string>);
52
54
  try {
53
55
  const propDict = getPropertiesDict(value.value, sh);
54
56
  return new DG.Widget(