You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

249 lines
9.7 KiB

extern crate sdl2;
use clipboard::{ClipboardProvider, ClipboardContext};
use sdl2::event::{Event, WindowEvent};
use sdl2::keyboard::Keycode;
use sdl2::pixels::Color;
use sdl2::rect::Point;
mod editor_render;
static SCREEN_WIDTH: u32 = 1680;
static SCREEN_HEIGHT: u32 = 945;
struct ModifierKeys {
alt: bool,
ctrl: bool,
shift: bool,
}
pub fn main() -> Result<(), String> {
let mut clipboard_context: ClipboardContext = ClipboardProvider::new().unwrap();
let (glyph_atlas, glyph_metrics) = editor_render::generate_glyph_data();
let sdl_context = sdl2::init()?;
let video_subsys = sdl_context.video()?;
let window = video_subsys
.window("Rude", SCREEN_WIDTH, SCREEN_HEIGHT)
.position_centered()
.resizable()
.opengl()
.build()
.map_err(|e| e.to_string())?;
let mut canvas = window.into_canvas().build().map_err(|e| e.to_string())?;
let mut buffer = String::new();
let mut cursor_position = 0;
let mut selection_anchor: Option<usize> = None;
let pad_offset = Point::new(10, 10);
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 = editor_render::draw_text(
&glyph_atlas,
&glyph_metrics,
text,
pad_offset
);
canvas.draw_points(&fb_text[..])?;
// Draw cursor
canvas.set_draw_color(Color::RGB(64, 240, 240));
let fb_cursor = editor_render::draw_cursor(
&glyph_metrics,
pos,
text,
pad_offset
);
canvas.draw_line(fb_cursor.0, fb_cursor.1)?;
canvas.present();
Ok(())
};
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 {
Event::Window { win_event, .. } => {
if let WindowEvent::Resized(_w, _h) = win_event {
draw_text(&buffer, cursor_position)?
}
}
// ESC or SIGKILL
Event::KeyDown { keycode: Some(Keycode::Escape), .. } |
Event::Quit { .. } => break 'mainloop,
Event::KeyUp { keycode, .. } => {
match keycode{
Some(Keycode::LAlt) | Some(Keycode::RAlt) => {
modifier_keys.alt = false
},
Some(Keycode::LCtrl) | Some(Keycode::RCtrl) => {
modifier_keys.ctrl = false
},
Some(Keycode::LShift) | Some(Keycode::RShift) => {
modifier_keys.shift = false
},
Some(Keycode::LGui) | Some(Keycode::RGui) => {
break
},
_ => (),
}
},
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
},
_ => (),
};
match (modifier_keys.shift, modifier_keys.ctrl, modifier_keys.alt) {
// All modifiers up
(false, false, false) => {
match keycode {
// 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) => {
selection_anchor = None;
cursor_position = usize::checked_sub(cursor_position, 1)
.unwrap_or(0);
draw_text(&buffer, cursor_position)?
},
// Right/Forward arrow
Some(Keycode::Right) => {
selection_anchor = None;
cursor_position = (cursor_position + 1).min(buffer.len());
draw_text(&buffer, cursor_position)?
},
// BACKSPACE key
Some(Keycode::Backspace) => {
if buffer.len() > 0 {
// Character backspace; regular
buffer.remove(cursor_position - 1);
cursor_position -= 1;
draw_text(&buffer, cursor_position)?
}
},
_ => (),
}
},
// CTRL down
(false, true, false) => {
match keycode {
Some(Keycode::Z) => println!("Undo"),
Some(Keycode::X) => println!("Cut"),
Some(Keycode::C) => {
clipboard_context.set_contents(buffer.clone()).unwrap()
},
Some(Keycode::V) => println!("Paste"),
// BACKSPACE key
// Word backspace
// TODO: Clean up this cursed expression
Some(Keycode::Backspace) => {
if buffer.len() > 0 {
let buffer_chars: Vec<char> = buffer.chars()
.collect();
while !(buffer_chars[cursor_position - 1] == ' ' ||
buffer_chars[cursor_position - 1] == '\n') &&
cursor_position > 1 {
buffer.remove(cursor_position - 1);
cursor_position -= 1;
}
buffer.remove(cursor_position - 1);
cursor_position -= 1;
draw_text(&buffer, cursor_position)?
}
},
_ => (),
}
},
(true, true, false) => {
match keycode {
Some(Keycode::Z) => println!("Redo"),
Some(Keycode::X) => println!("Cut line(s)"),
Some(Keycode::C) => println!("Copy line(s)"),
_ => (),
}
},
_ => (),
}
},
Event::TextInput { text, .. } => {
let input_char = text.chars().nth(0).expect("Empty");
buffer.insert(cursor_position, input_char);
cursor_position += 1;
draw_text(&buffer, cursor_position)?;
},
_ => {}
}
}
::std::thread::sleep(std::time::Duration::new(0, 50_000_000));
}
format!("{selection_anchor:?}");
println!("{buffer}");
Ok(())
}