One step to cmd line implementation
This commit is contained in:
parent
519c279c8d
commit
d6aa19510c
134
src/cmd_line.rs
134
src/cmd_line.rs
@ -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: >k::DrawingArea) -> Self {
|
pub fn new(drawing: >k::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)
|
||||||
|
}
|
||||||
|
@ -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::*;
|
||||||
|
@ -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,
|
||||||
|
150
src/shell.rs
150
src/shell.rs
@ -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) {
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user