UPDATE[API rename]: set_column_with => set_columns_with

Similarly set_row_height => set_rows_height
This commit is contained in:
Nicolás Hatcher
2025-02-16 09:06:18 +01:00
committed by Nicolás Hatcher Andrés
parent dd9ca4224d
commit 4095b7db6e
13 changed files with 134 additions and 74 deletions

View File

@@ -9,7 +9,7 @@ fn add_undo_redo() {
model.set_user_input(1, 1, 1, "=1 + 1").unwrap(); model.set_user_input(1, 1, 1, "=1 + 1").unwrap();
model.set_user_input(1, 1, 2, "=A1*3").unwrap(); model.set_user_input(1, 1, 2, "=A1*3").unwrap();
model model
.set_column_width(1, 5, 5.0 * DEFAULT_COLUMN_WIDTH) .set_columns_width(1, 5, 5, 5.0 * DEFAULT_COLUMN_WIDTH)
.unwrap(); .unwrap();
model.new_sheet().unwrap(); model.new_sheet().unwrap();
model.set_user_input(2, 1, 1, "=Sheet2!B1").unwrap(); model.set_user_input(2, 1, 1, "=Sheet2!B1").unwrap();

View File

@@ -39,7 +39,7 @@ fn column_width() {
// change the column width and check it does not affect the style // change the column width and check it does not affect the style
model model
.set_column_width(0, 7, DEFAULT_COLUMN_WIDTH * 2.0) .set_columns_width(0, 7, 7, DEFAULT_COLUMN_WIDTH * 2.0)
.unwrap(); .unwrap();
let style = model.get_cell_style(0, 109, 7).unwrap(); let style = model.get_cell_style(0, 109, 7).unwrap();
assert!(style.font.b); assert!(style.font.b);
@@ -241,7 +241,7 @@ fn width_column_undo() {
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap(); let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
model model
.set_column_width(0, 7, DEFAULT_COLUMN_WIDTH * 2.0) .set_columns_width(0, 7, 7, DEFAULT_COLUMN_WIDTH * 2.0)
.unwrap(); .unwrap();
let column_g_range = Area { let column_g_range = Area {
@@ -267,7 +267,7 @@ fn width_column_undo() {
fn height_row_undo() { fn height_row_undo() {
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap(); let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
model model
.set_row_height(0, 10, DEFAULT_ROW_HEIGHT * 2.0) .set_rows_height(0, 10, 10, DEFAULT_ROW_HEIGHT * 2.0)
.unwrap(); .unwrap();
let row_10_range = Area { let row_10_range = Area {
@@ -446,7 +446,7 @@ fn column_style_then_width() {
.update_range_style(&column_g_range, "fill.bg_color", "#555666") .update_range_style(&column_g_range, "fill.bg_color", "#555666")
.unwrap(); .unwrap();
model model
.set_column_width(0, 7, DEFAULT_COLUMN_WIDTH * 2.0) .set_columns_width(0, 7, 7, DEFAULT_COLUMN_WIDTH * 2.0)
.unwrap(); .unwrap();
// Check column width worked: // Check column width worked:

View File

@@ -105,7 +105,7 @@ fn delete_column_formatting() {
fn column_width() { fn column_width() {
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap(); let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
model model
.set_column_width(0, 7, DEFAULT_COLUMN_WIDTH * 2.0) .set_columns_width(0, 7, 7, DEFAULT_COLUMN_WIDTH * 2.0)
.unwrap(); .unwrap();
let column_g_range = Area { let column_g_range = Area {
@@ -145,7 +145,7 @@ fn column_width() {
fn column_row_style_undo() { fn column_row_style_undo() {
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap(); let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
model model
.set_column_width(0, 7, DEFAULT_COLUMN_WIDTH * 2.0) .set_columns_width(0, 7, 7, DEFAULT_COLUMN_WIDTH * 2.0)
.unwrap(); .unwrap();
let column_g_range = Area { let column_g_range = Area {
@@ -228,7 +228,7 @@ fn column_row_row_height_undo() {
.unwrap(); .unwrap();
model model
.set_row_height(0, 3, DEFAULT_ROW_HEIGHT * 2.0) .set_rows_height(0, 3, 3, DEFAULT_ROW_HEIGHT * 2.0)
.unwrap(); .unwrap();
model model

View File

@@ -10,7 +10,7 @@ use crate::{
fn send_queue() { fn send_queue() {
let mut model1 = UserModel::from_model(new_empty_model()); let mut model1 = UserModel::from_model(new_empty_model());
let width = model1.get_column_width(0, 3).unwrap() * 3.0; let width = model1.get_column_width(0, 3).unwrap() * 3.0;
model1.set_column_width(0, 3, width).unwrap(); model1.set_columns_width(0, 3, 3, width).unwrap();
model1.set_user_input(0, 1, 2, "Hello IronCalc!").unwrap(); model1.set_user_input(0, 1, 2, "Hello IronCalc!").unwrap();
let send_queue = model1.flush_send_queue(); let send_queue = model1.flush_send_queue();
@@ -34,7 +34,7 @@ fn apply_external_diffs_wrong_str() {
fn queue_undo_redo() { fn queue_undo_redo() {
let mut model1 = UserModel::from_model(new_empty_model()); let mut model1 = UserModel::from_model(new_empty_model());
let width = model1.get_column_width(0, 3).unwrap() * 3.0; let width = model1.get_column_width(0, 3).unwrap() * 3.0;
model1.set_column_width(0, 3, width).unwrap(); model1.set_columns_width(0, 3, 3, width).unwrap();
model1.set_user_input(0, 1, 2, "Hello IronCalc!").unwrap(); model1.set_user_input(0, 1, 2, "Hello IronCalc!").unwrap();
assert!(model1.undo().is_ok()); assert!(model1.undo().is_ok());
assert!(model1.redo().is_ok()); assert!(model1.redo().is_ok());
@@ -57,8 +57,8 @@ fn queue_undo_redo_multiple() {
// do a bunch of things // do a bunch of things
model1.set_frozen_columns_count(0, 5).unwrap(); model1.set_frozen_columns_count(0, 5).unwrap();
model1.set_frozen_rows_count(0, 6).unwrap(); model1.set_frozen_rows_count(0, 6).unwrap();
model1.set_column_width(0, 7, 300.0).unwrap(); model1.set_columns_width(0, 7, 7, 300.0).unwrap();
model1.set_row_height(0, 23, 123.0).unwrap(); model1.set_rows_height(0, 23, 23, 123.0).unwrap();
model1.set_user_input(0, 55, 55, "=42+8").unwrap(); model1.set_user_input(0, 55, 55, "=42+8").unwrap();
for row in 1..5 { for row in 1..5 {

View File

@@ -59,7 +59,7 @@ fn insert_remove_rows() {
// Insert some data in row 5 (and change the style) // Insert some data in row 5 (and change the style)
assert!(model.set_user_input(0, 5, 1, "100$").is_ok()); assert!(model.set_user_input(0, 5, 1, "100$").is_ok());
// Change the height of the column // Change the height of the column
assert!(model.set_row_height(0, 5, 3.0 * height).is_ok()); assert!(model.set_rows_height(0, 5, 5, 3.0 * height).is_ok());
// remove the row // remove the row
assert!(model.delete_row(0, 5).is_ok()); assert!(model.delete_row(0, 5).is_ok());
@@ -95,7 +95,7 @@ fn insert_remove_columns() {
// Insert some data in row 5 (and change the style) in E1 // Insert some data in row 5 (and change the style) in E1
assert!(model.set_user_input(0, 1, 5, "100$").is_ok()); assert!(model.set_user_input(0, 1, 5, "100$").is_ok());
// Change the width of the column // Change the width of the column
assert!(model.set_column_width(0, 5, 3.0 * column_width).is_ok()); assert!(model.set_columns_width(0, 5, 5, 3.0 * column_width).is_ok());
assert_eq!(model.get_column_width(0, 5).unwrap(), 3.0 * column_width); assert_eq!(model.get_column_width(0, 5).unwrap(), 3.0 * column_width);
// remove the column // remove the column

View File

@@ -59,7 +59,7 @@ fn simple_delete_column() {
model.set_user_input(0, 1, 5, "3").unwrap(); model.set_user_input(0, 1, 5, "3").unwrap();
model.set_user_input(0, 2, 5, "=E1*2").unwrap(); model.set_user_input(0, 2, 5, "=E1*2").unwrap();
model model
.set_column_width(0, 5, DEFAULT_COLUMN_WIDTH * 3.0) .set_columns_width(0, 5, 5, DEFAULT_COLUMN_WIDTH * 3.0)
.unwrap(); .unwrap();
model.delete_column(0, 5).unwrap(); model.delete_column(0, 5).unwrap();
@@ -116,7 +116,7 @@ fn simple_delete_row() {
model.set_user_input(0, 15, 6, "=D15*2").unwrap(); model.set_user_input(0, 15, 6, "=D15*2").unwrap();
model model
.set_row_height(0, 15, DEFAULT_ROW_HEIGHT * 3.0) .set_rows_height(0, 15, 15, DEFAULT_ROW_HEIGHT * 3.0)
.unwrap(); .unwrap();
model.delete_row(0, 15).unwrap(); model.delete_row(0, 15).unwrap();

View File

@@ -6,7 +6,7 @@ use crate::{test::util::new_empty_model, UserModel};
fn basic() { fn basic() {
let mut model1 = UserModel::from_model(new_empty_model()); let mut model1 = UserModel::from_model(new_empty_model());
let width = model1.get_column_width(0, 3).unwrap() * 3.0; let width = model1.get_column_width(0, 3).unwrap() * 3.0;
model1.set_column_width(0, 3, width).unwrap(); model1.set_columns_width(0, 3, 3, width).unwrap();
model1.set_user_input(0, 1, 2, "Hello IronCalc!").unwrap(); model1.set_user_input(0, 1, 2, "Hello IronCalc!").unwrap();
let model_bytes = model1.to_bytes(); let model_bytes = model1.to_bytes();

View File

@@ -939,34 +939,56 @@ impl UserModel {
Ok(()) Ok(())
} }
/// Sets the width of a column /// Sets the width of a group of columns in a single diff list
/// ///
/// See also: /// See also:
/// * [Model::set_column_width] /// * [Model::set_column_width]
pub fn set_column_width(&mut self, sheet: u32, column: i32, width: f64) -> Result<(), String> { pub fn set_columns_width(
&mut self,
sheet: u32,
column_start: i32,
column_end: i32,
width: f64,
) -> Result<(), String> {
let mut diff_list = Vec::new();
for column in column_start..=column_end {
let old_value = self.model.get_column_width(sheet, column)?; let old_value = self.model.get_column_width(sheet, column)?;
self.push_diff_list(vec![Diff::SetColumnWidth { diff_list.push(Diff::SetColumnWidth {
sheet, sheet,
column, column,
new_value: width, new_value: width,
old_value, old_value,
}]); });
self.model.set_column_width(sheet, column, width) self.model.set_column_width(sheet, column, width)?;
}
self.push_diff_list(diff_list);
Ok(())
} }
/// Sets the height of a row /// Sets the height of a range of rows in a single diff list
/// ///
/// See also: /// See also:
/// * [Model::set_row_height] /// * [Model::set_row_height]
pub fn set_row_height(&mut self, sheet: u32, row: i32, height: f64) -> Result<(), String> { pub fn set_rows_height(
&mut self,
sheet: u32,
row_start: i32,
row_end: i32,
height: f64,
) -> Result<(), String> {
let mut diff_list = Vec::new();
for row in row_start..=row_end {
let old_value = self.model.get_row_height(sheet, row)?; let old_value = self.model.get_row_height(sheet, row)?;
self.push_diff_list(vec![Diff::SetRowHeight { diff_list.push(Diff::SetRowHeight {
sheet, sheet,
row, row,
new_value: height, new_value: height,
old_value, old_value,
}]); });
self.model.set_row_height(sheet, row, height) self.model.set_row_height(sheet, row, height)?;
}
self.push_diff_list(diff_list);
Ok(())
} }
/// Gets the height of a row /// Gets the height of a row

View File

@@ -203,19 +203,31 @@ impl UserModel {
self.model.delete_column(sheet, column).map_err(to_js_error) self.model.delete_column(sheet, column).map_err(to_js_error)
} }
#[napi(js_name = "setRowHeight")] #[napi(js_name = "setRowsHeight")]
pub fn set_row_height(&mut self, sheet: u32, row: i32, height: f64) -> Result<()> { pub fn set_rows_height(
&mut self,
sheet: u32,
row_start: i32,
row_end: i32,
height: f64,
) -> Result<()> {
self self
.model .model
.set_row_height(sheet, row, height) .set_rows_height(sheet, row_start, row_end, height)
.map_err(to_js_error) .map_err(to_js_error)
} }
#[napi(js_name = "setColumnWidth")] #[napi(js_name = "setColumnsWidth")]
pub fn set_column_width(&mut self, sheet: u32, column: i32, width: f64) -> Result<()> { pub fn set_columns_width(
&mut self,
sheet: u32,
column_start: i32,
column_end: i32,
width: f64,
) -> Result<()> {
self self
.model .model
.set_column_width(sheet, column, width) .set_columns_width(sheet, column_start, column_end, width)
.map_err(to_js_error) .map_err(to_js_error)
} }

View File

@@ -215,17 +215,29 @@ impl Model {
self.model.delete_column(sheet, column).map_err(to_js_error) self.model.delete_column(sheet, column).map_err(to_js_error)
} }
#[wasm_bindgen(js_name = "setRowHeight")] #[wasm_bindgen(js_name = "setRowsHeight")]
pub fn set_row_height(&mut self, sheet: u32, row: i32, height: f64) -> Result<(), JsError> { pub fn set_rows_height(
&mut self,
sheet: u32,
row_start: i32,
row_end: i32,
height: f64,
) -> Result<(), JsError> {
self.model self.model
.set_row_height(sheet, row, height) .set_rows_height(sheet, row_start, row_end, height)
.map_err(to_js_error) .map_err(to_js_error)
} }
#[wasm_bindgen(js_name = "setColumnWidth")] #[wasm_bindgen(js_name = "setColumnsWidth")]
pub fn set_column_width(&mut self, sheet: u32, column: i32, width: f64) -> Result<(), JsError> { pub fn set_columns_width(
&mut self,
sheet: u32,
column_start: i32,
column_end: i32,
width: f64,
) -> Result<(), JsError> {
self.model self.model
.set_column_width(sheet, column, width) .set_columns_width(sheet, column_start, column_end, width)
.map_err(to_js_error) .map_err(to_js_error)
} }
@@ -292,6 +304,28 @@ impl Model {
.map_err(to_js_error) .map_err(to_js_error)
} }
// This two are only used when we want to compute the automatic width of a column or height of a row
#[wasm_bindgen(js_name = "getRowsWithData")]
pub fn get_rows_with_data(&self, sheet: u32, column: i32) -> Result<Vec<i32>, JsError> {
let sheet_data = &self.model.get_model().workbook.worksheet(sheet).map_err(to_js_error)?.sheet_data;
Ok(sheet_data
.iter()
.filter(|(_, data)| data.contains_key(&column))
.map(|(row, _)| *row)
.collect())
}
#[wasm_bindgen(js_name = "getColumnsWithData")]
pub fn get_columns_with_data(&self, sheet: u32, row: i32) -> Result<Vec<i32>, JsError> {
Ok(self.model.get_model()
.workbook
.worksheet(sheet).map_err(to_js_error)?
.sheet_data
.get(&row)
.map(|row_data| row_data.keys().copied().collect())
.unwrap_or_default())
}
#[wasm_bindgen(js_name = "updateRangeStyle")] #[wasm_bindgen(js_name = "updateRangeStyle")]
pub fn update_range_style( pub fn update_range_style(
&mut self, &mut self,

View File

@@ -20,7 +20,7 @@ test('Row height', () => {
let model = new Model('Workbook1', 'en', 'UTC'); let model = new Model('Workbook1', 'en', 'UTC');
assert.strictEqual(model.getRowHeight(0, 3), DEFAULT_ROW_HEIGHT); assert.strictEqual(model.getRowHeight(0, 3), DEFAULT_ROW_HEIGHT);
model.setRowHeight(0, 3, 32); model.setRowsHeight(0, 3, 3, 32);
assert.strictEqual(model.getRowHeight(0, 3), 32); assert.strictEqual(model.getRowHeight(0, 3), 32);
model.undo(); model.undo();
@@ -29,7 +29,7 @@ test('Row height', () => {
model.redo(); model.redo();
assert.strictEqual(model.getRowHeight(0, 3), 32); assert.strictEqual(model.getRowHeight(0, 3), 32);
model.setRowHeight(0, 3, 320); model.setRowsHeight(0, 3, 3, 320);
assert.strictEqual(model.getRowHeight(0, 3), 320); assert.strictEqual(model.getRowHeight(0, 3), 320);
}); });
@@ -96,7 +96,7 @@ test("Add sheets", (t) => {
test("invalid sheet index throws an exception", () => { test("invalid sheet index throws an exception", () => {
const model = new Model('Workbook1', 'en', 'UTC'); const model = new Model('Workbook1', 'en', 'UTC');
assert.throws(() => { assert.throws(() => {
model.setRowHeight(1, 1, 100); model.setRowsHeight(1, 1, 1, 100);
}, { }, {
name: 'Error', name: 'Error',
message: 'Invalid sheet index', message: 'Invalid sheet index',
@@ -106,7 +106,7 @@ test("invalid sheet index throws an exception", () => {
test("invalid column throws an exception", () => { test("invalid column throws an exception", () => {
const model = new Model('Workbook1', 'en', 'UTC'); const model = new Model('Workbook1', 'en', 'UTC');
assert.throws(() => { assert.throws(() => {
model.setRowHeight(0, -1, 100); model.setRowsHeight(0, -1, 0, 100);
}, { }, {
name: 'Error', name: 'Error',
message: "Row number '-1' is not valid.", message: "Row number '-1' is not valid.",
@@ -115,7 +115,7 @@ test("invalid column throws an exception", () => {
test("floating column numbers get truncated", () => { test("floating column numbers get truncated", () => {
const model = new Model('Workbook1', 'en', 'UTC'); const model = new Model('Workbook1', 'en', 'UTC');
model.setRowHeight(0.8, 5.2, 100.5); model.setRowsHeight(0.8, 5.2, 5.5, 100.5);
assert.strictEqual(model.getRowHeight(0.11, 5.99), 100.5); assert.strictEqual(model.getRowHeight(0.11, 5.99), 100.5);
assert.strictEqual(model.getRowHeight(0, 5), 100.5); assert.strictEqual(model.getRowHeight(0, 5), 100.5);

View File

@@ -112,19 +112,14 @@ function Worksheet(props: {
if (width < 0) { if (width < 0) {
return; return;
} }
// if the column is one of the selected columns, we need to update the width of all selected columns
// FIXME: This is a bit of a hack, we should probably have a separate function for this
const { range } = model.getSelectedView(); const { range } = model.getSelectedView();
let columnStart = column;
let columnEnd = column;
if (column >= range[1] && column <= range[3]) { if (column >= range[1] && column <= range[3]) {
model.setColumnWidth(sheet, column, width); columnStart = Math.min(range[1], column, range[3]);
for (let i = range[1]; i <= range[3]; i++) { columnEnd = Math.max(range[1], column, range[3]);
if (i !== column) {
model.setColumnWidth(sheet, i, width);
}
}
} else {
model.setColumnWidth(sheet, column, width);
} }
model.setColumnsWidth(sheet, columnStart, columnEnd, width);
worksheetCanvas.current?.renderSheet(); worksheetCanvas.current?.renderSheet();
}, },
onRowHeightChanges(sheet, row, height) { onRowHeightChanges(sheet, row, height) {
@@ -132,16 +127,13 @@ function Worksheet(props: {
return; return;
} }
const { range } = model.getSelectedView(); const { range } = model.getSelectedView();
let rowStart = row;
let rowEnd = row;
if (row >= range[0] && row <= range[2]) { if (row >= range[0] && row <= range[2]) {
model.setRowHeight(sheet, row, height); rowStart = Math.min(range[0], row, range[2]);
for (let i = range[0]; i <= range[2]; i++) { rowEnd = Math.max(range[0], row, range[2]);
if (i !== row) {
model.setRowHeight(sheet, i, height);
}
}
} else {
model.setRowHeight(sheet, row, height);
} }
model.setRowsHeight(sheet, rowStart, rowEnd, height);
worksheetCanvas.current?.renderSheet(); worksheetCanvas.current?.renderSheet();
}, },
}); });
@@ -362,7 +354,7 @@ function Worksheet(props: {
Math.min(rowStart, extendedArea.rowStart), Math.min(rowStart, extendedArea.rowStart),
Math.min(columnStart, extendedArea.columnStart), Math.min(columnStart, extendedArea.columnStart),
Math.max(rowStart + height - 1, extendedArea.rowEnd), Math.max(rowStart + height - 1, extendedArea.rowEnd),
Math.max(columnStart + width - 1, extendedArea.columnEnd) Math.max(columnStart + width - 1, extendedArea.columnEnd),
); );
workbookState.clearExtendToArea(); workbookState.clearExtendToArea();
canvas.renderSheet(); canvas.renderSheet();

View File

@@ -508,5 +508,5 @@ fn test_user_model() {
fs::remove_file(temp_file_name).unwrap(); fs::remove_file(temp_file_name).unwrap();
// we can still use the model afterwards // we can still use the model afterwards
model.set_row_height(0, 1, 100.0).unwrap(); model.set_rows_height(0, 1, 1, 100.0).unwrap();
} }