diff --git a/src/app.rs b/src/app.rs index 048d600..55c27a7 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1737,15 +1737,6 @@ impl App { } } - fn close_context_menus(&mut self) -> Task { - let active = self.tab_model.active(); - if let Some(tab) = self.tab_model.data_mut::(active) { - tab.location_context_menu_index = None; - } - - Task::none() - } - fn update_nav_model(&mut self) { let mut nav_model = segmented_button::ModelBuilder::default(); @@ -2802,11 +2793,6 @@ impl Application for App { return cosmic::task::message(cosmic::action::app(Message::SetShowDetails(false))); } if let Some(tab) = self.tab_model.data_mut::(entity) { - if tab.location_context_menu_index.is_some() { - tab.location_context_menu_index = None; - return Task::none(); - } - if tab.edit_location.is_some() { tab.edit_location = None; return Task::none(); @@ -3558,7 +3544,7 @@ impl Application for App { Message::Mouse(window_id, _button) => { // Close context menu when clicking outside. if self.core.main_window_id() == Some(window_id) { - return self.close_context_menus(); + return Task::none(); } } Message::MoveTo(entity_opt) => { @@ -4348,7 +4334,7 @@ impl Application for App { )); } Message::SearchActivate => { - let mut tasks = vec![self.close_context_menus()]; + let mut tasks = vec![]; if self.search_get().is_none() { tasks.push(self.search_set_active(Some(String::new()))); @@ -4359,7 +4345,7 @@ impl Application for App { return Task::batch(tasks); } Message::SearchClear => { - return Task::batch([self.close_context_menus(), self.search_set_active(None)]); + return self.search_set_active(None); } Message::SearchInput(input) => { return self.search_set_active(Some(input)); @@ -4380,7 +4366,7 @@ impl Application for App { return self.update_config(); } Message::TabActivate(entity) => { - let mut tasks = vec![self.close_context_menus()]; + let mut tasks = vec![]; // Activate new tab self.tab_model.activate(entity); @@ -4584,7 +4570,6 @@ impl Application for App { } tab::Command::OpenFile(paths) => commands.push(self.open_file(&paths)), tab::Command::OpenInNewTab(path) => { - commands.push(self.close_context_menus()); commands.push(self.open_tab(Location::Path(path), false, None)); } tab::Command::OpenInNewWindow(path) => match env::current_exe() { @@ -5021,8 +5006,6 @@ impl Application for App { if let Some(tab) = self.tab_model.data_mut::(tab_entity) { // Close location editing if enabled tab.edit_location = None; - // Close other context menus. - tab.location_context_menu_index = None; } } Message::NavMenuAction(action) => match action { @@ -5120,7 +5103,7 @@ impl Application for App { _ => Task::none(), }; - return Task::batch([self.close_context_menus(), open_task]); + return open_task; } // Open the selected path in a new cosmic-files window. diff --git a/src/dialog.rs b/src/dialog.rs index 8f5cd5d..bebbef4 100644 --- a/src/dialog.rs +++ b/src/dialog.rs @@ -864,12 +864,6 @@ impl App { } } - fn close_context_menus(&mut self) -> Task { - self.tab.location_context_menu_index = None; - - Task::none() - } - fn update_nav_model(&mut self) { let mut nav_model = segmented_button::ModelBuilder::default(); @@ -1314,11 +1308,6 @@ impl Application for App { return Task::none(); } - if self.tab.location_context_menu_index.is_some() { - self.tab.location_context_menu_index = None; - return Task::none(); - } - if self.tab.edit_location.is_some() { // Close location editing if enabled self.tab.edit_location = None; @@ -1553,7 +1542,7 @@ impl Application for App { Message::Mouse(window_id, _button) => { // Close context menu when clicking outside. if self.core.main_window_id() == Some(window_id) { - return self.close_context_menus(); + return Task::none(); } } Message::NewFolder => { @@ -1713,7 +1702,7 @@ impl Application for App { ))); } Message::SearchActivate => { - let mut tasks = vec![self.close_context_menus()]; + let mut tasks = vec![]; if self.search_get().is_none() { tasks.push(self.search_set(Some(String::new()))); @@ -1724,7 +1713,7 @@ impl Application for App { return Task::batch(tasks); } Message::SearchClear => { - return Task::batch([self.close_context_menus(), self.search_set(None)]); + return self.search_set(None); } Message::SearchInput(input) => { return self.search_set(Some(input)); diff --git a/src/menu.rs b/src/menu.rs index fc7584c..4caa701 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -1,13 +1,12 @@ // SPDX-License-Identifier: GPL-3.0-only +use cosmic::{Element, theme}; use cosmic::app::Core; use cosmic::iced::keyboard::Modifiers; -use cosmic::iced::{Alignment, Background, Border, Length}; use cosmic::widget::menu::action::MenuAction; use cosmic::widget::menu::key_bind::KeyBind; use cosmic::widget::menu::{self, ItemHeight, ItemWidth, MenuBar}; -use cosmic::widget::{self, Row, button, column, container, divider, responsive_menu_bar, text}; -use cosmic::{Element, theme}; +use cosmic::widget::{self, responsive_menu_bar}; use i18n_embed::LanguageLoader; use mime_guess::Mime; use std::collections::HashMap; @@ -24,21 +23,6 @@ use crate::trash::{Trash, TrashExt}; static MENU_ID: LazyLock = LazyLock::new(|| cosmic::widget::Id::new("responsive-menu")); -macro_rules! menu_button { - ($($x:expr),+ $(,)?) => ( - button::custom( - Row::with_children( - [$(Element::from($x)),+] - ) - .height(Length::Fixed(24.0)) - .align_y(Alignment::Center) - ) - .padding([theme::spacing().space_xxs, 16]) - .width(Length::Fill) - .class(theme::Button::MenuItem) - ); -} - const fn menu_button_optional( label: String, action: Action, @@ -765,50 +749,33 @@ pub fn menu_bar<'a>( ) } -pub fn location_context_menu<'a>(ancestor_index: usize) -> Element<'a, tab::Message> { +pub fn location_context_menu(ancestor_index: usize) -> Vec> { //TODO: only add some of these when in App mode - let children = [ - menu_button!(text::body(fl!("open-in-new-tab"))) - .on_press(tab::Message::LocationMenuAction( + menu::items( + &HashMap::new(), + vec![ + menu::Item::Button( + fl!("open-in-new-tab"), + None, LocationMenuAction::OpenInNewTab(ancestor_index), - )) - .into(), - menu_button!(text::body(fl!("open-in-new-window"))) - .on_press(tab::Message::LocationMenuAction( + ), + menu::Item::Button( + fl!("open-in-new-window"), + None, LocationMenuAction::OpenInNewWindow(ancestor_index), - )) - .into(), - divider::horizontal::light().into(), - menu_button!(text::body(fl!("show-details"))) - .on_press(tab::Message::LocationMenuAction( + ), + menu::Item::Divider, + menu::Item::Button( + fl!("show-details"), + None, LocationMenuAction::Preview(ancestor_index), - )) - .into(), - divider::horizontal::light().into(), - menu_button!(text::body(fl!("add-to-sidebar"))) - .on_press(tab::Message::LocationMenuAction( + ), + menu::Item::Divider, + menu::Item::Button( + fl!("add-to-sidebar"), + None, LocationMenuAction::AddToSidebar(ancestor_index), - )) - .into(), - ]; - - container(column::with_children(children)) - .padding(1) - .style(|theme| { - let cosmic = theme.cosmic(); - let component = &cosmic.background(theme.transparent).component; - container::Style { - icon_color: Some(component.on.into()), - text_color: Some(component.on.into()), - background: Some(Background::Color(component.base.into())), - border: Border { - radius: cosmic.radius_s().map(|x| x + 1.0).into(), - width: 1.0, - color: component.divider.into(), - }, - ..Default::default() - } - }) - .width(Length::Fixed(360.0)) - .into() + ), + ], + ) } diff --git a/src/tab.rs b/src/tab.rs index 3b1a361..28a20f7 100644 --- a/src/tab.rs +++ b/src/tab.rs @@ -1779,8 +1779,7 @@ pub enum Message { ContextAction(Action), RightClickBackground, Surface(cosmic::surface::Action), - LocationContextMenuPoint(Option), - LocationContextMenuIndex(Option, Option), + LocationContextMenuIndex(Option), LocationMenuAction(LocationMenuAction), Drag(Option), DragEnd, @@ -2806,7 +2805,7 @@ pub struct Tab { pub location: Location, pub location_ancestors: Vec<(Location, String)>, pub location_title: String, - pub location_context_menu_point: Option, + /// Breadcrumb whose context menu is open, drawn as active while it shows pub location_context_menu_index: Option, pub mode: Mode, pub scroll_opt: Option, @@ -2952,7 +2951,6 @@ impl Tab { location, location_ancestors, location_title, - location_context_menu_point: None, location_context_menu_index: None, mode: Mode::App, scroll_opt: None, @@ -3572,7 +3570,6 @@ impl Tab { } if click_i_opt != self.clicked.take() { - self.location_context_menu_index = None; if let Some(ref mut items) = self.items_opt { for (i, item) in items.iter_mut().enumerate() { if mod_ctrl { @@ -3615,7 +3612,6 @@ impl Tab { Message::Click(click_i_opt) => { self.selected_clicked = false; self.edit_location = None; - self.location_context_menu_index = None; if click_i_opt.is_none() { self.clicked = click_i_opt; } @@ -3764,7 +3760,6 @@ impl Tab { } Message::RightClickBackground => { self.edit_location = None; - self.location_context_menu_index = None; //TODO: hack for clearing selecting when right clicking empty space if self.last_right_click.take().is_none() @@ -3778,15 +3773,10 @@ impl Tab { Message::Surface(action) => { commands.push(Command::Surface(action)); } - Message::LocationContextMenuPoint(point_opt) => { - self.location_context_menu_point = point_opt; - } - Message::LocationContextMenuIndex(p, index_opt) => { - self.location_context_menu_point = p; - self.location_context_menu_index = index_opt; + Message::LocationContextMenuIndex(index) => { + self.location_context_menu_index = index; } Message::LocationMenuAction(action) => { - self.location_context_menu_index = None; let path_for_index = |ancestor_index| { self.location .path_opt() @@ -3838,7 +3828,6 @@ impl Tab { Message::Drag(rect_opt) => { self.watch_drag = false; if let Some(rect) = rect_opt { - self.location_context_menu_index = None; if self.mode.multiple() { self.select_rect(rect, mod_ctrl, mod_shift); } @@ -5570,10 +5559,14 @@ impl Tab { } let location = self.location.with_path(ancestor.to_path_buf()); - let mut mouse_area = crate::mouse_area::MouseArea::new( + let mouse_area = crate::mouse_area::MouseArea::new( widget::button::custom(row) .padding(space_xxxs) - .class(theme::Button::Link) + .class(if self.location_context_menu_index == Some(index) { + theme::Button::LinkActive + } else { + theme::Button::Link + }) .on_press(if ancestor == path { Message::EditLocation(Some(self.location.clone().into())) } else { @@ -5581,21 +5574,6 @@ impl Tab { }), ); - if self.location_context_menu_index.is_some() { - mouse_area = mouse_area - .on_right_press(move |point_opt| { - Message::LocationContextMenuIndex(point_opt, None) - }) - .wayland_on_right_press_window_position(); - } else { - mouse_area = mouse_area - .on_right_press_no_capture() - .on_right_press(move |point_opt| { - Message::LocationContextMenuIndex(point_opt, Some(index)) - }) - .wayland_on_right_press_window_position(); - } - let mouse_area = if let Location::Path(_) = &self.location { mouse_area .on_middle_press(move |_| Message::OpenInNewTab(ancestor.to_path_buf())) @@ -5603,7 +5581,16 @@ impl Tab { mouse_area }; - children.push(self.dnd_dest(&location, mouse_area)); + // Each breadcrumb carries the menu for its own ancestor index + let mut context_menu = + widget::context_menu(mouse_area, Some(menu::location_context_menu(index))) + .on_open(Message::LocationContextMenuIndex(Some(index))) + .on_close(Message::LocationContextMenuIndex(None)) + .on_surface_action(Message::Surface); + if let Some(window_id) = self.window_id { + context_menu = context_menu.window_id(window_id); + } + children.push(self.dnd_dest(&location, context_menu)); if found_home || overflow { break; @@ -5654,20 +5641,7 @@ impl Tab { column = column.push(heading_rule); } - let mouse_area = crate::mouse_area::MouseArea::new(column) - .on_right_press(Message::LocationContextMenuPoint); - - let mut popover = widget::popover(mouse_area); - if let (Some(point), Some(index)) = ( - self.location_context_menu_point, - self.location_context_menu_index, - ) { - popover = popover - .popup(menu::location_context_menu(index)) - .position(widget::popover::Position::Point(point)); - } - - popover.into() + column.into() } pub fn empty_view(&self, has_hidden: bool) -> Element<'_, Message> {