Compare commits
1 commit
master
...
context-me
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aebf8c4259 |
1 changed files with 74 additions and 15 deletions
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#[cfg(all(feature = "wayland", feature = "winit", feature = "surface-message"))]
|
#[cfg(all(feature = "wayland", feature = "winit", feature = "surface-message"))]
|
||||||
use crate::app::cosmic::{WINDOWING_SYSTEM, WindowingSystem};
|
use crate::app::cosmic::{WINDOWING_SYSTEM, WindowingSystem};
|
||||||
|
use crate::surface;
|
||||||
use crate::widget::menu::{
|
use crate::widget::menu::{
|
||||||
self, CloseCondition, Direction, ItemHeight, ItemWidth, MenuBarState, PathHighlight,
|
self, CloseCondition, Direction, ItemHeight, ItemWidth, MenuBarState, PathHighlight,
|
||||||
init_root_menu, menu_roots_diff,
|
init_root_menu, menu_roots_diff,
|
||||||
|
|
@ -22,7 +23,7 @@ pub fn context_menu<Message: 'static + Clone>(
|
||||||
content: impl Into<crate::Element<'static, Message>> + 'static,
|
content: impl Into<crate::Element<'static, Message>> + 'static,
|
||||||
// on_context: Message,
|
// on_context: Message,
|
||||||
context_menu: Option<Vec<menu::Tree<Message>>>,
|
context_menu: Option<Vec<menu::Tree<Message>>>,
|
||||||
) -> ContextMenu<'static, Message> {
|
) -> ContextMenu<'static, Message, Message> {
|
||||||
let mut this = ContextMenu {
|
let mut this = ContextMenu {
|
||||||
content: content.into(),
|
content: content.into(),
|
||||||
context_menu: context_menu.map(|menus| {
|
context_menu: context_menu.map(|menus| {
|
||||||
|
|
@ -33,6 +34,7 @@ pub fn context_menu<Message: 'static + Clone>(
|
||||||
}),
|
}),
|
||||||
window_id: window::Id::RESERVED,
|
window_id: window::Id::RESERVED,
|
||||||
on_surface_action: None,
|
on_surface_action: None,
|
||||||
|
action_map: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(ref mut context_menu) = this.context_menu {
|
if let Some(ref mut context_menu) = this.context_menu {
|
||||||
|
|
@ -42,10 +44,42 @@ pub fn context_menu<Message: 'static + Clone>(
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A context menu is a menu in a graphical user interface that appears upon user interaction, such as a right-click mouse operation.
|
||||||
|
pub fn context_menu_popup<Message: 'static + Clone, AppMessage: 'static + Clone>(
|
||||||
|
content: impl Into<crate::Element<'static, Message>> + 'static,
|
||||||
|
// on_context: Message,
|
||||||
|
context_menu: Option<Vec<menu::Tree<Message>>>,
|
||||||
|
_parent_id: window::Id,
|
||||||
|
_on_surface_action: impl Fn(surface::Action) -> Message + Send + Sync + 'static,
|
||||||
|
_map_action: impl Fn(Message) -> AppMessage + Send + Sync + 'static,
|
||||||
|
) -> ContextMenu<'static, Message, AppMessage> {
|
||||||
|
let mut this: ContextMenu<'_, Message, AppMessage> = ContextMenu {
|
||||||
|
content: content.into(),
|
||||||
|
context_menu: context_menu.map(|menus| {
|
||||||
|
vec![menu::Tree::with_children(
|
||||||
|
crate::Element::from(crate::widget::row::<'static, Message>()),
|
||||||
|
menus,
|
||||||
|
)]
|
||||||
|
}),
|
||||||
|
window_id: window::Id::RESERVED,
|
||||||
|
on_surface_action: None,
|
||||||
|
action_map: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "winit", feature = "wayland"))]
|
||||||
|
let mut this = this.with_popup(_parent_id, _on_surface_action, _map_action);
|
||||||
|
|
||||||
|
if let Some(ref mut context_menu) = this.context_menu {
|
||||||
|
context_menu.iter_mut().for_each(menu::Tree::set_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
/// A context menu is a menu in a graphical user interface that appears upon user interaction, such as a right-click mouse operation.
|
/// A context menu is a menu in a graphical user interface that appears upon user interaction, such as a right-click mouse operation.
|
||||||
#[derive(Setters)]
|
#[derive(Setters)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct ContextMenu<'a, Message> {
|
pub struct ContextMenu<'a, Message, AppMessage> {
|
||||||
#[setters(skip)]
|
#[setters(skip)]
|
||||||
content: crate::Element<'a, Message>,
|
content: crate::Element<'a, Message>,
|
||||||
#[setters(skip)]
|
#[setters(skip)]
|
||||||
|
|
@ -54,9 +88,13 @@ pub struct ContextMenu<'a, Message> {
|
||||||
#[setters(skip)]
|
#[setters(skip)]
|
||||||
pub(crate) on_surface_action:
|
pub(crate) on_surface_action:
|
||||||
Option<Arc<dyn Fn(crate::surface::Action) -> Message + Send + Sync + 'static>>,
|
Option<Arc<dyn Fn(crate::surface::Action) -> Message + Send + Sync + 'static>>,
|
||||||
|
#[setters(skip)]
|
||||||
|
pub action_map: Option<Arc<dyn Fn(Message) -> AppMessage + 'static + Send + Sync>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Message: Clone + 'static> ContextMenu<'_, Message> {
|
impl<'a, Message: Clone + 'static, AppMessage: Clone + 'static>
|
||||||
|
ContextMenu<'a, Message, AppMessage>
|
||||||
|
{
|
||||||
#[cfg(all(feature = "wayland", feature = "winit", feature = "surface-message"))]
|
#[cfg(all(feature = "wayland", feature = "winit", feature = "surface-message"))]
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
fn create_popup(
|
fn create_popup(
|
||||||
|
|
@ -68,7 +106,10 @@ impl<Message: Clone + 'static> ContextMenu<'_, Message> {
|
||||||
viewport: &iced::Rectangle,
|
viewport: &iced::Rectangle,
|
||||||
my_state: &mut LocalState,
|
my_state: &mut LocalState,
|
||||||
) {
|
) {
|
||||||
if self.window_id != window::Id::NONE && self.on_surface_action.is_some() {
|
if self.window_id != window::Id::NONE
|
||||||
|
&& self.on_surface_action.is_some()
|
||||||
|
&& self.action_map.is_some()
|
||||||
|
{
|
||||||
use crate::{surface::action::destroy_popup, widget::menu::Menu};
|
use crate::{surface::action::destroy_popup, widget::menu::Menu};
|
||||||
use iced_runtime::platform_specific::wayland::popup::{
|
use iced_runtime::platform_specific::wayland::popup::{
|
||||||
SctkPopupSettings, SctkPositioner,
|
SctkPopupSettings, SctkPositioner,
|
||||||
|
|
@ -171,6 +212,7 @@ impl<Message: Clone + 'static> ContextMenu<'_, Message> {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let parent = self.window_id;
|
let parent = self.window_id;
|
||||||
|
let action_map = self.action_map.clone().unwrap();
|
||||||
shell.publish((self.on_surface_action.as_ref().unwrap())(
|
shell.publish((self.on_surface_action.as_ref().unwrap())(
|
||||||
crate::surface::action::simple_popup(
|
crate::surface::action::simple_popup(
|
||||||
move || SctkPopupSettings {
|
move || SctkPopupSettings {
|
||||||
|
|
@ -183,27 +225,44 @@ impl<Message: Clone + 'static> ContextMenu<'_, Message> {
|
||||||
input_zone: None,
|
input_zone: None,
|
||||||
},
|
},
|
||||||
Some(move || {
|
Some(move || {
|
||||||
|
let action_map = action_map.clone();
|
||||||
crate::Element::from(
|
crate::Element::from(
|
||||||
crate::widget::container(popup_menu.clone()).center(Length::Fill),
|
crate::widget::container(popup_menu.clone()).center(Length::Fill),
|
||||||
)
|
)
|
||||||
.map(crate::action::app)
|
.map(move |m| crate::Action::App(action_map.clone()(m)))
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_surface_action(
|
#[cfg(all(feature = "winit", feature = "wayland"))]
|
||||||
|
/// Handle dropdown requests for popup creation.
|
||||||
|
/// Intended to be used with [`crate::app::message::get_popup`]
|
||||||
|
pub fn with_popup<NewAppMessage>(
|
||||||
mut self,
|
mut self,
|
||||||
handler: impl Fn(crate::surface::Action) -> Message + Send + Sync + 'static,
|
parent_id: window::Id,
|
||||||
) -> Self {
|
on_surface_action: impl Fn(surface::Action) -> Message + Send + Sync + 'static,
|
||||||
self.on_surface_action = Some(Arc::new(handler));
|
action_map: impl Fn(Message) -> NewAppMessage + Send + Sync + 'static,
|
||||||
self
|
) -> ContextMenu<'a, Message, NewAppMessage> {
|
||||||
|
let Self {
|
||||||
|
content,
|
||||||
|
context_menu,
|
||||||
|
..
|
||||||
|
} = self;
|
||||||
|
let new = ContextMenu::<'a, Message, NewAppMessage> {
|
||||||
|
content,
|
||||||
|
context_menu,
|
||||||
|
on_surface_action: Some(Arc::new(on_surface_action)),
|
||||||
|
action_map: Some(Arc::new(action_map)),
|
||||||
|
window_id: parent_id,
|
||||||
|
};
|
||||||
|
new
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Message: 'static + Clone> Widget<Message, crate::Theme, crate::Renderer>
|
impl<Message: 'static + Clone, AppMessage: 'static + Clone>
|
||||||
for ContextMenu<'_, Message>
|
Widget<Message, crate::Theme, crate::Renderer> for ContextMenu<'_, Message, AppMessage>
|
||||||
{
|
{
|
||||||
fn tag(&self) -> tree::Tag {
|
fn tag(&self) -> tree::Tag {
|
||||||
tree::Tag::of::<LocalState>()
|
tree::Tag::of::<LocalState>()
|
||||||
|
|
@ -539,10 +598,10 @@ impl<Message: 'static + Clone> Widget<Message, crate::Theme, crate::Renderer>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Message: Clone + 'static> From<ContextMenu<'static, Message>>
|
impl<'a, Message: Clone + 'static, AppMessage: Clone + 'static>
|
||||||
for crate::Element<'static, Message>
|
From<ContextMenu<'static, Message, AppMessage>> for crate::Element<'static, Message>
|
||||||
{
|
{
|
||||||
fn from(widget: ContextMenu<'static, Message>) -> Self {
|
fn from(widget: ContextMenu<'static, Message, AppMessage>) -> Self {
|
||||||
Self::new(widget)
|
Self::new(widget)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue