From 8469bad7487e111c8e5a0ec542f0232a0ebb4bdc Mon Sep 17 00:00:00 2001 From: Martin Haug Date: Thu, 4 Feb 2021 21:30:18 +0100 Subject: =?UTF-8?q?Add=20rectangle=20function=20=F0=9F=8E=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layout/mod.rs | 69 +++++++++++++++++++++++++++++++++++++++++++++++++--- src/layout/pad.rs | 10 ++------ src/layout/rect.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 12 deletions(-) create mode 100644 src/layout/rect.rs (limited to 'src/layout') diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 44960de7..1bb4419d 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -4,10 +4,12 @@ mod fixed; mod node; mod pad; mod par; +mod rect; mod spacing; mod stack; mod text; +use crate::color::Color; use crate::env::{Env, ResourceId}; use crate::geom::*; use crate::shaping::Shaped; @@ -16,6 +18,7 @@ pub use fixed::*; pub use node::*; pub use pad::*; pub use par::*; +pub use rect::*; pub use spacing::*; pub use stack::*; pub use text::*; @@ -54,7 +57,7 @@ impl NodePages { pub fn layout(&self, ctx: &mut LayoutContext) -> Vec { let areas = Areas::repeat(self.size); let layouted = self.child.layout(ctx, &areas); - layouted.frames() + layouted.into_frames() } } @@ -157,9 +160,27 @@ pub enum Layouted { } impl Layouted { - /// Return all frames contained in this variant (zero, one or arbitrarily - /// many). - pub fn frames(self) -> Vec { + /// Return a reference to all frames contained in this variant (zero, one or + /// arbitrarily many). + pub fn frames(&self) -> &[Frame] { + match self { + Self::Spacing(_) => &[], + Self::Frame(frame, _) => std::slice::from_ref(frame), + Self::Frames(frames, _) => frames, + } + } + + /// Return a mutable reference to all frames contained in this variant. + pub fn frames_mut(&mut self) -> &mut [Frame] { + match self { + Self::Spacing(_) => &mut [], + Self::Frame(frame, _) => std::slice::from_mut(frame), + Self::Frames(frames, _) => frames, + } + } + + /// Return all frames contained in this varian. + pub fn into_frames(self) -> Vec { match self { Self::Spacing(_) => vec![], Self::Frame(frame, _) => vec![frame], @@ -204,6 +225,46 @@ pub enum Element { Text(Shaped), /// An image. Image(Image), + /// Some shape that could hold another frame. + Geometry(Geometry), +} + +/// The kind of graphic fill to be applied to a [`Shape`]. +#[derive(Debug, Clone, PartialEq)] +pub enum Fill { + /// The fill is a color. + Color(Color), + /// The fill is an image. + Image(Image), + // Gradient(Gradient), +} + +/// A shape with some kind of fill. +#[derive(Debug, Clone, PartialEq)] +pub struct Geometry { + /// The shape to draw. + pub shape: Shape, + /// How the shape looks on the inside. + /// + /// **TODO:** This could be made into a Vec or something such that + /// the user can compose multiple fills with alpha values less + /// than one to achieve cool effects. + pub fill: Fill, +} + +/// Some shape. +#[derive(Debug, Clone, PartialEq)] +pub enum Shape { + /// A rectangle. + Rect(Rect), + // Ellipse(Ellipse), +} + +/// An rectangle. +#[derive(Debug, Clone, PartialEq)] +pub struct Rect { + /// The dimensions of the rectangle. + pub size: Size, } /// An image element. diff --git a/src/layout/pad.rs b/src/layout/pad.rs index f8a623e3..425fa41b 100644 --- a/src/layout/pad.rs +++ b/src/layout/pad.rs @@ -15,14 +15,8 @@ impl Layout for NodePad { let areas = shrink(areas, self.padding); let mut layouted = self.child.layout(ctx, &areas); - match &mut layouted { - Layouted::Spacing(_) => {} - Layouted::Frame(frame, _) => pad(frame, self.padding), - Layouted::Frames(frames, _) => { - for frame in frames { - pad(frame, self.padding); - } - } + for frame in layouted.frames_mut() { + pad(frame, self.padding); } layouted diff --git a/src/layout/rect.rs b/src/layout/rect.rs new file mode 100644 index 00000000..ab8e3b07 --- /dev/null +++ b/src/layout/rect.rs @@ -0,0 +1,71 @@ +use std::cmp::Ordering; + +use super::*; +use crate::{color::RgbaColor, geom::Linear}; + +/// A node that represents a rectangular box. +#[derive(Debug, Clone, PartialEq)] +pub struct NodeRect { + /// The fixed width, if any. + pub width: Option, + /// The fixed height, if any. + pub height: Option, + /// The background color. + pub color: Option, + /// The child node whose sides to pad. + pub child: Node, +} + +impl Layout for NodeRect { + fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted { + let Areas { current, full, .. } = areas; + + let height_opt = self.height.map(|h| h.resolve(full.height)); + let mut size = Size::new( + self.width.map(|w| w.resolve(full.width)).unwrap_or(current.width), + height_opt.unwrap_or(current.height), + ); + + let areas = Areas::once(size); + let mut layouted = self.child.layout(ctx, &areas); + + // If the children have some height, apply that, + // otherwise fall back to zero or the height property. + if let Some(max) = layouted + .frames() + .iter() + .map(|f| f.size.height) + .max_by(|x, y| x.partial_cmp(y).unwrap_or(Ordering::Equal)) + { + size.height = max; + } else { + size.height = height_opt.unwrap_or(Length::ZERO) + } + + if let Some(first) = layouted.frames_mut().first_mut() { + first.elements.insert( + 0, + ( + Point::ZERO, + Element::Geometry(Geometry { + shape: Shape::Rect(Rect { size }), + fill: Fill::Color(self.color.unwrap_or(Color::Rgba(RgbaColor { + r: 255, + g: 255, + b: 255, + a: 0, + }))), + }), + ), + ) + } + + layouted + } +} + +impl From for NodeAny { + fn from(pad: NodeRect) -> Self { + Self::new(pad) + } +} -- cgit v1.2.3 From 80e076814dde330fb2136172580f11e939bc6601 Mon Sep 17 00:00:00 2001 From: Martin Haug Date: Sat, 6 Feb 2021 12:30:44 +0100 Subject: =?UTF-8?q?Merge=20`rect`=20and=20`box`=20=F0=9F=A6=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layout/background.rs | 37 +++++++++++++++++++++++++ src/layout/mod.rs | 23 +++++----------- src/layout/rect.rs | 71 ------------------------------------------------ 3 files changed, 44 insertions(+), 87 deletions(-) create mode 100644 src/layout/background.rs delete mode 100644 src/layout/rect.rs (limited to 'src/layout') diff --git a/src/layout/background.rs b/src/layout/background.rs new file mode 100644 index 00000000..94d5bf45 --- /dev/null +++ b/src/layout/background.rs @@ -0,0 +1,37 @@ +use super::*; + +/// A node that represents a rectangular box. +#[derive(Debug, Clone, PartialEq)] +pub struct NodeBackground { + /// The background fill. + pub fill: Fill, + /// The child node whose sides to pad. + pub child: NodeFixed, +} + +impl Layout for NodeBackground { + fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted { + let mut layouted = self.child.layout(ctx, areas); + + if let Some(first) = layouted.frames_mut().first_mut() { + first.elements.insert( + 0, + ( + Point::ZERO, + Element::Geometry(Geometry { + shape: Shape::Rect(first.size), + fill: self.fill.clone(), + }), + ), + ) + } + + layouted + } +} + +impl From for NodeAny { + fn from(background: NodeBackground) -> Self { + Self::new(background) + } +} diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 1bb4419d..0c7a6a68 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -4,7 +4,7 @@ mod fixed; mod node; mod pad; mod par; -mod rect; +mod background; mod spacing; mod stack; mod text; @@ -18,7 +18,7 @@ pub use fixed::*; pub use node::*; pub use pad::*; pub use par::*; -pub use rect::*; +pub use background::*; pub use spacing::*; pub use stack::*; pub use text::*; @@ -236,7 +236,6 @@ pub enum Fill { Color(Color), /// The fill is an image. Image(Image), - // Gradient(Gradient), } /// A shape with some kind of fill. @@ -245,10 +244,10 @@ pub struct Geometry { /// The shape to draw. pub shape: Shape, /// How the shape looks on the inside. - /// - /// **TODO:** This could be made into a Vec or something such that - /// the user can compose multiple fills with alpha values less - /// than one to achieve cool effects. + // + // TODO: This could be made into a Vec or something such that + // the user can compose multiple fills with alpha values less + // than one to achieve cool effects. pub fill: Fill, } @@ -256,15 +255,7 @@ pub struct Geometry { #[derive(Debug, Clone, PartialEq)] pub enum Shape { /// A rectangle. - Rect(Rect), - // Ellipse(Ellipse), -} - -/// An rectangle. -#[derive(Debug, Clone, PartialEq)] -pub struct Rect { - /// The dimensions of the rectangle. - pub size: Size, + Rect(Size), } /// An image element. diff --git a/src/layout/rect.rs b/src/layout/rect.rs deleted file mode 100644 index ab8e3b07..00000000 --- a/src/layout/rect.rs +++ /dev/null @@ -1,71 +0,0 @@ -use std::cmp::Ordering; - -use super::*; -use crate::{color::RgbaColor, geom::Linear}; - -/// A node that represents a rectangular box. -#[derive(Debug, Clone, PartialEq)] -pub struct NodeRect { - /// The fixed width, if any. - pub width: Option, - /// The fixed height, if any. - pub height: Option, - /// The background color. - pub color: Option, - /// The child node whose sides to pad. - pub child: Node, -} - -impl Layout for NodeRect { - fn layout(&self, ctx: &mut LayoutContext, areas: &Areas) -> Layouted { - let Areas { current, full, .. } = areas; - - let height_opt = self.height.map(|h| h.resolve(full.height)); - let mut size = Size::new( - self.width.map(|w| w.resolve(full.width)).unwrap_or(current.width), - height_opt.unwrap_or(current.height), - ); - - let areas = Areas::once(size); - let mut layouted = self.child.layout(ctx, &areas); - - // If the children have some height, apply that, - // otherwise fall back to zero or the height property. - if let Some(max) = layouted - .frames() - .iter() - .map(|f| f.size.height) - .max_by(|x, y| x.partial_cmp(y).unwrap_or(Ordering::Equal)) - { - size.height = max; - } else { - size.height = height_opt.unwrap_or(Length::ZERO) - } - - if let Some(first) = layouted.frames_mut().first_mut() { - first.elements.insert( - 0, - ( - Point::ZERO, - Element::Geometry(Geometry { - shape: Shape::Rect(Rect { size }), - fill: Fill::Color(self.color.unwrap_or(Color::Rgba(RgbaColor { - r: 255, - g: 255, - b: 255, - a: 0, - }))), - }), - ), - ) - } - - layouted - } -} - -impl From for NodeAny { - fn from(pad: NodeRect) -> Self { - Self::new(pad) - } -} -- cgit v1.2.3 From a6cae89b47246a235ed7b1093747c6f3bcb64da4 Mon Sep 17 00:00:00 2001 From: Martin Haug Date: Sat, 6 Feb 2021 12:54:44 +0100 Subject: =?UTF-8?q?Generalize=20child=20of=20NodeBackground=20=F0=9F=8D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layout/background.rs | 4 ++-- src/layout/mod.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/layout') diff --git a/src/layout/background.rs b/src/layout/background.rs index 94d5bf45..07248e02 100644 --- a/src/layout/background.rs +++ b/src/layout/background.rs @@ -5,8 +5,8 @@ use super::*; pub struct NodeBackground { /// The background fill. pub fill: Fill, - /// The child node whose sides to pad. - pub child: NodeFixed, + /// The child node to be filled in. + pub child: Node, } impl Layout for NodeBackground { diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 0c7a6a68..30295841 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -1,10 +1,10 @@ //! Layouting. +mod background; mod fixed; mod node; mod pad; mod par; -mod background; mod spacing; mod stack; mod text; @@ -14,11 +14,11 @@ use crate::env::{Env, ResourceId}; use crate::geom::*; use crate::shaping::Shaped; +pub use background::*; pub use fixed::*; pub use node::*; pub use pad::*; pub use par::*; -pub use background::*; pub use spacing::*; pub use stack::*; pub use text::*; -- cgit v1.2.3