2017-04-19 08:40:53 +00:00
|
|
|
use std::rc::Rc;
|
2017-05-23 15:17:45 +00:00
|
|
|
use std::cell::RefCell;
|
2017-05-24 14:51:16 +00:00
|
|
|
use std::cmp::min;
|
2018-04-05 20:25:18 +00:00
|
|
|
use std::iter;
|
2017-04-19 08:40:53 +00:00
|
|
|
|
2017-05-17 15:25:50 +00:00
|
|
|
use gtk;
|
2017-04-19 08:40:53 +00:00
|
|
|
use gtk::prelude::*;
|
|
|
|
use glib;
|
|
|
|
use gdk::{EventButton, EventType};
|
2018-01-08 07:52:28 +00:00
|
|
|
use pango::{self, LayoutExt};
|
2017-04-19 08:40:53 +00:00
|
|
|
|
|
|
|
use neovim_lib::{Neovim, NeovimApi};
|
|
|
|
|
2017-11-16 13:53:58 +00:00
|
|
|
use color::ColorModel;
|
2017-11-18 12:56:37 +00:00
|
|
|
use nvim::{self, ErrorReport, NeovimClient};
|
2017-04-19 08:40:53 +00:00
|
|
|
use input;
|
2017-11-18 12:56:37 +00:00
|
|
|
use render;
|
2017-04-19 08:40:53 +00:00
|
|
|
|
2017-05-24 14:51:16 +00:00
|
|
|
const MAX_VISIBLE_ROWS: i32 = 10;
|
2017-04-19 08:40:53 +00:00
|
|
|
|
2017-05-22 15:38:36 +00:00
|
|
|
struct State {
|
2017-11-10 15:36:54 +00:00
|
|
|
nvim: Option<Rc<nvim::NeovimClient>>,
|
2017-05-22 15:38:36 +00:00
|
|
|
renderer: gtk::CellRendererText,
|
2017-05-23 15:17:45 +00:00
|
|
|
tree: gtk::TreeView,
|
2017-05-24 14:51:16 +00:00
|
|
|
scroll: gtk::ScrolledWindow,
|
2017-11-16 13:53:58 +00:00
|
|
|
css_provider: gtk::CssProvider,
|
2017-12-24 17:41:23 +00:00
|
|
|
info_label: gtk::Label,
|
2018-01-08 07:52:28 +00:00
|
|
|
word_column: gtk::TreeViewColumn,
|
|
|
|
kind_column: gtk::TreeViewColumn,
|
|
|
|
menu_column: gtk::TreeViewColumn,
|
2017-04-19 08:40:53 +00:00
|
|
|
}
|
|
|
|
|
2017-05-22 15:38:36 +00:00
|
|
|
impl State {
|
2017-05-23 15:17:45 +00:00
|
|
|
pub fn new() -> Self {
|
2017-11-16 13:53:58 +00:00
|
|
|
let tree = gtk::TreeView::new();
|
2018-03-31 19:57:53 +00:00
|
|
|
tree.get_selection().set_mode(gtk::SelectionMode::Single);
|
2017-11-16 13:53:58 +00:00
|
|
|
let css_provider = gtk::CssProvider::new();
|
|
|
|
|
|
|
|
let style_context = tree.get_style_context().unwrap();
|
|
|
|
style_context.add_provider(&css_provider, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION);
|
|
|
|
|
2017-12-21 19:54:27 +00:00
|
|
|
let renderer = gtk::CellRendererText::new();
|
2018-01-08 07:52:28 +00:00
|
|
|
renderer.set_property_ellipsize(pango::EllipsizeMode::End);
|
2017-12-21 19:54:27 +00:00
|
|
|
|
|
|
|
// word
|
2018-01-08 07:52:28 +00:00
|
|
|
let word_column = gtk::TreeViewColumn::new();
|
|
|
|
word_column.pack_start(&renderer, true);
|
|
|
|
word_column.add_attribute(&renderer, "text", 0);
|
|
|
|
tree.append_column(&word_column);
|
2017-12-21 19:54:27 +00:00
|
|
|
|
|
|
|
// kind
|
2018-01-08 07:52:28 +00:00
|
|
|
let kind_column = gtk::TreeViewColumn::new();
|
|
|
|
kind_column.pack_start(&renderer, true);
|
|
|
|
kind_column.add_attribute(&renderer, "text", 1);
|
|
|
|
tree.append_column(&kind_column);
|
2017-12-21 19:54:27 +00:00
|
|
|
|
|
|
|
// menu
|
2018-01-08 07:52:28 +00:00
|
|
|
let menu_column = gtk::TreeViewColumn::new();
|
|
|
|
menu_column.pack_start(&renderer, true);
|
|
|
|
menu_column.add_attribute(&renderer, "text", 2);
|
|
|
|
tree.append_column(&menu_column);
|
2017-12-21 19:54:27 +00:00
|
|
|
|
2017-12-24 17:41:23 +00:00
|
|
|
let info_label = gtk::Label::new(None);
|
|
|
|
info_label.set_line_wrap(true);
|
|
|
|
|
2018-04-03 19:05:59 +00:00
|
|
|
let scroll = gtk::ScrolledWindow::new(None, None);
|
|
|
|
|
|
|
|
tree.connect_size_allocate(
|
|
|
|
clone!(scroll, renderer => move |tree, _| on_treeview_allocate(&scroll, tree, &renderer)),
|
|
|
|
);
|
|
|
|
|
2017-05-23 15:17:45 +00:00
|
|
|
State {
|
|
|
|
nvim: None,
|
2017-11-16 13:53:58 +00:00
|
|
|
tree,
|
2017-12-21 19:54:27 +00:00
|
|
|
renderer,
|
2018-04-03 19:05:59 +00:00
|
|
|
scroll,
|
2017-11-16 13:53:58 +00:00
|
|
|
css_provider,
|
2017-12-24 17:41:23 +00:00
|
|
|
info_label,
|
2018-01-08 07:52:28 +00:00
|
|
|
word_column,
|
|
|
|
kind_column,
|
|
|
|
menu_column,
|
2017-05-23 15:17:45 +00:00
|
|
|
}
|
|
|
|
}
|
2017-04-19 08:40:53 +00:00
|
|
|
|
2017-11-18 12:56:37 +00:00
|
|
|
fn before_show(&mut self, ctx: PopupMenuContext) {
|
2017-05-23 15:17:45 +00:00
|
|
|
if self.nvim.is_none() {
|
2017-11-18 12:56:37 +00:00
|
|
|
self.nvim = Some(ctx.nvim.clone());
|
2017-05-23 15:17:45 +00:00
|
|
|
}
|
2017-04-19 08:40:53 +00:00
|
|
|
|
2018-01-01 14:56:10 +00:00
|
|
|
self.scroll.set_max_content_width(ctx.max_width);
|
2017-12-21 19:54:27 +00:00
|
|
|
self.scroll.set_propagate_natural_width(true);
|
2018-04-03 19:05:59 +00:00
|
|
|
self.scroll.set_propagate_natural_height(true);
|
2017-11-18 12:56:37 +00:00
|
|
|
self.update_tree(&ctx);
|
|
|
|
self.select(ctx.selected);
|
2017-05-23 15:17:45 +00:00
|
|
|
}
|
2017-05-22 15:38:36 +00:00
|
|
|
|
2018-02-23 09:36:26 +00:00
|
|
|
fn limit_column_widths(&self, ctx: &PopupMenuContext) {
|
2018-01-08 20:33:35 +00:00
|
|
|
const DEFAULT_PADDING: i32 = 5;
|
|
|
|
|
2018-02-23 09:36:26 +00:00
|
|
|
let layout = ctx.font_ctx.create_layout();
|
|
|
|
let kind_exists = ctx.menu_items.iter().find(|i| i.kind.len() > 0).is_some();
|
2018-01-08 07:52:28 +00:00
|
|
|
let max_width = self.scroll.get_max_content_width();
|
|
|
|
let (xpad, _) = self.renderer.get_padding();
|
|
|
|
|
2018-02-23 09:36:26 +00:00
|
|
|
let max_word_line = ctx.menu_items.iter().max_by_key(|m| m.word.len()).unwrap();
|
2018-01-08 20:33:35 +00:00
|
|
|
layout.set_text(max_word_line.word);
|
|
|
|
let (word_max_width, _) = layout.get_pixel_size();
|
|
|
|
let word_column_width = word_max_width + xpad * 2 + DEFAULT_PADDING;
|
|
|
|
|
|
|
|
if kind_exists {
|
2018-01-08 07:52:28 +00:00
|
|
|
layout.set_text("[v]");
|
|
|
|
let (kind_width, _) = layout.get_pixel_size();
|
|
|
|
|
2018-04-03 19:05:59 +00:00
|
|
|
self.kind_column
|
|
|
|
.set_fixed_width(kind_width + xpad * 2 + DEFAULT_PADDING);
|
2018-01-08 07:52:28 +00:00
|
|
|
self.kind_column.set_visible(true);
|
|
|
|
|
2018-04-03 19:05:59 +00:00
|
|
|
self.word_column
|
|
|
|
.set_fixed_width(min(max_width - kind_width, word_column_width));
|
2018-01-08 20:33:35 +00:00
|
|
|
} else {
|
2018-01-08 07:52:28 +00:00
|
|
|
self.kind_column.set_visible(false);
|
2018-04-03 19:05:59 +00:00
|
|
|
self.word_column
|
|
|
|
.set_fixed_width(min(max_width, word_column_width));
|
2018-01-08 07:52:28 +00:00
|
|
|
}
|
|
|
|
|
2018-02-23 09:36:26 +00:00
|
|
|
let max_menu_line = ctx.menu_items.iter().max_by_key(|m| m.menu.len()).unwrap();
|
2018-01-08 07:52:28 +00:00
|
|
|
|
2018-01-08 20:33:35 +00:00
|
|
|
if max_menu_line.menu.len() > 0 {
|
|
|
|
layout.set_text(max_menu_line.menu);
|
2018-01-08 07:52:28 +00:00
|
|
|
let (menu_max_width, _) = layout.get_pixel_size();
|
2018-04-03 19:05:59 +00:00
|
|
|
self.menu_column
|
|
|
|
.set_fixed_width(menu_max_width + xpad * 2 + DEFAULT_PADDING);
|
2018-01-08 07:52:28 +00:00
|
|
|
self.menu_column.set_visible(true);
|
|
|
|
} else {
|
|
|
|
self.menu_column.set_visible(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-18 12:56:37 +00:00
|
|
|
fn update_tree(&self, ctx: &PopupMenuContext) {
|
|
|
|
if ctx.menu_items.is_empty() {
|
2017-05-23 15:17:45 +00:00
|
|
|
return;
|
|
|
|
}
|
2017-05-22 15:38:36 +00:00
|
|
|
|
2018-02-23 09:36:26 +00:00
|
|
|
self.limit_column_widths(ctx);
|
2018-01-08 07:52:28 +00:00
|
|
|
|
2018-04-03 19:05:59 +00:00
|
|
|
self.renderer
|
|
|
|
.set_property_font(Some(&ctx.font_ctx.font_description().to_string()));
|
2017-11-14 15:38:24 +00:00
|
|
|
|
2017-11-18 12:56:37 +00:00
|
|
|
let color_model = &ctx.color_model;
|
2018-04-03 19:05:59 +00:00
|
|
|
self.renderer
|
|
|
|
.set_property_foreground_rgba(Some(&color_model.pmenu_fg().into()));
|
2017-05-23 15:17:45 +00:00
|
|
|
|
2018-04-03 19:05:59 +00:00
|
|
|
update_css(&self.css_provider, color_model);
|
2017-11-16 13:53:58 +00:00
|
|
|
|
2017-12-24 17:41:23 +00:00
|
|
|
let list_store = gtk::ListStore::new(&vec![gtk::Type::String; 4]);
|
|
|
|
let all_column_ids: Vec<u32> = (0..4).map(|i| i as u32).collect();
|
2017-05-23 15:17:45 +00:00
|
|
|
|
2017-11-18 12:56:37 +00:00
|
|
|
for line in ctx.menu_items {
|
2017-12-24 17:41:23 +00:00
|
|
|
let line_array: [&glib::ToValue; 4] = [&line.word, &line.kind, &line.menu, &line.info];
|
2017-05-23 15:17:45 +00:00
|
|
|
list_store.insert_with_values(None, &all_column_ids, &line_array[..]);
|
|
|
|
}
|
2017-05-22 15:38:36 +00:00
|
|
|
|
2018-04-02 20:18:29 +00:00
|
|
|
self.tree.set_model(&list_store);
|
2017-05-23 15:17:45 +00:00
|
|
|
}
|
|
|
|
|
2017-05-22 15:38:36 +00:00
|
|
|
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);
|
2018-04-03 19:05:59 +00:00
|
|
|
self.tree
|
|
|
|
.scroll_to_cell(Some(&selected_path), None, false, 0.0, 0.0);
|
2017-12-24 17:41:23 +00:00
|
|
|
|
|
|
|
self.show_info_column(&selected_path);
|
2017-05-22 15:38:36 +00:00
|
|
|
} else {
|
|
|
|
self.tree.get_selection().unselect_all();
|
2017-12-24 17:41:23 +00:00
|
|
|
self.info_label.hide();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn show_info_column(&self, selected_path: >k::TreePath) {
|
|
|
|
let model = self.tree.get_model().unwrap();
|
|
|
|
let iter = model.get_iter(selected_path);
|
|
|
|
|
|
|
|
if let Some(iter) = iter {
|
|
|
|
let info_value = model.get_value(&iter, 3);
|
|
|
|
let info: &str = info_value.get().unwrap();
|
|
|
|
|
|
|
|
if !info.trim().is_empty() {
|
|
|
|
self.info_label.show();
|
|
|
|
self.info_label.set_text(&info);
|
|
|
|
} else {
|
|
|
|
self.info_label.hide();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
self.info_label.hide();
|
2017-05-22 15:38:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct PopupMenu {
|
|
|
|
popover: gtk::Popover,
|
2017-05-23 15:17:45 +00:00
|
|
|
open: bool,
|
|
|
|
|
|
|
|
state: Rc<RefCell<State>>,
|
2017-05-22 15:38:36 +00:00
|
|
|
}
|
2017-04-19 08:40:53 +00:00
|
|
|
|
2017-05-22 15:38:36 +00:00
|
|
|
impl PopupMenu {
|
|
|
|
pub fn new(drawing: >k::DrawingArea) -> PopupMenu {
|
2017-05-23 15:17:45 +00:00
|
|
|
let state = State::new();
|
2017-05-22 15:38:36 +00:00
|
|
|
let popover = gtk::Popover::new(Some(drawing));
|
|
|
|
popover.set_modal(false);
|
|
|
|
|
2017-12-24 17:41:23 +00:00
|
|
|
let content = gtk::Box::new(gtk::Orientation::Vertical, 0);
|
|
|
|
|
2017-05-23 15:17:45 +00:00
|
|
|
state.tree.set_headers_visible(false);
|
|
|
|
state.tree.set_can_focus(false);
|
|
|
|
|
2018-04-03 19:05:59 +00:00
|
|
|
state
|
|
|
|
.scroll
|
|
|
|
.set_policy(gtk::PolicyType::Automatic, gtk::PolicyType::Automatic);
|
2017-05-22 15:38:36 +00:00
|
|
|
|
2017-05-24 14:51:16 +00:00
|
|
|
state.scroll.add(&state.tree);
|
|
|
|
state.scroll.show_all();
|
2017-12-24 17:41:23 +00:00
|
|
|
|
|
|
|
content.pack_start(&state.scroll, true, true, 0);
|
|
|
|
content.pack_start(&state.info_label, false, true, 0);
|
|
|
|
content.show();
|
|
|
|
popover.add(&content);
|
2017-05-23 15:17:45 +00:00
|
|
|
|
|
|
|
let state = Rc::new(RefCell::new(state));
|
|
|
|
let state_ref = state.clone();
|
2018-04-03 19:05:59 +00:00
|
|
|
state
|
|
|
|
.borrow()
|
|
|
|
.tree
|
|
|
|
.connect_button_press_event(move |tree, ev| {
|
2017-11-11 15:56:23 +00:00
|
|
|
let state = state_ref.borrow();
|
|
|
|
let nvim = state.nvim.as_ref().unwrap().nvim();
|
|
|
|
if let Some(mut nvim) = nvim {
|
2018-04-05 20:25:18 +00:00
|
|
|
tree_button_press(tree, ev, &mut *nvim, "<C-y>");
|
2017-11-11 15:56:23 +00:00
|
|
|
}
|
2018-04-05 20:25:18 +00:00
|
|
|
Inhibit(false)
|
2018-04-03 19:05:59 +00:00
|
|
|
});
|
2017-05-24 14:51:16 +00:00
|
|
|
|
2017-05-22 15:38:36 +00:00
|
|
|
let state_ref = state.clone();
|
2017-05-17 15:25:50 +00:00
|
|
|
popover.connect_key_press_event(move |_, ev| {
|
2017-11-11 15:56:23 +00:00
|
|
|
let state = state_ref.borrow();
|
|
|
|
let nvim = state.nvim.as_ref().unwrap().nvim();
|
|
|
|
if let Some(mut nvim) = nvim {
|
|
|
|
input::gtk_key_press(&mut *nvim, ev)
|
|
|
|
} else {
|
|
|
|
Inhibit(false)
|
|
|
|
}
|
|
|
|
});
|
2017-04-19 08:40:53 +00:00
|
|
|
|
2017-05-23 15:17:45 +00:00
|
|
|
PopupMenu {
|
|
|
|
popover,
|
|
|
|
state,
|
|
|
|
open: false,
|
|
|
|
}
|
|
|
|
}
|
2017-04-19 08:40:53 +00:00
|
|
|
|
2017-05-23 15:17:45 +00:00
|
|
|
pub fn is_open(&self) -> bool {
|
|
|
|
self.open
|
2017-04-19 08:40:53 +00:00
|
|
|
}
|
|
|
|
|
2017-11-18 12:56:37 +00:00
|
|
|
pub fn show(&mut self, ctx: PopupMenuContext) {
|
2017-05-23 15:17:45 +00:00
|
|
|
self.open = true;
|
|
|
|
|
2017-11-11 15:56:23 +00:00
|
|
|
self.popover.set_pointing_to(>k::Rectangle {
|
2017-11-18 12:56:37 +00:00
|
|
|
x: ctx.x,
|
|
|
|
y: ctx.y,
|
|
|
|
width: ctx.width,
|
|
|
|
height: ctx.height,
|
2017-11-11 15:56:23 +00:00
|
|
|
});
|
2017-11-18 12:56:37 +00:00
|
|
|
self.state.borrow_mut().before_show(ctx);
|
2017-05-25 14:50:56 +00:00
|
|
|
self.popover.popup()
|
2017-04-19 08:40:53 +00:00
|
|
|
}
|
|
|
|
|
2017-05-23 15:17:45 +00:00
|
|
|
pub fn hide(&mut self) {
|
|
|
|
self.open = false;
|
2017-05-25 14:50:56 +00:00
|
|
|
// popdown() in case of fast hide/show
|
|
|
|
// situation does not work and just close popup window
|
|
|
|
// so hide() is important here
|
|
|
|
self.popover.hide();
|
2017-04-19 08:40:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn select(&self, selected: i64) {
|
2017-05-23 15:17:45 +00:00
|
|
|
self.state.borrow().select(selected);
|
2017-04-19 08:40:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-18 12:56:37 +00:00
|
|
|
pub struct PopupMenuContext<'a> {
|
|
|
|
pub nvim: &'a Rc<NeovimClient>,
|
|
|
|
pub color_model: &'a ColorModel,
|
|
|
|
pub font_ctx: &'a render::Context,
|
2018-01-01 14:56:10 +00:00
|
|
|
pub menu_items: &'a [nvim::CompleteItem<'a>],
|
2017-11-18 12:56:37 +00:00
|
|
|
pub selected: i64,
|
|
|
|
pub x: i32,
|
|
|
|
pub y: i32,
|
|
|
|
pub width: i32,
|
|
|
|
pub height: i32,
|
2018-01-01 14:56:10 +00:00
|
|
|
pub max_width: i32,
|
2017-11-18 12:56:37 +00:00
|
|
|
}
|
2017-04-19 08:40:53 +00:00
|
|
|
|
2018-04-05 20:25:18 +00:00
|
|
|
pub fn tree_button_press(
|
|
|
|
tree: >k::TreeView,
|
|
|
|
ev: &EventButton,
|
|
|
|
nvim: &mut Neovim,
|
|
|
|
last_command: &str,
|
|
|
|
) {
|
2017-04-19 08:40:53 +00:00
|
|
|
if ev.get_event_type() != EventType::ButtonPress {
|
2018-04-05 20:25:18 +00:00
|
|
|
return;
|
2017-04-19 08:40:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let (paths, ..) = tree.get_selection().get_selected_rows();
|
|
|
|
let selected_idx = if !paths.is_empty() {
|
|
|
|
let ids = paths[0].get_indices();
|
2018-04-03 19:05:59 +00:00
|
|
|
if !ids.is_empty() {
|
|
|
|
ids[0]
|
|
|
|
} else {
|
|
|
|
-1
|
|
|
|
}
|
2017-04-19 08:40:53 +00:00
|
|
|
} else {
|
|
|
|
-1
|
|
|
|
};
|
|
|
|
|
|
|
|
let (x, y) = ev.get_position();
|
|
|
|
if let Some((Some(tree_path), ..)) = tree.get_path_at_pos(x as i32, y as i32) {
|
|
|
|
let target_idx = tree_path.get_indices()[0];
|
|
|
|
|
|
|
|
let scroll_count = find_scroll_count(selected_idx, target_idx);
|
|
|
|
|
2018-04-05 20:25:18 +00:00
|
|
|
let mut apply_command: String = if target_idx > selected_idx {
|
|
|
|
(0..scroll_count)
|
|
|
|
.map(|_| "<C-n>")
|
|
|
|
.chain(iter::once(last_command))
|
|
|
|
.collect()
|
|
|
|
} else {
|
|
|
|
(0..scroll_count)
|
|
|
|
.map(|_| "<C-p>")
|
|
|
|
.chain(iter::once(last_command))
|
|
|
|
.collect()
|
|
|
|
};
|
2017-04-19 08:40:53 +00:00
|
|
|
|
2017-12-11 20:15:17 +00:00
|
|
|
nvim.input(&apply_command).report_err();
|
2017-04-19 08:40:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn find_scroll_count(selected_idx: i32, target_idx: i32) -> i32 {
|
|
|
|
if selected_idx < 0 {
|
|
|
|
target_idx + 1
|
|
|
|
} else if target_idx > selected_idx {
|
|
|
|
target_idx - selected_idx
|
|
|
|
} else {
|
|
|
|
selected_idx - target_idx
|
|
|
|
}
|
|
|
|
}
|
2017-05-24 14:51:16 +00:00
|
|
|
|
2018-04-03 19:05:59 +00:00
|
|
|
fn on_treeview_allocate(
|
|
|
|
scroll: >k::ScrolledWindow,
|
|
|
|
tree: >k::TreeView,
|
|
|
|
renderer: >k::CellRendererText,
|
|
|
|
) {
|
|
|
|
let treeview_height = calc_treeview_height(tree, renderer);
|
|
|
|
|
|
|
|
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();
|
2017-05-24 14:51:16 +00:00
|
|
|
|
2018-04-03 19:05:59 +00:00
|
|
|
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(_) => (),
|
|
|
|
};
|
|
|
|
}
|
2017-05-24 14:51:16 +00:00
|
|
|
|
2018-04-03 19:05:59 +00:00
|
|
|
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();
|
2017-11-11 15:56:23 +00:00
|
|
|
|
2018-04-03 19:05:59 +00:00
|
|
|
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
|
2017-05-24 14:51:16 +00:00
|
|
|
}
|