Move functions to command-based architecture ✈
This commit is contained in:
parent
463e4ebd82
commit
e2d17aa9d9
20
src/func.rs
20
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<Command>
|
||||
pub struct FuncCommands<'a> {
|
||||
pub commands: Vec<Command<'a>>
|
||||
}
|
||||
|
||||
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<Command>;
|
||||
impl<'a> IntoIterator for FuncCommands<'a> {
|
||||
type Item = Command<'a>;
|
||||
type IntoIter = std::vec::IntoIter<Command<'a>>;
|
||||
|
||||
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),
|
||||
|
@ -81,6 +81,15 @@ impl MultiLayout {
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for MultiLayout {
|
||||
type Item = Layout;
|
||||
type IntoIter = std::vec::IntoIter<Layout>;
|
||||
|
||||
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<MultiLayout> {
|
||||
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<MultiLayout> {
|
||||
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<MultiLayout> {
|
||||
// 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),
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -38,13 +38,15 @@ impl Function for AlignFunc {
|
||||
Ok(AlignFunc { alignment, body })
|
||||
}
|
||||
|
||||
fn layout(&self, ctx: LayoutContext) -> LayoutResult<FuncCommands> {
|
||||
fn layout(&self, mut ctx: LayoutContext) -> LayoutResult<FuncCommands> {
|
||||
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")
|
||||
}
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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<FuncCommands> {
|
||||
// // Change the context.
|
||||
// let mut $style = ctx.style.clone();
|
||||
// $style_change
|
||||
fn layout(&self, _: LayoutContext) -> LayoutResult<FuncCommands> {
|
||||
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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user