@trebco/treb 27.12.2 → 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.
- package/README.md +6 -0
- package/dist/treb-spreadsheet-light.mjs +16 -0
- package/dist/treb-spreadsheet.mjs +14 -12
- package/dist/treb.d.ts +31 -3
- package/esbuild-custom-element.mjs +3 -1
- package/package.json +4 -4
- package/treb-base-types/src/dom-utilities.ts +157 -19
- package/treb-base-types/src/theme.ts +5 -4
- package/treb-charts/src/renderer.ts +4 -58
- package/treb-embed/markup/layout.html +4 -0
- package/treb-embed/src/custom-element/spreadsheet-constructor.ts +131 -87
- package/treb-embed/src/embedded-spreadsheet.ts +146 -111
- package/treb-embed/src/options.ts +9 -0
- package/treb-embed/src/spinner.ts +5 -3
- package/treb-embed/src/toolbar-message.ts +5 -0
- package/treb-embed/style/layout.scss +65 -1
- package/treb-grid/src/editors/autocomplete.ts +24 -13
- package/treb-grid/src/editors/editor.ts +43 -139
- package/treb-grid/src/editors/external_editor.ts +1 -1
- package/treb-grid/src/editors/formula_bar.ts +24 -24
- package/treb-grid/src/editors/overlay_editor.ts +1 -1
- package/treb-grid/src/layout/base_layout.ts +34 -25
- package/treb-grid/src/layout/grid_layout.ts +20 -20
- package/treb-grid/src/render/selection-renderer.ts +3 -3
- package/treb-grid/src/render/svg_header_overlay.ts +6 -4
- package/treb-grid/src/render/svg_selection_block.ts +10 -7
- package/treb-grid/src/types/grid.ts +80 -81
- package/treb-grid/src/types/scale-control.ts +69 -81
- package/treb-grid/src/types/sheet.ts +3 -52
- package/treb-grid/src/types/tab_bar.ts +27 -13
- package/treb-grid/src/util/fontmetrics2.ts +24 -21
- package/treb-utils/src/event_source.ts +23 -23
- package/treb-utils/src/index.ts +2 -2
- package/treb-utils/src/measurement.ts +24 -24
- package/treb-utils/src/serialize_html.ts +25 -21
- package/treb-utils/src/dispatch.ts +0 -57
- package/treb-utils/src/resizable.ts +0 -159
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import {
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
this.
|
|
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,
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
62
|
-
this.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 =
|
|
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 {
|
|
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 {
|
|
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.
|
|
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
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
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
|
-
|
|
589
|
-
|
|
590
|
-
if (event.button !== 0) {
|
|
591
|
-
return;
|
|
592
|
-
}
|
|
584
|
+
mousedown: (event) => {
|
|
593
585
|
|
|
594
|
-
|
|
595
|
-
|
|
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
|
-
|
|
602
|
-
|
|
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
|
-
|
|
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
|
-
|
|
625
|
-
|
|
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
|
-
|
|
645
|
+
}
|
|
646
|
+
});
|
|
629
647
|
|
|
630
|
-
|
|
648
|
+
view.node = node;
|
|
631
649
|
|
|
632
|
-
|
|
633
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
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',
|
|
57
|
-
|
|
54
|
+
this.input = DOM.Create('input', 'treb-scale-input', container, {
|
|
55
|
+
events: {
|
|
58
56
|
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
-
|
|
71
|
+
keydown: (event) => {
|
|
86
72
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
break;
|
|
73
|
+
switch (event.key) {
|
|
74
|
+
case 'Enter':
|
|
75
|
+
this.input.blur();
|
|
76
|
+
break;
|
|
92
77
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
78
|
+
case 'ArrowUp':
|
|
79
|
+
this.Tick(-1);
|
|
80
|
+
break;
|
|
96
81
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
82
|
+
case 'ArrowDown':
|
|
83
|
+
this.Tick(1);
|
|
84
|
+
break;
|
|
100
85
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
86
|
+
case 'Escape':
|
|
87
|
+
this.input.value = this.format.Format(this.scale) + '%';
|
|
88
|
+
this.input.blur();
|
|
89
|
+
break;
|
|
105
90
|
|
|
106
|
-
|
|
107
|
-
|
|
91
|
+
default:
|
|
92
|
+
return;
|
|
108
93
|
|
|
109
|
-
|
|
94
|
+
}
|
|
110
95
|
|
|
111
|
-
|
|
112
|
-
|
|
96
|
+
event.stopPropagation();
|
|
97
|
+
event.preventDefault();
|
|
113
98
|
|
|
114
|
-
|
|
99
|
+
},
|
|
115
100
|
|
|
116
|
-
|
|
117
|
-
|
|
101
|
+
// select text on click
|
|
102
|
+
focusin: () => this.input.select(),
|
|
118
103
|
|
|
119
|
-
|
|
104
|
+
change: () => {
|
|
120
105
|
|
|
121
|
-
|
|
122
|
-
|
|
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
|
-
|
|
125
|
-
|
|
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
|
-
|
|
128
|
-
|
|
112
|
+
let text = this.input.value;
|
|
113
|
+
text = text.replace(/%/g, '');
|
|
129
114
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
|
|
141
|
-
type: 'range',
|
|
142
|
-
min: '50',
|
|
143
|
-
max: '200',
|
|
144
|
-
value: '100',
|
|
145
|
-
step: '2.5',
|
|
125
|
+
}
|
|
146
126
|
});
|
|
147
127
|
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
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,
|
|
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 =
|
|
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];
|