neovim-gtk/src/tabline.rs

147 lines
3.6 KiB
Rust
Raw Normal View History

2017-05-27 16:50:25 +00:00
use std::ops::Deref;
2017-05-27 20:51:22 +00:00
use std::rc::Rc;
use std::cell::RefCell;
2017-05-27 16:50:25 +00:00
use gtk;
use gtk::prelude::*;
2017-05-28 09:29:50 +00:00
use glib::signal;
2017-09-26 13:59:28 +00:00
use pango;
use neovim_lib::NeovimApi;
2017-05-27 16:50:25 +00:00
use neovim_lib::neovim_api::Tabpage;
use nvim;
2017-05-27 20:51:22 +00:00
use nvim::ErrorReport;
struct State {
data: Vec<Tabpage>,
2017-05-28 09:29:50 +00:00
selected: Option<Tabpage>,
nvim: Option<Rc<RefCell<nvim::NeovimClient>>>,
2017-05-27 20:51:22 +00:00
}
impl State {
pub fn new() -> Self {
2017-05-28 09:29:50 +00:00
State {
2017-05-27 20:51:22 +00:00
data: Vec::new(),
2017-05-28 09:29:50 +00:00
selected: None,
2017-05-27 20:51:22 +00:00
nvim: None,
}
}
2017-05-28 09:29:50 +00:00
fn switch_page(&self, idx: u32) {
let target = &self.data[idx as usize];
if Some(target) != self.selected.as_ref() {
let mut nvim = self.nvim.as_ref().unwrap().borrow_mut();
2017-07-25 14:55:31 +00:00
nvim.set_current_tabpage(target).report_err(&mut **nvim);
2017-05-28 09:29:50 +00:00
}
2017-05-27 20:51:22 +00:00
}
}
2017-05-27 16:50:25 +00:00
pub struct Tabline {
tabs: gtk::Notebook,
2017-05-27 20:51:22 +00:00
state: Rc<RefCell<State>>,
2017-05-28 09:29:50 +00:00
switch_handler_id: u64,
2017-05-27 16:50:25 +00:00
}
impl Tabline {
pub fn new() -> Self {
let tabs = gtk::Notebook::new();
tabs.set_can_focus(false);
tabs.set_scrollable(true);
tabs.set_show_border(false);
tabs.set_border_width(0);
2017-05-27 20:51:22 +00:00
tabs.hide();
let state = Rc::new(RefCell::new(State::new()));
let state_ref = state.clone();
2017-05-28 09:29:50 +00:00
let switch_handler_id =
tabs.connect_switch_page(move |_, _, idx| state_ref.borrow().switch_page(idx));
2017-05-27 16:50:25 +00:00
2017-05-28 09:29:50 +00:00
Tabline {
2017-05-27 16:50:25 +00:00
tabs,
2017-05-27 20:51:22 +00:00
state,
2017-05-28 09:29:50 +00:00
switch_handler_id,
2017-05-27 16:50:25 +00:00
}
}
2017-09-26 13:59:28 +00:00
fn update_state(
&self,
nvim: &Rc<RefCell<nvim::NeovimClient>>,
selected: &Tabpage,
tabs: &[(Tabpage, Option<String>)],
) {
2017-05-28 09:29:50 +00:00
let mut state = self.state.borrow_mut();
if state.nvim.is_none() {
state.nvim = Some(nvim.clone());
}
state.selected = Some(selected.clone());
state.data = tabs.iter().map(|item| item.0.clone()).collect();
}
2017-09-26 13:59:28 +00:00
pub fn update_tabs(
&self,
nvim: &Rc<RefCell<nvim::NeovimClient>>,
selected: &Tabpage,
tabs: &[(Tabpage, Option<String>)],
) {
2017-05-27 20:51:22 +00:00
if tabs.len() <= 1 {
self.tabs.hide();
return;
} else {
self.tabs.show();
}
2017-05-28 09:29:50 +00:00
self.update_state(nvim, selected, tabs);
2017-05-27 20:51:22 +00:00
2017-05-28 09:29:50 +00:00
signal::signal_handler_block(&self.tabs, self.switch_handler_id);
2017-05-27 20:51:22 +00:00
2017-05-27 16:50:25 +00:00
let count = self.tabs.get_n_pages() as usize;
if count < tabs.len() {
for _ in count..tabs.len() {
let empty = gtk::Box::new(gtk::Orientation::Vertical, 0);
empty.show_all();
2017-09-26 13:59:28 +00:00
let title = gtk::Label::new(None);
title.set_ellipsize(pango::EllipsizeMode::Middle);
title.set_width_chars(25);
self.tabs.append_page(&empty, Some(&title));
2017-05-27 16:50:25 +00:00
}
2017-05-28 09:29:50 +00:00
} else if count > tabs.len() {
2017-05-27 16:50:25 +00:00
for _ in tabs.len()..count {
self.tabs.remove_page(None);
}
}
for (idx, tab) in tabs.iter().enumerate() {
let tab_child = self.tabs.get_nth_page(Some(idx as u32));
2017-09-26 13:59:28 +00:00
let tab_label = self.tabs
.get_tab_label(&tab_child.unwrap())
.unwrap()
.downcast::<gtk::Label>()
.unwrap();
tab_label.set_text(tab.1.as_ref().unwrap_or(&"??".to_owned()));
2017-05-27 20:51:22 +00:00
if *selected == tab.0 {
self.tabs.set_current_page(Some(idx as u32));
}
2017-05-27 16:50:25 +00:00
}
2017-05-28 09:29:50 +00:00
signal::signal_handler_unblock(&self.tabs, self.switch_handler_id);
2017-05-27 16:50:25 +00:00
}
}
impl Deref for Tabline {
type Target = gtk::Notebook;
fn deref(&self) -> &gtk::Notebook {
&self.tabs
}
}