From fab0002a569469ba013a5bd4ada3d84b766ce38f Mon Sep 17 00:00:00 2001 From: daa84 Date: Thu, 7 Sep 2017 18:51:12 +0300 Subject: [PATCH] Cursor rendering --- src/color.rs | 8 +++++++ src/cursor.rs | 61 ++++++++++++++++++++++++++++------------------- src/render/mod.rs | 34 +++++++++++++++++++------- src/shell.rs | 28 ++++++++++++---------- 4 files changed, 85 insertions(+), 46 deletions(-) diff --git a/src/color.rs b/src/color.rs index dc1871a..319da98 100644 --- a/src/color.rs +++ b/src/color.rs @@ -81,4 +81,12 @@ impl ColorModel { cell.attrs.foreground.as_ref().or(Some(&self.fg_color)) } } + + pub fn actual_cell_bg<'a>(&'a self, cell: &'a Cell) -> &'a Color { + if !cell.attrs.reverse { + cell.attrs.background.as_ref().unwrap_or(&self.bg_color) + } else { + cell.attrs.foreground.as_ref().unwrap_or(&self.fg_color) + } + } } diff --git a/src/cursor.rs b/src/cursor.rs index 1da0dfe..1b846db 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -6,6 +6,8 @@ use mode; use nvim; use nvim::{RepaintMode, RedrawEvents}; use std::sync::{Arc, Weak}; +use render; +use render::CellMetrics; use glib; @@ -106,14 +108,15 @@ impl Cursor { self.start(); } - pub fn draw(&self, - ctx: &cairo::Context, - shell: &shell::State, - char_width: f64, - line_height: f64, - line_y: f64, - double_width: bool, - bg: &Color) { + pub fn draw( + &self, + ctx: &cairo::Context, + font_ctx: &render::Context, + mode: &mode::Mode, + line_y: f64, + double_width: bool, + bg: &Color, + ) { let state = self.state.borrow(); @@ -124,8 +127,7 @@ impl Cursor { let current_point = ctx.get_current_point(); ctx.set_source_rgba(1.0 - bg.0, 1.0 - bg.1, 1.0 - bg.2, 0.6 * state.alpha.0); - let (y, width, height) = - cursor_rect(&shell.mode, char_width, line_height, line_y, double_width); + let (y, width, height) = cursor_rect(mode, font_ctx.cell_metrics(), line_y, double_width); ctx.rectangle(current_point.0, y, width, height); if state.anim_phase == AnimPhase::NoFocus { @@ -136,12 +138,18 @@ impl Cursor { } } -fn cursor_rect(mode: &mode::Mode, - char_width: f64, - line_height: f64, - line_y: f64, - double_width: bool) - -> (f64, f64, f64) { +fn cursor_rect( + mode: &mode::Mode, + cell_metrics: &CellMetrics, + line_y: f64, + double_width: bool, +) -> (f64, f64, f64) { + let &CellMetrics { + line_height, + char_width, + .. + } = cell_metrics; + if let Some(mode_info) = mode.mode_info() { match mode_info.cursor_shape() { None | @@ -258,9 +266,10 @@ mod tests { #[test] fn test_cursor_rect_horizontal() { let mut mode = mode::Mode::new(); - let mode_info = nvim::ModeInfo::new(&vec![(From::from("cursor_shape"), - From::from("horizontal")), - (From::from("cell_percentage"), From::from(25))]); + let mode_info = nvim::ModeInfo::new(&vec![ + (From::from("cursor_shape"), From::from("horizontal")), + (From::from("cell_percentage"), From::from(25)), + ]); mode.update("insert", 0); mode.set_info(true, vec![mode_info.unwrap()]); let char_width = 50.0; @@ -276,9 +285,10 @@ mod tests { #[test] fn test_cursor_rect_horizontal_doublewidth() { let mut mode = mode::Mode::new(); - let mode_info = nvim::ModeInfo::new(&vec![(From::from("cursor_shape"), - From::from("horizontal")), - (From::from("cell_percentage"), From::from(25))]); + let mode_info = nvim::ModeInfo::new(&vec![ + (From::from("cursor_shape"), From::from("horizontal")), + (From::from("cell_percentage"), From::from(25)), + ]); mode.update("insert", 0); mode.set_info(true, vec![mode_info.unwrap()]); let char_width = 50.0; @@ -294,9 +304,10 @@ mod tests { #[test] fn test_cursor_rect_vertical() { let mut mode = mode::Mode::new(); - let mode_info = nvim::ModeInfo::new(&vec![(From::from("cursor_shape"), - From::from("vertical")), - (From::from("cell_percentage"), From::from(25))]); + let mode_info = nvim::ModeInfo::new(&vec![ + (From::from("cursor_shape"), From::from("vertical")), + (From::from("cell_percentage"), From::from(25)), + ]); mode.update("insert", 0); mode.set_info(true, vec![mode_info.unwrap()]); let char_width = 50.0; diff --git a/src/render/mod.rs b/src/render/mod.rs index 3804197..67f77bf 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -3,22 +3,25 @@ mod context; pub use self::context::Context; pub use self::context::CellMetrics; +use mode; use color; use sys::pango::*; use pango; use cairo; +use cursor; use pangocairo::CairoContextExt; use ui_model; pub fn render( ctx: &cairo::Context, + cursor: &cursor::Cursor, font_ctx: &context::Context, ui_model: &ui_model::UiModel, color_model: &color::ColorModel, + mode: &mode::Mode, ) { // TODO: underline // TODO: undercurl - // TODO: cursor ctx.set_source_rgb( color_model.bg_color.0, color_model.bg_color.1, @@ -33,21 +36,24 @@ pub fn render( } = font_ctx.cell_metrics(); let mut line_y = 0.0; let ascent = font_ctx.ascent(); + let (cursor_row, cursor_col) = ui_model.get_cursor(); - for line in ui_model.model() { + for (row, line) in ui_model.model().iter().enumerate() { let mut line_x = 0.0; - for i in 0..line.line.len() { + for col in 0..line.line.len() { + let cell = &line.line[col]; - if let Some(item) = line.item_line[i].as_ref() { - let (bg, fg) = color_model.cell_colors(&line.line[i]); + // draw cell + if let Some(item) = line.item_line[col].as_ref() { + let (bg, fg) = color_model.cell_colors(cell); if let Some(bg) = bg { ctx.set_source_rgb(bg.0, bg.1, bg.2); ctx.rectangle( line_x, line_y, - char_width * line.item_len_from_idx(i) as f64, + char_width * line.item_len_from_idx(col) as f64, line_height, ); ctx.fill(); @@ -59,14 +65,26 @@ pub fn render( ctx.show_glyph_string(item.font(), glyphs); } - } else if !line.is_binded_to_item(i) { - let bg = color_model.cell_bg(&line.line[i]); + } else if !line.is_binded_to_item(col) { + let bg = color_model.cell_bg(cell); if let Some(bg) = bg { ctx.set_source_rgb(bg.0, bg.1, bg.2); ctx.rectangle(line_x, line_y, char_width, line_height); ctx.fill(); } } + + if row == cursor_row && col == cursor_col { + cursor.draw( + ctx, + font_ctx, + mode, + line_y, + false, //TODO: double_width, + color_model.actual_cell_bg(cell), + ); + } + line_x += char_width; } line_y += line_height; diff --git a/src/shell.rs b/src/shell.rs index 041b01c..04a487f 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -54,7 +54,7 @@ pub struct State { cur_attrs: Option, mouse_enabled: bool, nvim: Rc>, - font_ctx: render::Context, + pub font_ctx: render::Context, cursor: Option, popup_menu: RefCell, settings: Rc>, @@ -182,7 +182,8 @@ impl State { let mut rect = rect.as_ref().clone(); rect.extend_by_items(&self.model); - let (x, y, width, height) = rect.to_area_extend_ink(&self.model, self.font_ctx.cell_metrics()); + let (x, y, width, height) = + rect.to_area_extend_ink(&self.model, self.font_ctx.cell_metrics()); self.drawing_area.queue_draw_area(x, y, width, height); } } @@ -220,7 +221,8 @@ impl State { fn set_im_location(&self) { let (row, col) = self.model.get_cursor(); - let (x, y, width, height) = ModelRect::point(col, row).to_area(self.font_ctx.cell_metrics()); + let (x, y, width, height) = + ModelRect::point(col, row).to_area(self.font_ctx.cell_metrics()); self.im_context.set_cursor_location(&gdk::Rectangle { x, @@ -567,7 +569,14 @@ fn gtk_draw(state_arc: &Arc>, ctx: &cairo::Context) -> Inhibit { let mut state = state_arc.borrow_mut(); if state.nvim.borrow().is_initialized() { - render::render(ctx, &state.font_ctx, &state.model, &state.color_model); + render::render( + ctx, + state.cursor.as_ref().unwrap(), + &state.font_ctx, + &state.model, + &state.color_model, + &state.mode, + ); request_window_resize(&mut *state); } else if state.nvim.borrow().is_initializing() { draw_initializing(&*state, ctx); @@ -722,11 +731,6 @@ fn draw_initializing(state: &State, ctx: &cairo::Context) { let layout = ctx.create_pango_layout(); let desc = state.get_font_desc(); let alloc = state.drawing_area.get_allocation(); - let &CellMetrics { - line_height, - char_width, - .. - } = state.font_ctx.cell_metrics(); ctx.set_source_rgb( state.color_model.bg_color.0, @@ -755,9 +759,8 @@ fn draw_initializing(state: &State, ctx: &cairo::Context) { ctx.move_to(x + width as f64, y); state.cursor.as_ref().unwrap().draw( ctx, - state, - char_width, - line_height, + &state.font_ctx, + &state.mode, y, false, &state.color_model.bg_color, @@ -1153,4 +1156,3 @@ impl GuiApi for State { settings.set_font_source(FontSource::Rpc); } } -