diff --git a/src/app.rs b/src/app.rs index f54606b..b6c0b4d 100644 --- a/src/app.rs +++ b/src/app.rs @@ -47,6 +47,10 @@ pub enum Action { EditLocation, HistoryNext, HistoryPrevious, + ItemDown, + ItemLeft, + ItemRight, + ItemUp, LocationUp, MoveToTrash, NewFile, @@ -79,6 +83,10 @@ impl Action { Action::EditLocation => Message::EditLocation(entity_opt), Action::HistoryNext => Message::TabMessage(entity_opt, tab::Message::GoNext), Action::HistoryPrevious => Message::TabMessage(entity_opt, tab::Message::GoPrevious), + Action::ItemDown => Message::TabMessage(entity_opt, tab::Message::ItemDown), + Action::ItemLeft => Message::TabMessage(entity_opt, tab::Message::ItemLeft), + Action::ItemRight => Message::TabMessage(entity_opt, tab::Message::ItemRight), + Action::ItemUp => Message::TabMessage(entity_opt, tab::Message::ItemUp), Action::LocationUp => Message::TabMessage(entity_opt, tab::Message::LocationUp), Action::MoveToTrash => Message::MoveToTrash(entity_opt), Action::NewFile => Message::NewItem(entity_opt, false), @@ -658,10 +666,26 @@ impl Application for App { // Usually, the Escape key (for example) closes menus and panes one by one instead // of closing everything on one press // TODO: Close MenuBar too - match self.tab_model.data_mut::(entity) { - Some(tab) if tab.context_menu.is_some() => tab.context_menu = None, - _ => self.core.window.show_context = false, + if let Some(tab) = self.tab_model.data_mut::(entity) { + if tab.context_menu.is_some() { + tab.context_menu = None; + return Command::none(); + } + + if let Some(ref mut items) = tab.items_opt { + let mut had_selection = false; + for item in items.iter_mut() { + if item.selected { + item.selected = false; + had_selection = true; + } + } + if had_selection { + return Command::none(); + } + } } + self.core.window.show_context = false; Command::none() } diff --git a/src/key_bind.rs b/src/key_bind.rs index d73084b..9bc6db6 100644 --- a/src/key_bind.rs +++ b/src/key_bind.rs @@ -65,6 +65,16 @@ pub fn key_binds() -> HashMap { bind!([Ctrl], Key::Character("l".into()), EditLocation); bind!([Alt], Key::Named(Named::ArrowRight), HistoryNext); bind!([Alt], Key::Named(Named::ArrowLeft), HistoryPrevious); + // Catch arrow keys + bind!([], Key::Named(Named::ArrowDown), ItemDown); + bind!([], Key::Named(Named::ArrowLeft), ItemLeft); + bind!([], Key::Named(Named::ArrowRight), ItemRight); + bind!([], Key::Named(Named::ArrowUp), ItemUp); + // We also need to catch these when shift is held + bind!([Shift], Key::Named(Named::ArrowDown), ItemDown); + bind!([Shift], Key::Named(Named::ArrowLeft), ItemLeft); + bind!([Shift], Key::Named(Named::ArrowRight), ItemRight); + bind!([Shift], Key::Named(Named::ArrowUp), ItemUp); bind!([Alt], Key::Named(Named::ArrowUp), LocationUp); bind!([], Key::Named(Named::Delete), MoveToTrash); bind!([Ctrl, Shift], Key::Character("N".into()), NewFolder); diff --git a/src/tab.rs b/src/tab.rs index 30a6c2d..0f4b655 100644 --- a/src/tab.rs +++ b/src/tab.rs @@ -373,6 +373,10 @@ pub enum Message { EditLocation(Option), GoNext, GoPrevious, + ItemDown, + ItemLeft, + ItemRight, + ItemUp, Location(Location), LocationUp, Open, @@ -705,6 +709,56 @@ impl Tab { } } } + Message::ItemDown | Message::ItemLeft => { + //TODO: handle grid correctly + //TODO: do not wrap + if let Some(ref mut items) = self.items_opt { + let mut last_selected_opt = None; + for (i, item) in items.iter_mut().enumerate() { + if item.selected { + if !modifiers.contains(Modifiers::SHIFT) { + item.selected = false; + } + last_selected_opt = Some(i); + } + } + for (i, item) in items.iter_mut().enumerate() { + if !self.config.show_hidden && item.hidden { + continue; + } + + if last_selected_opt.map_or(true, |last_selected| i > last_selected) { + item.selected = true; + break; + } + } + } + } + Message::ItemUp | Message::ItemRight => { + //TODO: handle grid correctly + //TODO: do not wrap + if let Some(ref mut items) = self.items_opt { + let mut last_selected_opt = None; + for (i, item) in items.iter_mut().enumerate().rev() { + if item.selected { + if !modifiers.contains(Modifiers::SHIFT) { + item.selected = false; + } + last_selected_opt = Some(i); + } + } + for (i, item) in items.iter_mut().enumerate().rev() { + if !self.config.show_hidden && item.hidden { + continue; + } + + if last_selected_opt.map_or(true, |last_selected| i < last_selected) { + item.selected = true; + break; + } + } + } + } Message::Location(location) => { cd = Some(location); }