Introduce opaque widget helper
This commit is contained in:
parent
9492da11d9
commit
4cd45643d7
13 changed files with 182 additions and 12 deletions
|
|
@ -3,6 +3,7 @@
|
|||
#[allow(missing_docs)]
|
||||
pub enum Interaction {
|
||||
#[default]
|
||||
None,
|
||||
Idle,
|
||||
Pointer,
|
||||
Grab,
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ where
|
|||
_viewport: &Rectangle,
|
||||
_renderer: &Renderer,
|
||||
) -> mouse::Interaction {
|
||||
mouse::Interaction::Idle
|
||||
mouse::Interaction::None
|
||||
}
|
||||
|
||||
/// Returns true if the cursor is over the [`Overlay`].
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ where
|
|||
_viewport: &Rectangle,
|
||||
_renderer: &Renderer,
|
||||
) -> mouse::Interaction {
|
||||
mouse::Interaction::Idle
|
||||
mouse::Interaction::None
|
||||
}
|
||||
|
||||
/// Returns the overlay of the [`Widget`], if there is any.
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ mod loupe {
|
|||
if cursor.is_over(layout.bounds()) {
|
||||
mouse::Interaction::ZoomIn
|
||||
} else {
|
||||
mouse::Interaction::Idle
|
||||
mouse::Interaction::None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ where
|
|||
caches,
|
||||
queued_events: Vec::new(),
|
||||
queued_messages: Vec::new(),
|
||||
mouse_interaction: mouse::Interaction::Idle,
|
||||
mouse_interaction: mouse::Interaction::None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ where
|
|||
cache,
|
||||
queued_events: Vec::new(),
|
||||
queued_messages: Vec::new(),
|
||||
mouse_interaction: mouse::Interaction::Idle,
|
||||
mouse_interaction: mouse::Interaction::None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use crate::combo_box::{self, ComboBox};
|
|||
use crate::container::{self, Container};
|
||||
use crate::core;
|
||||
use crate::core::widget::operation;
|
||||
use crate::core::{Element, Length, Pixels};
|
||||
use crate::core::{Element, Length, Pixels, Widget};
|
||||
use crate::keyed;
|
||||
use crate::overlay;
|
||||
use crate::pick_list::{self, PickList};
|
||||
|
|
@ -123,6 +123,173 @@ where
|
|||
Stack::with_children(children)
|
||||
}
|
||||
|
||||
/// Wraps the given widget and captures any mouse button presses inside the bounds of
|
||||
/// the widget—therefore making it _opaque_.
|
||||
///
|
||||
/// This helper is meant to be used to mark elements in a [`Stack`] to avoid mouse
|
||||
/// events from passing through layers.
|
||||
///
|
||||
/// [`Stack`]: crate::Stack
|
||||
pub fn opaque<'a, Message, Theme, Renderer>(
|
||||
content: impl Into<Element<'a, Message, Theme, Renderer>>,
|
||||
) -> Element<'a, Message, Theme, Renderer>
|
||||
where
|
||||
Message: 'a,
|
||||
Theme: 'a,
|
||||
Renderer: core::Renderer + 'a,
|
||||
{
|
||||
use crate::core::event::{self, Event};
|
||||
use crate::core::layout::{self, Layout};
|
||||
use crate::core::mouse;
|
||||
use crate::core::renderer;
|
||||
use crate::core::widget::tree::{self, Tree};
|
||||
use crate::core::{Rectangle, Shell, Size};
|
||||
|
||||
struct Opaque<'a, Message, Theme, Renderer> {
|
||||
content: Element<'a, Message, Theme, Renderer>,
|
||||
}
|
||||
|
||||
impl<'a, Message, Theme, Renderer> Widget<Message, Theme, Renderer>
|
||||
for Opaque<'a, Message, Theme, Renderer>
|
||||
where
|
||||
Renderer: core::Renderer,
|
||||
{
|
||||
fn tag(&self) -> tree::Tag {
|
||||
self.content.as_widget().tag()
|
||||
}
|
||||
|
||||
fn state(&self) -> tree::State {
|
||||
self.content.as_widget().state()
|
||||
}
|
||||
|
||||
fn children(&self) -> Vec<Tree> {
|
||||
self.content.as_widget().children()
|
||||
}
|
||||
|
||||
fn diff(&self, tree: &mut Tree) {
|
||||
self.content.as_widget().diff(tree);
|
||||
}
|
||||
|
||||
fn size(&self) -> Size<Length> {
|
||||
self.content.as_widget().size()
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> Size<Length> {
|
||||
self.content.as_widget().size_hint()
|
||||
}
|
||||
|
||||
fn layout(
|
||||
&self,
|
||||
tree: &mut Tree,
|
||||
renderer: &Renderer,
|
||||
limits: &layout::Limits,
|
||||
) -> layout::Node {
|
||||
self.content.as_widget().layout(tree, renderer, limits)
|
||||
}
|
||||
|
||||
fn draw(
|
||||
&self,
|
||||
tree: &Tree,
|
||||
renderer: &mut Renderer,
|
||||
theme: &Theme,
|
||||
style: &renderer::Style,
|
||||
layout: Layout<'_>,
|
||||
cursor: mouse::Cursor,
|
||||
viewport: &Rectangle,
|
||||
) {
|
||||
self.content
|
||||
.as_widget()
|
||||
.draw(tree, renderer, theme, style, layout, cursor, viewport);
|
||||
}
|
||||
|
||||
fn operate(
|
||||
&self,
|
||||
state: &mut Tree,
|
||||
layout: Layout<'_>,
|
||||
renderer: &Renderer,
|
||||
operation: &mut dyn operation::Operation<Message>,
|
||||
) {
|
||||
self.content
|
||||
.as_widget()
|
||||
.operate(state, layout, renderer, operation);
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
state: &mut Tree,
|
||||
event: Event,
|
||||
layout: Layout<'_>,
|
||||
cursor: mouse::Cursor,
|
||||
renderer: &Renderer,
|
||||
clipboard: &mut dyn core::Clipboard,
|
||||
shell: &mut Shell<'_, Message>,
|
||||
viewport: &Rectangle,
|
||||
) -> event::Status {
|
||||
let is_mouse_press = matches!(
|
||||
event,
|
||||
core::Event::Mouse(mouse::Event::ButtonPressed(_))
|
||||
);
|
||||
|
||||
if let core::event::Status::Captured =
|
||||
self.content.as_widget_mut().on_event(
|
||||
state, event, layout, cursor, renderer, clipboard, shell,
|
||||
viewport,
|
||||
)
|
||||
{
|
||||
return event::Status::Captured;
|
||||
}
|
||||
|
||||
if is_mouse_press && cursor.is_over(layout.bounds()) {
|
||||
event::Status::Captured
|
||||
} else {
|
||||
event::Status::Ignored
|
||||
}
|
||||
}
|
||||
|
||||
fn mouse_interaction(
|
||||
&self,
|
||||
state: &core::widget::Tree,
|
||||
layout: core::Layout<'_>,
|
||||
cursor: core::mouse::Cursor,
|
||||
viewport: &core::Rectangle,
|
||||
renderer: &Renderer,
|
||||
) -> core::mouse::Interaction {
|
||||
let interaction = self
|
||||
.content
|
||||
.as_widget()
|
||||
.mouse_interaction(state, layout, cursor, viewport, renderer);
|
||||
|
||||
if interaction == mouse::Interaction::None
|
||||
&& cursor.is_over(layout.bounds())
|
||||
{
|
||||
mouse::Interaction::Idle
|
||||
} else {
|
||||
interaction
|
||||
}
|
||||
}
|
||||
|
||||
fn overlay<'b>(
|
||||
&'b mut self,
|
||||
state: &'b mut core::widget::Tree,
|
||||
layout: core::Layout<'_>,
|
||||
renderer: &Renderer,
|
||||
translation: core::Vector,
|
||||
) -> Option<core::overlay::Element<'b, Message, Theme, Renderer>>
|
||||
{
|
||||
self.content.as_widget_mut().overlay(
|
||||
state,
|
||||
layout,
|
||||
renderer,
|
||||
translation,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Element::new(Opaque {
|
||||
content: content.into(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new [`Scrollable`] with the provided content.
|
||||
///
|
||||
/// [`Scrollable`]: crate::Scrollable
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ where
|
|||
} else if is_mouse_over {
|
||||
mouse::Interaction::Grab
|
||||
} else {
|
||||
mouse::Interaction::Idle
|
||||
mouse::Interaction::None
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ where
|
|||
);
|
||||
|
||||
match (self.interaction, content_interaction) {
|
||||
(Some(interaction), mouse::Interaction::Idle)
|
||||
(Some(interaction), mouse::Interaction::None)
|
||||
if cursor.is_over(layout.bounds()) =>
|
||||
{
|
||||
interaction
|
||||
|
|
|
|||
|
|
@ -857,7 +857,7 @@ where
|
|||
if (mouse_over_x_scrollbar || mouse_over_y_scrollbar)
|
||||
|| state.scrollers_grabbed()
|
||||
{
|
||||
mouse::Interaction::Idle
|
||||
mouse::Interaction::None
|
||||
} else {
|
||||
let translation =
|
||||
state.translation(self.direction, bounds, content_bounds);
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ where
|
|||
state, layout, cursor, viewport, renderer,
|
||||
)
|
||||
})
|
||||
.find(|&interaction| interaction != mouse::Interaction::Idle)
|
||||
.find(|&interaction| interaction != mouse::Interaction::None)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -396,7 +396,9 @@ pub fn mouse_interaction(
|
|||
use mouse::Interaction;
|
||||
|
||||
match interaction {
|
||||
Interaction::Idle => winit::window::CursorIcon::Default,
|
||||
Interaction::None | Interaction::Idle => {
|
||||
winit::window::CursorIcon::Default
|
||||
}
|
||||
Interaction::Pointer => winit::window::CursorIcon::Pointer,
|
||||
Interaction::Working => winit::window::CursorIcon::Progress,
|
||||
Interaction::Grab => winit::window::CursorIcon::Grab,
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ where
|
|||
exit_on_close_request,
|
||||
surface,
|
||||
renderer,
|
||||
mouse_interaction: mouse::Interaction::Idle,
|
||||
mouse_interaction: mouse::Interaction::None,
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue