|
|
|
@ -7,7 +7,7 @@ use skulpin::skia_safe::paint::Style;
|
|
|
|
|
use skulpin::skia_safe::matrix::ScaleToFit;
|
|
|
|
|
use skulpin::skia_safe::icu;
|
|
|
|
|
use skulpin::winit::dpi::{LogicalSize, LogicalPosition};
|
|
|
|
|
use skulpin::winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent};
|
|
|
|
|
use skulpin::winit::event::{ElementState, Event, MouseScrollDelta, KeyboardInput, VirtualKeyCode, WindowEvent};
|
|
|
|
|
use skulpin::winit::event_loop::{ControlFlow, EventLoop};
|
|
|
|
|
use skulpin::winit::window::WindowBuilder;
|
|
|
|
|
|
|
|
|
@ -24,17 +24,21 @@ fn draw(
|
|
|
|
|
canvas: &mut Canvas,
|
|
|
|
|
cursor_pos: &mut (f32, f32),
|
|
|
|
|
shaper: &Shaper,
|
|
|
|
|
paint: &mut Paint,
|
|
|
|
|
font: &Font,
|
|
|
|
|
font_width: f32,
|
|
|
|
|
font_height: f32
|
|
|
|
|
) {
|
|
|
|
|
let (draw_commands, default_colors, cursor_grid_pos, cursor_type) = {
|
|
|
|
|
let (draw_commands, default_colors, cursor_grid_pos, cursor_type, cursor_foreground, cursor_background, cursor_enabled) = {
|
|
|
|
|
let editor = editor.lock().unwrap();
|
|
|
|
|
(
|
|
|
|
|
editor.build_draw_commands().clone(),
|
|
|
|
|
editor.default_colors.clone(),
|
|
|
|
|
editor.cursor_pos.clone(),
|
|
|
|
|
editor.cursor_type.clone()
|
|
|
|
|
editor.cursor_type.clone(),
|
|
|
|
|
editor.cursor_foreground(),
|
|
|
|
|
editor.cursor_background(),
|
|
|
|
|
editor.cursor_enabled
|
|
|
|
|
)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -47,16 +51,27 @@ fn draw(
|
|
|
|
|
let width = command.text.chars().count() as f32 * font_width;
|
|
|
|
|
let height = font_height;
|
|
|
|
|
let region = Rect::new(x, top, x + width, top + height);
|
|
|
|
|
let background_paint = Paint::new(command.style.colors.background.unwrap_or(default_colors.background.clone().unwrap()), None);
|
|
|
|
|
canvas.draw_rect(region, &background_paint);
|
|
|
|
|
paint.set_color(command.style.background(&default_colors).to_color());
|
|
|
|
|
canvas.draw_rect(region, &paint);
|
|
|
|
|
|
|
|
|
|
let mut foreground_paint = Paint::new(command.style.colors.foreground.unwrap_or(default_colors.foreground.clone().unwrap()), None);
|
|
|
|
|
let text = command.text.trim_end();
|
|
|
|
|
if text.len() > 0 {
|
|
|
|
|
if let Some((blob, _)) = shaper.shape_text_blob(&text, font, false, 10000.0, Point::default()) {
|
|
|
|
|
canvas.draw_text_blob(&blob, (x, top), &foreground_paint);
|
|
|
|
|
}
|
|
|
|
|
if command.style.underline || command.style.undercurl {
|
|
|
|
|
let (_, metrics) = font.metrics();
|
|
|
|
|
let width = command.text.chars().count() as f32 * font_width;
|
|
|
|
|
let underline_position = metrics.underline_position().unwrap();
|
|
|
|
|
|
|
|
|
|
paint.set_color(command.style.special(&default_colors).to_color());
|
|
|
|
|
canvas.draw_line((x, y + underline_position), (x + width, y + underline_position), &paint);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
paint.set_color(command.style.foreground(&default_colors).to_color());
|
|
|
|
|
let text = command.text.trim_end();
|
|
|
|
|
canvas.draw_str(text, (x, y), &font, &paint);
|
|
|
|
|
// if text.len() > 0 {
|
|
|
|
|
// if let Some((blob, _)) = shaper.shape_text_blob(&text, font, false, 10000.0, Point::default()) {
|
|
|
|
|
// canvas.draw_text_blob(&blob, (x, top), &paint);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let (cursor_grid_x, cursor_grid_y) = cursor_grid_pos;
|
|
|
|
@ -68,6 +83,7 @@ fn draw(
|
|
|
|
|
let cursor_y = (target_cursor_y - *previous_cursor_y) * 0.5 + *previous_cursor_y;
|
|
|
|
|
|
|
|
|
|
*cursor_pos = (cursor_x, cursor_y);
|
|
|
|
|
if cursor_enabled {
|
|
|
|
|
let cursor_width = match cursor_type {
|
|
|
|
|
CursorType::Vertical => font_width / 8.0,
|
|
|
|
|
CursorType::Horizontal | CursorType::Block => font_width
|
|
|
|
@ -77,29 +93,29 @@ fn draw(
|
|
|
|
|
CursorType::Vertical | CursorType::Block => font_height
|
|
|
|
|
};
|
|
|
|
|
let cursor = Rect::new(cursor_x, cursor_y, cursor_x + cursor_width, cursor_y + cursor_height);
|
|
|
|
|
let cursor_paint = Paint::new(default_colors.foreground.unwrap(), None);
|
|
|
|
|
canvas.draw_rect(cursor, &cursor_paint);
|
|
|
|
|
paint.set_color(cursor_background.to_color());
|
|
|
|
|
canvas.draw_rect(cursor, &paint);
|
|
|
|
|
|
|
|
|
|
if let CursorType::Block = cursor_type {
|
|
|
|
|
let text_paint = Paint::new(default_colors.background.unwrap(), None);
|
|
|
|
|
paint.set_color(cursor_foreground.to_color());
|
|
|
|
|
let editor = editor.lock().unwrap();
|
|
|
|
|
let character = editor.grid[cursor_grid_y as usize][cursor_grid_x as usize].clone()
|
|
|
|
|
.map(|(character, _)| character)
|
|
|
|
|
.unwrap_or(' ');
|
|
|
|
|
let text_y = cursor_y + font_height - font_height * 0.2;
|
|
|
|
|
canvas.draw_str(character.to_string(), (cursor_x, text_y), &font, &text_paint);
|
|
|
|
|
canvas.draw_str(character.to_string(), (cursor_x, text_y), &font, &paint);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn ui_loop(editor: Arc<Mutex<Editor>>) {
|
|
|
|
|
let shaper = Shaper::new(None);
|
|
|
|
|
let typeface = Typeface::new(FONT_NAME, FontStyle::default()).expect("Could not load font file.");
|
|
|
|
|
let font = Font::from_typeface(typeface, FONT_SIZE);
|
|
|
|
|
let paint = Paint::new(colors::WHITE, None);
|
|
|
|
|
let mut paint = Paint::new(colors::WHITE, None);
|
|
|
|
|
|
|
|
|
|
let (_, bounds) = font.measure_str("0", Some(&paint));
|
|
|
|
|
let font_width = bounds.width();
|
|
|
|
|
let (width, bounds) = font.measure_str("0", Some(&paint));
|
|
|
|
|
let font_width = width;
|
|
|
|
|
let font_height = bounds.height() * 1.68;
|
|
|
|
|
|
|
|
|
|
let event_loop = EventLoop::<()>::with_user_event();
|
|
|
|
@ -118,6 +134,8 @@ pub fn ui_loop(editor: Arc<Mutex<Editor>>) {
|
|
|
|
|
.expect("Failed to create renderer");
|
|
|
|
|
|
|
|
|
|
let mut cursor_pos = (0.0, 0.0);
|
|
|
|
|
let mut mouse_down = false;
|
|
|
|
|
let mut mouse_pos = (0, 0);
|
|
|
|
|
|
|
|
|
|
icu::init();
|
|
|
|
|
|
|
|
|
@ -152,8 +170,59 @@ pub fn ui_loop(editor: Arc<Mutex<Editor>>) {
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
Event::WindowEvent {
|
|
|
|
|
event: WindowEvent::CursorMoved {
|
|
|
|
|
position,
|
|
|
|
|
..
|
|
|
|
|
},
|
|
|
|
|
..
|
|
|
|
|
} => {
|
|
|
|
|
let grid_x = (position.x as f32 / font_width) as i64;
|
|
|
|
|
let grid_y = (position.y as f32 / font_height) as i64;
|
|
|
|
|
mouse_pos = (grid_x, grid_y);
|
|
|
|
|
if mouse_down {
|
|
|
|
|
editor.lock().unwrap().nvim.input_mouse("left", "drag", "", 0, grid_y, grid_x);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Event::WindowEvent {
|
|
|
|
|
event: WindowEvent::MouseInput {
|
|
|
|
|
state,
|
|
|
|
|
..
|
|
|
|
|
},
|
|
|
|
|
..
|
|
|
|
|
} => {
|
|
|
|
|
let input_type = match state {
|
|
|
|
|
ElementState::Pressed => {
|
|
|
|
|
mouse_down = true;
|
|
|
|
|
"press"
|
|
|
|
|
},
|
|
|
|
|
ElementState::Released => {
|
|
|
|
|
mouse_down = false;
|
|
|
|
|
"release"
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
let (grid_x, grid_y) = mouse_pos;
|
|
|
|
|
editor.lock().unwrap().nvim.input_mouse("left", input_type, "", 0, grid_y, grid_x);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Event::WindowEvent {
|
|
|
|
|
event: WindowEvent::MouseWheel {
|
|
|
|
|
delta: MouseScrollDelta::LineDelta(delta, _),
|
|
|
|
|
..
|
|
|
|
|
},
|
|
|
|
|
..
|
|
|
|
|
} => {
|
|
|
|
|
let input_type = if delta > 0.0 {
|
|
|
|
|
"up"
|
|
|
|
|
} else {
|
|
|
|
|
"down"
|
|
|
|
|
};
|
|
|
|
|
let (grid_x, grid_y) = mouse_pos;
|
|
|
|
|
editor.lock().unwrap().nvim.input_mouse("wheel", input_type, "", 0, grid_y, grid_x);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Event::EventsCleared => {
|
|
|
|
|
// Queue a RedrawRequested event.
|
|
|
|
|
window.request_redraw();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
@ -162,7 +231,7 @@ pub fn ui_loop(editor: Arc<Mutex<Editor>>) {
|
|
|
|
|
..
|
|
|
|
|
} => {
|
|
|
|
|
if let Err(e) = renderer.draw(&window, |canvas, _coordinate_system_helper| {
|
|
|
|
|
draw(&editor, canvas, &mut cursor_pos, &shaper, &font, font_width, font_height);
|
|
|
|
|
draw(&editor, canvas, &mut cursor_pos, &shaper, &mut paint, &font, font_width, font_height);
|
|
|
|
|
}) {
|
|
|
|
|
println!("Error during draw: {:?}", e);
|
|
|
|
|
*control_flow = ControlFlow::Exit
|
|
|
|
|