From 4288f604410672d9632039e03fd9ae51bf4a6fcc Mon Sep 17 00:00:00 2001 From: Rushmore75 Date: Tue, 11 Nov 2025 13:42:36 -0700 Subject: [PATCH] broken scrolling --- src/app/app.rs | 59 +++++++++++++++++++--------------- src/app/calc.rs | 2 +- src/app/mod.rs | 3 +- src/app/mode.rs | 4 +-- src/app/screen.rs | 80 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 117 insertions(+), 31 deletions(-) create mode 100644 src/app/screen.rs diff --git a/src/app/app.rs b/src/app/app.rs index 61988cf..76d6229 100644 --- a/src/app/app.rs +++ b/src/app/app.rs @@ -12,7 +12,7 @@ use ratatui::{ use crate::app::{ calc::{Grid, LEN}, error_msg::ErrorMessage, - mode::{Chord, Mode}, + mode::{Chord, Mode}, screen::ScreenSpace, }; pub struct App { @@ -22,28 +22,13 @@ pub struct App { pub file: Option, pub error_msg: ErrorMessage, pub vars: HashMap, + pub screen: ScreenSpace, } impl Widget for &App { fn render(self, area: prelude::Rect, buf: &mut prelude::Buffer) { - let len = LEN as u16; - let mut cell_height = 1; - let mut cell_length = 10; - - if let Some(h) = self.vars.get("height") { - if let Ok(p) = h.parse::() { - cell_height = p; - } - } - if let Some(l) = self.vars.get("length") { - if let Ok(p) = l.parse::() { - cell_length = p; - } - } - - let x_max = if area.width / cell_length > len { len - 1 } else { area.width / cell_length }; - let y_max = if area.height / cell_height > len { len - 1 } else { area.height / cell_height }; + let (x_max, y_max) = self.screen.how_many_cells_fit_in(&area, &self.vars); let is_selected = |x: usize, y: usize| -> bool { if let Mode::Visual((mut x1, mut y1)) = self.mode { @@ -74,11 +59,11 @@ impl Widget for &App { // to index the grid, these are you values. let mut x_idx: usize = 0; let mut y_idx: usize = 0; - if y != 0 { - y_idx = y as usize - 1; - } if x != 0 { - x_idx = x as usize - 1; + x_idx = x as usize - 1 + self.screen.scroll_x(); + } + if y != 0 { + y_idx = y as usize - 1 + self.screen.y(); } if is_selected(x.into(), y.into()) { @@ -136,8 +121,10 @@ impl Widget for &App { } else { // the formula is broken display = e.to_owned(); - style = - Style::new().fg(Color::Red).underline_color(Color::Red).add_modifier(Modifier::UNDERLINED) + style = Style::new() + .fg(Color::Red) + .underline_color(Color::Red) + .add_modifier(Modifier::UNDERLINED) } } } @@ -151,8 +138,14 @@ impl Widget for &App { } } } - - let area = Rect::new(area.x + (x * cell_length), area.y + (y * cell_height), cell_length, cell_height); + let w = self.screen.get_cell_width(&self.vars) as u16; + let h = self.screen.get_cell_height(&self.vars) as u16; + let area = Rect::new( + area.x + (x * w), + area.y + (y * h), + w, + h, + ); Paragraph::new(display).style(style).render(area, buf); } @@ -169,6 +162,7 @@ impl App { file: None, error_msg: ErrorMessage::none(), vars: HashMap::new(), + screen: ScreenSpace::new(), } } @@ -218,9 +212,22 @@ impl App { frame.render_widget(self, body); frame.render_widget(&self.error_msg, cmd_line_right); + #[cfg(debug_assertions)] + frame.render_widget(Paragraph::new(format!("x/w y/h: cursor{:?} scroll({}, {}) cell({}, {}) screen({}, {})", + self.grid.selected_cell, + self.screen.scroll_x(), + self.screen.y(), + self.screen.get_cell_width(&self.vars), + self.screen.get_cell_height(&self.vars), + body.width, + body.height, + )), cmd_line_right); } fn handle_events(&mut self) -> io::Result<()> { + // make sure cursor is inside window + self.screen.scroll_based_on_cursor_location(self.grid.selected_cell, &self.vars); + match &mut self.mode { Mode::Chord(chord) => match event::read()? { event::Event::Key(key) => match key.code { diff --git a/src/app/calc.rs b/src/app/calc.rs index 045d843..dad6dc7 100644 --- a/src/app/calc.rs +++ b/src/app/calc.rs @@ -4,7 +4,7 @@ use evalexpr::*; use crate::app::ctx; -pub const LEN: usize = 100; +pub const LEN: usize = 1000; pub struct Grid { // a b c ... diff --git a/src/app/mod.rs b/src/app/mod.rs index 5c735a6..adf4ca6 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -2,4 +2,5 @@ pub mod app; mod calc; mod mode; mod error_msg; -mod ctx; \ No newline at end of file +mod ctx; +mod screen; \ No newline at end of file diff --git a/src/app/mode.rs b/src/app/mode.rs index 0618b15..4a9a902 100644 --- a/src/app/mode.rs +++ b/src/app/mode.rs @@ -4,9 +4,7 @@ use std::{ }; use ratatui::{ - prelude, - style::{Color, Style}, - widgets::{Paragraph, Widget}, + layout::Rect, prelude, style::{Color, Style}, widgets::{Paragraph, Widget} }; use crate::app::{app::App, calc::LEN, error_msg::ErrorMessage}; diff --git a/src/app/screen.rs b/src/app/screen.rs new file mode 100644 index 0000000..d096eb8 --- /dev/null +++ b/src/app/screen.rs @@ -0,0 +1,80 @@ +use std::{collections::HashMap, sync::RwLock}; + +use ratatui::{layout::Rect, prelude}; + +use crate::app::calc::LEN; + +pub struct ScreenSpace { + /// This is measured in cells + scroll: (usize, usize), + default_cell_len: usize, + default_cell_hight: usize, + /// This is measured in chars + last_seen_screen_size: RwLock<(usize, usize)> +} + +impl ScreenSpace { + pub fn new() -> Self { + Self { + scroll: (0, 0), + default_cell_len: 10, + default_cell_hight: 1, + last_seen_screen_size: RwLock::new((0,0)) + } + } + + pub fn scroll_based_on_cursor_location(&mut self, (cursor_x, cursor_y): (usize, usize), vars: &HashMap) { + if let Ok(screen_size) = self.last_seen_screen_size.read() { + + // screen seems to be 2 cells smaller than it should be + let x_cells = (screen_size.0 / self.get_cell_width(vars) as usize)-2; + + let lower_x = self.scroll_x(); + let upper_x = self.scroll_x() + x_cells; + + if cursor_x<=lower_x { + self.scroll.0 = self.scroll.0.saturating_sub(1); + } + if cursor_x > upper_x { + self.scroll.0 = self.scroll.0.saturating_add(1); + } + + } + } + + pub fn scroll_x(&self) -> usize { + self.scroll.0 + } + pub fn y(&self) -> usize{ + self.scroll.1 + } + pub fn get_cell_height(&self, vars: &HashMap) -> usize { + if let Some(h) = vars.get("height") { + if let Ok(p) = h.parse::() { + return p; + } + } + return self.default_cell_hight + } + pub fn get_cell_width(&self, vars: &HashMap) -> usize { + if let Some(h) = vars.get("length") { + if let Ok(p) = h.parse::() { + return p; + } + } + self.default_cell_len + } + pub fn how_many_cells_fit_in(&self, area: &prelude::Rect, vars: &HashMap) -> (u16, u16) { + if let Ok(mut l) = self.last_seen_screen_size.write() { + l.0 = area.width as usize; + l.1 = area.height as usize; + } + + let x_max = + if area.width as usize / self.get_cell_width(vars) > LEN { LEN - 1 } else { area.width as usize / self.get_cell_width(vars)}; + let y_max = + if area.height as usize / self.get_cell_height(vars) > LEN { LEN - 1 } else { area.height as usize / self.get_cell_height(vars)}; + (x_max as u16, y_max as u16) + } +} +