diff --git a/src/cmd_line.rs b/src/cmd_line.rs new file mode 100644 index 0000000..78c2894 --- /dev/null +++ b/src/cmd_line.rs @@ -0,0 +1,23 @@ +use gtk; +use gtk::prelude::*; + +pub struct CmdLine { + dlg: gtk::Dialog, +} + +impl CmdLine { + pub fn new() -> Self { + let dlg = gtk::Dialog::new(); + dlg.set_modal(true); + dlg.set_destroy_with_parent(true); + + CmdLine { + dlg, + } + } + + pub fn show>(&self, parent: &W) { + self.dlg.set_transient_for(parent); + self.dlg.show(); + } +} diff --git a/src/main.rs b/src/main.rs index 8c1b907..e2bf109 100644 --- a/src/main.rs +++ b/src/main.rs @@ -43,6 +43,7 @@ mod shell; mod input; mod settings; mod cursor; +mod cmd_line; mod shell_dlg; mod popup_menu; mod project; diff --git a/src/nvim/cmd_line.rs b/src/nvim/cmd_line.rs deleted file mode 100644 index 5b539a1..0000000 --- a/src/nvim/cmd_line.rs +++ /dev/null @@ -1,30 +0,0 @@ -use ui_model; - -pub struct CmdLine { - content: Vec<(ui_model::Attrs, String)>, - pos: u64, - firstc: String, - prompt: String, - indent: u64, - level: u64, -} - -impl CmdLine { - pub fn new( - content: Vec<(ui_model::Attrs, String)>, - pos: u64, - firstc: String, - prompt: String, - indent: u64, - level: u64, - ) -> Self { - CmdLine { - content, - pos, - firstc, - prompt, - indent, - level, - } - } -} diff --git a/src/nvim/mod.rs b/src/nvim/mod.rs index d7f477c..74d42c5 100644 --- a/src/nvim/mod.rs +++ b/src/nvim/mod.rs @@ -4,13 +4,11 @@ mod handler; mod mode_info; mod redraw_handler; mod repaint_mode; -mod cmd_line; pub use self::redraw_handler::{RedrawEvents, GuiApi}; pub use self::repaint_mode::RepaintMode; pub use self::client::{NeovimClient, NeovimClientAsync, NeovimRef}; pub use self::mode_info::{ModeInfo, CursorShape}; -pub use self::cmd_line::{CmdLine}; use std::error; use std::fmt; diff --git a/src/nvim/redraw_handler.rs b/src/nvim/redraw_handler.rs index c3b90cd..83bfd31 100644 --- a/src/nvim/redraw_handler.rs +++ b/src/nvim/redraw_handler.rs @@ -37,7 +37,7 @@ pub trait RedrawEvents { fn on_update_sp(&mut self, sp: i64) -> RepaintMode; - fn on_mode_change(&mut self, mode: &str, idx: u64) -> RepaintMode; + fn on_mode_change(&mut self, mode: String, idx: u64) -> RepaintMode; fn on_mouse(&mut self, on: bool) -> RepaintMode; @@ -45,7 +45,7 @@ pub trait RedrawEvents { fn popupmenu_show( &mut self, - menu: &[Vec<&str>], + menu: Vec>, selected: i64, row: u64, col: u64, @@ -118,6 +118,7 @@ macro_rules! map_array { macro_rules! try_arg { ($value:expr, bool) => (try_bool!($value)); ($value:expr, uint) => (try_uint!($value)); + ($value:expr, int) => (try_int!($value)); ($value:expr, str) => ( match $value { Value::String(s) => { @@ -198,31 +199,18 @@ pub fn call( call!(ui->on_set_scroll_region(args: uint, uint, uint, uint)); RepaintMode::Nothing } - "scroll" => ui.on_scroll(try_int!(args[0])), - "update_bg" => ui.on_update_bg(try_int!(args[0])), - "update_fg" => ui.on_update_fg(try_int!(args[0])), - "update_sp" => ui.on_update_sp(try_int!(args[0])), - "mode_change" => ui.on_mode_change(try_str!(args[0]), try_uint!(args[1])), + "scroll" => call!(ui->on_scroll(args: int)), + "update_bg" => call!(ui->on_update_bg(args: int)), + "update_fg" => call!(ui->on_update_fg(args: int)), + "update_sp" => call!(ui->on_update_sp(args: int)), + "mode_change" => call!(ui->on_mode_change(args: str, uint)), "mouse_on" => ui.on_mouse(true), "mouse_off" => ui.on_mouse(false), "busy_start" => ui.on_busy(true), "busy_stop" => ui.on_busy(false), - "popupmenu_show" => { - let menu_items = map_array!(args[0], "Error get menu list array", |item| { - map_array!(item, "Error get menu item array", |col| { - col.as_str().ok_or("Error get menu column") - }) - })?; - - ui.popupmenu_show( - &menu_items, - try_int!(args[1]), - try_uint!(args[2]), - try_uint!(args[3]), - ) - } + "popupmenu_show" => call!(ui->popupmenu_show(args: ext, int, uint, uint)), "popupmenu_hide" => ui.popupmenu_hide(), - "popupmenu_select" => ui.popupmenu_select(try_int!(args[0])), + "popupmenu_select" => call!(ui->popupmenu_select(args: int)), "tabline_update" => { let tabs_out = map_array!(args[1], "Error get tabline list".to_owned(), |tab| { tab.as_map() diff --git a/src/popup_menu.rs b/src/popup_menu.rs index fdb7224..d3a10ed 100644 --- a/src/popup_menu.rs +++ b/src/popup_menu.rs @@ -10,9 +10,10 @@ use gdk::{EventButton, EventType}; use neovim_lib::{Neovim, NeovimApi}; use color::ColorModel; -use nvim::{self, ErrorReport}; +use nvim::{self, ErrorReport, NeovimClient}; use shell; use input; +use render; const MAX_VISIBLE_ROWS: i32 = 10; @@ -41,25 +42,25 @@ impl State { } } - fn before_show(&mut self, shell: &shell::State, menu_items: &[Vec<&str>], selected: i64) { + fn before_show(&mut self, ctx: PopupMenuContext) { if self.nvim.is_none() { - self.nvim = Some(shell.nvim_clone()); + self.nvim = Some(ctx.nvim.clone()); } - self.update_tree(menu_items, shell); - self.select(selected); + self.update_tree(&ctx); + self.select(ctx.selected); } - fn update_tree(&self, menu: &[Vec<&str>], shell: &shell::State) { - if menu.is_empty() { + fn update_tree(&self, ctx: &PopupMenuContext) { + if ctx.menu_items.is_empty() { return; } - self.renderer.set_property_font( - Some(&shell.get_font_desc().to_string()), - ); + self.renderer.set_property_font(Some( + &ctx.font_ctx.font_description().to_string(), + )); - let color_model = &shell.color_model; + let color_model = &ctx.color_model; self.renderer.set_property_foreground_rgba( Some(&color_model.pmenu_fg().into()), ); @@ -69,7 +70,7 @@ impl State { self.update_css(color_model); - let col_count = menu[0].len(); + let col_count = ctx.menu_items[0].len(); let columns = self.tree.get_columns(); if columns.len() != col_count { @@ -85,7 +86,7 @@ impl State { let list_store = gtk::ListStore::new(&vec![gtk::Type::String; col_count]); let all_column_ids: Vec = (0..col_count).map(|i| i as u32).collect(); - for line in menu { + for line in ctx.menu_items { let line_array: Vec<&glib::ToValue> = line.iter().map(|v| v as &glib::ToValue).collect(); list_store.insert_with_values(None, &all_column_ids, &line_array[..]); @@ -215,30 +216,17 @@ impl PopupMenu { self.open } - pub fn show( - &mut self, - shell: &shell::State, - menu_items: &[Vec<&str>], - selected: i64, - x: i32, - y: i32, - width: i32, - height: i32, - ) { + pub fn show(&mut self, ctx: PopupMenuContext) { self.open = true; self.popover.set_pointing_to(>k::Rectangle { - x, - y, - width, - height, + x: ctx.x, + y: ctx.y, + width: ctx.width, + height: ctx.height, }); - self.state.borrow_mut().before_show( - shell, - menu_items, - selected, - ); + self.state.borrow_mut().before_show(ctx); self.popover.popup() } @@ -255,6 +243,17 @@ impl PopupMenu { } } +pub struct PopupMenuContext<'a> { + pub nvim: &'a Rc, + pub color_model: &'a ColorModel, + pub font_ctx: &'a render::Context, + pub menu_items: &'a [Vec], + pub selected: i64, + pub x: i32, + pub y: i32, + pub width: i32, + pub height: i32, +} fn tree_button_press(tree: >k::TreeView, ev: &EventButton, nvim: &mut Neovim) -> Inhibit { if ev.get_event_type() != EventType::ButtonPress { diff --git a/src/shell.rs b/src/shell.rs index 476735a..ddb3275 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -23,14 +23,14 @@ use ui_model::{UiModel, Attrs, ModelRect}; use color::{ColorModel, Color, COLOR_BLACK, COLOR_WHITE, COLOR_RED}; use nvim::{self, RedrawEvents, GuiApi, RepaintMode, ErrorReport, NeovimClient, NeovimRef, - NeovimClientAsync, CmdLine}; + NeovimClientAsync}; -use input; -use input::keyval_to_input_string; +use input::{self, keyval_to_input_string}; use cursor::Cursor; use ui::UiMutex; -use popup_menu::PopupMenu; +use popup_menu::{self, PopupMenu}; use tabline::Tabline; +use cmd_line::CmdLine; use error; use mode; use render; @@ -66,7 +66,8 @@ pub struct State { nvim: Rc, pub font_ctx: render::Context, cursor: Option, - popup_menu: RefCell, + popup_menu: PopupMenu, + cmd_line: CmdLine, settings: Rc>, pub mode: mode::Mode, @@ -88,7 +89,7 @@ pub struct State { impl State { pub fn new(settings: Rc>, options: ShellOptions) -> State { let drawing_area = gtk::DrawingArea::new(); - let popup_menu = RefCell::new(PopupMenu::new(&drawing_area)); + let popup_menu = PopupMenu::new(&drawing_area); let font_ctx = render::Context::new(FontDescription::from_string(DEFAULT_FONT_NAME)); State { @@ -100,6 +101,7 @@ impl State { font_ctx, cursor: None, popup_menu, + cmd_line: CmdLine::new(), settings, mode: mode::Mode::new(), @@ -183,7 +185,7 @@ impl State { } fn close_popup_menu(&self) { - if self.popup_menu.borrow().is_open() { + if self.popup_menu.is_open() { if let Some(mut nvim) = self.nvim() { nvim.input("").report_err(&mut *nvim); } @@ -306,6 +308,14 @@ impl State { } + fn get_window(&self) -> gtk::Window { + self.drawing_area + .get_toplevel() + .unwrap() + .downcast() + .unwrap() + } + fn resize_main_window(&mut self) { let &CellMetrics { line_height, @@ -319,11 +329,7 @@ impl State { let request_width = (self.model.columns as f64 * char_width) as i32; if width != request_width || height != request_height { - let window: gtk::Window = self.drawing_area - .get_toplevel() - .unwrap() - .downcast() - .unwrap(); + let window = self.get_window(); let (win_width, win_height) = window.get_size(); let h_border = win_width - width; let v_border = win_height - height; @@ -998,8 +1004,8 @@ impl RedrawEvents for State { RepaintMode::Nothing } - fn on_mode_change(&mut self, mode: &str, idx: u64) -> RepaintMode { - self.mode.update(mode, idx as usize); + fn on_mode_change(&mut self, mode: String, idx: u64) -> RepaintMode { + self.mode.update(&mode, idx as usize); RepaintMode::Area(self.model.cur_point()) } @@ -1019,7 +1025,7 @@ impl RedrawEvents for State { fn popupmenu_show( &mut self, - menu: &[Vec<&str>], + menu: Vec>, selected: i64, row: u64, col: u64, @@ -1027,26 +1033,30 @@ impl RedrawEvents for State { let point = ModelRect::point(col as usize, row as usize); let (x, y, width, height) = point.to_area(self.font_ctx.cell_metrics()); - self.popup_menu.borrow_mut().show( - self, - menu, + let context = popup_menu::PopupMenuContext { + nvim: &self.nvim, + color_model: &self.color_model, + font_ctx: &self.font_ctx, + menu_items: &menu, selected, x, y, width, - height, - ); + height + }; + + self.popup_menu.show(context); RepaintMode::Nothing } fn popupmenu_hide(&mut self) -> RepaintMode { - self.popup_menu.borrow_mut().hide(); + self.popup_menu.hide(); RepaintMode::Nothing } fn popupmenu_select(&mut self, selected: i64) -> RepaintMode { - self.popup_menu.borrow().select(selected); + self.popup_menu.select(selected); RepaintMode::Nothing } @@ -1079,6 +1089,7 @@ impl RedrawEvents for State { indent: u64, level: u64, ) -> RepaintMode { + self.cmd_line.show(&self.get_window()); // TODO: implement RepaintMode::Nothing }