Popup menu refactor

This commit is contained in:
daa84 2017-05-22 18:38:36 +03:00
parent 6b1840549d
commit 14a154f628
2 changed files with 87 additions and 39 deletions

View File

@ -1,5 +1,5 @@
use std::rc::Rc; use std::rc::Rc;
use std::cell::RefCell; use std::cell::{RefCell, Cell};
use gtk; use gtk;
use gtk::prelude::*; use gtk::prelude::*;
@ -15,13 +15,14 @@ use input;
const MIN_CONTENT_HEIGHT: i32 = 250; const MIN_CONTENT_HEIGHT: i32 = 250;
pub struct PopupMenu { struct State {
popover: gtk::Popover, nvim: Rc<RefCell<Neovim>>,
tree: gtk::TreeView, tree: gtk::TreeView,
renderer: gtk::CellRendererText,
} }
impl PopupMenu { impl State {
pub fn new(drawing: &gtk::DrawingArea, pub fn new(popover: &gtk::Popover,
nvim: Rc<RefCell<Neovim>>, nvim: Rc<RefCell<Neovim>>,
font_desc: &FontDescription, font_desc: &FontDescription,
menu_items: &Vec<Vec<&str>>, menu_items: &Vec<Vec<&str>>,
@ -30,10 +31,7 @@ impl PopupMenu {
y: i32, y: i32,
width: i32, width: i32,
height: i32) height: i32)
-> PopupMenu { -> Self {
let popover = gtk::Popover::new(Some(drawing));
popover.set_modal(false);
let tree = create_list(menu_items, font_desc); let tree = create_list(menu_items, font_desc);
tree.set_can_focus(false); tree.set_can_focus(false);
@ -50,32 +48,25 @@ impl PopupMenu {
scroll.show_all(); scroll.show_all();
popover.add(&scroll); popover.add(&scroll);
popover.set_pointing_to(&gtk::Rectangle { popover.set_pointing_to(&gtk::Rectangle {
x, x,
y, y,
width, width,
height, height,
}); });
popover.connect_key_press_event(move |_, ev| {
input::gtk_key_press(&mut *nvim.borrow_mut(), ev)
});
let popup = PopupMenu { popover, tree }; let state = State {
nvim,
tree,
renderer: gtk::CellRendererText::new(),
};
popup.select(selected); state.select(selected);
popup state
} }
pub fn show(&self) { fn select(&self, selected: i64) {
self.popover.popup();
}
pub fn hide(self) {
self.popover.destroy();
}
pub fn select(&self, selected: i64) {
if selected >= 0 { if selected >= 0 {
let selected_path = gtk::TreePath::new_from_string(&format!("{}", selected)); let selected_path = gtk::TreePath::new_from_string(&format!("{}", selected));
self.tree.get_selection().select_path(&selected_path); self.tree.get_selection().select_path(&selected_path);
@ -87,6 +78,63 @@ impl PopupMenu {
} }
} }
pub struct PopupMenu {
popover: gtk::Popover,
state: Rc<Cell<Option<State>>>,
}
impl PopupMenu {
pub fn new(drawing: &gtk::DrawingArea) -> PopupMenu {
let state = Rc::new(Cell::new(None));
let popover = gtk::Popover::new(Some(drawing));
popover.set_modal(false);
let state_ref = state.clone();
popover.connect_key_press_event(move |_, ev| {
let mut state: &mut State = state_ref.get_mut().as_mut().unwrap();
input::gtk_key_press(&mut *state.nvim.borrow_mut(), ev)
});
let popup = PopupMenu { popover, state };
popup
}
pub fn show(&self,
nvim: Rc<RefCell<Neovim>>,
font_desc: &FontDescription,
menu_items: &Vec<Vec<&str>>,
selected: i64,
x: i32,
y: i32,
width: i32,
height: i32) {
self.state
.replace(Some(State::new(&self.popover,
nvim,
font_desc,
menu_items,
selected,
x,
y,
width,
height)));
self.popover.popup();
}
pub fn hide(self) {
self.popover.popdown();
let tree = self.state.get_mut().take().unwrap().tree;
self.popover.remove(&tree);
tree.destroy();
}
pub fn select(&self, selected: i64) {
}
}
fn create_list(menu: &Vec<Vec<&str>>, font_desc: &FontDescription) -> gtk::TreeView { fn create_list(menu: &Vec<Vec<&str>>, font_desc: &FontDescription) -> gtk::TreeView {
let tree = gtk::TreeView::new(); let tree = gtk::TreeView::new();

View File

@ -48,7 +48,7 @@ pub struct State {
nvim: Option<Rc<RefCell<Neovim>>>, nvim: Option<Rc<RefCell<Neovim>>>,
font_desc: FontDescription, font_desc: FontDescription,
cursor: Option<Cursor>, cursor: Option<Cursor>,
popup_menu: Option<PopupMenu>, popup_menu: PopupMenu,
settings: Rc<RefCell<Settings>>, settings: Rc<RefCell<Settings>>,
line_height: Option<f64>, line_height: Option<f64>,
@ -61,9 +61,12 @@ pub struct State {
impl State { impl State {
pub fn new(settings: Rc<RefCell<Settings>>, parent: &Arc<UiMutex<ui::Components>>) -> State { pub fn new(settings: Rc<RefCell<Settings>>, parent: &Arc<UiMutex<ui::Components>>) -> State {
let drawing_area = DrawingArea::new();
let popup_menu = PopupMenu::new(&drawing_area);
State { State {
model: UiModel::new(24, 80), model: UiModel::new(24, 80),
drawing_area: DrawingArea::new(), drawing_area,
nvim: None, nvim: None,
cur_attrs: None, cur_attrs: None,
bg_color: COLOR_BLACK, bg_color: COLOR_BLACK,
@ -73,7 +76,7 @@ impl State {
mouse_enabled: true, mouse_enabled: true,
font_desc: FontDescription::from_string(DEFAULT_FONT_NAME), font_desc: FontDescription::from_string(DEFAULT_FONT_NAME),
cursor: None, cursor: None,
popup_menu: None, popup_menu,
settings: settings, settings: settings,
line_height: None, line_height: None,
@ -822,17 +825,14 @@ impl RedrawEvents for State {
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(line_height, char_width); let (x, y, width, height) = point.to_area(line_height, char_width);
self.popup_menu = Some(PopupMenu::new( self.popup_menu.show(self.nvim.as_ref().unwrap().clone(),
&self.drawing_area,
self.nvim.as_ref().unwrap().clone(),
&self.font_desc, &self.font_desc,
menu, menu,
selected, selected,
x, x,
y, y,
width, width,
height)); height);
self.popup_menu.as_ref().unwrap().show();
} }
_ => (), _ => (),
}; };
@ -841,12 +841,12 @@ impl RedrawEvents for State {
} }
fn popupmenu_hide(&mut self) -> RepaintMode { fn popupmenu_hide(&mut self) -> RepaintMode {
self.popup_menu.take().unwrap().hide(); self.popup_menu.hide();
RepaintMode::Nothing RepaintMode::Nothing
} }
fn popupmenu_select(&mut self, selected: i64) -> RepaintMode { fn popupmenu_select(&mut self, selected: i64) -> RepaintMode {
self.popup_menu.as_mut().unwrap().select(selected); self.popup_menu.select(selected);
RepaintMode::Nothing RepaintMode::Nothing
} }
} }