Show block, blink cursor
This commit is contained in:
parent
29cf31914d
commit
3f62906fac
@ -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,
|
||||
|
@ -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 {
|
||||
@ -211,29 +245,25 @@ 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) {
|
||||
AnimPhase::Hide => if !mut_state.alpha.hide(0.3) {
|
||||
mut_state.anim_phase = AnimPhase::Hidden;
|
||||
|
||||
Some(300)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
},
|
||||
AnimPhase::Hidden => {
|
||||
mut_state.anim_phase = AnimPhase::Show;
|
||||
|
||||
Some(60)
|
||||
}
|
||||
AnimPhase::Show => {
|
||||
if !mut_state.alpha.show(0.3) {
|
||||
AnimPhase::Show => if !mut_state.alpha.show(0.3) {
|
||||
mut_state.anim_phase = AnimPhase::Shown;
|
||||
|
||||
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);
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,13 +84,12 @@ 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 {
|
||||
cell_metrics:
|
||||
&CellMetrics {
|
||||
line_height,
|
||||
char_width,
|
||||
underline_position,
|
||||
@ -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,7 +136,8 @@ fn draw_cell_bg(
|
||||
ctx,
|
||||
line,
|
||||
line_y,
|
||||
cell_metrics: &CellMetrics {
|
||||
cell_metrics:
|
||||
&CellMetrics {
|
||||
char_width,
|
||||
line_height,
|
||||
..
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
|
Loading…
Reference in New Issue
Block a user