One step to cmd line implementation

This commit is contained in:
daa84 2017-11-23 17:57:39 +03:00
parent 519c279c8d
commit d6aa19510c
5 changed files with 240 additions and 88 deletions

View File

@ -1,11 +1,19 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc;
use std::sync::Arc;
use std::cell::RefCell;
use gtk; use gtk;
use gtk::prelude::*; use gtk::prelude::*;
use cairo;
use neovim_lib::Value; use neovim_lib::Value;
use ui_model::{UiModel, Attrs}; use ui_model::{UiModel, Attrs};
use ui::UiMutex;
use render;
use shell;
use cursor;
pub struct Level { pub struct Level {
model: UiModel, model: UiModel,
@ -21,9 +29,9 @@ impl Level {
firstc: String, firstc: String,
prompt: String, prompt: String,
indent: u64, indent: u64,
level: u64,
) -> Self { ) -> Self {
//TODO: double width chars //TODO: double width chars
//TODO: im
let prompt = prompt_lines(firstc, prompt, indent); let prompt = prompt_lines(firstc, prompt, indent);
let content: Vec<(Attrs, Vec<char>)> = content let content: Vec<(Attrs, Vec<char>)> = content
@ -31,14 +39,44 @@ impl Level {
.map(|c| (Attrs::from_value_map(&c.0), c.1.chars().collect())) .map(|c| (Attrs::from_value_map(&c.0), c.1.chars().collect()))
.collect(); .collect();
let width = (content.iter().map(|c| c.1.len()).count() + prompt.last().map_or(0, |p| p.len())) as u64; let width = (content.iter().map(|c| c.1.len()).count() +
prompt.last().map_or(0, |p| p.len())) as u64;
let columns = ((width / Level::COLUMNS_STEP) + 1) * Level::COLUMNS_STEP; let columns = ((width / Level::COLUMNS_STEP) + 1) * Level::COLUMNS_STEP;
let rows = ((prompt.len() as u64 / Level::ROWS_STEP) + 1) * Level::ROWS_STEP; let rows = ((prompt.len() as u64 / Level::ROWS_STEP) + 1) * Level::ROWS_STEP;
let model = UiModel::new(rows, columns); let mut model = UiModel::new(rows, columns);
for (row_idx, prompt_line) in prompt.iter().enumerate() {
for (col_idx, &ch) in prompt_line.iter().enumerate() {
model.set_cursor(row_idx, col_idx);
model.put(ch, false, None);
}
}
let mut col_idx = 0;
let row_idx = if prompt.len() > 0 {
prompt.len() - 1
} else {
0
};
for (attr, ch_list) in content {
for ch in ch_list {
model.set_cursor(row_idx, col_idx);
model.put(ch, false, Some(&attr));
col_idx += 1;
}
}
Level { model } Level { model }
} }
fn update_cache(&mut self, render_state: &shell::RenderState) {
render::shape_dirty(
&render_state.font_ctx,
&mut self.model,
&render_state.color_model,
);
}
} }
fn prompt_lines(firstc: String, prompt: String, indent: u64) -> Vec<Vec<char>> { fn prompt_lines(firstc: String, prompt: String, indent: u64) -> Vec<Vec<char>> {
@ -51,31 +89,109 @@ fn prompt_lines(firstc: String, prompt: String, indent: u64) -> Vec<Vec<char>> {
} }
} }
struct State {
levels: Vec<Level>,
render_state: Rc<RefCell<shell::RenderState>>,
drawing_area: gtk::DrawingArea,
}
impl State {
fn new(drawing_area: gtk::DrawingArea, render_state: Rc<RefCell<shell::RenderState>>) -> Self {
State {
levels: Vec::new(),
render_state,
drawing_area,
}
}
}
impl cursor::CursorRedrawCb for State {
fn queue_redraw_cursor(&mut self) {
// TODO: implement
}
}
pub struct CmdLine { pub struct CmdLine {
popover: gtk::Popover, popover: gtk::Popover,
levels: Vec<Level>, displyed: bool,
state: Arc<UiMutex<State>>,
} }
impl CmdLine { impl CmdLine {
pub fn new(drawing: &gtk::DrawingArea) -> Self { pub fn new(drawing: &gtk::DrawingArea, render_state: Rc<RefCell<shell::RenderState>>) -> Self {
let popover = gtk::Popover::new(Some(drawing)); let popover = gtk::Popover::new(Some(drawing));
popover.set_modal(false); popover.set_modal(false);
let edit_frame = gtk::Frame::new(None); let edit_frame = gtk::Frame::new(None);
edit_frame.set_shadow_type(gtk::ShadowType::In); edit_frame.set_shadow_type(gtk::ShadowType::In);
let drawing_area = gtk::DrawingArea::new(); let drawing_area = gtk::DrawingArea::new();
drawing_area.set_size_request(50, 50);
edit_frame.add(&drawing_area); edit_frame.add(&drawing_area);
edit_frame.show_all(); edit_frame.show_all();
popover.add(&edit_frame); popover.add(&edit_frame);
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);
drawing_area.connect_draw(
clone!(state => move |_, ctx| gtk_draw(ctx, &state, &cursor)),
);
CmdLine { CmdLine {
levels: Vec::new(),
popover, popover,
state,
displyed: false,
} }
} }
pub fn show_level(&mut self, level: Level) { pub fn show_level(
self.levels.push(level); &mut self,
self.popover.popup(); content: Vec<(HashMap<String, Value>, String)>,
pos: u64,
firstc: String,
prompt: String,
indent: u64,
level_idx: u64,
) {
let mut state = self.state.borrow_mut();
let mut level = Level::from(content, pos, firstc, prompt, indent);
level.update_cache(&*state.render_state.borrow());
if level_idx as usize == state.levels.len() {
// TODO: update level
state.levels.pop();
}
state.levels.push(level);
if !self.displyed {
self.displyed = true;
self.popover.popup();
} else {
state.drawing_area.queue_draw()
}
} }
} }
fn gtk_draw(
ctx: &cairo::Context,
state: &Arc<UiMutex<State>>,
cursor: &cursor::Cursor<State>,
) -> Inhibit {
let state = state.borrow();
let level = state.levels.last();
if let Some(level) = level {
let render_state = state.render_state.borrow();
render::render(
ctx,
cursor,
&render_state.font_ctx,
&level.model,
&render_state.color_model,
&render_state.mode,
);
}
Inhibit(false)
}

