@trebco/treb 27.7.6 → 27.9.0
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/dist/treb-spreadsheet.mjs +14 -14
- package/dist/treb.d.ts +21 -21
- package/notes/conditional-fomratring.md +29 -0
- package/package.json +1 -1
- package/treb-base-types/src/area.ts +181 -0
- package/treb-base-types/src/evaluate-options.ts +21 -0
- package/treb-base-types/src/gradient.ts +97 -0
- package/treb-base-types/src/import.ts +2 -1
- package/treb-base-types/src/index.ts +2 -0
- package/treb-calculator/src/calculator.ts +190 -28
- package/treb-calculator/src/dag/calculation_leaf_vertex.ts +97 -0
- package/treb-calculator/src/dag/graph.ts +10 -22
- package/treb-calculator/src/dag/{leaf_vertex.ts → state_leaf_vertex.ts} +3 -3
- package/treb-calculator/src/descriptors.ts +10 -3
- package/treb-calculator/src/expression-calculator.ts +1 -1
- package/treb-calculator/src/function-library.ts +25 -22
- package/treb-calculator/src/functions/base-functions.ts +166 -5
- package/treb-calculator/src/index.ts +6 -6
- package/treb-calculator/src/notifier-types.ts +1 -1
- package/treb-calculator/src/utilities.ts +2 -2
- package/treb-charts/src/util.ts +2 -2
- package/treb-embed/src/embedded-spreadsheet.ts +352 -41
- package/treb-export/src/export-worker/export-worker.ts +0 -13
- package/treb-export/src/export2.ts +187 -2
- package/treb-export/src/import2.ts +169 -4
- package/treb-export/src/workbook-style2.ts +56 -8
- package/treb-export/src/workbook2.ts +10 -1
- package/treb-grid/src/index.ts +2 -1
- package/treb-grid/src/layout/base_layout.ts +23 -15
- package/treb-grid/src/render/tile_renderer.ts +2 -1
- package/treb-grid/src/types/conditional_format.ts +168 -0
- package/treb-grid/src/types/grid.ts +5 -6
- package/treb-grid/src/types/grid_base.ts +186 -33
- package/treb-grid/src/types/sheet.ts +330 -26
- package/treb-grid/src/types/sheet_types.ts +4 -0
- /package/{README-shadow-DOM.md → notes/shadow-DOM.md} +0 -0
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
*
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import type { Cell, ICellAddress, ICellAddress2, UnionValue,
|
|
23
|
-
ArrayUnion, IArea, CellDataWithAddress} from 'treb-base-types';
|
|
22
|
+
import type { Cell, ICellAddress, ICellAddress2, UnionValue, EvaluateOptions,
|
|
23
|
+
ArrayUnion, IArea, CellDataWithAddress, CellValue} from 'treb-base-types';
|
|
24
24
|
import { Localization, Area, ValueType, IsCellAddress} from 'treb-base-types';
|
|
25
25
|
|
|
26
26
|
import type { ExpressionUnit, DependencyList, UnitRange, UnitAddress, UnitIdentifier } from 'treb-parser';
|
|
27
27
|
import { Parser,
|
|
28
|
-
DecimalMarkType, ArgumentSeparatorType } from 'treb-parser';
|
|
28
|
+
DecimalMarkType, ArgumentSeparatorType, QuotedSheetNameRegex } from 'treb-parser';
|
|
29
29
|
|
|
30
30
|
import { Graph } from './dag/graph';
|
|
31
31
|
import type { SpreadsheetVertex } from './dag/spreadsheet_vertex';
|
|
@@ -49,10 +49,12 @@ import { Variance } from './functions/statistics-functions';
|
|
|
49
49
|
|
|
50
50
|
import * as Primitives from './primitives';
|
|
51
51
|
|
|
52
|
-
import type { DataModel, Annotation, FunctionDescriptor, Sheet } from 'treb-grid';
|
|
53
|
-
import { LeafVertex } from './dag/
|
|
52
|
+
import type { DataModel, Annotation, FunctionDescriptor, Sheet, ConditionalFormat } from 'treb-grid';
|
|
53
|
+
import type { LeafVertex } from './dag/graph';
|
|
54
54
|
|
|
55
55
|
import { ArgumentError, ReferenceError, UnknownError, ValueError, ExpressionError, NAError, DivideByZeroError } from './function-error';
|
|
56
|
+
import { StateLeafVertex } from './dag/state_leaf_vertex';
|
|
57
|
+
import { CalculationLeafVertex } from './dag/calculation_leaf_vertex';
|
|
56
58
|
|
|
57
59
|
/**
|
|
58
60
|
* breaking this out so we can use it for export (TODO)
|
|
@@ -120,27 +122,6 @@ const TranslateSubtotalType = (type: string|number): number => {
|
|
|
120
122
|
|
|
121
123
|
};
|
|
122
124
|
|
|
123
|
-
/**
|
|
124
|
-
* options for the evaluate function
|
|
125
|
-
*/
|
|
126
|
-
export interface EvaluateOptions {
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* argument separator to use when parsing input. set this option to
|
|
130
|
-
* use a consistent argument separator independent of current locale.
|
|
131
|
-
*/
|
|
132
|
-
argument_separator?: ','|';';
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* allow R1C1-style references. the Evaluate function cannot use
|
|
136
|
-
* relative references (e.g. R[-1]C[0]), so those will always fail.
|
|
137
|
-
* however it may be useful to use direct R1C1 references (e.g. R3C4),
|
|
138
|
-
* so we optionally support that behind this flag.
|
|
139
|
-
*/
|
|
140
|
-
r1c1?: boolean;
|
|
141
|
-
|
|
142
|
-
}
|
|
143
|
-
|
|
144
125
|
/**
|
|
145
126
|
* we're providing a runtime option for how to handle complex numbers.
|
|
146
127
|
* we will need to pass that into the calculator when it's created to
|
|
@@ -1309,6 +1290,7 @@ export class Calculator extends Graph {
|
|
|
1309
1290
|
if (this.full_rebuild_required) {
|
|
1310
1291
|
subset = undefined;
|
|
1311
1292
|
this.UpdateAnnotations();
|
|
1293
|
+
this.UpdateConditionals();
|
|
1312
1294
|
// this.UpdateNotifiers();
|
|
1313
1295
|
this.full_rebuild_required = false; // unset
|
|
1314
1296
|
}
|
|
@@ -1391,9 +1373,11 @@ export class Calculator extends Graph {
|
|
|
1391
1373
|
return map;
|
|
1392
1374
|
}
|
|
1393
1375
|
|
|
1376
|
+
public Evaluate(expression: string, active_sheet?: Sheet, options?: EvaluateOptions, raw_result?: false): CellValue|CellValue[][];
|
|
1377
|
+
public Evaluate(expression: string, active_sheet?: Sheet, options?: EvaluateOptions, raw_result?: true): UnionValue;
|
|
1394
1378
|
|
|
1395
1379
|
/** moved from embedded sheet */
|
|
1396
|
-
public Evaluate(expression: string, active_sheet?: Sheet, options: EvaluateOptions = {}) {
|
|
1380
|
+
public Evaluate(expression: string, active_sheet?: Sheet, options: EvaluateOptions = {}, raw_result = false) {
|
|
1397
1381
|
|
|
1398
1382
|
const current = this.parser.argument_separator;
|
|
1399
1383
|
const r1c1_state = this.parser.flags.r1c1;
|
|
@@ -1447,6 +1431,9 @@ export class Calculator extends Graph {
|
|
|
1447
1431
|
|
|
1448
1432
|
// console.info({expression: parse_result.expression})
|
|
1449
1433
|
const result = this.CalculateExpression(parse_result.expression);
|
|
1434
|
+
if (raw_result) {
|
|
1435
|
+
return result;
|
|
1436
|
+
}
|
|
1450
1437
|
|
|
1451
1438
|
if (result.type === ValueType.array) {
|
|
1452
1439
|
return result.value.map(row => row.map(value => value.value));
|
|
@@ -1500,6 +1487,7 @@ export class Calculator extends Graph {
|
|
|
1500
1487
|
// add leaf vertices for annotations
|
|
1501
1488
|
|
|
1502
1489
|
this.UpdateAnnotations(); // all
|
|
1490
|
+
this.UpdateConditionals();
|
|
1503
1491
|
|
|
1504
1492
|
// and notifiers
|
|
1505
1493
|
|
|
@@ -1722,6 +1710,180 @@ export class Calculator extends Graph {
|
|
|
1722
1710
|
}
|
|
1723
1711
|
*/
|
|
1724
1712
|
|
|
1713
|
+
public Unresolve(ref: IArea|ICellAddress, context: Sheet, qualified = true, named = true) {
|
|
1714
|
+
|
|
1715
|
+
let range = '';
|
|
1716
|
+
const area = IsCellAddress(ref) ? new Area(ref) : new Area(ref.start, ref.end);
|
|
1717
|
+
|
|
1718
|
+
if (named) {
|
|
1719
|
+
const named_range = this.model.named_ranges.MatchSelection(area);
|
|
1720
|
+
if (named_range) {
|
|
1721
|
+
return named_range;
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
if (area.count > 1) {
|
|
1726
|
+
range = Area.CellAddressToLabel(area.start) + ':' + Area.CellAddressToLabel(area.end);
|
|
1727
|
+
}
|
|
1728
|
+
else {
|
|
1729
|
+
range = Area.CellAddressToLabel(area.start);
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
if (!qualified) {
|
|
1733
|
+
return range;
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
// is there a function to resolve sheet? actually, don't we know that
|
|
1737
|
+
// the active selection must be on the active sheet? (...)
|
|
1738
|
+
|
|
1739
|
+
const sheet_id = area.start.sheet_id || context?.id;
|
|
1740
|
+
const sheet_name = this.ResolveSheetName(sheet_id, true);
|
|
1741
|
+
|
|
1742
|
+
return sheet_name ? sheet_name + '!' + range : range;
|
|
1743
|
+
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
/**
|
|
1747
|
+
*
|
|
1748
|
+
*/
|
|
1749
|
+
public ResolveSheetName(id: number, quote = false): string | undefined {
|
|
1750
|
+
const sheet = this.model.sheets.Find(id);
|
|
1751
|
+
if (sheet) {
|
|
1752
|
+
if (quote && QuotedSheetNameRegex.test(sheet.name)) {
|
|
1753
|
+
return `'${sheet.name}'`;
|
|
1754
|
+
}
|
|
1755
|
+
return sheet.name;
|
|
1756
|
+
}
|
|
1757
|
+
return undefined;
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
public RemoveConditional(conditional: ConditionalFormat): void {
|
|
1761
|
+
if (conditional.type === 'expression') {
|
|
1762
|
+
const vertex = conditional.internal?.vertex as LeafVertex;
|
|
1763
|
+
if (vertex) {
|
|
1764
|
+
vertex.Reset();
|
|
1765
|
+
this.RemoveLeafVertex(vertex);
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
public UpdateConditionals(list?: ConditionalFormat|ConditionalFormat[], context?: Sheet): void {
|
|
1771
|
+
|
|
1772
|
+
if (!list) {
|
|
1773
|
+
for (const sheet of this.model.sheets.list) {
|
|
1774
|
+
if (sheet.conditional_formats?.length) {
|
|
1775
|
+
this.UpdateConditionals(sheet.conditional_formats, sheet);
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
return;
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
if (!context) {
|
|
1782
|
+
throw new Error('invalid call to update conditionals without context');
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1785
|
+
if (list && !Array.isArray(list)) {
|
|
1786
|
+
list = [list];
|
|
1787
|
+
}
|
|
1788
|
+
|
|
1789
|
+
for (const entry of list) {
|
|
1790
|
+
|
|
1791
|
+
let expression = '';
|
|
1792
|
+
|
|
1793
|
+
switch (entry.type) {
|
|
1794
|
+
case 'cell-match':
|
|
1795
|
+
expression = this.Unresolve(entry.area, context, true, false) + ' ' + entry.expression;
|
|
1796
|
+
break;
|
|
1797
|
+
|
|
1798
|
+
case 'expression':
|
|
1799
|
+
expression = entry.expression;
|
|
1800
|
+
break;
|
|
1801
|
+
|
|
1802
|
+
case 'duplicate-values':
|
|
1803
|
+
expression = `UniqueValues(${
|
|
1804
|
+
this.Unresolve(entry.area, context, true, false)
|
|
1805
|
+
})`;
|
|
1806
|
+
if (!entry.unique) {
|
|
1807
|
+
expression = `NOT(${expression})`;
|
|
1808
|
+
}
|
|
1809
|
+
break;
|
|
1810
|
+
|
|
1811
|
+
case 'gradient':
|
|
1812
|
+
expression = `=Gradient(${
|
|
1813
|
+
[
|
|
1814
|
+
this.Unresolve(entry.area, context, true, false),
|
|
1815
|
+
entry.min ?? '',
|
|
1816
|
+
entry.max ?? '',
|
|
1817
|
+
|
|
1818
|
+
].join(this.parser.argument_separator)
|
|
1819
|
+
})`;
|
|
1820
|
+
break;
|
|
1821
|
+
|
|
1822
|
+
default:
|
|
1823
|
+
continue;
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
if (!expression) {
|
|
1827
|
+
continue; // FIXME: warn?
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
// console.info({type: entry.type, expression});
|
|
1831
|
+
|
|
1832
|
+
if (!entry.internal) {
|
|
1833
|
+
entry.internal = {};
|
|
1834
|
+
}
|
|
1835
|
+
if (!entry.internal.vertex) {
|
|
1836
|
+
entry.internal.vertex = new CalculationLeafVertex();
|
|
1837
|
+
|
|
1838
|
+
let options: EvaluateOptions|undefined;
|
|
1839
|
+
if (entry.type !== 'gradient' && entry.type !== 'duplicate-values') {
|
|
1840
|
+
options = entry.options;
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
// first pass, run the calculation
|
|
1844
|
+
const check = this.Evaluate(expression, context, options, true);
|
|
1845
|
+
entry.internal.vertex.result = check;
|
|
1846
|
+
entry.internal.vertex.updated = true;
|
|
1847
|
+
|
|
1848
|
+
}
|
|
1849
|
+
|
|
1850
|
+
const vertex = entry.internal.vertex as LeafVertex;
|
|
1851
|
+
this.AddLeafVertex(vertex);
|
|
1852
|
+
this.UpdateLeafVertex(vertex, expression, context);
|
|
1853
|
+
|
|
1854
|
+
/*
|
|
1855
|
+
if (entry.type === 'cell-match') {
|
|
1856
|
+
if (!entry.internal) {
|
|
1857
|
+
entry.internal = {};
|
|
1858
|
+
}
|
|
1859
|
+
if (!entry.internal.vertex) {
|
|
1860
|
+
entry.internal.vertex = new CalculationLeafVertex();
|
|
1861
|
+
}
|
|
1862
|
+
const vertex = entry.internal.vertex as LeafVertex;
|
|
1863
|
+
this.AddLeafVertex(vertex);
|
|
1864
|
+
this.UpdateLeafVertex(vertex, entry.expression, context);
|
|
1865
|
+
}
|
|
1866
|
+
else if (entry.type === 'expression') {
|
|
1867
|
+
if (!entry.internal) {
|
|
1868
|
+
entry.internal = {};
|
|
1869
|
+
}
|
|
1870
|
+
if (!entry.internal.vertex) {
|
|
1871
|
+
entry.internal.vertex = new CalculationLeafVertex();
|
|
1872
|
+
|
|
1873
|
+
// set initial state based on current state
|
|
1874
|
+
entry.internal.vertex.result = { type: ValueType.boolean, value: !!entry.applied };
|
|
1875
|
+
|
|
1876
|
+
}
|
|
1877
|
+
const vertex = entry.internal.vertex as LeafVertex;
|
|
1878
|
+
this.AddLeafVertex(vertex);
|
|
1879
|
+
this.UpdateLeafVertex(vertex, entry.expression, context);
|
|
1880
|
+
}
|
|
1881
|
+
*/
|
|
1882
|
+
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1725
1887
|
public RemoveAnnotation(annotation: Annotation): void {
|
|
1726
1888
|
const vertex = (annotation.temp.vertex as LeafVertex);
|
|
1727
1889
|
if (!vertex) { return; }
|
|
@@ -1756,7 +1918,7 @@ export class Calculator extends Graph {
|
|
|
1756
1918
|
for (const entry of list) {
|
|
1757
1919
|
if (entry.data.formula) {
|
|
1758
1920
|
if (!entry.temp.vertex) {
|
|
1759
|
-
entry.temp.vertex = new
|
|
1921
|
+
entry.temp.vertex = new StateLeafVertex();
|
|
1760
1922
|
}
|
|
1761
1923
|
const vertex = entry.temp.vertex as LeafVertex;
|
|
1762
1924
|
this.AddLeafVertex(vertex);
|
|
@@ -0,0 +1,97 @@
|
|
|
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 type { Vertex} from './vertex';
|
|
25
|
+
import { Color } from './vertex';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* adding a new leaf vertex type that actually does a calculation;
|
|
29
|
+
* but it has no spreadsheet context (address) and by definition it
|
|
30
|
+
* has no dependendents.
|
|
31
|
+
*
|
|
32
|
+
* this is intended for managing conditional formats, if they have
|
|
33
|
+
* an expression. we only want to calculate these when necessary
|
|
34
|
+
* (i.e. dependencies have updated, or they are volatile).
|
|
35
|
+
*
|
|
36
|
+
*/
|
|
37
|
+
export class CalculationLeafVertex extends SpreadsheetVertex {
|
|
38
|
+
|
|
39
|
+
public static type = 'calculation-leaf-vertex';
|
|
40
|
+
|
|
41
|
+
public type = CalculationLeafVertex.type; // for type guard
|
|
42
|
+
|
|
43
|
+
public address = { row: -1, column: -1 }; // fake address
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* flag, to reduce unecessary application. work in progress. this
|
|
47
|
+
* indicates that we reached the calculation step. that means either
|
|
48
|
+
* (1) dependencies changed, or (2) we were marked dirty in some global
|
|
49
|
+
* operation, probably a full-recalc.
|
|
50
|
+
*
|
|
51
|
+
* (2) is a waste but we're still going to save some cycles here. if you
|
|
52
|
+
* want you could add a state check like the other leaf vertex.
|
|
53
|
+
*/
|
|
54
|
+
public updated = false;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* leaf vertex defaults to black (i.e. tested) because leaf nodes cannot have
|
|
58
|
+
* outbound edges. it is still possible to change this, because it's a property
|
|
59
|
+
* and we can't override the set accessor, but making it an accessor in the
|
|
60
|
+
* superclass just for this purpose is not worthwhile since regular vertices
|
|
61
|
+
* should vastly outnumber leaves.
|
|
62
|
+
*/
|
|
63
|
+
public color = Color.black;
|
|
64
|
+
|
|
65
|
+
/** overrides calculate function */
|
|
66
|
+
public Calculate(graph: GraphCallbacks): void {
|
|
67
|
+
|
|
68
|
+
// if we are not dirty, nothing to do
|
|
69
|
+
if (!this.dirty) return;
|
|
70
|
+
|
|
71
|
+
// check deps
|
|
72
|
+
for (const edge of this.edges_in) {
|
|
73
|
+
if ((edge as SpreadsheetVertex).dirty) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ...
|
|
79
|
+
|
|
80
|
+
const result = graph.CalculationCallback.call(graph, this);
|
|
81
|
+
|
|
82
|
+
this.result = result.value;
|
|
83
|
+
this.dirty = false;
|
|
84
|
+
|
|
85
|
+
// set flag
|
|
86
|
+
|
|
87
|
+
this.updated = true;
|
|
88
|
+
|
|
89
|
+
// we are not allowed to have edges out, so nothing to do
|
|
90
|
+
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public AddDependent(edge: Vertex): void {
|
|
94
|
+
throw(new Error('leaf vertex cannot have dependents'));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
}
|
|
@@ -24,10 +24,13 @@ import { Color } from './vertex';
|
|
|
24
24
|
import { SpreadsheetVertex } from './spreadsheet_vertex';
|
|
25
25
|
import { ArrayVertex } from './array-vertex';
|
|
26
26
|
import type { SpreadsheetVertexBase, CalculationResult, GraphCallbacks } from './spreadsheet_vertex_base';
|
|
27
|
-
import type {
|
|
27
|
+
import type { StateLeafVertex } from './state_leaf_vertex';
|
|
28
28
|
import type { ICellAddress, ICellAddress2, IArea, UnionValue } from 'treb-base-types';
|
|
29
29
|
import { Area } from 'treb-base-types';
|
|
30
30
|
import type { DataModel } from 'treb-grid';
|
|
31
|
+
import { CalculationLeafVertex } from './calculation_leaf_vertex';
|
|
32
|
+
|
|
33
|
+
export type LeafVertex = StateLeafVertex|CalculationLeafVertex;
|
|
31
34
|
|
|
32
35
|
// FIXME: this is a bad habit if you're testing on falsy for OK.
|
|
33
36
|
|
|
@@ -61,7 +64,8 @@ export abstract class Graph implements GraphCallbacks {
|
|
|
61
64
|
public loop_hint?: string;
|
|
62
65
|
|
|
63
66
|
// special
|
|
64
|
-
public leaf_vertices: LeafVertex[] = [];
|
|
67
|
+
// public leaf_vertices: LeafVertex[] = [];
|
|
68
|
+
public leaf_vertices: Set<LeafVertex> = new Set();
|
|
65
69
|
|
|
66
70
|
/** lock down access */
|
|
67
71
|
private dirty_list: SpreadsheetVertexBase[] = [];
|
|
@@ -102,7 +106,7 @@ export abstract class Graph implements GraphCallbacks {
|
|
|
102
106
|
this.dirty_list = [];
|
|
103
107
|
this.volatile_list = [];
|
|
104
108
|
this.vertices = [[]];
|
|
105
|
-
this.leaf_vertices
|
|
109
|
+
this.leaf_vertices.clear();
|
|
106
110
|
// this.cells_map = {};
|
|
107
111
|
|
|
108
112
|
/** array vertex maintains its own list */
|
|
@@ -812,28 +816,12 @@ export abstract class Graph implements GraphCallbacks {
|
|
|
812
816
|
* managing and maintaining these vertices: we only need references.
|
|
813
817
|
*/
|
|
814
818
|
public AddLeafVertex(vertex: LeafVertex): void {
|
|
815
|
-
|
|
816
|
-
// ... don't add more than once. this is expensive but
|
|
817
|
-
// the list should (generally speaking) be short, so not
|
|
818
|
-
// a serious problem atm
|
|
819
|
-
|
|
820
|
-
/*
|
|
821
|
-
if (this.leaf_vertices.some((test) => test === vertex)) {
|
|
822
|
-
return;
|
|
823
|
-
}
|
|
824
|
-
*/
|
|
825
|
-
for (const test of this.leaf_vertices) {
|
|
826
|
-
if (test === vertex) {
|
|
827
|
-
return;
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
this.leaf_vertices.push(vertex);
|
|
819
|
+
this.leaf_vertices.add(vertex);
|
|
832
820
|
}
|
|
833
821
|
|
|
834
|
-
/** removes vertex
|
|
822
|
+
/** removes vertex */
|
|
835
823
|
public RemoveLeafVertex(vertex: LeafVertex): void {
|
|
836
|
-
this.leaf_vertices
|
|
824
|
+
this.leaf_vertices.delete(vertex);
|
|
837
825
|
}
|
|
838
826
|
|
|
839
827
|
/**
|
|
@@ -40,12 +40,12 @@ import { Color } from './vertex';
|
|
|
40
40
|
* have both leaf- and spreadsheet-vertex extend that.
|
|
41
41
|
*
|
|
42
42
|
*/
|
|
43
|
-
export class
|
|
43
|
+
export class StateLeafVertex extends SpreadsheetVertex {
|
|
44
44
|
|
|
45
|
-
public static type = 'leaf-vertex';
|
|
45
|
+
public static type = 'state-leaf-vertex';
|
|
46
46
|
|
|
47
47
|
public state_id = 0;
|
|
48
|
-
public type =
|
|
48
|
+
public type = StateLeafVertex.type; // for type guard
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* leaf vertex defaults to black (i.e. tested) because leaf nodes cannot have
|
|
@@ -112,10 +112,17 @@ export interface CompositeFunctionDescriptor {
|
|
|
112
112
|
fn: (...args: any[]) => UnionValue; // UnionOrArray; // |UnitAddress|UnitRange;
|
|
113
113
|
|
|
114
114
|
/**
|
|
115
|
-
*
|
|
116
|
-
*
|
|
115
|
+
* limited visibility
|
|
116
|
+
*
|
|
117
|
+
* internal functions do not show up in the spreadsheet. we have an
|
|
118
|
+
* annotation value which should be usef in the future but it's not
|
|
119
|
+
* implemented yet.
|
|
120
|
+
*
|
|
121
|
+
* should we allow these functions to be used, and just not tooltip them;
|
|
122
|
+
* or block them entirely? for now we'll do the former as it's helpful to
|
|
123
|
+
* defug.
|
|
117
124
|
*/
|
|
118
|
-
visibility?:
|
|
125
|
+
visibility?: 'internal'|'annotation';
|
|
119
126
|
|
|
120
127
|
/**
|
|
121
128
|
* for the future
|
|
@@ -821,7 +821,7 @@ export class ExpressionCalculator {
|
|
|
821
821
|
const value: UnionValue[][] = [];
|
|
822
822
|
|
|
823
823
|
for (let c = 0; c < columns; c++) {
|
|
824
|
-
const col = [];
|
|
824
|
+
const col: UnionValue[] = [];
|
|
825
825
|
for (let r = 0; r < rows; r++ ) {
|
|
826
826
|
col[r] = fn(left_values[c][r], right_values[c][r]);
|
|
827
827
|
}
|
|
@@ -1,24 +1,24 @@
|
|
|
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
|
-
|
|
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
22
|
import type {
|
|
23
23
|
ExtendedFunctionDescriptor, CompositeFunctionDescriptor,
|
|
24
24
|
FunctionMap, ExtendedFunctionMap } from './descriptors';
|
|
@@ -80,9 +80,12 @@ export class FunctionLibrary {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
/** get a list, for AC services */
|
|
83
|
-
public List() {
|
|
83
|
+
public List(filter_internal = true) {
|
|
84
84
|
const list: ExtendedFunctionMap = {};
|
|
85
85
|
for (const key of Object.keys(this.functions)) {
|
|
86
|
+
if (filter_internal && this.functions[key].visibility === 'internal') {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
86
89
|
list[key] = this.functions[key];
|
|
87
90
|
}
|
|
88
91
|
return list;
|