pub mod function_cache; pub mod math; pub mod ui; use function_cache::FunctionCache; use iced::{executor, Renderer}; use iced::widget::{canvas, container, pane_grid, responsive, text, text_input, PaneGrid}; use iced::{Application, Command, Element, Length, Settings, Theme}; use math::expression_function::ExpressionFunction; use std::sync::Mutex; use ui::graph::GraphCanvas; use ui::Message; use ui::pane::{Pane, PaneKind}; pub fn main() -> iced::Result { Graph::run(Settings { antialiasing: true, ..Settings::default() }) } struct Graph { panes: pane_grid::State, input_state: String, graph_canvas: GraphCanvas, } impl Application for Graph { type Executor = executor::Default; type Message = Message; type Theme = Theme; type Flags = (); fn new(_flags: ()) -> (Self, Command) { let (mut panes, pane) = pane_grid::State::new(Pane::new(PaneKind::FunctionPane)); panes.split( pane_grid::Axis::Vertical, &pane, Pane::new(PaneKind::GraphPane), ); let default_func = "f(x) = x^2".to_string(); ( Graph { graph_canvas: GraphCanvas::new(&default_func), input_state: default_func, panes, }, Command::none(), ) } fn title(&self) -> String { String::from("MathEval") } fn update(&mut self, message: Message) -> Command { match message { Message::InputChanged(s) => { self.input_state = s; } Message::UpdateFunction => { let func = ExpressionFunction::from_string( self.input_state.clone(), self.graph_canvas.ctx.operations(), ); self.graph_canvas.func = Mutex::new(FunctionCache::new(func)); self.graph_canvas.clear(); } Message::UpdateScreen => { self.graph_canvas.clear(); } Message::Resized(pane_grid::ResizeEvent { split, ratio }) => { self.panes.resize(&split, ratio); } } Command::none() } fn view(&self) -> Element { let pane_grid = PaneGrid::new(&self.panes, |_id, pane, _| { pane_grid::Content::new(responsive(move |_size| { let child : Element<'_, Message, Renderer> = match pane.kind { PaneKind::GraphPane => { canvas(&self.graph_canvas) .width(Length::Fill) .height(Length::Fill).into() } PaneKind::FunctionPane => { text_input("x", &self.input_state) .on_input(Message::InputChanged) .on_submit(Message::UpdateFunction) .padding(15) .size(30).into() }, _ => text("").into(), }; container(child) .width(Length::Fill) .height(Length::Fill) .into() })) }) .width(Length::Fill) .height(Length::Fill) .spacing(10) .on_resize(10, Message::Resized); container(pane_grid) .width(Length::Fill) .height(Length::Fill) .padding(10) .into() } }