@odoo/o-spreadsheet 16.3.0-alpha.1 → 16.3.0-alpha.3
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/o-spreadsheet.cjs.js +891 -371
- package/dist/o-spreadsheet.d.ts +171 -125
- package/dist/o-spreadsheet.esm.js +891 -371
- package/dist/o-spreadsheet.iife.js +891 -371
- package/dist/o-spreadsheet.iife.min.js +267 -261
- package/package.json +3 -3
|
@@ -114,88 +114,88 @@
|
|
|
114
114
|
const BACKGROUND_HEADER_FILTER_COLOR = "#E6F4EA";
|
|
115
115
|
const BACKGROUND_HEADER_SELECTED_FILTER_COLOR = "#CEEAD6";
|
|
116
116
|
const SEPARATOR_COLOR = "#E0E2E4";
|
|
117
|
-
// Color picker
|
|
117
|
+
// Color picker defaults as upper case HEX to match `toHex`helper
|
|
118
118
|
const COLOR_PICKER_DEFAULTS = [
|
|
119
119
|
"#000000",
|
|
120
120
|
"#434343",
|
|
121
121
|
"#666666",
|
|
122
122
|
"#999999",
|
|
123
|
-
"#
|
|
124
|
-
"#
|
|
125
|
-
"#
|
|
126
|
-
"#
|
|
127
|
-
"#
|
|
128
|
-
"#
|
|
123
|
+
"#B7B7B7",
|
|
124
|
+
"#CCCCCC",
|
|
125
|
+
"#D9D9D9",
|
|
126
|
+
"#EFEFEF",
|
|
127
|
+
"#F3F3F3",
|
|
128
|
+
"#FFFFFF",
|
|
129
129
|
"#980000",
|
|
130
|
-
"#
|
|
131
|
-
"#
|
|
132
|
-
"#
|
|
133
|
-
"#
|
|
134
|
-
"#
|
|
135
|
-
"#
|
|
136
|
-
"#
|
|
137
|
-
"#
|
|
138
|
-
"#
|
|
139
|
-
"#
|
|
140
|
-
"#
|
|
141
|
-
"#
|
|
142
|
-
"#
|
|
143
|
-
"#
|
|
144
|
-
"#
|
|
145
|
-
"#
|
|
146
|
-
"#
|
|
147
|
-
"#
|
|
148
|
-
"#
|
|
149
|
-
"#
|
|
150
|
-
"#
|
|
151
|
-
"#
|
|
152
|
-
"#
|
|
153
|
-
"#
|
|
154
|
-
"#
|
|
155
|
-
"#
|
|
156
|
-
"#
|
|
157
|
-
"#
|
|
158
|
-
"#
|
|
159
|
-
"#
|
|
160
|
-
"#
|
|
161
|
-
"#
|
|
162
|
-
"#
|
|
163
|
-
"#
|
|
164
|
-
"#
|
|
165
|
-
"#
|
|
166
|
-
"#
|
|
167
|
-
"#
|
|
168
|
-
"#
|
|
169
|
-
"#
|
|
170
|
-
"#
|
|
171
|
-
"#
|
|
172
|
-
"#
|
|
173
|
-
"#
|
|
174
|
-
"#
|
|
175
|
-
"#
|
|
176
|
-
"#
|
|
177
|
-
"#
|
|
178
|
-
"#
|
|
179
|
-
"#
|
|
130
|
+
"#FF0000",
|
|
131
|
+
"#FF9900",
|
|
132
|
+
"#FFFF00",
|
|
133
|
+
"#00FF00",
|
|
134
|
+
"#00FFFF",
|
|
135
|
+
"#4A86E8",
|
|
136
|
+
"#0000FF",
|
|
137
|
+
"#9900FF",
|
|
138
|
+
"#FF00FF",
|
|
139
|
+
"#E6B8AF",
|
|
140
|
+
"#F4CCCC",
|
|
141
|
+
"#FCE5CD",
|
|
142
|
+
"#FFF2CC",
|
|
143
|
+
"#D9EAD3",
|
|
144
|
+
"#D0E0E3",
|
|
145
|
+
"#C9DAF8",
|
|
146
|
+
"#CFE2F3",
|
|
147
|
+
"#D9D2E9",
|
|
148
|
+
"#EAD1DC",
|
|
149
|
+
"#DD7E6B",
|
|
150
|
+
"#EA9999",
|
|
151
|
+
"#F9CB9C",
|
|
152
|
+
"#FFE599",
|
|
153
|
+
"#B6D7A8",
|
|
154
|
+
"#A2C4C9",
|
|
155
|
+
"#A4C2F4",
|
|
156
|
+
"#9FC5E8",
|
|
157
|
+
"#B4A7D6",
|
|
158
|
+
"#D5A6BD",
|
|
159
|
+
"#CC4125",
|
|
160
|
+
"#E06666",
|
|
161
|
+
"#F6B26B",
|
|
162
|
+
"#FFD966",
|
|
163
|
+
"#93C47D",
|
|
164
|
+
"#76A5AF",
|
|
165
|
+
"#6D9EEB",
|
|
166
|
+
"#6FA8DC",
|
|
167
|
+
"#8E7CC3",
|
|
168
|
+
"#C27BA0",
|
|
169
|
+
"#A61C00",
|
|
170
|
+
"#CC0000",
|
|
171
|
+
"#E69138",
|
|
172
|
+
"#F1C232",
|
|
173
|
+
"#6AA84F",
|
|
174
|
+
"#45818E",
|
|
175
|
+
"#3C78D8",
|
|
176
|
+
"#3D85C6",
|
|
177
|
+
"#674EA7",
|
|
178
|
+
"#A64D79",
|
|
179
|
+
"#85200C",
|
|
180
180
|
"#990000",
|
|
181
|
-
"#
|
|
182
|
-
"#
|
|
183
|
-
"#
|
|
184
|
-
"#
|
|
185
|
-
"#
|
|
186
|
-
"#
|
|
187
|
-
"#
|
|
188
|
-
"#
|
|
189
|
-
"#
|
|
181
|
+
"#B45F06",
|
|
182
|
+
"#BF9000",
|
|
183
|
+
"#38761D",
|
|
184
|
+
"#134F5C",
|
|
185
|
+
"#1155CC",
|
|
186
|
+
"#0B5394",
|
|
187
|
+
"#351C75",
|
|
188
|
+
"#741B47",
|
|
189
|
+
"#5B0F00",
|
|
190
190
|
"#660000",
|
|
191
|
-
"#
|
|
192
|
-
"#
|
|
193
|
-
"#
|
|
194
|
-
"#
|
|
195
|
-
"#
|
|
191
|
+
"#783F04",
|
|
192
|
+
"#7F6000",
|
|
193
|
+
"#274E13",
|
|
194
|
+
"#0C343D",
|
|
195
|
+
"#1C4587",
|
|
196
196
|
"#073763",
|
|
197
|
-
"#
|
|
198
|
-
"#
|
|
197
|
+
"#20124D",
|
|
198
|
+
"#4C1130",
|
|
199
199
|
];
|
|
200
200
|
// Dimensions
|
|
201
201
|
const MIN_ROW_HEIGHT = 10;
|
|
@@ -224,8 +224,6 @@
|
|
|
224
224
|
const MENU_ITEM_HEIGHT = 28;
|
|
225
225
|
const MENU_SEPARATOR_BORDER_WIDTH = 1;
|
|
226
226
|
const MENU_SEPARATOR_PADDING = 5;
|
|
227
|
-
const MENU_SEPARATOR_HEIGHT = MENU_SEPARATOR_BORDER_WIDTH + 2 * MENU_SEPARATOR_PADDING;
|
|
228
|
-
const FIGURE_BORDER_SIZE = 1;
|
|
229
227
|
// Fonts
|
|
230
228
|
const DEFAULT_FONT_WEIGHT = "400";
|
|
231
229
|
const DEFAULT_FONT_SIZE = 10;
|
|
@@ -235,7 +233,7 @@
|
|
|
235
233
|
const DEFAULT_BORDER_DESC = ["thin", "#000"];
|
|
236
234
|
const DEFAULT_FILTER_BORDER_DESC = ["thin", FILTERS_COLOR];
|
|
237
235
|
// DateTimeRegex
|
|
238
|
-
const DATETIME_FORMAT = /[
|
|
236
|
+
const DATETIME_FORMAT = /[ymdhs:]/;
|
|
239
237
|
// Ranges
|
|
240
238
|
const INCORRECT_RANGE_STRING = CellErrorType.InvalidReference;
|
|
241
239
|
// Max Number of history steps kept in memory
|
|
@@ -245,6 +243,8 @@
|
|
|
245
243
|
// Figure
|
|
246
244
|
const DEFAULT_FIGURE_HEIGHT = 335;
|
|
247
245
|
const DEFAULT_FIGURE_WIDTH = 536;
|
|
246
|
+
const FIGURE_BORDER_WIDTH = 1;
|
|
247
|
+
const MIN_FIG_SIZE = 80;
|
|
248
248
|
// Chart
|
|
249
249
|
const MAX_CHAR_LABEL = 20;
|
|
250
250
|
const FIGURE_ID_SPLITTER = "??";
|
|
@@ -255,7 +255,6 @@
|
|
|
255
255
|
const DEFAULT_SCORECARD_BASELINE_COLOR_UP = "#00A04A";
|
|
256
256
|
const DEFAULT_SCORECARD_BASELINE_COLOR_DOWN = "#DC6965";
|
|
257
257
|
const LINE_FILL_TRANSPARENCY = 0.4;
|
|
258
|
-
const MIN_FIG_SIZE = 80;
|
|
259
258
|
// session
|
|
260
259
|
const DEBOUNCE_TIME = 200;
|
|
261
260
|
const MESSAGE_VERSION = 1;
|
|
@@ -277,7 +276,8 @@
|
|
|
277
276
|
ComponentsImportance[ComponentsImportance["TopBarComposer"] = 21] = "TopBarComposer";
|
|
278
277
|
ComponentsImportance[ComponentsImportance["IconPicker"] = 25] = "IconPicker";
|
|
279
278
|
ComponentsImportance[ComponentsImportance["Popover"] = 30] = "Popover";
|
|
280
|
-
ComponentsImportance[ComponentsImportance["
|
|
279
|
+
ComponentsImportance[ComponentsImportance["FigureAnchor"] = 1000] = "FigureAnchor";
|
|
280
|
+
ComponentsImportance[ComponentsImportance["FigureSnapLine"] = 1001] = "FigureSnapLine";
|
|
281
281
|
})(ComponentsImportance || (ComponentsImportance = {}));
|
|
282
282
|
const DEFAULT_SHEETVIEW_SIZE = 1000;
|
|
283
283
|
const MAXIMAL_FREEZABLE_RATIO = 0.85;
|
|
@@ -714,7 +714,7 @@
|
|
|
714
714
|
* '\w' captures [0-9][a-z][A-Z] and _.
|
|
715
715
|
* @param sheetName Name of the sheet
|
|
716
716
|
*/
|
|
717
|
-
function
|
|
717
|
+
function getCanonicalSheetName(sheetName) {
|
|
718
718
|
var _a;
|
|
719
719
|
if (((_a = sheetName.match(/\w/g)) === null || _a === void 0 ? void 0 : _a.length) !== sheetName.length) {
|
|
720
720
|
sheetName = `'${sheetName}'`;
|
|
@@ -735,8 +735,9 @@
|
|
|
735
735
|
return DEFAULT_CELL_HEIGHT;
|
|
736
736
|
}
|
|
737
737
|
const fontSize = computeTextFontSizeInPixels(cell.style);
|
|
738
|
-
|
|
739
|
-
|
|
738
|
+
// the number of lines should be computed from the formula result, but it's not evaluated at this point
|
|
739
|
+
const numberOfLines = cell.isFormula ? 1 : cell.content.split(NEWLINE).length;
|
|
740
|
+
return computeTextLinesHeight(fontSize, numberOfLines) + 2 * PADDING_AUTORESIZE_VERTICAL;
|
|
740
741
|
}
|
|
741
742
|
function computeTextWidth(context, text, style) {
|
|
742
743
|
context.save();
|
|
@@ -1088,6 +1089,8 @@
|
|
|
1088
1089
|
return text;
|
|
1089
1090
|
}
|
|
1090
1091
|
|
|
1092
|
+
const RBA_REGEX = /rgba?\(|\s+|\)/gi;
|
|
1093
|
+
const HEX_MATCH = /^#([A-F\d]{2}){3,4}$/g;
|
|
1091
1094
|
const colors$1 = [
|
|
1092
1095
|
"#eb6d00",
|
|
1093
1096
|
"#0074d9",
|
|
@@ -1113,7 +1116,10 @@
|
|
|
1113
1116
|
}
|
|
1114
1117
|
/**
|
|
1115
1118
|
* Converts any CSS color value to a standardized hex6 value.
|
|
1116
|
-
* Accepts: hex3, hex6, hex8 and
|
|
1119
|
+
* Accepts: hex3, hex6, hex8, rgb[1] and rgba[1].
|
|
1120
|
+
*
|
|
1121
|
+
* [1] under the form rgb(r, g, b, a?) or rgba(r, g, b, a?)
|
|
1122
|
+
* with r,g,b ∈ [0, 255] and a ∈ [0, 1]
|
|
1117
1123
|
*
|
|
1118
1124
|
* toHex("#ABC")
|
|
1119
1125
|
* >> "#AABBCC"
|
|
@@ -1124,27 +1130,31 @@
|
|
|
1124
1130
|
* toHex("rgb(30, 80, 16)")
|
|
1125
1131
|
* >> "#1E5010"
|
|
1126
1132
|
*
|
|
1133
|
+
* * toHex("rgb(30, 80, 16, 0.5)")
|
|
1134
|
+
* >> "#1E501080"
|
|
1135
|
+
*
|
|
1127
1136
|
*/
|
|
1128
1137
|
function toHex(color) {
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
if (color.includes("rgb")) {
|
|
1133
|
-
return rgbToHex6(color);
|
|
1138
|
+
let hexColor = color;
|
|
1139
|
+
if (color.startsWith("rgb")) {
|
|
1140
|
+
hexColor = rgbaStringToHex(color);
|
|
1134
1141
|
}
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1142
|
+
else {
|
|
1143
|
+
hexColor = color.replace("#", "").toUpperCase();
|
|
1144
|
+
if (hexColor.length === 3 || hexColor.length === 4) {
|
|
1145
|
+
hexColor = hexColor.split("").reduce((acc, h) => acc + h + h, "");
|
|
1146
|
+
}
|
|
1147
|
+
hexColor = `#${hexColor}`;
|
|
1138
1148
|
}
|
|
1139
|
-
if (
|
|
1140
|
-
throw new Error(
|
|
1149
|
+
if (!hexColor.match(HEX_MATCH)) {
|
|
1150
|
+
throw new Error(`invalid color input: ${color}`);
|
|
1141
1151
|
}
|
|
1142
|
-
return
|
|
1152
|
+
return hexColor;
|
|
1143
1153
|
}
|
|
1144
1154
|
function isColorValid(color) {
|
|
1145
1155
|
try {
|
|
1146
|
-
|
|
1147
|
-
return
|
|
1156
|
+
toHex(color);
|
|
1157
|
+
return true;
|
|
1148
1158
|
}
|
|
1149
1159
|
catch (error) {
|
|
1150
1160
|
return false;
|
|
@@ -1177,15 +1187,29 @@
|
|
|
1177
1187
|
/**
|
|
1178
1188
|
* Convert a CSS rgb color string to a standardized hex6 color value.
|
|
1179
1189
|
*
|
|
1180
|
-
*
|
|
1190
|
+
* rgbaStringToHex("rgb(30, 80, 16)")
|
|
1181
1191
|
* >> "#1E5010"
|
|
1192
|
+
*
|
|
1193
|
+
* rgbaStringToHex("rgba(30, 80, 16, 0.5)")
|
|
1194
|
+
* >> "#1E501080"
|
|
1195
|
+
*
|
|
1196
|
+
* DOES NOT SUPPORT NON INTEGER RGB VALUES
|
|
1182
1197
|
*/
|
|
1183
|
-
function
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1198
|
+
function rgbaStringToHex(color) {
|
|
1199
|
+
const stringVals = color.replace(RBA_REGEX, "").split(",");
|
|
1200
|
+
let alphaHex = 255;
|
|
1201
|
+
if (stringVals.length !== 3 && stringVals.length !== 4) {
|
|
1202
|
+
throw new Error("invalid color");
|
|
1203
|
+
}
|
|
1204
|
+
else if (stringVals.length === 4) {
|
|
1205
|
+
const alpha = parseFloat(stringVals.pop() || "1");
|
|
1206
|
+
alphaHex = Math.round((alpha || 1) * 255);
|
|
1207
|
+
}
|
|
1208
|
+
const vals = stringVals.map((val) => parseInt(val, 10));
|
|
1209
|
+
if (alphaHex !== 255) {
|
|
1210
|
+
vals.push(alphaHex);
|
|
1211
|
+
}
|
|
1212
|
+
return "#" + concat(vals.map((value) => value.toString(16).padStart(2, "0"))).toUpperCase();
|
|
1189
1213
|
}
|
|
1190
1214
|
/**
|
|
1191
1215
|
* RGBA to HEX representation (#RRGGBBAA).
|
|
@@ -1207,7 +1231,7 @@
|
|
|
1207
1231
|
a = "0" + a;
|
|
1208
1232
|
if (a === "ff")
|
|
1209
1233
|
a = "";
|
|
1210
|
-
return "#" + r + g + b + a;
|
|
1234
|
+
return ("#" + r + g + b + a).toUpperCase();
|
|
1211
1235
|
}
|
|
1212
1236
|
/**
|
|
1213
1237
|
* Color string to RGBA representation
|
|
@@ -1328,6 +1352,9 @@
|
|
|
1328
1352
|
s = +(s * 100).toFixed(1);
|
|
1329
1353
|
l = +(l * 100).toFixed(1);
|
|
1330
1354
|
return { a: rgba.a, h, s, l };
|
|
1355
|
+
}
|
|
1356
|
+
function isSameColor(color1, color2) {
|
|
1357
|
+
return isColorValid(color1) && isColorValid(color2) && toHex(color1) === toHex(color2);
|
|
1331
1358
|
}
|
|
1332
1359
|
|
|
1333
1360
|
/** Reference of a cell (eg. A1, $B$5) */
|
|
@@ -1479,7 +1506,7 @@
|
|
|
1479
1506
|
* formula, commas are used to separate arguments
|
|
1480
1507
|
* - it does not support % symbol, in formulas % is an operator
|
|
1481
1508
|
*/
|
|
1482
|
-
const formulaNumberRegexp =
|
|
1509
|
+
const formulaNumberRegexp = /(^-?\d+(\.?\d*(e\d+)?)?|^-?\.\d+)(?!\w|!)/;
|
|
1483
1510
|
const pIntegerAndDecimals = "(\\d+(,\\d{3,})*(\\.\\d*)?)"; // pattern that match integer number with or without decimal digits
|
|
1484
1511
|
const pOnlyDecimals = "(\\.\\d+)"; // pattern that match only expression with decimal digits
|
|
1485
1512
|
const pScientificFormat = "(e(\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
|
|
@@ -3052,6 +3079,9 @@
|
|
|
3052
3079
|
}
|
|
3053
3080
|
return attributes;
|
|
3054
3081
|
}
|
|
3082
|
+
/**
|
|
3083
|
+
* Transform CSS properties into a CSS string.
|
|
3084
|
+
*/
|
|
3055
3085
|
function cssPropertiesToCss(attributes) {
|
|
3056
3086
|
const str = Object.entries(attributes)
|
|
3057
3087
|
.filter(([attName, attValue]) => attValue !== undefined)
|
|
@@ -3085,6 +3115,7 @@
|
|
|
3085
3115
|
const LINE_HEIGHT = 1.2;
|
|
3086
3116
|
css /* scss */ `
|
|
3087
3117
|
div.o-scorecard {
|
|
3118
|
+
font-family: ${DEFAULT_FONT};
|
|
3088
3119
|
user-select: none;
|
|
3089
3120
|
background-color: white;
|
|
3090
3121
|
display: flex;
|
|
@@ -5072,6 +5103,10 @@
|
|
|
5072
5103
|
function rectIntersection(rect1, rect2) {
|
|
5073
5104
|
return zoneToRect(intersection(rectToZone(rect1), rectToZone(rect2)));
|
|
5074
5105
|
}
|
|
5106
|
+
/** Compute the union of the rectangles, ie. the smallest rectangle that contain them all */
|
|
5107
|
+
function rectUnion(...rects) {
|
|
5108
|
+
return zoneToRect(union(...rects.map(rectToZone)));
|
|
5109
|
+
}
|
|
5075
5110
|
function rectToZone(rect) {
|
|
5076
5111
|
return {
|
|
5077
5112
|
left: rect.x,
|
|
@@ -5368,24 +5403,30 @@
|
|
|
5368
5403
|
}
|
|
5369
5404
|
});
|
|
5370
5405
|
}
|
|
5371
|
-
get
|
|
5372
|
-
|
|
5406
|
+
get menuItemsAndSeparators() {
|
|
5407
|
+
const menuItemsAndSeparators = [];
|
|
5408
|
+
for (let i = 0; i < this.props.menuItems.length; i++) {
|
|
5409
|
+
const menuItem = this.props.menuItems[i];
|
|
5410
|
+
if (menuItem.isVisible(this.env)) {
|
|
5411
|
+
menuItemsAndSeparators.push(menuItem);
|
|
5412
|
+
}
|
|
5413
|
+
if (menuItem.separator &&
|
|
5414
|
+
i !== this.props.menuItems.length - 1 && // no separator at the end
|
|
5415
|
+
menuItemsAndSeparators[menuItemsAndSeparators.length - 1] !== "separator" // no double separator
|
|
5416
|
+
) {
|
|
5417
|
+
menuItemsAndSeparators.push("separator");
|
|
5418
|
+
}
|
|
5419
|
+
}
|
|
5420
|
+
if (menuItemsAndSeparators.length === 1 && menuItemsAndSeparators[0] === "separator") {
|
|
5421
|
+
return [];
|
|
5422
|
+
}
|
|
5423
|
+
return menuItemsAndSeparators;
|
|
5373
5424
|
}
|
|
5374
5425
|
get subMenuPosition() {
|
|
5375
5426
|
const position = Object.assign({}, this.subMenu.position);
|
|
5376
5427
|
position.y -= this.subMenu.scrollOffset || 0;
|
|
5377
5428
|
return position;
|
|
5378
5429
|
}
|
|
5379
|
-
get menuHeight() {
|
|
5380
|
-
const menuItems = this.visibleMenuItems;
|
|
5381
|
-
let menuItemsHeight = this.getMenuItemsHeight(menuItems);
|
|
5382
|
-
// We don't display separator at the end of a menu
|
|
5383
|
-
if (menuItems[menuItems.length - 1].separator) {
|
|
5384
|
-
menuItemsHeight -= MENU_SEPARATOR_HEIGHT;
|
|
5385
|
-
}
|
|
5386
|
-
const menuHeight = 2 * MENU_VERTICAL_PADDING + menuItemsHeight;
|
|
5387
|
-
return this.props.maxHeight ? Math.min(menuHeight, this.props.maxHeight) : menuHeight;
|
|
5388
|
-
}
|
|
5389
5430
|
get popoverProps() {
|
|
5390
5431
|
const isRoot = this.props.depth === 1;
|
|
5391
5432
|
return {
|
|
@@ -5399,7 +5440,6 @@
|
|
|
5399
5440
|
verticalOffset: isRoot ? 0 : MENU_VERTICAL_PADDING,
|
|
5400
5441
|
onPopoverHidden: () => this.closeSubMenu(),
|
|
5401
5442
|
onPopoverMoved: () => this.closeSubMenu(),
|
|
5402
|
-
maxHeight: this.menuHeight,
|
|
5403
5443
|
};
|
|
5404
5444
|
}
|
|
5405
5445
|
getColor(menu) {
|
|
@@ -5415,14 +5455,6 @@
|
|
|
5415
5455
|
this.closeSubMenu();
|
|
5416
5456
|
this.props.onClose();
|
|
5417
5457
|
}
|
|
5418
|
-
/**
|
|
5419
|
-
* Return the number of pixels between the top of the menu
|
|
5420
|
-
* and the menu item at a given index.
|
|
5421
|
-
*/
|
|
5422
|
-
subMenuVerticalPosition(menuIndex) {
|
|
5423
|
-
const menusAbove = this.visibleMenuItems.slice(0, menuIndex);
|
|
5424
|
-
return this.position.y + this.getMenuItemsHeight(menusAbove) + MENU_VERTICAL_PADDING;
|
|
5425
|
-
}
|
|
5426
5458
|
onExternalClick(ev) {
|
|
5427
5459
|
// Don't close a root menu when clicked to open the submenus.
|
|
5428
5460
|
const el = this.menuRef.el;
|
|
@@ -5432,10 +5464,6 @@
|
|
|
5432
5464
|
ev.closedMenuId = this.props.menuId;
|
|
5433
5465
|
this.close();
|
|
5434
5466
|
}
|
|
5435
|
-
getMenuItemsHeight(menuItems) {
|
|
5436
|
-
const numberOfSeparators = menuItems.filter((m) => m.separator).length;
|
|
5437
|
-
return MENU_ITEM_HEIGHT * menuItems.length + MENU_SEPARATOR_HEIGHT * numberOfSeparators;
|
|
5438
|
-
}
|
|
5439
5467
|
getName(menu) {
|
|
5440
5468
|
return menu.name(this.env);
|
|
5441
5469
|
}
|
|
@@ -5455,8 +5483,11 @@
|
|
|
5455
5483
|
* If the given menu is not disabled, open it's submenu at the
|
|
5456
5484
|
* correct position according to available surrounding space.
|
|
5457
5485
|
*/
|
|
5458
|
-
openSubMenu(menu, menuIndex) {
|
|
5459
|
-
const
|
|
5486
|
+
openSubMenu(menu, menuIndex, ev) {
|
|
5487
|
+
const parentMenuEl = ev.currentTarget;
|
|
5488
|
+
if (!parentMenuEl)
|
|
5489
|
+
return;
|
|
5490
|
+
const y = parentMenuEl.getBoundingClientRect().top;
|
|
5460
5491
|
this.subMenu.position = {
|
|
5461
5492
|
x: this.position.x + this.props.depth * MENU_WIDTH,
|
|
5462
5493
|
y: y - (this.subMenu.scrollOffset || 0),
|
|
@@ -5473,20 +5504,20 @@
|
|
|
5473
5504
|
this.subMenu.isOpen = false;
|
|
5474
5505
|
this.subMenu.parentMenu = undefined;
|
|
5475
5506
|
}
|
|
5476
|
-
onClickMenu(menu, menuIndex) {
|
|
5507
|
+
onClickMenu(menu, menuIndex, ev) {
|
|
5477
5508
|
if (this.isEnabled(menu)) {
|
|
5478
5509
|
if (this.isRoot(menu)) {
|
|
5479
|
-
this.openSubMenu(menu, menuIndex);
|
|
5510
|
+
this.openSubMenu(menu, menuIndex, ev);
|
|
5480
5511
|
}
|
|
5481
5512
|
else {
|
|
5482
5513
|
this.activateMenu(menu);
|
|
5483
5514
|
}
|
|
5484
5515
|
}
|
|
5485
5516
|
}
|
|
5486
|
-
onMouseOver(menu, position) {
|
|
5517
|
+
onMouseOver(menu, position, ev) {
|
|
5487
5518
|
if (menu.isEnabled(this.env)) {
|
|
5488
5519
|
if (this.isRoot(menu)) {
|
|
5489
|
-
this.openSubMenu(menu, position);
|
|
5520
|
+
this.openSubMenu(menu, position, ev);
|
|
5490
5521
|
}
|
|
5491
5522
|
else {
|
|
5492
5523
|
this.closeSubMenu();
|
|
@@ -6063,8 +6094,8 @@
|
|
|
6063
6094
|
const dataSets = [];
|
|
6064
6095
|
for (const sheetXC of dataSetsString) {
|
|
6065
6096
|
const dataRange = getters.getRangeFromSheetXC(sheetId, sheetXC);
|
|
6066
|
-
const { unboundedZone: zone, sheetId: dataSetSheetId, invalidSheetName } = dataRange;
|
|
6067
|
-
if (invalidSheetName) {
|
|
6097
|
+
const { unboundedZone: zone, sheetId: dataSetSheetId, invalidSheetName, invalidXc } = dataRange;
|
|
6098
|
+
if (invalidSheetName || invalidXc) {
|
|
6068
6099
|
continue;
|
|
6069
6100
|
}
|
|
6070
6101
|
// It's a rectangle. We treat all columns (arbitrary) as different data series.
|
|
@@ -6089,14 +6120,8 @@
|
|
|
6089
6120
|
: undefined));
|
|
6090
6121
|
}
|
|
6091
6122
|
}
|
|
6092
|
-
else if (zone.left === zone.right && zone.top === zone.bottom) {
|
|
6093
|
-
// A single cell. If it's only the title, the dataset is not added.
|
|
6094
|
-
if (!dataSetsHaveTitle) {
|
|
6095
|
-
dataSets.push(createDataSet(getters, dataSetSheetId, zone, undefined));
|
|
6096
|
-
}
|
|
6097
|
-
}
|
|
6098
6123
|
else {
|
|
6099
|
-
/* 1 row or 1 column */
|
|
6124
|
+
/* 1 cell, 1 row or 1 column */
|
|
6100
6125
|
dataSets.push(createDataSet(getters, dataSetSheetId, zone, dataSetsHaveTitle
|
|
6101
6126
|
? {
|
|
6102
6127
|
top: zone.top,
|
|
@@ -6150,6 +6175,18 @@
|
|
|
6150
6175
|
range: getters.getRangeString(dataRange, "forceSheetReference"),
|
|
6151
6176
|
};
|
|
6152
6177
|
}
|
|
6178
|
+
function toExcelLabelRange(getters, labelRange, shouldRemoveFirstLabel) {
|
|
6179
|
+
if (!labelRange)
|
|
6180
|
+
return undefined;
|
|
6181
|
+
let zone = {
|
|
6182
|
+
...labelRange.zone,
|
|
6183
|
+
};
|
|
6184
|
+
if (shouldRemoveFirstLabel && labelRange.zone.bottom > labelRange.zone.top) {
|
|
6185
|
+
zone.top = zone.top + 1;
|
|
6186
|
+
}
|
|
6187
|
+
const range = labelRange.clone({ zone });
|
|
6188
|
+
return getters.getRangeString(range, "forceSheetReference");
|
|
6189
|
+
}
|
|
6153
6190
|
/**
|
|
6154
6191
|
* Transform a chart definition which supports dataSets (dataSets and LabelRange)
|
|
6155
6192
|
* with an executed command
|
|
@@ -6234,6 +6271,20 @@
|
|
|
6234
6271
|
}
|
|
6235
6272
|
return 0 /* CommandResult.Success */;
|
|
6236
6273
|
}
|
|
6274
|
+
function shouldRemoveFirstLabel(labelRange, dataset, dataSetsHaveTitle) {
|
|
6275
|
+
if (!dataSetsHaveTitle)
|
|
6276
|
+
return false;
|
|
6277
|
+
if (!labelRange)
|
|
6278
|
+
return false;
|
|
6279
|
+
if (!dataset)
|
|
6280
|
+
return true;
|
|
6281
|
+
const datasetLength = getZoneArea(dataset.dataRange.zone);
|
|
6282
|
+
const labelLength = getZoneArea(labelRange.zone);
|
|
6283
|
+
if (labelLength < datasetLength) {
|
|
6284
|
+
return false;
|
|
6285
|
+
}
|
|
6286
|
+
return true;
|
|
6287
|
+
}
|
|
6237
6288
|
// ---------------------------------------------------------------------------
|
|
6238
6289
|
// Scorecard
|
|
6239
6290
|
// ---------------------------------------------------------------------------
|
|
@@ -6603,6 +6654,7 @@
|
|
|
6603
6654
|
this.legendPosition = definition.legendPosition;
|
|
6604
6655
|
this.stacked = definition.stacked;
|
|
6605
6656
|
this.aggregated = definition.aggregated;
|
|
6657
|
+
this.dataSetsHaveTitle = definition.dataSetsHaveTitle;
|
|
6606
6658
|
}
|
|
6607
6659
|
static transformDefinition(definition, executed) {
|
|
6608
6660
|
return transformChartDefinitionWithDataSetsWithZone(definition, executed);
|
|
@@ -6670,11 +6722,13 @@
|
|
|
6670
6722
|
const dataSets = this.dataSets
|
|
6671
6723
|
.map((ds) => toExcelDataset(this.getters, ds))
|
|
6672
6724
|
.filter((ds) => ds.range !== ""); // && range !== INCORRECT_RANGE_STRING ? show incorrect #ref ?
|
|
6725
|
+
const labelRange = toExcelLabelRange(this.getters, this.labelRange, shouldRemoveFirstLabel(this.labelRange, this.dataSets[0], this.dataSetsHaveTitle));
|
|
6673
6726
|
return {
|
|
6674
6727
|
...this.getDefinition(),
|
|
6675
6728
|
backgroundColor: toXlsxHexColor(this.background || BACKGROUND_CHART_COLOR),
|
|
6676
6729
|
fontColor: toXlsxHexColor(chartFontColor(this.background)),
|
|
6677
6730
|
dataSets,
|
|
6731
|
+
labelRange,
|
|
6678
6732
|
};
|
|
6679
6733
|
}
|
|
6680
6734
|
updateRanges(applyChange) {
|
|
@@ -6742,6 +6796,11 @@
|
|
|
6742
6796
|
const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
|
|
6743
6797
|
let labels = labelValues.formattedValues;
|
|
6744
6798
|
let dataSetsValues = getChartDatasetValues(getters, chart.dataSets);
|
|
6799
|
+
if (chart.dataSetsHaveTitle &&
|
|
6800
|
+
dataSetsValues[0] &&
|
|
6801
|
+
labels.length > dataSetsValues[0].data.length) {
|
|
6802
|
+
labels.shift();
|
|
6803
|
+
}
|
|
6745
6804
|
({ labels, dataSetsValues } = filterEmptyDataPoints(labels, dataSetsValues));
|
|
6746
6805
|
if (chart.aggregated) {
|
|
6747
6806
|
({ labels, dataSetsValues } = aggregateDataForLabels(labels, dataSetsValues));
|
|
@@ -7164,6 +7223,7 @@
|
|
|
7164
7223
|
this.labelsAsText = definition.labelsAsText;
|
|
7165
7224
|
this.stacked = definition.stacked;
|
|
7166
7225
|
this.aggregated = definition.aggregated;
|
|
7226
|
+
this.dataSetsHaveTitle = definition.dataSetsHaveTitle;
|
|
7167
7227
|
}
|
|
7168
7228
|
static validateChartDefinition(validator, definition) {
|
|
7169
7229
|
return validator.checkValidations(definition, checkDataset, checkLabelRange);
|
|
@@ -7231,11 +7291,13 @@
|
|
|
7231
7291
|
const dataSets = this.dataSets
|
|
7232
7292
|
.map((ds) => toExcelDataset(this.getters, ds))
|
|
7233
7293
|
.filter((ds) => ds.range !== ""); // && range !== INCORRECT_RANGE_STRING ? show incorrect #ref ?
|
|
7294
|
+
const labelRange = toExcelLabelRange(this.getters, this.labelRange, shouldRemoveFirstLabel(this.labelRange, this.dataSets[0], this.dataSetsHaveTitle));
|
|
7234
7295
|
return {
|
|
7235
7296
|
...this.getDefinition(),
|
|
7236
7297
|
backgroundColor: toXlsxHexColor(this.background || BACKGROUND_CHART_COLOR),
|
|
7237
7298
|
fontColor: toXlsxHexColor(chartFontColor(this.background)),
|
|
7238
7299
|
dataSets,
|
|
7300
|
+
labelRange,
|
|
7239
7301
|
};
|
|
7240
7302
|
}
|
|
7241
7303
|
copyForSheetId(sheetId) {
|
|
@@ -7373,6 +7435,11 @@
|
|
|
7373
7435
|
const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
|
|
7374
7436
|
let labels = axisType === "linear" ? labelValues.values : labelValues.formattedValues;
|
|
7375
7437
|
let dataSetsValues = getChartDatasetValues(getters, chart.dataSets);
|
|
7438
|
+
if (chart.dataSetsHaveTitle &&
|
|
7439
|
+
dataSetsValues[0] &&
|
|
7440
|
+
labels.length > dataSetsValues[0].data.length) {
|
|
7441
|
+
labels.shift();
|
|
7442
|
+
}
|
|
7376
7443
|
({ labels, dataSetsValues } = filterEmptyDataPoints(labels, dataSetsValues));
|
|
7377
7444
|
if (axisType === "time") {
|
|
7378
7445
|
({ labels, dataSetsValues } = fixEmptyLabelsForDateCharts(labels, dataSetsValues));
|
|
@@ -7431,6 +7498,7 @@
|
|
|
7431
7498
|
this.background = definition.background;
|
|
7432
7499
|
this.legendPosition = definition.legendPosition;
|
|
7433
7500
|
this.aggregated = definition.aggregated;
|
|
7501
|
+
this.dataSetsHaveTitle = definition.dataSetsHaveTitle;
|
|
7434
7502
|
}
|
|
7435
7503
|
static transformDefinition(definition, executed) {
|
|
7436
7504
|
return transformChartDefinitionWithDataSetsWithZone(definition, executed);
|
|
@@ -7494,12 +7562,14 @@
|
|
|
7494
7562
|
const dataSets = this.dataSets
|
|
7495
7563
|
.map((ds) => toExcelDataset(this.getters, ds))
|
|
7496
7564
|
.filter((ds) => ds.range !== ""); // && range !== INCORRECT_RANGE_STRING ? show incorrect #ref ?
|
|
7565
|
+
const labelRange = toExcelLabelRange(this.getters, this.labelRange, shouldRemoveFirstLabel(this.labelRange, this.dataSets[0], this.dataSetsHaveTitle));
|
|
7497
7566
|
return {
|
|
7498
7567
|
...this.getDefinition(),
|
|
7499
7568
|
backgroundColor: toXlsxHexColor(this.background || BACKGROUND_CHART_COLOR),
|
|
7500
7569
|
fontColor: toXlsxHexColor(chartFontColor(this.background)),
|
|
7501
7570
|
verticalAxisPosition: "left",
|
|
7502
7571
|
dataSets,
|
|
7572
|
+
labelRange,
|
|
7503
7573
|
};
|
|
7504
7574
|
}
|
|
7505
7575
|
updateRanges(applyChange) {
|
|
@@ -7545,6 +7615,11 @@
|
|
|
7545
7615
|
const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
|
|
7546
7616
|
let labels = labelValues.formattedValues;
|
|
7547
7617
|
let dataSetsValues = getChartDatasetValues(getters, chart.dataSets);
|
|
7618
|
+
if (chart.dataSetsHaveTitle &&
|
|
7619
|
+
dataSetsValues[0] &&
|
|
7620
|
+
labels.length > dataSetsValues[0].data.length) {
|
|
7621
|
+
labels.shift();
|
|
7622
|
+
}
|
|
7548
7623
|
({ labels, dataSetsValues } = filterEmptyDataPoints(labels, dataSetsValues));
|
|
7549
7624
|
if (chart.aggregated) {
|
|
7550
7625
|
({ labels, dataSetsValues } = aggregateDataForLabels(labels, dataSetsValues));
|
|
@@ -7801,6 +7876,10 @@
|
|
|
7801
7876
|
}
|
|
7802
7877
|
`;
|
|
7803
7878
|
class ChartFigure extends owl.Component {
|
|
7879
|
+
onDoubleClick() {
|
|
7880
|
+
this.env.model.dispatch("SELECT_FIGURE", { id: this.props.figure.id });
|
|
7881
|
+
this.env.openSidePanel("ChartPanel");
|
|
7882
|
+
}
|
|
7804
7883
|
get chartType() {
|
|
7805
7884
|
return this.env.model.getters.getChartType(this.props.figure.id);
|
|
7806
7885
|
}
|
|
@@ -8176,7 +8255,6 @@
|
|
|
8176
8255
|
labelRangeXc = zoneToXc({
|
|
8177
8256
|
...zone,
|
|
8178
8257
|
right: zone.left,
|
|
8179
|
-
top: dataSetsHaveTitle ? zone.top + 1 : zone.top,
|
|
8180
8258
|
});
|
|
8181
8259
|
}
|
|
8182
8260
|
// Only display legend for several datasets.
|
|
@@ -15094,7 +15172,7 @@
|
|
|
15094
15172
|
cellReference = rowPart + colPart;
|
|
15095
15173
|
}
|
|
15096
15174
|
if (sheet !== undefined) {
|
|
15097
|
-
return `${
|
|
15175
|
+
return `${getCanonicalSheetName(toString(sheet))}!${cellReference}`;
|
|
15098
15176
|
}
|
|
15099
15177
|
return cellReference;
|
|
15100
15178
|
},
|
|
@@ -16919,6 +16997,22 @@
|
|
|
16919
16997
|
aggregated: ev.target.checked,
|
|
16920
16998
|
});
|
|
16921
16999
|
}
|
|
17000
|
+
calculateHeaderPosition() {
|
|
17001
|
+
if (this.isDatasetInvalid || this.isLabelInvalid) {
|
|
17002
|
+
return undefined;
|
|
17003
|
+
}
|
|
17004
|
+
const getters = this.env.model.getters;
|
|
17005
|
+
const sheetId = getters.getActiveSheetId();
|
|
17006
|
+
const labelRange = createRange(getters, sheetId, this.labelRange);
|
|
17007
|
+
const dataSets = createDataSets(getters, this.dataSeriesRanges, sheetId, this.props.definition.dataSetsHaveTitle);
|
|
17008
|
+
if (dataSets.length) {
|
|
17009
|
+
return dataSets[0].dataRange.zone.top + 1;
|
|
17010
|
+
}
|
|
17011
|
+
else if (labelRange) {
|
|
17012
|
+
return labelRange.zone.top + 1;
|
|
17013
|
+
}
|
|
17014
|
+
return undefined;
|
|
17015
|
+
}
|
|
16922
17016
|
}
|
|
16923
17017
|
LineBarPieConfigPanel.template = "o-spreadsheet-LineBarPieConfigPanel";
|
|
16924
17018
|
LineBarPieConfigPanel.components = { SelectionInput };
|
|
@@ -17166,6 +17260,9 @@
|
|
|
17166
17260
|
top,
|
|
17167
17261
|
});
|
|
17168
17262
|
}
|
|
17263
|
+
isSameColor(color1, color2) {
|
|
17264
|
+
return isSameColor(color1, color2);
|
|
17265
|
+
}
|
|
17169
17266
|
}
|
|
17170
17267
|
ColorPicker.template = "o-spreadsheet-ColorPicker";
|
|
17171
17268
|
ColorPicker.defaultProps = {
|
|
@@ -18838,7 +18935,7 @@
|
|
|
18838
18935
|
box-sizing: content-box;
|
|
18839
18936
|
|
|
18840
18937
|
.o-fig-anchor {
|
|
18841
|
-
z-index: ${ComponentsImportance.
|
|
18938
|
+
z-index: ${ComponentsImportance.FigureAnchor};
|
|
18842
18939
|
position: absolute;
|
|
18843
18940
|
width: ${ANCHOR_SIZE}px;
|
|
18844
18941
|
height: ${ANCHOR_SIZE}px;
|
|
@@ -19407,6 +19504,8 @@
|
|
|
19407
19504
|
start = 0;
|
|
19408
19505
|
if (end > textLength)
|
|
19409
19506
|
end = textLength;
|
|
19507
|
+
if (start > textLength)
|
|
19508
|
+
start = textLength;
|
|
19410
19509
|
}
|
|
19411
19510
|
let startNode = this.findChildAtCharacterIndex(start);
|
|
19412
19511
|
let endNode = this.findChildAtCharacterIndex(end);
|
|
@@ -19676,6 +19775,7 @@
|
|
|
19676
19775
|
padding-right: 2px;
|
|
19677
19776
|
|
|
19678
19777
|
box-sizing: border-box;
|
|
19778
|
+
font-family: ${DEFAULT_FONT};
|
|
19679
19779
|
|
|
19680
19780
|
caret-color: black;
|
|
19681
19781
|
padding-left: 3px;
|
|
@@ -19705,13 +19805,6 @@
|
|
|
19705
19805
|
pointer-events: none;
|
|
19706
19806
|
}
|
|
19707
19807
|
}
|
|
19708
|
-
|
|
19709
|
-
.o-topbar-composer .o-composer:empty:not(:focus)::before {
|
|
19710
|
-
/* svg free of use from https://uxwing.com/formula-fx-icon/ */
|
|
19711
|
-
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 121.8 122.9' width='16' height='16' focusable='false'%3E%3Cpath d='m28 34-4 5v2h10l-6 40c-4 22-6 28-7 30-2 2-3 3-5 3-3 0-7-2-9-4H4c-2 2-4 4-4 7s4 6 8 6 9-2 15-8c8-7 13-17 18-39l7-35 13-1 3-6H49c4-23 7-27 11-27 2 0 5 2 8 6h4c1-1 4-4 4-7 0-2-3-6-9-6-5 0-13 4-20 10-6 7-9 14-11 24h-8zm41 16c4-5 7-7 8-7s2 1 5 9l3 12c-7 11-12 17-16 17l-3-1-2-1c-3 0-6 3-6 7s3 7 7 7c6 0 12-6 22-23l3 10c3 9 6 13 10 13 5 0 11-4 18-15l-3-4c-4 6-7 8-8 8-2 0-4-3-6-10l-5-15 8-10 6-4 3 1 3 2c2 0 6-3 6-7s-2-7-6-7c-6 0-11 5-21 20l-2-6c-3-9-5-14-9-14-5 0-12 6-18 15l3 3z' fill='%23BDBDBD' /%3E%3C/svg%3E");
|
|
19712
|
-
position: relative;
|
|
19713
|
-
top: 20%;
|
|
19714
|
-
}
|
|
19715
19808
|
`;
|
|
19716
19809
|
class Composer extends owl.Component {
|
|
19717
19810
|
constructor() {
|
|
@@ -20125,7 +20218,7 @@
|
|
|
20125
20218
|
const highlights = this.env.model.getters.getHighlights();
|
|
20126
20219
|
const refSheet = sheetName
|
|
20127
20220
|
? this.env.model.getters.getSheetIdByName(sheetName)
|
|
20128
|
-
: this.env.model.getters.
|
|
20221
|
+
: this.env.model.getters.getCurrentEditedCell().sheetId;
|
|
20129
20222
|
const highlight = highlights.find((highlight) => {
|
|
20130
20223
|
if (highlight.sheetId !== refSheet)
|
|
20131
20224
|
return false;
|
|
@@ -20286,7 +20379,7 @@
|
|
|
20286
20379
|
get cellReference() {
|
|
20287
20380
|
const { col, row, sheetId } = this.env.model.getters.getCurrentEditedCell();
|
|
20288
20381
|
const prefixSheet = sheetId !== this.env.model.getters.getActiveSheetId();
|
|
20289
|
-
return `${prefixSheet ?
|
|
20382
|
+
return `${prefixSheet ? getCanonicalSheetName(this.env.model.getters.getSheetName(sheetId)) + "!" : ""}${toXC(col, row)}`;
|
|
20290
20383
|
}
|
|
20291
20384
|
get cellReferenceStyle() {
|
|
20292
20385
|
const { x: left, y: top } = this.rect;
|
|
@@ -20439,6 +20532,269 @@
|
|
|
20439
20532
|
gridPosition: { type: Object, optional: true },
|
|
20440
20533
|
};
|
|
20441
20534
|
|
|
20535
|
+
/**
|
|
20536
|
+
* Transform a figure with coordinates from the model, to coordinates as they are shown on the screen,
|
|
20537
|
+
* taking into account the scroll position of the active sheet and the frozen panes.
|
|
20538
|
+
*/
|
|
20539
|
+
function internalFigureToScreen(getters, fig) {
|
|
20540
|
+
return { ...fig, ...internalToScreenCoordinates(getters, { x: fig.x, y: fig.y }) };
|
|
20541
|
+
}
|
|
20542
|
+
/**
|
|
20543
|
+
* Transform a figure with coordinates as they are shown on the screen, to coordinates as they are in the model,
|
|
20544
|
+
* taking into account the scroll position of the active sheet and the frozen panes.
|
|
20545
|
+
*
|
|
20546
|
+
* Note that this isn't exactly the reverse operation as internalFigureToScreen, because the figure will always be on top
|
|
20547
|
+
* of the frozen panes.
|
|
20548
|
+
*/
|
|
20549
|
+
function screenFigureToInternal(getters, fig) {
|
|
20550
|
+
return { ...fig, ...screenCoordinatesToInternal(getters, { x: fig.x, y: fig.y }) };
|
|
20551
|
+
}
|
|
20552
|
+
function internalToScreenCoordinates(getters, { x, y }) {
|
|
20553
|
+
const { x: viewportX, y: viewportY } = getters.getMainViewportCoordinates();
|
|
20554
|
+
const { scrollX, scrollY } = getters.getActiveSheetScrollInfo();
|
|
20555
|
+
x = x < viewportX ? x : x - scrollX;
|
|
20556
|
+
y = y < viewportY ? y : y - scrollY;
|
|
20557
|
+
return { x, y };
|
|
20558
|
+
}
|
|
20559
|
+
function screenCoordinatesToInternal(getters, { x, y }) {
|
|
20560
|
+
const { x: viewportX, y: viewportY } = getters.getMainViewportCoordinates();
|
|
20561
|
+
const { scrollX, scrollY } = getters.getActiveSheetScrollInfo();
|
|
20562
|
+
x = viewportX && x < viewportX ? x : x + scrollX;
|
|
20563
|
+
y = viewportY && y < viewportY ? y : y + scrollY;
|
|
20564
|
+
return { x, y };
|
|
20565
|
+
}
|
|
20566
|
+
|
|
20567
|
+
function dragFigureForMove({ x: mouseX, y: mouseY }, { x: mouseInitialX, y: mouseInitialY }, initialFigure, { x: viewportX, y: viewportY }, { maxX, maxY }, { scrollX, scrollY }) {
|
|
20568
|
+
const minX = viewportX ? 0 : -scrollX;
|
|
20569
|
+
const minY = viewportY ? 0 : -scrollY;
|
|
20570
|
+
const deltaX = mouseX - mouseInitialX;
|
|
20571
|
+
const newX = clamp(initialFigure.x + deltaX, minX, maxX - initialFigure.width - scrollX);
|
|
20572
|
+
const deltaY = mouseY - mouseInitialY;
|
|
20573
|
+
const newY = clamp(initialFigure.y + deltaY, minY, maxY - initialFigure.height - scrollY);
|
|
20574
|
+
return { ...initialFigure, x: newX, y: newY };
|
|
20575
|
+
}
|
|
20576
|
+
function clamp(value, min, max) {
|
|
20577
|
+
return Math.min(Math.max(value, min), max);
|
|
20578
|
+
}
|
|
20579
|
+
function dragFigureForResize(initialFigure, dirX, dirY, { x: mouseX, y: mouseY }, { x: mouseInitialX, y: mouseInitialY }, keepRatio, minFigSize) {
|
|
20580
|
+
let { x, y, width, height } = initialFigure;
|
|
20581
|
+
if (keepRatio && dirX != 0 && dirY != 0) {
|
|
20582
|
+
const deltaX = Math.min(dirX * (mouseInitialX - mouseX), initialFigure.width - minFigSize);
|
|
20583
|
+
const deltaY = Math.min(dirY * (mouseInitialY - mouseY), initialFigure.height - minFigSize);
|
|
20584
|
+
const fraction = Math.min(deltaX / initialFigure.width, deltaY / initialFigure.height);
|
|
20585
|
+
width = initialFigure.width * (1 - fraction);
|
|
20586
|
+
height = initialFigure.height * (1 - fraction);
|
|
20587
|
+
if (dirX < 0) {
|
|
20588
|
+
x = initialFigure.x + initialFigure.width * fraction;
|
|
20589
|
+
}
|
|
20590
|
+
if (dirY < 0) {
|
|
20591
|
+
y = initialFigure.y + initialFigure.height * fraction;
|
|
20592
|
+
}
|
|
20593
|
+
}
|
|
20594
|
+
else {
|
|
20595
|
+
const deltaX = Math.max(dirX * (mouseX - mouseInitialX), minFigSize - initialFigure.width);
|
|
20596
|
+
const deltaY = Math.max(dirY * (mouseY - mouseInitialY), minFigSize - initialFigure.height);
|
|
20597
|
+
width = initialFigure.width + deltaX;
|
|
20598
|
+
height = initialFigure.height + deltaY;
|
|
20599
|
+
if (dirX < 0) {
|
|
20600
|
+
x = initialFigure.x - deltaX;
|
|
20601
|
+
}
|
|
20602
|
+
if (dirY < 0) {
|
|
20603
|
+
y = initialFigure.y - deltaY;
|
|
20604
|
+
}
|
|
20605
|
+
}
|
|
20606
|
+
return { ...initialFigure, x, y, width, height };
|
|
20607
|
+
}
|
|
20608
|
+
|
|
20609
|
+
const SNAP_MARGIN = 5;
|
|
20610
|
+
/**
|
|
20611
|
+
* Try to snap the given figure to other figures when moving the figure, and return the snapped
|
|
20612
|
+
* figure and the possible snap lines, if any were found
|
|
20613
|
+
*/
|
|
20614
|
+
function snapForMove(getters, figureToSnap, otherFigures) {
|
|
20615
|
+
const snappedFigure = { ...figureToSnap };
|
|
20616
|
+
const verticalSnapLine = getSnapLine(getters, snappedFigure, ["hCenter", "right", "left"], otherFigures, ["hCenter", "right", "left"]);
|
|
20617
|
+
const horizontalSnapLine = getSnapLine(getters, snappedFigure, ["vCenter", "bottom", "top"], otherFigures, ["vCenter", "bottom", "top"]);
|
|
20618
|
+
const { y: viewportY, x: viewportX } = getters.getMainViewportCoordinates();
|
|
20619
|
+
const { scrollY, scrollX } = getters.getActiveSheetScrollInfo();
|
|
20620
|
+
// If the snap cause the figure to change pane, we need to also apply the scroll as an offset
|
|
20621
|
+
if (horizontalSnapLine) {
|
|
20622
|
+
snappedFigure.y -= horizontalSnapLine.snapOffset;
|
|
20623
|
+
const isBaseFigFrozenY = figureToSnap.y < viewportY;
|
|
20624
|
+
const isSnappedFrozenY = snappedFigure.y < viewportY;
|
|
20625
|
+
if (isBaseFigFrozenY && !isSnappedFrozenY)
|
|
20626
|
+
snappedFigure.y += scrollY;
|
|
20627
|
+
else if (!isBaseFigFrozenY && isSnappedFrozenY)
|
|
20628
|
+
snappedFigure.y -= scrollY;
|
|
20629
|
+
}
|
|
20630
|
+
if (verticalSnapLine) {
|
|
20631
|
+
snappedFigure.x -= verticalSnapLine.snapOffset;
|
|
20632
|
+
const isBaseFigFrozenX = figureToSnap.x < viewportX;
|
|
20633
|
+
const isSnappedFrozenX = snappedFigure.x < viewportX;
|
|
20634
|
+
if (isBaseFigFrozenX && !isSnappedFrozenX)
|
|
20635
|
+
snappedFigure.x += scrollX;
|
|
20636
|
+
else if (!isBaseFigFrozenX && isSnappedFrozenX)
|
|
20637
|
+
snappedFigure.x -= scrollX;
|
|
20638
|
+
}
|
|
20639
|
+
return { snappedFigure, verticalSnapLine, horizontalSnapLine };
|
|
20640
|
+
}
|
|
20641
|
+
/**
|
|
20642
|
+
* Try to snap the given figure to the other figures when resizing the figure, and return the snapped
|
|
20643
|
+
* figure and the possible snap lines, if any were found
|
|
20644
|
+
*/
|
|
20645
|
+
function snapForResize(getters, resizeDirX, resizeDirY, figureToSnap, otherFigures) {
|
|
20646
|
+
const snappedFigure = { ...figureToSnap };
|
|
20647
|
+
// Vertical snap line
|
|
20648
|
+
const verticalSnapLine = getSnapLine(getters, snappedFigure, [resizeDirX === -1 ? "left" : "right"], otherFigures, ["right", "left"]);
|
|
20649
|
+
if (verticalSnapLine) {
|
|
20650
|
+
if (resizeDirX === 1) {
|
|
20651
|
+
snappedFigure.width -= verticalSnapLine.snapOffset;
|
|
20652
|
+
}
|
|
20653
|
+
else if (resizeDirX === -1) {
|
|
20654
|
+
snappedFigure.x -= verticalSnapLine.snapOffset;
|
|
20655
|
+
snappedFigure.width += verticalSnapLine.snapOffset;
|
|
20656
|
+
}
|
|
20657
|
+
}
|
|
20658
|
+
// Horizontal snap line
|
|
20659
|
+
const horizontalSnapLine = getSnapLine(getters, snappedFigure, [resizeDirY === -1 ? "top" : "bottom"], otherFigures, ["bottom", "top"]);
|
|
20660
|
+
if (horizontalSnapLine) {
|
|
20661
|
+
if (resizeDirY === 1) {
|
|
20662
|
+
snappedFigure.height -= horizontalSnapLine.snapOffset;
|
|
20663
|
+
}
|
|
20664
|
+
else if (resizeDirY === -1) {
|
|
20665
|
+
snappedFigure.y -= horizontalSnapLine.snapOffset;
|
|
20666
|
+
snappedFigure.height += horizontalSnapLine.snapOffset;
|
|
20667
|
+
}
|
|
20668
|
+
}
|
|
20669
|
+
snappedFigure.x = Math.round(snappedFigure.x);
|
|
20670
|
+
snappedFigure.y = Math.round(snappedFigure.y);
|
|
20671
|
+
snappedFigure.height = Math.round(snappedFigure.height);
|
|
20672
|
+
snappedFigure.width = Math.round(snappedFigure.width);
|
|
20673
|
+
return { snappedFigure, verticalSnapLine, horizontalSnapLine };
|
|
20674
|
+
}
|
|
20675
|
+
/**
|
|
20676
|
+
* Get the position of snap axes for the given figure
|
|
20677
|
+
*
|
|
20678
|
+
* @param figure the figure
|
|
20679
|
+
* @param axesTypes the list of axis types to return the positions of
|
|
20680
|
+
*/
|
|
20681
|
+
function getVisibleAxes(getters, figure, axesTypes) {
|
|
20682
|
+
const axes = axesTypes.map((axisType) => getAxis(figure, axisType));
|
|
20683
|
+
return axes
|
|
20684
|
+
.filter((axis) => isAxisVisible(getters, figure, axis))
|
|
20685
|
+
.map((axis) => getAxisScreenPosition(getters, figure, axis));
|
|
20686
|
+
}
|
|
20687
|
+
/**
|
|
20688
|
+
* We need two positions for the figure axis :
|
|
20689
|
+
* - the position (core) of the axis in the figure. This is used to know whether or not the axis is
|
|
20690
|
+
* displayed, or is hidden by the scroll/the frozen panes
|
|
20691
|
+
* - the position in the screen, which is used to find snap matches. We cannot use the core position for this,
|
|
20692
|
+
* because figures partially in frozen panes aren't displayed at their actual coordinates
|
|
20693
|
+
*/
|
|
20694
|
+
function getAxisScreenPosition(getters, figure, figureAxis) {
|
|
20695
|
+
const screenFigure = internalFigureToScreen(getters, figure);
|
|
20696
|
+
return getAxis(screenFigure, figureAxis.axisType);
|
|
20697
|
+
}
|
|
20698
|
+
function isAxisVisible(getters, figure, axis) {
|
|
20699
|
+
const { x: mainViewportX, y: mainViewportY } = getters.getMainViewportCoordinates();
|
|
20700
|
+
const axisStartEndPositions = [];
|
|
20701
|
+
switch (axis.axisType) {
|
|
20702
|
+
case "top":
|
|
20703
|
+
case "bottom":
|
|
20704
|
+
case "vCenter":
|
|
20705
|
+
if (figure.y < mainViewportY)
|
|
20706
|
+
return true;
|
|
20707
|
+
axisStartEndPositions.push({ x: figure.x, y: axis.position });
|
|
20708
|
+
axisStartEndPositions.push({ x: figure.x + figure.width, y: axis.position });
|
|
20709
|
+
break;
|
|
20710
|
+
case "left":
|
|
20711
|
+
case "right":
|
|
20712
|
+
case "hCenter":
|
|
20713
|
+
if (figure.x < mainViewportX)
|
|
20714
|
+
return true;
|
|
20715
|
+
axisStartEndPositions.push({ x: axis.position, y: figure.y });
|
|
20716
|
+
axisStartEndPositions.push({ x: axis.position, y: figure.y + figure.height });
|
|
20717
|
+
break;
|
|
20718
|
+
}
|
|
20719
|
+
return axisStartEndPositions.some(getters.isPositionVisible);
|
|
20720
|
+
}
|
|
20721
|
+
/**
|
|
20722
|
+
* Get a snap line for the given figure, if the figure can snap to any other figure
|
|
20723
|
+
*
|
|
20724
|
+
* @param figureToSnap figure to get the snap line for
|
|
20725
|
+
* @param figAxesTypes figure axes of the given figure to be considered to find a snap line
|
|
20726
|
+
* @param otherFigures figures to match against the snapped figure to find a snap line
|
|
20727
|
+
* @param otherAxesTypes figure axes of the other figures to be considered to find a snap line
|
|
20728
|
+
*/
|
|
20729
|
+
function getSnapLine(getters, figureToSnap, figAxesTypes, otherFigures, otherAxesTypes) {
|
|
20730
|
+
const axesOfFigure = getVisibleAxes(getters, figureToSnap, figAxesTypes);
|
|
20731
|
+
let closestMatch = undefined;
|
|
20732
|
+
for (const otherFigure of otherFigures) {
|
|
20733
|
+
const axesOfOtherFig = getVisibleAxes(getters, otherFigure, otherAxesTypes);
|
|
20734
|
+
for (const axisOfFigure of axesOfFigure) {
|
|
20735
|
+
for (const axisOfOtherFig of axesOfOtherFig) {
|
|
20736
|
+
if (!canSnap(axisOfFigure.position, axisOfOtherFig.position))
|
|
20737
|
+
continue;
|
|
20738
|
+
const snapOffset = axisOfFigure.position - axisOfOtherFig.position;
|
|
20739
|
+
if (closestMatch && snapOffset === closestMatch.snapOffset) {
|
|
20740
|
+
closestMatch.matchedFigIds.push(otherFigure.id);
|
|
20741
|
+
}
|
|
20742
|
+
else if (!closestMatch || Math.abs(snapOffset) <= Math.abs(closestMatch.snapOffset)) {
|
|
20743
|
+
closestMatch = {
|
|
20744
|
+
matchedFigIds: [otherFigure.id],
|
|
20745
|
+
snapOffset,
|
|
20746
|
+
snappedAxisType: axisOfFigure.axisType,
|
|
20747
|
+
position: axisOfOtherFig.position,
|
|
20748
|
+
};
|
|
20749
|
+
}
|
|
20750
|
+
}
|
|
20751
|
+
}
|
|
20752
|
+
}
|
|
20753
|
+
return closestMatch;
|
|
20754
|
+
}
|
|
20755
|
+
/** Check if two axes are close enough to snap */
|
|
20756
|
+
function canSnap(axisPosition1, axisPosition2) {
|
|
20757
|
+
return Math.abs(axisPosition1 - axisPosition2) <= SNAP_MARGIN;
|
|
20758
|
+
}
|
|
20759
|
+
function getAxis(fig, axisType) {
|
|
20760
|
+
let position = 0;
|
|
20761
|
+
switch (axisType) {
|
|
20762
|
+
case "top":
|
|
20763
|
+
position = fig.y;
|
|
20764
|
+
break;
|
|
20765
|
+
case "bottom":
|
|
20766
|
+
position = fig.y + fig.height - FIGURE_BORDER_WIDTH;
|
|
20767
|
+
break;
|
|
20768
|
+
case "vCenter":
|
|
20769
|
+
position = fig.y + Math.floor(fig.height / 2) - FIGURE_BORDER_WIDTH;
|
|
20770
|
+
break;
|
|
20771
|
+
case "left":
|
|
20772
|
+
position = fig.x;
|
|
20773
|
+
break;
|
|
20774
|
+
case "right":
|
|
20775
|
+
position = fig.x + fig.width - FIGURE_BORDER_WIDTH;
|
|
20776
|
+
break;
|
|
20777
|
+
case "hCenter":
|
|
20778
|
+
position = fig.x + Math.floor(fig.width / 2) - FIGURE_BORDER_WIDTH;
|
|
20779
|
+
break;
|
|
20780
|
+
}
|
|
20781
|
+
return { position, axisType: axisType };
|
|
20782
|
+
}
|
|
20783
|
+
|
|
20784
|
+
css /*SCSS*/ `
|
|
20785
|
+
.o-figure-snap-line {
|
|
20786
|
+
position: relative;
|
|
20787
|
+
z-index: ${ComponentsImportance.FigureSnapLine};
|
|
20788
|
+
&.vertical {
|
|
20789
|
+
width: 0px;
|
|
20790
|
+
border-left: 1px dashed black;
|
|
20791
|
+
}
|
|
20792
|
+
&.horizontal {
|
|
20793
|
+
border-top: 1px dashed black;
|
|
20794
|
+
height: 0px;
|
|
20795
|
+
}
|
|
20796
|
+
}
|
|
20797
|
+
`;
|
|
20442
20798
|
/**
|
|
20443
20799
|
* Each figure ⭐ is positioned inside a container `div` placed and sized
|
|
20444
20800
|
* according to the split pane the figure is part of, or a separate container for the figure
|
|
@@ -20503,11 +20859,9 @@
|
|
|
20503
20859
|
constructor() {
|
|
20504
20860
|
super(...arguments);
|
|
20505
20861
|
this.dnd = owl.useState({
|
|
20506
|
-
|
|
20507
|
-
|
|
20508
|
-
|
|
20509
|
-
width: 0,
|
|
20510
|
-
height: 0,
|
|
20862
|
+
draggedFigure: undefined,
|
|
20863
|
+
horizontalSnap: undefined,
|
|
20864
|
+
verticalSnap: undefined,
|
|
20511
20865
|
});
|
|
20512
20866
|
}
|
|
20513
20867
|
setup() {
|
|
@@ -20523,9 +20877,11 @@
|
|
|
20523
20877
|
});
|
|
20524
20878
|
}
|
|
20525
20879
|
getVisibleFigures() {
|
|
20880
|
+
var _a;
|
|
20526
20881
|
const visibleFigures = this.env.model.getters.getVisibleFigures();
|
|
20527
|
-
if (this.dnd.
|
|
20528
|
-
visibleFigures.
|
|
20882
|
+
if (this.dnd.draggedFigure &&
|
|
20883
|
+
!visibleFigures.some((figure) => { var _a; return figure.id === ((_a = this.dnd.draggedFigure) === null || _a === void 0 ? void 0 : _a.id); })) {
|
|
20884
|
+
visibleFigures.push(this.env.model.getters.getFigure(this.env.model.getters.getActiveSheetId(), (_a = this.dnd.draggedFigure) === null || _a === void 0 ? void 0 : _a.id));
|
|
20529
20885
|
}
|
|
20530
20886
|
return visibleFigures;
|
|
20531
20887
|
}
|
|
@@ -20548,7 +20904,7 @@
|
|
|
20548
20904
|
});
|
|
20549
20905
|
}
|
|
20550
20906
|
}
|
|
20551
|
-
if (this.dnd.
|
|
20907
|
+
if (this.dnd.draggedFigure) {
|
|
20552
20908
|
containers.push({
|
|
20553
20909
|
type: "dnd",
|
|
20554
20910
|
figures: [this.getDndFigure()],
|
|
@@ -20559,19 +20915,25 @@
|
|
|
20559
20915
|
return containers;
|
|
20560
20916
|
}
|
|
20561
20917
|
getContainerStyle(container) {
|
|
20562
|
-
|
|
20563
|
-
|
|
20564
|
-
|
|
20565
|
-
const width = viewWidth - left;
|
|
20566
|
-
const top = ["bottomRight", "bottomLeft"].includes(container) ? viewportY : 0;
|
|
20567
|
-
const height = viewHeight - top;
|
|
20918
|
+
return this.rectToCss(this.getContainerRect(container));
|
|
20919
|
+
}
|
|
20920
|
+
rectToCss(rect) {
|
|
20568
20921
|
return cssPropertiesToCss({
|
|
20569
|
-
left: `${
|
|
20570
|
-
top: `${
|
|
20571
|
-
width: `${width}px`,
|
|
20572
|
-
height: `${height}px`,
|
|
20922
|
+
left: `${rect.x}px`,
|
|
20923
|
+
top: `${rect.y}px`,
|
|
20924
|
+
width: `${rect.width}px`,
|
|
20925
|
+
height: `${rect.height}px`,
|
|
20573
20926
|
});
|
|
20574
20927
|
}
|
|
20928
|
+
getContainerRect(container) {
|
|
20929
|
+
const { width: viewWidth, height: viewHeight } = this.env.model.getters.getMainViewportRect();
|
|
20930
|
+
const { x: viewportX, y: viewportY } = this.env.model.getters.getMainViewportCoordinates();
|
|
20931
|
+
const x = ["bottomRight", "topRight"].includes(container) ? viewportX : 0;
|
|
20932
|
+
const width = viewWidth - x;
|
|
20933
|
+
const y = ["bottomRight", "bottomLeft"].includes(container) ? viewportY : 0;
|
|
20934
|
+
const height = viewHeight - y;
|
|
20935
|
+
return { x, y, width, height };
|
|
20936
|
+
}
|
|
20575
20937
|
getInverseViewportPositionStyle(container) {
|
|
20576
20938
|
const { scrollX, scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
|
|
20577
20939
|
const { x: viewportX, y: viewportY } = this.env.model.getters.getMainViewportCoordinates();
|
|
@@ -20583,8 +20945,9 @@
|
|
|
20583
20945
|
});
|
|
20584
20946
|
}
|
|
20585
20947
|
getFigureContainer(figure) {
|
|
20948
|
+
var _a;
|
|
20586
20949
|
const { x: viewportX, y: viewportY } = this.env.model.getters.getMainViewportCoordinates();
|
|
20587
|
-
if (figure.id === this.dnd.
|
|
20950
|
+
if (figure.id === ((_a = this.dnd.draggedFigure) === null || _a === void 0 ? void 0 : _a.id)) {
|
|
20588
20951
|
return "dnd";
|
|
20589
20952
|
}
|
|
20590
20953
|
else if (figure.x < viewportX && figure.y < viewportY) {
|
|
@@ -20610,133 +20973,141 @@
|
|
|
20610
20973
|
return;
|
|
20611
20974
|
}
|
|
20612
20975
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
20613
|
-
const
|
|
20614
|
-
const
|
|
20615
|
-
|
|
20616
|
-
|
|
20617
|
-
|
|
20618
|
-
this.
|
|
20619
|
-
|
|
20976
|
+
const initialMousePosition = { x: ev.clientX, y: ev.clientY };
|
|
20977
|
+
const maxDimensions = {
|
|
20978
|
+
maxX: this.env.model.getters.getColDimensions(sheetId, this.env.model.getters.getNumberCols(sheetId) - 1).end,
|
|
20979
|
+
maxY: this.env.model.getters.getRowDimensions(sheetId, this.env.model.getters.getNumberRows(sheetId) - 1).end,
|
|
20980
|
+
};
|
|
20981
|
+
const { x, y } = internalFigureToScreen(this.env.model.getters, figure);
|
|
20982
|
+
const initialFig = { ...figure, x, y };
|
|
20620
20983
|
const onMouseMove = (ev) => {
|
|
20621
|
-
const
|
|
20622
|
-
const {
|
|
20623
|
-
const
|
|
20624
|
-
const
|
|
20625
|
-
|
|
20626
|
-
const
|
|
20627
|
-
|
|
20628
|
-
this.dnd.
|
|
20629
|
-
|
|
20630
|
-
let deltaY = newY - mouseInitialY;
|
|
20631
|
-
this.dnd.y = Math.max(dndInitialY + deltaY, minY);
|
|
20984
|
+
const getters = this.env.model.getters;
|
|
20985
|
+
const currentMousePosition = { x: ev.clientX, y: ev.clientY };
|
|
20986
|
+
const draggedFigure = dragFigureForMove(currentMousePosition, initialMousePosition, initialFig, this.env.model.getters.getMainViewportCoordinates(), maxDimensions, getters.getActiveSheetScrollInfo());
|
|
20987
|
+
const otherFigures = this.getOtherFigures(figure.id);
|
|
20988
|
+
const internalDragged = screenFigureToInternal(getters, draggedFigure);
|
|
20989
|
+
const snapResult = snapForMove(getters, internalDragged, otherFigures);
|
|
20990
|
+
this.dnd.draggedFigure = internalFigureToScreen(getters, snapResult.snappedFigure);
|
|
20991
|
+
this.dnd.horizontalSnap = this.getSnap(snapResult.horizontalSnapLine);
|
|
20992
|
+
this.dnd.verticalSnap = this.getSnap(snapResult.verticalSnapLine);
|
|
20632
20993
|
};
|
|
20633
20994
|
const onMouseUp = (ev) => {
|
|
20634
|
-
if (!this.dnd.
|
|
20995
|
+
if (!this.dnd.draggedFigure) {
|
|
20635
20996
|
return;
|
|
20636
20997
|
}
|
|
20637
|
-
let { x, y } = this.
|
|
20638
|
-
this.dnd.
|
|
20998
|
+
let { x, y } = screenFigureToInternal(this.env.model.getters, this.dnd.draggedFigure);
|
|
20999
|
+
this.dnd.draggedFigure = undefined;
|
|
21000
|
+
this.dnd.horizontalSnap = undefined;
|
|
21001
|
+
this.dnd.verticalSnap = undefined;
|
|
20639
21002
|
this.env.model.dispatch("UPDATE_FIGURE", { sheetId, id: figure.id, x, y });
|
|
20640
21003
|
};
|
|
20641
21004
|
startDnd(onMouseMove, onMouseUp);
|
|
20642
21005
|
}
|
|
21006
|
+
/**
|
|
21007
|
+
* Initialize the resize of a figure with mouse movements
|
|
21008
|
+
*
|
|
21009
|
+
* @param dirX X direction of the resize. -1 : resize from the left border of the figure, 0 : no resize in X, 1 :
|
|
21010
|
+
* resize from the right border of the figure
|
|
21011
|
+
* @param dirY Y direction of the resize. -1 : resize from the top border of the figure, 0 : no resize in Y, 1 :
|
|
21012
|
+
* resize from the bottom border of the figure
|
|
21013
|
+
* @param ev Mouse Event
|
|
21014
|
+
*/
|
|
20643
21015
|
startResize(figure, dirX, dirY, ev) {
|
|
20644
21016
|
ev.stopPropagation();
|
|
20645
|
-
const
|
|
20646
|
-
const
|
|
20647
|
-
const { x
|
|
20648
|
-
this.dnd.x = dndInitialX;
|
|
20649
|
-
this.dnd.y = dndInitialY;
|
|
20650
|
-
this.dnd.width = figure.width;
|
|
20651
|
-
this.dnd.height = figure.height;
|
|
21017
|
+
const initialMousePosition = { x: ev.clientX, y: ev.clientY };
|
|
21018
|
+
const { x, y } = internalFigureToScreen(this.env.model.getters, figure);
|
|
21019
|
+
const initialFig = { ...figure, x, y };
|
|
20652
21020
|
const keepRatio = figureRegistry.get(figure.tag).keepRatio || false;
|
|
20653
21021
|
const minFigSize = figureRegistry.get(figure.tag).minFigSize || MIN_FIG_SIZE;
|
|
20654
|
-
|
|
20655
|
-
|
|
20656
|
-
|
|
20657
|
-
|
|
20658
|
-
|
|
20659
|
-
|
|
20660
|
-
|
|
20661
|
-
|
|
20662
|
-
|
|
20663
|
-
if (dirX < 0) {
|
|
20664
|
-
this.dnd.x = dndInitialX + figure.width * fraction;
|
|
20665
|
-
}
|
|
20666
|
-
if (dirY < 0) {
|
|
20667
|
-
this.dnd.y = dndInitialY + figure.height * fraction;
|
|
20668
|
-
}
|
|
20669
|
-
};
|
|
20670
|
-
}
|
|
20671
|
-
else {
|
|
20672
|
-
onMouseMove = (ev) => {
|
|
20673
|
-
this.dnd.figId = figure.id;
|
|
20674
|
-
const deltaX = Math.max(dirX * (ev.clientX - initialX), minFigSize - figure.width);
|
|
20675
|
-
const deltaY = Math.max(dirY * (ev.clientY - initialY), minFigSize - figure.height);
|
|
20676
|
-
this.dnd.width = figure.width + deltaX;
|
|
20677
|
-
this.dnd.height = figure.height + deltaY;
|
|
20678
|
-
if (dirX < 0) {
|
|
20679
|
-
this.dnd.x = dndInitialX - deltaX;
|
|
20680
|
-
}
|
|
20681
|
-
if (dirY < 0) {
|
|
20682
|
-
this.dnd.y = dndInitialY - deltaY;
|
|
20683
|
-
}
|
|
20684
|
-
};
|
|
20685
|
-
}
|
|
21022
|
+
const onMouseMove = (ev) => {
|
|
21023
|
+
const currentMousePosition = { x: ev.clientX, y: ev.clientY };
|
|
21024
|
+
const draggedFigure = dragFigureForResize(initialFig, dirX, dirY, currentMousePosition, initialMousePosition, keepRatio, minFigSize);
|
|
21025
|
+
const otherFigures = this.getOtherFigures(figure.id);
|
|
21026
|
+
const snapResult = snapForResize(this.env.model.getters, dirX, dirY, draggedFigure, otherFigures);
|
|
21027
|
+
this.dnd.draggedFigure = snapResult.snappedFigure;
|
|
21028
|
+
this.dnd.horizontalSnap = this.getSnap(snapResult.horizontalSnapLine);
|
|
21029
|
+
this.dnd.verticalSnap = this.getSnap(snapResult.verticalSnapLine);
|
|
21030
|
+
};
|
|
20686
21031
|
const onMouseUp = (ev) => {
|
|
20687
|
-
if (!this.dnd.
|
|
21032
|
+
if (!this.dnd.draggedFigure) {
|
|
20688
21033
|
return;
|
|
20689
21034
|
}
|
|
20690
|
-
this.dnd.
|
|
20691
|
-
let { x, y } = this.screenCoordinatesToInternal(this.dnd);
|
|
21035
|
+
let { x, y } = screenFigureToInternal(this.env.model.getters, this.dnd.draggedFigure);
|
|
20692
21036
|
const update = { x, y };
|
|
20693
21037
|
if (dirX) {
|
|
20694
|
-
update.width = this.dnd.width;
|
|
21038
|
+
update.width = this.dnd.draggedFigure.width;
|
|
20695
21039
|
}
|
|
20696
21040
|
if (dirY) {
|
|
20697
|
-
update.height = this.dnd.height;
|
|
21041
|
+
update.height = this.dnd.draggedFigure.height;
|
|
20698
21042
|
}
|
|
20699
21043
|
this.env.model.dispatch("UPDATE_FIGURE", {
|
|
20700
21044
|
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
20701
21045
|
id: figure.id,
|
|
20702
21046
|
...update,
|
|
20703
21047
|
});
|
|
21048
|
+
this.dnd.draggedFigure = undefined;
|
|
21049
|
+
this.dnd.horizontalSnap = undefined;
|
|
21050
|
+
this.dnd.verticalSnap = undefined;
|
|
20704
21051
|
};
|
|
20705
21052
|
startDnd(onMouseMove, onMouseUp);
|
|
20706
21053
|
}
|
|
21054
|
+
getOtherFigures(figId) {
|
|
21055
|
+
return this.getVisibleFigures().filter((f) => f.id !== figId);
|
|
21056
|
+
}
|
|
20707
21057
|
getDndFigure() {
|
|
20708
|
-
const figure = this.getVisibleFigures().find((fig) => fig.id === this.dnd.
|
|
21058
|
+
const figure = this.getVisibleFigures().find((fig) => { var _a; return fig.id === ((_a = this.dnd.draggedFigure) === null || _a === void 0 ? void 0 : _a.id); });
|
|
20709
21059
|
if (!figure)
|
|
20710
21060
|
throw new Error("Dnd figure not found");
|
|
20711
21061
|
return {
|
|
20712
21062
|
...figure,
|
|
20713
|
-
|
|
20714
|
-
y: this.dnd.y,
|
|
20715
|
-
width: this.dnd.width,
|
|
20716
|
-
height: this.dnd.height,
|
|
21063
|
+
...this.dnd.draggedFigure,
|
|
20717
21064
|
};
|
|
20718
21065
|
}
|
|
20719
21066
|
getFigureStyle(figure) {
|
|
20720
|
-
|
|
21067
|
+
var _a;
|
|
21068
|
+
if (figure.id !== ((_a = this.dnd.draggedFigure) === null || _a === void 0 ? void 0 : _a.id))
|
|
20721
21069
|
return "";
|
|
20722
21070
|
return cssPropertiesToCss({
|
|
20723
21071
|
opacity: "0.9",
|
|
20724
21072
|
cursor: "grabbing",
|
|
20725
21073
|
});
|
|
20726
21074
|
}
|
|
20727
|
-
|
|
20728
|
-
|
|
20729
|
-
|
|
20730
|
-
|
|
20731
|
-
|
|
20732
|
-
|
|
21075
|
+
getSnap(snapLine) {
|
|
21076
|
+
if (!snapLine || !this.dnd.draggedFigure)
|
|
21077
|
+
return undefined;
|
|
21078
|
+
const figureVisibleRects = snapLine.matchedFigIds
|
|
21079
|
+
.map((id) => this.getVisibleFigures().find((fig) => fig.id === id))
|
|
21080
|
+
.filter(isDefined$1)
|
|
21081
|
+
.map((fig) => {
|
|
21082
|
+
const figOnSCreen = internalFigureToScreen(this.env.model.getters, fig);
|
|
21083
|
+
const container = this.getFigureContainer(fig);
|
|
21084
|
+
return rectIntersection(figOnSCreen, this.getContainerRect(container));
|
|
21085
|
+
})
|
|
21086
|
+
.filter(isDefined$1);
|
|
21087
|
+
const containerRect = rectUnion(this.dnd.draggedFigure, ...figureVisibleRects);
|
|
21088
|
+
return {
|
|
21089
|
+
line: snapLine,
|
|
21090
|
+
containerStyle: this.rectToCss(containerRect),
|
|
21091
|
+
lineStyle: this.getSnapLineStyle(snapLine, containerRect),
|
|
21092
|
+
};
|
|
20733
21093
|
}
|
|
20734
|
-
|
|
20735
|
-
|
|
20736
|
-
|
|
20737
|
-
|
|
20738
|
-
|
|
20739
|
-
|
|
21094
|
+
getSnapLineStyle(snapLine, containerRect) {
|
|
21095
|
+
if (!snapLine)
|
|
21096
|
+
return "";
|
|
21097
|
+
if (["top", "vCenter", "bottom"].includes(snapLine.snappedAxisType)) {
|
|
21098
|
+
return cssPropertiesToCss({
|
|
21099
|
+
top: `${snapLine.position - containerRect.y}px`,
|
|
21100
|
+
left: `0px`,
|
|
21101
|
+
width: `100%`,
|
|
21102
|
+
});
|
|
21103
|
+
}
|
|
21104
|
+
else {
|
|
21105
|
+
return cssPropertiesToCss({
|
|
21106
|
+
top: `0px`,
|
|
21107
|
+
left: `${snapLine.position - containerRect.x}px`,
|
|
21108
|
+
height: `100%`,
|
|
21109
|
+
});
|
|
21110
|
+
}
|
|
20740
21111
|
}
|
|
20741
21112
|
}
|
|
20742
21113
|
FiguresContainer.template = "o-spreadsheet-FiguresContainer";
|
|
@@ -20883,6 +21254,9 @@
|
|
|
20883
21254
|
owl.onMounted(() => {
|
|
20884
21255
|
resizeObserver.observe(this.gridOverlayEl);
|
|
20885
21256
|
});
|
|
21257
|
+
owl.onWillUnmount(() => {
|
|
21258
|
+
resizeObserver.disconnect();
|
|
21259
|
+
});
|
|
20886
21260
|
useTouchMove(this.gridOverlay, this.props.onGridMoved, () => {
|
|
20887
21261
|
const { scrollY } = this.env.model.getters.getActiveSheetDOMScrollInfo();
|
|
20888
21262
|
return scrollY > 0;
|
|
@@ -22303,6 +22677,10 @@
|
|
|
22303
22677
|
}
|
|
22304
22678
|
}
|
|
22305
22679
|
onInput(ev) {
|
|
22680
|
+
// the user meant to paste in the sheet, not open the composer with the pasted content
|
|
22681
|
+
if (!ev.isComposing && ev.inputType === "insertFromPaste") {
|
|
22682
|
+
return;
|
|
22683
|
+
}
|
|
22306
22684
|
if (ev.data) {
|
|
22307
22685
|
// if the user types a character on the grid, it means he wants to start composing the selected cell with that
|
|
22308
22686
|
// character
|
|
@@ -23151,6 +23529,70 @@
|
|
|
23151
23529
|
});
|
|
23152
23530
|
}
|
|
23153
23531
|
|
|
23532
|
+
const XLSX_DATE_FORMAT_REGEX = /^(yy|yyyy|m{1,5}|d{1,4}|h{1,2}|s{1,2}|am\/pm|a\/m|\s|-|\/|\.|:)+$/i;
|
|
23533
|
+
/**
|
|
23534
|
+
* Convert excel format to o_spreadsheet format
|
|
23535
|
+
*
|
|
23536
|
+
* Excel format are defined in openXML §18.8.31
|
|
23537
|
+
*/
|
|
23538
|
+
function convertXlsxFormat(numFmtId, formats, warningManager) {
|
|
23539
|
+
var _a, _b, _c;
|
|
23540
|
+
if (numFmtId === 0) {
|
|
23541
|
+
return undefined;
|
|
23542
|
+
}
|
|
23543
|
+
// Format is either defined in the imported data, or the formatId is defined in openXML §18.8.30
|
|
23544
|
+
let format = XLSX_FORMATS_CONVERSION_MAP[numFmtId] || ((_a = formats.find((f) => f.id === numFmtId)) === null || _a === void 0 ? void 0 : _a.format);
|
|
23545
|
+
if (format) {
|
|
23546
|
+
try {
|
|
23547
|
+
let convertedFormat = format.replace(/(.*?);.*/, "$1"); // only take first part of multi-part format
|
|
23548
|
+
convertedFormat = convertedFormat.replace(/\[(.*)-[A-Z0-9]{3}\]/g, "[$1]"); // remove currency and locale/date system/number system info (ECMA §18.8.31)
|
|
23549
|
+
convertedFormat = convertedFormat.replace(/\[\$\]/g, ""); // remove empty bocks
|
|
23550
|
+
// Quotes in format escape sequences of characters. ATM we only support [$...] blocks to escape characters, and only one of them per format
|
|
23551
|
+
const numberOfQuotes = ((_b = convertedFormat.match(/"/g)) === null || _b === void 0 ? void 0 : _b.length) || 0;
|
|
23552
|
+
const numberOfOpenBrackets = ((_c = convertedFormat.match(/\[/g)) === null || _c === void 0 ? void 0 : _c.length) || 0;
|
|
23553
|
+
if (numberOfQuotes / 2 + numberOfOpenBrackets > 1) {
|
|
23554
|
+
throw new Error("Multiple escaped blocks in format");
|
|
23555
|
+
}
|
|
23556
|
+
convertedFormat = convertedFormat.replace(/"(.*)"/g, "[$$$1]"); // replace '"..."' by '[$...]'
|
|
23557
|
+
convertedFormat = convertedFormat.replace(/_.{1}/g, ""); // _ == ignore width of next char for align purposes. Not supported ATM
|
|
23558
|
+
convertedFormat = convertedFormat.replace(/\*.{1}/g, ""); // * == repeat next character enough to fill the line. Not supported ATM
|
|
23559
|
+
convertedFormat = convertedFormat.replace(/\\ /g, " "); // unescape spaces
|
|
23560
|
+
convertedFormat = convertedFormat.replace(/\\./g, (match) => match[1]); // unescape other characters
|
|
23561
|
+
if (isXlsxDateFormat(convertedFormat)) {
|
|
23562
|
+
convertedFormat = convertDateFormat$1(convertedFormat);
|
|
23563
|
+
}
|
|
23564
|
+
if (isFormatSupported(convertedFormat)) {
|
|
23565
|
+
return convertedFormat;
|
|
23566
|
+
}
|
|
23567
|
+
}
|
|
23568
|
+
catch (e) { }
|
|
23569
|
+
}
|
|
23570
|
+
warningManager.generateNotSupportedWarning(WarningTypes.NumFmtIdNotSupported, format || `nmFmtId ${numFmtId}`);
|
|
23571
|
+
return undefined;
|
|
23572
|
+
}
|
|
23573
|
+
function isFormatSupported(format) {
|
|
23574
|
+
try {
|
|
23575
|
+
formatValue(0, format);
|
|
23576
|
+
return true;
|
|
23577
|
+
}
|
|
23578
|
+
catch (e) {
|
|
23579
|
+
return false;
|
|
23580
|
+
}
|
|
23581
|
+
}
|
|
23582
|
+
function isXlsxDateFormat(format) {
|
|
23583
|
+
return format.match(XLSX_DATE_FORMAT_REGEX) !== null;
|
|
23584
|
+
}
|
|
23585
|
+
function convertDateFormat$1(format) {
|
|
23586
|
+
// Some of these aren't defined neither in the OpenXML spec not the Xlsx extension of OpenXML,
|
|
23587
|
+
// but can still occur and are supported by Excel/Google sheets
|
|
23588
|
+
format = format.toLowerCase();
|
|
23589
|
+
format = format.replace(/mmmmm/g, "mmm");
|
|
23590
|
+
format = format.replace(/am\/pm|a\/m/g, "a");
|
|
23591
|
+
format = format.replace(/hhhh/g, "hh");
|
|
23592
|
+
format = format.replace(/\bh\b/g, "hh");
|
|
23593
|
+
return format;
|
|
23594
|
+
}
|
|
23595
|
+
|
|
23154
23596
|
function convertBorders(data, warningManager) {
|
|
23155
23597
|
const borderArray = data.borders.map((border) => {
|
|
23156
23598
|
addBorderWarnings(border, warningManager);
|
|
@@ -23213,41 +23655,6 @@
|
|
|
23213
23655
|
}
|
|
23214
23656
|
return arrayToObject(formats, 1);
|
|
23215
23657
|
}
|
|
23216
|
-
/**
|
|
23217
|
-
* Convert excel format to o_spreadsheet format
|
|
23218
|
-
*
|
|
23219
|
-
* Excel format are defined in openXML §18.8.31
|
|
23220
|
-
*/
|
|
23221
|
-
function convertXlsxFormat(numFmtId, formats, warningManager) {
|
|
23222
|
-
var _a, _b, _c;
|
|
23223
|
-
if (numFmtId === 0) {
|
|
23224
|
-
return undefined;
|
|
23225
|
-
}
|
|
23226
|
-
// Format is either defined in the imported data, or the formatId is defined in openXML §18.8.30
|
|
23227
|
-
let format = XLSX_FORMATS_CONVERSION_MAP[numFmtId] || ((_a = formats.find((f) => f.id === numFmtId)) === null || _a === void 0 ? void 0 : _a.format);
|
|
23228
|
-
if (format) {
|
|
23229
|
-
try {
|
|
23230
|
-
let convertedFormat = format.replace(/(.*?);.*/, "$1"); // only take first part of multi-part format
|
|
23231
|
-
convertedFormat = convertedFormat.replace(/\[(.*)-[A-Z0-9]{3}\]/g, "[$1]"); // remove currency and locale/date system/number system info (ECMA §18.8.31)
|
|
23232
|
-
convertedFormat = convertedFormat.replace(/\[\$\]/g, ""); // remove empty bocks
|
|
23233
|
-
// Quotes in format escape sequences of characters. ATM we only support [$...] blocks to escape characters, and only one of them per format
|
|
23234
|
-
const numberOfQuotes = ((_b = convertedFormat.match(/"/g)) === null || _b === void 0 ? void 0 : _b.length) || 0;
|
|
23235
|
-
const numberOfOpenBrackets = ((_c = convertedFormat.match(/\[/g)) === null || _c === void 0 ? void 0 : _c.length) || 0;
|
|
23236
|
-
if (numberOfQuotes / 2 + numberOfOpenBrackets > 1) {
|
|
23237
|
-
throw new Error("Multiple escaped blocks in format");
|
|
23238
|
-
}
|
|
23239
|
-
convertedFormat = convertedFormat.replace(/"(.*)"/g, "[$$$1]"); // replace '"..."' by '[$...]'
|
|
23240
|
-
convertedFormat = convertedFormat.replace(/_.{1}/g, ""); // _ == ignore with of next char for align purposes. Not supported ATM
|
|
23241
|
-
convertedFormat = convertedFormat.replace(/\*.{1}/g, ""); // * == repeat next character enough to fill the line. Not supported ATM
|
|
23242
|
-
convertedFormat = convertedFormat.replace(/\\ /g, " "); // unescape spaces
|
|
23243
|
-
formatValue(0, convertedFormat);
|
|
23244
|
-
return convertedFormat;
|
|
23245
|
-
}
|
|
23246
|
-
catch (e) { }
|
|
23247
|
-
}
|
|
23248
|
-
warningManager.generateNotSupportedWarning(WarningTypes.NumFmtIdNotSupported, format || `nmFmtId ${numFmtId}`);
|
|
23249
|
-
return undefined;
|
|
23250
|
-
}
|
|
23251
23658
|
// ---------------------------------------------------------------------------
|
|
23252
23659
|
// Warnings
|
|
23253
23660
|
// ---------------------------------------------------------------------------
|
|
@@ -23802,16 +24209,18 @@
|
|
|
23802
24209
|
};
|
|
23803
24210
|
}
|
|
23804
24211
|
function convertChartData(chartData) {
|
|
23805
|
-
|
|
23806
|
-
const labelRange =
|
|
23807
|
-
|
|
24212
|
+
const dataSetsHaveTitle = chartData.dataSets[0].label !== undefined;
|
|
24213
|
+
const labelRange = chartData.labelRange
|
|
24214
|
+
? convertExcelRangeToSheetXC(chartData.labelRange, dataSetsHaveTitle)
|
|
24215
|
+
: undefined;
|
|
24216
|
+
let dataSets = chartData.dataSets.map((data) => convertExcelRangeToSheetXC(data.range, dataSetsHaveTitle));
|
|
23808
24217
|
// For doughnut charts, in chartJS first dataset = outer dataset, in excel first dataset = inner dataset
|
|
23809
24218
|
if (chartData.type === "pie") {
|
|
23810
24219
|
dataSets.reverse();
|
|
23811
24220
|
}
|
|
23812
24221
|
return {
|
|
23813
24222
|
dataSets,
|
|
23814
|
-
dataSetsHaveTitle
|
|
24223
|
+
dataSetsHaveTitle,
|
|
23815
24224
|
labelRange,
|
|
23816
24225
|
title: chartData.title || "",
|
|
23817
24226
|
type: chartData.type,
|
|
@@ -23822,6 +24231,28 @@
|
|
|
23822
24231
|
aggregated: false,
|
|
23823
24232
|
labelsAsText: false,
|
|
23824
24233
|
};
|
|
24234
|
+
}
|
|
24235
|
+
function convertExcelRangeToSheetXC(range, dataSetsHaveTitle) {
|
|
24236
|
+
let { sheetName, xc } = splitReference(range);
|
|
24237
|
+
if (sheetName) {
|
|
24238
|
+
sheetName = getCanonicalSheetName(sheetName) + "!";
|
|
24239
|
+
}
|
|
24240
|
+
else {
|
|
24241
|
+
sheetName = "";
|
|
24242
|
+
}
|
|
24243
|
+
let zone = toUnboundedZone(xc);
|
|
24244
|
+
if (dataSetsHaveTitle && zone.bottom !== undefined && zone.right !== undefined) {
|
|
24245
|
+
const height = zone.bottom - zone.top + 1;
|
|
24246
|
+
const width = zone.right - zone.left + 1;
|
|
24247
|
+
if (height === 1) {
|
|
24248
|
+
zone = { ...zone, left: zone.left - 1 };
|
|
24249
|
+
}
|
|
24250
|
+
else if (width === 1) {
|
|
24251
|
+
zone = { ...zone, top: zone.top - 1 };
|
|
24252
|
+
}
|
|
24253
|
+
}
|
|
24254
|
+
const dataXC = zoneToXc(zone);
|
|
24255
|
+
return sheetName + dataXC;
|
|
23825
24256
|
}
|
|
23826
24257
|
|
|
23827
24258
|
/**
|
|
@@ -24889,6 +25320,7 @@
|
|
|
24889
25320
|
title: chartTitle,
|
|
24890
25321
|
type: CHART_TYPE_CONVERSION_MAP[chartType],
|
|
24891
25322
|
dataSets: this.extractChartDatasets(this.querySelector(rootChartElement, `c:${chartType}`)),
|
|
25323
|
+
labelRange: this.extractChildTextContent(rootChartElement, "c:ser c:cat c:f"),
|
|
24892
25324
|
backgroundColor: this.extractChildAttr(rootChartElement, "c:chartSpace > c:spPr a:srgbClr", "val", {
|
|
24893
25325
|
default: "ffffff",
|
|
24894
25326
|
}).asString(),
|
|
@@ -24908,7 +25340,7 @@
|
|
|
24908
25340
|
extractChartDatasets(chartElement) {
|
|
24909
25341
|
return this.mapOnElements({ parent: chartElement, query: "c:ser" }, (chartDataElement) => {
|
|
24910
25342
|
return {
|
|
24911
|
-
label: this.extractChildTextContent(chartDataElement, "c:
|
|
25343
|
+
label: this.extractChildTextContent(chartDataElement, "c:tx c:f"),
|
|
24912
25344
|
range: this.extractChildTextContent(chartDataElement, "c:val c:f", { required: true }),
|
|
24913
25345
|
};
|
|
24914
25346
|
});
|
|
@@ -28825,6 +29257,39 @@
|
|
|
28825
29257
|
case "DELETE_FIGURE":
|
|
28826
29258
|
this.removeFigure(cmd.id, cmd.sheetId);
|
|
28827
29259
|
break;
|
|
29260
|
+
case "REMOVE_COLUMNS_ROWS":
|
|
29261
|
+
this.onRowColDelete(cmd.sheetId, cmd.dimension);
|
|
29262
|
+
}
|
|
29263
|
+
}
|
|
29264
|
+
onRowColDelete(sheetId, dimension) {
|
|
29265
|
+
dimension === "ROW" ? this.onRowDeletion(sheetId) : this.onColDeletion(sheetId);
|
|
29266
|
+
}
|
|
29267
|
+
onRowDeletion(sheetId) {
|
|
29268
|
+
const numHeader = this.getters.getNumberRows(sheetId);
|
|
29269
|
+
let gridHeight = 0;
|
|
29270
|
+
for (let i = 0; i < numHeader; i++) {
|
|
29271
|
+
gridHeight += this.getters.getRowSize(sheetId, i);
|
|
29272
|
+
}
|
|
29273
|
+
const figures = this.getters.getFigures(sheetId);
|
|
29274
|
+
for (const figure of figures) {
|
|
29275
|
+
const newY = Math.min(figure.y, gridHeight - figure.height);
|
|
29276
|
+
if (newY !== figure.y) {
|
|
29277
|
+
this.dispatch("UPDATE_FIGURE", { sheetId, id: figure.id, y: newY });
|
|
29278
|
+
}
|
|
29279
|
+
}
|
|
29280
|
+
}
|
|
29281
|
+
onColDeletion(sheetId) {
|
|
29282
|
+
const numHeader = this.getters.getNumberCols(sheetId);
|
|
29283
|
+
let gridWidth = 0;
|
|
29284
|
+
for (let i = 0; i < numHeader; i++) {
|
|
29285
|
+
gridWidth += this.getters.getColSize(sheetId, i);
|
|
29286
|
+
}
|
|
29287
|
+
const figures = this.getters.getFigures(sheetId);
|
|
29288
|
+
for (const figure of figures) {
|
|
29289
|
+
const newX = Math.min(figure.x, gridWidth - figure.width);
|
|
29290
|
+
if (newX !== figure.x) {
|
|
29291
|
+
this.dispatch("UPDATE_FIGURE", { sheetId, id: figure.id, x: newX });
|
|
29292
|
+
}
|
|
28828
29293
|
}
|
|
28829
29294
|
}
|
|
28830
29295
|
updateFigure(sheetId, figure) {
|
|
@@ -30239,6 +30704,7 @@
|
|
|
30239
30704
|
}
|
|
30240
30705
|
else if (range.zone[start] >= min && range.zone[end] <= max) {
|
|
30241
30706
|
changeType = "REMOVE";
|
|
30707
|
+
newRange = range.clone({ ...this.getInvalidRange() });
|
|
30242
30708
|
}
|
|
30243
30709
|
else if (range.zone[start] <= max && range.zone[end] >= max) {
|
|
30244
30710
|
const toRemove = max - range.zone[start] + 1;
|
|
@@ -30304,8 +30770,10 @@
|
|
|
30304
30770
|
return { changeType: "NONE" };
|
|
30305
30771
|
}
|
|
30306
30772
|
const invalidSheetName = this.getters.getSheetName(cmd.sheetId);
|
|
30307
|
-
|
|
30308
|
-
|
|
30773
|
+
range = range.clone({
|
|
30774
|
+
...this.getInvalidRange(),
|
|
30775
|
+
invalidSheetName,
|
|
30776
|
+
});
|
|
30309
30777
|
return { changeType: "REMOVE", range };
|
|
30310
30778
|
}, cmd.sheetId);
|
|
30311
30779
|
break;
|
|
@@ -30492,7 +30960,7 @@
|
|
|
30492
30960
|
sheetName = rangeImpl.invalidSheetName;
|
|
30493
30961
|
}
|
|
30494
30962
|
else {
|
|
30495
|
-
sheetName =
|
|
30963
|
+
sheetName = getCanonicalSheetName(this.getters.getSheetName(rangeImpl.sheetId));
|
|
30496
30964
|
}
|
|
30497
30965
|
}
|
|
30498
30966
|
if (prefixSheet && !sheetName) {
|
|
@@ -30565,6 +31033,15 @@
|
|
|
30565
31033
|
}
|
|
30566
31034
|
return str;
|
|
30567
31035
|
}
|
|
31036
|
+
getInvalidRange() {
|
|
31037
|
+
return {
|
|
31038
|
+
parts: [],
|
|
31039
|
+
prefixSheet: false,
|
|
31040
|
+
zone: { left: -1, top: -1, right: -1, bottom: -1 },
|
|
31041
|
+
sheetId: "",
|
|
31042
|
+
invalidXc: INCORRECT_RANGE_STRING,
|
|
31043
|
+
};
|
|
31044
|
+
}
|
|
30568
31045
|
}
|
|
30569
31046
|
RangeAdapter.getters = [
|
|
30570
31047
|
"getRangeString",
|
|
@@ -31534,9 +32011,7 @@
|
|
|
31534
32011
|
// remove duplicates first to check validity on a reduced
|
|
31535
32012
|
// set of colors, then normalize to HEX and remove duplicates
|
|
31536
32013
|
// again
|
|
31537
|
-
[...new Set([...usedColors, ...this.customColors])]
|
|
31538
|
-
.filter(isColorValid)
|
|
31539
|
-
.map((c) => toHex(c).toLowerCase())),
|
|
32014
|
+
[...new Set([...usedColors, ...this.customColors])].filter(isColorValid).map(toHex)),
|
|
31540
32015
|
]).filter((color) => !COLOR_PICKER_DEFAULTS.includes(color));
|
|
31541
32016
|
}
|
|
31542
32017
|
getColorsFromCells(cells) {
|
|
@@ -31597,7 +32072,7 @@
|
|
|
31597
32072
|
return [...chartsColors];
|
|
31598
32073
|
}
|
|
31599
32074
|
tryToAddColor(color) {
|
|
31600
|
-
const formattedColor = toHex(color)
|
|
32075
|
+
const formattedColor = toHex(color);
|
|
31601
32076
|
if (color && !COLOR_PICKER_DEFAULTS.includes(formattedColor)) {
|
|
31602
32077
|
this.customColors.add(formattedColor);
|
|
31603
32078
|
}
|
|
@@ -32612,8 +33087,8 @@
|
|
|
32612
33087
|
this.getters = getters;
|
|
32613
33088
|
this.sheetId = sheetId;
|
|
32614
33089
|
this.boundaries = boundaries;
|
|
32615
|
-
this.
|
|
32616
|
-
this.
|
|
33090
|
+
this.viewportWidth = sizeInGrid.width;
|
|
33091
|
+
this.viewportHeight = sizeInGrid.height;
|
|
32617
33092
|
this.offsetScrollbarX = offsets.x;
|
|
32618
33093
|
this.offsetScrollbarY = offsets.y;
|
|
32619
33094
|
this.canScrollVertically = options.canScrollVertically;
|
|
@@ -32624,6 +33099,10 @@
|
|
|
32624
33099
|
this.adjustViewportOffsetY();
|
|
32625
33100
|
}
|
|
32626
33101
|
// PUBLIC
|
|
33102
|
+
/** Returns the maximum size (in Pixels) of the viewport relative to its allocated client size
|
|
33103
|
+
* When the viewport grid size is smaller than its client width (resp. height), it will return
|
|
33104
|
+
* the client width (resp. height).
|
|
33105
|
+
*/
|
|
32627
33106
|
getMaxSize() {
|
|
32628
33107
|
const lastCol = this.getters.findLastVisibleColRowIndex(this.sheetId, "COL", {
|
|
32629
33108
|
first: this.boundaries.left,
|
|
@@ -32635,20 +33114,24 @@
|
|
|
32635
33114
|
});
|
|
32636
33115
|
const { end: lastColEnd, size: lastColSize } = this.getters.getColDimensions(this.sheetId, lastCol);
|
|
32637
33116
|
const { end: lastRowEnd, size: lastRowSize } = this.getters.getRowDimensions(this.sheetId, lastRow);
|
|
32638
|
-
const leftColIndex = this.searchHeaderIndex("COL", lastColEnd - this.
|
|
33117
|
+
const leftColIndex = this.searchHeaderIndex("COL", lastColEnd - this.viewportWidth, 0);
|
|
32639
33118
|
const leftColSize = this.getters.getColSize(this.sheetId, leftColIndex);
|
|
32640
|
-
const leftRowIndex = this.searchHeaderIndex("ROW", lastRowEnd - this.
|
|
33119
|
+
const leftRowIndex = this.searchHeaderIndex("ROW", lastRowEnd - this.viewportHeight, 0);
|
|
32641
33120
|
const topRowSize = this.getters.getRowSize(this.sheetId, leftRowIndex);
|
|
32642
|
-
|
|
32643
|
-
|
|
32644
|
-
(
|
|
32645
|
-
|
|
32646
|
-
|
|
32647
|
-
|
|
32648
|
-
|
|
32649
|
-
|
|
32650
|
-
|
|
32651
|
-
|
|
33121
|
+
let width = lastColEnd - this.offsetCorrectionX;
|
|
33122
|
+
if (this.canScrollHorizontally) {
|
|
33123
|
+
width += Math.max(DEFAULT_CELL_WIDTH, // leave some minimal space to let the user know they scrolled all the way
|
|
33124
|
+
Math.min(leftColSize, this.viewportWidth - lastColSize) // Add pixels that allows the snapping at maximum horizontal scroll
|
|
33125
|
+
);
|
|
33126
|
+
width = Math.max(width, this.viewportWidth); // if the viewport grid size is smaller than its client width, return client width
|
|
33127
|
+
}
|
|
33128
|
+
let height = lastRowEnd - this.offsetCorrectionY;
|
|
33129
|
+
if (this.canScrollVertically) {
|
|
33130
|
+
height += Math.max(DEFAULT_CELL_HEIGHT + 5, // leave some space to let the user know they scrolled all the way
|
|
33131
|
+
Math.min(topRowSize, this.viewportHeight - lastRowSize) // Add pixels that allows the snapping at maximum vertical scroll
|
|
33132
|
+
);
|
|
33133
|
+
height = Math.max(height, this.viewportHeight); // if the viewport grid size is smaller than its client height, return client height
|
|
33134
|
+
}
|
|
32652
33135
|
return { width, height };
|
|
32653
33136
|
}
|
|
32654
33137
|
/**
|
|
@@ -32657,7 +33140,7 @@
|
|
|
32657
33140
|
* It returns -1 if no column is found.
|
|
32658
33141
|
*/
|
|
32659
33142
|
getColIndex(x, absolute = false) {
|
|
32660
|
-
if (x < this.offsetCorrectionX || x > this.offsetCorrectionX + this.
|
|
33143
|
+
if (x < this.offsetCorrectionX || x > this.offsetCorrectionX + this.viewportWidth) {
|
|
32661
33144
|
return -1;
|
|
32662
33145
|
}
|
|
32663
33146
|
return this.searchHeaderIndex("COL", x - this.offsetCorrectionX, this.left, absolute);
|
|
@@ -32668,7 +33151,7 @@
|
|
|
32668
33151
|
* It returns -1 if no row is found.
|
|
32669
33152
|
*/
|
|
32670
33153
|
getRowIndex(y, absolute = false) {
|
|
32671
|
-
if (y < this.offsetCorrectionY || y > this.offsetCorrectionY + this.
|
|
33154
|
+
if (y < this.offsetCorrectionY || y > this.offsetCorrectionY + this.viewportHeight) {
|
|
32672
33155
|
return -1;
|
|
32673
33156
|
}
|
|
32674
33157
|
return this.searchHeaderIndex("ROW", y - this.offsetCorrectionY, this.top, absolute);
|
|
@@ -32695,7 +33178,7 @@
|
|
|
32695
33178
|
adjustPositionX(col) {
|
|
32696
33179
|
const sheetId = this.sheetId;
|
|
32697
33180
|
const { start, end } = this.getters.getColDimensions(sheetId, col);
|
|
32698
|
-
while (end > this.offsetX + this.offsetCorrectionX + this.
|
|
33181
|
+
while (end > this.offsetX + this.offsetCorrectionX + this.viewportWidth &&
|
|
32699
33182
|
this.offsetX + this.offsetCorrectionX < start) {
|
|
32700
33183
|
this.offsetX = this.getters.getColDimensions(sheetId, this.left).end - this.offsetCorrectionX;
|
|
32701
33184
|
this.offsetScrollbarX = this.offsetX;
|
|
@@ -32717,7 +33200,7 @@
|
|
|
32717
33200
|
adjustPositionY(row) {
|
|
32718
33201
|
const sheetId = this.sheetId;
|
|
32719
33202
|
while (this.getters.getRowDimensions(sheetId, row).end >
|
|
32720
|
-
this.offsetY + this.
|
|
33203
|
+
this.offsetY + this.viewportHeight + this.offsetCorrectionY &&
|
|
32721
33204
|
this.offsetY + this.offsetCorrectionY < this.getters.getRowDimensions(sheetId, row).start) {
|
|
32722
33205
|
this.offsetY = this.getters.getRowDimensions(sheetId, this.top).end - this.offsetCorrectionY;
|
|
32723
33206
|
this.offsetScrollbarY = this.offsetY;
|
|
@@ -32755,8 +33238,8 @@
|
|
|
32755
33238
|
const x = this.getters.getColRowOffset("COL", this.zone.left, targetZone.left) +
|
|
32756
33239
|
this.offsetCorrectionX;
|
|
32757
33240
|
const y = this.getters.getColRowOffset("ROW", this.zone.top, targetZone.top) + this.offsetCorrectionY;
|
|
32758
|
-
const width = Math.min(this.getters.getColRowOffset("COL", targetZone.left, targetZone.right + 1), this.
|
|
32759
|
-
const height = Math.min(this.getters.getColRowOffset("ROW", targetZone.top, targetZone.bottom + 1), this.
|
|
33241
|
+
const width = Math.min(this.getters.getColRowOffset("COL", targetZone.left, targetZone.right + 1), this.viewportWidth);
|
|
33242
|
+
const height = Math.min(this.getters.getColRowOffset("ROW", targetZone.top, targetZone.bottom + 1), this.viewportHeight);
|
|
32760
33243
|
return {
|
|
32761
33244
|
x,
|
|
32762
33245
|
y,
|
|
@@ -32819,12 +33302,12 @@
|
|
|
32819
33302
|
adjustViewportOffsetX() {
|
|
32820
33303
|
if (this.canScrollHorizontally) {
|
|
32821
33304
|
const { width: viewportWidth } = this.getMaxSize();
|
|
32822
|
-
if (this.
|
|
32823
|
-
this.offsetScrollbarX = Math.max(0, viewportWidth - this.
|
|
33305
|
+
if (this.viewportWidth + this.offsetScrollbarX > viewportWidth) {
|
|
33306
|
+
this.offsetScrollbarX = Math.max(0, viewportWidth - this.viewportWidth);
|
|
32824
33307
|
}
|
|
32825
33308
|
}
|
|
32826
33309
|
this.left = this.getColIndex(this.offsetScrollbarX, true);
|
|
32827
|
-
this.right = this.getColIndex(this.offsetScrollbarX + this.
|
|
33310
|
+
this.right = this.getColIndex(this.offsetScrollbarX + this.viewportWidth, true);
|
|
32828
33311
|
if (this.right === -1) {
|
|
32829
33312
|
this.right = this.boundaries.right;
|
|
32830
33313
|
}
|
|
@@ -32836,12 +33319,12 @@
|
|
|
32836
33319
|
adjustViewportOffsetY() {
|
|
32837
33320
|
if (this.canScrollVertically) {
|
|
32838
33321
|
const { height: paneHeight } = this.getMaxSize();
|
|
32839
|
-
if (this.
|
|
32840
|
-
this.offsetScrollbarY = Math.max(0, paneHeight - this.
|
|
33322
|
+
if (this.viewportHeight + this.offsetScrollbarY > paneHeight) {
|
|
33323
|
+
this.offsetScrollbarY = Math.max(0, paneHeight - this.viewportHeight);
|
|
32841
33324
|
}
|
|
32842
33325
|
}
|
|
32843
33326
|
this.top = this.getRowIndex(this.offsetScrollbarY, true);
|
|
32844
|
-
this.bottom = this.getRowIndex(this.offsetScrollbarY + this.
|
|
33327
|
+
this.bottom = this.getRowIndex(this.offsetScrollbarY + this.viewportWidth, true);
|
|
32845
33328
|
if (this.bottom === -1) {
|
|
32846
33329
|
this.bottom = this.boundaries.bottom;
|
|
32847
33330
|
}
|
|
@@ -32852,7 +33335,7 @@
|
|
|
32852
33335
|
adjustViewportZoneX() {
|
|
32853
33336
|
const sheetId = this.sheetId;
|
|
32854
33337
|
this.left = this.searchHeaderIndex("COL", this.offsetScrollbarX, this.boundaries.left);
|
|
32855
|
-
this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.
|
|
33338
|
+
this.right = Math.min(this.boundaries.right, this.searchHeaderIndex("COL", this.viewportWidth, this.left));
|
|
32856
33339
|
if (this.right === -1) {
|
|
32857
33340
|
this.right = this.getters.getNumberCols(sheetId) - 1;
|
|
32858
33341
|
}
|
|
@@ -32865,7 +33348,7 @@
|
|
|
32865
33348
|
adjustViewportZoneY() {
|
|
32866
33349
|
const sheetId = this.sheetId;
|
|
32867
33350
|
this.top = this.searchHeaderIndex("ROW", this.offsetScrollbarY, this.boundaries.top);
|
|
32868
|
-
this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.
|
|
33351
|
+
this.bottom = Math.min(this.boundaries.bottom, this.searchHeaderIndex("ROW", this.viewportHeight, this.top));
|
|
32869
33352
|
if (this.bottom === -1) {
|
|
32870
33353
|
this.bottom = this.getters.getNumberRows(sheetId) - 1;
|
|
32871
33354
|
}
|
|
@@ -33128,8 +33611,7 @@
|
|
|
33128
33611
|
return [...new Set(viewports.map((v) => range(v.top, v.bottom + 1)).flat())].filter((row) => !this.getters.isHeaderHidden(sheetId, "ROW", row));
|
|
33129
33612
|
}
|
|
33130
33613
|
/**
|
|
33131
|
-
* Return the main viewport maximum size
|
|
33132
|
-
* with some bottom and right padding.
|
|
33614
|
+
* Return the main viewport maximum size relative to the client size.
|
|
33133
33615
|
*/
|
|
33134
33616
|
getMainViewportRect() {
|
|
33135
33617
|
const sheetId = this.getters.getActiveSheetId();
|
|
@@ -33145,8 +33627,8 @@
|
|
|
33145
33627
|
const { width, height } = this.getMainViewportRect();
|
|
33146
33628
|
const viewport = this.getMainInternalViewport(sheetId);
|
|
33147
33629
|
return {
|
|
33148
|
-
maxOffsetX: Math.max(0, width - viewport.
|
|
33149
|
-
maxOffsetY: Math.max(0, height - viewport.
|
|
33630
|
+
maxOffsetX: Math.max(0, width - viewport.viewportWidth + 1),
|
|
33631
|
+
maxOffsetY: Math.max(0, height - viewport.viewportHeight + 1),
|
|
33150
33632
|
};
|
|
33151
33633
|
}
|
|
33152
33634
|
getColRowOffsetInViewport(dimension, referenceIndex, index) {
|
|
@@ -33461,6 +33943,20 @@
|
|
|
33461
33943
|
}
|
|
33462
33944
|
return result;
|
|
33463
33945
|
}
|
|
33946
|
+
isPositionVisible(position) {
|
|
33947
|
+
const { scrollX, scrollY } = this.getters.getActiveSheetScrollInfo();
|
|
33948
|
+
const { x: mainViewportX, y: mainViewportY } = this.getters.getMainViewportCoordinates();
|
|
33949
|
+
const { width, height } = this.getters.getSheetViewDimension();
|
|
33950
|
+
if (position.x >= mainViewportX &&
|
|
33951
|
+
(position.x < mainViewportX + scrollX || position.x > width + scrollX + mainViewportX)) {
|
|
33952
|
+
return false;
|
|
33953
|
+
}
|
|
33954
|
+
if (position.y >= mainViewportY &&
|
|
33955
|
+
(position.y < mainViewportY + scrollY || position.y > height + scrollY + mainViewportY)) {
|
|
33956
|
+
return false;
|
|
33957
|
+
}
|
|
33958
|
+
return true;
|
|
33959
|
+
}
|
|
33464
33960
|
getFrozenSheetViewRatio(sheetId) {
|
|
33465
33961
|
const { xSplit, ySplit } = this.getters.getPaneDivisions(sheetId);
|
|
33466
33962
|
const offsetCorrectionX = this.getters.getColDimensions(sheetId, xSplit).start;
|
|
@@ -33489,6 +33985,7 @@
|
|
|
33489
33985
|
"getSheetViewVisibleCols",
|
|
33490
33986
|
"getSheetViewVisibleRows",
|
|
33491
33987
|
"getFrozenSheetViewRatio",
|
|
33988
|
+
"isPositionVisible",
|
|
33492
33989
|
];
|
|
33493
33990
|
|
|
33494
33991
|
/**
|
|
@@ -35351,7 +35848,7 @@
|
|
|
35351
35848
|
const inputSheetId = this.activeSheet;
|
|
35352
35849
|
const sheetId = this.getters.getActiveSheetId();
|
|
35353
35850
|
const sheetName = this.getters.getSheetName(sheetId);
|
|
35354
|
-
this.add([sheetId === inputSheetId ? xc : `${
|
|
35851
|
+
this.add([sheetId === inputSheetId ? xc : `${getCanonicalSheetName(sheetName)}!${xc}`]);
|
|
35355
35852
|
}
|
|
35356
35853
|
handle(cmd) {
|
|
35357
35854
|
switch (cmd.type) {
|
|
@@ -37598,13 +38095,19 @@
|
|
|
37598
38095
|
*/
|
|
37599
38096
|
paste(target) {
|
|
37600
38097
|
const sheetId = this.getters.getActiveSheetId();
|
|
38098
|
+
const { width, height } = this.copiedFigure;
|
|
38099
|
+
const numCols = this.getters.getNumberCols(sheetId);
|
|
38100
|
+
const numRows = this.getters.getNumberRows(sheetId);
|
|
38101
|
+
const targetX = this.getters.getColDimensions(sheetId, target[0].left).start;
|
|
38102
|
+
const targetY = this.getters.getRowDimensions(sheetId, target[0].top).start;
|
|
38103
|
+
const maxX = this.getters.getColDimensions(sheetId, numCols - 1).end;
|
|
38104
|
+
const maxY = this.getters.getRowDimensions(sheetId, numRows - 1).end;
|
|
37601
38105
|
const position = {
|
|
37602
|
-
x:
|
|
37603
|
-
y:
|
|
38106
|
+
x: maxX < width ? 0 : Math.min(targetX, maxX - width),
|
|
38107
|
+
y: maxY < height ? 0 : Math.min(targetY, maxY - height),
|
|
37604
38108
|
};
|
|
37605
|
-
const size = { height: this.copiedFigure.height, width: this.copiedFigure.width };
|
|
37606
38109
|
const newId = new UuidGenerator().uuidv4();
|
|
37607
|
-
this.copiedFigureContent.paste(sheetId, newId, position,
|
|
38110
|
+
this.copiedFigureContent.paste(sheetId, newId, position, { height, width });
|
|
37608
38111
|
if (this.operation === "CUT") {
|
|
37609
38112
|
this.dispatch("DELETE_FIGURE", {
|
|
37610
38113
|
sheetId: this.copiedFigureContent.sheetId,
|
|
@@ -37970,7 +38473,7 @@
|
|
|
37970
38473
|
return token;
|
|
37971
38474
|
const { xc, sheetName } = splitReference(token.value);
|
|
37972
38475
|
const [left, right] = xc.split(":");
|
|
37973
|
-
const sheetRef = sheetName ? `${
|
|
38476
|
+
const sheetRef = sheetName ? `${getCanonicalSheetName(sheetName)}!` : "";
|
|
37974
38477
|
const updatedLeft = getTokenNextReferenceType(left);
|
|
37975
38478
|
const updatedRight = right ? `:${getTokenNextReferenceType(right)}` : "";
|
|
37976
38479
|
return { ...token, value: sheetRef + updatedLeft + updatedRight };
|
|
@@ -38229,9 +38732,6 @@
|
|
|
38229
38732
|
}
|
|
38230
38733
|
return this.currentContent;
|
|
38231
38734
|
}
|
|
38232
|
-
getEditionSheet() {
|
|
38233
|
-
return this.sheetId;
|
|
38234
|
-
}
|
|
38235
38735
|
getComposerSelection() {
|
|
38236
38736
|
return {
|
|
38237
38737
|
start: this.selectionStart,
|
|
@@ -38515,8 +39015,8 @@
|
|
|
38515
39015
|
getZoneReference(zone, fixedParts = [{ colFixed: false, rowFixed: false }]) {
|
|
38516
39016
|
const sheetId = this.getters.getActiveSheetId();
|
|
38517
39017
|
let selectedXc = this.getters.zoneToXC(sheetId, zone, fixedParts);
|
|
38518
|
-
if (this.getters.
|
|
38519
|
-
const sheetName =
|
|
39018
|
+
if (this.getters.getCurrentEditedCell().sheetId !== this.getters.getActiveSheetId()) {
|
|
39019
|
+
const sheetName = getCanonicalSheetName(this.getters.getSheetName(this.getters.getActiveSheetId()));
|
|
38520
39020
|
selectedXc = `${sheetName}!${selectedXc}`;
|
|
38521
39021
|
}
|
|
38522
39022
|
return selectedXc;
|
|
@@ -38530,7 +39030,7 @@
|
|
|
38530
39030
|
_fixedParts.pop();
|
|
38531
39031
|
}
|
|
38532
39032
|
const newRange = range.clone({ parts: _fixedParts });
|
|
38533
|
-
return this.getters.getSelectionRangeString(newRange, this.getters.
|
|
39033
|
+
return this.getters.getSelectionRangeString(newRange, this.getters.getCurrentEditedCell().sheetId);
|
|
38534
39034
|
}
|
|
38535
39035
|
/**
|
|
38536
39036
|
* Replace the current selection by a new text.
|
|
@@ -38563,7 +39063,7 @@
|
|
|
38563
39063
|
if (!this.currentContent.startsWith("=") || this.mode === "inactive") {
|
|
38564
39064
|
return;
|
|
38565
39065
|
}
|
|
38566
|
-
const editionSheetId = this.getters.
|
|
39066
|
+
const editionSheetId = this.getters.getCurrentEditedCell().sheetId;
|
|
38567
39067
|
const XCs = this.getReferencedRanges().map((range) => this.getters.getRangeString(range, editionSheetId));
|
|
38568
39068
|
const colorsToKeep = {};
|
|
38569
39069
|
for (const xc of XCs) {
|
|
@@ -38592,7 +39092,7 @@
|
|
|
38592
39092
|
if (!this.currentContent.startsWith("=") || this.mode === "inactive") {
|
|
38593
39093
|
return [];
|
|
38594
39094
|
}
|
|
38595
|
-
const editionSheetId = this.getters.
|
|
39095
|
+
const editionSheetId = this.getters.getCurrentEditedCell().sheetId;
|
|
38596
39096
|
const rangeColor = (rangeString) => {
|
|
38597
39097
|
const colorIndex = this.colorIndexByRange[rangeString];
|
|
38598
39098
|
return colors$1[colorIndex % colors$1.length];
|
|
@@ -38610,7 +39110,7 @@
|
|
|
38610
39110
|
* Return ranges currently referenced in the composer
|
|
38611
39111
|
*/
|
|
38612
39112
|
getReferencedRanges() {
|
|
38613
|
-
const editionSheetId = this.getters.
|
|
39113
|
+
const editionSheetId = this.getters.getCurrentEditedCell().sheetId;
|
|
38614
39114
|
return this.currentTokens
|
|
38615
39115
|
.filter((token) => token.type === "REFERENCE")
|
|
38616
39116
|
.map((token) => this.getters.getRangeFromSheetXC(editionSheetId, token.value));
|
|
@@ -38669,7 +39169,6 @@
|
|
|
38669
39169
|
"isSelectingForComposer",
|
|
38670
39170
|
"showSelectionIndicator",
|
|
38671
39171
|
"getCurrentContent",
|
|
38672
|
-
"getEditionSheet",
|
|
38673
39172
|
"getComposerSelection",
|
|
38674
39173
|
"getCurrentTokens",
|
|
38675
39174
|
"getTokenAtCursor",
|
|
@@ -39992,10 +40491,6 @@
|
|
|
39992
40491
|
.o-bottom-bar-arrows {
|
|
39993
40492
|
.o-bottom-bar-arrow {
|
|
39994
40493
|
cursor: pointer;
|
|
39995
|
-
&.o-disabled {
|
|
39996
|
-
opacity: 0.4;
|
|
39997
|
-
cursor: default;
|
|
39998
|
-
}
|
|
39999
40494
|
&:hover:not([class*="o-disabled"]) {
|
|
40000
40495
|
.o-icon {
|
|
40001
40496
|
opacity: 0.9;
|
|
@@ -40588,6 +41083,11 @@
|
|
|
40588
41083
|
margin-top: -1px;
|
|
40589
41084
|
border: 1px solid;
|
|
40590
41085
|
z-index: ${ComponentsImportance.TopBarComposer};
|
|
41086
|
+
|
|
41087
|
+
.o-composer:empty:not(:focus)::before {
|
|
41088
|
+
/* svg free of use from https://uxwing.com/formula-fx-icon/ */
|
|
41089
|
+
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -10 121.8 142.9' width='24' height='24' focusable='false'%3E%3Cpath d='m28 34-4 5v2h10l-6 40c-4 22-6 28-7 30-2 2-3 3-5 3-3 0-7-2-9-4H4c-2 2-4 4-4 7s4 6 8 6 9-2 15-8c8-7 13-17 18-39l7-35 13-1 3-6H49c4-23 7-27 11-27 2 0 5 2 8 6h4c1-1 4-4 4-7 0-2-3-6-9-6-5 0-13 4-20 10-6 7-9 14-11 24h-8zm41 16c4-5 7-7 8-7s2 1 5 9l3 12c-7 11-12 17-16 17l-3-1-2-1c-3 0-6 3-6 7s3 7 7 7c6 0 12-6 22-23l3 10c3 9 6 13 10 13 5 0 11-4 18-15l-3-4c-4 6-7 8-8 8-2 0-4-3-6-10l-5-15 8-10 6-4 3 1 3 2c2 0 6-3 6-7s-2-7-6-7c-6 0-11 5-21 20l-2-6c-3-9-5-14-9-14-5 0-12 6-18 15l3 3z' fill='%23BDBDBD' /%3E%3C/svg%3E");
|
|
41090
|
+
}
|
|
40591
41091
|
}
|
|
40592
41092
|
`;
|
|
40593
41093
|
class TopBarComposer extends owl.Component {
|
|
@@ -40828,11 +41328,6 @@
|
|
|
40828
41328
|
margin: 0 6px;
|
|
40829
41329
|
}
|
|
40830
41330
|
|
|
40831
|
-
.o-disabled {
|
|
40832
|
-
opacity: 0.6;
|
|
40833
|
-
cursor: default;
|
|
40834
|
-
}
|
|
40835
|
-
|
|
40836
41331
|
.o-dropdown {
|
|
40837
41332
|
position: relative;
|
|
40838
41333
|
display: flex;
|
|
@@ -40994,6 +41489,7 @@
|
|
|
40994
41489
|
this.state.menuState.parentMenu = menu;
|
|
40995
41490
|
this.isSelectingMenu = true;
|
|
40996
41491
|
this.openedEl = ev.target;
|
|
41492
|
+
this.env.model.dispatch("STOP_EDITION");
|
|
40997
41493
|
}
|
|
40998
41494
|
closeMenus() {
|
|
40999
41495
|
this.state.activeTool = "";
|
|
@@ -41206,10 +41702,12 @@
|
|
|
41206
41702
|
button {
|
|
41207
41703
|
color: #333;
|
|
41208
41704
|
}
|
|
41209
|
-
|
|
41210
|
-
|
|
41211
|
-
|
|
41705
|
+
.o-disabled {
|
|
41706
|
+
opacity: 0.4;
|
|
41707
|
+
pointer: default;
|
|
41708
|
+
pointer-events: none;
|
|
41212
41709
|
}
|
|
41710
|
+
|
|
41213
41711
|
&,
|
|
41214
41712
|
*,
|
|
41215
41713
|
*:before,
|
|
@@ -41367,8 +41865,10 @@
|
|
|
41367
41865
|
this.sidePanel.isOpen = true;
|
|
41368
41866
|
}
|
|
41369
41867
|
closeSidePanel() {
|
|
41868
|
+
var _a, _b;
|
|
41370
41869
|
this.sidePanel.isOpen = false;
|
|
41371
41870
|
this.focusGrid();
|
|
41871
|
+
(_b = (_a = this.sidePanel.panelProps) === null || _a === void 0 ? void 0 : _a.onCloseSidePanel) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
41372
41872
|
}
|
|
41373
41873
|
toggleSidePanel(panel, panelProps) {
|
|
41374
41874
|
if (this.sidePanel.isOpen && panel === this.sidePanel.component) {
|
|
@@ -43807,7 +44307,7 @@
|
|
|
43807
44307
|
if (currentPosition <= position && position < currentPosition + header.size) {
|
|
43808
44308
|
return {
|
|
43809
44309
|
index: parseInt(headerIndex),
|
|
43810
|
-
offset: convertDotValueToEMU(position - currentPosition +
|
|
44310
|
+
offset: convertDotValueToEMU(position - currentPosition + FIGURE_BORDER_WIDTH),
|
|
43811
44311
|
};
|
|
43812
44312
|
}
|
|
43813
44313
|
else {
|
|
@@ -43816,7 +44316,7 @@
|
|
|
43816
44316
|
}
|
|
43817
44317
|
return {
|
|
43818
44318
|
index: headers.length - 1,
|
|
43819
|
-
offset: convertDotValueToEMU(position - currentPosition +
|
|
44319
|
+
offset: convertDotValueToEMU(position - currentPosition + FIGURE_BORDER_WIDTH),
|
|
43820
44320
|
};
|
|
43821
44321
|
}
|
|
43822
44322
|
function createChartDrawing(figure, sheet, chartRelId) {
|
|
@@ -44576,6 +45076,13 @@
|
|
|
44576
45076
|
* Internal status of the model. Important for command handling coordination
|
|
44577
45077
|
*/
|
|
44578
45078
|
this.status = 0 /* Status.Ready */;
|
|
45079
|
+
/**
|
|
45080
|
+
* Check if a command can be dispatched, and returns a DispatchResult object with the possible
|
|
45081
|
+
* reasons the dispatch failed.
|
|
45082
|
+
*/
|
|
45083
|
+
this.canDispatch = (type, payload) => {
|
|
45084
|
+
return this.checkDispatchAllowed({ ...payload, type });
|
|
45085
|
+
};
|
|
44579
45086
|
/**
|
|
44580
45087
|
* The dispatch method is the only entry point to manipulate data in the model.
|
|
44581
45088
|
* This is through this method that commands are dispatched most of the time
|
|
@@ -44719,7 +45226,10 @@
|
|
|
44719
45226
|
owl.markRaw(this);
|
|
44720
45227
|
}
|
|
44721
45228
|
get handlers() {
|
|
44722
|
-
return [
|
|
45229
|
+
return [...this.coreHandlers, ...this.allUIPlugins, this.history];
|
|
45230
|
+
}
|
|
45231
|
+
get coreHandlers() {
|
|
45232
|
+
return [this.range, ...this.corePlugins];
|
|
44723
45233
|
}
|
|
44724
45234
|
get allUIPlugins() {
|
|
44725
45235
|
return [...this.statefulUIPlugins, ...this.coreViewsPlugins, ...this.featurePlugins];
|
|
@@ -44847,6 +45357,16 @@
|
|
|
44847
45357
|
* Check if the given command is allowed by all the plugins and the history.
|
|
44848
45358
|
*/
|
|
44849
45359
|
checkDispatchAllowed(command) {
|
|
45360
|
+
if (isCoreCommand(command)) {
|
|
45361
|
+
return this.checkDispatchAllowedCoreCommand(command);
|
|
45362
|
+
}
|
|
45363
|
+
return this.checkDispatchAllowedLocalCommand(command);
|
|
45364
|
+
}
|
|
45365
|
+
checkDispatchAllowedCoreCommand(command) {
|
|
45366
|
+
const results = this.coreHandlers.map((handler) => handler.allowDispatch(command));
|
|
45367
|
+
return new DispatchResult(results.flat());
|
|
45368
|
+
}
|
|
45369
|
+
checkDispatchAllowedLocalCommand(command) {
|
|
44850
45370
|
const results = this.handlers.map((handler) => handler.allowDispatch(command));
|
|
44851
45371
|
return new DispatchResult(results.flat());
|
|
44852
45372
|
}
|
|
@@ -45077,9 +45597,9 @@
|
|
|
45077
45597
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
45078
45598
|
|
|
45079
45599
|
|
|
45080
|
-
__info__.version = '16.3.0-alpha.
|
|
45081
|
-
__info__.date = '2023-
|
|
45082
|
-
__info__.hash = '
|
|
45600
|
+
__info__.version = '16.3.0-alpha.3';
|
|
45601
|
+
__info__.date = '2023-04-13T08:30:41.165Z';
|
|
45602
|
+
__info__.hash = '573e679';
|
|
45083
45603
|
|
|
45084
45604
|
|
|
45085
45605
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|