Use popover instead of popup
This commit is contained in:
parent
1f929023f4
commit
6f8ed8c1fe
@ -1,9 +1,8 @@
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
use gtk;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Window, WindowType, TreeView, TreeViewColumn, TreePath, CellRendererText, ListStore,
|
|
||||||
Type, ScrolledWindow, PolicyType};
|
|
||||||
use glib;
|
use glib;
|
||||||
use pango::FontDescription;
|
use pango::FontDescription;
|
||||||
use gdk::{EventButton, EventType};
|
use gdk::{EventButton, EventType};
|
||||||
@ -17,45 +16,51 @@ use input;
|
|||||||
const MIN_CONTENT_HEIGHT: i32 = 250;
|
const MIN_CONTENT_HEIGHT: i32 = 250;
|
||||||
|
|
||||||
pub struct PopupMenu {
|
pub struct PopupMenu {
|
||||||
menu: Window,
|
popover: gtk::Popover,
|
||||||
list: TreeView,
|
tree: gtk::TreeView,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PopupMenu {
|
impl PopupMenu {
|
||||||
pub fn new(nvim: Rc<RefCell<Neovim>>,
|
pub fn new(drawing: >k::DrawingArea,
|
||||||
|
nvim: Rc<RefCell<Neovim>>,
|
||||||
font_desc: &FontDescription,
|
font_desc: &FontDescription,
|
||||||
menu: &Vec<Vec<&str>>,
|
menu_items: &Vec<Vec<&str>>,
|
||||||
selected: i64,
|
selected: i64,
|
||||||
x: i32,
|
x: i32,
|
||||||
y: i32,
|
y: i32,
|
||||||
grow_up: bool)
|
width: i32,
|
||||||
|
height: i32)
|
||||||
-> PopupMenu {
|
-> PopupMenu {
|
||||||
let win = Window::new(WindowType::Popup);
|
let popover = gtk::Popover::new(Some(drawing));
|
||||||
|
popover.set_modal(false);
|
||||||
|
|
||||||
let tree = create_list(menu, font_desc);
|
let tree = create_list(menu_items, font_desc);
|
||||||
tree.set_can_focus(false);
|
tree.set_can_focus(false);
|
||||||
|
|
||||||
let nvim_ref = nvim.clone();
|
let nvim_ref = nvim.clone();
|
||||||
tree.connect_button_press_event(move |tree, ev| tree_button_press(tree, ev, &mut *nvim_ref.borrow_mut()));
|
tree.connect_button_press_event(move |tree, ev| {
|
||||||
|
tree_button_press(tree, ev, &mut *nvim_ref.borrow_mut())
|
||||||
|
});
|
||||||
|
|
||||||
let scroll = ScrolledWindow::new(None, None);
|
let scroll = gtk::ScrolledWindow::new(None, None);
|
||||||
scroll.set_policy(PolicyType::Never, PolicyType::Automatic);
|
scroll.set_policy(gtk::PolicyType::Never, gtk::PolicyType::Automatic);
|
||||||
scroll.set_min_content_height(MIN_CONTENT_HEIGHT);
|
scroll.set_min_content_height(MIN_CONTENT_HEIGHT);
|
||||||
|
|
||||||
scroll.add(&tree);
|
scroll.add(&tree);
|
||||||
win.add(&scroll);
|
scroll.show_all();
|
||||||
if grow_up {
|
popover.add(&scroll);
|
||||||
win.move_(x, y - MIN_CONTENT_HEIGHT);
|
popover.set_pointing_to(>k::Rectangle {
|
||||||
} else {
|
x,
|
||||||
win.move_(x, y);
|
y,
|
||||||
}
|
width,
|
||||||
|
height,
|
||||||
|
});
|
||||||
|
|
||||||
win.connect_key_press_event(move |_, ev| input::gtk_key_press(&mut *nvim.borrow_mut(), ev));
|
popover.connect_key_press_event(move |_, ev| {
|
||||||
|
input::gtk_key_press(&mut *nvim.borrow_mut(), ev)
|
||||||
|
});
|
||||||
|
|
||||||
let popup = PopupMenu {
|
let popup = PopupMenu { popover, tree };
|
||||||
menu: win,
|
|
||||||
list: tree,
|
|
||||||
};
|
|
||||||
|
|
||||||
popup.select(selected);
|
popup.select(selected);
|
||||||
|
|
||||||
@ -63,28 +68,34 @@ impl PopupMenu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn show(&self) {
|
pub fn show(&self) {
|
||||||
self.menu.show_all();
|
let popover = self.popover.clone();
|
||||||
|
gtk::idle_add(move || {
|
||||||
|
popover.popup();
|
||||||
|
Continue(false)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hide(self) {
|
pub fn hide(self) {
|
||||||
self.menu.destroy();
|
gtk::idle_add(move || {
|
||||||
|
self.popover.destroy();
|
||||||
|
Continue(false)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select(&self, selected: i64) {
|
pub fn select(&self, selected: i64) {
|
||||||
if selected >= 0 {
|
if selected >= 0 {
|
||||||
let selected_path = TreePath::new_from_string(&format!("{}", selected));
|
let selected_path = gtk::TreePath::new_from_string(&format!("{}", selected));
|
||||||
self.list
|
self.tree.get_selection().select_path(&selected_path);
|
||||||
.get_selection()
|
self.tree
|
||||||
.select_path(&selected_path);
|
.scroll_to_cell(Some(&selected_path), None, false, 0.0, 0.0);
|
||||||
self.list.scroll_to_cell(Some(&selected_path), None, false, 0.0, 0.0);
|
|
||||||
} else {
|
} else {
|
||||||
self.list.get_selection().unselect_all();
|
self.tree.get_selection().unselect_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_list(menu: &Vec<Vec<&str>>, font_desc: &FontDescription) -> TreeView {
|
fn create_list(menu: &Vec<Vec<&str>>, font_desc: &FontDescription) -> gtk::TreeView {
|
||||||
let tree = TreeView::new();
|
let tree = gtk::TreeView::new();
|
||||||
|
|
||||||
if menu.is_empty() {
|
if menu.is_empty() {
|
||||||
return tree;
|
return tree;
|
||||||
@ -96,7 +107,7 @@ fn create_list(menu: &Vec<Vec<&str>>, font_desc: &FontDescription) -> TreeView {
|
|||||||
append_column(&tree, i as i32, &font_str);
|
append_column(&tree, i as i32, &font_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
let list_store = ListStore::new(&vec![Type::String; columns]);
|
let list_store = gtk::ListStore::new(&vec![gtk::Type::String; columns]);
|
||||||
let all_column_ids: Vec<u32> = (0..columns).map(|i| i as u32).collect();
|
let all_column_ids: Vec<u32> = (0..columns).map(|i| i as u32).collect();
|
||||||
|
|
||||||
for line in menu {
|
for line in menu {
|
||||||
@ -110,17 +121,17 @@ fn create_list(menu: &Vec<Vec<&str>>, font_desc: &FontDescription) -> TreeView {
|
|||||||
tree
|
tree
|
||||||
}
|
}
|
||||||
|
|
||||||
fn append_column(tree: &TreeView, id: i32, font_str: &str) {
|
fn append_column(tree: >k::TreeView, id: i32, font_str: &str) {
|
||||||
let renderer = CellRendererText::new();
|
let renderer = gtk::CellRendererText::new();
|
||||||
renderer.set_property_font(Some(font_str));
|
renderer.set_property_font(Some(font_str));
|
||||||
|
|
||||||
let column = TreeViewColumn::new();
|
let column = gtk::TreeViewColumn::new();
|
||||||
column.pack_start(&renderer, true);
|
column.pack_start(&renderer, true);
|
||||||
column.add_attribute(&renderer, "text", id);
|
column.add_attribute(&renderer, "text", id);
|
||||||
tree.append_column(&column);
|
tree.append_column(&column);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tree_button_press(tree: &TreeView, ev: &EventButton, nvim: &mut Neovim) -> Inhibit {
|
fn tree_button_press(tree: >k::TreeView, ev: &EventButton, nvim: &mut Neovim) -> Inhibit {
|
||||||
if ev.get_event_type() != EventType::ButtonPress {
|
if ev.get_event_type() != EventType::ButtonPress {
|
||||||
return Inhibit(false);
|
return Inhibit(false);
|
||||||
}
|
}
|
||||||
@ -128,11 +139,7 @@ fn tree_button_press(tree: &TreeView, ev: &EventButton, nvim: &mut Neovim) -> In
|
|||||||
let (paths, ..) = tree.get_selection().get_selected_rows();
|
let (paths, ..) = tree.get_selection().get_selected_rows();
|
||||||
let selected_idx = if !paths.is_empty() {
|
let selected_idx = if !paths.is_empty() {
|
||||||
let ids = paths[0].get_indices();
|
let ids = paths[0].get_indices();
|
||||||
if !ids.is_empty() {
|
if !ids.is_empty() { ids[0] } else { -1 }
|
||||||
ids[0]
|
|
||||||
} else {
|
|
||||||
-1
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
37
src/shell.rs
37
src/shell.rs
@ -345,7 +345,6 @@ fn gtk_focus_out(state: &mut State) -> Inhibit {
|
|||||||
let point = state.model.cur_point();
|
let point = state.model.cur_point();
|
||||||
state.on_redraw(&RepaintMode::Area(point));
|
state.on_redraw(&RepaintMode::Area(point));
|
||||||
|
|
||||||
state.close_popup_menu();
|
|
||||||
Inhibit(false)
|
Inhibit(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -820,37 +819,19 @@ impl RedrawEvents for State {
|
|||||||
-> RepaintMode {
|
-> RepaintMode {
|
||||||
match (&self.line_height, &self.char_width) {
|
match (&self.line_height, &self.char_width) {
|
||||||
(&Some(line_height), &Some(char_width)) => {
|
(&Some(line_height), &Some(char_width)) => {
|
||||||
let parent = sync::Weak::upgrade(&self.parent).unwrap();
|
let point = ModelRect::point(col as usize, row as usize);
|
||||||
let comps = parent.borrow();
|
let (x, y, width, height) = point.to_area(line_height, char_width);
|
||||||
let window = comps.window();
|
|
||||||
let screen = window.get_screen().unwrap();
|
|
||||||
let height = screen.get_height();
|
|
||||||
|
|
||||||
let point = ModelRect::point((col + 1) as usize, (row + 1) as usize);
|
self.popup_menu = Some(PopupMenu::new(
|
||||||
let (x, y, ..) = point.to_area(line_height, char_width);
|
&self.drawing_area,
|
||||||
let translated = self.drawing_area.translate_coordinates(window, x, y);
|
self.nvim.as_ref().unwrap().clone(),
|
||||||
let (x, y) = if let Some((x, y)) = translated {
|
|
||||||
(x, y)
|
|
||||||
} else {
|
|
||||||
(x, y)
|
|
||||||
};
|
|
||||||
|
|
||||||
let (win_x, win_y) = window.get_position();
|
|
||||||
let (abs_x, mut abs_y) = (win_x + x, win_y + y);
|
|
||||||
|
|
||||||
let grow_up = abs_y > height / 2;
|
|
||||||
|
|
||||||
if grow_up {
|
|
||||||
abs_y -= line_height as i32;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.popup_menu = Some(PopupMenu::new(self.nvim.as_ref().unwrap().clone(),
|
|
||||||
&self.font_desc,
|
&self.font_desc,
|
||||||
menu,
|
menu,
|
||||||
selected,
|
selected,
|
||||||
abs_x,
|
x,
|
||||||
abs_y,
|
y,
|
||||||
grow_up));
|
width,
|
||||||
|
height));
|
||||||
self.popup_menu.as_ref().unwrap().show();
|
self.popup_menu.as_ref().unwrap().show();
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
Loading…
Reference in New Issue
Block a user