diff --git a/src/main.rs b/src/main.rs index 7cc148f..99db371 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,9 +31,9 @@ mod color; mod value; mod mode; mod ui_model; -mod plug_manager; #[macro_use] mod ui; +mod plug_manager; mod nvim; mod render; mod shell; diff --git a/src/plug_manager/manager.rs b/src/plug_manager/manager.rs index 7a54462..143900e 100644 --- a/src/plug_manager/manager.rs +++ b/src/plug_manager/manager.rs @@ -67,6 +67,10 @@ impl Manager { pub fn save(&self) { self.store().map(|s| s.save()); } + + pub fn clear_removed(&mut self) { + self.store_mut().map(|s| s.clear_removed()); + } } pub enum PlugManageState { @@ -85,7 +89,9 @@ impl PlugManagerConfigSource { let mut builder = "call plug#begin()\n".to_owned(); for plug in store.get_plugs() { - builder += &format!("Plug '{}'\n", plug.get_plug_path()); + if !plug.removed { + builder += &format!("Plug '{}'\n", plug.get_plug_path()); + } } builder += "call plug#end()\n"; diff --git a/src/plug_manager/store.rs b/src/plug_manager/store.rs index bd9e8b5..df4a19c 100644 --- a/src/plug_manager/store.rs +++ b/src/plug_manager/store.rs @@ -46,9 +46,21 @@ impl Store { self.settings.enabled = enabled; } + pub fn clear_removed(&mut self) { + self.settings.plugs.retain(|p| !p.removed); + } + pub fn save(&self) { self.settings.save(); } + + pub fn remove_plug(&mut self, idx: usize) { + self.settings.plugs[idx].removed = true; + } + + pub fn restore_plug(&mut self, idx: usize) { + self.settings.plugs[idx].removed = false; + } } #[derive(Serialize, Deserialize)] diff --git a/src/plug_manager/ui.rs b/src/plug_manager/ui.rs index c7bf79c..deba02e 100644 --- a/src/plug_manager/ui.rs +++ b/src/plug_manager/ui.rs @@ -9,7 +9,7 @@ use gtk; use gtk::prelude::*; use super::manager; -use super::store::Store; +use super::store::{Store, PlugInfo}; pub struct Ui<'a> { manager: &'a Arc>, @@ -81,9 +81,9 @@ impl<'a> Ui<'a> { enable_swc.connect_state_set(move |_, state| { - manager_ref.borrow_mut().store_mut().map(|s| { - s.set_enabled(state) - }); + manager_ref.borrow_mut().store_mut().map( + |s| s.set_enabled(state), + ); Inhibit(false) }); @@ -93,7 +93,9 @@ impl<'a> Ui<'a> { match dlg.run() { OK_ID => { - self.manager.borrow().save(); + let mut manager = self.manager.borrow_mut(); + manager.clear_removed(); + manager.save(); } _ => (), } @@ -113,44 +115,56 @@ impl<'a> Ui<'a> { let scroll = gtk::ScrolledWindow::new(None, None); scroll.get_style_context().map(|c| c.add_class("view")); let plugs_panel = gtk::ListBox::new(); - plugs_panel.set_selection_mode(gtk::SelectionMode::None); for (idx, plug_info) in store.get_plugs().iter().enumerate() { let row = gtk::ListBoxRow::new(); let row_container = gtk::Box::new(gtk::Orientation::Vertical, 5); row_container.set_border_width(5); let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 5); - let vbox = gtk::Box::new(gtk::Orientation::Vertical, 5); + 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); - let name_lbl = gtk::Label::new(None); - name_lbl.set_markup(&format!("{}", plug_info.name.as_str())); - name_lbl.set_halign(gtk::Align::Start); - let url_lbl = gtk::Label::new(Some(plug_info.url.as_str())); - url_lbl.set_halign(gtk::Align::Start); let remove_btn = gtk::Button::new_with_label("Remove"); - remove_btn.set_halign(gtk::Align::End); + exists_button_box.pack_start(&remove_btn, false, true, 0); + + let undo_btn = gtk::Button::new_with_label("Undo"); - //let store_ref = store.clone(); - let panel_ref = panel.clone(); - let row_ref = row.clone(); - remove_btn.connect_clicked(move |_| { - // store_ref.borrow_mut().remove(idx); - row_ref.remove(row_ref.get_child().as_ref().unwrap()); - let undo_btn = gtk::Button::new_with_label("Undo"); - let row_container = gtk::Box::new(gtk::Orientation::Horizontal, 5); - row_container.pack_end(&undo_btn, false, true, 0); - row_ref.add(&row_container); - row_container.show_all(); - }); row_container.pack_start(&hbox, true, true, 0); - vbox.pack_start(&name_lbl, true, true, 0); - vbox.pack_start(&url_lbl, true, true, 0); - hbox.pack_start(&vbox, true, true, 0); - hbox.pack_start(&remove_btn, false, true, 0); + 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); row.add(&row_container); plugs_panel.add(&row); + + + 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)); + }), + ); } scroll.add(&plugs_panel); @@ -158,6 +172,21 @@ impl<'a> Ui<'a> { } } +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!("{}", 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); @@ -188,16 +217,16 @@ impl SettingsPages { content.pack_start(&categories, false, true, 0); content.pack_start(&stack, true, true, 0); - let rows_ref = rows.clone(); - let stack_ref = stack.clone(); - categories.connect_row_selected(move |_, row| if let &Some(ref row) = row { - if let Some(ref r) = rows_ref.borrow().iter().find(|r| r.0 == *row) { - if let Some(child) = stack_ref.get_child_by_name(&r.1) { - stack_ref.set_visible_child(&child); + 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); } } - }); + }), + ); SettingsPages { categories, diff --git a/src/ui.rs b/src/ui.rs index 1f2ce02..4c46f9e 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -60,7 +60,9 @@ impl Ui { let plug_manager = Arc::new(UiMutex::new(plug_manager)); let comps = Arc::new(UiMutex::new(Components::new())); let settings = Rc::new(RefCell::new(Settings::new())); - let shell = Rc::new(RefCell::new(Shell::new(settings.clone(), options, nvim_config))); + let shell = Rc::new(RefCell::new( + Shell::new(settings.clone(), options, nvim_config), + )); settings.borrow_mut().set_shell(Rc::downgrade(&shell)); let projects = Projects::new(&comps.borrow().open_btn, shell.clone()); @@ -263,3 +265,20 @@ impl UiMutex { } } } + +macro_rules! clone { + (@param _) => ( _ ); + (@param $x:ident) => ( $x ); + ($($n:ident),+ => move || $body:expr) => ( + { + $( let $n = $n.clone(); )+ + move || $body + } + ); + ($($n:ident),+ => move |$($p:tt),+| $body:expr) => ( + { + $( let $n = $n.clone(); )+ + move |$(clone!(@param $p),)+| $body + } + ); +}