@trebco/treb 30.16.0 → 31.0.2

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 (47) hide show
  1. package/api-generator/api-generator.ts +3 -1
  2. package/api-generator/package.json +2 -1
  3. package/dist/treb-export-worker.mjs +2 -2
  4. package/dist/treb-spreadsheet.mjs +13 -13
  5. package/dist/treb.d.ts +19 -2
  6. package/package.json +8 -7
  7. package/treb-base-types/src/font-stack.ts +144 -0
  8. package/treb-base-types/src/style.ts +121 -11
  9. package/treb-base-types/src/theme.ts +53 -8
  10. package/treb-calculator/src/calculator.ts +13 -13
  11. package/treb-calculator/src/descriptors.ts +12 -4
  12. package/treb-calculator/src/expression-calculator.ts +17 -4
  13. package/treb-calculator/src/functions/base-functions.ts +57 -4
  14. package/treb-calculator/src/functions/statistics-functions.ts +9 -6
  15. package/treb-calculator/tsconfig.json +11 -0
  16. package/treb-charts/style/charts.scss +7 -1
  17. package/treb-data-model/src/annotation.ts +6 -0
  18. package/treb-data-model/src/data_model.ts +14 -3
  19. package/treb-data-model/src/sheet.ts +57 -56
  20. package/treb-embed/markup/toolbar.html +15 -1
  21. package/treb-embed/src/custom-element/spreadsheet-constructor.ts +38 -0
  22. package/treb-embed/src/embedded-spreadsheet.ts +119 -29
  23. package/treb-embed/src/options.ts +3 -0
  24. package/treb-embed/src/selection-state.ts +1 -0
  25. package/treb-embed/src/toolbar-message.ts +6 -0
  26. package/treb-embed/src/types.ts +9 -0
  27. package/treb-embed/style/defaults.scss +12 -1
  28. package/treb-embed/style/font-stacks.scss +105 -0
  29. package/treb-embed/style/layout.scss +1 -0
  30. package/treb-embed/style/theme-defaults.scss +12 -2
  31. package/treb-embed/style/toolbar.scss +16 -0
  32. package/treb-grid/src/editors/overlay_editor.ts +36 -3
  33. package/treb-grid/src/layout/base_layout.ts +52 -37
  34. package/treb-grid/src/layout/grid_layout.ts +7 -0
  35. package/treb-grid/src/render/tile_renderer.ts +154 -148
  36. package/treb-grid/src/types/grid.ts +188 -54
  37. package/treb-grid/src/types/grid_events.ts +1 -1
  38. package/treb-grid/src/types/grid_options.ts +3 -0
  39. package/treb-grid/src/util/fontmetrics.ts +134 -0
  40. package/treb-parser/src/parser.ts +12 -3
  41. package/treb-utils/src/measurement.ts +2 -3
  42. package/tsproject.json +1 -1
  43. package/treb-calculator/modern.tsconfig.json +0 -11
  44. package/treb-grid/src/util/fontmetrics2.ts +0 -182
  45. package/treb-parser/src/parser.test.ts +0 -298
  46. /package/treb-embed/{modern.tsconfig.json → tsconfig.json} +0 -0
  47. /package/treb-export/{modern.tsconfig.json → tsconfig.json} +0 -0
@@ -41,6 +41,8 @@ import { CoerceComplex } from './function-utilities';
41
41
  import type { UnitAddress, UnitRange } from 'treb-parser';
42
42
  import { ConstructDate } from './date-utils';
43
43
 
44
+ // import type { CalculationContext } from '../descriptors';
45
+
44
46
  /**
45
47
  * BaseFunctionLibrary is a static object that has basic spreadsheet
46
48
  * functions and associated metadata (there's also a list of aliases).
@@ -1253,10 +1255,35 @@ export const BaseFunctionLibrary: FunctionMap = {
1253
1255
  },
1254
1256
  */
1255
1257
 
