pub mod function_cache; pub mod math; pub mod ui; use iced::widget::{ button, canvas, container, pane_grid, responsive, text, text_input, Column, PaneGrid, row, }; use iced::{executor, Renderer}; use iced::{Application, Command, Element, Length, Settings, Theme}; use ui::graph::GraphCanvas; use ui::pane::{Pane, PaneKind}; use ui::Message; pub fn main() -> iced::Result { Graph::run(Settings { antialiasing: true, ..Settings::default() }) } struct Graph { panes: pane_grid::State, func_vec: Vec, 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), ); ( Graph { graph_canvas: GraphCanvas::new(), func_vec: Vec::new(), panes, }, Command::none(), ) } fn title(&self) -> String { String::from("MathEval") } fn update(&mut self, message: Message) -> Command { match message { Message::InputChanged(content, i) => { self.func_vec[i] = content; } Message::AddFunction => { self.func_vec.push(String::new()); self.graph_canvas.push(""); } Message::RemoveFunction(i) => { self.func_vec.remove(i); self.graph_canvas.remove(i); self.graph_canvas.clear() } Message::UpdateFunction(i) => { self.graph_canvas.set(i, &self.func_vec[i]); self.graph_canvas.clear(); } Message::RefreshGraphCanvas => { self.graph_canvas.clear(); } Message::Resized(pane_grid::ResizeEvent { split, ratio }) => { self.graph_canvas.clear(); 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 => { let mut flist = Column::new(); for (i, f) in self.func_vec.iter().enumerate() { flist = flist.push( row![ text_input("f(x) = x^2", f) .on_input(move |s| Message::InputChanged(s, i)) .on_submit(Message::UpdateFunction(i)), button("-").on_press(Message::RemoveFunction(i)) ].padding(5) ); } flist = flist.push( button("+") .width(Length::Fill) .on_press(Message::AddFunction), ); flist.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() } fn theme(&self) -> Self::Theme { Theme::Dark } }