[fix] Right click menu in service and library
This commit is contained in:
parent
f746227ae2
commit
784e13b6ac
2 changed files with 115 additions and 57 deletions
97
src/main.rs
97
src/main.rs
|
|
@ -13,8 +13,8 @@ use cosmic::iced::keyboard::{Key, Modifiers};
|
|||
use cosmic::iced::widget::{column, row, stack};
|
||||
use cosmic::iced::window::Position;
|
||||
use cosmic::iced::{
|
||||
self, Background as IcedBackground, Border, Color, Length, Subscription, event,
|
||||
window,
|
||||
self, Background as IcedBackground, Border, Color, Length, Point, Subscription,
|
||||
event, window,
|
||||
};
|
||||
use cosmic::widget::dnd_destination::dnd_destination;
|
||||
use cosmic::widget::image::Handle;
|
||||
|
|
@ -24,8 +24,8 @@ use cosmic::widget::nav_bar::nav_bar_style;
|
|||
use cosmic::widget::space::{self, horizontal};
|
||||
use cosmic::widget::{
|
||||
Container, Space, button, container, context_menu, divider, icon, menu, mouse_area,
|
||||
nav_bar, nav_bar_toggle, responsive, scrollable, search_input, settings, slider,
|
||||
text, text_input, tooltip,
|
||||
nav_bar, nav_bar_toggle, popover, responsive, scrollable, search_input, settings,
|
||||
slider, text, text_input, tooltip,
|
||||
};
|
||||
use cosmic::{
|
||||
Application, ApplicationExt, Apply, Element, cosmic_config, executor, theme,
|
||||
|
|
@ -211,6 +211,8 @@ struct App {
|
|||
obs_connection: String,
|
||||
view_mode: ViewMode,
|
||||
genius_token_hidden: bool,
|
||||
hovered_point: iced::Point,
|
||||
context_point: iced::Point,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
@ -247,7 +249,7 @@ enum Message {
|
|||
AppendServiceItem(ServiceItem),
|
||||
AppendServiceItemKind(ServiceItemKind),
|
||||
ReorderService(usize, usize),
|
||||
ContextMenuItem(usize),
|
||||
ContextMenuItem(Option<usize>),
|
||||
SearchFocus,
|
||||
Search(String),
|
||||
CloseSearch,
|
||||
|
|
@ -273,6 +275,7 @@ enum Message {
|
|||
InsertThumbnail((iced::core::image::Allocation, usize)),
|
||||
ClearFooterMsg,
|
||||
SavingReport,
|
||||
ContextPoint(Point),
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
@ -464,6 +467,8 @@ impl cosmic::Application for App {
|
|||
hovered_item: None,
|
||||
hovered_dnd: None,
|
||||
context_menu: None,
|
||||
hovered_point: Point::ORIGIN,
|
||||
context_point: Point::ORIGIN,
|
||||
modifiers_pressed: None,
|
||||
settings_open: false,
|
||||
settings,
|
||||
|
|
@ -1434,7 +1439,12 @@ impl cosmic::Application for App {
|
|||
Task::none()
|
||||
}
|
||||
Message::ContextMenuItem(index) => {
|
||||
self.context_menu = Some(index);
|
||||
self.context_menu = index;
|
||||
self.context_point = self.hovered_point;
|
||||
Task::none()
|
||||
}
|
||||
Message::ContextPoint(point) => {
|
||||
self.hovered_point = point;
|
||||
Task::none()
|
||||
}
|
||||
Message::AddServiceItemDrop(index) => {
|
||||
|
|
@ -2172,21 +2182,41 @@ where
|
|||
}
|
||||
(Key::Character(k), _) if k == *"/" => self.update(Message::SearchFocus),
|
||||
(Key::Named(iced::keyboard::key::Named::ArrowRight), _) => {
|
||||
self.update(Message::Present(presenter::Message::NextSlide))
|
||||
if self.editor_mode.is_none() {
|
||||
self.update(Message::Present(presenter::Message::NextSlide))
|
||||
} else {
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
(Key::Named(iced::keyboard::key::Named::ArrowLeft), _) => {
|
||||
self.update(Message::Present(presenter::Message::PrevSlide))
|
||||
if self.editor_mode.is_none() {
|
||||
self.update(Message::Present(presenter::Message::PrevSlide))
|
||||
} else {
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
(Key::Character(k), _) if k == *" " => {
|
||||
self.update(Message::Present(presenter::Message::NextSlide))
|
||||
if self.editor_mode.is_none() {
|
||||
self.update(Message::Present(presenter::Message::NextSlide))
|
||||
} else {
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
(Key::Character(k), _) if k == *"j" || k == *"l" => {
|
||||
self.update(Message::Present(presenter::Message::NextSlide))
|
||||
if self.editor_mode.is_none() {
|
||||
self.update(Message::Present(presenter::Message::NextSlide))
|
||||
} else {
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
(Key::Character(k), _) if k == *"k" || k == *"h" => {
|
||||
self.update(Message::Present(presenter::Message::PrevSlide))
|
||||
if self.editor_mode.is_none() {
|
||||
self.update(Message::Present(presenter::Message::PrevSlide))
|
||||
} else {
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
(Key::Character(k), _) if k == *"q" => self.update(Message::Quit),
|
||||
// (Key::Character(k), _) if k == *"q" => self.update(Message::Quit),
|
||||
_ => Task::none(),
|
||||
}
|
||||
}
|
||||
|
|
@ -2251,32 +2281,35 @@ where
|
|||
container
|
||||
};
|
||||
let mouse_area = mouse_area(visual_item)
|
||||
.on_move(|point| Message::ContextPoint(point))
|
||||
.on_enter(Message::HoveredServiceItem(Some(index)))
|
||||
.on_exit(Message::HoveredServiceItem(None))
|
||||
.on_double_press(Message::ChangeServiceItem(index))
|
||||
.on_right_press(Message::ContextMenuItem(index))
|
||||
.on_right_press(Message::ContextMenuItem(Some(index)))
|
||||
.on_release(Message::SelectServiceItem(index));
|
||||
let single_item = if let Some(context_menu_item) = self.context_menu {
|
||||
let menu_item = |label, message| {
|
||||
menu::menu_button(vec![
|
||||
text(label).into(),
|
||||
space::horizontal().into(),
|
||||
])
|
||||
.on_press(message)
|
||||
};
|
||||
let delete_button: Element<Message> =
|
||||
menu_item("Delete", Message::RemoveServiceItem(index)).into();
|
||||
|
||||
let menu = column![delete_button]
|
||||
.spacing(theme::spacing().space_s)
|
||||
.apply(cosmic::widget::container)
|
||||
.width(300)
|
||||
.padding(theme::spacing().space_s)
|
||||
.class(theme::Container::Dropdown);
|
||||
|
||||
if context_menu_item == index {
|
||||
let context_menu = context_menu(
|
||||
mouse_area,
|
||||
self.context_menu.map_or_else(
|
||||
|| None,
|
||||
|i| {
|
||||
if i == index {
|
||||
let menu = vec![menu::Item::Button(
|
||||
"Delete",
|
||||
None,
|
||||
MenuAction::DeleteItem(index),
|
||||
)];
|
||||
Some(menu::items(&HashMap::new(), menu))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
.close_on_escape(true);
|
||||
let context_menu = popover(mouse_area)
|
||||
.position(popover::Position::Point(self.context_point))
|
||||
.on_close(Message::ContextMenuItem(None))
|
||||
.popup(menu);
|
||||
Element::from(context_menu)
|
||||
} else {
|
||||
Element::from(mouse_area)
|
||||
|
|
|
|||
|
|
@ -9,14 +9,14 @@ use cosmic::iced::core::text::{Ellipsize, EllipsizeHeightLimit};
|
|||
use cosmic::iced::core::widget::tree::State as TreeState;
|
||||
use cosmic::iced::keyboard::Modifiers;
|
||||
use cosmic::iced::widget::{column, row as rowm, text as textm};
|
||||
use cosmic::iced::{Background, Border, Color, Length};
|
||||
use cosmic::iced::{Background, Border, Color, Length, Point};
|
||||
use cosmic::widget::menu::{self, Action as MenuAction};
|
||||
use cosmic::widget::nav_bar::nav_bar_style;
|
||||
use cosmic::widget::space::{self, horizontal};
|
||||
use cosmic::widget::{
|
||||
Container, DndSource, Space, button, container, context_menu, divider,
|
||||
dnd_destination, icon, indeterminate_circular, mouse_area, row, scrollable, text,
|
||||
text_input,
|
||||
dnd_destination, icon, indeterminate_circular, mouse_area, popover, row, scrollable,
|
||||
text, text_input,
|
||||
};
|
||||
use cosmic::{Apply, Element, Task, theme};
|
||||
use itertools::Itertools;
|
||||
|
|
@ -53,6 +53,8 @@ pub struct Library {
|
|||
modifiers_pressed: Option<Modifiers>,
|
||||
state: State,
|
||||
video_popup_input: String,
|
||||
hovered_point: cosmic::iced::Point,
|
||||
context_point: cosmic::iced::Point,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
|
|
@ -108,7 +110,7 @@ pub enum Message {
|
|||
UpdatePresentation(Presentation),
|
||||
PresentationChanged,
|
||||
Error(String),
|
||||
OpenContext(i32),
|
||||
OpenContext(Option<i32>),
|
||||
None,
|
||||
AddFiles(Vec<ServiceItemKind>),
|
||||
ReaddSongs(Vec<Song>),
|
||||
|
|
@ -124,6 +126,7 @@ pub enum Message {
|
|||
AddSongFromEditor(Song),
|
||||
PopupUpdate(String),
|
||||
PopupSearch(String),
|
||||
HoverPoint(cosmic::iced::Point),
|
||||
}
|
||||
|
||||
impl<'a> Library {
|
||||
|
|
@ -148,6 +151,8 @@ impl<'a> Library {
|
|||
modifiers_pressed: None,
|
||||
state: State::Idle,
|
||||
video_popup_input: String::new(),
|
||||
hovered_point: Point::ORIGIN,
|
||||
context_point: Point::ORIGIN,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -526,10 +531,14 @@ impl<'a> Library {
|
|||
}
|
||||
Message::PresentationChanged => (),
|
||||
Message::Error(_) => (),
|
||||
Message::OpenContext(index) => {
|
||||
Message::OpenContext(None) => {
|
||||
self.context_menu = None;
|
||||
}
|
||||
Message::OpenContext(Some(index)) => {
|
||||
let Some(kind) = self.library_open else {
|
||||
return Action::None;
|
||||
};
|
||||
self.context_point = self.hovered_point;
|
||||
debug!(index, "should context");
|
||||
let Some(items) = self.selected_items.as_mut() else {
|
||||
self.selected_items = vec![(kind, index)].into();
|
||||
|
|
@ -547,6 +556,7 @@ impl<'a> Library {
|
|||
self.context_menu = Some(index);
|
||||
}
|
||||
Message::AddFiles(items) => return self.add_files(items),
|
||||
Message::HoverPoint(point) => self.hovered_point = point,
|
||||
Message::PopupUpdate(_) => todo!(),
|
||||
Message::PopupSearch(_) => todo!(),
|
||||
}
|
||||
|
|
@ -707,16 +717,17 @@ impl<'a> Library {
|
|||
let kind = model.kind;
|
||||
let visual_item = self.single_item(index, item, model);
|
||||
|
||||
DndSource::<Message, KindWrapper>::new({
|
||||
let item = DndSource::<Message, KindWrapper>::new({
|
||||
let mouse_area = mouse_area(visual_item);
|
||||
let mouse_area = mouse_area
|
||||
.on_move(|point| Message::HoverPoint(point))
|
||||
.on_enter(Message::HoverItem(Some((
|
||||
model.kind, i32_index,
|
||||
))))
|
||||
.on_double_click(Message::OpenItem(Some((
|
||||
model.kind, i32_index,
|
||||
))))
|
||||
.on_right_press(Message::OpenContext(i32_index))
|
||||
.on_right_press(Message::OpenContext(Some(i32_index)))
|
||||
.on_exit(Message::HoverItem(None))
|
||||
.on_press(Message::SelectItem(Some((
|
||||
model.kind, i32_index,
|
||||
|
|
@ -747,8 +758,9 @@ impl<'a> Library {
|
|||
(icon.into(), state, i)
|
||||
}
|
||||
})
|
||||
.drag_content(move || KindWrapper((kind, i32_index)))
|
||||
.into()
|
||||
.drag_content(move || KindWrapper((kind, i32_index)));
|
||||
|
||||
self.context_menu(item.into(), kind, i32_index).into()
|
||||
})
|
||||
})
|
||||
.spacing(2)
|
||||
|
|
@ -764,8 +776,7 @@ impl<'a> Library {
|
|||
.on_press(Message::AddItem)
|
||||
)
|
||||
.align_y(Vertical::Center);
|
||||
let context_menu = self.context_menu(items.into());
|
||||
let library_column = column![library_toolbar, context_menu].spacing(3);
|
||||
let library_column = column![library_toolbar, items].spacing(3);
|
||||
Container::new(library_column).padding(5)
|
||||
} else {
|
||||
Container::new(Space::new())
|
||||
|
|
@ -925,22 +936,36 @@ impl<'a> Library {
|
|||
.into()
|
||||
}
|
||||
|
||||
fn context_menu<'b>(&self, items: Element<'b, Message>) -> Element<'b, Message> {
|
||||
if self.context_menu.is_some() {
|
||||
let menu_items = vec![
|
||||
menu::Item::Button("Open", None, MenuMessage::Open),
|
||||
menu::Item::Button("Delete", None, MenuMessage::Delete),
|
||||
];
|
||||
let context_menu = context_menu(
|
||||
items,
|
||||
self.context_menu.map_or_else(
|
||||
|| None,
|
||||
|_| Some(menu::items(&self.menu_keys, menu_items)),
|
||||
),
|
||||
);
|
||||
fn context_menu<'b>(
|
||||
&self,
|
||||
item: Element<'b, Message>,
|
||||
library: LibraryKind,
|
||||
id: i32,
|
||||
) -> Element<'b, Message> {
|
||||
if self.context_menu.is_some_and(|index| index == id)
|
||||
&& self.library_open.is_some_and(|kind| kind == library)
|
||||
{
|
||||
let menu_item = |label, message| {
|
||||
menu::menu_button(vec![text(label).into(), space::horizontal().into()])
|
||||
.on_press(message)
|
||||
};
|
||||
|
||||
let menu_items = column![
|
||||
menu_item("Open", Message::OpenItem(Some((library, id)))),
|
||||
menu_item("Delete", Message::DeleteItem),
|
||||
]
|
||||
.spacing(theme::spacing().space_s)
|
||||
.apply(container)
|
||||
.width(300)
|
||||
.padding(theme::spacing().space_s)
|
||||
.class(theme::Container::Dropdown);
|
||||
let context_menu = popover(item)
|
||||
.position(popover::Position::Point(self.context_point))
|
||||
.on_close(Message::OpenContext(None))
|
||||
.popup(menu_items);
|
||||
Element::from(context_menu)
|
||||
} else {
|
||||
items
|
||||
item
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue