@odoo/o-spreadsheet 17.2.0-alpha.8 → 17.2.1

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.
@@ -3,9 +3,9 @@
3
3
  /**
4
4
  * This file is generated by o-spreadsheet build tools. Do not edit it.
5
5
  * @see https://github.com/odoo/o-spreadsheet
6
- * @version 17.2.0-alpha.8
7
- * @date 2024-03-15T11:01:01.388Z
8
- * @hash 11cf381
6
+ * @version 17.2.1
7
+ * @date 2024-03-25T09:41:58.737Z
8
+ * @hash f97284c
9
9
  */
10
10
 
11
11
  (function (exports, owl) {
@@ -30,7 +30,6 @@
30
30
  const LINK_COLOR = "#017E84";
31
31
  const FILTERS_COLOR = "#188038";
32
32
  const BACKGROUND_HEADER_FILTER_COLOR = "#E6F4EA";
33
- const BACKGROUND_HEADER_SELECTED_FILTER_COLOR = "#CEEAD6";
34
33
  const SEPARATOR_COLOR = "#E0E2E4";
35
34
  const ICONS_COLOR = "#4A4F59";
36
35
  const HEADER_GROUPING_BACKGROUND_COLOR = "#F5F5F5";
@@ -641,21 +640,6 @@
641
640
  }
642
641
  return true;
643
642
  }
