mirror of
https://github.com/typst/typst
synced 2025-08-14 07:07:54 +08:00
refactor conflicting header/footer check into function
This commit is contained in:
parent
5ac4ab2f1b
commit
db845d732e
@ -422,12 +422,14 @@ pub struct Line {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A repeatable grid header. Starts at the first row.
|
/// A repeatable grid header. Starts at the first row.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Header {
|
pub struct Header {
|
||||||
/// The index after the last row included in this header.
|
/// The index after the last row included in this header.
|
||||||
pub end: usize,
|
pub end: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A repeatable grid footer. Stops at the last row.
|
/// A repeatable grid footer. Stops at the last row.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Footer {
|
pub struct Footer {
|
||||||
/// The first row included in this footer.
|
/// The first row included in this footer.
|
||||||
pub start: usize,
|
pub start: usize,
|
||||||
@ -994,6 +996,7 @@ impl<'a> CellGrid<'a> {
|
|||||||
&mut local_auto_index,
|
&mut local_auto_index,
|
||||||
first_available_row,
|
first_available_row,
|
||||||
c,
|
c,
|
||||||
|
is_row_group,
|
||||||
)
|
)
|
||||||
.at(cell_span)?
|
.at(cell_span)?
|
||||||
};
|
};
|
||||||
@ -1148,34 +1151,6 @@ impl<'a> CellGrid<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
child_range = Some(new_child_start..new_child_end);
|
child_range = Some(new_child_start..new_child_end);
|
||||||
} else {
|
|
||||||
// TODO: Perhaps do this during cell resolving?
|
|
||||||
// This is unnecessary for non-row-positioned cells, as
|
|
||||||
// they skip headers and footers already.
|
|
||||||
if let Some(header) = &header {
|
|
||||||
// TODO: check start (right now zero, always satisfied)
|
|
||||||
if y < header.end {
|
|
||||||
bail!(
|
|
||||||
cell_span,
|
|
||||||
"cell would conflict with header spanning the same position";
|
|
||||||
hint: "try moving the cell or the header"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some((footer_end, _, footer)) = &footer {
|
|
||||||
// NOTE: y + rowspan >, not >=, footer.start, to
|
|
||||||
// check if the rowspan enters the footer. For example,
|
|
||||||
// rowspan of 1: y + 1 = footer.start means
|
|
||||||
// `y < footer.start`, and it only occupies one row
|
|
||||||
// (`y`), so the cell is safe.
|
|
||||||
if y < *footer_end && y + rowspan > footer.start {
|
|
||||||
bail!(
|
|
||||||
cell_span,
|
|
||||||
"cell would conflict with footer spanning the same position";
|
|
||||||
hint: "try reducing the cell's rowspan or moving the footer"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if largest_index >= resolved_cells.len() {
|
if largest_index >= resolved_cells.len() {
|
||||||
@ -1738,6 +1713,40 @@ impl<'a> CellGrid<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if a cell's fixed row would conflict with a header or footer.
|
||||||
|
fn check_for_conflicting_cell_row(
|
||||||
|
header: Option<&Header>,
|
||||||
|
footer: Option<&(usize, Span, Footer)>,
|
||||||
|
cell_y: usize,
|
||||||
|
rowspan: usize,
|
||||||
|
) -> HintedStrResult<()> {
|
||||||
|
if let Some(header) = header {
|
||||||
|
// TODO: check start (right now zero, always satisfied)
|
||||||
|
if cell_y < header.end {
|
||||||
|
bail!(
|
||||||
|
"cell would conflict with header spanning the same position";
|
||||||
|
hint: "try moving the cell or the header"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((footer_end, _, footer)) = footer {
|
||||||
|
// NOTE: y + rowspan >, not >=, footer.start, to check if the rowspan
|
||||||
|
// enters the footer. For example, consider a rowspan of 1: if
|
||||||
|
// `y + 1 = footer.start` holds, that means `y < footer.start`, and it
|
||||||
|
// only occupies one row (`y`), so the cell is actually not in
|
||||||
|
// conflict.
|
||||||
|
if cell_y < *footer_end && cell_y + rowspan > footer.start {
|
||||||
|
bail!(
|
||||||
|
"cell would conflict with footer spanning the same position";
|
||||||
|
hint: "try reducing the cell's rowspan or moving the footer"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Given a cell's requested x and y, the vector with the resolved cell
|
/// Given a cell's requested x and y, the vector with the resolved cell
|
||||||
/// positions, the `auto_index` counter (determines the position of the next
|
/// positions, the `auto_index` counter (determines the position of the next
|
||||||
/// `(auto, auto)` cell) and the amount of columns in the grid, returns the
|
/// `(auto, auto)` cell) and the amount of columns in the grid, returns the
|
||||||
@ -1759,6 +1768,7 @@ fn resolve_cell_position(
|
|||||||
auto_index: &mut usize,
|
auto_index: &mut usize,
|
||||||
first_available_row: usize,
|
first_available_row: usize,
|
||||||
columns: usize,
|
columns: usize,
|
||||||
|
is_row_group: bool,
|
||||||
) -> HintedStrResult<usize> {
|
) -> HintedStrResult<usize> {
|
||||||
// Translates a (x, y) position to the equivalent index in the final cell vector.
|
// Translates a (x, y) position to the equivalent index in the final cell vector.
|
||||||
// Errors if the position would be too large.
|
// Errors if the position would be too large.
|
||||||
@ -1833,6 +1843,14 @@ fn resolve_cell_position(
|
|||||||
}
|
}
|
||||||
if let Smart::Custom(cell_y) = cell_y {
|
if let Smart::Custom(cell_y) = cell_y {
|
||||||
// Cell has chosen its exact position.
|
// Cell has chosen its exact position.
|
||||||
|
//
|
||||||
|
// Ensure it doesn't conflict with an existing header or
|
||||||
|
// footer (but only if it isn't already in one, otherwise there
|
||||||
|
// will already be a separate check).
|
||||||
|
if !is_row_group {
|
||||||
|
check_for_conflicting_cell_row(header, footer, cell_y, rowspan)?;
|
||||||
|
}
|
||||||
|
|
||||||
cell_index(cell_x, cell_y)
|
cell_index(cell_x, cell_y)
|
||||||
} else {
|
} else {
|
||||||
// Cell has only chosen its column.
|
// Cell has only chosen its column.
|
||||||
@ -1886,6 +1904,13 @@ fn resolve_cell_position(
|
|||||||
}
|
}
|
||||||
// Cell has only chosen its row, not its column.
|
// Cell has only chosen its row, not its column.
|
||||||
(Smart::Auto, Smart::Custom(cell_y)) => {
|
(Smart::Auto, Smart::Custom(cell_y)) => {
|
||||||
|
// Ensure it doesn't conflict with an existing header or
|
||||||
|
// footer (but only if it isn't already in one, otherwise there
|
||||||
|
// will already be a separate check).
|
||||||
|
if !is_row_group {
|
||||||
|
check_for_conflicting_cell_row(header, footer, cell_y, rowspan)?;
|
||||||
|
}
|
||||||
|
|
||||||
// Let's find the first column which has that row available.
|
// Let's find the first column which has that row available.
|
||||||
let first_row_pos = cell_index(0, cell_y)?;
|
let first_row_pos = cell_index(0, cell_y)?;
|
||||||
let last_row_pos = first_row_pos
|
let last_row_pos = first_row_pos
|
||||||
|
@ -95,7 +95,22 @@
|
|||||||
grid.cell(x: 1)[c]
|
grid.cell(x: 1)[c]
|
||||||
)
|
)
|
||||||
|
|
||||||
--- grid-footer-no-expand ---
|
--- grid-footer-no-expand-with-col-and-row-pos-cell ---
|
||||||
|
#grid(
|
||||||
|
columns: 2,
|
||||||
|
[a], [],
|
||||||
|
[b], [],
|
||||||
|
fill: (_, y) => if calc.odd(y) { blue } else { red },
|
||||||
|
inset: 5pt,
|
||||||
|
grid.cell(x: 1, y: 3, rowspan: 4)[b],
|
||||||
|
grid.cell(y: 2, rowspan: 2)[a],
|
||||||
|
grid.footer(),
|
||||||
|
// Error: 3-27 cell would conflict with footer spanning the same position
|
||||||
|
// Hint: 3-27 try reducing the cell's rowspan or moving the footer
|
||||||
|
grid.cell(x: 1, y: 7)[d],
|
||||||
|
)
|
||||||
|
|
||||||
|
--- grid-footer-no-expand-with-row-pos-cell ---
|
||||||
#grid(
|
#grid(
|
||||||
columns: 2,
|
columns: 2,
|
||||||
[a], [],
|
[a], [],
|
||||||
|
@ -284,7 +284,7 @@
|
|||||||
)
|
)
|
||||||
#context count.display()
|
#context count.display()
|
||||||
|
|
||||||
--- grid-header-no-expand ---
|
--- grid-header-no-expand-with-col-and-row-pos-cell ---
|
||||||
#set page(height: 10em)
|
#set page(height: 10em)
|
||||||
#table(
|
#table(
|
||||||
columns: 2,
|
columns: 2,
|
||||||
@ -297,6 +297,19 @@
|
|||||||
table.cell(x: 1, y: 1, rowspan: 2, lorem(80))
|
table.cell(x: 1, y: 1, rowspan: 2, lorem(80))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
--- grid-header-no-expand-with-row-pos-cell ---
|
||||||
|
#set page(height: 10em)
|
||||||
|
#table(
|
||||||
|
columns: 2,
|
||||||
|
table.header(
|
||||||
|
[a], [b],
|
||||||
|
[c],
|
||||||
|
),
|
||||||
|
// Error: 3-42 cell would conflict with header spanning the same position
|
||||||
|
// Hint: 3-42 try moving the cell or the header
|
||||||
|
table.cell(y: 1, rowspan: 2, lorem(80))
|
||||||
|
)
|
||||||
|
|
||||||
--- grid-nested-with-headers ---
|
--- grid-nested-with-headers ---
|
||||||
// Nested table with header should repeat both headers
|
// Nested table with header should repeat both headers
|
||||||
#set page(height: 10em)
|
#set page(height: 10em)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user