From 4791b3cfb936c2fdf59b9a7e356a6811001a5100 Mon Sep 17 00:00:00 2001 From: korin Date: Fri, 7 Apr 2023 03:22:00 -0400 Subject: [PATCH] cursor --- src/font_build.rs | 44 +++++++--- src/main.rs | 214 +++++++++++++++++++++++----------------------- 2 files changed, 135 insertions(+), 123 deletions(-) diff --git a/src/font_build.rs b/src/font_build.rs index 66ce765..289fc0b 100644 --- a/src/font_build.rs +++ b/src/font_build.rs @@ -30,8 +30,6 @@ fn read_file(file_name: String) -> Vec { pub fn generate_glyph_atlas() -> Vec { // Retrieve font data from file let file_path = String::from("./fonts/Terminus14x8.data"); - println!("In file {file_path}"); - let contents = read_file(file_path); // Get width of image for proper positioning of pixels @@ -39,9 +37,9 @@ pub fn generate_glyph_atlas() -> Vec { let width_right_byte = contents[1]; let number = [width_left_byte, width_right_byte]; let width = u16::from_be_bytes(number); - println!("Left Byte: {width_left_byte}, Right Byte: {width_right_byte}, Byte Pair: {width}"); - let gtable_prune = &contents[762..]; + + let gtable_prune = &contents[width as usize + 2 ..]; // Generate the glyph atlas let mut glyph_atlas: Vec = vec![]; @@ -59,22 +57,13 @@ pub fn generate_glyph_atlas() -> Vec { if gtable_prune[position] == 1 { new_glyph.push(Point::new(x as i32, y as i32)); } - - /* // Debug info - print!("Glyph num: {glyph:2.} | Addr: {p:3.} | Line: {multiplier:5.} | Pos: {position:5.}"); - - if gtable_prune[position] == 1 { - println!(" | X: {x:2.} | Y: {y:2.}"); - } else { - println!(); - } - */ } glyph_atlas.push(new_glyph); } glyph_atlas } +/// Method for generating points to render, using given string pub fn draw_text(content: &str, glyph_atlas: Vec) -> Vec { let mut points: Vec = vec![]; @@ -102,3 +91,30 @@ pub fn draw_text(content: &str, glyph_atlas: Vec) -> Vec { } points } + +pub fn draw_cursor(content: &str, mut cursor_position: usize) -> (Point, Point) { + let mut x = 0; + let mut y = 0; + + if cursor_position > 0 { + cursor_position = cursor_position.checked_sub(1).unwrap_or(0); + for (idx, chara) in content.chars().enumerate() { + x += 1; + + if chara == '\n' { + x = 0; + y += 1; + } + if idx == cursor_position { + let point_a = Point::new((x * GLYPH_WIDTH) as i32, + (y * GLYPH_HEIGHT) as i32 + ); + let point_b = Point::new(point_a.x, + point_a.y + GLYPH_HEIGHT as i32 + ); + return (point_a, point_b) + } + } + } + (Point::new(0, 0), Point::new(0, GLYPH_HEIGHT as i32)) +} diff --git a/src/main.rs b/src/main.rs index efa7c18..6a0e1d1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,5 @@ extern crate sdl2; -use std::path::Path; - -use font_build::draw_text; use sdl2::event::Event; use sdl2::keyboard::Keycode; use sdl2::pixels::Color; @@ -38,14 +35,11 @@ fn get_corner_rect(rect_width: u32, rect_height: u32) -> Rect { pub fn main() -> Result<(), String> { let glyph_atlas = font_build::generate_glyph_atlas(); - let font_path: &Path = Path::new("./fonts/Monoid-Regular.ttf"); - let sdl_context = sdl2::init()?; let video_subsys = sdl_context.video()?; - let ttf_context = sdl2::ttf::init().map_err(|e| e.to_string())?; let window = video_subsys - .window("SDL2_TTF Example", SCREEN_WIDTH, SCREEN_HEIGHT) + .window("Rude", SCREEN_WIDTH, SCREEN_HEIGHT) .position_centered() .opengl() .build() @@ -53,146 +47,148 @@ pub fn main() -> Result<(), String> { let mut canvas = window.into_canvas().build().map_err(|e| e.to_string())?; - // Load a font - let mut font = ttf_context.load_font(font_path, 12)?; - font.set_style(sdl2::ttf::FontStyle::BOLD); - let mut buffer = String::new(); let mut cursor_position = 0; - let mut draw_text = |text: &str| -> Result<(), String> { + let mut draw_text = |text: &str, pos: usize| -> Result<(), String> { + // Draw background canvas.set_draw_color(Color::RGB(32, 32, 32)); canvas.clear(); + // Draw text canvas.set_draw_color(Color::RGB(240, 240, 240)); - let fb_text = draw_text(text, glyph_atlas.clone()); + let fb_text = font_build::draw_text(text, glyph_atlas.clone()); canvas.draw_points(&fb_text[..])?; + // Draw cursor + canvas.set_draw_color(Color::RGB(64, 240, 240)); + let fb_cursor = font_build::draw_cursor(text, pos); + canvas.draw_line(fb_cursor.0, fb_cursor.1)?; + canvas.present(); Ok(()) }; - draw_text(" ")?; + draw_text("", cursor_position)?; let mut modifier_keys = ModifierKeys {alt: false, ctrl: false, shift: false}; 'mainloop: loop { + // TODO: Make this completely user-configurable instead of hardcoded for event in sdl_context.event_pump()?.poll_iter() { match event { // ESC or SIGKILL Event::KeyDown { keycode: Some(Keycode::Escape), .. } | Event::Quit { .. } => break 'mainloop, - // ALT down - Event::KeyDown { keycode: Some(Keycode::LAlt), .. } | - Event::KeyDown { keycode: Some(Keycode::RAlt), .. } => { - modifier_keys.alt = true - }, - - // ALT up - Event::KeyUp { keycode: Some(Keycode::LAlt), .. } | - Event::KeyUp { keycode: Some(Keycode::RAlt), .. } => { - modifier_keys.alt = false - }, - - // CTRL down - Event::KeyDown { keycode: Some(Keycode::LCtrl), .. } | - Event::KeyDown { keycode: Some(Keycode::RCtrl), .. } => { - modifier_keys.ctrl = true - }, - - // CTRL up - Event::KeyUp { keycode: Some(Keycode::LCtrl), .. } | - Event::KeyUp { keycode: Some(Keycode::RCtrl), .. } => { - modifier_keys.ctrl = false - }, - - // SHIFT down - Event::KeyDown { keycode: Some(Keycode::LShift), .. } | - Event::KeyDown { keycode: Some(Keycode::RShift), .. } => { - modifier_keys.shift = true - }, - - // SHIFT up - Event::KeyUp { keycode: Some(Keycode::LShift), .. } | - Event::KeyUp { keycode: Some(Keycode::RShift), .. } => { - modifier_keys.shift = false - }, - - // Ignore SUPER - Event::KeyDown { keycode: Some(Keycode::LGui), .. } | - Event::KeyDown { keycode: Some(Keycode::RGui), .. } => (), + Event::KeyUp { keycode, .. } => { + match keycode{ + Some(Keycode::LAlt) | Some(Keycode::RAlt) => { + modifier_keys.alt = false + }, - // Type spacebar - Event::KeyDown { keycode: Some(Keycode::Space), .. } => { - buffer.insert(cursor_position, ' '); - cursor_position += 1; - draw_text(&buffer)? - }, - - // Backspace - Event::KeyDown { keycode: Some(Keycode::Backspace), .. } => { - buffer.remove(cursor_position - 1); - cursor_position -= 1; - draw_text(&buffer)? - }, - - // Enter - Event::KeyDown { keycode: Some(Keycode::Return), .. } => { - let key = '\n'; - buffer.insert(cursor_position, key); - cursor_position += 1; - draw_text(&buffer)? - }, + Some(Keycode::LCtrl) | Some(Keycode::RCtrl) => { + modifier_keys.ctrl = false + }, - // Left/Back arrow - Event::KeyDown { keycode: Some(Keycode::Left), .. } => { - cursor_position = usize::checked_sub(cursor_position, 1) - .unwrap_or(0) - }, + Some(Keycode::LShift) | Some(Keycode::RShift) => { + modifier_keys.shift = false + }, - // Home key - Event::KeyDown { keycode: Some(Keycode::Home), .. } => { - cursor_position = 0 - }, + Some(Keycode::LGui) | Some(Keycode::RGui) => { + break + }, - // End key - Event::KeyDown { keycode: Some(Keycode::End), .. } => { - cursor_position = buffer.len() + _ => (), + } }, - // Right/Forward arrow - Event::KeyDown { keycode: Some(Keycode::Right), .. } => { - cursor_position = (cursor_position + 1).min(buffer.len()) + Event::KeyDown { keycode, .. } => { + match keycode { + Some(Keycode::LAlt) | Some(Keycode::RAlt) => { + modifier_keys.alt = true + }, + + Some(Keycode::LCtrl) | Some(Keycode::RCtrl) => { + modifier_keys.ctrl = true + }, + + Some(Keycode::LShift) | Some(Keycode::RShift) => { + modifier_keys.shift = true + }, + + Some(Keycode::LGui) | Some(Keycode::RGui) => { + break + }, + + // BACKSPACE key + Some(Keycode::Backspace) => { + if buffer.len() > 0 { + buffer.remove(cursor_position - 1); + cursor_position -= 1; + draw_text(&buffer, cursor_position)? + } + }, + + // DELETE key + Some(Keycode::Delete) => { + if buffer.len() > 0 && cursor_position < buffer.len() { + buffer.remove(cursor_position); + draw_text(&buffer, cursor_position)? + } + }, + + // ENTER key + Some(Keycode::Return) => { + let key = '\n'; + buffer.insert(cursor_position, key); + cursor_position += 1; + draw_text(&buffer, cursor_position)? + }, + + // HOME key + Some(Keycode::Home) => { + cursor_position = 0; + draw_text(&buffer, cursor_position)? + }, + + // END key + Some(Keycode::End) => { + cursor_position = buffer.len(); + draw_text(&buffer, cursor_position)? + }, + + // Left/Back arrow + Some(Keycode::Left) => { + cursor_position = usize::checked_sub(cursor_position, 1) + .unwrap_or(0); + draw_text(&buffer, cursor_position)? + }, + + // Right/Forward arrow + Some(Keycode::Right) => { + cursor_position = (cursor_position + 1).min(buffer.len()); + draw_text(&buffer, cursor_position)? + }, + + _ => (), + } }, Event::TextInput { text, .. } => { - println!("{text}") + if !modifier_keys.alt && !modifier_keys.ctrl { + let input_char = text.chars().nth(0).expect("Empty"); + buffer.insert(cursor_position, input_char); + cursor_position += 1; + draw_text(&buffer, cursor_position)?; + } }, - Event::KeyDown { keycode, .. } => { - let key = keycode.unwrap().to_string(); - - // Ignore multi-char keycodes - if key.len() != 1 { break } - - let key_case = match modifier_keys.shift { - true => key.to_uppercase(), - false => key.to_lowercase() - }.chars().nth(0).expect("Empty"); - - buffer.insert(cursor_position, key_case); - cursor_position += 1; - draw_text(&buffer)?; - //println!("{key}"); - }, - - _ => {} } } } - + println!("{buffer}"); Ok(()) }