|
|
|
|
@ -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(()) |
|
|
|
|
} |
|
|
|
|
|