@trebco/treb 27.12.1 → 28.0.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.
Files changed (37) hide show
  1. package/README.md +6 -0
  2. package/dist/treb-spreadsheet-light.mjs +16 -0
  3. package/dist/treb-spreadsheet.mjs +14 -12
  4. package/dist/treb.d.ts +31 -3
  5. package/esbuild-custom-element.mjs +3 -1
  6. package/package.json +4 -4
  7. package/treb-base-types/src/dom-utilities.ts +157 -19
  8. package/treb-base-types/src/theme.ts +5 -4
  9. package/treb-charts/src/renderer.ts +4 -58
  10. package/treb-embed/markup/layout.html +4 -0
  11. package/treb-embed/src/custom-element/spreadsheet-constructor.ts +131 -87
  12. package/treb-embed/src/embedded-spreadsheet.ts +146 -111
  13. package/treb-embed/src/options.ts +9 -0
  14. package/treb-embed/src/spinner.ts +5 -3
  15. package/treb-embed/src/toolbar-message.ts +5 -0
  16. package/treb-embed/style/layout.scss +65 -1
  17. package/treb-grid/src/editors/autocomplete.ts +24 -13
  18. package/treb-grid/src/editors/editor.ts +43 -139
  19. package/treb-grid/src/editors/external_editor.ts +1 -1
  20. package/treb-grid/src/editors/formula_bar.ts +24 -24
  21. package/treb-grid/src/editors/overlay_editor.ts +6 -2
  22. package/treb-grid/src/layout/base_layout.ts +34 -25
  23. package/treb-grid/src/layout/grid_layout.ts +20 -20
  24. package/treb-grid/src/render/selection-renderer.ts +3 -3
  25. package/treb-grid/src/render/svg_header_overlay.ts +6 -4
  26. package/treb-grid/src/render/svg_selection_block.ts +10 -7
  27. package/treb-grid/src/types/grid.ts +80 -81
  28. package/treb-grid/src/types/scale-control.ts +69 -81
  29. package/treb-grid/src/types/sheet.ts +3 -52
  30. package/treb-grid/src/types/tab_bar.ts +27 -13
  31. package/treb-grid/src/util/fontmetrics2.ts +24 -21
  32. package/treb-utils/src/event_source.ts +23 -23
  33. package/treb-utils/src/index.ts +2 -2
  34. package/treb-utils/src/measurement.ts +24 -24
  35. package/treb-utils/src/serialize_html.ts +25 -21
  36. package/treb-utils/src/dispatch.ts +0 -57
  37. package/treb-utils/src/resizable.ts +0 -159
@@ -20,7 +20,7 @@
20
20
  */
21
21
 
22
22
  import type { Theme, ICellAddress } from 'treb-base-types';
23
- import { DOMUtilities, Rectangle } from 'treb-base-types';
23
+ import { DOMContext, Rectangle } from 'treb-base-types';
24
24
  import type { BaseLayout } from '../layout/base_layout';
25
25
  import type { SelectionOffset } from './svg_selection_block';
26
26
  import { SVGSelectionBlock } from './svg_selection_block';