644
- class JetSet extends Set {
645
- addMany(iterable) {
646
- for (const element of iterable) {
647
- super.add(element);
648
- }
649
- return this;
650
- }
651
- deleteMany(iterable) {
652
- let wasDeleted = false;
653
- for (const element of iterable) {
654
- wasDeleted ||= super.delete(element);
655
- }
656
- return wasDeleted;
657
- }
658
- }
659
643
  /**
660
644
  * Creates a version of the function that's memoized on the value of its first
661
645
  * argument, if any.
@@ -4101,14 +4085,6 @@
4101
4085
  }
4102
4086
  return positions;
4103
4087
  }
4104
- function forEachPositionsInZone(zone, callback) {
4105
- const { left, right, top, bottom } = zone;
4106
- for (let col = left; col <= right; col++) {
4107
- for (let row = top; row <= bottom; row++) {
4108
- callback(col, row);
4109
- }
4110
- }
4111
- }
4112
4088
  /**
4113
4089
  * This function returns a zone with coordinates modified according to the change
4114
4090
  * applied to the zone. It may be possible to change the zone by resizing or moving
@@ -8027,6 +8003,9 @@
8027
8003
  instantiate(Store, ...args) {
8028
8004
  return this.factory.build(Store, ...args);
8029
8005
  }
8006
+ resetStores() {
8007
+ this.dependencies.clear();
8008
+ }
8030
8009
  }
8031
8010
  class StoreFactory {
8032
8011
  get;
@@ -10054,6 +10033,9 @@ stores.inject(MyMetaStore, storeInstance);
10054
10033
  result.default = true;
10055
10034
  result.defaultValue = defaultValue;
10056
10035
  }
10036
+ if (types.some((t) => t.startsWith("RANGE"))) {
10037
+ result.acceptMatrix = true;
10038
+ }
10057
10039
  return result;
10058
10040
  }
10059
10041
  /**
@@ -18624,11 +18606,27 @@ stores.inject(MyMetaStore, storeInstance);
18624
18606
  }
18625
18607
  const descr = addMetaInfoFromArg(addDescr);
18626
18608
  validateArguments(descr.args);
18627
- this.mapping[name] = addErrorHandling(addResultHandling(descr.compute), name);
18609
+ this.mapping[name] = addErrorHandling(addResultHandling(addInputHandling(descr)), name);
18628
18610
  super.add(name, descr);
18629
18611
  return this;
18630
18612
  }
18631
18613
  }
18614
+ function addInputHandling(descr) {
18615
+ function computeWithInputHandling(...args) {
18616
+ for (let i = 0; i < args.length; i++) {
18617
+ const argDefinition = descr.args[descr.getArgToFocus(i + 1) - 1];
18618
+ const arg = args[i];
18619
+ if (isMatrix(arg) && !argDefinition.acceptMatrix) {
18620
+ if (arg.length !== 1 || arg[0].length !== 1) {
18621
+ throw new EvaluationError(_t("Function [[FUNCTION_NAME]] expects the parameter '%s' to be a single value or a single cell reference, not a range.", argDefinition.name));
18622
+ }
18623
+ args[i] = arg[0][0];
18624
+ }
18625
+ }
18626
+ return descr.compute.apply(this, args);
18627
+ }
18628
+ return computeWithInputHandling;
18629
+ }
18632
18630
  function addErrorHandling(compute, functionName) {
18633
18631
  return function (...args) {
18634
18632
  try {
@@ -24218,14 +24216,19 @@ stores.inject(MyMetaStore, storeInstance);
24218
24216
  children: [allFunctionListMenuBuilder],
24219
24217
  };
24220
24218
  function allFunctionListMenuBuilder() {
24221
- const fnNames = functionRegistry.getKeys();
24219
+ const fnNames = functionRegistry.getKeys().filter((key) => !functionRegistry.get(key).hidden);
24222
24220
  return createFormulaFunctions(fnNames);
24223
24221
  }
24224
24222
  const categoriesFunctionListMenuBuilder = () => {
24225
24223
  const functions = functionRegistry.content;
24226
- const categories = [...new Set(functionRegistry.getAll().map((fn) => fn.category))].filter(isDefined$1);
24224
+ const categories = [
24225
+ ...new Set(functionRegistry
24226
+ .getAll()
24227
+ .filter((fn) => !fn.hidden)
24228
+ .map((fn) => fn.category)),
24229
+ ].filter(isDefined$1);
24227
24230
  return categories.sort().map((category, i) => {
24228
- const functionsInCategory = Object.keys(functions).filter((key) => functions[key].category === category);
24231
+ const functionsInCategory = Object.keys(functions).filter((key) => functions[key].category === category && !functions[key].hidden);
24229
24232
  return {
24230
24233
  name: category,
24231
24234
  children: createFormulaFunctions(functionsInCategory),
@@ -28383,11 +28386,9 @@ stores.inject(MyMetaStore, storeInstance);
28383
28386
  }
28384
28387
  .o-cell-is-operator {
28385
28388
  margin-bottom: 5px;
28386
- width: 96%;
28387
28389
  }
28388
28390
  .o-cell-is-value {
28389
28391
  margin-bottom: 5px;
28390
- width: 96%;
28391
28392
  }
28392
28393
  .o-color-picker-widget .o-color-picker-button {
28393
28394
  pointer-events: all;
@@ -31089,6 +31090,9 @@ stores.inject(MyMetaStore, storeInstance);
31089
31090
  el?.focus({ preventScroll: true });
31090
31091
  }
31091
31092
  }, () => [this.env.model.getters.getSelectedFigureId(), this.props.figure.id, this.figureRef.el]);
31093
+ owl.onWillUnmount(() => {
31094
+ this.props.onFigureDeleted();
31095
+ });
31092
31096
  }
31093
31097
  clickAnchor(dirX, dirY, ev) {
31094
31098
  this.props.onClickAnchor(dirX, dirY, ev);
@@ -31107,6 +31111,7 @@ stores.inject(MyMetaStore, storeInstance);
31107
31111
  this.props.onFigureDeleted();
31108
31112
  ev.stopPropagation();
31109
31113
  ev.preventDefault();
31114
+ ev.stopPropagation();
31110
31115
  break;
31111
31116
  case "ArrowDown":
31112
31117
  case "ArrowLeft":
@@ -31127,6 +31132,7 @@ stores.inject(MyMetaStore, storeInstance);
31127
31132
  });
31128
31133
  ev.stopPropagation();
31129
31134
  ev.preventDefault();
31135
+ ev.stopPropagation();
31130
31136
  break;
31131
31137
  }
31132
31138
  }
@@ -31794,6 +31800,7 @@ stores.inject(MyMetaStore, storeInstance);
31794
31800
  // -----------------------------------------------------------------------------
31795
31801
  css /* scss */ `
31796
31802
  .o-formula-assistant {
31803
+ background: #ffffff;
31797
31804
  .o-formula-assistant-head {
31798
31805
  background-color: #f2f2f2;
31799
31806
  padding: 10px;
@@ -31849,6 +31856,9 @@ stores.inject(MyMetaStore, storeInstance);
31849
31856
  this.assistantState.allowCellSelectionBehind = false;
31850
31857
  }, 2000);
31851
31858
  }
31859
+ get formulaArgSeparator() {
31860
+ return this.env.model.getters.getLocale().formulaArgSeparator + " ";
31861
+ }
31852
31862
  }
31853
31863
 
31854
31864
  const functions$2 = functionRegistry.content;
@@ -34618,19 +34628,16 @@ stores.inject(MyMetaStore, storeInstance);
34618
34628
  for (let col = left; col <= right; col++) {
34619
34629
  const colZone = { left: col, right: col, top: 0, bottom: numberOfRows - 1 };
34620
34630
  const { x, width } = this.getters.getVisibleRect(colZone);
34621
- const colHasFilter = this.getters.doesZonesContainFilter(sheetId, [colZone]);
34622
34631
  const isColActive = activeCols.has(col);
34623
34632
  const isColSelected = selectedCols.has(col);
34624
34633
  if (isColActive) {
34625
- ctx.fillStyle = colHasFilter ? FILTERS_COLOR : BACKGROUND_HEADER_ACTIVE_COLOR;
34634
+ ctx.fillStyle = BACKGROUND_HEADER_ACTIVE_COLOR;
34626
34635
  }
34627
34636
  else if (isColSelected) {
34628
- ctx.fillStyle = colHasFilter
34629
- ? BACKGROUND_HEADER_SELECTED_FILTER_COLOR
34630
- : BACKGROUND_HEADER_SELECTED_COLOR;
34637
+ ctx.fillStyle = BACKGROUND_HEADER_SELECTED_COLOR;
34631
34638
  }
34632
34639
  else {
34633
- ctx.fillStyle = colHasFilter ? BACKGROUND_HEADER_FILTER_COLOR : BACKGROUND_HEADER_COLOR;
34640
+ ctx.fillStyle = BACKGROUND_HEADER_COLOR;
34634
34641
  }
34635
34642
  ctx.fillRect(x, 0, width, HEADER_HEIGHT);
34636
34643
  }
@@ -34638,19 +34645,16 @@ stores.inject(MyMetaStore, storeInstance);
34638
34645
  for (let row = top; row <= bottom; row++) {
34639
34646
  const rowZone = { top: row, bottom: row, left: 0, right: numberOfCols - 1 };
34640
34647
  const { y, height } = this.getters.getVisibleRect(rowZone);
34641
- const rowHasFilter = this.getters.doesZonesContainFilter(sheetId, [rowZone]);
34642
34648
  const isRowActive = activeRows.has(row);
34643
34649
  const isRowSelected = selectedRows.has(row);
34644
34650
  if (isRowActive) {
34645
- ctx.fillStyle = rowHasFilter ? FILTERS_COLOR : BACKGROUND_HEADER_ACTIVE_COLOR;
34651
+ ctx.fillStyle = BACKGROUND_HEADER_ACTIVE_COLOR;
34646
34652
  }
34647
34653
  else if (isRowSelected) {
34648
- ctx.fillStyle = rowHasFilter
34649
- ? BACKGROUND_HEADER_SELECTED_FILTER_COLOR
34650
- : BACKGROUND_HEADER_SELECTED_COLOR;
34654
+ ctx.fillStyle = BACKGROUND_HEADER_SELECTED_COLOR;
34651
34655
  }
34652
34656
  else {
34653
- ctx.fillStyle = rowHasFilter ? BACKGROUND_HEADER_FILTER_COLOR : BACKGROUND_HEADER_COLOR;
34657
+ ctx.fillStyle = BACKGROUND_HEADER_COLOR;
34654
34658
  }
34655
34659
  ctx.fillRect(0, y, HEADER_WIDTH, height);
34656
34660
  }
@@ -44823,7 +44827,6 @@ stores.inject(MyMetaStore, storeInstance);
44823
44827
 
44824
44828
  class TablePlugin extends CorePlugin {
44825
44829
  static getters = [
44826
- "doesZonesContainFilter",
44827
44830
  "getFilter",
44828
44831
  "getFilters",
44829
44832
  "getTable",
@@ -44980,10 +44983,6 @@ stores.inject(MyMetaStore, storeInstance);
44980
44983
  getTablesOverlappingZones(sheetId, zones) {
44981
44984
  return this.getTables(sheetId).filter((table) => zones.some((zone) => overlap(table.range.zone, zone)));
44982
44985
  }
44983
- doesZonesContainFilter(sheetId, zones) {
44984
- return (this.getTablesOverlappingZones(sheetId, zones).filter((table) => table.config.hasFilters)
44985
- .length > 0);
44986
- }
44987
44986
  getFilterHeaders(sheetId) {
44988
44987
  const headers = [];
44989
44988
  for (const table of this.getTables(sheetId)) {
@@ -45850,6 +45849,41 @@ stores.inject(MyMetaStore, storeInstance);
45850
45849
  }
45851
45850
  }
45852
45851
 
45852
+ class PositionMap {
45853
+ map = {};
45854
+ set({ sheetId, col, row }, value) {
45855
+ const map = this.map;
45856
+ if (!map[sheetId]) {
45857
+ map[sheetId] = {};
45858
+ }
45859
+ if (!map[sheetId][col]) {
45860
+ map[sheetId][col] = {};
45861
+ }
45862
+ map[sheetId][col][row] = value;
45863
+ }
45864
+ get({ sheetId, col, row }) {
45865
+ return this.map[sheetId]?.[col]?.[row];
45866
+ }
45867
+ has({ sheetId, col, row }) {
45868
+ return this.map[sheetId]?.[col]?.[row] !== undefined;
45869
+ }
45870
+ delete({ sheetId, col, row }) {
45871
+ delete this.map[sheetId]?.[col]?.[row];
45872
+ }
45873
+ keys() {
45874
+ const map = this.map;
45875
+ const keys = [];
45876
+ for (const sheetId in map) {
45877
+ for (const col in map[sheetId]) {
45878
+ for (const row in map[sheetId][col]) {
45879
+ keys.push({ sheetId, col: parseInt(col), row: parseInt(row) });
45880
+ }
45881
+ }
45882
+ }
45883
+ return keys;
45884
+ }
45885
+ }
45886
+
45853
45887
  function quickselect(arr, k, left, right, compare) {
45854
45888
  quickselectStep(arr, k, left || 0, right || (arr.length - 1), compare || defaultCompare);
45855
45889
  }
@@ -46576,26 +46610,26 @@ stores.inject(MyMetaStore, storeInstance);
46576
46610
  * It uses an R-Tree data structure to efficiently find dependent cells.
46577
46611
  */
46578
46612
  class FormulaDependencyGraph {
46579
- encoder;
46580
- dependencies = new Map();
46613
+ createEmptyPositionSet;
46614
+ dependencies = new PositionMap();
46581
46615
  rTree;
46582
- constructor(encoder, data = []) {
46583
- this.encoder = encoder;
46616
+ constructor(createEmptyPositionSet, data = []) {
46617
+ this.createEmptyPositionSet = createEmptyPositionSet;
46584
46618
  this.rTree = new SpreadsheetRTree(data);
46585
46619
  }
46586
- removeAllDependencies(formulaPositionId) {
46587
- const ranges = this.dependencies.get(formulaPositionId);
46620
+ removeAllDependencies(formulaPosition) {
46621
+ const ranges = this.dependencies.get(formulaPosition);
46588
46622
  if (!ranges) {
46589
46623
  return;
46590
46624
  }
46591
46625
  for (const range of ranges) {
46592
46626
  this.rTree.remove(range);
46593
46627
  }
46594
- this.dependencies.delete(formulaPositionId);
46628
+ this.dependencies.delete(formulaPosition);
46595
46629
  }
46596
- addDependencies(formulaPositionId, dependencies) {
46630
+ addDependencies(formulaPosition, dependencies) {
46597
46631
  const rTreeItems = dependencies.map(({ sheetId, zone }) => ({
46598
- data: formulaPositionId,
46632
+ data: formulaPosition,
46599
46633
  boundingBox: {
46600
46634
  zone,
46601
46635
  sheetId,
@@ -46604,12 +46638,12 @@ stores.inject(MyMetaStore, storeInstance);
46604
46638
  for (const item of rTreeItems) {
46605
46639
  this.rTree.insert(item);
46606
46640
  }
46607
- const existingDependencies = this.dependencies.get(formulaPositionId);
46641
+ const existingDependencies = this.dependencies.get(formulaPosition);
46608
46642
  if (existingDependencies) {
46609
46643
  existingDependencies.push(...rTreeItems);
46610
46644
  }
46611
46645
  else {
46612
- this.dependencies.set(formulaPositionId, rTreeItems);
46646
+ this.dependencies.set(formulaPosition, rTreeItems);
46613
46647
  }
46614
46648
  }
46615
46649
  /**
@@ -46618,23 +46652,194 @@ stores.inject(MyMetaStore, storeInstance);
46618
46652
  * This is called a topological ordering (excluding cycles)
46619
46653
  */
46620
46654
  getCellsDependingOn(ranges) {
46621
- const visited = new JetSet();
46655
+ const visited = this.createEmptyPositionSet();
46622
46656
  const queue = Array.from(ranges).reverse();
46623
46657
  while (queue.length > 0) {
46624
46658
  const range = queue.pop();
46625
- visited.addMany(this.encoder.encodeBoundingBox(range));
46626
- const impactedPositionIds = this.rTree.search(range).map((dep) => dep.data);
46627
- for (const positionId of impactedPositionIds) {
46628
- if (!visited.has(positionId)) {
46629
- queue.push(this.encoder.decodeToBoundingBox(positionId));
46659
+ visited.addMany(positions(range.zone).map((position) => ({ sheetId: range.sheetId, ...position })));
46660
+ const impactedPositions = this.rTree.search(range).map((dep) => dep.data);
46661
+ for (const position of impactedPositions) {
46662
+ if (!visited.has(position)) {
46663
+ queue.push({ sheetId: position.sheetId, zone: positionToZone(position) });
46630
46664
  }
46631
46665
  }
46632
46666
  }
46633
- visited.deleteMany(ranges.flatMap((r) => this.encoder.encodeBoundingBox(r)));
46667
+ visited.deleteMany(ranges.flatMap((r) => positions(r.zone).map((position) => ({ sheetId: r.sheetId, ...position }))));
46634
46668
  return visited;
46635
46669
  }
46636
46670
  }
46637
46671
 
46672
+ /**
46673
+ * Implements a fixed-sized grid or 2D matrix of bits.
46674
+ * based on https://github.com/zandaqo/structurae
46675
+ *
46676
+ * The grid is implemented as a 1D array of 32-bit integers, where each bit represents a cell in the grid.
46677
+ * It follows row-major order, with each row stored consecutively in 32-bit blocks.
46678
+ * Pads the number of columns to the next power of 2 to allow quick lookups with bitwise operations.
46679
+ *
46680
+ * Key terminology:
46681
+ * - bucket: Index of an item in the Uint32Array, a 32-bit integer.
46682
+ * - bitPosition: The position of a bit within the bucket 32-bit integer.
46683
+ */
46684
+ class BinaryGrid extends Uint32Array {
46685
+ columnOffset = 0;
46686
+ cols = 0;
46687
+ rows = 0;
46688
+ /**
46689
+ * Creates a binary grid of specified dimensions.
46690
+ */
46691
+ static create(rows, columns) {
46692
+ const columnOffset = log2Ceil(columns);
46693
+ const length = (rows << columnOffset) >> 5;
46694
+ const grid = new this(length + 1);
46695
+ grid.columnOffset = columnOffset;
46696
+ grid.cols = columns;
46697
+ grid.rows = rows;
46698
+ return grid;
46699
+ }
46700
+ /**
46701
+ * Returns the bit at given coordinates.
46702
+ */
46703
+ getValue(position) {
46704
+ const [bucket, bitPosition] = this.getCoordinates(position);
46705
+ return ((this[bucket] >> bitPosition) & 1);
46706
+ }
46707
+ /**
46708
+ * Sets the bit at given coordinates.
46709
+ */
46710
+ setValue(position, value) {
46711
+ const [bucket, bitPosition] = this.getCoordinates(position);
46712
+ const currentValue = (this[bucket] >> bitPosition) & 1;
46713
+ const hasBeenInserted = currentValue === 0 && value === 1;
46714
+ this[bucket] = (this[bucket] & ~(1 << bitPosition)) | (value << bitPosition);
46715
+ return hasBeenInserted;
46716
+ // Let's breakdown of the above line:
46717
+ // with an example with a 4-bit integer (instead of 32-bit).
46718
+ //
46719
+ // Let's say we want to set the bit at position 2 to 1 and the existing
46720
+ // bit sequence this[bucket] is 1001. The final bit sequence should be 1101.
46721
+ //
46722
+ // First, we clear the bit at position 2 by AND-ing this[bucket] with a
46723
+ // mask having all 1s except a 0 at the bit position (~ (1 << bitPosition)).
46724
+ // 1 << bitPosition is 0100 (shifting 0001 to the left by 2)
46725
+ // Inverting the bits with ~ gives the final mask ~(1 << bitPosition): 1011
46726
+ //
46727
+ // Then, we shift the value by the bit position (value << bitPosition: 0100)
46728
+ // and OR the result with the previous step's result:
46729
+ // (1001 & 1011) | 0100 = 1101
46730
+ }
46731
+ isEmpty() {
46732
+ return !this.some((bucket) => bucket !== 0);
46733
+ }
46734
+ fillAllPositions() {
46735
+ const thirtyTwoOnes = -1 >>> 0; // same as 2 ** 32 - 1, a 32-bit number with all bits set to 1
46736
+ this.fill(thirtyTwoOnes);
46737
+ }
46738
+ clear() {
46739
+ this.fill(0);
46740
+ }
46741
+ getCoordinates(position) {
46742
+ const { row, col } = position;
46743
+ const index = (row << this.columnOffset) + col;
46744
+ const bucket = index >> 5;
46745
+ return [bucket, index - (bucket << 5)];
46746
+ }
46747
+ }
46748
+ function log2Ceil(value) {
46749
+ // A faster version of Math.ceil(Math.log2(value)).
46750
+ if (value === 0) {
46751
+ return -Infinity;
46752
+ }
46753
+ else if (value < 0) {
46754
+ return NaN;
46755
+ }
46756
+ // --value handles the case where value is a power of 2
46757
+ return 32 - Math.clz32(--value);
46758
+ }
46759
+
46760
+ class PositionSet {
46761
+ sheets = {};
46762
+ /**
46763
+ * List of positions in the order they were inserted.
46764
+ */
46765
+ insertions = [];
46766
+ maxSize = 0;
46767
+ constructor(sheetSizes) {
46768
+ for (const sheetId in sheetSizes) {
46769
+ const cols = sheetSizes[sheetId].cols;
46770
+ const rows = sheetSizes[sheetId].rows;
46771
+ this.maxSize += cols * rows;
46772
+ this.sheets[sheetId] = BinaryGrid.create(rows, cols);
46773
+ }
46774
+ }
46775
+ add(position) {
46776
+ const hasBeenInserted = this.sheets[position.sheetId].setValue(position, 1);
46777
+ if (hasBeenInserted) {
46778
+ this.insertions.push(position);
46779
+ }
46780
+ }
46781
+ addMany(positions) {
46782
+ for (const position of positions) {
46783
+ this.add(position);
46784
+ }
46785
+ }
46786
+ delete(position) {
46787
+ this.sheets[position.sheetId].setValue(position, 0);
46788
+ }
46789
+ deleteMany(positions) {
46790
+ for (const position of positions) {
46791
+ this.delete(position);
46792
+ }
46793
+ }
46794
+ has(position) {
46795
+ return this.sheets[position.sheetId].getValue(position) === 1;
46796
+ }
46797
+ clear() {
46798
+ const insertions = this.insertions;
46799
+ this.insertions = [];
46800
+ for (const sheetId in this.sheets) {
46801
+ this.sheets[sheetId].clear();
46802
+ }
46803
+ return insertions;
46804
+ }
46805
+ isEmpty() {
46806
+ if (this.insertions.length === 0) {
46807
+ return true;
46808
+ }
46809
+ for (const sheetId in this.sheets) {
46810
+ if (!this.sheets[sheetId].isEmpty()) {
46811
+ return false;
46812
+ }
46813
+ }
46814
+ return true;
46815
+ }
46816
+ fillAllPositions() {
46817
+ this.insertions = new Array(this.maxSize);
46818
+ let index = 0;
46819
+ for (const sheetId in this.sheets) {
46820
+ const grid = this.sheets[sheetId];
46821
+ grid.fillAllPositions();
46822
+ for (let i = 0; i < grid.rows; i++) {
46823
+ for (let j = 0; j < grid.cols; j++) {
46824
+ this.insertions[index++] = { sheetId, row: i, col: j };
46825
+ }
46826
+ }
46827
+ }
46828
+ }
46829
+ /**
46830
+ * Iterate over the positions in the order of insertion.
46831
+ * Note that the same position may be yielded multiple times if the value was added
46832
+ * to the set then removed and then added again.
46833
+ */
46834
+ *[Symbol.iterator]() {
46835
+ for (const position of this.insertions) {
46836
+ if (this.sheets[position.sheetId].getValue(position) === 1) {
46837
+ yield position;
46838
+ }
46839
+ }
46840
+ }
46841
+ }
46842
+
46638
46843
  /**
46639
46844
  * Contains, for each cell, the array
46640
46845
  * formulas that could potentially spread on it
@@ -46648,6 +46853,7 @@ stores.inject(MyMetaStore, storeInstance);
46648
46853
  *
46649
46854
  */
46650
46855
  class SpreadingRelation {
46856
+ createEmptyPositionSet;
46651
46857
  /**
46652
46858
  * Internal structure:
46653
46859
  * For something like
@@ -46676,39 +46882,42 @@ stores.inject(MyMetaStore, storeInstance);
46676
46882
  * - (B1) --> (B2, B3, B4) meaning B1 spreads on B2, B3 and B4
46677
46883
  *
46678
46884
  */
46679
- resultsToArrayFormulas = new Map();
46680
- arrayFormulasToResults = new Map();
46681
- getFormulaPositionsSpreadingOn(resultPositionId) {
46682
- return this.resultsToArrayFormulas.get(resultPositionId) || EMPTY_ARRAY;
46885
+ resultsToArrayFormulas = new PositionMap();
46886
+ arrayFormulasToResults = new PositionMap();
46887
+ constructor(createEmptyPositionSet) {
46888
+ this.createEmptyPositionSet = createEmptyPositionSet;
46889
+ }
46890
+ getFormulaPositionsSpreadingOn(resultPosition) {
46891
+ return this.resultsToArrayFormulas.get(resultPosition) || EMPTY_ARRAY;
46683
46892
  }
46684
- getArrayResultPositionIds(formulasPositionId) {
46685
- return this.arrayFormulasToResults.get(formulasPositionId) || EMPTY_ARRAY;
46893
+ getArrayResultPositions(formulasPosition) {
46894
+ return this.arrayFormulasToResults.get(formulasPosition) || EMPTY_ARRAY;
46686
46895
  }
46687
46896
  /**
46688
46897
  * Remove a node, also remove it from other nodes adjacency list
46689
46898
  */
46690
- removeNode(positionId) {
46691
- this.resultsToArrayFormulas.delete(positionId);
46692
- this.arrayFormulasToResults.delete(positionId);
46899
+ removeNode(position) {
46900
+ this.resultsToArrayFormulas.delete(position);
46901
+ this.arrayFormulasToResults.delete(position);
46693
46902
  }
46694
46903
  /**
46695
46904
  * Create a spreading relation between two cells
46696
46905
  */
46697
- addRelation({ arrayFormulaPositionId, resultPositionId, }) {
46698
- if (!this.resultsToArrayFormulas.has(resultPositionId)) {
46699
- this.resultsToArrayFormulas.set(resultPositionId, new Set());
46906
+ addRelation({ arrayFormulaPosition, resultPosition, }) {
46907
+ if (!this.resultsToArrayFormulas.has(resultPosition)) {
46908
+ this.resultsToArrayFormulas.set(resultPosition, this.createEmptyPositionSet());
46700
46909
  }
46701
- this.resultsToArrayFormulas.get(resultPositionId)?.add(arrayFormulaPositionId);
46702
- if (!this.arrayFormulasToResults.has(arrayFormulaPositionId)) {
46703
- this.arrayFormulasToResults.set(arrayFormulaPositionId, new Set());
46910
+ this.resultsToArrayFormulas.get(resultPosition)?.add(arrayFormulaPosition);
46911
+ if (!this.arrayFormulasToResults.has(arrayFormulaPosition)) {
46912
+ this.arrayFormulasToResults.set(arrayFormulaPosition, this.createEmptyPositionSet());
46704
46913
  }
46705
- this.arrayFormulasToResults.get(arrayFormulaPositionId)?.add(resultPositionId);
46914
+ this.arrayFormulasToResults.get(arrayFormulaPosition)?.add(resultPosition);
46706
46915
  }
46707
- hasArrayFormulaResult(positionId) {
46708
- return this.resultsToArrayFormulas.has(positionId);
46916
+ hasArrayFormulaResult(position) {
46917
+ return this.resultsToArrayFormulas.has(position);
46709
46918
  }
46710
- isArrayFormula(positionId) {
46711
- return this.arrayFormulasToResults.has(positionId);
46919
+ isArrayFormula(position) {
46920
+ return this.arrayFormulasToResults.has(position);
46712
46921
  }
46713
46922
  }
46714
46923
  const EMPTY_ARRAY = [];
@@ -46720,50 +46929,41 @@ stores.inject(MyMetaStore, storeInstance);
46720
46929
  context;
46721
46930
  getters;
46722
46931
  compilationParams;
46723
- encoder = new PositionBitsEncoder();
46724
- evaluatedCells = new Map();
46725
- formulaDependencies = lazy(new FormulaDependencyGraph(this.encoder));
46726
- blockedArrayFormulas = new Set();
46727
- spreadingRelations = new SpreadingRelation();
46932
+ evaluatedCells = new PositionMap();
46933
+ formulaDependencies = lazy(new FormulaDependencyGraph(this.createEmptyPositionSet.bind(this)));
46934
+ blockedArrayFormulas = new PositionSet({});
46935
+ spreadingRelations = new SpreadingRelation(this.createEmptyPositionSet.bind(this));
46728
46936
  constructor(context, getters) {
46729
46937
  this.context = context;
46730
46938
  this.getters = getters;
46731
46939
  this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
46732
46940
  }
46733
46941
  getEvaluatedCell(position) {
46734
- return this.evaluatedCells.get(this.encoder.encode(position)) || EMPTY_CELL;
46942
+ return this.evaluatedCells.get(position) || EMPTY_CELL;
46735
46943
  }
46736
46944
  getSpreadPositionsOf(position) {
46737
- const positionId = this.encoder.encode(position);
46738
- if (!this.spreadingRelations.isArrayFormula(positionId)) {
46945
+ if (!this.spreadingRelations.isArrayFormula(position)) {
46739
46946
  return [];
46740
46947
  }
46741
- return Array.from(this.spreadingRelations.getArrayResultPositionIds(positionId)).map((positionId) => this.encoder.decode(positionId));
46742
- }
46743
- getArrayFormulaSpreadingOn(position) {
46744
- const positionId = this.encoder.encode(position);
46745
- const formulaPosition = this.getArrayFormulaSpreadingOnId(positionId);
46746
- return formulaPosition !== undefined ? this.encoder.decode(formulaPosition) : undefined;
46948
+ return Array.from(this.spreadingRelations.getArrayResultPositions(position));
46747
46949
  }
46748
46950
  getEvaluatedPositions() {
46749
- return [...this.evaluatedCells.keys()].map((p) => this.encoder.decode(p));
46951
+ return this.evaluatedCells.keys();
46750
46952
  }
46751
- getArrayFormulaSpreadingOnId(positionId) {
46752
- if (!this.spreadingRelations.hasArrayFormulaResult(positionId)) {
46953
+ getArrayFormulaSpreadingOn(position) {
46954
+ if (!this.spreadingRelations.hasArrayFormulaResult(position)) {
46753
46955
  return undefined;
46754
46956
  }
46755
- const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(positionId);
46756
- return Array.from(arrayFormulas).find((positionId) => !this.blockedArrayFormulas.has(positionId));
46957
+ const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(position);
46958
+ return Array.from(arrayFormulas).find((position) => !this.blockedArrayFormulas.has(position));
46757
46959
  }
46758
46960
  updateDependencies(position) {
46759
- const positionId = this.encoder.encode(position);
46760
- this.formulaDependencies().removeAllDependencies(positionId);
46761
- const dependencies = this.getDirectDependencies(positionId);
46762
- this.formulaDependencies().addDependencies(positionId, dependencies);
46961
+ this.formulaDependencies().removeAllDependencies(position);
46962
+ const dependencies = this.getDirectDependencies(position);
46963
+ this.formulaDependencies().addDependencies(position, dependencies);
46763
46964
  }
46764
46965
  addDependencies(position, dependencies) {
46765
- const positionId = this.encoder.encode(position);
46766
- this.formulaDependencies().addDependencies(positionId, dependencies);
46966
+ this.formulaDependencies().addDependencies(position, dependencies);
46767
46967
  }
46768
46968
  updateCompilationParameters() {
46769
46969
  // rebuild the compilation parameters (with a clean cache)
@@ -46771,47 +46971,57 @@ stores.inject(MyMetaStore, storeInstance);
46771
46971
  this.compilationParams.evalContext.updateDependencies = this.updateDependencies.bind(this);
46772
46972
  this.compilationParams.evalContext.addDependencies = this.addDependencies.bind(this);
46773
46973
  }
46974
+ createEmptyPositionSet() {
46975
+ const sheetSizes = {};
46976
+ for (const sheetId of this.getters.getSheetIds()) {
46977
+ sheetSizes[sheetId] = {
46978
+ rows: this.getters.getNumberRows(sheetId),
46979
+ cols: this.getters.getNumberCols(sheetId),
46980
+ };
46981
+ }
46982
+ return new PositionSet(sheetSizes);
46983
+ }
46774
46984
  evaluateCells(positions) {
46775
- const cells = positions.map((p) => this.encoder.encode(p));
46776
- const cellsToCompute = new JetSet(cells);
46777
- const arrayFormulasPositionIds = this.getArrayFormulasImpactedByChangesOf(cells);
46778
- cellsToCompute.addMany(this.getCellsDependingOn(cells));
46779
- cellsToCompute.addMany(arrayFormulasPositionIds);
46780
- cellsToCompute.addMany(this.getCellsDependingOn(arrayFormulasPositionIds));
46985
+ const cellsToCompute = this.createEmptyPositionSet();
46986
+ cellsToCompute.addMany(positions);
46987
+ const arrayFormulasPositions = this.getArrayFormulasImpactedByChangesOf(positions);
46988
+ cellsToCompute.addMany(this.getCellsDependingOn(positions));
46989
+ cellsToCompute.addMany(arrayFormulasPositions);
46990
+ cellsToCompute.addMany(this.getCellsDependingOn(arrayFormulasPositions));
46781
46991
  this.evaluate(cellsToCompute);
46782
46992
  }
46783
- getArrayFormulasImpactedByChangesOf(positionIds) {
46784
- const impactedPositionIds = new JetSet();
46785
- for (const positionId of positionIds) {
46786
- const content = this.getCell(positionId)?.content;
46787
- const arrayFormulaPositionId = this.getArrayFormulaSpreadingOnId(positionId);
46788
- if (arrayFormulaPositionId !== undefined) {
46993
+ getArrayFormulasImpactedByChangesOf(positions) {
46994
+ const impactedPositions = this.createEmptyPositionSet();
46995
+ for (const position of positions) {
46996
+ const content = this.getters.getCell(position)?.content;
46997
+ const arrayFormulaPosition = this.getArrayFormulaSpreadingOn(position);
46998
+ if (arrayFormulaPosition !== undefined) {
46789
46999
  // take into account new collisions.
46790
- impactedPositionIds.add(arrayFormulaPositionId);
47000
+ impactedPositions.add(arrayFormulaPosition);
46791
47001
  }
46792
47002
  if (!content) {
46793
47003
  // The previous content could have blocked some array formulas
46794
- impactedPositionIds.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(positionId));
47004
+ impactedPositions.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(position));
46795
47005
  }
46796
47006
  }
46797
- return impactedPositionIds;
47007
+ return impactedPositions;
46798
47008
  }
46799
47009
  buildDependencyGraph() {
46800
- this.blockedArrayFormulas = new Set();
46801
- this.spreadingRelations = new SpreadingRelation();
47010
+ this.blockedArrayFormulas = this.createEmptyPositionSet();
47011
+ this.spreadingRelations = new SpreadingRelation(this.createEmptyPositionSet.bind(this));
46802
47012
  this.formulaDependencies = lazy(() => {
46803
- const dependencies = [...this.getAllCells()].flatMap((positionId) => this.getDirectDependencies(positionId).map((range) => ({
46804
- data: positionId,
47013
+ const dependencies = [...this.getAllCells()].flatMap((position) => this.getDirectDependencies(position).map((range) => ({
47014
+ data: position,
46805
47015
  boundingBox: {
46806
47016
  zone: range.zone,
46807
47017
  sheetId: range.sheetId,
46808
47018
  },
46809
47019
  })));
46810
- return new FormulaDependencyGraph(this.encoder, dependencies);
47020
+ return new FormulaDependencyGraph(this.createEmptyPositionSet.bind(this), dependencies);
46811
47021
  });
46812
47022
  }
46813
47023
  evaluateAllCells() {
46814
- this.evaluatedCells = new Map();
47024
+ this.evaluatedCells = new PositionMap();
46815
47025
  this.evaluate(this.getAllCells());
46816
47026
  }
46817
47027
  evaluateFormula(sheetId, formulaString) {
@@ -46828,57 +47038,50 @@ stores.inject(MyMetaStore, storeInstance);
46828
47038
  return result.value;
46829
47039
  }
46830
47040
  getAllCells() {
46831
- const positionIds = new JetSet();
46832
- for (const sheetId of this.getters.getSheetIds()) {
46833
- const cellIds = this.getters.getCells(sheetId);
46834
- for (const cellId in cellIds) {
46835
- positionIds.add(this.encoder.encode(this.getters.getCellPosition(cellId)));
46836
- }
46837
- }
46838
- return positionIds;
47041
+ const positions = this.createEmptyPositionSet();
47042
+ positions.fillAllPositions();
47043
+ return positions;
46839
47044
  }
46840
- getArrayFormulasBlockedByOrSpreadingOn(positionId) {
46841
- if (!this.spreadingRelations.hasArrayFormulaResult(positionId)) {
47045
+ getArrayFormulasBlockedByOrSpreadingOn(position) {
47046
+ if (!this.spreadingRelations.hasArrayFormulaResult(position)) {
46842
47047
  return [];
46843
47048
  }
46844
- const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(positionId);
46845
- const cells = new JetSet(arrayFormulas);
46846
- cells.addMany(this.getCellsDependingOn(arrayFormulas));
46847
- return cells;
47049
+ const arrayFormulas = this.spreadingRelations.getFormulaPositionsSpreadingOn(position);
47050
+ const positions = this.createEmptyPositionSet();
47051
+ positions.addMany(arrayFormulas);
47052
+ positions.addMany(this.getCellsDependingOn(arrayFormulas));
47053
+ return positions;
46848
47054
  }
46849
- nextPositionsToUpdate = new JetSet();
47055
+ nextPositionsToUpdate = new PositionSet({});
46850
47056
  cellsBeingComputed = new Set();
46851
- evaluate(cells) {
47057
+ evaluate(positions) {
46852
47058
  this.cellsBeingComputed = new Set();
46853
- this.nextPositionsToUpdate = cells;
47059
+ this.nextPositionsToUpdate = positions;
46854
47060
  let currentIteration = 0;
46855
- while (this.nextPositionsToUpdate.size && currentIteration++ < MAX_ITERATION) {
47061
+ while (!this.nextPositionsToUpdate.isEmpty() && currentIteration++ < MAX_ITERATION) {
46856
47062
  this.updateCompilationParameters();
46857
- const positionIds = Array.from(this.nextPositionsToUpdate);
46858
- this.nextPositionsToUpdate.clear();
46859
- for (let i = 0; i < positionIds.length; ++i) {
46860
- const cell = positionIds[i];
46861
- this.evaluatedCells.delete(cell);
47063
+ const positions = this.nextPositionsToUpdate.clear();
47064
+ for (let i = 0; i < positions.length; ++i) {
47065
+ this.evaluatedCells.delete(positions[i]);
46862
47066
  }
46863
- for (let i = 0; i < positionIds.length; ++i) {
46864
- const cell = positionIds[i];
46865
- this.setEvaluatedCell(cell, this.computeCell(cell));
47067
+ for (let i = 0; i < positions.length; ++i) {
47068
+ const position = positions[i];
47069
+ const evaluatedCell = this.computeCell(position);
47070
+ if (evaluatedCell !== EMPTY_CELL) {
47071
+ this.evaluatedCells.set(position, evaluatedCell);
47072
+ }
46866
47073
  }
46867
47074
  }
46868
47075
  }
46869
- setEvaluatedCell(positionId, evaluatedCell) {
46870
- this.evaluatedCells.set(positionId, evaluatedCell);
46871
- }
46872
- computeCell(positionId) {
46873
- const evaluation = this.evaluatedCells.get(positionId);
47076
+ computeCell(position) {
47077
+ const evaluation = this.evaluatedCells.get(position);
46874
47078
  if (evaluation) {
46875
47079
  return evaluation; // already computed
46876
47080
  }
46877
- if (!this.blockedArrayFormulas.has(positionId)) {
46878
- this.invalidateSpreading(positionId);
47081
+ if (!this.blockedArrayFormulas.has(position)) {
47082
+ this.invalidateSpreading(position);
46879
47083
  }
46880
- const cellPosition = this.encoder.decode(positionId);
46881
- const cell = this.getters.getCell(cellPosition);
47084
+ const cell = this.getters.getCell(position);
46882
47085
  if (cell === undefined) {
46883
47086
  return EMPTY_CELL;
46884
47087
  }
@@ -46890,7 +47093,7 @@ stores.inject(MyMetaStore, storeInstance);
46890
47093
  }
46891
47094
  this.cellsBeingComputed.add(cellId);
46892
47095
  return cell.isFormula
46893
- ? this.computeFormulaCell(cellPosition.sheetId, cell)
47096
+ ? this.computeFormulaCell(position.sheetId, cell)
46894
47097
  : evaluateLiteral(cell.content, localeFormat);
46895
47098
  }
46896
47099
  catch (e) {
@@ -46903,10 +47106,9 @@ stores.inject(MyMetaStore, storeInstance);
46903
47106
  }
46904
47107
  }
46905
47108
  computeAndSave(position) {
46906
- const positionId = this.encoder.encode(position);
46907
- const evaluatedCell = this.computeCell(positionId);
46908
- if (!this.evaluatedCells.has(positionId)) {
46909
- this.setEvaluatedCell(positionId, evaluatedCell);
47109
+ const evaluatedCell = this.computeCell(position);
47110
+ if (!this.evaluatedCells.has(position)) {
47111
+ this.evaluatedCells.set(position, evaluatedCell);
46910
47112
  }
46911
47113
  return evaluatedCell;
46912
47114
  }
@@ -46944,24 +47146,23 @@ stores.inject(MyMetaStore, storeInstance);
46944
47146
  throw new EvaluationError(_t("Result couldn't be automatically expanded. Please insert more columns and rows."));
46945
47147
  }
46946
47148
  updateSpreadRelation({ sheetId, col, row, }) {
46947
- const arrayFormulaPositionId = this.encoder.encode({ sheetId, col, row });
47149
+ const arrayFormulaPosition = { sheetId, col, row };
46948
47150
  return (i, j) => {
46949
47151
  const position = { sheetId, col: i + col, row: j + row };
46950
- const resultPositionId = this.encoder.encode(position);
46951
- this.spreadingRelations.addRelation({ resultPositionId, arrayFormulaPositionId });
47152
+ this.spreadingRelations.addRelation({ resultPosition: position, arrayFormulaPosition });
46952
47153
  };
46953
47154
  }
46954
- checkCollision({ sheetId, col, row }) {
46955
- const formulaPositionId = this.encoder.encode({ sheetId, col, row });
47155
+ checkCollision(formulaPosition) {
47156
+ const { sheetId, col, row } = formulaPosition;
46956
47157
  return (i, j) => {
46957
47158
  const position = { sheetId: sheetId, col: i + col, row: j + row };
46958
47159
  const rawCell = this.getters.getCell(position);
46959
47160
  if (rawCell?.content ||
46960
47161
  this.getters.getEvaluatedCell(position).type !== CellValueType.empty) {
46961
- this.blockedArrayFormulas.add(formulaPositionId);
47162
+ this.blockedArrayFormulas.add(formulaPosition);
46962
47163
  throw new EvaluationError(_t("Array result was not expanded because it would overwrite data in %s.", toXC(position.col, position.row)));
46963
47164
  }
46964
- this.blockedArrayFormulas.delete(formulaPositionId);
47165
+ this.blockedArrayFormulas.delete(formulaPosition);
46965
47166
  };
46966
47167
  }
46967
47168
  spreadValues({ sheetId, col, row }, matrixResult) {
@@ -46969,19 +47170,18 @@ stores.inject(MyMetaStore, storeInstance);
46969
47170
  const position = { sheetId, col: i + col, row: j + row };
46970
47171
  const cell = this.getters.getCell(position);
46971
47172
  const evaluatedCell = createEvaluatedCell(nullValueToZeroValue(matrixResult[i][j]), this.getters.getLocale(), cell);
46972
- const positionId = this.encoder.encode(position);
46973
- this.setEvaluatedCell(positionId, evaluatedCell);
47173
+ this.evaluatedCells.set(position, evaluatedCell);
46974
47174
  // check if formula dependencies present in the spread zone
46975
47175
  // if so, they need to be recomputed
46976
- this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([positionId]));
47176
+ this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([position]));
46977
47177
  };
46978
47178
  }
46979
- invalidateSpreading(positionId) {
46980
- if (!this.spreadingRelations.isArrayFormula(positionId)) {
47179
+ invalidateSpreading(position) {
47180
+ if (!this.spreadingRelations.isArrayFormula(position)) {
46981
47181
  return;
46982
47182
  }
46983
- for (const child of this.spreadingRelations.getArrayResultPositionIds(positionId)) {
46984
- const content = this.getCell(child)?.content;
47183
+ for (const child of this.spreadingRelations.getArrayResultPositions(position)) {
47184
+ const content = this.getters.getCell(child)?.content;
46985
47185
  if (content) {
46986
47186
  // there's no point at re-evaluating overlapping array formulas,
46987
47187
  // there's still a collision
@@ -46991,28 +47191,25 @@ stores.inject(MyMetaStore, storeInstance);
46991
47191
  this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([child]));
46992
47192
  this.nextPositionsToUpdate.addMany(this.getArrayFormulasBlockedByOrSpreadingOn(child));
46993
47193
  }
46994
- this.spreadingRelations.removeNode(positionId);
47194
+ this.spreadingRelations.removeNode(position);
46995
47195
  }
46996
47196
  // ----------------------------------------------------------
46997
47197
  // COMMON FUNCTIONALITY
46998
47198
  // ----------------------------------------------------------
46999
- getDirectDependencies(positionId) {
47000
- const cell = this.getCell(positionId);
47199
+ getDirectDependencies(position) {
47200
+ const cell = this.getters.getCell(position);
47001
47201
  if (!cell?.isFormula) {
47002
47202
  return [];
47003
47203
  }
47004
47204
  return cell.compiledFormula.dependencies;
47005
47205
  }
47006
- getCellsDependingOn(positionIds) {
47206
+ getCellsDependingOn(positions) {
47007
47207
  const ranges = [];
47008
- for (const positionId of positionIds) {
47009
- ranges.push(this.encoder.decodeToBoundingBox(positionId));
47208
+ for (const position of positions) {
47209
+ ranges.push({ sheetId: position.sheetId, zone: positionToZone(position) });
47010
47210
  }
47011
47211
  return this.formulaDependencies().getCellsDependingOn(ranges);
47012
47212
  }
47013
- getCell(positionId) {
47014
- return this.getters.getCell(this.encoder.decode(positionId));
47015
- }
47016
47213
  }
47017
47214
  function forEachSpreadPositionInMatrix(nbColumns, nbRows, callback) {
47018
47215
  for (let i = 0; i < nbColumns; ++i) {
@@ -47038,85 +47235,6 @@ stores.inject(MyMetaStore, storeInstance);
47038
47235
  }
47039
47236
  return fPayload;
47040
47237
  }
47041
- /**
47042
- * Encode (and decode) cell positions { sheetId, col, row }
47043
- * to a single integer.
47044
- *
47045
- * `col` and `row` values are encoded on 21 bits each (max 2^21 = 2_097_152),
47046
- * An incremental integer id is assigned to each different sheet id, starting at 0.
47047
- *
47048
- * e.g.
47049
- * Given { col: 10, row: 4, sheetId: "abcde" }
47050
- * we have:
47051
- * - row "4" encoded on 21 bits: 000000000000000000100
47052
- * - col "10" encoded on 21 bits: 000000000000000001010
47053
- * - sheetId: let's say it's the 4th sheetId met, encoded to: 11
47054
- *
47055
- * The final encoded value is found by concatenating the 3 bit sequences:
47056
- *
47057
- * sheetId: 11
47058
- * col: 000000000000000001010
47059
- * row: 000000000000000000100
47060
- * => 11000000000000000001010000000000000000000100
47061
- *
47062
- * this binary sequence is the integer 13194160504836
47063
- */
47064
- class PositionBitsEncoder {
47065
- sheetMapping = {};
47066
- inverseSheetMapping = new Map();
47067
- constructor() {
47068
- try {
47069
- // @ts-ignore
47070
- o_spreadsheet.__DEBUG__ = o_spreadsheet.__DEBUG__ || {};
47071
- // @ts-ignore
47072
- o_spreadsheet.__DEBUG__.decodePosition = this.decode.bind(this);
47073
- // @ts-ignore
47074
- o_spreadsheet.__DEBUG__.encodePosition = this.encode.bind(this);
47075
- }
47076
- catch (error) { }
47077
- }
47078
- /**
47079
- * Encode a cell position to a single integer.
47080
- */
47081
- encode({ sheetId, col, row }) {
47082
- return (this.encodeSheet(sheetId) << 42n) | (BigInt(col) << 21n) | BigInt(row);
47083
- }
47084
- encodeBoundingBox({ sheetId, zone }) {
47085
- const positions = [];
47086
- forEachPositionsInZone(zone, (col, row) => {
47087
- positions.push(this.encode({ sheetId, col, row }));
47088
- });
47089
- return positions;
47090
- }
47091
- decode(id) {
47092
- // keep only the last 21 bits by AND-ing the bit sequence with 21 ones
47093
- const row = Number(id & 2097151n);
47094
- const col = Number((id >> 21n) & 2097151n);
47095
- const sheetId = this.decodeSheet(id >> 42n);
47096
- return { sheetId, col, row };
47097
- }
47098
- decodeToBoundingBox(id) {
47099
- const { sheetId, col, row } = this.decode(id);
47100
- return { sheetId, zone: { left: col, top: row, right: col, bottom: row } };
47101
- }
47102
- encodeSheet(sheetId) {
47103
- const sheetKey = this.sheetMapping[sheetId];
47104
- if (sheetKey === undefined) {
47105
- const newSheetKey = BigInt(Object.keys(this.sheetMapping).length);
47106
- this.sheetMapping[sheetId] = newSheetKey;
47107
- this.inverseSheetMapping.set(newSheetKey, sheetId);
47108
- return newSheetKey;
47109
- }
47110
- return sheetKey;
47111
- }
47112
- decodeSheet(sheetKey) {
47113
- const sheetId = this.inverseSheetMapping.get(sheetKey);
47114
- if (sheetId === undefined) {
47115
- throw new Error("Sheet id not found");
47116
- }
47117
- return sheetId;
47118
- }
47119
- }
47120
47238
  function updateEvalContextAndExecute(compiledFormula, compilationParams, sheetId, cellId) {
47121
47239
  compilationParams.evalContext.__originCellXC = lazy(() => {
47122
47240
  if (!cellId) {
@@ -47263,6 +47381,10 @@ stores.inject(MyMetaStore, storeInstance);
47263
47381
  this.evaluator.updateDependencies(cmd);
47264
47382
  }
47265
47383
  break;
47384
+ case "DUPLICATE_SHEET":
47385
+ case "CREATE_SHEET":
47386
+ this.shouldRebuildDependenciesGraph = true;
47387
+ break;
47266
47388
  case "EVALUATE_CELLS":
47267
47389
  this.evaluator.evaluateAllCells();
47268
47390
  break;
@@ -52355,6 +52477,7 @@ stores.inject(MyMetaStore, storeInstance);
52355
52477
  this.gridSelection.zones = this.gridSelection.zones.map((z) => this.getters.expandZone(sheetId, z));
52356
52478
  this.gridSelection.anchor.zone = this.getters.expandZone(sheetId, this.gridSelection.anchor.zone);
52357
52479
  this.setSelectionMixin(this.gridSelection.anchor, this.gridSelection.zones);
52480
+ this.selectedFigureId = null;
52358
52481
  break;
52359
52482
  }
52360
52483
  /** Any change to the selection has to be reflected in the selection processor. */
@@ -55973,9 +56096,6 @@ stores.inject(MyMetaStore, storeInstance);
55973
56096
  .text-muted {
55974
56097
  color: grey !important;
55975
56098
  }
55976
- button {
55977
- color: #333;
55978
- }
55979
56099
  .o-disabled {
55980
56100
  opacity: 0.4;
55981
56101
  pointer: default;
@@ -56096,17 +56216,17 @@ stores.inject(MyMetaStore, storeInstance);
56096
56216
  }
56097
56217
 
56098
56218
  .o-button {
56099
- border: 1px solid lightgrey;
56219
+ border: 1px solid;
56100
56220
  padding: 0px 20px 0px 20px;
56101
56221
  border-radius: 4px;
56102
56222
  font-weight: 500;
56103
56223
  font-size: 14px;
56104
56224
  height: 30px;
56105
56225
  line-height: 16px;
56106
- background: white;
56107
56226
  margin-right: 8px;
56108
- &:hover:enabled {
56109
- background-color: rgba(0, 0, 0, 0.08);
56227
+
56228
+ &:not(:hover) {
56229
+ background-color: transparent;
56110
56230
  }
56111
56231
 
56112
56232
  &:enabled {
@@ -56120,6 +56240,15 @@ stores.inject(MyMetaStore, storeInstance);
56120
56240
  &:last-child {
56121
56241
  margin-right: 0px;
56122
56242
  }
56243
+
56244
+ &.o-button-grey {
56245
+ border-color: lightgrey;
56246
+ background: #ffffff;
56247
+ color: #333;
56248
+ &:hover:enabled {
56249
+ background-color: rgba(0, 0, 0, 0.08);
56250
+ }
56251
+ }
56123
56252
  }
56124
56253
 
56125
56254
  .o-input {
@@ -60047,9 +60176,9 @@ stores.inject(MyMetaStore, storeInstance);
60047
60176
  exports.tokenize = tokenize;
60048
60177
 
60049
60178
 
60050
- __info__.version = "17.2.0-alpha.8";
60051
- __info__.date = "2024-03-15T11:01:01.388Z";
60052
- __info__.hash = "11cf381";
60179
+ __info__.version = "17.2.1";
60180
+ __info__.date = "2024-03-25T09:41:58.737Z";
60181
+ __info__.hash = "f97284c";
60053
60182
 
60054
60183
 
60055
60184
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);