new rendering working without multigrid enabled. Making progress

macos-click-through
keith 4 years ago
parent 4ef6adcfef
commit d2665c2471

@ -16,6 +16,7 @@ pub enum ParseError {
InvalidString(Value), InvalidString(Value),
InvalidU64(Value), InvalidU64(Value),
InvalidI64(Value), InvalidI64(Value),
InvalidF64(Value),
InvalidBool(Value), InvalidBool(Value),
InvalidWindowAnchor(Value), InvalidWindowAnchor(Value),
InvalidFormat, InvalidFormat,
@ -30,6 +31,7 @@ impl fmt::Display for ParseError {
ParseError::InvalidString(value) => write!(f, "invalid string format {}", value), ParseError::InvalidString(value) => write!(f, "invalid string format {}", value),
ParseError::InvalidU64(value) => write!(f, "invalid u64 format {}", value), ParseError::InvalidU64(value) => write!(f, "invalid u64 format {}", value),
ParseError::InvalidI64(value) => write!(f, "invalid i64 format {}", value), ParseError::InvalidI64(value) => write!(f, "invalid i64 format {}", value),
ParseError::InvalidF64(value) => write!(f, "invalid f64 format {}", value),
ParseError::InvalidBool(value) => write!(f, "invalid bool format {}", value), ParseError::InvalidBool(value) => write!(f, "invalid bool format {}", value),
ParseError::InvalidWindowAnchor(value) => { ParseError::InvalidWindowAnchor(value) => {
write!(f, "invalid window anchor format {}", value) write!(f, "invalid window anchor format {}", value)
@ -185,7 +187,6 @@ pub enum RedrawEvent {
}, },
WindowPosition { WindowPosition {
grid: u64, grid: u64,
window: u64,
start_row: u64, start_row: u64,
start_column: u64, start_column: u64,
width: u64, width: u64,
@ -193,16 +194,14 @@ pub enum RedrawEvent {
}, },
WindowFloatPosition { WindowFloatPosition {
grid: u64, grid: u64,
window: u64,
anchor: WindowAnchor, anchor: WindowAnchor,
anchor_grid: u64, anchor_grid: u64,
anchor_row: u64, anchor_row: f64,
anchor_column: u64, anchor_column: f64,
focusable: bool, focusable: bool,
}, },
WindowExternalPosition { WindowExternalPosition {
grid: u64, grid: u64,
window: u64,
}, },
WindowHide { WindowHide {
grid: u64, grid: u64,
@ -378,6 +377,10 @@ fn parse_i64(i64_value: Value) -> Result<i64> {
i64_value.try_into().map_err(ParseError::InvalidI64) i64_value.try_into().map_err(ParseError::InvalidI64)
} }
fn parse_f64(f64_value: Value) -> Result<f64> {
f64_value.try_into().map_err(ParseError::InvalidF64)
}
fn parse_bool(bool_value: Value) -> Result<bool> { fn parse_bool(bool_value: Value) -> Result<bool> {
bool_value.try_into().map_err(ParseError::InvalidBool) bool_value.try_into().map_err(ParseError::InvalidBool)
} }
@ -638,12 +641,11 @@ fn parse_win_pos(win_pos_arguments: Vec<Value>) -> Result<RedrawEvent> {
Value::Nil, Value::Nil,
Value::Nil, Value::Nil,
]; ];
let [grid, window, start_row, start_column, width, height] = let [grid, _window, start_row, start_column, width, height] =
extract_values(win_pos_arguments, values)?; extract_values(win_pos_arguments, values)?;
Ok(RedrawEvent::WindowPosition { Ok(RedrawEvent::WindowPosition {
grid: parse_u64(grid)?, grid: parse_u64(grid)?,
window: parse_u64(window)?,
start_row: parse_u64(start_row)?, start_row: parse_u64(start_row)?,
start_column: parse_u64(start_column)?, start_column: parse_u64(start_column)?,
width: parse_u64(width)?, width: parse_u64(width)?,
@ -672,26 +674,24 @@ fn parse_win_float_pos(win_float_pos_arguments: Vec<Value>) -> Result<RedrawEven
Value::Nil, Value::Nil,
Value::Nil, Value::Nil,
]; ];
let [grid, window, anchor, anchor_grid, anchor_row, anchor_column, focusable] = let [grid, _window, anchor, anchor_grid, anchor_row, anchor_column, focusable] =
extract_values(win_float_pos_arguments, values)?; extract_values(win_float_pos_arguments, values)?;
Ok(RedrawEvent::WindowFloatPosition { Ok(RedrawEvent::WindowFloatPosition {
grid: parse_u64(grid)?, grid: parse_u64(grid)?,
window: parse_u64(window)?,
anchor: parse_window_anchor(anchor)?, anchor: parse_window_anchor(anchor)?,
anchor_grid: parse_u64(anchor_grid)?, anchor_grid: parse_u64(anchor_grid)?,
anchor_row: parse_u64(anchor_row)?, anchor_row: parse_f64(anchor_row)?,
anchor_column: parse_u64(anchor_column)?, anchor_column: parse_f64(anchor_column)?,
focusable: parse_bool(focusable)?, focusable: parse_bool(focusable)?,
}) })
} }
fn parse_win_external_pos(win_external_pos_arguments: Vec<Value>) -> Result<RedrawEvent> { fn parse_win_external_pos(win_external_pos_arguments: Vec<Value>) -> Result<RedrawEvent> {
let [grid, window] = extract_values(win_external_pos_arguments, [Value::Nil, Value::Nil])?; let [grid, _window] = extract_values(win_external_pos_arguments, [Value::Nil, Value::Nil])?;
Ok(RedrawEvent::WindowExternalPosition { Ok(RedrawEvent::WindowExternalPosition {
grid: parse_u64(grid)?, grid: parse_u64(grid)?,
window: parse_u64(window)?,
}) })
} }

@ -160,7 +160,7 @@ async fn start_process(mut receiver: UnboundedReceiver<UiCommand>) {
.unwrap_or_explained_panic("Could not communicate with neovim process"); .unwrap_or_explained_panic("Could not communicate with neovim process");
let mut options = UiAttachOptions::new(); let mut options = UiAttachOptions::new();
options.set_linegrid_external(true); options.set_linegrid_external(true);
options.set_multigrid_external(true); // options.set_multigrid_external(true);
options.set_rgb(true); options.set_rgb(true);
if let Err(command_error) = nvim.command("runtime! ginit.vim").await { if let Err(command_error) = nvim.command("runtime! ginit.vim").await {
nvim.command(&format!( nvim.command(&format!(

@ -35,7 +35,7 @@ pub struct CursorMode {
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub struct Cursor { pub struct Cursor {
pub position: (u64, u64), pub position: (f64, f64),
pub shape: CursorShape, pub shape: CursorShape,
pub cell_percentage: Option<f32>, pub cell_percentage: Option<f32>,
pub blinkwait: Option<u64>, pub blinkwait: Option<u64>,
@ -44,13 +44,13 @@ pub struct Cursor {
pub style: Option<Arc<Style>>, pub style: Option<Arc<Style>>,
pub enabled: bool, pub enabled: bool,
pub double_width: bool, pub double_width: bool,
pub character: String pub character: String,
} }
impl Cursor { impl Cursor {
pub fn new() -> Cursor { pub fn new() -> Cursor {
Cursor { Cursor {
position: (0, 0), position: (0.0, 0.0),
shape: CursorShape::Block, shape: CursorShape::Block,
style: None, style: None,
cell_percentage: None, cell_percentage: None,
@ -59,7 +59,7 @@ impl Cursor {
blinkoff: None, blinkoff: None,
enabled: true, enabled: true,
double_width: false, double_width: false,
character: " ".to_string() character: " ".to_string(),
} }
} }

@ -3,37 +3,37 @@ mod grid;
mod style; mod style;
mod window; mod window;
use std::collections::{HashSet, HashMap}; use std::collections::{HashMap, HashSet};
use std::sync::Arc; use std::sync::Arc;
use log::{trace, error}; use log::{error, trace};
use parking_lot::Mutex; use parking_lot::Mutex;
use skulpin::skia_safe::colors; use skulpin::skia_safe::colors;
use crate::bridge::{EditorMode, GuiOption, RedrawEvent, WindowAnchor}; use crate::bridge::{EditorMode, GuiOption, RedrawEvent, WindowAnchor};
use crate::redraw_scheduler::REDRAW_SCHEDULER; use crate::redraw_scheduler::REDRAW_SCHEDULER;
pub use window::*;
pub use cursor::{Cursor, CursorMode, CursorShape}; pub use cursor::{Cursor, CursorMode, CursorShape};
pub use grid::CharacterGrid; pub use grid::CharacterGrid;
pub use style::{Colors, Style}; pub use style::{Colors, Style};
pub use window::*;
lazy_static! { lazy_static! {
pub static ref EDITOR: Arc<Mutex<Editor>> = Arc::new(Mutex::new(Editor::new())); pub static ref EDITOR: Arc<Mutex<Editor>> = Arc::new(Mutex::new(Editor::new()));
} }
pub struct RenderInfo { pub struct RenderInfo {
windows: Vec<WindowRenderInfo>, pub windows: Vec<WindowRenderInfo>,
closed_window_ids: Vec<u64>, pub closed_window_ids: Vec<u64>,
} }
pub struct WindowRenderInfo { pub struct WindowRenderInfo {
pub grid_id: u64, pub grid_id: u64,
pub grid_position: (u64, u64), pub grid_position: (f64, f64),
pub width: u64, pub width: u64,
pub height: u64, pub height: u64,
pub should_clear: bool, pub should_clear: bool,
pub draw_commands: Vec<DrawCommand>, pub draw_commands: Vec<DrawCommand>,
pub child_windows: Vec<WindowRenderInfo> pub child_windows: Vec<WindowRenderInfo>,
} }
pub struct Editor { pub struct Editor {
@ -106,21 +106,46 @@ impl Editor {
RedrawEvent::HighlightAttributesDefine { id, style } => { RedrawEvent::HighlightAttributesDefine { id, style } => {
self.defined_styles.insert(id, Arc::new(style)); self.defined_styles.insert(id, Arc::new(style));
} }
RedrawEvent::CursorGoto { grid, row, column } => self.set_cursor_position(grid, row, column), RedrawEvent::CursorGoto { grid, row, column } => {
RedrawEvent::Resize { grid, width, height } => { self.set_cursor_position(grid, row, column)
self.windows.get_mut(&grid).map(|window| window.resize(width, height)); }
}, RedrawEvent::Resize {
grid,
width,
height,
} => {
if let Some(window) = self.windows.get_mut(&grid) {
window.grid.resize(width, height);
} else {
let new_window =
Window::new(grid, width, height, None, WindowAnchor::NorthWest, 0.0, 0.0);
self.windows.insert(grid, new_window);
}
}
RedrawEvent::GridLine { RedrawEvent::GridLine {
grid, grid,
row, row,
column_start, column_start,
cells cells,
} => { } => {
self.windows.get_mut(&grid).map(|window| window.draw_grid_line(row, column_start, cells, &self.defined_styles, &mut self.previous_style)); let defined_styles = &self.defined_styles;
}, let mut previous_style = self.previous_style.clone();
self.windows.get_mut(&grid).map(|window| {
window.draw_grid_line(
row,
column_start,
cells,
defined_styles,
&mut previous_style,
)
});
self.previous_style = previous_style;
}
RedrawEvent::Clear { grid } => { RedrawEvent::Clear { grid } => {
self.windows.get_mut(&grid).map(|window| window.grid.clear()); self.windows
}, .get_mut(&grid)
.map(|window| window.grid.clear());
}
RedrawEvent::Scroll { RedrawEvent::Scroll {
grid, grid,
top, top,
@ -128,43 +153,90 @@ impl Editor {
left, left,
right, right,
rows, rows,
columns columns,
} => {
self.windows
.get_mut(&grid)
.map(|window| window.scroll_region(top, bottom, left, right, rows, columns));
}
RedrawEvent::WindowPosition {
grid,
start_row,
start_column,
width,
height,
} => self.set_window_position(grid, start_row, start_column, width, height),
RedrawEvent::WindowFloatPosition {
grid,
anchor,
anchor_grid,
anchor_row,
anchor_column,
..
} => { } => {
self.windows.get_mut(&grid).map(|window| window.scroll_region(top, bottom, left, right, rows, columns)); self.set_window_float_position(grid, anchor_grid, anchor, anchor_row, anchor_column)
}, }
RedrawEvent::WindowPosition { grid, window, start_row, start_column, width, height } => self.set_window_position(grid, window, start_row, start_column, width, height),
RedrawEvent::WindowFloatPosition { grid, window, anchor, anchor_grid, anchor_row, anchor_column, .. } => self.set_window_float_position(grid, window, anchor_grid, anchor, anchor_row, anchor_column),
RedrawEvent::WindowHide { grid } => { RedrawEvent::WindowHide { grid } => {
self.windows.get_mut(&grid).map(|window| window.hidden = true); self.windows
}, .get_mut(&grid)
.map(|window| window.hidden = true);
}
RedrawEvent::WindowClose { grid } => self.close_window(grid), RedrawEvent::WindowClose { grid } => self.close_window(grid),
RedrawEvent::MessageSetPosition { grid, row, .. } => {
self.set_message_position(grid, row)
}
_ => {} _ => {}
}; };
} }
fn close_window(&mut self, grid: u64) { fn close_window(&mut self, grid: u64) {
self.windows
.get(&grid)
.and_then(|window| window.anchor_grid_id)
.and_then(|parent_window_id| self.windows.get_mut(&parent_window_id))
.map(|parent_window| parent_window.children.remove(&grid));
self.windows.remove(&grid); self.windows.remove(&grid);
self.closed_window_ids.insert(grid); self.closed_window_ids.insert(grid);
} }
fn set_window_position(&mut self, grid: u64, window_id: u64, start_row: u64, start_column: u64, width: u64, height: u64) { fn set_window_position(
match self.windows.get_mut(&grid) { &mut self,
Some(window) => { grid: u64,
window.hidden = false; start_row: u64,
window.anchor_grid_id = None; start_column: u64,
window.anchor_type = WindowAnchor::NorthWest; width: u64,
window.anchor_row = start_row; height: u64,
window.anchor_column = start_column; ) {
window.resize(width, height); if let Some(window) = self.windows.get_mut(&grid) {
}, window.hidden = false;
None => { window.anchor_grid_id = None;
let new_window = Window::new(window_id, grid, width, height, None, WindowAnchor::NorthWest, start_row, start_column); window.anchor_type = WindowAnchor::NorthWest;
self.windows.insert(grid, new_window); window.anchor_row = start_row as f64;
} window.anchor_column = start_column as f64;
window.resize(width, height);
} else {
let new_window = Window::new(
grid,
width,
height,
None,
WindowAnchor::NorthWest,
start_row as f64,
start_column as f64,
);
self.windows.insert(grid, new_window);
} }
} }
fn set_window_float_position(&mut self, grid: u64, window_id: u64, anchor_grid: u64, anchor_type: WindowAnchor, anchor_row: u64, anchor_column: u64) { fn set_window_float_position(
&mut self,
grid: u64,
anchor_grid: u64,
anchor_type: WindowAnchor,
anchor_row: f64,
anchor_column: f64,
) {
if let Some(window) = self.windows.get_mut(&grid) { if let Some(window) = self.windows.get_mut(&grid) {
window.hidden = false; window.hidden = false;
window.anchor_grid_id = Some(anchor_grid); window.anchor_grid_id = Some(anchor_grid);
@ -180,50 +252,82 @@ impl Editor {
} }
} }
fn get_window_top_left(&self, grid: u64) -> Option<(u64, u64)> { fn set_message_position(&mut self, grid: u64, row: u64) {
if let Some(window) = self.windows.get_mut(&grid) {
window.hidden = false;
window.anchor_grid_id = Some(1);
window.anchor_type = WindowAnchor::NorthWest;
window.anchor_row = row as f64;
window.anchor_column = 0.0;
} else {
if let Some(parent) = self.windows.get(&1) {
let new_window = Window::new(
grid,
parent.grid.width,
1,
None,
WindowAnchor::NorthWest,
row as f64,
0.0,
);
self.windows.insert(grid, new_window);
}
}
if let Some(parent) = self.windows.get_mut(&1) {
parent.children.insert(grid);
}
}
fn get_window_top_left(&self, grid: u64) -> Option<(f64, f64)> {
let window = self.windows.get(&grid)?; let window = self.windows.get(&grid)?;
match window.anchor_grid_id { match window.anchor_grid_id {
Some(anchor_grid) => { Some(anchor_grid) => {
let (parent_anchor_row, parent_anchor_column) = self.get_window_top_left(anchor_grid)?; let (parent_anchor_column, parent_anchor_row) =
self.get_window_top_left(anchor_grid)?;
match window.anchor_type { match window.anchor_type {
WindowAnchor::NorthWest => { WindowAnchor::NorthWest => Some((
Some((parent_anchor_row + window.anchor_row, parent_anchor_column + window.anchor_column)) parent_anchor_column + window.anchor_column,
}, parent_anchor_row + window.anchor_row,
WindowAnchor::NorthEast => { )),
Some((parent_anchor_row + window.anchor_row, parent_anchor_column + window.anchor_column - window.grid.width)) WindowAnchor::NorthEast => Some((
}, parent_anchor_column + window.anchor_column - window.grid.width as f64,
WindowAnchor::SouthWest => { parent_anchor_row + window.anchor_row,
Some((parent_anchor_row + window.anchor_row - window.grid.height, parent_anchor_column + window.anchor_column)) )),
}, WindowAnchor::SouthWest => Some((
WindowAnchor::SouthEast => { parent_anchor_column + window.anchor_column,
Some((parent_anchor_row + window.anchor_row - window.grid.height, parent_anchor_column + window.anchor_column - window.grid.width)) parent_anchor_row + window.anchor_row - window.grid.height as f64,
}, )),
WindowAnchor::SouthEast => Some((
parent_anchor_column + window.anchor_column - window.grid.width as f64,
parent_anchor_row + window.anchor_row - window.grid.height as f64,
)),
} }
}, }
None => Some((window.anchor_row, window.anchor_column)) None => Some((window.anchor_column, window.anchor_row)),
} }
} }
fn set_cursor_position(&self, grid: u64, row: u64, column: u64) { fn set_cursor_position(&mut self, grid: u64, row: u64, column: u64) {
match self.get_window_top_left(grid) { match self.get_window_top_left(grid) {
Some((window_row, window_column)) => { Some((window_row, window_column)) => {
self.cursor.position = (window_row + row, window_column + column); self.cursor.position = (window_row + row as f64, window_column + column as f64);
if let Some(window) = self.windows.get(&grid) { if let Some(window) = self.windows.get(&grid) {
self.cursor.character = match window.grid.get_cell(column, row) { self.cursor.character = match window.grid.get_cell(row, column) {
Some(Some((character, _))) => character.clone(), Some(Some((character, _))) => character.clone(),
_ => ' '.to_string(), _ => ' '.to_string(),
}; };
self.cursor.double_width = match window.grid.get_cell(column + 1, row) { self.cursor.double_width = match window.grid.get_cell(row, column + 1) {
Some(Some((character, _))) => character.is_empty(), Some(Some((character, _))) => character.is_empty(),
_ => false, _ => false,
}; };
} }
}, }
None => { None => {
self.cursor.position = (row, column); self.cursor.position = (row as f64, column as f64);
self.cursor.double_width = false; self.cursor.double_width = false;
self.cursor.character = " ".to_string(); self.cursor.character = " ".to_string();
} }
@ -239,33 +343,47 @@ impl Editor {
fn build_window_render_info(&mut self, grid: u64) -> Option<WindowRenderInfo> { fn build_window_render_info(&mut self, grid: u64) -> Option<WindowRenderInfo> {
let grid_position = self.get_window_top_left(grid)?; let grid_position = self.get_window_top_left(grid)?;
let (draw_commands, should_clear) = {
let mut window = self.windows.get_mut(&grid)?;
window.build_draw_commands()
};
let window = self.windows.get(&grid)?; let window = self.windows.get_mut(&grid)?;
let child_windows = window.children.iter().filter_map(|child_id| self.build_window_render_info(*child_id)).collect();
if window.hidden {
return None;
}
let (draw_commands, should_clear) = window.build_draw_commands();
let children = window.children.clone();
let width = window.grid.width;
let height = window.grid.height;
let child_windows = children
.iter()
.filter_map(|child_id| self.build_window_render_info(*child_id))
.collect();
Some(WindowRenderInfo { Some(WindowRenderInfo {
grid_id: grid, grid_id: grid,
grid_position, grid_position,
width: window.grid.width, width,
height: window.grid.height, height,
should_clear, should_clear,
draw_commands, draw_commands,
child_windows child_windows,
}) })
} }
pub fn build_render_info(&mut self) -> RenderInfo { pub fn build_render_info(&mut self) -> RenderInfo {
let mut windows = Vec::new(); let mut windows = Vec::new();
for window in self.windows.values() { let root_window_ids: Vec<u64> = self
if !window.hidden && window.anchor_grid_id.is_none() { .windows
if let Some(window_render_info) = self.build_window_render_info(window.grid_id) { .values()
windows.push(window_render_info); .filter(|window| !window.hidden && window.anchor_grid_id.is_none())
} .map(|window| window.grid_id)
.collect();
for root_window_id in root_window_ids.into_iter() {
if let Some(window_render_info) = self.build_window_render_info(root_window_id) {
windows.push(window_render_info);
} }
} }
@ -273,7 +391,8 @@ impl Editor {
self.closed_window_ids.clear(); self.closed_window_ids.clear();
RenderInfo { RenderInfo {
windows, closed_window_ids windows,
closed_window_ids,
} }
} }
} }

@ -1,12 +1,12 @@
use std::collections::{HashSet, HashMap}; use std::collections::{HashMap, HashSet};
use std::sync::Arc; use std::sync::Arc;
use log::trace; use log::trace;
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
use crate::bridge::{GridLineCell, WindowAnchor};
use super::grid::CharacterGrid; use super::grid::CharacterGrid;
use super::style::Style; use super::style::Style;
use crate::bridge::{GridLineCell, WindowAnchor};
#[derive(new, Debug, Clone)] #[derive(new, Debug, Clone)]
pub struct DrawCommand { pub struct DrawCommand {
@ -17,24 +17,35 @@ pub struct DrawCommand {
} }
pub struct Window { pub struct Window {
pub id: u64,
pub grid_id: u64, pub grid_id: u64,
pub grid: CharacterGrid, pub grid: CharacterGrid,
pub hidden: bool, pub hidden: bool,
pub anchor_grid_id: Option<u64>, pub anchor_grid_id: Option<u64>,
pub anchor_type: WindowAnchor, pub anchor_type: WindowAnchor,
pub anchor_row: u64, pub anchor_row: f64,
pub anchor_column: u64, pub anchor_column: f64,
pub children: HashSet<u64>, pub children: HashSet<u64>,
} }
impl Window { impl Window {
pub fn new(id: u64, grid_id: u64, width: u64, height: u64, anchor_grid_id: Option<u64>, anchor_type: WindowAnchor, anchor_row: u64, anchor_column: u64) -> Window { pub fn new(
grid_id: u64,
width: u64,
height: u64,
anchor_grid_id: Option<u64>,
anchor_type: WindowAnchor,
anchor_row: f64,
anchor_column: f64,
) -> Window {
Window { Window {
id, grid_id, anchor_grid_id, anchor_type, anchor_row, anchor_column, grid_id,
anchor_grid_id,
anchor_type,
anchor_row,
anchor_column,
grid: CharacterGrid::new((width, height)), grid: CharacterGrid::new((width, height)),
hidden: false, hidden: false,
children: HashSet::new() children: HashSet::new(),
} }
} }
@ -42,7 +53,14 @@ impl Window {
self.grid.resize(width, height); self.grid.resize(width, height);
} }
fn draw_grid_line_cell(&mut self, row_index: u64, column_pos: &mut u64, cell: GridLineCell, defined_styles: &HashMap<u64, Arc<Style>>, previous_style: &mut Option<Arc<Style>>) { fn draw_grid_line_cell(
&mut self,
row_index: u64,
column_pos: &mut u64,
cell: GridLineCell,
defined_styles: &HashMap<u64, Arc<Style>>,
previous_style: &mut Option<Arc<Style>>,
) {
let style = match cell.highlight_id { let style = match cell.highlight_id {
Some(0) => None, Some(0) => None,
Some(style_id) => defined_styles.get(&style_id).cloned(), Some(style_id) => defined_styles.get(&style_id).cloned(),
@ -75,18 +93,39 @@ impl Window {
*previous_style = style; *previous_style = style;
} }
pub fn draw_grid_line(&mut self, row: u64, column_start: u64, cells: Vec<GridLineCell>, defined_styles: &HashMap<u64, Arc<Style>>, previous_style: &mut Option<Arc<Style>>) { pub fn draw_grid_line(
&mut self,
row: u64,
column_start: u64,
cells: Vec<GridLineCell>,
defined_styles: &HashMap<u64, Arc<Style>>,
previous_style: &mut Option<Arc<Style>>,
) {
if row < self.grid.height { if row < self.grid.height {
let mut column_pos = column_start; let mut column_pos = column_start;
for cell in cells { for cell in cells {
self.draw_grid_line_cell(row, &mut column_pos, cell, defined_styles, previous_style); self.draw_grid_line_cell(
row,
&mut column_pos,
cell,
defined_styles,
previous_style,
);
} }
} else { } else {
println!("Draw command out of bounds"); println!("Draw command out of bounds");
} }
} }
pub fn scroll_region(&mut self, top: u64, bot: u64, left: u64, right: u64, rows: i64, cols: i64) { pub fn scroll_region(
&mut self,
top: u64,
bot: u64,
left: u64,
right: u64,
rows: i64,
cols: i64,
) {
let y_iter: Box<dyn Iterator<Item = i64>> = if rows > 0 { let y_iter: Box<dyn Iterator<Item = i64>> = if rows > 0 {
Box::new((top as i64 + rows)..bot as i64) Box::new((top as i64 + rows)..bot as i64)
} else { } else {

@ -1,4 +1,5 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
#![feature(entry_insert)]
#[macro_use] #[macro_use]
mod settings; mod settings;

@ -13,7 +13,6 @@ use crate::bridge::EditorMode;
use animation_utils::*; use animation_utils::*;
use blink::*; use blink::*;
const COMMAND_LINE_DELAY_FRAMES: u64 = 5;
const DEFAULT_CELL_PERCENTAGE: f32 = 1.0 / 8.0; const DEFAULT_CELL_PERCENTAGE: f32 = 1.0 / 8.0;
const STANDARD_CORNERS: &[(f32, f32); 4] = &[(-0.5, -0.5), (0.5, -0.5), (0.5, 0.5), (-0.5, 0.5)]; const STANDARD_CORNERS: &[(f32, f32); 4] = &[(-0.5, -0.5), (0.5, -0.5), (0.5, 0.5), (-0.5, 0.5)];
@ -180,8 +179,6 @@ impl Corner {
pub struct CursorRenderer { pub struct CursorRenderer {
pub corners: Vec<Corner>, pub corners: Vec<Corner>,
pub previous_position: (u64, u64),
pub command_line_delay: u64,
blink_status: BlinkStatus, blink_status: BlinkStatus,
previous_cursor_shape: Option<CursorShape>, previous_cursor_shape: Option<CursorShape>,
cursor_vfx: Option<Box<dyn cursor_vfx::CursorVfx>>, cursor_vfx: Option<Box<dyn cursor_vfx::CursorVfx>>,
@ -192,8 +189,6 @@ impl CursorRenderer {
pub fn new() -> CursorRenderer { pub fn new() -> CursorRenderer {
let mut renderer = CursorRenderer { let mut renderer = CursorRenderer {
corners: vec![Corner::new(); 4], corners: vec![Corner::new(); 4],
previous_position: (0, 0),
command_line_delay: 0,
blink_status: BlinkStatus::new(), blink_status: BlinkStatus::new(),
previous_cursor_shape: None, previous_cursor_shape: None,
//cursor_vfx: Box::new(PointHighlight::new(Point{x:0.0, y:0.0}, HighlightMode::Ripple)), //cursor_vfx: Box::new(PointHighlight::new(Point{x:0.0, y:0.0}, HighlightMode::Ripple)),
@ -255,39 +250,19 @@ impl CursorRenderer {
let mut paint = Paint::new(skulpin::skia_safe::colors::WHITE, None); let mut paint = Paint::new(skulpin::skia_safe::colors::WHITE, None);
paint.set_anti_alias(settings.antialiasing); paint.set_anti_alias(settings.antialiasing);
self.previous_position = { let (grid_x, grid_y) = cursor.position;
let editor = EDITOR.lock(); let character = &cursor.character;
let (_, grid_y) = cursor.position;
let (_, previous_y) = self.previous_position;
if grid_y == editor.grid.height - 1 && previous_y != grid_y {
self.command_line_delay += 1;
if self.command_line_delay < COMMAND_LINE_DELAY_FRAMES {
self.previous_position
} else {
self.command_line_delay = 0;
cursor.position
}
} else {
self.command_line_delay = 0;
cursor.position
}
};
let (grid_x, grid_y) = self.previous_position;
let character = cursor.text;
let font_width = match (cursor.double_width, &cursor.shape) { let font_width = match (cursor.double_width, &cursor.shape) {
(true, CursorShape::Block) => font_width * 2.0, (true, CursorShape::Block) => font_width * 2.0,
_ => font_width _ => font_width,
}; };
let font_dimensions: Point = (font_width, font_height).into(); let font_dimensions: Point = (font_width, font_height).into();
let in_insert_mode = { let in_insert_mode = {
let editor = EDITOR.lock(); let editor = EDITOR.lock();
matches!(editor.current_mode, EditorMode::Insert); matches!(editor.current_mode, EditorMode::Insert)
}; };
let destination: Point = (grid_x as f32 * font_width, grid_y as f32 * font_height).into(); let destination: Point = (grid_x as f32 * font_width, grid_y as f32 * font_height).into();
@ -330,7 +305,7 @@ impl CursorRenderer {
animating |= vfx_animating; animating |= vfx_animating;
} }
if animating || self.command_line_delay != 0 { if animating {
REDRAW_SCHEDULER.queue_next_frame(); REDRAW_SCHEDULER.queue_next_frame();
} }

@ -3,7 +3,9 @@ use std::sync::Arc;
use log::trace; use log::trace;
use skulpin::skia_safe::gpu::SurfaceOrigin; use skulpin::skia_safe::gpu::SurfaceOrigin;
use skulpin::skia_safe::{colors, dash_path_effect, Budgeted, Canvas, Paint, Rect, Surface, ImageInfo}; use skulpin::skia_safe::{
colors, dash_path_effect, Budgeted, Canvas, ImageInfo, Paint, Rect, Surface,
};
use skulpin::CoordinateSystemHelper; use skulpin::CoordinateSystemHelper;
mod caching_shaper; mod caching_shaper;
@ -13,7 +15,7 @@ pub mod font_options;
pub use caching_shaper::CachingShaper; pub use caching_shaper::CachingShaper;
pub use font_options::*; pub use font_options::*;
use crate::editor::{Style, EDITOR}; use crate::editor::{Style, WindowRenderInfo, EDITOR};
use cursor_renderer::CursorRenderer; use cursor_renderer::CursorRenderer;
pub struct Renderer { pub struct Renderer {
@ -149,11 +151,21 @@ impl Renderer {
canvas.restore(); canvas.restore();
} }
pub fn build_window_surface(&self, gpu_canvas: &mut Canvas, default_style: &Arc<Style>, dimensions: (u64, u64)) -> Surface { pub fn build_window_surface(
&self,
gpu_canvas: &mut Canvas,
default_style: &Arc<Style>,
dimensions: (i32, i32),
) -> Surface {
let mut context = gpu_canvas.gpu_context().unwrap(); let mut context = gpu_canvas.gpu_context().unwrap();
let budgeted = Budgeted::YES; let budgeted = Budgeted::Yes;
let parent_image_info = gpu_canvas.image_info(); let parent_image_info = gpu_canvas.image_info();
let image_info = ImageInfo::new(dimensions, parent_image_info.color_type(), parent_image_info.alpha_type(), parent_image_info.color_space()); let image_info = ImageInfo::new(
dimensions,
parent_image_info.color_type(),
parent_image_info.alpha_type(),
parent_image_info.color_space(),
);
let surface_origin = SurfaceOrigin::TopLeft; let surface_origin = SurfaceOrigin::TopLeft;
let mut surface = Surface::new_render_target( let mut surface = Surface::new_render_target(
&mut context, &mut context,
@ -170,24 +182,36 @@ impl Renderer {
surface surface
} }
pub fn draw_window(&mut self, root_canvas: &mut Canvas, window_render_info: &WindowRenderInfo, coordinate_system_helper: &CoordinateSystemHelper, default_style: Arc<Style>) { pub fn draw_window(
let image_width = (window_render_info.width * self.font_width) as i32; &mut self,
let image_height = (window_render_info.height * self.font_height) as i32; root_canvas: &mut Canvas,
window_render_info: &WindowRenderInfo,
let mut surface_entry = self.window_surfaces.entry(&window_render_info.grid_id); default_style: &Arc<Style>,
) {
let build_surface = || build_window_surface(gpu_canvas, default_style, (image_width, image_height)); let image_width = (window_render_info.width as f32 * self.font_width) as i32;
let image_height = (window_render_info.height as f32 * self.font_height) as i32;
if window_render_info.should_clear { let mut surface = if window_render_info.should_clear {
surface_entry = surface_entry.insert(build_surface()); None
} else {
self.window_surfaces.remove(&window_render_info.grid_id)
}
.unwrap_or_else(|| {
self.build_window_surface(root_canvas, &default_style, (image_width, image_height))
});
if surface.width() != image_width || surface.height() != image_height {
let image = surface.image_snapshot();
surface =
self.build_window_surface(root_canvas, &default_style, (image_width, image_height));
let image_destination =
Rect::new(0.0, 0.0, image.width() as f32, image.height() as f32);
surface
.canvas()
.draw_image_rect(image, None, &image_destination, &self.paint);
} }
let surface = self.window_surfaces
.entry(&window_render_info.grid_id)
.or_insert_with(build_surface());
let mut canvas = surface.canvas(); let mut canvas = surface.canvas();
coordinate_system_helper.use_logical_coordinates(&mut canvas);
for command in window_render_info.draw_commands.iter() { for command in window_render_info.draw_commands.iter() {
self.draw_background( self.draw_background(
@ -212,18 +236,23 @@ impl Renderer {
let image = surface.image_snapshot(); let image = surface.image_snapshot();
let (grid_left, grid_right) = window_render_info.grid_position; let (grid_left, grid_top) = window_render_info.grid_position;
let image_left = grid_left as f32 * self.font_width;
let image_top = grid_top as f32 * self.font_height;
let image_destination = Rect::new( let image_destination = Rect::new(
grid_left * self.font_width, image_left,
grid_height * self.font_height, image_top,
image_width as f32, image_left + image_width as f32,
image_height as f32, image_top + image_height as f32,
); );
root_canvas.draw_image_rect(image, None, &image_destination, &self.paint); root_canvas.draw_image_rect(image, None, &image_destination, &self.paint);
self.window_surfaces
.insert(window_render_info.grid_id, surface);
for child_window_render_info in window_render_info.child_windows.iter() { for child_window_render_info in window_render_info.child_windows.iter() {
self.draw_window(root_canvas, child_window_render_info, coordinate_system_helper, default_style); self.draw_window(root_canvas, child_window_render_info, default_style);
} }
} }
@ -245,11 +274,22 @@ impl Renderer {
) )
}; };
gpu_canvas.clear(default_style.colors.background.clone().unwrap().to_color());
let font_changed = guifont_setting let font_changed = guifont_setting
.map(|guifont| self.update_font(&guifont)) .map(|guifont| self.update_font(&guifont))
.unwrap_or(false); .unwrap_or(false);
self.surface = Some(surface); for closed_window_id in render_info.closed_window_ids.iter() {
self.window_surfaces.remove(&closed_window_id);
}
coordinate_system_helper.use_logical_coordinates(gpu_canvas);
for window_render_info in render_info.windows.iter() {
self.draw_window(gpu_canvas, window_render_info, &default_style);
}
self.cursor_renderer.draw( self.cursor_renderer.draw(
cursor, cursor,
&default_style.colors, &default_style.colors,

Loading…
Cancel
Save