@@ -289,7 +289,7 @@ export class SelectionRenderer {
289
289
 
290
290
  let selection_block: SVGSelectionBlock = node_set[index];
291
291
  if (!selection_block) {
292
- selection_block = new SVGSelectionBlock(!index, this.theme);
292
+ selection_block = new SVGSelectionBlock(!index, this.theme, undefined, node);
293
293
  node_set[index] = selection_block;
294
294
 
295
295
  if (index) {
@@ -302,7 +302,7 @@ export class SelectionRenderer {
302
302
 
303
303
  let group: SVGElement = node.querySelector('.alternate-selections') as SVGElement;
304
304
  if (!group) {
305
- group = DOMUtilities.SVG('g', 'alternate-selections');
305
+ group = this.layout.DOM.SVG('g', 'alternate-selections');
306
306
  node.appendChild(group);
307
307
  }
308
308
  group?.appendChild(selection_block.g);
@@ -19,7 +19,7 @@
19
19
  *
20
20
  */
21
21
 
22
- import { DOMUtilities, type Theme } from 'treb-base-types';
22
+ import { DOMContext, type Theme } from 'treb-base-types';
23
23
 
24
24
  export enum Orientation {
25
25
  Horizontal,
@@ -37,9 +37,11 @@ export class HeaderOverlay {
37
37
  private container: SVGElement,
38
38
  private orientation: Orientation) {
39
39
 
40
- this.g = DOMUtilities.SVG('g', 'treb-header-overlay');
41
- this.overlay = DOMUtilities.SVG('rect', 'treb-overlay');
42
- this.highlight = DOMUtilities.SVG('rect', 'treb-highlight');
40
+ const DOM = DOMContext.GetInstance(container.ownerDocument);
41
+
42
+ this.g = DOM.SVG('g', 'treb-header-overlay');
43
+ this.overlay = DOM.SVG('rect', 'treb-overlay');
44
+ this.highlight = DOM.SVG('rect', 'treb-highlight');
43
45
 
44
46
  this.g.style.display = 'none';
45
47
  this.g.appendChild(this.highlight);
@@ -19,7 +19,7 @@
19
19
  *
20
20
  */
21
21
 
22
- import { type Theme, type Rectangle, DOMUtilities } from 'treb-base-types';
22
+ import { type Theme, type Rectangle, DOMContext } from 'treb-base-types';
23
23
 
24
24
  /**
25
25
  * the original selections -- a canvas overlaid over the tile canvases --
@@ -44,12 +44,15 @@ export class SVGSelectionBlock {
44
44
 
45
45
  constructor( primary: boolean,
46
46
  private theme: Theme,
47
- private offset: SelectionOffset = {x: 0, y: 0}) {
47
+ private offset: SelectionOffset = {x: 0, y: 0},
48
+ node: SVGElement) {
48
49
 
49
- this.g = DOMUtilities.SVG('g');
50
+ const DOM = DOMContext.GetInstance(node.ownerDocument);
51
+
52
+ this.g = DOM.SVG('g');
50
53
  this.g.setAttribute('transform', `translate(${offset.x}, ${offset.y})`);
51
54
 
52
- this.outline = DOMUtilities.SVG('rect', 'outline');
55
+ this.outline = DOM.SVG('rect', 'outline');
53
56
 
54
57
  if (primary) {
55
58
 
@@ -58,8 +61,8 @@ export class SVGSelectionBlock {
58
61
  // primary selections have a separate fill, plus the nub. separate
59
62
  // fill because the "target" is unfilled.
60
63
 
61
- this.fill = DOMUtilities.SVG('path', 'fill');
62
- this.nub = DOMUtilities.SVG('rect', 'nub');
64
+ this.fill = DOM.SVG('path', 'fill');
65
+ this.nub = DOM.SVG('rect', 'nub');
63
66
 
64
67
  this.g.appendChild(this.fill);
65
68
  this.g.appendChild(this.outline);
@@ -75,7 +78,7 @@ export class SVGSelectionBlock {
75
78
  // and use currentColor, but we can't set opacity separately so we
76
79
  // need another node. which is a waste, but ergonomics ftw!
77
80
 
78
- this.fill = DOMUtilities.SVG('rect', 'fill');
81
+ this.fill = DOM.SVG('rect', 'fill');
79
82
 
80
83
  // this.SetThemeColor(0);
81
84
  // if (theme.additional_selection_line_dash_array) {
@@ -58,7 +58,7 @@ import {
58
58
  MDParser,
59
59
  } from 'treb-parser';
60
60
 
61
- import { Yield, SerializeHTML } from 'treb-utils';
61
+ import { SerializeHTML } from 'treb-utils';
62
62
  import type { ParseResult as ParseResult2 } from 'treb-format';
63
63
  import { NumberFormatCache, LotusDate, ValueParser, type Hints, NumberFormat } from 'treb-format';
64
64
  import { SelectionRenderer } from '../render/selection-renderer';
@@ -111,7 +111,7 @@ import { CommandKey
111
111
 
112
112
  import type { DataModel, SerializedModel } from './data_model';
113
113
 
114
- import { DOMUtilities } from 'treb-base-types';
114
+ import { DOMContext } from 'treb-base-types';
115
115
  import { GridBase } from './grid_base';
116
116
  import type { SetRangeOptions } from './set_range_options';
117
117
  import type { ClipboardCellData } from './clipboard_data';
@@ -360,6 +360,8 @@ export class Grid extends GridBase {
360
360
 
361
361
  private tab_bar?: TabBar;
362
362
 
363
+ private DOM = DOMContext.GetInstance();
364
+
363
365
  // --- constructor -----------------------------------------------------------
364
366
 
365
367
  /**
@@ -369,7 +371,8 @@ export class Grid extends GridBase {
369
371
  options: GridOptions = {},
370
372
  model: DataModel,
371
373
  theme: Theme = DefaultTheme,
372
- initialze_dom = true ) {
374
+ initialze_dom = true,
375
+ DOM: DOMContext ) {
373
376
 
374
377
  super(options, model);
375
378
 
@@ -385,7 +388,8 @@ export class Grid extends GridBase {
385
388
  return;
386
389
  }
387
390
 
388
- this.layout = new GridLayout(this.model, this.view);
391
+ this.DOM = DOM;
392
+ this.layout = new GridLayout(this.model, this.view, DOM);
389
393
 
390
394
  if (options.initial_scale) {
391
395
  if (typeof options.initial_scale === 'string') {
@@ -571,84 +575,83 @@ export class Grid extends GridBase {
571
575
 
572
576
  // FIXME: why is this not in layout? it is layout.
573
577
 
574
- view.node = DOMUtilities.Div();
575
- view.node.dataset.scale = this.layout.scale.toString();
576
- view.node.style.fontSize = `${10 * this.layout.scale}pt`;
577
-
578
- view.content_node = DOMUtilities.Div('annotation-content', view.node);
579
- const move_target = DOMUtilities.Div('annotation-move-target', view.node);
580
- const resize_target = DOMUtilities.Div('annotation-resize-target', view.node);
581
-
582
- if (view.node) {
583
- const node = view.node;
584
-
585
- // support focus
586
- node.setAttribute('tabindex', '-1');
578
+ const node = this.DOM.Div('annotation', undefined, {
579
+ data: { scale: this.layout.scale.toString() },
580
+ style: { fontSize: `${10 * this.layout.scale}pt` },
581
+ attrs: { tabindex: '-1', },
582
+ events: {
587
583
 
588
- node.addEventListener('mousedown', (event) => {
589
-
590
- if (event.button !== 0) {
591
- return;
592
- }
584
+ mousedown: (event) => {
593
585
 
594
- // this.AnnotationMouseDown(annotation, event, move_target, resize_target);
595
- this.layout.AnnotationMouseDown(annotation, node, event, move_target, resize_target).then(event => {
596
- // console.info('resolved', event);
597
- if (event) {
598
- this.grid_events.Publish(event);
586
+ if (event.button !== 0) {
587
+ return;
599
588
  }
589
+
590
+ this.layout.AnnotationMouseDown(annotation, node, event, move_target, resize_target).then(event => {
591
+ // console.info('resolved', event);
592
+ if (event) {
593
+ this.grid_events.Publish(event);
594
+ }
595
+
596
+ if (annotation.data.layout) {
597
+ this.EnsureAddress(annotation.data.layout.br.address, 1);
598
+ }
599
+
600
+ });
601
+ },
600
602
 
601
- if (annotation.data.layout) {
602
- this.EnsureAddress(annotation.data.layout.br.address, 1);
603
+ focusin: () => {
604
+
605
+ for (const element of this.layout.GetFrozenAnnotations(annotation)) {
606
+ element.classList.add('clone-focus');
603
607
  }
608
+
609
+ this.selected_annotation = annotation;
610
+ this.primary_selection.empty = true; // FIXME: not using method? (...)
611
+
612
+ // this is done for the side-effect when we start editing, we
613
+ // capture the sheet of the primary selection. if you switch
614
+ // sheets while editing, the selection won't be set so it persists.
615
+ // we need that to switch back to the correct sheet when an edit ends.
616
+
617
+ this.primary_selection.target = { row: -1, column: -1, sheet_id: this.active_sheet.id };
618
+ this.HideGridSelection();
604
619
 
605
- });
606
- });
607
-
608
- node.addEventListener('focusin', () => {
609
-
610
- // console.info('annotation focusin', annotation);
611
-
612
- for (const element of this.layout.GetFrozenAnnotations(annotation)) {
613
- element.classList.add('clone-focus');
614
- }
615
-
616
- this.selected_annotation = annotation;
617
- this.primary_selection.empty = true; // FIXME: not using method? (...)
620
+ },
618
621
 
619
- // this is done for the side-effect when we start editing, we
620
- // capture the sheet of the primary selection. if you switch
621
- // sheets while editing, the selection won't be set so it persists.
622
- // we need that to switch back to the correct sheet when an edit ends.
622
+ focusout: (event) => {
623
623
 
624
- this.primary_selection.target = { row: -1, column: -1, sheet_id: this.active_sheet.id };
625
- this.HideGridSelection();
626
- });
624
+ // console.info('annotation focusout', annotation);
625
+
626
+ for (const element of this.layout.GetFrozenAnnotations(annotation)) {
627
+ element.classList.remove('clone-focus');
628
+ }
629
+
630
+ if (this.formula_bar && this.formula_bar.IsElement((event as FocusEvent).relatedTarget as HTMLElement)) {
631
+ // console.info('editing...');
632
+ this.primary_selection.empty = true;
633
+ this.RenderSelections();
634
+ this.editing_annotation = annotation;
635
+ this.layout.ShowSelections(true);
636
+ }
637
+ else {
638
+ if (this.selected_annotation === annotation) {
639
+ this.selected_annotation = undefined;
640
+ }
641
+ this.ShowGridSelection();
642
+ }
643
+ },
627
644
 
628
- node.addEventListener('focusout', (event) => {
645
+ }
646
+ });
629
647
 
630
- // console.info('annotation focusout', annotation);
648
+ view.node = node;
631
649
 
632
- for (const element of this.layout.GetFrozenAnnotations(annotation)) {
633
- element.classList.remove('clone-focus');
634
- }
635
-
636
- if (this.formula_bar && this.formula_bar.IsElement((event as FocusEvent).relatedTarget as HTMLElement)) {
637
- // console.info('editing...');
638
- this.primary_selection.empty = true;
639
- this.RenderSelections();
640
- this.editing_annotation = annotation;
641
- this.layout.ShowSelections(true);
642
- }
643
- else {
644
- if (this.selected_annotation === annotation) {
645
- this.selected_annotation = undefined;
646
- }
647
- this.ShowGridSelection();
648
- }
649
- });
650
+ view.content_node = this.DOM.Div('annotation-content', node);
651
+ const move_target = this.DOM.Div('annotation-move-target', node);
652
+ const resize_target = this.DOM.Div('annotation-resize-target', node);
650
653
 
651
- node.addEventListener('keydown', (event) => {
654
+ node.addEventListener('keydown', (event) => {
652
655
 
653
656
  const rect = annotation.scaled_rect;
654
657
  if (!rect) {
@@ -748,14 +751,8 @@ export class Grid extends GridBase {
748
751
  }
749
752
 
750
753
  });
751
- }
752
- }
753
754
 
754
- view.node.classList.add('annotation');
755
-
756
- // if (annotation.class_name) {
757
- // annotation.node.classList.add(annotation.class_name);
758
- // }
755
+ }
759
756
 
760
757
  if (add_to_layout) {
761
758
  this.layout.AddAnnotation(annotation);
@@ -2413,7 +2410,7 @@ export class Grid extends GridBase {
2413
2410
  */
2414
2411
  private ActivateSheetTasks() {
2415
2412
 
2416
- this.active_sheet.Activate();
2413
+ this.active_sheet.Activate(this.DOM);
2417
2414
 
2418
2415
  if (this.active_sheet.image && !this.active_sheet.image.complete) {
2419
2416
 
@@ -2785,7 +2782,7 @@ export class Grid extends GridBase {
2785
2782
 
2786
2783
  if (!this.render_token) {
2787
2784
  this.render_token = 1;
2788
- Yield().then(() => {
2785
+ Promise.resolve().then(() => {
2789
2786
  this.render_token = 0;
2790
2787
  this.Repaint(force, full_tile);
2791
2788
  });
@@ -3846,7 +3843,7 @@ export class Grid extends GridBase {
3846
3843
  if (cell.hyperlink) {
3847
3844
  if (this.PointInTextPart(address, offset_point, cell)) {
3848
3845
  const link = cell.hyperlink;
3849
- Yield().then(() => {
3846
+ Promise.resolve().then(() => {
3850
3847
  this.grid_events.Publish({
3851
3848
  type: 'cell-event',
3852
3849
  data: {
@@ -4678,7 +4675,9 @@ export class Grid extends GridBase {
4678
4675
  // console.info('ek', event.key);
4679
4676
 
4680
4677
  if (!selection.empty) {
4681
- this.OverlayEditCell(selection, true, event);
4678
+ if (event.key !== 'Escape') {
4679
+ this.OverlayEditCell(selection, true, event);
4680
+ }
4682
4681
  }
4683
4682
 
4684
4683
  return;
@@ -19,14 +19,13 @@
19
19
  *
20
20
  */
21
21
 
22
- import { DOMUtilities as DOM } from 'treb-base-types';
22
+ import { DOMContext } from 'treb-base-types';
23
23
  import { NumberFormat, NumberFormatCache, ValueParser } from 'treb-format';
24
24
  import { ValueType } from 'treb-base-types';
25
25
  import { EventSource } from 'treb-utils';
26
26
 
27
27
  export interface ScaleEvent {
28
28
  type: 'scale';
29
- // action: 'increase'|'decrease'|number;
30
29
  value: number;
31
30
  keep_focus?: boolean;
32
31
  }
@@ -50,106 +49,98 @@ export class ScaleControl extends EventSource<ScaleEvent> {
50
49
 
51
50
  this.format = NumberFormatCache.Get('0.0');
52
51
 
53
- // not sure what this extra div was for, we don't need it
54
- // const div = DOM.CreateDiv('treb-scale-control-2', container);
52
+ const DOM = DOMContext.GetInstance(container.ownerDocument);
55
53
 
56
- this.input = DOM.Create('input', 'treb-scale-input', /* div */ container);
57
- const popup = DOM.Div('treb-slider-container', /* div */ container);
54
+ this.input = DOM.Create('input', 'treb-scale-input', container, {
55
+ events: {
58
56
 
59
- /*
60
- this.input.addEventListener('keyup', (event) => {
61
- switch (event.key) {
62
- case 'ArrowUp':
63
- case 'ArrowDown':
64
- event.stopPropagation();
65
- event.preventDefault();
66
- break;
67
- }
68
- });
69
- */
70
-
71
- // is this for some x-browser issue? or did we just not
72
- // know which event to use and this is old junk?
57
+ // is this for some x-browser issue? or did we just not
58
+ // know which event to use and this is old junk?
73
59
 
74
- this.input.addEventListener('keypress', (event) => {
75
- switch (event.key) {
76
- case 'ArrowUp':
77
- case 'ArrowDown':
78
- event.stopPropagation();
79
- event.preventDefault();
80
- console.info('mark?');
81
- break;
82
- }
83
- })
60
+ keypress: (event) => {
61
+ switch (event.key) {
62
+ case 'ArrowUp':
63
+ case 'ArrowDown':
64
+ event.stopPropagation();
65
+ event.preventDefault();
66
+ console.info('mark?');
67
+ break;
68
+ }
69
+ },
84
70
 
85
- // this is the one we want
71
+ keydown: (event) => {
86
72
 
87
- this.input.addEventListener('keydown', (event) => {
88
- switch (event.key) {
89
- case 'Enter':
90
- this.input.blur();
91
- break;
73
+ switch (event.key) {
74
+ case 'Enter':
75
+ this.input.blur();
76
+ break;
92
77
 
93
- case 'ArrowUp':
94
- this.Tick(-1);
95
- break;
78
+ case 'ArrowUp':
79
+ this.Tick(-1);
80
+ break;
96
81
 
97
- case 'ArrowDown':
98
- this.Tick(1);
99
- break;
82
+ case 'ArrowDown':
83
+ this.Tick(1);
84
+ break;
100
85
 
101
- case 'Escape':
102
- this.input.value = this.format.Format(this.scale) + '%';
103
- this.input.blur();
104
- break;
86
+ case 'Escape':
87
+ this.input.value = this.format.Format(this.scale) + '%';
88
+ this.input.blur();
89
+ break;
105
90
 
106
- default:
107
- return;
91
+ default:
92
+ return;
108
93
 
109
- }
94
+ }
110
95
 
111
- event.stopPropagation();
112
- event.preventDefault();
96
+ event.stopPropagation();
97
+ event.preventDefault();
113
98
 
114
- });
99
+ },
115
100
 
116
- // select text on click
117
- this.input.addEventListener('focusin', () => this.input.select());
101
+ // select text on click
102
+ focusin: () => this.input.select(),
118
103
 
119
- this.input.addEventListener('change', () => {
104
+ change: () => {
120
105
 
121
- // what we're doing here is a little unusual. we always treat
122
- // the value as a percent, even if there's no percent sign.
106
+ // what we're doing here is a little unusual. we always treat
107
+ // the value as a percent, even if there's no percent sign.
123
108
 
124
- // for that to work, if there is a percent sign, we need to remove
125
- // it before we continue. then try to parse as a number.
109
+ // for that to work, if there is a percent sign, we need to remove
110
+ // it before we continue. then try to parse as a number.
126
111
 
127
- let text = this.input.value;
128
- text = text.replace(/%/g, '');
112
+ let text = this.input.value;
113
+ text = text.replace(/%/g, '');
129
114
 
130
- const value = ValueParser.TryParse(text);
131
- if (value.type === ValueType.number) {
132
- this.UpdateScale(Number(value.value), true);
133
- }
134
- else {
135
- this.input.value = this.format.Format(this.scale) + '%';
136
- }
115
+ const value = ValueParser.TryParse(text);
116
+ if (value.type === ValueType.number) {
117
+ this.UpdateScale(Number(value.value), true);
118
+ }
119
+ else {
120
+ this.input.value = this.format.Format(this.scale) + '%';
121
+ }
137
122
 
138
- });
123
+ },
139
124
 
140
- this.slider = DOM.Create('input', undefined, popup, undefined, {
141
- type: 'range',
142
- min: '50',
143
- max: '200',
144
- value: '100',
145
- step: '2.5',
125
+ }
146
126
  });
147
127
 
148
- this.slider.addEventListener('input', () => {
149
- this.UpdateScale(Number(this.slider.value), true);
128
+ const popup = DOM.Div('treb-slider-container', container);
129
+
130
+ this.slider = DOM.Create('input', undefined, popup, {
131
+ attrs: {
132
+ type: 'range',
133
+ min: '50',
134
+ max: '200',
135
+ value: '100',
136
+ step: '2.5',
137
+ },
138
+ events: {
139
+ input: () => this.UpdateScale(Number(this.slider.value), true),
140
+ }
150
141
  });
151
142
 
152
- /* div */ container.addEventListener('wheel', (event: WheelEvent) => {
143
+ container.addEventListener('wheel', (event: WheelEvent) => {
153
144
  event.stopPropagation();
154
145
  event.preventDefault();
155
146
  this.Tick(event.deltaY)
@@ -159,9 +150,6 @@ export class ScaleControl extends EventSource<ScaleEvent> {
159
150
 
160
151
  public Tick(value: number): void {
161
152
 
162
- // not sure what alternate case I am worried about here,
163
- // sideways wheel? shift key?
164
-
165
153
  // normalize
166
154
 
167
155
  const scale = Math.round(this.scale / 2.5) * 2.5;
@@ -26,7 +26,7 @@ import { ValueType, Cells, Style,
26
26
  type PropertyKeys,
27
27
  type Color,
28
28
  Area, IsFlatDataArray,
29
- IsNestedRowArray, IsCellAddress, DOMUtilities
29
+ IsNestedRowArray, IsCellAddress, DOMContext
30
30
  } from 'treb-base-types';
31
31
  import { NumberFormatCache } from 'treb-format';
32
32
  import { Measurement, ValidateURI } from 'treb-utils';
@@ -741,14 +741,14 @@ export class Sheet {
741
741
  }
742
742
 
743
743
 
744
- public Activate() {
744
+ public Activate(DOM: DOMContext) {
745
745
 
746
746
  // load background image, if set
747
747
 
748
748
  if (this.background_image) {
749
749
  const resource = ValidateURI(this.background_image);
750
750
  if (resource) {
751
- this._image = DOMUtilities.Create('img');
751
+ this._image = DOM.Create('img');
752
752
  this._image.src = resource;
753
753
  }
754
754
 
@@ -1592,55 +1592,6 @@ export class Sheet {
1592
1592
 
1593
1593
  }
1594
1594
 
1595
- /* *
1596
- * auto-sizes the column, but if the allow_shrink parameter is not set
1597
- * it will only enlarge, never shrink the column.
1598
- *
1599
- * UPDATE: since the only caller calls with inline = true, removing
1600
- * parameter, test, and extra behavior.
1601
- *
1602
- * UPDATE: moving to grid, for reasons of canvas...
1603
- * /
1604
- public AutoSizeColumn(column: number, allow_shrink = true): void {
1605
-
1606
- if (!Sheet.measurement_canvas) {
1607
- Sheet.measurement_canvas = document.createElement('canvas');
1608
- }
1609
- Sheet.measurement_canvas.style.font = Style.Font(this.default_style_properties);
1610
- console.info("SMC", Sheet.measurement_canvas.style.font);
1611
- (self as any).SMC = Sheet.measurement_canvas;
1612
-
1613
- document
1614
-
1615
- const context = Sheet.measurement_canvas.getContext('2d');
1616
- if (!context) return;
1617
-
1618
- let width = 12;
1619
- const padding = 4 * 2; // FIXME: parameterize
1620
-
1621
- if (!allow_shrink) width = this.GetColumnWidth(column);
1622
-
1623
- for (let row = 0; row < this.cells.rows; row++) {
1624
- const cell = this.CellData({ row, column });
1625
- let text = cell.formatted || '';
1626
- if (typeof text !== 'string') {
1627
- text = text.map((part) => part.text).join('');
1628
- }
1629
-
1630
- if (text && text.length) {
1631
- context.font = Style.Font(cell.style || {});
1632
-
1633
- console.info({text, style: Style.Font(cell.style||{}), cf: context.font});
1634
-
1635
- width = Math.max(width, Math.ceil(context.measureText(text).width) + padding);
1636
- }
1637
- }
1638
-
1639
- this.SetColumnWidth(column, width);
1640
-
1641
- }
1642
- */
1643
-
1644
1595
  /** returns the style properties for a given style index */
1645
1596
  public GetStyle(index: number): CellStyle {
1646
1597
  return this.style_map[index];