summaryrefslogtreecommitdiff
path: root/src/library/layout
diff options
context:
space:
mode:
authorMartin Haug <mhaug@live.de>2022-06-04 12:57:45 +0200
committerMartin Haug <mhaug@live.de>2022-06-04 12:57:45 +0200
commit4640585fbdf72df993dbed46799844aa78996cce (patch)
tree38a09389885a61068970441d6d27178a2ae4f115 /src/library/layout
parenta937462491a63f5cff3551b5bb8bc45fb350f0b6 (diff)
First iteration of outline items
Diffstat (limited to 'src/library/layout')
-rw-r--r--src/library/layout/flow.rs7
-rw-r--r--src/library/layout/grid.rs44
-rw-r--r--src/library/layout/page.rs23
-rw-r--r--src/library/layout/stack.rs3
4 files changed, 70 insertions, 7 deletions
diff --git a/src/library/layout/flow.rs b/src/library/layout/flow.rs
index 6193a68f..0ba84b09 100644
--- a/src/library/layout/flow.rs
+++ b/src/library/layout/flow.rs
@@ -182,7 +182,12 @@ impl FlowLayouter {
let frames = node.layout(ctx, &self.regions, styles)?;
let len = frames.len();
- for (i, frame) in frames.into_iter().enumerate() {
+ for (i, mut frame) in frames.into_iter().enumerate() {
+ // Set the generic block role.
+ if frame.role().is_none() {
+ Arc::make_mut(&mut frame).apply_role(Role::GenericBlock);
+ }
+
// Grow our size, shrink the region and save the frame for later.
let size = frame.size;
self.used.y += size.y;
diff --git a/src/library/layout/grid.rs b/src/library/layout/grid.rs
index 4cad9de6..2517d193 100644
--- a/src/library/layout/grid.rs
+++ b/src/library/layout/grid.rs
@@ -9,6 +9,8 @@ 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]
@@ -26,6 +28,7 @@ impl GridNode {
row_gutter.unwrap_or(base_gutter),
),
cells: args.all()?,
+ semantic: GridSemantics::None,
}))
}
}
@@ -45,6 +48,7 @@ impl Layout for GridNode {
&self.cells,
regions,
styles,
+ self.semantic,
);
// Measure the columns and layout the grid row-by-row.
@@ -65,6 +69,28 @@ pub enum TrackSizing {
Fractional(Fraction),
}
+/// Defines what kind of semantics a grid should represent.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+pub 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
+ /// the list is ordered.
+ List,
+ /// The grid is a table.
+ Table,
+}
+
+impl GridSemantics {
+ fn row(self) -> Option<Role> {
+ match self {
+ Self::None => None,
+ Self::List => Some(Role::ListItem),
+ Self::Table => Some(Role::TableRow),
+ }
+ }
+}
+
castable! {
Vec<TrackSizing>,
Expected: "integer, auto, relative length, fraction, or array of the latter three)",
@@ -104,6 +130,8 @@ 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.
@@ -139,6 +167,7 @@ impl<'a> GridLayouter<'a> {
cells: &'a [LayoutNode],
regions: &Regions,
styles: StyleChain<'a>,
+ semantic: GridSemantics,
) -> Self {
let mut cols = vec![];
let mut rows = vec![];
@@ -193,6 +222,7 @@ impl<'a> GridLayouter<'a> {
rows,
regions,
styles,
+ semantic,
rcols,
lrows,
full,
@@ -450,6 +480,10 @@ 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();
for (x, &rcol) in self.rcols.iter().enumerate() {
@@ -464,6 +498,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);
+
output.push_frame(pos, frame);
}
@@ -482,7 +517,14 @@ impl<'a> GridLayouter<'a> {
// Prepare frames.
let mut outputs: Vec<_> = heights
.iter()
- .map(|&h| Frame::new(Size::new(self.used.x, h)))
+ .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
+ })
.collect();
// Prepare regions.
diff --git a/src/library/layout/page.rs b/src/library/layout/page.rs
index 8435e510..d524839b 100644
--- a/src/library/layout/page.rs
+++ b/src/library/layout/page.rs
@@ -110,15 +110,28 @@ impl PageNode {
let pad = padding.resolve(styles).relative_to(size);
let pw = size.x - pad.left - pad.right;
let py = size.y - pad.bottom;
- for (marginal, pos, area) in [
- (header, Point::with_x(pad.left), Size::new(pw, pad.top)),
- (footer, Point::new(pad.left, py), Size::new(pw, pad.bottom)),
- (foreground, Point::zero(), size),
- (background, Point::zero(), size),
+ for (marginal, pos, area, role) in [
+ (
+ header,
+ Point::with_x(pad.left),
+ Size::new(pw, pad.top),
+ Role::Header,
+ ),
+ (
+ footer,
+ Point::new(pad.left, py),
+ Size::new(pw, pad.bottom),
+ Role::Footer,
+ ),
+ (foreground, Point::zero(), size, Role::Background),
+ (background, Point::zero(), size, Role::Background),
] {
if let Some(content) = marginal.resolve(ctx, page)? {
let pod = Regions::one(area, area, Spec::splat(true));
+ let role_map = StyleMap::with_role(role);
+ let styles = role_map.chain(&styles);
let sub = content.layout(ctx, &pod, styles)?.remove(0);
+
if std::ptr::eq(marginal, background) {
Arc::make_mut(frame).prepend_frame(pos, sub);
} else {
diff --git a/src/library/layout/stack.rs b/src/library/layout/stack.rs
index 828ff8e3..7bad01d9 100644
--- a/src/library/layout/stack.rs
+++ b/src/library/layout/stack.rs
@@ -192,6 +192,9 @@ impl<'a> StackLayouter<'a> {
self.dir.start().into()
});
+ let role_map = StyleMap::with_role(Role::GenericBlock);
+ let styles = role_map.chain(&styles);
+
let frames = node.layout(ctx, &self.regions, styles)?;
let len = frames.len();
for (i, frame) in frames.into_iter().enumerate() {