@trebco/treb 23.6.2 → 25.0.0-rc1

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 (217) hide show
  1. package/.eslintignore +8 -0
  2. package/.eslintrc.js +164 -0
  3. package/README-shadow-DOM.md +88 -0
  4. package/README.md +37 -130
  5. package/api-config.json +29 -0
  6. package/api-generator/api-generator-types.ts +82 -0
  7. package/api-generator/api-generator.ts +1172 -0
  8. package/api-generator/package.json +3 -0
  9. package/build/treb-spreadsheet.mjs +14 -0
  10. package/{treb.d.ts → build/treb.d.ts} +293 -299
  11. package/esbuild-custom-element.mjs +336 -0
  12. package/esbuild.js +305 -0
  13. package/package.json +43 -14
  14. package/treb-base-types/package.json +5 -0
  15. package/treb-base-types/src/api_types.ts +36 -0
  16. package/treb-base-types/src/area.ts +583 -0
  17. package/treb-base-types/src/basic_types.ts +45 -0
  18. package/treb-base-types/src/cell.ts +612 -0
  19. package/treb-base-types/src/cells.ts +1066 -0
  20. package/treb-base-types/src/color.ts +124 -0
  21. package/treb-base-types/src/import.ts +71 -0
  22. package/treb-base-types/src/index-standalone.ts +29 -0
  23. package/treb-base-types/src/index.ts +42 -0
  24. package/treb-base-types/src/layout.ts +47 -0
  25. package/treb-base-types/src/localization.ts +187 -0
  26. package/treb-base-types/src/rectangle.ts +145 -0
  27. package/treb-base-types/src/render_text.ts +72 -0
  28. package/treb-base-types/src/style.ts +545 -0
  29. package/treb-base-types/src/table.ts +109 -0
  30. package/treb-base-types/src/text_part.ts +54 -0
  31. package/treb-base-types/src/theme.ts +608 -0
  32. package/treb-base-types/src/union.ts +152 -0
  33. package/treb-base-types/src/value-type.ts +164 -0
  34. package/treb-base-types/style/resizable.css +59 -0
  35. package/treb-calculator/modern.tsconfig.json +11 -0
  36. package/treb-calculator/package.json +5 -0
  37. package/treb-calculator/src/calculator.ts +2546 -0
  38. package/treb-calculator/src/complex-math.ts +558 -0
  39. package/treb-calculator/src/dag/array-vertex.ts +198 -0
  40. package/treb-calculator/src/dag/graph.ts +951 -0
  41. package/treb-calculator/src/dag/leaf_vertex.ts +118 -0
  42. package/treb-calculator/src/dag/spreadsheet_vertex.ts +327 -0
  43. package/treb-calculator/src/dag/spreadsheet_vertex_base.ts +44 -0
  44. package/treb-calculator/src/dag/vertex.ts +352 -0
  45. package/treb-calculator/src/descriptors.ts +162 -0
  46. package/treb-calculator/src/expression-calculator.ts +1069 -0
  47. package/treb-calculator/src/function-error.ts +103 -0
  48. package/treb-calculator/src/function-library.ts +103 -0
  49. package/treb-calculator/src/functions/base-functions.ts +1214 -0
  50. package/treb-calculator/src/functions/checkbox.ts +164 -0
  51. package/treb-calculator/src/functions/complex-functions.ts +253 -0
  52. package/treb-calculator/src/functions/finance-functions.ts +399 -0
  53. package/treb-calculator/src/functions/information-functions.ts +102 -0
  54. package/treb-calculator/src/functions/matrix-functions.ts +182 -0
  55. package/treb-calculator/src/functions/sparkline.ts +335 -0
  56. package/treb-calculator/src/functions/statistics-functions.ts +350 -0
  57. package/treb-calculator/src/functions/text-functions.ts +298 -0
  58. package/treb-calculator/src/index.ts +27 -0
  59. package/treb-calculator/src/notifier-types.ts +59 -0
  60. package/treb-calculator/src/primitives.ts +428 -0
  61. package/treb-calculator/src/utilities.ts +305 -0
  62. package/treb-charts/package.json +5 -0
  63. package/treb-charts/src/chart-functions.ts +156 -0
  64. package/treb-charts/src/chart-types.ts +230 -0
  65. package/treb-charts/src/chart.ts +1288 -0
  66. package/treb-charts/src/index.ts +24 -0
  67. package/treb-charts/src/main.ts +37 -0
  68. package/treb-charts/src/rectangle.ts +52 -0
  69. package/treb-charts/src/renderer.ts +1841 -0
  70. package/treb-charts/src/util.ts +122 -0
  71. package/treb-charts/style/charts.scss +221 -0
  72. package/treb-charts/style/old-charts.scss +250 -0
  73. package/treb-embed/markup/layout.html +137 -0
  74. package/treb-embed/markup/toolbar.html +175 -0
  75. package/treb-embed/modern.tsconfig.json +25 -0
  76. package/treb-embed/src/custom-element/content-types.d.ts +18 -0
  77. package/treb-embed/src/custom-element/global.d.ts +11 -0
  78. package/treb-embed/src/custom-element/spreadsheet-constructor.ts +1227 -0
  79. package/treb-embed/src/custom-element/treb-global.ts +44 -0
  80. package/treb-embed/src/custom-element/treb-spreadsheet-element.ts +52 -0
  81. package/treb-embed/src/embedded-spreadsheet.ts +5362 -0
  82. package/treb-embed/src/index.ts +16 -0
  83. package/treb-embed/src/language-model.ts +41 -0
  84. package/treb-embed/src/options.ts +320 -0
  85. package/treb-embed/src/progress-dialog.ts +228 -0
  86. package/treb-embed/src/selection-state.ts +16 -0
  87. package/treb-embed/src/spinner.ts +42 -0
  88. package/treb-embed/src/toolbar-message.ts +96 -0
  89. package/treb-embed/src/types.ts +167 -0
  90. package/treb-embed/style/autocomplete.scss +103 -0
  91. package/treb-embed/style/dark-theme.scss +114 -0
  92. package/treb-embed/style/defaults.scss +36 -0
  93. package/treb-embed/style/dialog.scss +181 -0
  94. package/treb-embed/style/dropdown-select.scss +101 -0
  95. package/treb-embed/style/formula-bar.scss +193 -0
  96. package/treb-embed/style/grid.scss +374 -0
  97. package/treb-embed/style/layout.scss +424 -0
  98. package/treb-embed/style/mouse-mask.scss +67 -0
  99. package/treb-embed/style/note.scss +92 -0
  100. package/treb-embed/style/overlay-editor.scss +102 -0
  101. package/treb-embed/style/spinner.scss +92 -0
  102. package/treb-embed/style/tab-bar.scss +228 -0
  103. package/treb-embed/style/table.scss +80 -0
  104. package/treb-embed/style/theme-defaults.scss +444 -0
  105. package/treb-embed/style/toolbar.scss +416 -0
  106. package/treb-embed/style/tooltip.scss +68 -0
  107. package/treb-embed/style/treb-icons.scss +130 -0
  108. package/treb-embed/style/treb-spreadsheet-element.scss +20 -0
  109. package/treb-embed/style/z-index.scss +43 -0
  110. package/treb-export/docs/charts.md +68 -0
  111. package/treb-export/modern.tsconfig.json +19 -0
  112. package/treb-export/package.json +4 -0
  113. package/treb-export/src/address-type.ts +77 -0
  114. package/treb-export/src/base-template.ts +22 -0
  115. package/treb-export/src/column-width.ts +85 -0
  116. package/treb-export/src/drawing2/chart-template-components2.ts +389 -0
  117. package/treb-export/src/drawing2/chart2.ts +282 -0
  118. package/treb-export/src/drawing2/column-chart-template2.ts +521 -0
  119. package/treb-export/src/drawing2/donut-chart-template2.ts +296 -0
  120. package/treb-export/src/drawing2/drawing2.ts +355 -0
  121. package/treb-export/src/drawing2/embedded-image.ts +71 -0
  122. package/treb-export/src/drawing2/scatter-chart-template2.ts +555 -0
  123. package/treb-export/src/export-worker/export-worker.ts +99 -0
  124. package/treb-export/src/export-worker/index-modern.ts +22 -0
  125. package/treb-export/src/export2.ts +2204 -0
  126. package/treb-export/src/import2.ts +882 -0
  127. package/treb-export/src/relationship.ts +36 -0
  128. package/treb-export/src/shared-strings2.ts +128 -0
  129. package/treb-export/src/template-2.ts +22 -0
  130. package/treb-export/src/unescape_xml.ts +47 -0
  131. package/treb-export/src/workbook-sheet2.ts +182 -0
  132. package/treb-export/src/workbook-style2.ts +1285 -0
  133. package/treb-export/src/workbook-theme2.ts +88 -0
  134. package/treb-export/src/workbook2.ts +491 -0
  135. package/treb-export/src/xml-utils.ts +201 -0
  136. package/treb-export/template/base/[Content_Types].xml +2 -0
  137. package/treb-export/template/base/_rels/.rels +2 -0
  138. package/treb-export/template/base/docProps/app.xml +2 -0
  139. package/treb-export/template/base/docProps/core.xml +12 -0
  140. package/treb-export/template/base/xl/_rels/workbook.xml.rels +2 -0
  141. package/treb-export/template/base/xl/sharedStrings.xml +2 -0
  142. package/treb-export/template/base/xl/styles.xml +2 -0
  143. package/treb-export/template/base/xl/theme/theme1.xml +2 -0
  144. package/treb-export/template/base/xl/workbook.xml +2 -0
  145. package/treb-export/template/base/xl/worksheets/sheet1.xml +2 -0
  146. package/treb-export/template/base.xlsx +0 -0
  147. package/treb-format/package.json +8 -0
  148. package/treb-format/src/format.test.ts +213 -0
  149. package/treb-format/src/format.ts +942 -0
  150. package/treb-format/src/format_cache.ts +199 -0
  151. package/treb-format/src/format_parser.ts +723 -0
  152. package/treb-format/src/index.ts +25 -0
  153. package/treb-format/src/number_format_section.ts +100 -0
  154. package/treb-format/src/value_parser.ts +337 -0
  155. package/treb-grid/package.json +5 -0
  156. package/treb-grid/src/editors/autocomplete.ts +394 -0
  157. package/treb-grid/src/editors/autocomplete_matcher.ts +260 -0
  158. package/treb-grid/src/editors/formula_bar.ts +473 -0
  159. package/treb-grid/src/editors/formula_editor_base.ts +910 -0
  160. package/treb-grid/src/editors/overlay_editor.ts +511 -0
  161. package/treb-grid/src/index.ts +37 -0
  162. package/treb-grid/src/layout/base_layout.ts +2618 -0
  163. package/treb-grid/src/layout/grid_layout.ts +299 -0
  164. package/treb-grid/src/layout/rectangle_cache.ts +86 -0
  165. package/treb-grid/src/render/selection-renderer.ts +414 -0
  166. package/treb-grid/src/render/svg_header_overlay.ts +93 -0
  167. package/treb-grid/src/render/svg_selection_block.ts +187 -0
  168. package/treb-grid/src/render/tile_renderer.ts +2122 -0
  169. package/treb-grid/src/types/annotation.ts +216 -0
  170. package/treb-grid/src/types/border_constants.ts +34 -0
  171. package/treb-grid/src/types/clipboard_data.ts +31 -0
  172. package/treb-grid/src/types/data_model.ts +334 -0
  173. package/treb-grid/src/types/drag_mask.ts +81 -0
  174. package/treb-grid/src/types/grid.ts +7743 -0
  175. package/treb-grid/src/types/grid_base.ts +3644 -0
  176. package/treb-grid/src/types/grid_command.ts +470 -0
  177. package/treb-grid/src/types/grid_events.ts +124 -0
  178. package/treb-grid/src/types/grid_options.ts +97 -0
  179. package/treb-grid/src/types/grid_selection.ts +60 -0
  180. package/treb-grid/src/types/named_range.ts +369 -0
  181. package/treb-grid/src/types/scale-control.ts +202 -0
  182. package/treb-grid/src/types/serialize_options.ts +72 -0
  183. package/treb-grid/src/types/set_range_options.ts +52 -0
  184. package/treb-grid/src/types/sheet.ts +3099 -0
  185. package/treb-grid/src/types/sheet_types.ts +95 -0
  186. package/treb-grid/src/types/tab_bar.ts +464 -0
  187. package/treb-grid/src/types/tile.ts +59 -0
  188. package/treb-grid/src/types/update_flags.ts +75 -0
  189. package/treb-grid/src/util/dom_utilities.ts +44 -0
  190. package/treb-grid/src/util/fontmetrics2.ts +179 -0
  191. package/treb-grid/src/util/ua.ts +104 -0
  192. package/treb-logo.svg +18 -0
  193. package/treb-parser/package.json +5 -0
  194. package/treb-parser/src/csv-parser.ts +122 -0
  195. package/treb-parser/src/index.ts +25 -0
  196. package/treb-parser/src/md-parser.ts +526 -0
  197. package/treb-parser/src/parser-types.ts +397 -0
  198. package/treb-parser/src/parser.test.ts +298 -0
  199. package/treb-parser/src/parser.ts +2673 -0
  200. package/treb-utils/package.json +5 -0
  201. package/treb-utils/src/dispatch.ts +57 -0
  202. package/treb-utils/src/event_source.ts +147 -0
  203. package/treb-utils/src/ievent_source.ts +33 -0
  204. package/treb-utils/src/index.ts +31 -0
  205. package/treb-utils/src/measurement.ts +174 -0
  206. package/treb-utils/src/resizable.ts +160 -0
  207. package/treb-utils/src/scale.ts +137 -0
  208. package/treb-utils/src/serialize_html.ts +124 -0
  209. package/treb-utils/src/template.ts +70 -0
  210. package/treb-utils/src/validate_uri.ts +61 -0
  211. package/tsconfig.json +10 -0
  212. package/tsproject.json +30 -0
  213. package/util/license-plugin-esbuild.js +86 -0
  214. package/util/list-css-vars.sh +46 -0
  215. package/README-esm.md +0 -37
  216. package/treb-bundle.css +0 -2
  217. package/treb-bundle.mjs +0 -15
