diff options
Diffstat (limited to 'widget/src/helpers.rs')
-rw-r--r-- | widget/src/helpers.rs | 98 |
1 files changed, 64 insertions, 34 deletions
diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index 52290a54..cdfd2daf 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -24,7 +24,7 @@ use crate::text_input::{self, TextInput}; use crate::toggler::{self, Toggler}; use crate::tooltip::{self, Tooltip}; use crate::vertical_slider::{self, VerticalSlider}; -use crate::{Column, MouseArea, Row, Space, Stack, Themer}; +use crate::{Column, MouseArea, Pin, Row, Space, Stack, Themer}; use std::borrow::Borrow; use std::ops::RangeInclusive; @@ -249,6 +249,38 @@ where container(content).center(Length::Fill) } +/// Creates a new [`Pin`] widget with the given content. +/// +/// A [`Pin`] widget positions its contents at some fixed coordinates inside of its boundaries. +/// +/// # Example +/// ```no_run +/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::core::Length::Fill; } +/// # pub type State = (); +/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>; +/// use iced::widget::pin; +/// use iced::Fill; +/// +/// enum Message { +/// // ... +/// } +/// +/// fn view(state: &State) -> Element<'_, Message> { +/// pin("This text is displayed at coordinates (50, 50)!") +/// .x(50) +/// .y(50) +/// .into() +/// } +/// ``` +pub fn pin<'a, Message, Theme, Renderer>( + content: impl Into<Element<'a, Message, Theme, Renderer>>, +) -> Pin<'a, Message, Theme, Renderer> +where + Renderer: core::Renderer, +{ + Pin::new(content) +} + /// Creates a new [`Column`] with the given children. /// /// Columns distribute their children vertically. @@ -363,19 +395,18 @@ where 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}; + use crate::core::{Event, 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> + impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer> + for Opaque<'_, Message, Theme, Renderer> where Renderer: core::Renderer, { @@ -439,7 +470,7 @@ where .operate(state, layout, renderer, operation); } - fn on_event( + fn update( &mut self, state: &mut Tree, event: Event, @@ -449,25 +480,19 @@ where 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; - } + self.content.as_widget_mut().update( + state, event, layout, cursor, renderer, clipboard, shell, + viewport, + ); if is_mouse_press && cursor.is_over(layout.bounds()) { - event::Status::Captured - } else { - event::Status::Ignored + shell.capture_event(); } } @@ -530,22 +555,22 @@ where 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}; + use crate::core::{Event, Rectangle, Shell, Size}; struct Hover<'a, Message, Theme, Renderer> { base: Element<'a, Message, Theme, Renderer>, top: Element<'a, Message, Theme, Renderer>, is_top_focused: bool, is_top_overlay_active: bool, + is_hovered: bool, } - impl<'a, Message, Theme, Renderer> Widget<Message, Theme, Renderer> - for Hover<'a, Message, Theme, Renderer> + impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer> + for Hover<'_, Message, Theme, Renderer> where Renderer: core::Renderer, { @@ -648,7 +673,7 @@ where } } - fn on_event( + fn update( &mut self, tree: &mut Tree, event: Event, @@ -658,11 +683,13 @@ where clipboard: &mut dyn core::Clipboard, shell: &mut Shell<'_, Message>, viewport: &Rectangle, - ) -> event::Status { + ) { let mut children = layout.children().zip(&mut tree.children); let (base_layout, base_tree) = children.next().unwrap(); let (top_layout, top_tree) = children.next().unwrap(); + let is_hovered = cursor.is_over(layout.bounds()); + if matches!(event, Event::Window(window::Event::RedrawRequested(_))) { let mut count_focused = operation::focusable::count(); @@ -678,19 +705,23 @@ where operation::Outcome::Some(count) => count.focused.is_some(), _ => false, }; + + self.is_hovered = is_hovered; + } else if is_hovered != self.is_hovered { + shell.request_redraw(); } - let top_status = if matches!( + if matches!( event, Event::Mouse( mouse::Event::CursorMoved { .. } | mouse::Event::ButtonReleased(_) ) - ) || cursor.is_over(layout.bounds()) + ) || is_hovered || self.is_top_focused || self.is_top_overlay_active { - self.top.as_widget_mut().on_event( + self.top.as_widget_mut().update( top_tree, event.clone(), top_layout, @@ -699,16 +730,14 @@ where clipboard, shell, viewport, - ) - } else { - event::Status::Ignored + ); }; - if top_status == event::Status::Captured { - return top_status; + if shell.is_event_captured() { + return; } - self.base.as_widget_mut().on_event( + self.base.as_widget_mut().update( base_tree, event.clone(), base_layout, @@ -717,7 +746,7 @@ where clipboard, shell, viewport, - ) + ); } fn mouse_interaction( @@ -777,6 +806,7 @@ where top: top.into(), is_top_focused: false, is_top_overlay_active: false, + is_hovered: false, }) } |