View File

@ -1,10 +1,8 @@
use cairo; use cairo;
use color::Color; use color::Color;
use ui::UiMutex; use ui::UiMutex;
use shell;
use mode; use mode;
use nvim; use nvim;
use nvim::{RepaintMode, RedrawEvents};
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use render; use render;
use render::CellMetrics; use render::CellMetrics;
@ -44,20 +42,20 @@ enum AnimPhase {
Busy, Busy,
} }
struct State { struct State<CB: CursorRedrawCb> {
alpha: Alpha, alpha: Alpha,
anim_phase: AnimPhase, anim_phase: AnimPhase,
shell: Weak<UiMutex<shell::State>>, redraw_cb: Weak<UiMutex<CB>>,
timer: Option<glib::SourceId>, timer: Option<glib::SourceId>,
} }
impl State { impl <CB: CursorRedrawCb> State <CB> {
fn new(shell: Weak<UiMutex<shell::State>>) -> State { fn new(redraw_cb: Weak<UiMutex<CB>>) -> Self {
State { State {
alpha: Alpha(1.0), alpha: Alpha(1.0),
anim_phase: AnimPhase::Shown, anim_phase: AnimPhase::Shown,
shell: shell, redraw_cb,
timer: None, timer: None,
} }
} }
@ -72,13 +70,13 @@ impl State {
} }
} }
pub struct Cursor { pub struct Cursor <CB: CursorRedrawCb> {
state: Arc<UiMutex<State>>, state: Arc<UiMutex<State<CB>>>,
} }
impl Cursor { impl <CB: CursorRedrawCb + 'static> Cursor <CB> {
pub fn new(shell: Weak<UiMutex<shell::State>>) -> Cursor { pub fn new(redraw_cb: Weak<UiMutex<CB>>) -> Self {
Cursor { state: Arc::new(UiMutex::new(State::new(shell))) } Cursor { state: Arc::new(UiMutex::new(State::new(redraw_cb))) }
} }
pub fn start(&mut self) { pub fn start(&mut self) {
@ -205,7 +203,8 @@ fn cursor_rect(
(line_y, cursor_width, line_height) (line_y, cursor_width, line_height)
} }
} }
fn anim_step(state: &Arc<UiMutex<State>>) -> glib::Continue {
fn anim_step<CB: CursorRedrawCb + 'static> (state: &Arc<UiMutex<State<CB>>>) -> glib::Continue {
let mut mut_state = state.borrow_mut(); let mut mut_state = state.borrow_mut();
let next_event = match mut_state.anim_phase { let next_event = match mut_state.anim_phase {
@ -240,10 +239,9 @@ fn anim_step(state: &Arc<UiMutex<State>>) -> glib::Continue {
AnimPhase::Busy => None, AnimPhase::Busy => None,
}; };
let shell = mut_state.shell.upgrade().unwrap(); let redraw_cb = mut_state.redraw_cb.upgrade().unwrap();
let mut shell = shell.borrow_mut(); let mut redraw_cb = redraw_cb.borrow_mut();
let point = shell.model.cur_point(); redraw_cb.queue_redraw_cursor();
shell.on_redraw(&RepaintMode::Area(point));
if let Some(timeout) = next_event { if let Some(timeout) = next_event {
@ -257,7 +255,7 @@ fn anim_step(state: &Arc<UiMutex<State>>) -> glib::Continue {
} }
impl Drop for Cursor { impl <CB: CursorRedrawCb> Drop for Cursor<CB> {
fn drop(&mut self) { fn drop(&mut self) {
if let Some(timer_id) = self.state.borrow().timer { if let Some(timer_id) = self.state.borrow().timer {
glib::source_remove(timer_id); glib::source_remove(timer_id);
@ -265,6 +263,10 @@ impl Drop for Cursor {
} }
} }
pub trait CursorRedrawCb {
fn queue_redraw_cursor(&mut self);
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -15,9 +15,9 @@ use cursor;
use pangocairo::CairoContextExt; use pangocairo::CairoContextExt;
use ui_model; use ui_model;
pub fn render( pub fn render<RC: cursor::CursorRedrawCb + 'static>(
ctx: &cairo::Context, ctx: &cairo::Context,
cursor: &cursor::Cursor, cursor: &cursor::Cursor<RC>,
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,

View File

@ -26,7 +26,7 @@ use nvim::{self, RedrawEvents, GuiApi, RepaintMode, ErrorReport, NeovimClient, N
NeovimClientAsync}; NeovimClientAsync};
use input::{self, keyval_to_input_string}; use input::{self, keyval_to_input_string};
use cursor::Cursor; use cursor::{Cursor, CursorRedrawCb};
use ui::UiMutex; use ui::UiMutex;
use popup_menu::{self, PopupMenu}; use popup_menu::{self, PopupMenu};
use tabline::Tabline; use tabline::Tabline;
@ -58,19 +58,32 @@ enum ResizeState {
Wait, Wait,
} }
pub struct RenderState {
pub font_ctx: render::Context,
pub color_model: ColorModel,
pub mode: mode::Mode,
}
impl RenderState {
pub fn new() -> Self {
RenderState {
font_ctx: render::Context::new(FontDescription::from_string(DEFAULT_FONT_NAME)),
color_model: ColorModel::new(),
mode: mode::Mode::new(),
}
}
}
pub struct State { pub struct State {
pub model: UiModel, pub model: UiModel,
pub color_model: ColorModel,
cur_attrs: Option<Attrs>, cur_attrs: Option<Attrs>,
mouse_enabled: bool, mouse_enabled: bool,
nvim: Rc<NeovimClient>, nvim: Rc<NeovimClient>,
pub font_ctx: render::Context, cursor: Option<Cursor<State>>,
cursor: Option<Cursor>,
popup_menu: PopupMenu, popup_menu: PopupMenu,
cmd_line: CmdLine, cmd_line: CmdLine,
settings: Rc<RefCell<Settings>>, settings: Rc<RefCell<Settings>>,
render_state: Rc<RefCell<RenderState>>,
pub mode: mode::Mode,
stack: gtk::Stack, stack: gtk::Stack,
drawing_area: gtk::DrawingArea, drawing_area: gtk::DrawingArea,
@ -89,23 +102,20 @@ pub struct State {
impl State { impl State {
pub fn new(settings: Rc<RefCell<Settings>>, options: ShellOptions) -> State { pub fn new(settings: Rc<RefCell<Settings>>, options: ShellOptions) -> State {
let drawing_area = gtk::DrawingArea::new(); let drawing_area = gtk::DrawingArea::new();
let render_state = Rc::new(RefCell::new(RenderState::new()));
let popup_menu = PopupMenu::new(&drawing_area); let popup_menu = PopupMenu::new(&drawing_area);
let cmd_line = CmdLine::new(&drawing_area); let cmd_line = CmdLine::new(&drawing_area, render_state.clone());
let font_ctx = render::Context::new(FontDescription::from_string(DEFAULT_FONT_NAME));
State { State {
model: UiModel::empty(), model: UiModel::empty(),
color_model: ColorModel::new(),
nvim: Rc::new(NeovimClient::new()), nvim: Rc::new(NeovimClient::new()),
cur_attrs: None, cur_attrs: None,
mouse_enabled: true, mouse_enabled: true,
font_ctx,
cursor: None, cursor: None,
popup_menu, popup_menu,
cmd_line, cmd_line,
settings, settings,
render_state,
mode: mode::Mode::new(),
// UI // UI
stack: gtk::Stack::new(), stack: gtk::Stack::new(),
@ -162,12 +172,10 @@ impl State {
} }
} }
pub fn get_font_desc(&self) -> &FontDescription {
self.font_ctx.font_description()
}
pub fn set_font_desc(&mut self, desc: &str) { pub fn set_font_desc(&mut self, desc: &str) {
self.font_ctx.update(FontDescription::from_string(desc)); self.render_state.borrow_mut().font_ctx.update(
FontDescription::from_string(desc),
);
self.model.clear_glyphs(); self.model.clear_glyphs();
self.try_nvim_resize(); self.try_nvim_resize();
self.on_redraw(&RepaintMode::All); self.on_redraw(&RepaintMode::All);
@ -207,18 +215,25 @@ impl State {
self.update_dirty_glyphs(); self.update_dirty_glyphs();
let render_state = self.render_state.borrow();
let cell_metrics = render_state.font_ctx.cell_metrics();
for mut rect in rects { for mut rect in rects {
rect.extend_by_items(&self.model); rect.extend_by_items(&self.model);
let (x, y, width, height) = let (x, y, width, height) = rect.to_area_extend_ink(&self.model, cell_metrics);
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);
} }
} }
#[inline] #[inline]
fn update_dirty_glyphs(&mut self) { fn update_dirty_glyphs(&mut self) {
render::shape_dirty(&self.font_ctx, &mut self.model, &self.color_model); let render_state = self.render_state.borrow();
render::shape_dirty(
&render_state.font_ctx,
&mut self.model,
&render_state.color_model,
);
} }
fn im_commit(&self, ch: &str) { fn im_commit(&self, ch: &str) {
@ -232,7 +247,7 @@ impl State {
line_height, line_height,
char_width, char_width,
.. ..
} = self.font_ctx.cell_metrics(); } = self.render_state.borrow().font_ctx.cell_metrics();
let alloc = self.drawing_area.get_allocation(); let alloc = self.drawing_area.get_allocation();
( (
(alloc.width as f64 / char_width).trunc() as usize, (alloc.width as f64 / char_width).trunc() as usize,
@ -252,7 +267,7 @@ impl State {
let (row, col) = self.model.get_cursor(); let (row, col) = self.model.get_cursor();
let (x, y, width, height) = let (x, y, width, height) =
ModelRect::point(col, row).to_area(self.font_ctx.cell_metrics()); ModelRect::point(col, row).to_area(self.render_state.borrow().font_ctx.cell_metrics());
self.im_context.set_cursor_location(&gdk::Rectangle { self.im_context.set_cursor_location(&gdk::Rectangle {
x, x,
@ -310,11 +325,11 @@ impl State {
} }
fn get_window(&self) -> gtk::Window { fn get_window(&self) -> gtk::Window {
self.drawing_area self.drawing_area
.get_toplevel() .get_toplevel()
.unwrap() .unwrap()
.downcast() .downcast()
.unwrap() .unwrap()
} }
fn resize_main_window(&mut self) { fn resize_main_window(&mut self) {
@ -322,7 +337,7 @@ impl State {
line_height, line_height,
char_width, char_width,
.. ..
} = self.font_ctx.cell_metrics(); } = self.render_state.borrow().font_ctx.cell_metrics();
let width = self.drawing_area.get_allocated_width(); let width = self.drawing_area.get_allocated_width();
let height = self.drawing_area.get_allocated_height(); let height = self.drawing_area.get_allocated_height();
@ -341,7 +356,10 @@ impl State {
fn edit_paste(&self, clipboard: &str) { fn edit_paste(&self, clipboard: &str) {
let nvim = self.nvim(); let nvim = self.nvim();
if let Some(mut nvim) = nvim { if let Some(mut nvim) = nvim {
if self.mode.is(&mode::NvimMode::Insert) || self.mode.is(&mode::NvimMode::Normal) { let render_state = self.render_state.borrow();
if render_state.mode.is(&mode::NvimMode::Insert) ||
render_state.mode.is(&mode::NvimMode::Normal)
{
let paste_code = format!("normal! \"{}P", clipboard); let paste_code = format!("normal! \"{}P", clipboard);
nvim.command(&paste_code).report_err(&mut *nvim); nvim.command(&paste_code).report_err(&mut *nvim);
} else { } else {
@ -682,7 +700,7 @@ fn mouse_input(shell: &mut State, input: &str, state: ModifierType, position: (f
line_height, line_height,
char_width, char_width,
.. ..
} = shell.font_ctx.cell_metrics(); } = shell.render_state.borrow().font_ctx.cell_metrics();
let (x, y) = position; let (x, y) = position;
let col = (x / char_width).trunc() as u64; let col = (x / char_width).trunc() as u64;
let row = (y / line_height).trunc() as u64; let row = (y / line_height).trunc() as u64;
@ -722,13 +740,14 @@ fn gtk_draw(state_arc: &Arc<UiMutex<State>>, ctx: &cairo::Context) -> Inhibit {
let state = state_arc.borrow(); let state = state_arc.borrow();
if state.nvim.is_initialized() { if state.nvim.is_initialized() {
let render_state = state.render_state.borrow();
render::render( render::render(
ctx, ctx,
state.cursor.as_ref().unwrap(), state.cursor.as_ref().unwrap(),
&state.font_ctx, &render_state.font_ctx,
&state.model, &state.model,
&state.color_model, &render_state.color_model,
&state.mode, &render_state.mode,
); );
} else if state.nvim.is_initializing() { } else if state.nvim.is_initializing() {
draw_initializing(&*state, ctx); draw_initializing(&*state, ctx);
@ -852,14 +871,16 @@ fn set_nvim_initialized(state_arc: Arc<UiMutex<State>>) {
} }
fn draw_initializing(state: &State, ctx: &cairo::Context) { fn draw_initializing(state: &State, ctx: &cairo::Context) {
let render_state = state.render_state.borrow();
let color_model = &render_state.color_model;
let layout = ctx.create_pango_layout(); let layout = ctx.create_pango_layout();
let desc = state.get_font_desc(); let desc = render_state.font_ctx.font_description();
let alloc = state.drawing_area.get_allocation(); let alloc = state.drawing_area.get_allocation();
ctx.set_source_rgb( ctx.set_source_rgb(
state.color_model.bg_color.0, color_model.bg_color.0,
state.color_model.bg_color.1, color_model.bg_color.1,
state.color_model.bg_color.2, color_model.bg_color.2,
); );
ctx.paint(); ctx.paint();
@ -872,9 +893,9 @@ fn draw_initializing(state: &State, ctx: &cairo::Context) {
ctx.move_to(x, y); ctx.move_to(x, y);
ctx.set_source_rgb( ctx.set_source_rgb(
state.color_model.fg_color.0, color_model.fg_color.0,
state.color_model.fg_color.1, color_model.fg_color.1,
state.color_model.fg_color.2, color_model.fg_color.2,
); );
ctx.update_pango_layout(&layout); ctx.update_pango_layout(&layout);
ctx.show_pango_layout(&layout); ctx.show_pango_layout(&layout);
@ -883,11 +904,11 @@ 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.font_ctx, &render_state.font_ctx,
&state.mode, &render_state.mode,
y, y,
false, false,
&state.color_model.bg_color, &color_model.bg_color,
); );
} }
@ -947,7 +968,8 @@ impl RedrawEvents for State {
} }
if let Some(mut nvim) = self.nvim.nvim() { if let Some(mut nvim) = self.nvim.nvim() {
self.color_model.theme.update(&mut *nvim); let mut render_state = self.render_state.borrow_mut();
render_state.color_model.theme.update(&mut *nvim);
} }
RepaintMode::Nothing RepaintMode::Nothing
} }
@ -981,34 +1003,38 @@ impl RedrawEvents for State {
} }
fn on_update_bg(&mut self, bg: i64) -> RepaintMode { fn on_update_bg(&mut self, bg: i64) -> RepaintMode {
let mut render_state = self.render_state.borrow_mut();
if bg >= 0 { if bg >= 0 {
self.color_model.bg_color = Color::from_indexed_color(bg as u64); render_state.color_model.bg_color = Color::from_indexed_color(bg as u64);
} else { } else {
self.color_model.bg_color = COLOR_BLACK; render_state.color_model.bg_color = COLOR_BLACK;
} }
RepaintMode::Nothing RepaintMode::Nothing
} }
fn on_update_fg(&mut self, fg: i64) -> RepaintMode { fn on_update_fg(&mut self, fg: i64) -> RepaintMode {
let mut render_state = self.render_state.borrow_mut();
if fg >= 0 { if fg >= 0 {
self.color_model.fg_color = Color::from_indexed_color(fg as u64); render_state.color_model.fg_color = Color::from_indexed_color(fg as u64);
} else { } else {
self.color_model.fg_color = COLOR_WHITE; render_state.color_model.fg_color = COLOR_WHITE;
} }
RepaintMode::Nothing RepaintMode::Nothing
} }
fn on_update_sp(&mut self, sp: i64) -> RepaintMode { fn on_update_sp(&mut self, sp: i64) -> RepaintMode {
let mut render_state = self.render_state.borrow_mut();
if sp >= 0 { if sp >= 0 {
self.color_model.sp_color = Color::from_indexed_color(sp as u64); render_state.color_model.sp_color = Color::from_indexed_color(sp as u64);
} else { } else {
self.color_model.sp_color = COLOR_RED; render_state.color_model.sp_color = COLOR_RED;
} }
RepaintMode::Nothing RepaintMode::Nothing
} }
fn on_mode_change(&mut self, mode: String, idx: u64) -> RepaintMode { fn on_mode_change(&mut self, mode: String, idx: u64) -> RepaintMode {
self.mode.update(&mode, idx as usize); let mut render_state = self.render_state.borrow_mut();
render_state.mode.update(&mode, idx as usize);
RepaintMode::Area(self.model.cur_point()) RepaintMode::Area(self.model.cur_point())
} }
@ -1034,18 +1060,19 @@ impl RedrawEvents for State {
col: u64, col: u64,
) -> RepaintMode { ) -> RepaintMode {
let point = ModelRect::point(col as usize, row as usize); let point = ModelRect::point(col as usize, row as usize);
let (x, y, width, height) = point.to_area(self.font_ctx.cell_metrics()); let render_state = self.render_state.borrow();
let (x, y, width, height) = point.to_area(render_state.font_ctx.cell_metrics());
let context = popup_menu::PopupMenuContext { let context = popup_menu::PopupMenuContext {
nvim: &self.nvim, nvim: &self.nvim,
color_model: &self.color_model, color_model: &render_state.color_model,
font_ctx: &self.font_ctx, font_ctx: &render_state.font_ctx,
menu_items: &menu, menu_items: &menu,
selected, selected,
x, x,
y, y,
width, width,
height height,
}; };
self.popup_menu.show(context); self.popup_menu.show(context);
@ -1079,7 +1106,8 @@ impl RedrawEvents for State {
cursor_style_enabled: bool, cursor_style_enabled: bool,
mode_info: Vec<nvim::ModeInfo>, mode_info: Vec<nvim::ModeInfo>,
) -> RepaintMode { ) -> RepaintMode {
self.mode.set_info(cursor_style_enabled, mode_info); let mut render_state = self.render_state.borrow_mut();
render_state.mode.set_info(cursor_style_enabled, mode_info);
RepaintMode::Nothing RepaintMode::Nothing
} }
@ -1092,12 +1120,18 @@ impl RedrawEvents for State {
indent: u64, indent: u64,
level: u64, level: u64,
) -> RepaintMode { ) -> RepaintMode {
let level = cmd_line::Level::from(content, pos, firstc, prompt, indent, level); self.cmd_line.show_level(content, pos, firstc, prompt, indent, level);
self.cmd_line.show_level(level);
RepaintMode::Nothing RepaintMode::Nothing
} }
} }
impl CursorRedrawCb for State {
fn queue_redraw_cursor(&mut self) {
let cur_point = self.model.cur_point();
self.on_redraw(&RepaintMode::Area(cur_point));
}
}
impl GuiApi for State { impl GuiApi for State {
fn set_font(&mut self, font_desc: &str) { fn set_font(&mut self, font_desc: &str) {
{ {

View File

@ -293,7 +293,7 @@ mod tests {
model.set_cursor(1, 1); model.set_cursor(1, 1);
let rect = model.put(" ", None); let rect = model.put(' ', false, None);
assert_eq!(1, rect.top); assert_eq!(1, rect.top);
assert_eq!(1, rect.left); assert_eq!(1, rect.left);