@@ -0,0 +1,118 @@
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2023 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
+ import type { GraphCallbacks } from './spreadsheet_vertex_base';
23
+ import { SpreadsheetVertex } from './spreadsheet_vertex';
24
+ import { Vertex, Color } from './vertex';
25
+
26
+ /**
27
+ * second specialization of vertex: this class is for non-cell elements
28
+ * that are dependent on cells: specifically, charts.
29
+ *
30
+ * we want leaf vertices to participate in the normal dirty/calculate
31
+ * cycle, but they don't need to do any calculation other than checking
32
+ * if the underlying data has changed. we should maintain some state so
33
+ * this is a simple check for observers.
34
+ *
35
+ * leaves specifically do not have addresses. we can represent the chart
36
+ * as a calculation, however. (...)
37
+ *
38
+ * FIXME: it might be better to have an intermediate class/interface and
39
+ * have both leaf- and spreadsheet-vertex extend that.
40
+ *
41
+ */
42
+ export class LeafVertex extends SpreadsheetVertex {
43
+
44
+ public static type = 'leaf-vertex';
45
+
46
+ public state_id = 0;
47
+ public type = LeafVertex.type; // for type guard
48
+
49
+ /**
50
+ * leaf vertex defaults to black (i.e. tested) because leaf nodes cannot have
51
+ * outbound edges. it is still possible to change this, because it's a property
52
+ * and we can't override the set accessor, but making it an accessor in the
53
+ * superclass just for this purpose is not worthwhile since regular vertices
54
+ * should vastly outnumber leaves.
55
+ */
56
+ public color = Color.black;
57
+
58
+ protected state_representation = '';
59
+
60
+ /**
61
+ * construct the state, compare, and increment the state id if
62
+ * it changes. this is expected to be called from Calculate(), but
63
+ * we can also call it on init if we already know the state.
64
+ *
65
+ * FIXME: what's more expensive, generating this state field or
66
+ * re-rendering a chart with the same data? (...?)
67
+ * especially since it's only called on dirty...
68
+ *
69
+ * what is the case where the depenendency is dirty but state
70
+ * does not change? you type in the same value? (...) or maybe
71
+ * there's a volatile function that doesn't change value (e.g. Today())
72
+ *
73
+ * still, it seems like a waste here. let's test without the state.
74
+ * (meaning just update the flag anytime it's dirty)
75
+ *
76
+ * Actually I think the case is manual recalc, when values don't change
77
+ * (especially true for MC charts).
78
+ *
79
+ * TODO: perf
80
+ */
81
+ public UpdateState(): void {
82
+
83
+ // FIXME: hash!
84
+ //const state = JSON.stringify(this.edges_in.map((edge) => (edge as SpreadsheetVertex).result));
85
+ const state = JSON.stringify(Array.from(this.edges_in).map((edge) => (edge as SpreadsheetVertex).result));
86
+
87
+ if (state !== this.state_representation) {
88
+ this.state_representation = state;
89
+ this.state_id++;
90
+ }
91
+
92
+ }
93
+
94
+ /** overrides calculate function */
95
+ public Calculate(graph: GraphCallbacks): void {
96
+
97
+ // if we are not dirty, nothing to do
98
+ if (!this.dirty) return;
99
+
100
+ // check deps
101
+ for (const edge of this.edges_in) {
102
+ if ((edge as SpreadsheetVertex).dirty) {
103
+ return;
104
+ }
105
+ }
106
+
107
+ // ok, we can evaluate... all we are doing here is checking state consistency
108
+ this.UpdateState();
109
+ this.dirty = false;
110
+
111
+ // we are not allowed to have edges out, so nothing to do
112
+ }
113
+
114
+ public AddDependent(edge: Vertex): void {
115
+ throw(new Error('leaf vertex cannot have dependents'));
116
+ }
117
+
118
+ }
@@ -0,0 +1,327 @@
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2023 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
+ import { SpreadsheetVertexBase, GraphCallbacks } from './spreadsheet_vertex_base';
23
+ import { Cell, Box, ICellAddress, ValueType, UnionValue } from 'treb-base-types';
24
+ import type { ExpressionUnit } from 'treb-parser';
25
+ import { Color } from './vertex';
26
+ import { ErrorType } from '../function-error';
27
+
28
+ export enum SpreadsheetError {
29
+ None,
30
+ CalculationError,
31
+ }
32
+
33
+ /**
34
+ * specialization of vertex with attached data and calculation metadata
35
+ */
36
+ export class SpreadsheetVertex extends SpreadsheetVertexBase {
37
+
38
+ public static type = 'spreadsheet-vertex';
39
+
40
+ // I wonder if we should drop this and look up on demand -- might
41
+ // help in large blocks...
42
+
43
+ public reference?: Cell;
44
+
45
+ public error = SpreadsheetError.None;
46
+
47
+ // why is this (?)? can't we use a default junk address?
48
+ public address?: ICellAddress;
49
+
50
+ //public result: UnionOrArray = UndefinedUnion();
51
+ public result: UnionValue = {type: ValueType.undefined};
52
+
53
+ public expression: ExpressionUnit = { type: 'missing', id: -1 };
54
+ public expression_error = false;
55
+ public short_circuit = false;
56
+
57
+ public type = SpreadsheetVertex.type; // for type guard
58
+
59
+ /**
60
+ * it seems like this could be cached, if it gets checked a lot
61
+ * also what's with the crazy return signature? [fixed]
62
+ */
63
+ get array_head(): boolean {
64
+ if (!this.address) return false;
65
+ return (!!this.reference)
66
+ && (!!this.reference.area)
67
+ && (this.reference.area.start.column === this.address.column)
68
+ && (this.reference.area.start.row === this.address.row);
69
+
70
+ }
71
+
72
+ /**
73
+ * to support restoring cached values (from file), we need a way to get
74
+ * the value from the reference (cell). normally this is done during
75
+ * calculation, and in reverse (we set the value).
76
+ *
77
+ * some additional implications of this:
78
+ *
79
+ * - does not set volatile/nonvolatile, which is usually managed as a
80
+ * side-effect of the calculation.
81
+ *
82
+ * - does not remove the entry from the dirty list
83
+ *
84
+ * - does not clear the internal dirty flag. it used to do that, but we
85
+ * took it out because we are now managing multple vertex types, and
86
+ * we don't want to attach that behavior to a type-specific method.
87
+ *
88
+ * so the caller needs to explicitly address the dirty and volatile lists
89
+ * for this vertex.
90
+ */
91
+ public TakeReferenceValue(): void {
92
+ if (this.reference) {
93
+ this.result = Box(this.reference.GetValue());
94
+ }
95
+ }
96
+
97
+ /**
98
+ * calculates the function, but only if all dependencies are clean.
99
+ * if one or more dependencies are dirty, just exit. this should work out
100
+ * so that when the last dependency is satisfied, the propagation will
101
+ * succeed. FIXME: optimize order.
102
+ *
103
+ * FIXME: why is this in vertex, instead of graph? [a: dirty check?]
104
+ * A: for overloading. leaf extends this class, and has a separate
105
+ * calculation routine.
106
+ */
107
+ public Calculate(graph: GraphCallbacks): void {
108
+
109
+ if (!this.dirty) return;
110
+
111
+ // it would be nice if we could get this out of the calculate routine,
112
+ // but that's a problem because we can't calculate in the right order.
113
+
114
+ // one solution might be to have two methods, one which includes it
115
+ // and one which doesn't, and call the checked method only when necessary.
116
+ // OTOH that means maintaining the internal calculation part twice (or
117
+ // adding a method call).
118
+
119
+ if (this.color === Color.white && this.LoopCheck()) {
120
+
121
+ // console.info('LCB', `R${this.address?.row} C${this.address?.column}`, this);
122
+
123
+ // if (this.LoopCheck()) {
124
+ // throw new Error('loop loop 2')
125
+
126
+ this.dirty = false;
127
+
128
+ if (this.edges_in.size) {
129
+
130
+ // console.info('set loop err', `R${this.address?.row} C${this.address?.column}`, this);
131
+
132
+ // this should alwys be true, because it has edges so
133
+ // it must be a formula (right?)
134
+
135
+ // we don't have to do that test because now we only set
136
+ // vertices -> white if they match
137
+
138
+ if (this.reference && (
139
+ this.array_head || this.reference.type === ValueType.formula )) {
140
+ this.reference.SetCalculationError(ErrorType.Loop);
141
+ }
142
+ //this.reference?.SetCalculationError('LOOP');
143
+
144
+ // intuitively this seems like a good idea but I'm not sure
145
+ // that it is actually necessary (TODO: check)
146
+
147
+ for (const edge of this.edges_out){
148
+ (edge as SpreadsheetVertex).Calculate(graph);
149
+ }
150
+
151
+ return;
152
+
153
+ }
154
+ /*
155
+ else {
156
+ console.info('SKIP loop err', `R${this.address?.row} C${this.address?.column}`, this);
157
+ }
158
+ */
159
+
160
+ // }
161
+ }
162
+
163
+ // this is done before checking if it's a formula for the case of
164
+ // arrays: arrays are not formulae but they are dependent on the
165
+ // array head. if the head is dirty we need to calculate that before
166
+ // any dependents of _this_ cell are calculated.
167
+
168
+ // the head calculation should take care of setting this value, that is,
169
+ // we don't need to do the actual lookup.
170
+
171
+ // this prevents a runaway if there's a loop (and we are not catching it),
172
+ // but there's a side-effect: the dirty flag never gets cleared. if we want
173
+ // to fix this we need to clean the dirty flag on vertices before a full
174
+ // recalc, I guess...
175
+
176
+ // that's also why page reload "fixes" the issue: because there's a global
177
+ // cleaning of dirty flags. or maybe they don't survive serialization, I don't know.
178
+
179
+ for (const edge of this.edges_in) {
180
+ if ((edge as SpreadsheetVertexBase).dirty) {
181
+ // console.info('exiting on dirty deps', `R${this.address?.row} C${this.address?.column}`, this);
182
+ return;
183
+ }
184
+ }
185
+
186
+ // console.info('OK calc', `R${this.address?.row} C${this.address?.column}`, this);
187
+
188
+ // we won't have a reference if the reference is to an empty cell,
189
+ // so check that. [Q: what?]
190
+
191
+ if (this.reference) {
192
+
193
+ if (this.reference.type === ValueType.formula) {
194
+
195
+ this.short_circuit = false;
196
+ const result = graph.CalculationCallback.call(graph, this);
197
+
198
+ // console.info("RX", result);
199
+
200
+ this.result = result.value;
201
+
202
+ // this test is a waste for 99% of calls
203
+ //
204
+ // [FYI it has to do with dynamic dependencies, needs to be documented]
205
+ //
206
+ if (this.short_circuit) { return; } // what about setting dirty flag? (...)
207
+
208
+ // and this one for ~75%?
209
+ if (result.volatile) graph.volatile_list.push(this);
210
+ }
211
+ else this.result = this.reference.GetValue4();
212
+
213
+ // is this going to work properly if it's an error? (...)
214
+
215
+ if (this.array_head) {
216
+ graph.SpreadCallback.call(graph, this, this.result);
217
+ }
218
+ else if (this.reference.type === ValueType.formula) {
219
+
220
+ // data should now be clean when it gets here (famous last words)
221
+
222
+ // we're now sometimes getting 0-length arrays here. that's a
223
+ // function of our new polynomial methods, BUT, we should probably
224
+ // handle it properly regardless.
225
+
226
+ const single = (this.result.type === ValueType.array) ? this.result.value[0][0] : this.result;
227
+ /*
228
+ if (single.type === ValueType.object) {
229
+ this.reference.SetCalculationError('OBJECT');
230
+ }
231
+ else */
232
+
233
+ // we are using object type in the returned value for sparklines...
234
+ // so we can't drop it here. we could change rendering though. or
235
+ // whitelist types. or blacklist types. or something.
236
+
237
+ {
238
+ this.reference.SetCalculatedValue(single.value as any, single.type);
239
+ }
240
+
241
+ /*
242
+ console.info("T2", t2);
243
+
244
+ // because we let sloppy data filter through, it's possible
245
+ // that we get some random stuff at this point. generally this
246
+ // shoudl not happen but if you use (e.g.) one of the chart
247
+ // functions in a spreadsheet cell, you'll get a 1d array.
248
+
249
+ // so we need to validate that what we have is either a UnionValue
250
+ // or a 2d UnionValue[][] array.
251
+
252
+ // don't know the performance cost of this.
253
+
254
+ // FIXME: don't let sloppy data through.
255
+
256
+ let test: any = this.result;
257
+
258
+ if (Array.isArray(test)) {
259
+ if (test[0] && Array.isArray(test[0])) {
260
+ test = test[0][0];
261
+ }
262
+ else {
263
+ // console.warn('error 1');
264
+ test = undefined;
265
+ }
266
+ }
267
+
268
+ if (!test || typeof (test as any).type === undefined) {
269
+ // console.warn('error 2/3');
270
+ this.reference.SetCalculationError('UNK');
271
+ }
272
+ else {
273
+ this.reference.SetCalculatedValue((test as UnionValue).value, (test as UnionValue).type);
274
+ }
275
+ */
276
+
277
+ /*
278
+ const single = Array.isArray(this.result) ? this.result[0][0] : this.result;
279
+
280
+ // error is implicit
281
+ this.reference.SetCalculatedValue(single.value, single.type);
282
+ */
283
+
284
+ /*
285
+ if (typeof this.result === 'object' && this.result.error) {
286
+ this.reference.SetCalculationError(this.result.error);
287
+ }
288
+ else {
289
+ this.reference.SetCalculatedValue(this.result);
290
+ }
291
+ */
292
+ }
293
+
294
+ }
295
+ else {
296
+ console.info('skip dirty constant? [or dangling...]');
297
+ }
298
+
299
+ this.dirty = false;
300
+
301
+ // so this is causing problems in long chains. we need
302
+ // to do this !recursively. there's a slight problem in
303
+ // that we do it in the loop check as well... not sure
304
+ // how this will play out.
305
+
306
+ // some options:
307
+ // (1) push (dirty) edges onto a global list (or list contained in graph)
308
+ // (2) return boolean, with one state indicating our dependencies need calculating
309
+ // (3) return a list of dirty dependencies, caller can push onto their list
310
+ //
311
+ // (4) because dirty vertices are on the list, you could just loop until
312
+ // the list is clean (i.e. restart and exit if there are no dirty
313
+ // vertices left)... that's kind of the same as pushing onto the back of
314
+ // the list but it avoids extending the list (not sure if that that is
315
+ // a useful optimization or not)
316
+ //
317
+
318
+ for (const edge of this.edges_out as Set<SpreadsheetVertexBase>){
319
+ // (edge as SpreadsheetVertex).Calculate(graph);
320
+ if (edge.dirty) {
321
+ graph.calculation_list.push(edge);
322
+ }
323
+ }
324
+
325
+ }
326
+
327
+ }
@@ -0,0 +1,44 @@
1
+ /*
2
+ * This file is part of TREB.
3
+ *
4
+ * TREB is free software: you can redistribute it and/or modify it under the
5
+ * terms of the GNU General Public License as published by the Free Software
6
+ * Foundation, either version 3 of the License, or (at your option) any
7
+ * later version.
8
+ *
9
+ * TREB is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ * details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License along
15
+ * with TREB. If not, see <https://www.gnu.org/licenses/>.
16
+ *
17
+ * Copyright 2022-2023 trebco, llc.
18
+ * info@treb.app
19
+ *
20
+ */
21
+
22
+ import { Vertex } from './vertex';
23
+ import type { UnionValue } from 'treb-base-types';
24
+
25
+ export interface CalculationResult {
26
+ // value: any;
27
+ value: UnionValue;
28
+ volatile?: boolean;
29
+ }
30
+
31
+ /**
32
+ * this is a subset of Graph so we can avoid the circular dependency.
33
+ */
34
+ export interface GraphCallbacks {
35
+ CalculationCallback: (vertex: SpreadsheetVertexBase) => CalculationResult;
36
+ SpreadCallback: (vertex: SpreadsheetVertexBase, value: UnionValue) => void;
37
+ volatile_list: SpreadsheetVertexBase[];
38
+ calculation_list: SpreadsheetVertexBase[];
39
+ }
40
+
41
+ export abstract class SpreadsheetVertexBase extends Vertex {
42
+ public dirty = false;
43
+ public abstract Calculate(graph: GraphCallbacks): void;
44
+ }