committed by
Nicolás Hatcher Andrés
parent
42d557d485
commit
8a54f45d75
@@ -436,3 +436,47 @@ fn false_removes_value() {
|
|||||||
let style = model.get_cell_style(0, 1, 1).unwrap();
|
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||||
assert!(!style.font.b);
|
assert!(!style.font.b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cell_clear_formatting() {
|
||||||
|
let mut model = UserModel::new_empty("model", "en", "UTC").unwrap();
|
||||||
|
let range = Area {
|
||||||
|
sheet: 0,
|
||||||
|
row: 1,
|
||||||
|
column: 1,
|
||||||
|
width: 1,
|
||||||
|
height: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// bold
|
||||||
|
model.update_range_style(&range, "font.b", "true").unwrap();
|
||||||
|
model
|
||||||
|
.update_range_style(&range, "alignment.horizontal", "centerContinuous")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||||
|
assert!(style.font.b);
|
||||||
|
assert_eq!(
|
||||||
|
style.alignment.unwrap().horizontal,
|
||||||
|
HorizontalAlignment::CenterContinuous
|
||||||
|
);
|
||||||
|
|
||||||
|
model.range_clear_all(&range).unwrap();
|
||||||
|
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||||
|
assert!(!style.font.b);
|
||||||
|
assert_eq!(style.alignment, None);
|
||||||
|
|
||||||
|
model.undo().unwrap();
|
||||||
|
|
||||||
|
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||||
|
assert!(style.font.b);
|
||||||
|
assert_eq!(
|
||||||
|
style.alignment.unwrap().horizontal,
|
||||||
|
HorizontalAlignment::CenterContinuous
|
||||||
|
);
|
||||||
|
model.redo().unwrap();
|
||||||
|
|
||||||
|
let style = model.get_cell_style(0, 1, 1).unwrap();
|
||||||
|
assert!(!style.font.b);
|
||||||
|
assert_eq!(style.alignment, None);
|
||||||
|
}
|
||||||
|
|||||||
@@ -566,6 +566,34 @@ impl UserModel {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes cells styles and formatting, but keeps the content
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
/// * [UserModel::range_clear_all]
|
||||||
|
/// * [UserModel::range_clear_contents]
|
||||||
|
pub fn range_clear_formatting(&mut self, range: &Area) -> Result<(), String> {
|
||||||
|
let sheet = range.sheet;
|
||||||
|
let mut diff_list = Vec::new();
|
||||||
|
for row in range.row..range.row + range.height {
|
||||||
|
for column in range.column..range.column + range.width {
|
||||||
|
let old_style = self.model.get_style_for_cell(sheet, row, column)?;
|
||||||
|
// We can always assume that style with style_index 0 exists and it is the default
|
||||||
|
self.model
|
||||||
|
.workbook
|
||||||
|
.worksheet_mut(sheet)?
|
||||||
|
.set_cell_style(row, column, 0)?;
|
||||||
|
diff_list.push(Diff::CellClearFormatting {
|
||||||
|
sheet,
|
||||||
|
row,
|
||||||
|
column,
|
||||||
|
old_style: Box::new(old_style),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.push_diff_list(diff_list);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Inserts a row
|
/// Inserts a row
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
@@ -2006,6 +2034,15 @@ impl UserModel {
|
|||||||
old_value,
|
old_value,
|
||||||
new_value: _,
|
new_value: _,
|
||||||
} => self.model.set_sheet_state(*index, old_value.clone())?,
|
} => self.model.set_sheet_state(*index, old_value.clone())?,
|
||||||
|
Diff::CellClearFormatting {
|
||||||
|
sheet,
|
||||||
|
row,
|
||||||
|
column,
|
||||||
|
old_style,
|
||||||
|
} => {
|
||||||
|
self.model
|
||||||
|
.set_cell_style(*sheet, *row, *column, old_style)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if needs_evaluation {
|
if needs_evaluation {
|
||||||
@@ -2160,6 +2197,17 @@ impl UserModel {
|
|||||||
old_value: _,
|
old_value: _,
|
||||||
new_value,
|
new_value,
|
||||||
} => self.model.set_sheet_state(*index, new_value.clone())?,
|
} => self.model.set_sheet_state(*index, new_value.clone())?,
|
||||||
|
Diff::CellClearFormatting {
|
||||||
|
sheet,
|
||||||
|
row,
|
||||||
|
column,
|
||||||
|
old_style: _,
|
||||||
|
} => {
|
||||||
|
self.model
|
||||||
|
.workbook
|
||||||
|
.worksheet_mut(*sheet)?
|
||||||
|
.set_cell_style(*row, *column, 0)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,12 @@ pub(crate) enum Diff {
|
|||||||
old_value: Box<Option<Cell>>,
|
old_value: Box<Option<Cell>>,
|
||||||
old_style: Box<Style>,
|
old_style: Box<Style>,
|
||||||
},
|
},
|
||||||
|
CellClearFormatting {
|
||||||
|
sheet: u32,
|
||||||
|
row: i32,
|
||||||
|
column: i32,
|
||||||
|
old_style: Box<Style>,
|
||||||
|
},
|
||||||
SetCellStyle {
|
SetCellStyle {
|
||||||
sheet: u32,
|
sheet: u32,
|
||||||
row: i32,
|
row: i32,
|
||||||
|
|||||||
@@ -161,6 +161,28 @@ impl UserModel {
|
|||||||
self.model.range_clear_contents(&range).map_err(to_js_error)
|
self.model.range_clear_contents(&range).map_err(to_js_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[napi(js_name = "rangeClearFormatting")]
|
||||||
|
pub fn range_clear_formatting(
|
||||||
|
&mut self,
|
||||||
|
sheet: u32,
|
||||||
|
start_row: i32,
|
||||||
|
start_column: i32,
|
||||||
|
end_row: i32,
|
||||||
|
end_column: i32,
|
||||||
|
) -> Result<()> {
|
||||||
|
let range = Area {
|
||||||
|
sheet,
|
||||||
|
row: start_row,
|
||||||
|
column: start_column,
|
||||||
|
width: end_column - start_column + 1,
|
||||||
|
height: end_row - start_row + 1,
|
||||||
|
};
|
||||||
|
self
|
||||||
|
.model
|
||||||
|
.range_clear_formatting(&range)
|
||||||
|
.map_err(to_js_error)
|
||||||
|
}
|
||||||
|
|
||||||
#[napi(js_name = "insertRow")]
|
#[napi(js_name = "insertRow")]
|
||||||
pub fn insert_row(&mut self, sheet: u32, row: i32) -> Result<()> {
|
pub fn insert_row(&mut self, sheet: u32, row: i32) -> Result<()> {
|
||||||
self.model.insert_row(sheet, row).map_err(to_js_error)
|
self.model.insert_row(sheet, row).map_err(to_js_error)
|
||||||
|
|||||||
@@ -174,6 +174,27 @@ impl Model {
|
|||||||
self.model.range_clear_contents(&range).map_err(to_js_error)
|
self.model.range_clear_contents(&range).map_err(to_js_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = "rangeClearFormatting")]
|
||||||
|
pub fn range_clear_formatting(
|
||||||
|
&mut self,
|
||||||
|
sheet: u32,
|
||||||
|
start_row: i32,
|
||||||
|
start_column: i32,
|
||||||
|
end_row: i32,
|
||||||
|
end_column: i32,
|
||||||
|
) -> Result<(), JsError> {
|
||||||
|
let range = Area {
|
||||||
|
sheet,
|
||||||
|
row: start_row,
|
||||||
|
column: start_column,
|
||||||
|
width: end_column - start_column + 1,
|
||||||
|
height: end_row - start_row + 1,
|
||||||
|
};
|
||||||
|
self.model
|
||||||
|
.range_clear_formatting(&range)
|
||||||
|
.map_err(to_js_error)
|
||||||
|
}
|
||||||
|
|
||||||
#[wasm_bindgen(js_name = "insertRow")]
|
#[wasm_bindgen(js_name = "insertRow")]
|
||||||
pub fn insert_row(&mut self, sheet: u32, row: i32) -> Result<(), JsError> {
|
pub fn insert_row(&mut self, sheet: u32, row: i32) -> Result<(), JsError> {
|
||||||
self.model.insert_row(sheet, row).map_err(to_js_error)
|
self.model.insert_row(sheet, row).map_err(to_js_error)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import {
|
|||||||
PaintRoller,
|
PaintRoller,
|
||||||
Percent,
|
Percent,
|
||||||
Redo2,
|
Redo2,
|
||||||
|
RemoveFormatting,
|
||||||
Strikethrough,
|
Strikethrough,
|
||||||
Tags,
|
Tags,
|
||||||
Type,
|
Type,
|
||||||
@@ -65,6 +66,7 @@ type ToolbarProperties = {
|
|||||||
onFillColorPicked: (hex: string) => void;
|
onFillColorPicked: (hex: string) => void;
|
||||||
onNumberFormatPicked: (numberFmt: string) => void;
|
onNumberFormatPicked: (numberFmt: string) => void;
|
||||||
onBorderChanged: (border: BorderOptions) => void;
|
onBorderChanged: (border: BorderOptions) => void;
|
||||||
|
onClearFormatting: () => void;
|
||||||
fillColor: string;
|
fillColor: string;
|
||||||
fontColor: string;
|
fontColor: string;
|
||||||
bold: boolean;
|
bold: boolean;
|
||||||
@@ -360,6 +362,19 @@ function Toolbar(properties: ToolbarProperties) {
|
|||||||
<Tags />
|
<Tags />
|
||||||
</StyledButton>
|
</StyledButton>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
<StyledButton
|
||||||
|
type="button"
|
||||||
|
$pressed={false}
|
||||||
|
disabled={!canEdit}
|
||||||
|
onClick={() => {
|
||||||
|
properties.onClearFormatting();
|
||||||
|
}}
|
||||||
|
title={t("toolbar.clear_formatting")}
|
||||||
|
>
|
||||||
|
<RemoveFormatting />
|
||||||
|
</StyledButton>
|
||||||
|
|
||||||
<ColorPicker
|
<ColorPicker
|
||||||
color={properties.fontColor}
|
color={properties.fontColor}
|
||||||
onChange={(color): void => {
|
onChange={(color): void => {
|
||||||
|
|||||||
@@ -527,6 +527,20 @@ const Workbook = (props: { model: Model; workbookState: WorkbookState }) => {
|
|||||||
onTextColorPicked={onTextColorPicked}
|
onTextColorPicked={onTextColorPicked}
|
||||||
onFillColorPicked={onFillColorPicked}
|
onFillColorPicked={onFillColorPicked}
|
||||||
onNumberFormatPicked={onNumberFormatPicked}
|
onNumberFormatPicked={onNumberFormatPicked}
|
||||||
|
onClearFormatting={() => {
|
||||||
|
const {
|
||||||
|
sheet,
|
||||||
|
range: [rowStart, columnStart, rowEnd, columnEnd],
|
||||||
|
} = model.getSelectedView();
|
||||||
|
model.rangeClearFormatting(
|
||||||
|
sheet,
|
||||||
|
rowStart,
|
||||||
|
columnStart,
|
||||||
|
rowEnd,
|
||||||
|
columnEnd,
|
||||||
|
);
|
||||||
|
setRedrawId((id) => id + 1);
|
||||||
|
}}
|
||||||
onBorderChanged={(border: BorderOptions): void => {
|
onBorderChanged={(border: BorderOptions): void => {
|
||||||
const {
|
const {
|
||||||
sheet,
|
sheet,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"redo": "Redo",
|
"redo": "Redo",
|
||||||
"undo": "Undo",
|
"undo": "Undo",
|
||||||
"copy_styles": "Copy styles",
|
"copy_styles": "Copy styles",
|
||||||
|
"clear_formatting": "Clear formatting",
|
||||||
"euro": "Format as Euro",
|
"euro": "Format as Euro",
|
||||||
"percentage": "Format as Percentage",
|
"percentage": "Format as Percentage",
|
||||||
"bold": "Bold",
|
"bold": "Bold",
|
||||||
|
|||||||
Reference in New Issue
Block a user