FIX: Numerous fixes

This also fix old issues:

* Top border is only the top border of the selected area
  (and not he top border of each cell in the area)
* Same for bottom, left and right borders

Factored out all the border related issues to a new file
This commit is contained in:
Nicolás Hatcher
2025-02-12 16:12:11 +01:00
committed by Nicolás Hatcher Andrés
parent 23ab5dfef2
commit 6ee450709a
5 changed files with 590 additions and 361 deletions

View File

@@ -520,14 +520,19 @@ fn borders_top() {
.unwrap(); .unwrap();
model.set_area_with_border(range, &border_area).unwrap(); model.set_area_with_border(range, &border_area).unwrap();
check_borders(&model); check_borders(&model);
for row in 5..9 { for row in 4..9 {
for column in 6..9 { for column in 6..9 {
let style = model.get_cell_style(0, row, column).unwrap(); let style = model.get_cell_style(0, row, column).unwrap();
let border_item = BorderItem { let border_item = BorderItem {
style: BorderStyle::Thin, style: BorderStyle::Thin,
color: Some("#FF5566".to_string()), color: Some("#FF5566".to_string()),
}; };
let bottom = if row == 8 { let bottom = if row != 4 {
None
} else {
Some(border_item.clone())
};
let top = if row != 5 {
None None
} else { } else {
Some(border_item.clone()) Some(border_item.clone())
@@ -537,7 +542,7 @@ fn borders_top() {
diagonal_down: false, diagonal_down: false,
left: None, left: None,
right: None, right: None,
top: Some(border_item.clone()), top,
bottom, bottom,
diagonal: None, diagonal: None,
}; };
@@ -647,12 +652,12 @@ fn borders_right() {
style: BorderStyle::Thin, style: BorderStyle::Thin,
color: Some("#FF5566".to_string()), color: Some("#FF5566".to_string()),
}; };
let left = if column == 6 { let left = if column != 9 {
None None
} else { } else {
Some(border_item.clone()) Some(border_item.clone())
}; };
let right = if column == 9 { let right = if column != 8 {
None None
} else { } else {
Some(border_item.clone()) Some(border_item.clone())
@@ -705,7 +710,7 @@ fn borders_bottom() {
color: Some("#FF5566".to_string()), color: Some("#FF5566".to_string()),
}; };
// The top will also have a value for all but the first one // The top will also have a value for all but the first one
let top = if row == 5 { let bottom = if row != 8 {
None None
} else { } else {
Some(border_item.clone()) Some(border_item.clone())
@@ -715,8 +720,8 @@ fn borders_bottom() {
diagonal_down: false, diagonal_down: false,
left: None, left: None,
right: None, right: None,
top, top: None,
bottom: Some(border_item.clone()), bottom,
diagonal: None, diagonal: None,
}; };
assert_eq!(style.border, expected_border); assert_eq!(style.border, expected_border);
@@ -751,18 +756,13 @@ fn borders_left() {
model.set_area_with_border(range, &border_area).unwrap(); model.set_area_with_border(range, &border_area).unwrap();
for row in 5..9 { for row in 5..9 {
for column in 5..9 { for column in 6..9 {
let style = model.get_cell_style(0, row, column).unwrap(); let style = model.get_cell_style(0, row, column).unwrap();
let border_item = BorderItem { let border_item = BorderItem {
style: BorderStyle::Thin, style: BorderStyle::Thin,
color: Some("#FF5566".to_string()), color: Some("#FF5566".to_string()),
}; };
let left = if column == 5 { let left = if column != 6 {
None
} else {
Some(border_item.clone())
};
let right = if column == 8 {
None None
} else { } else {
Some(border_item.clone()) Some(border_item.clone())
@@ -771,13 +771,29 @@ fn borders_left() {
diagonal_up: false, diagonal_up: false,
diagonal_down: false, diagonal_down: false,
left, left,
right, right: None,
top: None, top: None,
bottom: None, bottom: None,
diagonal: None, diagonal: None,
}; };
assert_eq!(style.border, expected_border); assert_eq!(style.border, expected_border);
} }
// Column 5 has a border to the right, of course:
let style = model.get_cell_style(0, row, 5).unwrap();
let border_item = BorderItem {
style: BorderStyle::Thin,
color: Some("#FF5566".to_string()),
};
let expected_border = Border {
diagonal_up: false,
diagonal_down: false,
left: None,
right: Some(border_item.clone()),
top: None,
bottom: None,
diagonal: None,
};
assert_eq!(style.border, expected_border);
} }
} }
@@ -1018,10 +1034,7 @@ fn border_top() {
style: BorderStyle::Thin, style: BorderStyle::Thin,
color: Some("#F2F2F2".to_string()), color: Some("#F2F2F2".to_string()),
}; };
assert_eq!( assert_eq!(model._get_cell_actual_border("C4").top, Some(border_item));
model._get_cell_actual_border("C4").bottom,
Some(border_item)
);
model.undo().unwrap(); model.undo().unwrap();

View File

@@ -0,0 +1,540 @@
use crate::{
constants::{LAST_COLUMN, LAST_ROW},
expressions::types::Area,
types::Style,
};
use super::{
border_utils::is_max_border, common::BorderType, history::Diff, BorderArea, UserModel,
};
impl UserModel {
fn get_new_border_value(
&self,
border_area: &BorderArea,
old_value: &Option<Style>,
row: i32,
column: i32,
range: (i32, i32, i32, i32),
) -> Result<Style, String> {
let mut new_value = match old_value {
Some(value) => value.clone(),
None => Default::default(),
};
let (first_row, first_column, last_row, last_column) = range;
match border_area.r#type {
BorderType::All => {
new_value.border.top = Some(border_area.item.clone());
new_value.border.right = Some(border_area.item.clone());
new_value.border.bottom = Some(border_area.item.clone());
new_value.border.left = Some(border_area.item.clone());
}
BorderType::Inner => {
if row != first_row {
new_value.border.top = Some(border_area.item.clone());
}
if row != last_row {
new_value.border.bottom = Some(border_area.item.clone());
}
if column != first_column {
new_value.border.left = Some(border_area.item.clone());
}
if column != last_column {
new_value.border.right = Some(border_area.item.clone());
}
}
BorderType::Outer => {
if row == first_row {
new_value.border.top = Some(border_area.item.clone());
}
if row == last_row {
new_value.border.bottom = Some(border_area.item.clone());
}
if column == first_column {
new_value.border.left = Some(border_area.item.clone());
}
if column == last_column {
new_value.border.right = Some(border_area.item.clone());
}
}
BorderType::Top => {
if row == first_row {
new_value.border.top = Some(border_area.item.clone());
}
}
BorderType::Right => {
if column == last_column {
new_value.border.right = Some(border_area.item.clone());
}
}
BorderType::Bottom => {
if row == last_row {
new_value.border.bottom = Some(border_area.item.clone());
}
}
BorderType::Left => {
if column == first_column {
new_value.border.left = Some(border_area.item.clone());
}
}
BorderType::CenterH => {
if row != first_row {
new_value.border.top = Some(border_area.item.clone());
}
if row != last_row {
new_value.border.bottom = Some(border_area.item.clone());
}
}
BorderType::CenterV => {
if column != first_column {
new_value.border.left = Some(border_area.item.clone());
}
if column != last_column {
new_value.border.right = Some(border_area.item.clone());
}
}
BorderType::None => {
new_value.border.top = None;
new_value.border.right = None;
new_value.border.bottom = None;
new_value.border.left = None;
}
}
Ok(new_value)
}
fn set_rows_with_border(
&mut self,
sheet: u32,
first_row: i32,
last_row: i32,
border_area: &BorderArea,
) -> Result<(), String> {
let mut diff_list = Vec::new();
for row in first_row..=last_row {
let old_value = self.model.get_row_style(sheet, row)?;
let mut new_value = match &old_value {
Some(value) => value.clone(),
None => Default::default(),
};
match border_area.r#type {
BorderType::All => {
new_value.border.top = Some(border_area.item.clone());
new_value.border.right = Some(border_area.item.clone());
new_value.border.bottom = Some(border_area.item.clone());
new_value.border.left = Some(border_area.item.clone());
}
BorderType::Inner => {
if row != first_row {
new_value.border.top = Some(border_area.item.clone());
}
if row != last_row {
new_value.border.bottom = Some(border_area.item.clone());
}
}
BorderType::Outer => {
if row == first_row {
new_value.border.top = Some(border_area.item.clone());
}
if row == last_row {
new_value.border.bottom = Some(border_area.item.clone());
}
}
BorderType::Top => {
if row == first_row {
new_value.border.top = Some(border_area.item.clone());
}
}
BorderType::Right => {
// noop
}
BorderType::Bottom => {
if row == last_row {
new_value.border.bottom = Some(border_area.item.clone());
}
}
BorderType::Left => {
// noop
}
BorderType::CenterH => {
if row != first_row {
new_value.border.top = Some(border_area.item.clone());
}
if row != last_row {
new_value.border.bottom = Some(border_area.item.clone());
}
}
BorderType::CenterV => {
new_value.border.left = Some(border_area.item.clone());
new_value.border.right = Some(border_area.item.clone());
}
BorderType::None => {
new_value.border.top = None;
new_value.border.right = None;
new_value.border.bottom = None;
new_value.border.left = None;
}
}
// We need to go throw each non-empty cell in the row
let columns: Vec<i32> = self
.model
.workbook
.worksheet(sheet)?
.sheet_data
.get(&row)
.map(|row_data| row_data.keys().copied().collect())
.unwrap_or_default();
for column in columns {
let old_value = self.model.get_cell_style_or_none(sheet, row, column)?;
let new_value = self.get_new_border_value(
border_area,
&old_value,
row,
column,
(first_row, 1, last_row, LAST_COLUMN),
)?;
self.model.set_cell_style(sheet, row, column, &new_value)?;
diff_list.push(Diff::SetCellStyle {
sheet,
row,
column,
old_value: Box::new(old_value),
new_value: Box::new(new_value),
});
}
self.model.set_row_style(sheet, row, &new_value)?;
diff_list.push(Diff::SetRowStyle {
sheet,
row,
old_value: Box::new(old_value),
new_value: Box::new(new_value),
});
}
self.push_diff_list(diff_list);
Ok(())
}
fn set_columns_with_border(
&mut self,
sheet: u32,
first_column: i32,
last_column: i32,
border_area: &BorderArea,
) -> Result<(), String> {
let mut diff_list = Vec::new();
// We need all the rows in the column to update the style
// NB: This is too much, this is all the rows that have values
let data_rows: Vec<i32> = self
.model
.workbook
.worksheet(sheet)?
.sheet_data
.keys()
.copied()
.collect();
let styled_rows = &self.model.workbook.worksheet(sheet)?.rows.clone();
for column in first_column..=last_column {
let old_value = self.model.get_column_style(sheet, column)?;
let mut new_value = match &old_value {
Some(value) => value.clone(),
None => Default::default(),
};
match border_area.r#type {
BorderType::All => {
new_value.border.top = Some(border_area.item.clone());
new_value.border.right = Some(border_area.item.clone());
new_value.border.bottom = Some(border_area.item.clone());
new_value.border.left = Some(border_area.item.clone());
}
BorderType::Inner => {
if column != first_column {
new_value.border.left = Some(border_area.item.clone());
}
if column != last_column {
new_value.border.right = Some(border_area.item.clone());
}
}
BorderType::Outer => {
if column == first_column {
new_value.border.left = Some(border_area.item.clone());
}
if column == last_column {
new_value.border.right = Some(border_area.item.clone());
}
}
BorderType::Top => {
// noop
}
BorderType::Right => {
if column == last_column {
new_value.border.right = Some(border_area.item.clone());
}
}
BorderType::Bottom => {
// noop
}
BorderType::Left => {
if column == first_column {
new_value.border.left = Some(border_area.item.clone());
}
}
BorderType::CenterH => {
new_value.border.top = Some(border_area.item.clone());
new_value.border.bottom = Some(border_area.item.clone());
}
BorderType::CenterV => {
if column != first_column {
new_value.border.left = Some(border_area.item.clone());
}
if column != last_column {
new_value.border.right = Some(border_area.item.clone());
}
}
BorderType::None => {
new_value.border.top = None;
new_value.border.right = None;
new_value.border.bottom = None;
new_value.border.left = None;
}
}
// We need to go through each non empty cell in the column
for &row in &data_rows {
if let Some(data_row) = self.model.workbook.worksheet(sheet)?.sheet_data.get(&row) {
if data_row.get(&column).is_some() {
let old_value = self.model.get_cell_style_or_none(sheet, row, column)?;
let new_value = self.get_new_border_value(
border_area,
&old_value,
row,
column,
(1, first_column, LAST_ROW, last_column),
)?;
self.model.set_cell_style(sheet, row, column, &new_value)?;
diff_list.push(Diff::SetCellStyle {
sheet,
row,
column,
old_value: Box::new(old_value),
new_value: Box::new(new_value),
});
}
}
}
// We also need to overwrite those that have a row style
for row_s in styled_rows.iter() {
let row = row_s.r;
let old_value = self.model.get_cell_style_or_none(sheet, row, column)?;
let new_value = self.get_new_border_value(
border_area,
&old_value,
row,
column,
(1, first_column, LAST_ROW, last_column),
)?;
self.model.set_cell_style(sheet, row, column, &new_value)?;
diff_list.push(Diff::SetCellStyle {
sheet,
row,
column,
old_value: Box::new(old_value),
new_value: Box::new(new_value),
});
}
self.model.set_column_style(sheet, column, &new_value)?;
diff_list.push(Diff::SetColumnStyle {
sheet,
column,
old_value: Box::new(old_value),
new_value: Box::new(new_value),
});
}
self.push_diff_list(diff_list);
Ok(())
}
/// Sets the border in an area of cells.
/// When setting the border we need to check if the adjacent cells have a "heavier" border
/// If that is the case we need to change it
pub fn set_area_with_border(
&mut self,
range: &Area,
border_area: &BorderArea,
) -> Result<(), String> {
let sheet = range.sheet;
let first_row = range.row;
let first_column = range.column;
let last_row = first_row + range.height - 1;
let last_column = first_column + range.width - 1;
if first_row == 1 && last_row == LAST_ROW {
// full columns
self.set_columns_with_border(sheet, first_column, last_column, border_area)?;
return Ok(());
}
if first_column == 1 && last_column == LAST_COLUMN {
// full rows
self.set_rows_with_border(sheet, first_row, last_row, border_area)?;
return Ok(());
}
let mut diff_list = Vec::new();
for row in first_row..=last_row {
for column in first_column..=last_column {
let old_value = self.model.get_cell_style_or_none(sheet, row, column)?;
let new_value = self.get_new_border_value(
border_area,
&old_value,
row,
column,
(first_row, first_column, last_row, last_column),
)?;
self.model.set_cell_style(sheet, row, column, &new_value)?;
diff_list.push(Diff::SetCellStyle {
sheet,
row,
column,
old_value: Box::new(old_value),
new_value: Box::new(new_value),
});
}
}
// bottom of the cells above the first
if first_row > 1
&& [
BorderType::All,
BorderType::None,
BorderType::Outer,
BorderType::Top,
]
.contains(&border_area.r#type)
{
let row = first_row - 1;
for column in first_column..=last_column {
let old_value = self.model.get_style_for_cell(sheet, row, column)?;
if is_max_border(Some(&border_area.item), old_value.border.bottom.as_ref()) {
let mut style = old_value.clone();
if border_area.r#type == BorderType::None {
style.border.bottom = None;
} else {
style.border.bottom = Some(border_area.item.clone());
}
self.model.set_cell_style(sheet, row, column, &style)?;
diff_list.push(Diff::SetCellStyle {
sheet,
row,
column,
old_value: Box::new(Some(old_value)),
new_value: Box::new(style),
});
}
}
}
// Cells to the right
if last_column < LAST_COLUMN
&& [
BorderType::All,
BorderType::None,
BorderType::Outer,
BorderType::Right,
]
.contains(&border_area.r#type)
{
let column = last_column + 1;
for row in first_row..=last_row {
let old_value = self.model.get_style_for_cell(sheet, row, column)?;
// If the border in the adjacent cell is "heavier" we change it
if is_max_border(Some(&border_area.item), old_value.border.left.as_ref()) {
let mut style = old_value.clone();
if border_area.r#type == BorderType::None {
style.border.left = None;
} else {
style.border.left = Some(border_area.item.clone());
}
self.model.set_cell_style(sheet, row, column, &style)?;
diff_list.push(Diff::SetCellStyle {
sheet,
row,
column,
old_value: Box::new(Some(old_value)),
new_value: Box::new(style),
});
}
}
}
// Cells bellow
if last_row < LAST_ROW
&& [
BorderType::All,
BorderType::None,
BorderType::Outer,
BorderType::Bottom,
]
.contains(&border_area.r#type)
{
let row = last_row + 1;
for column in first_column..=last_column {
let old_value = self.model.get_style_for_cell(sheet, row, column)?;
if is_max_border(Some(&border_area.item), old_value.border.top.as_ref()) {
let mut style = old_value.clone();
if border_area.r#type == BorderType::None {
style.border.top = None;
} else {
style.border.top = Some(border_area.item.clone());
}
self.model.set_cell_style(sheet, row, column, &style)?;
diff_list.push(Diff::SetCellStyle {
sheet,
row,
column,
old_value: Box::new(Some(old_value)),
new_value: Box::new(style),
});
}
}
}
// Cells to the left
if first_column > 1
&& [
BorderType::All,
BorderType::None,
BorderType::Outer,
BorderType::Left,
]
.contains(&border_area.r#type)
{
let column = first_column - 1;
for row in first_row..=last_row {
let old_value = self.model.get_style_for_cell(sheet, row, column)?;
if is_max_border(Some(&border_area.item), old_value.border.right.as_ref()) {
let mut style = old_value.clone();
if border_area.r#type == BorderType::None {
style.border.right = None;
} else {
style.border.right = Some(border_area.item.clone());
}
self.model.set_cell_style(sheet, row, column, &style)?;
diff_list.push(Diff::SetCellStyle {
sheet,
row,
column,
old_value: Box::new(Some(old_value)),
new_value: Box::new(style),
});
}
}
}
self.push_diff_list(diff_list);
Ok(())
}
}

View File

@@ -60,8 +60,8 @@ pub enum BorderType {
/// This is the struct for a border area /// This is the struct for a border area
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct BorderArea { pub struct BorderArea {
item: BorderItem, pub(crate) item: BorderItem,
r#type: BorderType, pub(crate) r#type: BorderType,
} }
fn boolean(value: &str) -> Result<bool, String> { fn boolean(value: &str) -> Result<bool, String> {
@@ -652,18 +652,19 @@ impl UserModel {
let mut diff_list = Vec::new(); let mut diff_list = Vec::new();
for row in range.row..range.row + range.height { for row in range.row..range.row + range.height {
for column in range.column..range.column + range.width { for column in range.column..range.column + range.width {
let old_style = self.model.get_style_for_cell(sheet, row, column)?; if let Some(old_style) = self.model.get_cell_style_or_none(sheet, row, column)? {
// We can always assume that style with style_index 0 exists and it is the default // We can always assume that style with style_index 0 exists and it is the default
self.model self.model
.workbook .workbook
.worksheet_mut(sheet)? .worksheet_mut(sheet)?
.set_cell_style(row, column, 0)?; .set_cell_style(row, column, 0)?;
diff_list.push(Diff::CellClearFormatting { diff_list.push(Diff::CellClearFormatting {
sheet, sheet,
row, row,
column, column,
old_style: Box::new(old_style), old_style: Box::new(old_style),
}); });
}
} }
} }
self.push_diff_list(diff_list); self.push_diff_list(diff_list);
@@ -915,331 +916,6 @@ impl UserModel {
Ok(()) Ok(())
} }
/// Sets the border in an area of cells.
/// When setting the border we need to check if the adjacent cells have a "heavier" border
/// If that is the case we need to change it
pub fn set_area_with_border(
&mut self,
range: &Area,
border_area: &BorderArea,
) -> Result<(), String> {
let sheet = range.sheet;
let mut diff_list = Vec::new();
let last_row = range.row + range.height - 1;
let last_column = range.column + range.width - 1;
for row in range.row..=last_row {
for column in range.column..=last_column {
let old_value = self.model.get_style_for_cell(sheet, row, column)?;
let mut new_value = old_value.clone();
match border_area.r#type {
BorderType::All => {
new_value.border.top = Some(border_area.item.clone());
new_value.border.right = Some(border_area.item.clone());
new_value.border.bottom = Some(border_area.item.clone());
new_value.border.left = Some(border_area.item.clone());
}
BorderType::Inner => {
if row != range.row {
new_value.border.top = Some(border_area.item.clone());
}
if row != last_row {
new_value.border.bottom = Some(border_area.item.clone());
}
if column != range.column {
new_value.border.left = Some(border_area.item.clone());
}
if column != last_column {
new_value.border.right = Some(border_area.item.clone());
}
}
BorderType::Outer => {
if row == range.row {
new_value.border.top = Some(border_area.item.clone());
}
if row == last_row {
new_value.border.bottom = Some(border_area.item.clone());
}
if column == range.column {
new_value.border.left = Some(border_area.item.clone());
}
if column == last_column {
new_value.border.right = Some(border_area.item.clone());
}
}
BorderType::Top => {
new_value.border.top = Some(border_area.item.clone());
// Check if the cell above has a "heavier" bottom border
if row > 1 {
let old_value_cell_above =
self.model.get_style_for_cell(sheet, row - 1, column)?;
if is_max_border(
Some(&border_area.item),
old_value_cell_above.border.bottom.as_ref(),
) {
let mut new_value_cell_above = old_value_cell_above.clone();
if border_area.r#type == BorderType::None {
new_value_cell_above.border.bottom = None;
} else {
new_value_cell_above.border.bottom =
Some(border_area.item.clone());
}
self.model.set_cell_style(
sheet,
row - 1,
column,
&new_value_cell_above,
)?;
diff_list.push(Diff::SetCellStyle {
sheet,
row: row - 1,
column,
old_value: Box::new(Some(old_value_cell_above)),
new_value: Box::new(new_value_cell_above),
});
}
}
}
BorderType::Right => {
new_value.border.right = Some(border_area.item.clone());
// Check if the cell to the right has a "heavier" left border
if column < LAST_COLUMN {
let old_value_cell_right =
self.model.get_style_for_cell(sheet, row, column + 1)?;
if is_max_border(
Some(&border_area.item),
old_value_cell_right.border.left.as_ref(),
) {
let mut new_value_cell_right = old_value_cell_right.clone();
if border_area.r#type == BorderType::None {
new_value_cell_right.border.left = None;
} else {
new_value_cell_right.border.left =
Some(border_area.item.clone());
}
self.model.set_cell_style(
sheet,
row,
column + 1,
&new_value_cell_right,
)?;
diff_list.push(Diff::SetCellStyle {
sheet,
row,
column: column + 1,
old_value: Box::new(Some(old_value_cell_right)),
new_value: Box::new(new_value_cell_right),
});
}
}
}
BorderType::Bottom => {
new_value.border.bottom = Some(border_area.item.clone());
// Check if the cell bellow has a "heavier" top border
if row < LAST_ROW {
let old_value_cell_below =
self.model.get_style_for_cell(sheet, row + 1, column)?;
if is_max_border(
Some(&border_area.item),
old_value_cell_below.border.top.as_ref(),
) {
let mut new_value_cell_below = old_value_cell_below.clone();
if border_area.r#type == BorderType::None {
new_value_cell_below.border.top = None;
} else {
new_value_cell_below.border.top =
Some(border_area.item.clone());
}
self.model.set_cell_style(
sheet,
row + 1,
column,
&new_value_cell_below,
)?;
diff_list.push(Diff::SetCellStyle {
sheet,
row: row + 1,
column,
old_value: Box::new(Some(old_value_cell_below)),
new_value: Box::new(new_value_cell_below),
});
}
}
}
BorderType::Left => {
new_value.border.left = Some(border_area.item.clone());
// Check if the cell to the left has a "heavier" right border
if column > 1 {
let old_value_cell_left =
self.model.get_style_for_cell(sheet, row, column - 1)?;
if is_max_border(
Some(&border_area.item),
old_value_cell_left.border.right.as_ref(),
) {
let mut new_value_cell_left = old_value_cell_left.clone();
if border_area.r#type == BorderType::None {
new_value_cell_left.border.right = None;
} else {
new_value_cell_left.border.right =
Some(border_area.item.clone());
}
self.model.set_cell_style(
sheet,
row,
column - 1,
&new_value_cell_left,
)?;
diff_list.push(Diff::SetCellStyle {
sheet,
row,
column: column - 1,
old_value: Box::new(Some(old_value_cell_left)),
new_value: Box::new(new_value_cell_left),
});
}
}
}
BorderType::CenterH => {
if row != range.row {
new_value.border.top = Some(border_area.item.clone());
}
if row != last_row {
new_value.border.bottom = Some(border_area.item.clone());
}
}
BorderType::CenterV => {
if column != range.column {
new_value.border.left = Some(border_area.item.clone());
}
if column != last_column {
new_value.border.right = Some(border_area.item.clone());
}
}
BorderType::None => {
new_value.border.top = None;
new_value.border.right = None;
new_value.border.bottom = None;
new_value.border.left = None;
}
}
self.model.set_cell_style(sheet, row, column, &new_value)?;
diff_list.push(Diff::SetCellStyle {
sheet,
row,
column,
old_value: Box::new(Some(old_value)),
new_value: Box::new(new_value),
});
}
}
// bottom of the cells above the first
if range.row > 1
&& [BorderType::All, BorderType::None, BorderType::Outer].contains(&border_area.r#type)
{
let row = range.row - 1;
for column in range.column..=last_column {
let old_value = self.model.get_style_for_cell(sheet, row, column)?;
if is_max_border(Some(&border_area.item), old_value.border.bottom.as_ref()) {
let mut style = old_value.clone();
if border_area.r#type == BorderType::None {
style.border.bottom = None;
} else {
style.border.bottom = Some(border_area.item.clone());
}
self.model.set_cell_style(sheet, row, column, &style)?;
diff_list.push(Diff::SetCellStyle {
sheet,
row,
column,
old_value: Box::new(Some(old_value)),
new_value: Box::new(style),
});
}
}
}
// Cells to the right
if last_column < LAST_COLUMN
&& [BorderType::All, BorderType::None, BorderType::Outer].contains(&border_area.r#type)
{
let column = last_column + 1;
for row in range.row..=last_row {
let old_value = self.model.get_style_for_cell(sheet, row, column)?;
// If the border in the adjacent cell is "heavier" we change it
if is_max_border(Some(&border_area.item), old_value.border.left.as_ref()) {
let mut style = old_value.clone();
if border_area.r#type == BorderType::None {
style.border.left = None;
} else {
style.border.left = Some(border_area.item.clone());
}
self.model.set_cell_style(sheet, row, column, &style)?;
diff_list.push(Diff::SetCellStyle {
sheet,
row,
column,
old_value: Box::new(Some(old_value)),
new_value: Box::new(style),
});
}
}
}
// Cells bellow
if last_row < LAST_ROW
&& [BorderType::All, BorderType::None, BorderType::Outer].contains(&border_area.r#type)
{
let row = last_row + 1;
for column in range.column..=last_column {
let old_value = self.model.get_style_for_cell(sheet, row, column)?;
if is_max_border(Some(&border_area.item), old_value.border.top.as_ref()) {
let mut style = old_value.clone();
if border_area.r#type == BorderType::None {
style.border.top = None;
} else {
style.border.top = Some(border_area.item.clone());
}
self.model.set_cell_style(sheet, row, column, &style)?;
diff_list.push(Diff::SetCellStyle {
sheet,
row,
column,
old_value: Box::new(Some(old_value)),
new_value: Box::new(style),
});
}
}
}
// Cells to the left
if range.column > 1
&& [BorderType::All, BorderType::None, BorderType::Outer].contains(&border_area.r#type)
{
let column = range.column - 1;
for row in range.row..=last_row {
let old_value = self.model.get_style_for_cell(sheet, row, column)?;
if is_max_border(Some(&border_area.item), old_value.border.right.as_ref()) {
let mut style = old_value.clone();
if border_area.r#type == BorderType::None {
style.border.right = None;
} else {
style.border.right = Some(border_area.item.clone());
}
self.model.set_cell_style(sheet, row, column, &style)?;
diff_list.push(Diff::SetCellStyle {
sheet,
row,
column,
old_value: Box::new(Some(old_value)),
new_value: Box::new(style),
});
}
}
}
self.push_diff_list(diff_list);
Ok(())
}
fn update_single_cell_style( fn update_single_cell_style(
&mut self, &mut self,
sheet: u32, sheet: u32,
@@ -1968,7 +1644,7 @@ impl UserModel {
// **** Private methods ****** // // **** Private methods ****** //
fn push_diff_list(&mut self, diff_list: DiffList) { pub(crate) fn push_diff_list(&mut self, diff_list: DiffList) {
self.send_queue.push(QueueDiffs { self.send_queue.push(QueueDiffs {
r#type: DiffType::Redo, r#type: DiffType::Redo,
list: diff_list.clone(), list: diff_list.clone(),

View File

@@ -1,5 +1,6 @@
#![deny(missing_docs)] #![deny(missing_docs)]
mod border;
mod border_utils; mod border_utils;
mod common; mod common;
mod history; mod history;

View File

@@ -119,7 +119,6 @@ const usePointer = (options: PointerSettings): PointerEvents => {
const onPointerDown = useCallback( const onPointerDown = useCallback(
(event: PointerEvent) => { (event: PointerEvent) => {
console.log("onPointerDown");
let x = event.clientX; let x = event.clientX;
let y = event.clientY; let y = event.clientY;
const { const {