🏡 index : ~doyle/shalom.git

author Jordan Doyle <jordan@doyle.la> 2024-01-06 17:17:04.0 +00:00:00
committer Jordan Doyle <jordan@doyle.la> 2024-01-06 17:17:04.0 +00:00:00
commit
e1c36f186f5de101c8482e42fc7e09c253437bf4 [patch]
tree
e6151c367f2a5f952cfb292a7cc907090543db1f
parent
6d04d3065e3e4c9a7d8befdb6ead797a9fba18de
download
e1c36f186f5de101c8482e42fc7e09c253437bf4.tar.gz

Prevent layers under context menus from disappearing



Diff

 shalom/src/main.rs                     |  1 +-
 shalom/src/widgets/blackhole_event.rs  | 83 +++++++++++++++++++++++++++++++++++-
 shalom/src/widgets/context_menu.rs     | 43 +++++++++++++-----
 shalom/src/widgets/image_background.rs | 19 +++-----
 shalom/src/widgets/mod.rs              |  1 +-
 5 files changed, 126 insertions(+), 21 deletions(-)

diff --git a/shalom/src/main.rs b/shalom/src/main.rs
index c826a2f..ca52e54 100644
--- a/shalom/src/main.rs
+++ b/shalom/src/main.rs
@@ -1,4 +1,5 @@
#![deny(clippy::pedantic)]
#![allow(clippy::struct_field_names)]

mod config;
mod context_menus;
diff --git a/shalom/src/widgets/blackhole_event.rs b/shalom/src/widgets/blackhole_event.rs
new file mode 100644
index 0000000..b70543e
--- /dev/null
+++ b/shalom/src/widgets/blackhole_event.rs
@@ -0,0 +1,83 @@
//! Prevents any events from reaching the inner element.

use iced::{advanced::overlay, Vector};

pub fn blackhole_event<O>(o: O) -> BlackholeEvent<O> {
    BlackholeEvent { overlay: o }
}

pub struct BlackholeEvent<O> {
    overlay: O,
}

impl<Message, Renderer: iced::advanced::Renderer> overlay::Overlay<Message, Renderer>
    for BlackholeEvent<overlay::Element<'_, Message, Renderer>>
{
    fn operate(
        &mut self,
        layout: iced::advanced::Layout<'_>,
        renderer: &Renderer,
        operation: &mut dyn iced::advanced::widget::Operation<Message>,
    ) {
        self.overlay.operate(layout, renderer, operation);
    }

    fn on_event(
        &mut self,
        _event: iced::Event,
        _layout: iced::advanced::Layout<'_>,
        _cursor: iced::advanced::mouse::Cursor,
        _renderer: &Renderer,
        _clipboard: &mut dyn iced::advanced::Clipboard,
        _shell: &mut iced::advanced::Shell<'_, Message>,
    ) -> iced::event::Status {
        iced::event::Status::Ignored
    }

    fn mouse_interaction(
        &self,
        _layout: iced::advanced::Layout<'_>,
        _cursor: iced::advanced::mouse::Cursor,
        _viewport: &iced::Rectangle,
        _renderer: &Renderer,
    ) -> iced::advanced::mouse::Interaction {
        iced::advanced::mouse::Interaction::Idle
    }

    fn is_over(
        &self,
        _layout: iced::advanced::Layout<'_>,
        _renderer: &Renderer,
        _cursor_position: iced::Point,
    ) -> bool {
        false
    }

    fn overlay<'a>(
        &'a mut self,
        layout: iced::advanced::Layout<'_>,
        renderer: &Renderer,
    ) -> Option<overlay::Element<'a, Message, Renderer>> {
        self.overlay.overlay(layout, renderer)
    }

    fn layout(
        &self,
        renderer: &Renderer,
        bounds: iced::Size,
        _position: iced::Point,
    ) -> iced::advanced::layout::Node {
        self.overlay.layout(renderer, bounds, Vector::ZERO)
    }

    fn draw(
        &self,
        renderer: &mut Renderer,
        theme: &<Renderer as iced::advanced::Renderer>::Theme,
        style: &iced::advanced::renderer::Style,
        layout: iced::advanced::Layout<'_>,
        cursor: iced::advanced::mouse::Cursor,
    ) {
        self.overlay.draw(renderer, theme, style, layout, cursor);
    }
}
diff --git a/shalom/src/widgets/context_menu.rs b/shalom/src/widgets/context_menu.rs
index 70200b6..a43a8ee 100644
--- a/shalom/src/widgets/context_menu.rs
+++ b/shalom/src/widgets/context_menu.rs
@@ -21,6 +21,8 @@ use iced::{
};
use keyframe::{functions::EaseOutQuint, keyframes, AnimationSequence};

use super::blackhole_event::blackhole_event;

pub struct ContextMenu<'a, M> {
    base: Element<'a, M, Renderer>,
    content: Element<'a, M, Renderer>,
@@ -140,17 +142,38 @@ impl<'a, M: Clone> Widget<M, Renderer> for ContextMenu<'a, M> {
        &'b mut self,
        state: &'b mut Tree,
        layout: Layout<'_>,
        _renderer: &Renderer,
        renderer: &Renderer,
    ) -> Option<overlay::Element<'b, M, Renderer>> {
        Some(overlay::Element::new(
            layout.position(),
            Box::new(Overlay {
                content: &mut self.content,
                tree: &mut state.children[1],
                on_close: self.on_close.clone(),
                state: state.state.downcast_mut::<OverlayState>(),
            }),
        ))
        let [ref mut base_tree, ref mut content_tree] = &mut state.children[..] else {
            panic!();
        };

        let mut group = overlay::Group::new();

        if let Some(child) = self
            .base
            .as_widget_mut()
            .overlay(base_tree, layout, renderer)
        {
            group = group.push(overlay::Element::new(
                layout.position(),
                Box::new(blackhole_event(child)),
            ));
        }

        Some(
            group
                .push(overlay::Element::new(
                    layout.position(),
                    Box::new(Overlay {
                        content: &mut self.content,
                        tree: content_tree,
                        on_close: self.on_close.clone(),
                        state: state.state.downcast_mut::<OverlayState>(),
                    }),
                ))
                .into(),
        )
    }
}

diff --git a/shalom/src/widgets/image_background.rs b/shalom/src/widgets/image_background.rs
index 9cf8dc7..e91a832 100644
--- a/shalom/src/widgets/image_background.rs
+++ b/shalom/src/widgets/image_background.rs
@@ -120,17 +120,14 @@ impl<
        layout: Layout<'_>,
        _renderer: &R,
    ) -> Option<iced::advanced::overlay::Element<'b, M, R>> {
        Some(
            overlay::Group::with_children(vec![overlay::Element::new(
                layout.position(),
                Box::new(Overlay {
                    el: &mut self.el,
                    tree: &mut state.children[0],
                    size: layout.bounds().size(),
                }),
            )])
            .overlay(),
        )
        Some(overlay::Element::new(
            layout.position(),
            Box::new(Overlay {
                el: &mut self.el,
                tree: &mut state.children[0],
                size: layout.bounds().size(),
            }),
        ))
    }
}

diff --git a/shalom/src/widgets/mod.rs b/shalom/src/widgets/mod.rs
index e04b2f8..16d56e0 100644
--- a/shalom/src/widgets/mod.rs
+++ b/shalom/src/widgets/mod.rs
@@ -1,3 +1,4 @@
pub mod blackhole_event;
pub mod cards;
pub mod colour_picker;
pub mod context_menu;