use std::sync::{Arc, RwLock}; use cacao::appkit::App; use cacao::lazy_static::lazy_static; use crate::CalculatorApp; #[derive(Clone, Debug)] pub enum Msg { Push(i32), Add, Subtract, Multiply, Divide, Decimal, Clear, Mod, Invert, Equals, } /// Asynchronously calls back through to the top of the application /// on the main thread. pub fn dispatch(msg: Msg) { println!("Dispatching UI message: {:?}", msg); CALCULATOR.run(msg) } lazy_static! { pub static ref CALCULATOR: Calculator = Calculator::new(); } #[derive(Debug)] pub struct Calculator(Arc>>); impl Calculator { pub fn new() -> Self { Calculator(Arc::new(RwLock::new(Vec::new()))) } pub fn run(&self, message: Msg) { let mut expression = self.0.write().unwrap(); match message { Msg::Push(i) => { // Realistically you might want to check decimal length here or something. // We're not bothering for this example. (*expression).push(i.to_string()); let display = (*expression).join("").split(" ").last().unwrap_or("0").to_string(); App::::dispatch_main(display); }, Msg::Decimal => { let display = (*expression).join("").split(" ").last().unwrap_or("0").to_string(); if !display.contains(".") { (*expression).push(".".to_string()); App::::dispatch_main(display + "."); } }, Msg::Add => { if let Some(last_entry) = (*expression).last() { if !last_entry.ends_with(" ") { (*expression).push(" + ".to_string()); } } }, Msg::Subtract => { (*expression).push(" - ".to_string()); }, Msg::Multiply => { (*expression).push(" * ".to_string()); }, Msg::Divide => { (*expression).push(" / ".to_string()); }, Msg::Clear => { (*expression) = Vec::new(); App::::dispatch_main("0".to_string()) }, Msg::Equals => { let mut expr = (*expression).join(""); if expr.ends_with(" ") { expr.truncate(expr.len() - 3); } println!("Expr: {}", expr); match eval::eval(&expr) { Ok(val) => { App::::dispatch_main(val.to_string()); }, Err(e) => { eprintln!("Error parsing expression: {:?}", e); }, } }, _ => {}, } } }