diff --git a/src/func.rs b/src/func.rs index a7044b6e9..14dd5bebc 100644 --- a/src/func.rs +++ b/src/func.rs @@ -37,20 +37,20 @@ impl PartialEq for dyn Function { /// A sequence of commands requested for execution by a function. #[derive(Debug)] -pub struct FuncCommands { - pub commands: Vec +pub struct FuncCommands<'a> { + pub commands: Vec> } -impl FuncCommands { +impl<'a> FuncCommands<'a> { /// Create an empty command list. - pub fn new() -> FuncCommands { + pub fn new() -> FuncCommands<'a> { FuncCommands { commands: vec![], } } /// Add a command to the sequence. - pub fn add_command(&mut self, command: Command) { + pub fn add(&mut self, command: Command<'a>) { self.commands.push(command); } @@ -60,9 +60,9 @@ impl FuncCommands { } } -impl IntoIterator for FuncCommands { - type Item = Command; - type IntoIter = std::vec::IntoIter; +impl<'a> IntoIterator for FuncCommands<'a> { + type Item = Command<'a>; + type IntoIter = std::vec::IntoIter>; fn into_iter(self) -> Self::IntoIter { self.commands.into_iter() @@ -71,8 +71,8 @@ impl IntoIterator for FuncCommands { /// Commands requested for execution by functions. #[derive(Debug)] -pub enum Command { - Layout(SyntaxTree), +pub enum Command<'a> { + Layout(&'a SyntaxTree), Add(Layout), AddMany(MultiLayout), ToggleStyleClass(FontClass), diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 195433896..1bd11e148 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -81,6 +81,15 @@ impl MultiLayout { } } +impl IntoIterator for MultiLayout { + type Item = Layout; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.layouts.into_iter() + } +} + /// The context for layouting. #[derive(Copy, Clone)] pub struct LayoutContext<'a, 'p> { @@ -122,13 +131,14 @@ pub enum Alignment { } pub fn layout_tree(tree: &SyntaxTree, ctx: LayoutContext) -> LayoutResult { - Layouter::new(tree, ctx).layout() + let mut layouter = Layouter::new(ctx); + layouter.layout(tree)?; + layouter.finish() } /// Transforms a syntax tree into a box layout. struct Layouter<'a, 'p> { ctx: LayoutContext<'a, 'p>, - tree: &'a SyntaxTree, stack_layouter: StackLayouter, flex_layouter: FlexLayouter, style: Cow<'a, TextStyle>, @@ -136,10 +146,9 @@ struct Layouter<'a, 'p> { impl<'a, 'p> Layouter<'a, 'p> { /// Create a new layouter. - fn new(tree: &'a SyntaxTree, ctx: LayoutContext<'a, 'p>) -> Layouter<'a, 'p> { + fn new(ctx: LayoutContext<'a, 'p>) -> Layouter<'a, 'p> { Layouter { ctx, - tree, stack_layouter: StackLayouter::new(StackContext { space: ctx.space }), flex_layouter: FlexLayouter::new(FlexContext { space: LayoutSpace { @@ -155,9 +164,9 @@ impl<'a, 'p> Layouter<'a, 'p> { } /// Layout the tree into a box. - fn layout(mut self) -> LayoutResult { + fn layout(&mut self, tree: &SyntaxTree) -> LayoutResult<()> { // Walk all nodes and layout them. - for node in &self.tree.nodes { + for node in &tree.nodes { match node { // Layout a single piece of text. Node::Text(text) => self.layout_text(text, false)?, @@ -190,6 +199,10 @@ impl<'a, 'p> Layouter<'a, 'p> { } } + Ok(()) + } + + fn finish(mut self) -> LayoutResult { // If there are remainings, add them to the layout. if !self.flex_layouter.is_empty() { self.layout_flex()?; @@ -254,9 +267,9 @@ impl<'a, 'p> Layouter<'a, 'p> { for command in commands { match command { - Command::Layout(tree) => unimplemented!(), - Command::Add(layout) => unimplemented!(), - Command::AddMany(layouts) => unimplemented!(), + Command::Layout(tree) => self.layout(tree)?, + Command::Add(layout) => self.stack_layouter.add_box(layout)?, + Command::AddMany(layouts) => self.stack_layouter.add_many(layouts)?, Command::ToggleStyleClass(class) => self.style.to_mut().toggle_class(class), } } diff --git a/src/layout/stacked.rs b/src/layout/stacked.rs index 78eb0058b..312681ace 100644 --- a/src/layout/stacked.rs +++ b/src/layout/stacked.rs @@ -72,9 +72,17 @@ impl StackLayouter { Ok(()) } + /// Add multiple sublayouts. + pub fn add_many(&mut self, layouts: MultiLayout) -> LayoutResult<()> { + for layout in layouts { + self.add_box(layout)?; + } + Ok(()) + } + /// Add a sublayout at an absolute position. - pub fn add_box_absolute(&mut self, position: Size2D, layout: Layout) -> LayoutResult<()> { - Ok(self.actions.add_box(position, layout)) + pub fn add_box_absolute(&mut self, position: Size2D, layout: Layout) { + self.actions.add_box(position, layout); } /// Add space in between two boxes. diff --git a/src/library/align.rs b/src/library/align.rs index b1e41abb8..099daf888 100644 --- a/src/library/align.rs +++ b/src/library/align.rs @@ -38,13 +38,15 @@ impl Function for AlignFunc { Ok(AlignFunc { alignment, body }) } - fn layout(&self, ctx: LayoutContext) -> LayoutResult { + fn layout(&self, mut ctx: LayoutContext) -> LayoutResult { if let Some(body) = &self.body { - // // Override the previous alignment and do the layouting. - // ctx.space.alignment = self.alignment; - // layout(body, ctx) - // .map(|l| Some(Layout::Boxed(l))) - Ok(FuncCommands::new()) + ctx.space.alignment = self.alignment; + let layouts = layout_tree(body, ctx)?; + + let mut commands = FuncCommands::new(); + commands.add(Command::AddMany(layouts)); + + Ok(commands) } else { unimplemented!("context-modifying align func") } diff --git a/src/library/mod.rs b/src/library/mod.rs index acbd11db4..848ba8476 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -9,7 +9,7 @@ mod styles; pub mod prelude { pub use crate::syntax::{SyntaxTree, FuncHeader, Expression}; pub use crate::parsing::{parse, ParseContext, ParseResult, ParseError}; - pub use crate::layout::{layout_tree, layout_text, MultiLayout, Layout, LayoutContext}; + pub use crate::layout::{layout_tree, LayoutContext, MultiLayout, Layout}; pub use crate::layout::{LayoutResult, LayoutError}; pub use crate::func::{Function, Command, FuncCommands}; diff --git a/src/library/styles.rs b/src/library/styles.rs index 28cc0e480..85ae47898 100644 --- a/src/library/styles.rs +++ b/src/library/styles.rs @@ -1,13 +1,15 @@ //! Basic style functions: bold, italic, monospace. use super::prelude::*; -// use toddle::query::FontClass; - +use toddle::query::FontClass; macro_rules! style_func { - ($(#[$outer:meta])* pub struct $struct:ident { $name:expr }, - $style:ident => $style_change:block) => { + ( + $(#[$outer:meta])* + pub struct $struct:ident { $name:expr }, + $style:ident => $class:ident + ) => { $(#[$outer])* #[derive(Debug, PartialEq)] pub struct $struct { body: SyntaxTree } @@ -27,20 +29,14 @@ macro_rules! style_func { } } - fn layout(&self, ctx: LayoutContext) -> LayoutResult { - // // Change the context. - // let mut $style = ctx.style.clone(); - // $style_change + fn layout(&self, _: LayoutContext) -> LayoutResult { + let mut commands = FuncCommands::new(); - // // Create a box and put it into a flex layout. - // let boxed = layout(&self.body, LayoutContext { - // style: &$style, - // .. ctx - // })?; - // let flex = FlexLayout::from_box(boxed); + commands.add(Command::ToggleStyleClass(FontClass::$class)); + commands.add(Command::Layout(&self.body)); + commands.add(Command::ToggleStyleClass(FontClass::$class)); - // Ok(Some(Layout::Flex(flex))) - Ok(FuncCommands::new()) + Ok(commands) } } }; @@ -49,17 +45,17 @@ macro_rules! style_func { style_func! { /// Typesets text in bold. pub struct BoldFunc { "bold" }, - style => { style.toggle_class(FontClass::Bold) } + style => Bold } style_func! { /// Typesets text in italics. pub struct ItalicFunc { "italic" }, - style => { style.toggle_class(FontClass::Italic) } + style => Italic } style_func! { /// Typesets text in monospace. pub struct MonospaceFunc { "mono" }, - style => { style.toggle_class(FontClass::Monospace) } + style => Monospace }