From 033d2d973a3aacd7cee63624dbac33e20ab47c7e Mon Sep 17 00:00:00 2001 From: Austen Adler Date: Mon, 18 Sep 2023 22:11:16 -0400 Subject: [PATCH] Cleanup input --- rpn_rs_gui/src/app.rs | 315 ++++++++++++++++++++++-------------------- 1 file changed, 169 insertions(+), 146 deletions(-) diff --git a/rpn_rs_gui/src/app.rs b/rpn_rs_gui/src/app.rs index f79bbaf..06d1b0b 100644 --- a/rpn_rs_gui/src/app.rs +++ b/rpn_rs_gui/src/app.rs @@ -1,4 +1,4 @@ -use egui::{Button, Color32, FontId, Grid, Key, RichText, Rounding, Stroke, Vec2}; +use egui::{Button, Color32, FontId, Frame, Grid, Key, Label, RichText, Rounding, Stroke, Vec2}; use rpn_rs::calc::{errors::CalculatorError, Calculator}; use tracing::{error, info}; @@ -19,6 +19,9 @@ pub struct TemplateApp { #[serde(skip)] latest_error: Option, + + #[serde(skip)] + error_state: ErrorState, } impl Default for TemplateApp { @@ -28,6 +31,7 @@ impl Default for TemplateApp { // Example stuff: label: "Hello World!".to_owned(), latest_error: None, + error_state: ErrorState::default(), } } } @@ -47,11 +51,77 @@ impl TemplateApp { Default::default() } - fn calculator_input(&mut self, c: char, error_state: &mut ErrorState) { + fn calculator_input(&mut self, c: char) { if let Err(e) = self.calculator.take_input(c) { - error_state.errored(e); + self.error_state.errored(e); } else { - error_state.success(); + self.error_state.success(); + } + } + + fn handle_input(&mut self, i: &egui::InputState) { + if i.events.is_empty() { + return; + } + + for e in i.events.iter() { + match e { + egui::Event::Text(t) => { + self.calculator_input(t.chars().next().unwrap()); + } + egui::Event::Key { + key: Key::ArrowLeft, + pressed: true, + .. + } => { + self.calculator_input('<'); + } + egui::Event::Key { + key: Key::ArrowRight, + pressed: true, + .. + } => { + self.calculator_input('>'); + } + egui::Event::Key { + key: Key::Enter, + pressed: true, + .. + } => { + self.calculator_input(' '); + } + + egui::Event::Copy => continue, + egui::Event::Cut => continue, + egui::Event::Paste(_) => continue, + egui::Event::Key { + key: _, + pressed: _, + repeat: _, + modifiers: _, + } => continue, + egui::Event::PointerMoved(_) => continue, + egui::Event::PointerButton { + pos: _, + button: _, + pressed: _, + modifiers: _, + } => continue, + egui::Event::PointerGone => continue, + egui::Event::Scroll(_) => continue, + egui::Event::Zoom(_) => continue, + egui::Event::CompositionStart => continue, + egui::Event::CompositionUpdate(_) => continue, + egui::Event::CompositionEnd(_) => continue, + egui::Event::Touch { + device_id: _, + id: _, + phase: _, + pos: _, + force: _, + } => continue, + egui::Event::AccessKitActionRequest(_) => continue, + } } } } @@ -84,153 +154,101 @@ impl eframe::App for TemplateApp { }); }); - let mut error_state = ErrorState::NoModify; + self.error_state = ErrorState::default(); egui::CentralPanel::default().show(ctx, |ui| { ui.style_mut().spacing.button_padding = BUTTON_PADDING; // The central panel the region left after adding TopPanel's and SidePanel's - ui.heading("rpn_rs_gui"); - ui.hyperlink("https://gitea.austen-wares.com/stonewareslord/rpn_rs"); + ui.input(|i: &egui::InputState| self.handle_input(i)); - ui.input(|i| { - if i.events.is_empty() { - return; - } + Frame::none().fill(Color32::GREEN).show(ui, |ui| { + ui.vertical(|ui| { + ui.heading("rpn_rs_gui"); + ui.hyperlink("https://gitea.austen-wares.com/stonewareslord/rpn_rs"); - for e in i.events.iter() { - match e { - egui::Event::Text(t) => { - self.calculator_input(t.chars().next().unwrap(), &mut error_state); - } - egui::Event::Key { - key: Key::ArrowLeft, - pressed: true, - .. - } => { - self.calculator_input('<', &mut error_state); - } - egui::Event::Key { - key: Key::ArrowRight, - pressed: true, - .. - } => { - self.calculator_input('>', &mut error_state); - } - egui::Event::Key { - key: Key::Enter, - pressed: true, - .. - } => { - self.calculator_input(' ', &mut error_state); + // Buttons + Grid::new("grid").spacing(BUTTON_SPACING).show(ui, |ui| { + for row in BUTTON_LAYOUT.iter() { + for button in row.iter() { + let label = RichText::new(button.value) + .font(DEFAULT_FONT) + .color(Color32::WHITE); + if ui + .add( + Button::new(label) + // .frame(false) + .stroke(Stroke::NONE) + .rounding(Rounding::none()) + .fill(Color32::from_gray(0x12)), + ) + .clicked() + { + info!("Clicked button {}", button.value); + self.calculator_input(button.value); + // if let Err(e) = self.calculator.take_input(button.value) { + // error!("Calculator input error: {e:?}"); + // self.latest_error = Some(e); + // fresh_error = true; + // } else if !fresh_error { + // self.latest_error = None; + // } + } + } + ui.end_row(); } + }); - egui::Event::Copy => continue, - egui::Event::Cut => continue, - egui::Event::Paste(_) => continue, - egui::Event::Key { - key: _, - pressed: _, - repeat: _, - modifiers: _, - } => continue, - egui::Event::PointerMoved(_) => continue, - egui::Event::PointerButton { - pos: _, - button: _, - pressed: _, - modifiers: _, - } => continue, - egui::Event::PointerGone => continue, - egui::Event::Scroll(_) => continue, - egui::Event::Zoom(_) => continue, - egui::Event::CompositionStart => continue, - egui::Event::CompositionUpdate(_) => continue, - egui::Event::CompositionEnd(_) => continue, - egui::Event::Touch { - device_id: _, - id: _, - phase: _, - pos: _, - force: _, - } => continue, - egui::Event::AccessKitActionRequest(_) => continue, - } - } - }); - - Grid::new("grid").spacing(BUTTON_SPACING).show(ui, |ui| { - for row in BUTTON_LAYOUT.iter() { - for button in row.iter() { - let label = RichText::new(button.value).font(DEFAULT_FONT); - if ui - .add( - Button::new(label) - .stroke(Stroke::NONE) - .rounding(Rounding::none()), - ) - .clicked() - { - info!("Clicked button {}", button.value); - self.calculator_input(button.value, &mut error_state); - // if let Err(e) = self.calculator.take_input(button.value) { - // error!("Calculator input error: {e:?}"); - // self.latest_error = Some(e); - // fresh_error = true; - // } else if !fresh_error { - // self.latest_error = None; - // } - } - } - ui.end_row(); - } - }); - - ui.label( - RichText::new( - self.calculator - .stack - .iter() - .rev() - .map(|e| e.to_string()) - .collect::>() - .join("\n"), - ) - .background_color(egui::Color32::RED) - .font(DEFAULT_FONT) - .size(STACK_FONT_SIZE) - .color(Color32::WHITE), - ); - - egui::Frame::none() - .fill(egui::Color32::RED) - .inner_margin(5.0) - .stroke(Stroke::new(10.0, Color32::BLUE)) - .show(ui, |ui| { - ui.label( - RichText::new(self.calculator.get_l()) - .color(Color32::WHITE) - .font(DEFAULT_FONT), - ); - }); - - match error_state { - ErrorState::NoModify => {} - ErrorState::Errored(e) => self.latest_error = Some(e), - ErrorState::Clear => self.latest_error = None, - } - - if let Some(ref e) = self.latest_error { - ui.label( - RichText::new(e.to_string()) + // Stack + // ui.add_sized( Vec2::new(ui.available_width(), ui.available_height()), + ui.add(Label::new( + RichText::new( + self.calculator + .stack + .iter() + .rev() + .map(|e| e.to_string()) + .collect::>() + .join("\n"), + ) + .background_color(egui::Color32::RED) .font(DEFAULT_FONT) .size(STACK_FONT_SIZE) - .color(Color32::RED), - ); - } + .color(Color32::WHITE), + )); - egui::warn_if_debug_build(ui); + egui::Frame::none() + .fill(egui::Color32::RED) + .inner_margin(5.0) + .stroke(Stroke::new(10.0, Color32::BLUE)) + .show(ui, |ui| { + ui.label( + RichText::new(self.calculator.get_l()) + .color(Color32::WHITE) + .font(DEFAULT_FONT), + ); + }); + + // Reset the error state and update `self.latest_error` if required + match std::mem::take(&mut self.error_state) { + ErrorState::NoModify => {} + ErrorState::Errored(e) => self.latest_error = Some(e), + ErrorState::Clear => self.latest_error = None, + } + + if let Some(ref e) = self.latest_error { + ui.label( + RichText::new(e.to_string()) + .font(DEFAULT_FONT) + .size(STACK_FONT_SIZE) + .color(Color32::RED), + ); + } + + egui::warn_if_debug_build(ui); + }); + }) }); // if false { @@ -257,49 +275,49 @@ impl CalculatorButton { const BUTTON_LAYOUT: &[&[CalculatorButton]] = &[ &[ - CalculatorButton::new('s', "Sin"), + // CalculatorButton::new('s', "Sin"), CalculatorButton::new('u', "Undo"), CalculatorButton::new('U', "Redo"), CalculatorButton::new('>', "Swap"), - // CalculatorButton::new('\\', "Drop"), + CalculatorButton::new('@', "Drop"), ], &[ - CalculatorButton::new('|', "AbsoluteValue"), + // CalculatorButton::new('|', "AbsoluteValue"), CalculatorButton::new('v', "Sqrt"), CalculatorButton::new('^', "Pow"), CalculatorButton::new('l', "Log"), CalculatorButton::new('L', "Ln"), ], &[ - CalculatorButton::new('c', "Cos"), + // CalculatorButton::new('c', "Cos"), CalculatorButton::new('n', "Negate"), CalculatorButton::new('%', "Modulo"), CalculatorButton::new('i', "Inverse"), CalculatorButton::new('/', "Divide"), ], &[ - CalculatorButton::new('t', "Tan"), + // CalculatorButton::new('t', "Tan"), CalculatorButton::new('7', "7"), CalculatorButton::new('8', "8"), CalculatorButton::new('9', "9"), CalculatorButton::new('*', "Multiply"), ], &[ - CalculatorButton::new('S', "ASin"), + // CalculatorButton::new('S', "ASin"), CalculatorButton::new('4', "4"), CalculatorButton::new('5', "5"), CalculatorButton::new('6', "6"), CalculatorButton::new('-', "Subtract"), ], &[ - CalculatorButton::new('C', "ACos"), + // CalculatorButton::new('C', "ACos"), CalculatorButton::new('1', "1"), CalculatorButton::new('2', "2"), CalculatorButton::new('3', "3"), CalculatorButton::new('+', "Add"), ], &[ - CalculatorButton::new('T', "ATan"), + // CalculatorButton::new('T', "ATan"), CalculatorButton::new('0', "0"), CalculatorButton::new('\\', "Drop"), CalculatorButton::new('.', "Decimal"), @@ -347,3 +365,8 @@ impl ErrorState { } } } +impl Default for ErrorState { + fn default() -> ErrorState { + ErrorState::NoModify + } +}