use std::rc::Rc; use clay_layout::{ Declaration, fit, grow, layout::{ Alignment, LayoutAlignmentX, LayoutAlignmentY, LayoutDirection::{self, TopToBottom}, Padding, }, text::{TextConfig, TextElementConfig}, }; use libopenbirch::node::NodeEnum; use super::{Document, State}; pub struct Line { pub segments: Vec, } impl From for Line { fn from(value: String) -> Self { Line { segments: vec![LineSegment::Text(value, 20)], } } } impl Line { pub fn draw<'a>(&'a mut self, clay: &'a clay_layout::Clay, theme: &Theme, state: &'a State) { for segment in self.segments.iter_mut() { segment.draw(clay, theme, state); } } } pub struct Theme { pub text_color: clay_layout::color::Color, pub text_font: u16, pub math_color: clay_layout::color::Color, pub math_font: u16, } pub enum LineSegment { Text(String, u16), // Link(String, Link), Math(String, Rc, u16), } impl LineSegment { pub fn draw<'a>(&'a mut self, clay: &'a clay_layout::Clay, theme: &'a Theme, state: &'a State) { match self { LineSegment::Text(text, font_size) => clay.text( text.as_str(), TextConfig::new() .font_id(theme.text_font) .font_size(*font_size) .color(theme.text_color) .end(), ), LineSegment::Math(_source, node_enum, font_size) => { draw_math_enum(node_enum.clone(), clay, theme, *font_size, state); } } } } fn draw_binary( symbol: &'static str, left: Rc, right: Rc, font_size: u16, clay: &clay_layout::Clay, theme: &Theme, state: &State, ) { clay.with( &Declaration::new() .layout() .direction(LayoutDirection::LeftToRight) .width(fit!(0.)) .height(fit!(0.)) .child_alignment(Alignment::new( LayoutAlignmentX::Center, LayoutAlignmentY::Center, )) .padding(Padding::new(2, 2, 3, 3)) .end(), |clay| { // Left side draw_math_enum(left, clay, theme, font_size, state); // add symbol clay.text( symbol, TextConfig::new() .color(theme.math_color) .font_size(font_size) .font_id(theme.math_font) .end(), ); // Right side draw_math_enum(right, clay, theme, font_size, state); }, ) } fn draw_math_enum<'a>( node: Rc, clay: &'a clay_layout::Clay, theme: &'a Theme, font_size: u16, state: &'a State, ) { match node.as_ref() { NodeEnum::Constant(constant) => { let str = std::mem::ManuallyDrop::new(constant.get_value().to_string()); clay.text( str.as_str(), TextConfig::new() .color(theme.math_color) .font_size(font_size) .font_id(theme.math_font) .end(), ) } NodeEnum::Add(add) => draw_binary( " + ", add.get_left(), add.get_right(), font_size, clay, theme, state, ), NodeEnum::Subtract(sub) => draw_binary( " - ", sub.get_left(), sub.get_right(), font_size, clay, theme, state, ), NodeEnum::Multiply(mul) => draw_binary( "× ", mul.get_left(), mul.get_right(), font_size, clay, theme, state, ), NodeEnum::Assign(assign) => draw_binary( " := ", assign.get_left(), assign.get_right(), font_size, clay, theme, state, ), NodeEnum::Divide(divide) => clay.with( &Declaration::new() .layout() .direction(TopToBottom) .width(fit!(0.)) .height(fit!(0.)) .child_alignment(Alignment::new( LayoutAlignmentX::Center, LayoutAlignmentY::Center, )) .padding(Padding::new(4, 4, 2, 2)) .end(), |clay| { // Left side draw_math_enum(divide.get_left(), clay, theme, font_size, state); // Seperator bar clay.with( &Declaration::new() .layout() .width(grow!(0.)) .height(fit!(1.)) .end() .background_color(theme.math_color), |_| {}, ); // Right side draw_math_enum(divide.get_right(), clay, theme, font_size, state); }, ), NodeEnum::Symbol(symbol) => todo!(), NodeEnum::Function(function) => todo!(), NodeEnum::Call(call) => todo!(), NodeEnum::Empty(empty) => {} } }