use alloc::vec::Vec;
use calc_common::{Button, Character, ExtendedCharacter, GetButton, MetaButton};
use calc_parser::lexer::Lexer;
use crate::{
drawing::{self, ScreenBuffer},
math::{self, CalcEvaluator},
};
#[derive(Default)]
struct CalcExpression {
pub expression: Vec<Character>,
pub answer: Option<Vec<Character>>,
}
impl CalcExpression {
pub fn draw(&self, map: &mut ScreenBuffer) {
let expression: &[Character] = &self.expression;
drawing::draw_text_at(map, expression, 1, 1);
drawing::draw_hline(map, 128, 0, 10);
if let Some(answer) = &self.answer {
drawing::draw_text_at(
map,
answer,
(128 - drawing::get_text_width(answer)) as u16,
1,
);
}
}
}
pub struct EvaluationMenuPersistentData {
cursor_position: usize,
current_expression: CalcExpression,
}
#[derive(Default)]
pub struct EvaluationMenuState;
impl Default for EvaluationMenuPersistentData {
fn default() -> Self {
let cursor_position = 0;
let current_expression = Default::default();
Self {
cursor_position,
current_expression,
}
}
}
impl EvaluationMenuState {
pub fn draw(&self, screen: &mut ScreenBuffer, persistent_data: &EvaluationMenuPersistentData) {
screen.clear();
drawing::draw_sprite_at(
screen,
ExtendedCharacter::Cursor,
(&persistent_data.cursor_position * 5) as u16,
1,
);
persistent_data.current_expression.draw(screen);
}
}
impl EvaluationMenuState {
pub fn on_button_press(
&mut self,
screen: &mut ScreenBuffer,
button: Button,
persistent_data: &mut EvaluationMenuPersistentData,
) {
match button.get() {
GetButton::Character(char) => {
persistent_data
.current_expression
.expression
.insert(persistent_data.cursor_position, char);
persistent_data.cursor_position += 1
}
GetButton::Meta(MetaButton::Enter) => {
let mut lexer = Lexer::<CalcEvaluator, _>::new(
persistent_data
.current_expression
.expression
.iter()
.copied(),
);
let res = calc_parser::parse_and_evaluate::<CalcEvaluator, _>(&mut lexer);
match res {
Ok(ok) => {
persistent_data.current_expression.answer = Some(math::number_to_chars(ok))
}
Err(_err) => todo!("Calculator error handling todo"),
};
}
GetButton::Meta(MetaButton::Back) => {
if persistent_data.cursor_position != 0 {
persistent_data
.current_expression
.expression
.remove(persistent_data.cursor_position - 1);
persistent_data.cursor_position -= 1;
}
}
GetButton::Meta(MetaButton::Left) => {
persistent_data.cursor_position = persistent_data.cursor_position.saturating_sub(1);
}
GetButton::Meta(MetaButton::Right) => {
persistent_data.cursor_position = (persistent_data.cursor_position + 1)
.min(persistent_data.current_expression.expression.len());
}
GetButton::Meta(MetaButton::Clear) => {
persistent_data.current_expression.expression.clear();
persistent_data.current_expression.answer = None;
persistent_data.cursor_position = 0;
}
_ => todo!(),
}
self.draw(screen, persistent_data)
}
}