summaryrefslogtreecommitdiff
path: root/library/src/shared/ext.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-11-26 12:49:30 +0100
committerLaurenz <laurmaedje@gmail.com>2022-11-26 12:51:15 +0100
commit3cdd8bfa40fe5fdf0c676af905c3c2c1f614ef24 (patch)
treefe837d4a30bcad673f581fab18fd946364a60ef3 /library/src/shared/ext.rs
parentbf5edbbbbb75120d065d1c9587ccfa4eed4fdca1 (diff)
Extract numbering pattern from list node
Diffstat (limited to 'library/src/shared/ext.rs')
-rw-r--r--library/src/shared/ext.rs147
1 files changed, 147 insertions, 0 deletions
diff --git a/library/src/shared/ext.rs b/library/src/shared/ext.rs
new file mode 100644
index 00000000..f90260ad
--- /dev/null
+++ b/library/src/shared/ext.rs
@@ -0,0 +1,147 @@
+//! Extension traits.
+
+use crate::prelude::*;
+
+/// Additional methods on content.
+pub trait ContentExt {
+ /// Make this content strong.
+ fn strong(self) -> Self;
+
+ /// Make this content emphasized.
+ fn emph(self) -> Self;
+
+ /// Underline this content.
+ fn underlined(self) -> Self;
+
+ /// Force a size for this content.
+ fn boxed(self, sizing: Axes<Option<Rel<Length>>>) -> Self;
+
+ /// Set alignments for this content.
+ fn aligned(self, aligns: Axes<Option<GenAlign>>) -> Self;
+
+ /// Pad this content at the sides.
+ fn padded(self, padding: Sides<Rel<Length>>) -> Self;
+
+ /// Transform this content's contents without affecting layout.
+ fn moved(self, delta: Axes<Rel<Length>>) -> Self;
+
+ /// Fill the frames resulting from a content.
+ fn filled(self, fill: Paint) -> Self;
+
+ /// Stroke the frames resulting from a content.
+ fn stroked(self, stroke: Stroke) -> Self;
+}
+
+impl ContentExt for Content {
+ fn strong(self) -> Self {
+ crate::text::StrongNode(self).pack()
+ }
+
+ fn emph(self) -> Self {
+ crate::text::EmphNode(self).pack()
+ }
+
+ fn underlined(self) -> Self {
+ crate::text::DecoNode::<{ crate::text::UNDERLINE }>(self).pack()
+ }
+
+ fn boxed(self, sizing: Axes<Option<Rel<Length>>>) -> Self {
+ crate::layout::BoxNode { sizing, child: self }.pack()
+ }
+
+ fn aligned(self, aligns: Axes<Option<GenAlign>>) -> Self {
+ crate::layout::AlignNode { aligns, child: self }.pack()
+ }
+
+ fn padded(self, padding: Sides<Rel<Length>>) -> Self {
+ crate::layout::PadNode { padding, child: self }.pack()
+ }
+
+ fn moved(self, delta: Axes<Rel<Length>>) -> Self {
+ crate::layout::MoveNode { delta, child: self }.pack()
+ }
+
+ fn filled(self, fill: Paint) -> Self {
+ FillNode { fill, child: self }.pack()
+ }
+
+ fn stroked(self, stroke: Stroke) -> Self {
+ StrokeNode { stroke, child: self }.pack()
+ }
+}
+
+/// Additional methods for style maps.
+pub trait StyleMapExt {
+ /// Set a font family composed of a preferred family and existing families
+ /// from a style chain.
+ fn set_family(&mut self, preferred: crate::text::FontFamily, existing: StyleChain);
+}
+
+impl StyleMapExt for StyleMap {
+ fn set_family(&mut self, preferred: crate::text::FontFamily, existing: StyleChain) {
+ self.set(
+ crate::text::TextNode::FAMILY,
+ crate::text::FallbackList(
+ std::iter::once(preferred)
+ .chain(existing.get(crate::text::TextNode::FAMILY).0.iter().cloned())
+ .collect(),
+ ),
+ );
+ }
+}
+
+/// Fill the frames resulting from content.
+#[derive(Debug, Hash)]
+struct FillNode {
+ /// How to fill the frames resulting from the `child`.
+ fill: Paint,
+ /// The content whose frames should be filled.
+ child: Content,
+}
+
+#[node(LayoutBlock)]
+impl FillNode {}
+
+impl LayoutBlock for FillNode {
+ fn layout_block(
+ &self,
+ world: Tracked<dyn World>,
+ styles: StyleChain,
+ regions: &Regions,
+ ) -> SourceResult<Vec<Frame>> {
+ let mut frames = self.child.layout_block(world, styles, regions)?;
+ for frame in &mut frames {
+ let shape = Geometry::Rect(frame.size()).filled(self.fill);
+ frame.prepend(Point::zero(), Element::Shape(shape));
+ }
+ Ok(frames)
+ }
+}
+
+/// Stroke the frames resulting from content.
+#[derive(Debug, Hash)]
+struct StrokeNode {
+ /// How to stroke the frames resulting from the `child`.
+ stroke: Stroke,
+ /// The content whose frames should be stroked.
+ child: Content,
+}
+
+#[node(LayoutBlock)]
+impl StrokeNode {}
+
+impl LayoutBlock for StrokeNode {
+ fn layout_block(
+ &self,
+ world: Tracked<dyn World>,
+ styles: StyleChain,
+ regions: &Regions,
+ ) -> SourceResult<Vec<Frame>> {
+ let mut frames = self.child.layout_block(world, styles, regions)?;
+ for frame in &mut frames {
+ let shape = Geometry::Rect(frame.size()).stroked(self.stroke);
+ frame.prepend(Point::zero(), Element::Shape(shape));
+ }
+ Ok(frames)
+ }
+}