Show block, blink cursor

This commit is contained in:
daa 2018-01-21 23:19:00 +03:00
parent 29cf31914d
commit 3f62906fac
5 changed files with 136 additions and 86 deletions

View File

@ -26,6 +26,7 @@ impl Level {
//TODO: double width chars render, also note in text wrapping
//TODO: im
//TODO: cursor
//TODO: delete
pub fn replace_from_ctx(&mut self, ctx: &CmdLineContext, render_state: &shell::RenderState) {
self.replace_line(&ctx.get_lines(), render_state, false);
@ -147,6 +148,7 @@ struct State {
block: Option<Level>,
render_state: Rc<RefCell<shell::RenderState>>,
drawing_area: gtk::DrawingArea,
cursor: Option<cursor::BlinkCursor<State>>,
}
impl State {
@ -156,6 +158,7 @@ impl State {
block: None,
render_state,
drawing_area,
cursor: None,
}
}
@ -180,7 +183,19 @@ impl State {
impl cursor::CursorRedrawCb for State {
fn queue_redraw_cursor(&mut self) {
// TODO: implement
// TODO: take gap and preview offset here
if let Some(ref level) = self.levels.last() {
let model = &level.model_layout.model;
let mut cur_point = model.cur_point();
cur_point.extend_by_items(model);
let render_state = self.render_state.borrow();
let cell_metrics = render_state.font_ctx.cell_metrics();
let (x, y, width, height) = cur_point.to_area_extend_ink(model, cell_metrics);
self.drawing_area.queue_draw_area(x, y, width, height);
}
}
}
@ -202,9 +217,10 @@ impl CmdLine {
let state = Arc::new(UiMutex::new(State::new(drawing_area.clone(), render_state)));
let weak_cb = Arc::downgrade(&state);
let cursor = cursor::Cursor::new(weak_cb);
let cursor = cursor::BlinkCursor::new(weak_cb);
state.borrow_mut().cursor = Some(cursor);
drawing_area.connect_draw(clone!(state => move |_, ctx| gtk_draw(ctx, &state, &cursor)));
drawing_area.connect_draw(clone!(state => move |_, ctx| gtk_draw(ctx, &state)));
CmdLine {
popover,
@ -240,6 +256,7 @@ impl CmdLine {
});
self.popover.popup();
state.cursor.as_mut().unwrap().start();
} else {
state.drawing_area.queue_draw()
}
@ -255,6 +272,7 @@ impl CmdLine {
if state.levels.is_empty() {
self.popover.hide();
self.displyed = false;
state.cursor.as_mut().unwrap().leave_focus();
}
}
@ -298,7 +316,6 @@ impl CmdLine {
fn gtk_draw(
ctx: &cairo::Context,
state: &Arc<UiMutex<State>>,
cursor: &cursor::Cursor<State>,
) -> Inhibit {
let state = state.borrow();
let level = state.levels.last();
@ -314,11 +331,12 @@ fn gtk_draw(
ctx.translate(0.0, gap as f64 / 2.0);
}
render::clear(ctx, &render_state.color_model);
if let Some(block) = block {
// TODO: disable cursor
render::render(
ctx,
cursor,
&cursor::EmptyCursor::new(),
&render_state.font_ctx,
&block.model_layout.model,
&render_state.color_model,
@ -332,7 +350,7 @@ fn gtk_draw(
//TODO: limit model to row filled
render::render(
ctx,
cursor,
state.cursor.as_ref().unwrap(),
&render_state.font_ctx,
&level.model_layout.model,
&render_state.color_model,

View File

@ -50,7 +50,7 @@ struct State<CB: CursorRedrawCb> {
timer: Option<glib::SourceId>,
}
impl <CB: CursorRedrawCb> State <CB> {
impl<CB: CursorRedrawCb> State<CB> {
fn new(redraw_cb: Weak<UiMutex<CB>>) -> Self {
State {
alpha: Alpha(1.0),
@ -69,13 +69,48 @@ impl <CB: CursorRedrawCb> State <CB> {
}
}
pub struct Cursor <CB: CursorRedrawCb> {
pub trait Cursor {
fn draw(
&self,
ctx: &cairo::Context,
font_ctx: &render::Context,
mode: &mode::Mode,
line_y: f64,
double_width: bool,
bg: &Color,
);
}
pub struct EmptyCursor;
impl EmptyCursor {
pub fn new() -> Self {
EmptyCursor { }
}
}
impl Cursor for EmptyCursor {
fn draw(
&self,
_ctx: &cairo::Context,
_font_ctx: &render::Context,
_mode: &mode::Mode,
_line_y: f64,
_double_width: bool,
_bg: &Color,
) {
}
}
pub struct BlinkCursor<CB: CursorRedrawCb> {
state: Arc<UiMutex<State<CB>>>,
}
impl <CB: CursorRedrawCb + 'static> Cursor <CB> {
impl<CB: CursorRedrawCb + 'static> BlinkCursor<CB> {
pub fn new(redraw_cb: Weak<UiMutex<CB>>) -> Self {
Cursor { state: Arc::new(UiMutex::new(State::new(redraw_cb))) }
BlinkCursor {
state: Arc::new(UiMutex::new(State::new(redraw_cb))),
}
}
pub fn start(&mut self) {
@ -110,8 +145,10 @@ impl <CB: CursorRedrawCb + 'static> Cursor <CB> {
pub fn busy_off(&mut self) {
self.start();
}
}
pub fn draw(
impl<CB: CursorRedrawCb> Cursor for BlinkCursor<CB> {
fn draw(
&self,
ctx: &cairo::Context,
font_ctx: &render::Context,
@ -120,7 +157,6 @@ impl <CB: CursorRedrawCb + 'static> Cursor <CB> {
double_width: bool,
bg: &Color,
) {
let state = self.state.borrow();
if state.anim_phase == AnimPhase::Busy {
@ -155,9 +191,7 @@ fn cursor_rect(
if let Some(mode_info) = mode.mode_info() {
match mode_info.cursor_shape() {
None |
Some(&nvim::CursorShape::Unknown) |
Some(&nvim::CursorShape::Block) => {
None | Some(&nvim::CursorShape::Unknown) | Some(&nvim::CursorShape::Block) => {
let cursor_width = if double_width {
char_width * 2.0
} else {
@ -203,7 +237,7 @@ fn cursor_rect(
}
}
fn anim_step<CB: CursorRedrawCb + 'static> (state: &Arc<UiMutex<State<CB>>>) -> glib::Continue {
fn anim_step<CB: CursorRedrawCb + 'static>(state: &Arc<UiMutex<State<CB>>>) -> glib::Continue {
let mut mut_state = state.borrow_mut();
let next_event = match mut_state.anim_phase {
@ -211,30 +245,26 @@ fn anim_step<CB: CursorRedrawCb + 'static> (state: &Arc<UiMutex<State<CB>>>) ->
mut_state.anim_phase = AnimPhase::Hide;
Some(60)
}
AnimPhase::Hide => {
if !mut_state.alpha.hide(0.3) {
mut_state.anim_phase = AnimPhase::Hidden;
AnimPhase::Hide => if !mut_state.alpha.hide(0.3) {
mut_state.anim_phase = AnimPhase::Hidden;
Some(300)
} else {
None
}
}
Some(300)
} else {
None
},
AnimPhase::Hidden => {
mut_state.anim_phase = AnimPhase::Show;
Some(60)
}
AnimPhase::Show => {
if !mut_state.alpha.show(0.3) {
mut_state.anim_phase = AnimPhase::Shown;
AnimPhase::Show => if !mut_state.alpha.show(0.3) {
mut_state.anim_phase = AnimPhase::Shown;
Some(500)
} else {
None
}
}
AnimPhase::NoFocus => None,
Some(500)
} else {
None
},
AnimPhase::NoFocus => None,
AnimPhase::Busy => None,
};
@ -251,10 +281,9 @@ fn anim_step<CB: CursorRedrawCb + 'static> (state: &Arc<UiMutex<State<CB>>>) ->
} else {
glib::Continue(true)
}
}
impl <CB: CursorRedrawCb> Drop for Cursor<CB> {
impl<CB: CursorRedrawCb> Drop for BlinkCursor<CB> {
fn drop(&mut self) {
if let Some(timer_id) = self.state.borrow_mut().timer.take() {
glib::source_remove(timer_id);

View File

@ -14,7 +14,9 @@ pub struct Context {
impl Context {
pub fn new(font_desc: pango::FontDescription) -> Self {
Context { state: ContextState::new(font_desc) }
Context {
state: ContextState::new(font_desc),
}
}
pub fn update(&mut self, font_desc: pango::FontDescription) {
@ -84,20 +86,18 @@ pub struct CellMetrics {
impl CellMetrics {
fn new(font_metrics: &pango::FontMetrics) -> Self {
CellMetrics {
pango_ascent: font_metrics.get_ascent(),
pango_descent: font_metrics.get_descent(),
pango_char_width: font_metrics.get_approximate_digit_width(),
ascent: font_metrics.get_ascent() as f64 / pango::SCALE as f64,
line_height: (font_metrics.get_ascent() + font_metrics.get_descent()) as f64 /
pango::SCALE as f64,
line_height: (font_metrics.get_ascent() + font_metrics.get_descent()) as f64
/ pango::SCALE as f64,
char_width: font_metrics.get_approximate_digit_width() as f64 / pango::SCALE as f64,
underline_position: (font_metrics.get_ascent() -
font_metrics.get_underline_position()) as
f64 / pango::SCALE as f64,
underline_thickness: font_metrics.get_underline_thickness() as f64 /
pango::SCALE as f64,
underline_position: (font_metrics.get_ascent() - font_metrics.get_underline_position())
as f64 / pango::SCALE as f64,
underline_thickness: font_metrics.get_underline_thickness() as f64
/ pango::SCALE as f64,
}
}

View File

@ -4,7 +4,7 @@ mod model_clip_iterator;
pub use self::context::Context;
pub use self::context::CellMetrics;
use self::model_clip_iterator::{RowView, ModelClipIteratorFactory};
use self::model_clip_iterator::{ModelClipIteratorFactory, RowView};
use mode;
use color;
@ -14,24 +14,26 @@ use pango;
use cairo;
use pangocairo;
use cursor;
use cursor::Cursor;
use ui_model;
pub fn render<RC: cursor::CursorRedrawCb + 'static>(
ctx: &cairo::Context,
cursor: &cursor::Cursor<RC>,
font_ctx: &context::Context,
ui_model: &ui_model::UiModel,
color_model: &color::ColorModel,
mode: &mode::Mode,
) {
pub fn clear(ctx: &cairo::Context, color_model: &color::ColorModel) {
ctx.set_source_rgb(
color_model.bg_color.0,
color_model.bg_color.1,
color_model.bg_color.2,
);
ctx.paint();
}
pub fn render<C: Cursor>(
ctx: &cairo::Context,
cursor: &C,
font_ctx: &context::Context,
ui_model: &ui_model::UiModel,
color_model: &color::ColorModel,
mode: &mode::Mode,
) {
let cell_metrics = font_ctx.cell_metrics();
let &CellMetrics { char_width, .. } = cell_metrics;
let (cursor_row, cursor_col) = ui_model.get_cursor();
@ -47,19 +49,19 @@ pub fn render<RC: cursor::CursorRedrawCb + 'static>(
for cell_view in ui_model.get_clip_iterator(ctx, cell_metrics) {
let mut line_x = 0.0;
let RowView { line, row, line_y, .. } = cell_view;
let RowView {
line, row, line_y, ..
} = cell_view;
for (col, cell) in line.line.iter().enumerate() {
draw_cell(&cell_view, color_model, cell, col, line_x);
draw_underline(&cell_view, color_model, cell, line_x);
if row == cursor_row && col == cursor_col {
let double_width = line.line.get(col + 1).map_or(
false,
|c| c.attrs.double_width,
);
let double_width = line.line
.get(col + 1)
.map_or(false, |c| c.attrs.double_width);
ctx.move_to(line_x, line_y);
cursor.draw(
ctx,
@ -82,19 +84,18 @@ fn draw_underline(
cell: &ui_model::Cell,
line_x: f64,
) {
if cell.attrs.underline || cell.attrs.undercurl {
let &RowView {
ctx,
line_y,
cell_metrics: &CellMetrics {
line_height,
char_width,
underline_position,
underline_thickness,
..
},
cell_metrics:
&CellMetrics {
line_height,
char_width,
underline_position,
underline_thickness,
..
},
..
} = cell_view;
@ -106,7 +107,13 @@ fn draw_underline(
let undercurl_height = (underline_thickness * 4.0).min(max_undercurl_height);
let undercurl_y = line_y + underline_position - undercurl_height / 2.0;
pangocairo::functions::error_underline_path(ctx, line_x, undercurl_y, char_width, undercurl_height);
pangocairo::functions::error_underline_path(
ctx,
line_x,
undercurl_y,
char_width,
undercurl_height,
);
} else if cell.attrs.underline {
let fg = color_model.actual_cell_fg(cell);
ctx.set_source_rgb(fg.0, fg.1, fg.2);
@ -129,11 +136,12 @@ fn draw_cell_bg(
ctx,
line,
line_y,
cell_metrics: &CellMetrics {
char_width,
line_height,
..
},
cell_metrics:
&CellMetrics {
char_width,
line_height,
..
},
..
} = cell_view;
@ -157,7 +165,6 @@ fn draw_cell_bg(
ctx.fill();
}
}
}
fn draw_cell(
@ -167,15 +174,11 @@ fn draw_cell(
col: usize,
line_x: f64,
) {
let &RowView {
ctx,
line,
line_y,
cell_metrics: &CellMetrics {
ascent,
..
},
cell_metrics: &CellMetrics { ascent, .. },
..
} = cell_view;
@ -188,7 +191,6 @@ fn draw_cell(
show_glyph_string(ctx, item.font(), glyphs);
}
}
}

View File

@ -26,7 +26,7 @@ use nvim::{self, RedrawEvents, GuiApi, RepaintMode, ErrorReport, NeovimClient,
NeovimRef, NeovimClientAsync, CompleteItem};
use input;
use input::keyval_to_input_string;
use cursor::{Cursor, CursorRedrawCb};
use cursor::{BlinkCursor, Cursor, CursorRedrawCb};
use ui::UiMutex;
use popup_menu::{self, PopupMenu};
use tabline::Tabline;
@ -94,7 +94,7 @@ pub struct State {
cur_attrs: Option<Attrs>,
mouse_enabled: bool,
nvim: Rc<NeovimClient>,
cursor: Option<Cursor<State>>,
cursor: Option<BlinkCursor<State>>,
popup_menu: PopupMenu,
cmd_line: CmdLine,
settings: Rc<RefCell<Settings>>,
@ -449,7 +449,7 @@ impl Shell {
};
let shell_ref = Arc::downgrade(&shell.state);
shell.state.borrow_mut().cursor = Some(Cursor::new(shell_ref));
shell.state.borrow_mut().cursor = Some(BlinkCursor::new(shell_ref));
shell
}
@ -807,6 +807,7 @@ fn gtk_draw(state_arc: &Arc<UiMutex<State>>, ctx: &cairo::Context) -> Inhibit {
let state = state_arc.borrow();
if state.nvim.is_initialized() {
let render_state = state.render_state.borrow();
render::clear(ctx, &render_state.color_model);
render::render(
ctx,
state.cursor.as_ref().unwrap(),