mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Auto-detect grid row semantics
This commit is contained in:
parent
6d8b65c4b2
commit
995a7882d2
@ -9,8 +9,6 @@ pub struct GridNode {
|
||||
pub gutter: Spec<Vec<TrackSizing>>,
|
||||
/// The nodes to be arranged in a grid.
|
||||
pub cells: Vec<LayoutNode>,
|
||||
/// The role of the grid in the semantic tree.
|
||||
pub semantic: GridSemantics,
|
||||
}
|
||||
|
||||
#[node]
|
||||
@ -28,7 +26,6 @@ impl GridNode {
|
||||
row_gutter.unwrap_or(base_gutter),
|
||||
),
|
||||
cells: args.all()?,
|
||||
semantic: GridSemantics::None,
|
||||
}))
|
||||
}
|
||||
}
|
||||
@ -48,7 +45,6 @@ impl Layout for GridNode {
|
||||
&self.cells,
|
||||
regions,
|
||||
styles,
|
||||
self.semantic,
|
||||
);
|
||||
|
||||
// Measure the columns and layout the grid row-by-row.
|
||||
@ -71,7 +67,7 @@ pub enum TrackSizing {
|
||||
|
||||
/// Defines what kind of semantics a grid should represent.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum GridSemantics {
|
||||
enum GridSemantics {
|
||||
/// The grid is transparent to the semantic tree.
|
||||
None,
|
||||
/// The grid is a list, its rows are list items. The bool indicates whether
|
||||
@ -82,6 +78,7 @@ pub enum GridSemantics {
|
||||
}
|
||||
|
||||
impl GridSemantics {
|
||||
/// The role of a row in a grid with these semantics.
|
||||
fn row(self) -> Option<Role> {
|
||||
match self {
|
||||
Self::None => None,
|
||||
@ -89,6 +86,18 @@ impl GridSemantics {
|
||||
Self::Table => Some(Role::TableRow),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the semantic role of a grid row given the previous semantics and
|
||||
/// the cell's role.
|
||||
fn determine(other: Option<Self>, role: Option<Role>) -> Self {
|
||||
match (other, role) {
|
||||
(None, Some(Role::ListItem | Role::ListLabel)) => Self::List,
|
||||
(Some(Self::List), Some(Role::ListItem | Role::ListLabel)) => Self::List,
|
||||
(None, Some(Role::TableCell)) => Self::Table,
|
||||
(Some(Self::Table), Some(Role::TableCell)) => Self::Table,
|
||||
_ => Self::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
castable! {
|
||||
@ -130,8 +139,6 @@ pub struct GridLayouter<'a> {
|
||||
regions: Regions,
|
||||
/// The inherited styles.
|
||||
styles: StyleChain<'a>,
|
||||
/// The role of the grid in the semantic tree.
|
||||
semantic: GridSemantics,
|
||||
/// Resolved column sizes.
|
||||
rcols: Vec<Length>,
|
||||
/// Rows in the current region.
|
||||
@ -167,7 +174,6 @@ impl<'a> GridLayouter<'a> {
|
||||
cells: &'a [LayoutNode],
|
||||
regions: &Regions,
|
||||
styles: StyleChain<'a>,
|
||||
semantic: GridSemantics,
|
||||
) -> Self {
|
||||
let mut cols = vec![];
|
||||
let mut rows = vec![];
|
||||
@ -222,7 +228,6 @@ impl<'a> GridLayouter<'a> {
|
||||
rows,
|
||||
regions,
|
||||
styles,
|
||||
semantic,
|
||||
rcols,
|
||||
lrows,
|
||||
full,
|
||||
@ -480,11 +485,9 @@ impl<'a> GridLayouter<'a> {
|
||||
/// Layout a row with fixed height and return its frame.
|
||||
fn layout_single_row(&mut self, height: Length, y: usize) -> TypResult<Frame> {
|
||||
let mut output = Frame::new(Size::new(self.used.x, height));
|
||||
if let Some(role) = self.semantic.row() {
|
||||
output.apply_role(role);
|
||||
}
|
||||
|
||||
let mut pos = Point::zero();
|
||||
let mut semantic = None;
|
||||
|
||||
for (x, &rcol) in self.rcols.iter().enumerate() {
|
||||
if let Some(node) = self.cell(x, y) {
|
||||
@ -498,6 +501,7 @@ impl<'a> GridLayouter<'a> {
|
||||
|
||||
let pod = Regions::one(size, base, Spec::splat(true));
|
||||
let frame = node.layout(self.ctx, &pod, self.styles)?.remove(0);
|
||||
semantic = Some(GridSemantics::determine(semantic, frame.role()));
|
||||
|
||||
output.push_frame(pos, frame);
|
||||
}
|
||||
@ -505,6 +509,10 @@ impl<'a> GridLayouter<'a> {
|
||||
pos.x += rcol;
|
||||
}
|
||||
|
||||
if let Some(role) = semantic.and_then(GridSemantics::row) {
|
||||
output.apply_role(role);
|
||||
}
|
||||
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
@ -517,14 +525,7 @@ impl<'a> GridLayouter<'a> {
|
||||
// Prepare frames.
|
||||
let mut outputs: Vec<_> = heights
|
||||
.iter()
|
||||
.map(|&h| {
|
||||
let mut f = Frame::new(Size::new(self.used.x, h));
|
||||
if let Some(role) = self.semantic.row() {
|
||||
f.apply_role(role);
|
||||
}
|
||||
|
||||
f
|
||||
})
|
||||
.map(|&h| Frame::new(Size::new(self.used.x, h)))
|
||||
.collect();
|
||||
|
||||
// Prepare regions.
|
||||
@ -534,6 +535,7 @@ impl<'a> GridLayouter<'a> {
|
||||
|
||||
// Layout the row.
|
||||
let mut pos = Point::zero();
|
||||
let mut semantic = None;
|
||||
for (x, &rcol) in self.rcols.iter().enumerate() {
|
||||
if let Some(node) = self.cell(x, y) {
|
||||
pod.first.x = rcol;
|
||||
@ -547,6 +549,7 @@ impl<'a> GridLayouter<'a> {
|
||||
// Push the layouted frames into the individual output frames.
|
||||
let frames = node.layout(self.ctx, &pod, self.styles)?;
|
||||
for (output, frame) in outputs.iter_mut().zip(frames) {
|
||||
semantic = Some(GridSemantics::determine(semantic, frame.role()));
|
||||
output.push_frame(pos, frame);
|
||||
}
|
||||
}
|
||||
@ -554,6 +557,12 @@ impl<'a> GridLayouter<'a> {
|
||||
pos.x += rcol;
|
||||
}
|
||||
|
||||
for output in outputs.iter_mut() {
|
||||
if let Some(role) = semantic.and_then(GridSemantics::row) {
|
||||
output.apply_role(role);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(outputs)
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::library::layout::BlockSpacing;
|
||||
use crate::library::prelude::*;
|
||||
use crate::library::text::{FontFamily, TextNode, TextSize};
|
||||
use crate::model::StyleEntry;
|
||||
|
||||
/// A section heading.
|
||||
#[derive(Debug, Hash)]
|
||||
|
@ -2,11 +2,10 @@ use std::fmt::Write;
|
||||
|
||||
use unscanny::Scanner;
|
||||
|
||||
use crate::library::layout::{BlockSpacing, GridNode, GridSemantics, TrackSizing};
|
||||
use crate::library::layout::{BlockSpacing, GridNode, TrackSizing};
|
||||
use crate::library::prelude::*;
|
||||
use crate::library::text::ParNode;
|
||||
use crate::library::utility::Numbering;
|
||||
use crate::model::StyleEntry;
|
||||
|
||||
/// An unordered (bulleted) or ordered (numbered) list.
|
||||
#[derive(Debug, Hash)]
|
||||
@ -141,7 +140,6 @@ impl<const L: ListKind> Show for ListNode<L> {
|
||||
]),
|
||||
gutter: Spec::with_y(vec![TrackSizing::Relative(gutter.into())]),
|
||||
cells,
|
||||
semantic: GridSemantics::List,
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::library::layout::{BlockSpacing, GridNode, GridSemantics, TrackSizing};
|
||||
use crate::library::layout::{BlockSpacing, GridNode, TrackSizing};
|
||||
use crate::library::prelude::*;
|
||||
use crate::model::StyleEntry;
|
||||
|
||||
/// A table of items.
|
||||
#[derive(Debug, Hash)]
|
||||
@ -105,7 +104,6 @@ impl Show for TableNode {
|
||||
tracks: self.tracks.clone(),
|
||||
gutter: self.gutter.clone(),
|
||||
cells,
|
||||
semantic: GridSemantics::Table,
|
||||
})
|
||||
.role(Role::Table))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user