Cursor rendering
This commit is contained in:
parent
e4bbce3be4
commit
fab0002a56
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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(
|
||||||
ctx: &cairo::Context,
|
&self,
|
||||||
shell: &shell::State,
|
ctx: &cairo::Context,
|
||||||
char_width: f64,
|
font_ctx: &render::Context,
|
||||||
line_height: f64,
|
mode: &mode::Mode,
|
||||||
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;
|
||||||
|
@ -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;
|
||||||
|
28
src/shell.rs
28
src/shell.rs
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user