From 1560748f1f7f27f5db29bac8b0af4a3a49a48e41 Mon Sep 17 00:00:00 2001 From: daa Date: Tue, 3 Apr 2018 22:05:59 +0300 Subject: [PATCH] Add colors/height/current --- src/cmd_line.rs | 64 +++++++++++++-- src/nvim/redraw_handler.rs | 1 + src/popup_menu.rs | 159 ++++++++++++++++++------------------- src/shell.rs | 12 ++- 4 files changed, 145 insertions(+), 91 deletions(-) diff --git a/src/cmd_line.rs b/src/cmd_line.rs index 07e7d86..7f76e2e 100644 --- a/src/cmd_line.rs +++ b/src/cmd_line.rs @@ -17,6 +17,7 @@ use ui::UiMutex; use render::{self, CellMetrics}; use shell; use cursor; +use popup_menu; pub struct Level { model_layout: ModelLayout, @@ -265,6 +266,8 @@ pub struct CmdLine { popover: gtk::Popover, wild_tree: gtk::TreeView, wild_scroll: gtk::ScrolledWindow, + wild_css_provider: gtk::CssProvider, + wild_renderer: gtk::CellRendererText, displyed: bool, state: Arc>, } @@ -287,8 +290,7 @@ impl CmdLine { drawing_area.connect_draw(clone!(state => move |_, ctx| gtk_draw(ctx, &state))); - - let (wild_scroll, wild_tree) = CmdLine::create_widlmenu(); + let (wild_scroll, wild_tree, wild_css_provider, wild_renderer) = CmdLine::create_widlmenu(); content.pack_start(&wild_scroll, false, true, 0); popover.add(&content); @@ -301,11 +303,22 @@ impl CmdLine { displyed: false, wild_scroll, wild_tree, + wild_css_provider, + wild_renderer, } } - fn create_widlmenu() -> (gtk::ScrolledWindow, gtk::TreeView) { + fn create_widlmenu() -> ( + gtk::ScrolledWindow, + gtk::TreeView, + gtk::CssProvider, + gtk::CellRendererText, + ) { + let css_provider = gtk::CssProvider::new(); + let tree = gtk::TreeView::new(); + let style_context = tree.get_style_context().unwrap(); + style_context.add_provider(&css_provider, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION); tree.get_selection().set_mode(gtk::SelectionMode::Single); tree.set_headers_visible(false); @@ -327,7 +340,11 @@ impl CmdLine { tree.show_all(); scroll.hide(); - (scroll, tree) + tree.connect_size_allocate( + clone!(scroll, renderer => move |tree, _| on_wild_treeview_allocate(&scroll, tree, &renderer)), + ); + + (scroll, tree, css_provider, renderer) } pub fn show_level(&mut self, ctx: &CmdLineContext) { @@ -446,7 +463,15 @@ impl CmdLine { .set_mode_info(mode_info); } - pub fn show_wildmenu(&self, items: Vec) { + pub fn show_wildmenu(&self, items: Vec, render_state: &shell::RenderState) { + self.wild_renderer + .set_property_font(Some(&render_state.font_ctx.font_description().to_string())); + + self.wild_renderer + .set_property_foreground_rgba(Some(&render_state.color_model.pmenu_fg().into())); + + popup_menu::update_css(&self.wild_css_provider, &render_state.color_model); + let list_store = gtk::ListStore::new(&vec![gtk::Type::String; 1]); for item in items { list_store.insert_with_values(None, &[0], &[&item]); @@ -458,6 +483,21 @@ impl CmdLine { pub fn hide_wildmenu(&self) { self.wild_scroll.hide(); } + + pub fn wildmenu_select(&self, selected: i64) { + if selected >= 0 { + let wild_tree = self.wild_tree.clone(); + idle_add(move || { + let selected_path = gtk::TreePath::new_from_string(&format!("{}", selected)); + wild_tree.get_selection().select_path(&selected_path); + wild_tree.scroll_to_cell(&selected_path, None, false, 0.0, 0.0); + + Continue(false) + }); + } else { + self.wild_tree.get_selection().unselect_all(); + } + } } fn gtk_draw(ctx: &cairo::Context, state: &Arc>) -> Inhibit { @@ -499,6 +539,20 @@ fn gtk_draw(ctx: &cairo::Context, state: &Arc>) -> Inhibit { Inhibit(false) } +fn on_wild_treeview_allocate( + scroll: >k::ScrolledWindow, + tree: >k::TreeView, + renderer: >k::CellRendererText, +) { + let treeview_height = popup_menu::calc_treeview_height(tree, renderer); + + idle_add(clone!(scroll => move || { + scroll + .set_max_content_height(treeview_height); + Continue(false) + })); +} + pub struct CmdLineContext { pub content: Vec<(HashMap, String)>, pub pos: u64, diff --git a/src/nvim/redraw_handler.rs b/src/nvim/redraw_handler.rs index d24e2c6..874dff5 100644 --- a/src/nvim/redraw_handler.rs +++ b/src/nvim/redraw_handler.rs @@ -233,6 +233,7 @@ pub fn call( "cmdline_special_char" => call!(ui->cmdline_special_char(args: str, bool, uint)), "wildmenu_show" => call!(ui->wildmenu_show(args: ext)), "wildmenu_hide" => ui.wildmenu_hide(), + "wildmenu_select" => call!(ui->wildmenu_select(args: int)), _ => { warn!("Event {}({:?})", method, args); RepaintMode::Nothing diff --git a/src/popup_menu.rs b/src/popup_menu.rs index 0451c02..961041a 100644 --- a/src/popup_menu.rs +++ b/src/popup_menu.rs @@ -62,11 +62,17 @@ impl State { let info_label = gtk::Label::new(None); info_label.set_line_wrap(true); + let scroll = gtk::ScrolledWindow::new(None, None); + + tree.connect_size_allocate( + clone!(scroll, renderer => move |tree, _| on_treeview_allocate(&scroll, tree, &renderer)), + ); + State { nvim: None, tree, - scroll: gtk::ScrolledWindow::new(None, None), renderer, + scroll, css_provider, info_label, word_column, @@ -82,6 +88,7 @@ impl State { self.scroll.set_max_content_width(ctx.max_width); self.scroll.set_propagate_natural_width(true); + self.scroll.set_propagate_natural_height(true); self.update_tree(&ctx); self.select(ctx.selected); } @@ -99,27 +106,29 @@ impl State { let (word_max_width, _) = layout.get_pixel_size(); let word_column_width = word_max_width + xpad * 2 + DEFAULT_PADDING; - if kind_exists { layout.set_text("[v]"); let (kind_width, _) = layout.get_pixel_size(); - self.kind_column.set_fixed_width(kind_width + xpad * 2 + DEFAULT_PADDING); + self.kind_column + .set_fixed_width(kind_width + xpad * 2 + DEFAULT_PADDING); self.kind_column.set_visible(true); - self.word_column.set_fixed_width(min(max_width - kind_width, word_column_width)); + self.word_column + .set_fixed_width(min(max_width - kind_width, word_column_width)); } else { self.kind_column.set_visible(false); - self.word_column.set_fixed_width(min(max_width, word_column_width)); + self.word_column + .set_fixed_width(min(max_width, word_column_width)); } - let max_menu_line = ctx.menu_items.iter().max_by_key(|m| m.menu.len()).unwrap(); if max_menu_line.menu.len() > 0 { layout.set_text(max_menu_line.menu); let (menu_max_width, _) = layout.get_pixel_size(); - self.menu_column.set_fixed_width(menu_max_width + xpad * 2 + DEFAULT_PADDING); + self.menu_column + .set_fixed_width(menu_max_width + xpad * 2 + DEFAULT_PADDING); self.menu_column.set_visible(true); } else { self.menu_column.set_visible(false); @@ -133,16 +142,14 @@ impl State { self.limit_column_widths(ctx); - self.renderer.set_property_font( - Some(&ctx.font_ctx.font_description().to_string()), - ); + self.renderer + .set_property_font(Some(&ctx.font_ctx.font_description().to_string())); let color_model = &ctx.color_model; - self.renderer.set_property_foreground_rgba( - Some(&color_model.pmenu_fg().into()), - ); + self.renderer + .set_property_foreground_rgba(Some(&color_model.pmenu_fg().into())); - self.update_css(color_model); + update_css(&self.css_provider, color_model); let list_store = gtk::ListStore::new(&vec![gtk::Type::String; 4]); let all_column_ids: Vec = (0..4).map(|i| i as u32).collect(); @@ -155,39 +162,14 @@ impl State { self.tree.set_model(&list_store); } - fn update_css(&self, color_model: &ColorModel) { - let bg = color_model.pmenu_bg_sel(); - let fg = color_model.pmenu_fg_sel(); - - match gtk::CssProviderExt::load_from_data( - &self.css_provider, - &format!( - ".view :selected {{ color: {}; background-color: {};}}\n - .view {{ background-color: {}; }}", - fg.to_hex(), - bg.to_hex(), - color_model.pmenu_bg().to_hex(), - ).as_bytes(), - ) { - Err(e) => error!("Can't update css {}", e), - Ok(_) => (), - }; - } - fn select(&self, selected: i64) { if selected >= 0 { let selected_path = gtk::TreePath::new_from_string(&format!("{}", selected)); self.tree.get_selection().select_path(&selected_path); - self.tree.scroll_to_cell( - Some(&selected_path), - None, - false, - 0.0, - 0.0, - ); + self.tree + .scroll_to_cell(Some(&selected_path), None, false, 0.0, 0.0); self.show_info_column(&selected_path); - } else { self.tree.get_selection().unselect_all(); self.info_label.hide(); @@ -212,17 +194,6 @@ impl State { self.info_label.hide(); } } - - fn calc_treeview_height(&self) -> i32 { - let (_, natural_size) = self.renderer.get_preferred_height(&self.tree); - let (_, ypad) = self.renderer.get_padding(); - - let row_height = natural_size + ypad; - - let actual_count = self.tree.get_model().unwrap().iter_n_children(None); - - row_height * min(actual_count, MAX_VISIBLE_ROWS) as i32 - } } pub struct PopupMenu { @@ -243,11 +214,9 @@ impl PopupMenu { state.tree.set_headers_visible(false); state.tree.set_can_focus(false); - - state.scroll.set_policy( - gtk::PolicyType::Automatic, - gtk::PolicyType::Automatic, - ); + state + .scroll + .set_policy(gtk::PolicyType::Automatic, gtk::PolicyType::Automatic); state.scroll.add(&state.tree); state.scroll.show_all(); @@ -259,8 +228,10 @@ impl PopupMenu { let state = Rc::new(RefCell::new(state)); let state_ref = state.clone(); - state.borrow().tree.connect_button_press_event( - move |tree, ev| { + state + .borrow() + .tree + .connect_button_press_event(move |tree, ev| { let state = state_ref.borrow(); let nvim = state.nvim.as_ref().unwrap().nvim(); if let Some(mut nvim) = nvim { @@ -268,13 +239,7 @@ impl PopupMenu { } else { Inhibit(false) } - }, - ); - - let state_ref = state.clone(); - state.borrow().tree.connect_size_allocate(move |_, _| { - on_treeview_allocate(state_ref.clone()) - }); + }); let state_ref = state.clone(); popover.connect_key_press_event(move |_, ev| { @@ -345,7 +310,11 @@ fn tree_button_press(tree: >k::TreeView, ev: &EventButton, nvim: &mut Neovim) let (paths, ..) = tree.get_selection().get_selected_rows(); let selected_idx = if !paths.is_empty() { let ids = paths[0].get_indices(); - if !ids.is_empty() { ids[0] } else { -1 } + if !ids.is_empty() { + ids[0] + } else { + -1 + } } else { -1 }; @@ -383,22 +352,46 @@ fn find_scroll_count(selected_idx: i32, target_idx: i32) -> i32 { } } +fn on_treeview_allocate( + scroll: >k::ScrolledWindow, + tree: >k::TreeView, + renderer: >k::CellRendererText, +) { + let treeview_height = calc_treeview_height(tree, renderer); -fn on_treeview_allocate(state: Rc>) { - let treeview_height = state.borrow().calc_treeview_height(); - - idle_add(move || { - let state = state.borrow(); - - // strange solution to make gtk assertions happy - let previous_height = state.scroll.get_max_content_height(); - if previous_height < treeview_height { - state.scroll.set_max_content_height(treeview_height); - state.scroll.set_min_content_height(treeview_height); - } else if previous_height > treeview_height { - state.scroll.set_min_content_height(treeview_height); - state.scroll.set_max_content_height(treeview_height); - } + idle_add(clone!(scroll => move || { + scroll + .set_max_content_height(treeview_height); Continue(false) - }); + })); +} + +pub fn update_css(css_provider: >k::CssProvider, color_model: &ColorModel) { + let bg = color_model.pmenu_bg_sel(); + let fg = color_model.pmenu_fg_sel(); + + match gtk::CssProviderExt::load_from_data( + css_provider, + &format!( + ".view :selected {{ color: {}; background-color: {};}}\n + .view {{ background-color: {}; }}", + fg.to_hex(), + bg.to_hex(), + color_model.pmenu_bg().to_hex(), + ).as_bytes(), + ) { + Err(e) => error!("Can't update css {}", e), + Ok(_) => (), + }; +} + +pub fn calc_treeview_height(tree: >k::TreeView, renderer: >k::CellRendererText) -> i32 { + let (_, natural_size) = renderer.get_preferred_height(tree); + let (_, ypad) = renderer.get_padding(); + + let row_height = natural_size + ypad; + + let actual_count = tree.get_model().unwrap().iter_n_children(None); + + row_height * min(actual_count, MAX_VISIBLE_ROWS) as i32 } diff --git a/src/shell.rs b/src/shell.rs index 6bc89e7..6d02f17 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -1422,15 +1422,21 @@ impl State { RepaintMode::Nothing } - pub fn wildmenu_show(&mut self, items: Vec) -> RepaintMode { - self.cmd_line.show_wildmenu(items); + pub fn wildmenu_show(&self, items: Vec) -> RepaintMode { + self.cmd_line + .show_wildmenu(items, &*self.render_state.borrow()); RepaintMode::Nothing } - pub fn wildmenu_hide(&mut self) -> RepaintMode { + pub fn wildmenu_hide(&self) -> RepaintMode { self.cmd_line.hide_wildmenu(); RepaintMode::Nothing } + + pub fn wildmenu_select(&self, selected: i64) -> RepaintMode { + self.cmd_line.wildmenu_select(selected); + RepaintMode::Nothing + } } impl CursorRedrawCb for State {