Add open message, improve context menus

This commit is contained in:
Jeremy Soller 2024-02-28 15:46:23 -07:00
parent 09be33e391
commit dc8433ce59
No known key found for this signature in database
GPG key ID: D02FD439211AF56F
5 changed files with 89 additions and 29 deletions

View file

@ -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::<Tab>(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);
}

View file

@ -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)),
);

View file

@ -68,6 +68,7 @@ pub fn key_binds() -> HashMap<KeyBind, Action> {
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);

View file

@ -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<KeyBind, Action>,
) -> 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<Element<_>> = 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<KeyBind, Action>) -> 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

View file

@ -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<image::RgbaImage, ()>),
@ -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<Message> {
pub fn view(&self, core: &Core, key_binds: &HashMap<KeyBind, Action>) -> Element<Message> {
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![