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