neovim-gtk/src/plug_manager/ui.rs

279 lines
9.1 KiB
Rust
Raw Normal View History

2017-10-24 15:03:34 +00:00
use std::sync::Arc;
2017-10-28 20:18:42 +00:00
use std::rc::Rc;
use std::cell::RefCell;
use std::ops::Deref;
2017-10-24 15:03:34 +00:00
use ui::UiMutex;
2017-10-23 15:07:04 +00:00
use gtk;
use gtk::prelude::*;
2017-10-16 15:34:26 +00:00
use super::manager;
2017-10-29 19:16:55 +00:00
use super::store::{Store, PlugInfo};
2017-10-29 20:45:05 +00:00
use super::plugin_settings_dlg;
2017-10-17 18:34:49 +00:00
pub struct Ui<'a> {
2017-10-24 15:03:34 +00:00
manager: &'a Arc<UiMutex<manager::Manager>>,
2017-10-16 15:34:26 +00:00
}
2017-10-17 18:34:49 +00:00
impl<'a> Ui<'a> {
2017-10-24 15:03:34 +00:00
pub fn new(manager: &'a Arc<UiMutex<manager::Manager>>) -> Ui<'a> {
manager.borrow_mut().update_state();
2017-10-17 18:34:49 +00:00
Ui { manager }
}
2017-10-24 15:03:34 +00:00
pub fn show<T: IsA<gtk::Window>>(&mut self, parent: &T) {
let dlg = gtk::Dialog::new_with_buttons(
Some("Plug"),
Some(parent),
2017-10-29 20:45:05 +00:00
gtk::DIALOG_DESTROY_WITH_PARENT,
&[("Ok", gtk::ResponseType::Ok.into())],
);
2017-10-21 17:20:55 +00:00
dlg.set_default_size(800, 600);
let content = dlg.get_content_area();
2017-10-28 20:18:42 +00:00
let header_bar = gtk::HeaderBar::new();
2017-10-29 20:45:05 +00:00
let add_plug_btn = gtk::Button::new_with_label("Add..");
header_bar.pack_end(&add_plug_btn);
let manager_ref = self.manager.clone();
add_plug_btn.connect_clicked(clone!(dlg => move |_| {
add_plugin(&dlg, &manager_ref);
}));
let enable_swc = gtk::Switch::new();
2017-10-28 20:18:42 +00:00
enable_swc.set_valign(gtk::Align::Center);
let manager_ref = self.manager.clone();
2017-10-28 20:18:42 +00:00
header_bar.pack_end(&enable_swc);
header_bar.set_title("Plug");
header_bar.set_show_close_button(true);
header_bar.show_all();
dlg.set_titlebar(&header_bar);
2017-10-29 20:45:05 +00:00
let pages = SettingsPages::new(move |row_name| if row_name == "plugins" {
add_plug_btn.show();
} else {
add_plug_btn.hide();
});
2017-10-24 15:03:34 +00:00
match self.manager.borrow_mut().plug_manage_state {
manager::PlugManageState::Unknown => {
add_help_tab(
&pages,
"<span foreground=\"red\">Note:</span> NeovimGtk plugin manager <b>disabled</b>!",
);
2017-10-24 15:03:34 +00:00
}
manager::PlugManageState::VimPlug(ref store) => {
enable_swc.set_state(store.is_enabled());
add_help_tab(
&pages,
"<span foreground=\"red\">Note:</span> NeovimGtk plugin manager <b>disabled</b>!\n\
NeovimGtk manages plugins use vim-plug as backend, so enable it disables vim-plug configuration.\n\
Current configuration taken from your vim-plug",
);
2017-10-28 20:18:42 +00:00
self.add_plugin_list_tab(&pages, store);
2017-10-17 18:34:49 +00:00
}
2017-10-24 15:03:34 +00:00
manager::PlugManageState::NvimGtk(ref store) => {
enable_swc.set_state(store.is_enabled());
2017-10-17 18:34:49 +00:00
let get_plugins = gtk::Box::new(gtk::Orientation::Vertical, 0);
2017-10-28 20:18:42 +00:00
// TODO:
2017-10-17 18:34:49 +00:00
let get_plugins_lbl = gtk::Label::new("Get Plugins");
2017-10-28 20:18:42 +00:00
pages.add_page(&get_plugins_lbl, &get_plugins, "get_plugins");
2017-10-24 15:03:34 +00:00
2017-10-28 20:18:42 +00:00
self.add_plugin_list_tab(&pages, store);
2017-10-17 18:34:49 +00:00
}
}
enable_swc.connect_state_set(move |_, state| {
2017-10-29 19:16:55 +00:00
manager_ref.borrow_mut().store_mut().map(
|s| s.set_enabled(state),
);
Inhibit(false)
});
2017-10-28 20:18:42 +00:00
content.pack_start(&*pages, true, true, 0);
content.show_all();
2017-10-29 20:45:05 +00:00
if dlg.run() == gtk::ResponseType::Ok.into() {
let mut manager = self.manager.borrow_mut();
manager.clear_removed();
manager.save();
}
dlg.destroy();
}
2017-10-17 18:34:49 +00:00
2017-10-28 20:18:42 +00:00
fn add_plugin_list_tab(&self, pages: &SettingsPages, store: &Store) {
2017-10-24 15:03:34 +00:00
let plugins = gtk::Box::new(gtk::Orientation::Vertical, 3);
self.fill_plugin_list(&plugins, store);
let plugins_lbl = gtk::Label::new("Plugins");
2017-10-28 20:18:42 +00:00
pages.add_page(&plugins_lbl, &plugins, "plugins");
2017-10-24 15:03:34 +00:00
}
fn fill_plugin_list(&self, panel: &gtk::Box, store: &Store) {
2017-10-20 15:06:05 +00:00
let scroll = gtk::ScrolledWindow::new(None, None);
2017-10-28 21:28:32 +00:00
scroll.get_style_context().map(|c| c.add_class("view"));
2017-10-21 17:20:55 +00:00
let plugs_panel = gtk::ListBox::new();
2017-10-24 15:03:34 +00:00
for (idx, plug_info) in store.get_plugs().iter().enumerate() {
2017-10-23 15:07:04 +00:00
let row = gtk::ListBoxRow::new();
let row_container = gtk::Box::new(gtk::Orientation::Vertical, 5);
2017-10-28 21:28:32 +00:00
row_container.set_border_width(5);
2017-10-23 15:07:04 +00:00
let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 5);
2017-10-29 19:16:55 +00:00
let label_box = create_plug_label(plug_info);
let button_box = gtk::Box::new(gtk::Orientation::Horizontal, 0);
button_box.set_halign(gtk::Align::End);
let exists_button_box = gtk::Box::new(gtk::Orientation::Horizontal, 5);
2017-10-21 17:20:55 +00:00
2017-10-23 15:07:04 +00:00
let remove_btn = gtk::Button::new_with_label("Remove");
2017-10-29 19:16:55 +00:00
exists_button_box.pack_start(&remove_btn, false, true, 0);
let undo_btn = gtk::Button::new_with_label("Undo");
2017-10-23 15:07:04 +00:00
row_container.pack_start(&hbox, true, true, 0);
2017-10-29 19:16:55 +00:00
hbox.pack_start(&label_box, true, true, 0);
button_box.pack_start(&exists_button_box, false, true, 0);
hbox.pack_start(&button_box, false, true, 0);
2017-10-23 15:07:04 +00:00
row.add(&row_container);
plugs_panel.add(&row);
2017-10-29 19:16:55 +00:00
let manager_ref = self.manager.clone();
remove_btn.connect_clicked(
clone!(label_box, button_box, exists_button_box, undo_btn => move |_| {
label_box.set_sensitive(false);
button_box.remove(&exists_button_box);
button_box.pack_start(&undo_btn, false, true, 0);
button_box.show_all();
manager_ref.borrow_mut().store_mut().map(|s| s.remove_plug(idx));
}),
);
let manager_ref = self.manager.clone();
undo_btn.connect_clicked(
clone!(label_box, button_box, exists_button_box, undo_btn => move |_| {
label_box.set_sensitive(true);
button_box.remove(&undo_btn);
button_box.pack_start(&exists_button_box, false, true, 0);
button_box.show_all();
manager_ref.borrow_mut().store_mut().map(|s| s.restore_plug(idx));
}),
);
2017-10-21 17:20:55 +00:00
}
2017-10-20 15:06:05 +00:00
2017-10-21 17:20:55 +00:00
scroll.add(&plugs_panel);
panel.pack_start(&scroll, true, true, 0);
2017-10-18 14:49:56 +00:00
}
}
2017-10-28 20:18:42 +00:00
2017-10-29 20:45:05 +00:00
fn add_plugin<F: IsA<gtk::Window>>(parent: &F, manager: &Arc<UiMutex<manager::Manager>>) {
plugin_settings_dlg::Builder::new("Add plugin").show(parent);
}
2017-10-29 19:16:55 +00:00
fn create_plug_label(plug_info: &PlugInfo) -> gtk::Box {
let label_box = gtk::Box::new(gtk::Orientation::Vertical, 5);
let name_lbl = gtk::Label::new(None);
name_lbl.set_markup(&format!("<b>{}</b>", plug_info.name));
name_lbl.set_halign(gtk::Align::Start);
let url_lbl = gtk::Label::new(Some(plug_info.get_plug_path().as_str()));
url_lbl.set_halign(gtk::Align::Start);
label_box.pack_start(&name_lbl, true, true, 0);
label_box.pack_start(&url_lbl, true, true, 0);
label_box
}
fn add_help_tab(pages: &SettingsPages, markup: &str) {
let help = gtk::Box::new(gtk::Orientation::Vertical, 3);
let label = gtk::Label::new(None);
label.set_markup(markup);
help.pack_start(&label, true, false, 0);
let help_lbl = gtk::Label::new("Help");
pages.add_page(&help_lbl, &help, "help");
}
2017-10-28 20:18:42 +00:00
struct SettingsPages {
categories: gtk::ListBox,
stack: gtk::Stack,
content: gtk::Box,
rows: Rc<RefCell<Vec<(gtk::ListBoxRow, &'static str)>>>,
2017-10-29 20:45:05 +00:00
row_selected: Box<FnMut(&str)>,
2017-10-28 20:18:42 +00:00
}
impl SettingsPages {
2017-10-29 20:45:05 +00:00
pub fn new<F: FnMut(&str) + 'static>(row_selected: F) -> Self {
2017-10-28 21:28:32 +00:00
let content = gtk::Box::new(gtk::Orientation::Horizontal, 5);
2017-10-28 20:18:42 +00:00
let categories = gtk::ListBox::new();
2017-10-28 21:28:32 +00:00
categories.get_style_context().map(|c| c.add_class("view"));
2017-10-28 20:18:42 +00:00
let stack = gtk::Stack::new();
stack.set_transition_type(gtk::StackTransitionType::Crossfade);
let rows: Rc<RefCell<Vec<(gtk::ListBoxRow, &'static str)>>> =
Rc::new(RefCell::new(Vec::new()));
content.pack_start(&categories, false, true, 0);
content.pack_start(&stack, true, true, 0);
2017-10-29 19:16:55 +00:00
categories.connect_row_selected(
clone!(stack, rows => move |_, row| if let &Some(ref row) = row {
if let Some(ref r) = rows.borrow().iter().find(|r| r.0 == *row) {
if let Some(child) = stack.get_child_by_name(&r.1) {
stack.set_visible_child(&child);
2017-10-28 20:18:42 +00:00
}
}
2017-10-29 19:16:55 +00:00
}),
);
2017-10-28 20:18:42 +00:00
SettingsPages {
categories,
stack,
content,
rows,
2017-10-29 20:45:05 +00:00
row_selected: Box::new(row_selected),
2017-10-28 20:18:42 +00:00
}
}
fn add_page<W: gtk::IsA<gtk::Widget>>(
&self,
label: &gtk::Label,
widget: &W,
name: &'static str,
) {
let row = gtk::ListBoxRow::new();
let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 0);
hbox.set_border_width(12);
hbox.pack_start(label, false, true, 0);
row.add(&hbox);
self.categories.add(&row);
self.stack.add_named(widget, name);
self.rows.borrow_mut().push((row, name));
}
}
impl Deref for SettingsPages {
type Target = gtk::Box;
fn deref(&self) -> &gtk::Box {
&self.content
}
}