Cursor rendering

This commit is contained in:
daa84 2017-09-07 18:51:12 +03:00
parent e4bbce3be4
commit fab0002a56
4 changed files with 85 additions and 46 deletions

View File

@ -81,4 +81,12 @@ impl ColorModel {
cell.attrs.foreground.as_ref().or(Some(&self.fg_color)) 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)
}
}
} }

View File

@ -6,6 +6,8 @@ use mode;
use nvim; use nvim;
use nvim::{RepaintMode, RedrawEvents}; use nvim::{RepaintMode, RedrawEvents};
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use render;
use render::CellMetrics;
use glib; use glib;
@ -106,14 +108,15 @@ impl Cursor {
self.start(); self.start();
} }
pub fn draw(&self, pub fn draw(
&self,
ctx: &cairo::Context, ctx: &cairo::Context,
shell: &shell::State, font_ctx: &render::Context,
char_width: f64, mode: &mode::Mode,
line_height: f64,
line_y: f64, line_y: f64,
double_width: bool, double_width: bool,
bg: &Color) { bg: &Color,
) {
let state = self.state.borrow(); let state = self.state.borrow();
@ -124,8 +127,7 @@ impl Cursor {
let current_point = ctx.get_current_point(); 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); 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) = let (y, width, height) = cursor_rect(mode, font_ctx.cell_metrics(), line_y, double_width);
cursor_rect(&shell.mode, char_width, line_height, line_y, double_width);
ctx.rectangle(current_point.0, y, width, height); ctx.rectangle(current_point.0, y, width, height);
if state.anim_phase == AnimPhase::NoFocus { if state.anim_phase == AnimPhase::NoFocus {
@ -136,12 +138,18 @@ impl Cursor {
} }
} }
fn cursor_rect(mode: &mode::Mode, fn cursor_rect(
char_width: f64, mode: &mode::Mode,
line_height: f64, cell_metrics: &CellMetrics,
line_y: f64, line_y: f64,
double_width: bool) double_width: bool,
-> (f64, f64, f64) { ) -> (f64, f64, f64) {
let &CellMetrics {
line_height,
char_width,
..
} = cell_metrics;
if let Some(mode_info) = mode.mode_info() { if let Some(mode_info) = mode.mode_info() {
match mode_info.cursor_shape() { match mode_info.cursor_shape() {
None | None |
@ -258,9 +266,10 @@ mod tests {
#[test] #[test]
fn test_cursor_rect_horizontal() { fn test_cursor_rect_horizontal() {
let mut mode = mode::Mode::new(); let mut mode = mode::Mode::new();
let mode_info = nvim::ModeInfo::new(&vec![(From::from("cursor_shape"), let mode_info = nvim::ModeInfo::new(&vec![
From::from("horizontal")), (From::from("cursor_shape"), From::from("horizontal")),
(From::from("cell_percentage"), From::from(25))]); (From::from("cell_percentage"), From::from(25)),
]);
mode.update("insert", 0); mode.update("insert", 0);
mode.set_info(true, vec![mode_info.unwrap()]); mode.set_info(true, vec![mode_info.unwrap()]);
let char_width = 50.0; let char_width = 50.0;
@ -276,9 +285,10 @@ mod tests {
#[test] #[test]
fn test_cursor_rect_horizontal_doublewidth() { fn test_cursor_rect_horizontal_doublewidth() {
let mut mode = mode::Mode::new(); let mut mode = mode::Mode::new();
let mode_info = nvim::ModeInfo::new(&vec![(From::from("cursor_shape"), let mode_info = nvim::ModeInfo::new(&vec![
From::from("horizontal")), (From::from("cursor_shape"), From::from("horizontal")),
(From::from("cell_percentage"), From::from(25))]); (From::from("cell_percentage"), From::from(25)),
]);
mode.update("insert", 0); mode.update("insert", 0);
mode.set_info(true, vec![mode_info.unwrap()]); mode.set_info(true, vec![mode_info.unwrap()]);
let char_width = 50.0; let char_width = 50.0;
@ -294,9 +304,10 @@ mod tests {
#[test] #[test]
fn test_cursor_rect_vertical() { fn test_cursor_rect_vertical() {
let mut mode = mode::Mode::new(); let mut mode = mode::Mode::new();
let mode_info = nvim::ModeInfo::new(&vec![(From::from("cursor_shape"), let mode_info = nvim::ModeInfo::new(&vec![
From::from("vertical")), (From::from("cursor_shape"), From::from("vertical")),
(From::from("cell_percentage"), From::from(25))]); (From::from("cell_percentage"), From::from(25)),
]);
mode.update("insert", 0); mode.update("insert", 0);
mode.set_info(true, vec![mode_info.unwrap()]); mode.set_info(true, vec![mode_info.unwrap()]);
let char_width = 50.0; let char_width = 50.0;

View File

@ -3,22 +3,25 @@ mod context;
pub use self::context::Context; pub use self::context::Context;
pub use self::context::CellMetrics; pub use self::context::CellMetrics;
use mode;
use color; use color;
use sys::pango::*; use sys::pango::*;
use pango; use pango;
use cairo; use cairo;
use cursor;
use pangocairo::CairoContextExt; use pangocairo::CairoContextExt;
use ui_model; use ui_model;
pub fn render( pub fn render(
ctx: &cairo::Context, ctx: &cairo::Context,
cursor: &cursor::Cursor,
font_ctx: &context::Context, font_ctx: &context::Context,
ui_model: &ui_model::UiModel, ui_model: &ui_model::UiModel,
color_model: &color::ColorModel, color_model: &color::ColorModel,
mode: &mode::Mode,
) { ) {
// TODO: underline // TODO: underline
// TODO: undercurl // TODO: undercurl
// TODO: cursor
ctx.set_source_rgb( ctx.set_source_rgb(
color_model.bg_color.0, color_model.bg_color.0,
color_model.bg_color.1, color_model.bg_color.1,
@ -33,21 +36,24 @@ pub fn render(
} = font_ctx.cell_metrics(); } = font_ctx.cell_metrics();
let mut line_y = 0.0; let mut line_y = 0.0;
let ascent = font_ctx.ascent(); 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; 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() { // draw cell
let (bg, fg) = color_model.cell_colors(&line.line[i]); if let Some(item) = line.item_line[col].as_ref() {
let (bg, fg) = color_model.cell_colors(cell);
if let Some(bg) = bg { if let Some(bg) = bg {
ctx.set_source_rgb(bg.0, bg.1, bg.2); ctx.set_source_rgb(bg.0, bg.1, bg.2);
ctx.rectangle( ctx.rectangle(
line_x, line_x,
line_y, line_y,
char_width * line.item_len_from_idx(i) as f64, char_width * line.item_len_from_idx(col) as f64,
line_height, line_height,
); );
ctx.fill(); ctx.fill();
@ -59,14 +65,26 @@ pub fn render(
ctx.show_glyph_string(item.font(), glyphs); ctx.show_glyph_string(item.font(), glyphs);
} }
} else if !line.is_binded_to_item(i) { } else if !line.is_binded_to_item(col) {
let bg = color_model.cell_bg(&line.line[i]); let bg = color_model.cell_bg(cell);
if let Some(bg) = bg { if let Some(bg) = bg {
ctx.set_source_rgb(bg.0, bg.1, bg.2); ctx.set_source_rgb(bg.0, bg.1, bg.2);
ctx.rectangle(line_x, line_y, char_width, line_height); ctx.rectangle(line_x, line_y, char_width, line_height);
ctx.fill(); 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_x += char_width;
} }
line_y += line_height; line_y += line_height;

View File

@ -54,7 +54,7 @@ pub struct State {
cur_attrs: Option<Attrs>, cur_attrs: Option<Attrs>,
mouse_enabled: bool, mouse_enabled: bool,
nvim: Rc<RefCell<NeovimClient>>, nvim: Rc<RefCell<NeovimClient>>,
font_ctx: render::Context, pub font_ctx: render::Context,
cursor: Option<Cursor>, cursor: Option<Cursor>,
popup_menu: RefCell<PopupMenu>, popup_menu: RefCell<PopupMenu>,
settings: Rc<RefCell<Settings>>, settings: Rc<RefCell<Settings>>,
@ -182,7 +182,8 @@ impl State {
let mut rect = rect.as_ref().clone(); let mut rect = rect.as_ref().clone();
rect.extend_by_items(&self.model); 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); self.drawing_area.queue_draw_area(x, y, width, height);
} }
} }
@ -220,7 +221,8 @@ impl State {
fn set_im_location(&self) { fn set_im_location(&self) {
let (row, col) = self.model.get_cursor(); 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 { self.im_context.set_cursor_location(&gdk::Rectangle {
x, x,
@ -567,7 +569,14 @@ fn gtk_draw(state_arc: &Arc<UiMutex<State>>, ctx: &cairo::Context) -> Inhibit {
let mut state = state_arc.borrow_mut(); let mut state = state_arc.borrow_mut();
if state.nvim.borrow().is_initialized() { 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); request_window_resize(&mut *state);
} else if state.nvim.borrow().is_initializing() { } else if state.nvim.borrow().is_initializing() {
draw_initializing(&*state, ctx); draw_initializing(&*state, ctx);
@ -722,11 +731,6 @@ fn draw_initializing(state: &State, ctx: &cairo::Context) {
let layout = ctx.create_pango_layout(); let layout = ctx.create_pango_layout();
let desc = state.get_font_desc(); let desc = state.get_font_desc();
let alloc = state.drawing_area.get_allocation(); let alloc = state.drawing_area.get_allocation();
let &CellMetrics {
line_height,
char_width,
..
} = state.font_ctx.cell_metrics();
ctx.set_source_rgb( ctx.set_source_rgb(
state.color_model.bg_color.0, 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); ctx.move_to(x + width as f64, y);
state.cursor.as_ref().unwrap().draw( state.cursor.as_ref().unwrap().draw(
ctx, ctx,
state, &state.font_ctx,
char_width, &state.mode,
line_height,
y, y,
false, false,
&state.color_model.bg_color, &state.color_model.bg_color,
@ -1153,4 +1156,3 @@ impl GuiApi for State {
settings.set_font_source(FontSource::Rpc); settings.set_font_source(FontSource::Rpc);
} }
} }