1256
-
1257
1258
  Row: {
1258
1259
  arguments: [{ name: 'reference', metadata: true }],
1259
- fn: (ref: UnionValue): UnionValue => {
1260
+ fn: function(ref?: UnionValue): UnionValue {
1261
+
1262
+ if (!ref) {
1263
+ if (this?.area) {
1264
+ const value: UnionValue[][] = [];
1265
+ for (let c = this.area.start.column; c <= this.area.end.column; c++) {
1266
+ const col: UnionValue[] = [];
1267
+ for (let r = this.area.start.row; r <= this.area.end.row; r++) {
1268
+ col.push({
1269
+ type: ValueType.number,
1270
+ value: r + 1,
1271
+ });
1272
+ }
1273
+ value.push(col);
1274
+ }
1275
+ return {
1276
+ type: ValueType.array, value,
1277
+ }
1278
+ }
1279
+ else {
1280
+ return {
1281
+ type: ValueType.number,
1282
+ value: this ? this.address.row + 1 : -1,
1283
+ };
1284
+ }
1285
+ }
1286
+
1260
1287
  if (ref.type === ValueType.array) {
1261
1288
  const arr = ref.value;
1262
1289
  const first = arr[0][0];
@@ -1283,7 +1310,33 @@ export const BaseFunctionLibrary: FunctionMap = {
1283
1310
 
1284
1311
  Column: {
1285
1312
  arguments: [{ name: 'reference', metadata: true }],
1286
- fn: (ref: UnionValue): UnionValue => {
1313
+ fn: function(ref?: UnionValue): UnionValue {
1314
+
1315
+ if (!ref) {
1316
+ if (this?.area) {
1317
+ const value: UnionValue[][] = [];
1318
+ for (let c = this.area.start.column; c <= this.area.end.column; c++) {
1319
+ const col: UnionValue[] = [];
1320
+ for (let r = this.area.start.row; r <= this.area.end.row; r++) {
1321
+ col.push({
1322
+ type: ValueType.number,
1323
+ value: c + 1,
1324
+ });
1325
+ }
1326
+ value.push(col);
1327
+ }
1328
+ return {
1329
+ type: ValueType.array, value,
1330
+ }
1331
+ }
1332
+ else {
1333
+ return {
1334
+ type: ValueType.number,
1335
+ value: this ? this.address.column + 1 : -1,
1336
+ };
1337
+ }
1338
+ }
1339
+
1287
1340
  if (ref.type === ValueType.array) {
1288
1341
  const arr = ref.value;
1289
1342
  const first = arr[0][0];
@@ -1307,7 +1360,7 @@ export const BaseFunctionLibrary: FunctionMap = {
1307
1360
  return ArgumentError();
1308
1361
  },
1309
1362
  },
1310
-
1363
+
1311
1364
  Choose: {
1312
1365
  arguments: [
1313
1366
  { name: 'Selected index', },
@@ -409,6 +409,7 @@ export const StatisticsFunctionLibrary: FunctionMap = {
409
409
  },
410
410
  },
411
411
 
412
+ /* use alias instead
412
413
  'NormsInv': {
413
414
 
414
415
  description: 'Inverse of the normal cumulative distribution',
@@ -423,7 +424,8 @@ export const StatisticsFunctionLibrary: FunctionMap = {
423
424
  }
424
425
  }
425
426
  },
426
-
427
+ */
428
+
427
429
  'Norm.Inv': {
428
430
  description: 'Inverse of the normal cumulative distribution',
429
431
  arguments: [
@@ -441,17 +443,15 @@ export const StatisticsFunctionLibrary: FunctionMap = {
441
443
  },
442
444
 
443
445
  'Norm.S.Inv': {
444
- description: 'Inverse of the normal cumulative distribution',
446
+ description: 'Inverse of the standard normal cumulative distribution',
445
447
  arguments: [
446
448
  {name: 'probability'},
447
- {name: 'mean', default: 0},
448
- {name: 'standard deviation', default: 1},
449
449
  ],
450
450
  xlfn: true,
451
- fn: (q: number, mean = 0, stdev = 1): UnionValue => {
451
+ fn: (q: number): UnionValue => {
452
452
  return {
453
453
  type: ValueType.number,
454
- value: inverse_normal(q) * stdev + mean,
454
+ value: inverse_normal(q),
455
455
  }
456
456
  }
457
457
  },
@@ -1073,4 +1073,7 @@ export const StatisticsFunctionAliases: {[index: string]: string} = {
1073
1073
  'StDevPA': 'StDev.P',
1074
1074
  'Var': 'Var.S',
1075
1075
  'Quartile': 'Quartile.Inc',
1076
+ 'NormSInv': 'Norm.S.Inv',
1077
+ 'NormSDist': 'Norm.S.Dist',
1078
+
1076
1079
  };
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "../tsproject.json",
3
+ "references": [
4
+ { "path": "../treb-grid/tsconfig.json" },
5
+ { "path": "../treb-utils/tsconfig.json" }
6
+ ],
7
+ "include": [
8
+ "../treb-base-types/**/*.ts"
9
+ ]
10
+ }
11
+
@@ -43,8 +43,14 @@
43
43
  // this was getting lost by the new higher-specificity reset
44
44
  background: var(--treb-chart-background, #fff);
45
45
 
46
- }
46
+ }
47
47
 
48
+ /**
49
+ * new override allows inheriting fonts in annotations (at least for charts)
50
+ */
51
+ .treb-main.treb-main .treb-inherit-font .treb-chart {
52
+ font-family: inherit;
53
+ }
48
54
 
49
55
  /* container style */
50
56
  .treb-chart {
@@ -117,6 +117,12 @@ export interface AnnotationDataBase {
117
117
  /** the new layout, persisted and takes preference over the old one */
118
118
  layout?: AnnotationLayout;
119
119
 
120
+ /**
121
+ * adding cell style as a convenient store for font stack; atm we are
122
+ * ignoring everything but the font_face attribute
123
+ */
124
+ style?: CellStyle;
125
+
120
126
  /**
121
127
  * the old layout used rectangles, and we need to keep support for
122
128
  * that. this is not the layout rectangle. this rectangle is just
@@ -435,8 +435,8 @@ export class DataModel {
435
435
  }
436
436
 
437
437
  /** wrapper method ensures it always returns an Area (instance, not interface) */
438
- public ResolveArea(address: string|ICellAddress|IArea, active_sheet: Sheet): Area {
439
- const resolved = this.ResolveAddress(address, active_sheet);
438
+ public ResolveArea(address: string|ICellAddress|IArea, active_sheet: Sheet, options?: { r1c1?: boolean }): Area {
439
+ const resolved = this.ResolveAddress(address, active_sheet, options);
440
440
  return IsCellAddress(resolved) ? new Area(resolved) : new Area(resolved.start, resolved.end);
441
441
  }
442
442
 
@@ -449,10 +449,21 @@ export class DataModel {
449
449
  * Q: why are we not preserving absoute/relative? (...)
450
450
  *
451
451
  */
452
- public ResolveAddress(address: string|ICellAddress|IArea, active_sheet: Sheet): ICellAddress|IArea {
452
+ public ResolveAddress(address: string|ICellAddress|IArea, active_sheet: Sheet, options? : { r1c1?: boolean }): ICellAddress|IArea {
453
453
 
454
454
  if (typeof address === 'string') {
455
+
456
+ if (options?.r1c1) {
457
+ this.parser.Save();
458
+ this.parser.flags.r1c1 = true;
459
+ }
460
+
455
461
  const parse_result = this.parser.Parse(address);
462
+
463
+ if (options?.r1c1) {
464
+ this.parser.Restore();
465
+ }
466
+
456
467
  if (parse_result.expression && parse_result.expression.type === 'address') {
457
468
  this.ResolveSheetID(parse_result.expression, undefined, active_sheet);
458
469
  return {
@@ -33,7 +33,10 @@ import { Measurement, ValidateURI } from 'treb-utils';
33
33
 
34
34
  import type { TextPart ,
35
35
  Cell, ICellAddress, CellSerializationOptions, CellValue, ImportedSheetData, Complex,
36
- DimensionedQuantity, IArea, Table, TableTheme, HorizontalAlign, VerticalAlign} from 'treb-base-types';
36
+ DimensionedQuantity, IArea, Table, TableTheme, HorizontalAlign, VerticalAlign,
37
+ Theme} from 'treb-base-types';
38
+
39
+ import { Get as GetFonrMetrics } from 'treb-grid/src/util/fontmetrics';
37
40
 
38
41
  // --- local imports ----------------------------------------------------------
39
42
 
@@ -299,7 +302,8 @@ export class Sheet {
299
302
 
300
303
  this.default_column_width = DEFAULT_COLUMN_WIDTH;
301
304
  this.row_header_width = DEFAULT_ROW_HEADER_WIDTH;
302
- this.UpdateDefaultRowHeight();
305
+
306
+ // this.UpdateDefaultRowHeight();
303
307
 
304
308
  this.id_ = Sheet.base_id++;
305
309
 
@@ -314,10 +318,14 @@ export class Sheet {
314
318
  /**
315
319
  * factory method creates a new sheet
316
320
  */
317
- public static Blank(style_defaults: CellStyle, name?: string, rows = 30, columns = 20): Sheet {
321
+ public static Blank(style_defaults: CellStyle, name?: string, rows = 30, columns = 20, theme?: Theme): Sheet {
318
322
 
319
323
  const sheet = new Sheet(style_defaults);
320
324
 
325
+ if (theme) {
326
+ sheet.UpdateDefaultRowHeight(theme);
327
+ }
328
+
321
329
  if (name) {
322
330
  sheet.name = name;
323
331
  }
@@ -905,71 +913,45 @@ export class Sheet {
905
913
 
906
914
  }
907
915
 
908
- /**
909
- * FIXME: measure the font.
910
- *
911
- * Can we use the same metrics as renderer? That uses a canvas. Obviously
912
- * canvas won't work if there's no DOM but it's OK if this method fails in
913
- * that case; the only question is will it break if it's running headless?
914
- */
915
- public StyleFontSize(style: CellStyle, default_properties: CellStyle = {}): number {
916
-
917
- let font_height = (style.font_size?.value || 0);
918
-
919
- let scale = 0;
920
-
921
- switch (style.font_size?.unit) {
922
- case 'px':
923
- font_height *= (75 / 100);
924
- break;
925
-
926
- case 'em':
927
- scale = style.font_size.value || 1;
928
- break;
929
-
930
- case '%':
931
- scale = (style.font_size.value || 100) / 100;
932
- break;
933
- }
934
-
935
- if (scale) {
936
- font_height = scale * (default_properties.font_size?.value || 10);
937
- if (default_properties.font_size?.unit === 'px') {
938
- font_height *= (75 / 100);
939
- }
940
- }
941
-
942
- return font_height || 10;
943
-
944
- }
945
-
946
916
  /**
947
917
  * FIXME: this is called in the ctor, which made sense when sheets
948
918
  * were more ephemeral. now that we update a single instance, rather
949
919
  * than create new instances, we lose this behavior. we should call
950
920
  * this when we change sheet style.
951
921
  *
952
- * removing parameter, event
922
+ * actually this should just move to theme, no? as long as sheet has
923
+ * a reference to theme. for headless instances that would just use
924
+ * theme defaults, which should be appropriate.
925
+ *
926
+ * I guess the original idea was that sheet style might be used to
927
+ * base row height on sheet font size? not sure if that's how it actually
928
+ * plays out, since this is only called in the ctor (or equivalent) or when
929
+ * theme is updated (but not when sheet style is updated). might need some
930
+ * thought.
931
+ *
953
932
  */
954
- public UpdateDefaultRowHeight(): void {
933
+ public UpdateDefaultRowHeight(theme: Theme, scale = 1): void {
955
934
 
956
- const composite = Style.Composite([this.default_style_properties, this.sheet_style]);
935
+ // this guard is here because this is called by sheet directly, so maybe
936
+ // in headless context? would make more sense to just not call it
957
937
 
958
938
  if (typeof window !== 'undefined') {
959
939
 
960
- const measurement = Measurement.MeasureText(Style.Font(composite), 'M');
961
- const height = Math.round(measurement.height * 1.4);
940
+ const composite = Style.Composite([this.default_style_properties, this.sheet_style]);
941
+ const font_info = Style.CompositeFont(theme.grid_cell_font_size, composite, scale, theme);
942
+ const metrics = GetFonrMetrics(font_info.font, font_info.variants);
943
+ const height = metrics.height * 1.25; // ??
944
+
945
+ // const measurement = Measurement.MeasureText(Style.Font2(composite, 1, theme).font, 'M');
946
+ // const height = Math.round(measurement.height * 1.4);
947
+
948
+ // console.info({height, default: this.default_row_height});
962
949
 
963
950
  if (this.default_row_height < height) {
964
951
  this.default_row_height = height;
965
952
  }
966
953
 
967
954
  }
968
- /*
969
- else {
970
- // console.info('worker?');
971
- }
972
- */
973
955
 
974
956
  }
975
957
 
@@ -1658,14 +1640,14 @@ export class Sheet {
1658
1640
  this.column_header_height = column_header_height;
1659
1641
  }
1660
1642
 
1661
- /**
1643
+ /* *
1662
1644
  * resize row to match character hight, taking into
1663
1645
  * account multi-line values.
1664
1646
  *
1665
1647
  * UPDATE: since the only caller calls with inline = true, removing
1666
1648
  * parameter, test, and extra behavior.
1667
- */
1668
- public AutoSizeRow(row: number, default_properties: CellStyle = {}, allow_shrink = true): void {
1649
+ * /
1650
+ public AutoSizeRow(row: number, theme?: Theme, allow_shrink = true, scale = 1): void {
1669
1651
 
1670
1652
  let height = this.default_row_height;
1671
1653
  const padding = 9; // 9?
@@ -1673,7 +1655,7 @@ export class Sheet {
1673
1655
  for (let column = 0; column < this.cells.columns; column++) {
1674
1656
 
1675
1657
  const cell = this.CellData({ row, column });
1676
- const style = cell.style;
1658
+ const style = JSON.parse(JSON.stringify(cell.style));
1677
1659
  let text = cell.formatted || '';
1678
1660
 
1679
1661
  if (typeof text !== 'string') {
@@ -1682,7 +1664,25 @@ export class Sheet {
1682
1664
 
1683
1665
  if (style && text && text.length) {
1684
1666
  const lines = text.split(/\n/);
1685
- const font_height = Math.round(this.StyleFontSize(style, default_properties) * 1.5); // it's a start, we still need to measure properly
1667
+
1668
+ if (style.font_size) {
1669
+ if (style.font_size.unit === 'em') {
1670
+ const base = theme?.grid_cell_font_size || { unit: 'pt', value: 10 };
1671
+ style.font_size.unit = base.unit;
1672
+ style.font_size.value *= base.value;
1673
+ }
1674
+ }
1675
+ else {
1676
+ style.font_size = theme?.grid_cell_font_size || { unit: 'pt', value: 10 };
1677
+ }
1678
+
1679
+ let target = style.font_size.value;
1680
+ if (style.font_size.unit === 'px') {
1681
+ target = Math.round((style.font_size.value||16) * 300 / 4) / 100;
1682
+ }
1683
+
1684
+ const font_height = // Math.round(this.StyleFontSize(style, default_properties) * 1.5); // it's a start, we still need to measure properly
1685
+ Math.round(target * 1.5 * scale);
1686
1686
  height = Math.max(height, ((font_height || 10) + padding) * lines.length);
1687
1687
  }
1688
1688
  }
@@ -1695,6 +1695,7 @@ export class Sheet {
1695
1695
  this.SetRowHeight(row, height);
1696
1696
 
1697
1697
  }
1698
+ */
1698
1699
 
1699
1700
  /** returns the style properties for a given style index */
1700
1701
  public GetStyle(index: number): CellStyle {
@@ -130,13 +130,27 @@
130
130
  <button data-command="font-scale" data-scale="0.9">0.90</button>
131
131
  <button data-command="font-scale" data-scale="1.0">1.00</button>
132
132
  <button data-command="font-scale" data-scale="1.1">1.10</button>
133
- <button data-command="font-scale" data-scale="1.2">1.20</button>
133
+ <button data-command="font-scale" data-scale="1.25">1.25</button>
134
134
  <button data-command="font-scale" data-scale="1.5">1.50</button>
135
135
  <button data-command="font-scale" data-scale="2.0">2.00</button>
136
136
  </div>
137
137
  </div>
138
138
  </div>
139
139
 
140
+ <div composite font-stack>
141
+ <button class="treb-font-stack" data-command="font-stack" data-font-stack="" title="Font stack"></button>
142
+ <div class="treb-menu">
143
+ <button dropdown title="Font stack options"></button>
144
+ <div>
145
+ <button data-command="font-stack" data-font-stack="default"></button>
146
+ <button data-command="font-stack" data-font-stack="transitional"></button>
147
+ <button data-command="font-stack" data-font-stack="monospace"></button>
148
+ <button data-command="font-stack" data-font-stack="handwritten"></button>
149
+ <button data-command="font-stack" data-font-stack="ui"></button>
150
+ </div>
151
+ </div>
152
+ </div>
153
+
140
154
  <div composite>
141
155
  <input class="treb-number-format" title="Number format">
142
156
  <div class="treb-menu">
@@ -12,6 +12,7 @@ import { Measurement } from 'treb-utils';
12
12
  import type { ToolbarMessage } from '../toolbar-message';
13
13
 
14
14
  import { DOMContext } from 'treb-base-types';
15
+ import { font_stack_labels, type FontStackType } from 'treb-base-types/src/font-stack';
15
16
 
16
17
  /** with a view towards i18n */
17
18
  const default_titles: Record<string, string> = {
@@ -668,6 +669,24 @@ export class SpreadsheetConstructor<USER_DATA_TYPE = unknown> {
668
669
  }
669
670
  }
670
671
 
672
+ if (this.toolbar_controls.stack) {
673
+ if (state.style?.font_face) {
674
+ if (state.style.font_face.startsWith('stack:')) {
675
+ const stack_name = state.style.font_face.substring(6) as FontStackType;
676
+ this.toolbar_controls.stack.textContent = font_stack_labels[stack_name] || '';
677
+ this.toolbar_controls.stack.dataset.fontStack = stack_name;
678
+ }
679
+ else {
680
+ this.toolbar_controls.stack.textContent = '';
681
+ this.toolbar_controls.stack.dataset.fontStack = '';
682
+ }
683
+ }
684
+ else { // } if (!state.empty) {
685
+ this.toolbar_controls.stack.textContent = font_stack_labels.default || '';
686
+ this.toolbar_controls.stack.dataset.fontStack = 'default';
687
+ }
688
+ }
689
+
671
690
  const format = this.toolbar_controls.format as HTMLInputElement;
672
691
  if (format) {
673
692
  if (state.style?.number_format) {
@@ -914,6 +933,19 @@ export class SpreadsheetConstructor<USER_DATA_TYPE = unknown> {
914
933
  if (!sheet.options.font_scale) {
915
934
  remove.push(toolbar.querySelector('[font-scale]'));
916
935
  }
936
+ if (!sheet.options.font_stack) {
937
+ remove.push(toolbar.querySelector('[font-stack]'));
938
+ }
939
+ else {
940
+ const buttons = toolbar.querySelectorAll(`[font-stack] button[data-font-stack]`) as NodeListOf<HTMLElement>;
941
+ for (const button of buttons) {
942
+ if (button.dataset.fontStack) {
943
+ const label = font_stack_labels[button.dataset.fontStack as FontStackType];
944
+ button.textContent = label || '';
945
+ }
946
+ }
947
+ }
948
+
917
949
  if (!sheet.options.chart_menu) {
918
950
  remove.push(toolbar.querySelector('[chart-menu]'));
919
951
  }
@@ -967,6 +999,8 @@ export class SpreadsheetConstructor<USER_DATA_TYPE = unknown> {
967
999
  'format': 'input.treb-number-format',
968
1000
  'scale': 'input.treb-font-scale',
969
1001
 
1002
+ 'stack': 'button.treb-font-stack',
1003
+
970
1004
  })) {
971
1005
 
972
1006
  const element = toolbar.querySelector(value) as HTMLElement;
@@ -1029,9 +1063,11 @@ export class SpreadsheetConstructor<USER_DATA_TYPE = unknown> {
1029
1063
  color?: Color;
1030
1064
  format?: string;
1031
1065
  scale?: string;
1066
+ font_stack?: string;
1032
1067
  } = {
1033
1068
  format: target.dataset.format,
1034
1069
  scale: target.dataset.scale,
1070
+ font_stack: target.dataset.fontStack,
1035
1071
  };
1036
1072
 
1037
1073
  let command = target?.dataset.command;
@@ -1376,9 +1412,11 @@ export class SpreadsheetConstructor<USER_DATA_TYPE = unknown> {
1376
1412
  this.UpdateSelectionStyle(sheet, toolbar, comment_box);
1377
1413
  break;
1378
1414
 
1415
+ case 'annotation-selection':
1379
1416
  case 'selection':
1380
1417
  this.UpdateSelectionStyle(sheet, toolbar, comment_box);
1381
1418
  break;
1419
+
1382
1420
  }
1383
1421
  });
1384
1422