From dc8433ce590995fce52572f3f2521ac469e0126e Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 28 Feb 2024 15:46:23 -0700 Subject: [PATCH] Add open message, improve context menus --- src/app.rs | 10 +++++--- src/dialog.rs | 11 +++++++-- src/key_bind.rs | 1 + src/menu.rs | 66 ++++++++++++++++++++++++++++++++++--------------- src/tab.rs | 30 +++++++++++++++++++--- 5 files changed, 89 insertions(+), 29 deletions(-) diff --git a/src/app.rs b/src/app.rs index a89270c..f54606b 100644 --- a/src/app.rs +++ b/src/app.rs @@ -51,6 +51,7 @@ pub enum Action { MoveToTrash, NewFile, NewFolder, + Open, Operations, Paste, Properties, @@ -76,12 +77,13 @@ impl Action { Action::Copy => Message::Copy(entity_opt), Action::Cut => Message::Cut(entity_opt), Action::EditLocation => Message::EditLocation(entity_opt), - Action::HistoryNext => Message::TabMessage(None, tab::Message::GoNext), - Action::HistoryPrevious => Message::TabMessage(None, tab::Message::GoPrevious), - Action::LocationUp => Message::TabMessage(None, tab::Message::LocationUp), + Action::HistoryNext => Message::TabMessage(entity_opt, tab::Message::GoNext), + Action::HistoryPrevious => Message::TabMessage(entity_opt, tab::Message::GoPrevious), + Action::LocationUp => Message::TabMessage(entity_opt, tab::Message::LocationUp), Action::MoveToTrash => Message::MoveToTrash(entity_opt), Action::NewFile => Message::NewItem(entity_opt, false), Action::NewFolder => Message::NewItem(entity_opt, true), + Action::Open => Message::TabMessage(entity_opt, tab::Message::Open), Action::Operations => Message::ToggleContextPage(ContextPage::Operations), Action::Paste => Message::Paste(entity_opt), Action::Properties => Message::ToggleContextPage(ContextPage::Properties), @@ -1316,7 +1318,7 @@ impl Application for App { match self.tab_model.data::(entity) { Some(tab) => { let tab_view = tab - .view(self.core()) + .view(self.core(), &self.key_binds) .map(move |message| Message::TabMessage(Some(entity), message)); tab_column = tab_column.push(tab_view); } diff --git a/src/dialog.rs b/src/dialog.rs index db2cbde..237e4d8 100644 --- a/src/dialog.rs +++ b/src/dialog.rs @@ -16,7 +16,13 @@ use cosmic::{ Application, ApplicationExt, Element, }; use notify::Watcher; -use std::{any::TypeId, collections::HashSet, env, fs, path::PathBuf, time}; +use std::{ + any::TypeId, + collections::{HashMap, HashSet}, + env, fs, + path::PathBuf, + time, +}; use crate::{ config::TabConfig, @@ -610,8 +616,9 @@ impl Application for App { let mut tab_column = widget::column::with_capacity(2); tab_column = tab_column.push( + //TODO: key binds for dialog self.tab - .view(self.core()) + .view(self.core(), &HashMap::new()) .map(move |message| Message::TabMessage(message)), ); diff --git a/src/key_bind.rs b/src/key_bind.rs index 24b9e03..d73084b 100644 --- a/src/key_bind.rs +++ b/src/key_bind.rs @@ -68,6 +68,7 @@ pub fn key_binds() -> HashMap { bind!([Alt], Key::Named(Named::ArrowUp), LocationUp); bind!([], Key::Named(Named::Delete), MoveToTrash); bind!([Ctrl, Shift], Key::Character("N".into()), NewFolder); + bind!([], Key::Named(Named::Enter), Open); bind!([Ctrl], Key::Character("v".into()), Paste); bind!([], Key::Named(Named::F2), Rename); bind!([Ctrl], Key::Character("a".into()), SelectAll); diff --git a/src/menu.rs b/src/menu.rs index c37237c..bfe02c3 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -34,10 +34,27 @@ macro_rules! menu_button { ); } -pub fn context_menu<'a>(tab: &Tab) -> Element<'a, tab::Message> { - //TODO: show key bindings in context menu? - let menu_action = |label, action| { - menu_button!(widget::text(label)).on_press(tab::Message::ContextAction(action)) +pub fn context_menu<'a>( + tab: &Tab, + key_binds: &HashMap, +) -> Element<'a, tab::Message> { + let find_key = |action: &Action| -> String { + for (key_bind, key_action) in key_binds.iter() { + if action == key_action { + return key_bind.to_string(); + } + } + String::new() + }; + + let menu_item = |label, action| { + let key = find_key(&action); + menu_button!( + widget::text(label), + widget::horizontal_space(Length::Fill), + widget::text(key) + ) + .on_press(tab::Message::ContextAction(action)) }; let selected = tab @@ -48,32 +65,41 @@ pub fn context_menu<'a>(tab: &Tab) -> Element<'a, tab::Message> { let mut children: Vec> = Vec::new(); match tab.location { Location::Path(_) => { - children.push(menu_action(fl!("new-file"), Action::NewFile).into()); - children.push(menu_action(fl!("new-folder"), Action::NewFolder).into()); - children.push(horizontal_rule(1).into()); - if selected > 0 { - children.push(menu_action(fl!("rename"), Action::Rename).into()); - children.push(menu_action(fl!("cut"), Action::Cut).into()); - children.push(menu_action(fl!("copy"), Action::Copy).into()); - children.push(menu_action(fl!("paste"), Action::Paste).into()); - } - children.push(menu_action(fl!("select-all"), Action::SelectAll).into()); if selected > 0 { + children.push(menu_item(fl!("open"), Action::Open).into()); + //TODO: Open with children.push(horizontal_rule(1).into()); - children.push(menu_action(fl!("move-to-trash"), Action::MoveToTrash).into()); + children.push(menu_item(fl!("rename"), Action::Rename).into()); + children.push(menu_item(fl!("cut"), Action::Cut).into()); + children.push(menu_item(fl!("copy"), Action::Copy).into()); + //TODO: Print? + children.push(horizontal_rule(1).into()); + //TODO: change to Show details + children.push(menu_item(fl!("properties"), Action::Properties).into()); + //TODO: Add to sidebar + children.push(horizontal_rule(1).into()); + children.push(menu_item(fl!("move-to-trash"), Action::MoveToTrash).into()); + } else { + //TODO: need better designs for menu with no selection + //TODO: have things like properties but they apply to the folder? + children.push(menu_item(fl!("new-file"), Action::NewFile).into()); + children.push(menu_item(fl!("new-folder"), Action::NewFolder).into()); + children.push(horizontal_rule(1).into()); + children.push(menu_item(fl!("select-all"), Action::SelectAll).into()); + children.push(menu_item(fl!("paste"), Action::Paste).into()); } } Location::Trash => { - children.push(menu_action(fl!("select-all"), Action::SelectAll).into()); + children.push(menu_item(fl!("select-all"), Action::SelectAll).into()); if selected > 0 { + children.push(horizontal_rule(1).into()); + children.push(menu_item(fl!("properties"), Action::Properties).into()); children.push(horizontal_rule(1).into()); children - .push(menu_action(fl!("restore-from-trash"), Action::RestoreFromTrash).into()); + .push(menu_item(fl!("restore-from-trash"), Action::RestoreFromTrash).into()); } } } - children.push(horizontal_rule(1).into()); - children.push(menu_action(fl!("properties"), Action::Properties).into()); widget::container(widget::column::with_children(children)) .padding(1) @@ -134,7 +160,7 @@ pub fn menu_bar<'a>(key_binds: &HashMap) -> Element<'a, Message menu_item(fl!("new-window"), Action::WindowNew), menu_item(fl!("new-file"), Action::NewFile), menu_item(fl!("new-folder"), Action::NewFolder), - //TODO: open + menu_item(fl!("open"), Action::Open), MenuTree::new(horizontal_rule(1)), menu_item(fl!("rename"), Action::Rename), //TOOD: add to sidebar, then divider diff --git a/src/tab.rs b/src/tab.rs index 099177a..30a6c2d 100644 --- a/src/tab.rs +++ b/src/tab.rs @@ -32,7 +32,9 @@ use crate::{ app::Action, config::{IconSizes, TabConfig}, dialog::DialogKind, - fl, menu, + fl, + key_bind::KeyBind, + menu, mime_icon::mime_icon, mouse_area, }; @@ -373,6 +375,7 @@ pub enum Message { GoPrevious, Location(Location), LocationUp, + Open, RightClick(usize), Scroll(Viewport), Thumbnail(PathBuf, Result), @@ -714,6 +717,27 @@ impl Tab { } } } + Message::Open => { + if let Some(ref mut items) = self.items_opt { + for item in items.iter() { + if item.selected { + match self.location { + Location::Path(_) => { + if item.path.is_dir() { + //TODO: allow opening multiple tabs? + cd = Some(Location::Path(item.path.clone())); + } else { + commands.push(Command::OpenFile(item.path.clone())); + } + } + Location::Trash => { + //TODO: open properties? + } + } + } + } + } + } Message::RightClick(click_i) => { if let Some(ref mut items) = self.items_opt { if !items.get(click_i).map_or(false, |x| x.selected) { @@ -1214,7 +1238,7 @@ impl Tab { .into() } - pub fn view(&self, core: &Core) -> Element { + pub fn view(&self, core: &Core, key_binds: &HashMap) -> Element { let location_view = self.location_view(core); let item_view = match self.view { View::Grid => self.grid_view(core), @@ -1237,7 +1261,7 @@ impl Tab { let mut popover = widget::popover(mouse_area); if let Some(point) = self.context_menu { popover = popover - .popup(menu::context_menu(&self)) + .popup(menu::context_menu(&self, &key_binds)) .position(widget::popover::Position::Point(point)); } widget::container(widget::column::with_children(vec![