Introduce Shell type in iced_native

Widgets now can invalidate the current layout of the application on demand.
This commit is contained in:
Héctor Ramón Jiménez 2021-11-29 16:22:01 +07:00
parent f7792d89d6
commit bbd9355450
No known key found for this signature in database
GPG key ID: 140CC052C94F138E
26 changed files with 218 additions and 130 deletions

View file

@ -9,8 +9,8 @@ use crate::{Backend, Primitive};
use iced_native::layout; use iced_native::layout;
use iced_native::mouse; use iced_native::mouse;
use iced_native::{ use iced_native::{
Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Size, Vector, Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Shell, Size,
Widget, Vector, Widget,
}; };
use std::hash::Hash; use std::hash::Hash;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -158,7 +158,7 @@ where
cursor_position: Point, cursor_position: Point,
_renderer: &Renderer<B>, _renderer: &Renderer<B>,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
let bounds = layout.bounds(); let bounds = layout.bounds();
@ -179,7 +179,7 @@ where
self.program.update(canvas_event, bounds, cursor); self.program.update(canvas_event, bounds, cursor);
if let Some(message) = message { if let Some(message) = message {
messages.push(message); shell.publish(message);
} }
return event_status; return event_status;

View file

@ -4,7 +4,7 @@ use iced_native::mouse;
use iced_native::overlay; use iced_native::overlay;
use iced_native::renderer; use iced_native::renderer;
use iced_native::{ use iced_native::{
Clipboard, Element, Hasher, Length, Point, Rectangle, Widget, Clipboard, Element, Hasher, Length, Point, Rectangle, Shell, Widget,
}; };
use ouroboros::self_referencing; use ouroboros::self_referencing;
@ -91,9 +91,10 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
let mut local_messages = Vec::new(); let mut local_messages = Vec::new();
let mut local_shell = Shell::new(&mut local_messages);
let event_status = let event_status =
self.state.as_mut().unwrap().with_cache_mut(|cache| { self.state.as_mut().unwrap().with_cache_mut(|cache| {
@ -103,7 +104,7 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
&mut local_messages, &mut local_shell,
) )
}); });
@ -111,11 +112,12 @@ where
let mut component = let mut component =
self.state.take().unwrap().into_heads().component; self.state.take().unwrap().into_heads().component;
messages.extend( for message in local_messages
local_messages .into_iter()
.into_iter() .filter_map(|message| component.update(message))
.filter_map(|message| component.update(message)), {
); shell.publish(message);
}
self.state = Some( self.state = Some(
StateBuilder { StateBuilder {
@ -128,7 +130,7 @@ where
.build(), .build(),
); );
// TODO: Invalidate layout (!) shell.invalidate_layout();
} }
event_status event_status

View file

@ -4,7 +4,7 @@ use crate::mouse;
use crate::overlay; use crate::overlay;
use crate::renderer; use crate::renderer;
use crate::{ use crate::{
Clipboard, Color, Hasher, Layout, Length, Point, Rectangle, Widget, Clipboard, Color, Hasher, Layout, Length, Point, Rectangle, Shell, Widget,
}; };
/// A generic [`Widget`]. /// A generic [`Widget`].
@ -228,7 +228,7 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
self.widget.on_event( self.widget.on_event(
event, event,
@ -236,7 +236,7 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
messages, shell,
) )
} }
@ -327,9 +327,10 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<B>, shell: &mut Shell<'_, B>,
) -> event::Status { ) -> event::Status {
let mut original_messages = Vec::new(); let mut local_messages = Vec::new();
let mut local_shell = Shell::new(&mut local_messages);
let status = self.widget.on_event( let status = self.widget.on_event(
event, event,
@ -337,12 +338,10 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
&mut original_messages, &mut local_shell,
); );
original_messages shell.merge(local_shell, &self.mapper);
.drain(..)
.for_each(|message| messages.push((self.mapper)(message)));
status status
} }
@ -427,7 +426,7 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
self.element.widget.on_event( self.element.widget.on_event(
event, event,
@ -435,7 +434,7 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
messages, shell,
) )
} }

View file

@ -53,6 +53,7 @@ pub mod window;
mod element; mod element;
mod hasher; mod hasher;
mod runtime; mod runtime;
mod shell;
mod user_interface; mod user_interface;
// We disable debug capabilities on release builds unless the `debug` feature // We disable debug capabilities on release builds unless the `debug` feature
@ -85,6 +86,7 @@ pub use overlay::Overlay;
pub use program::Program; pub use program::Program;
pub use renderer::Renderer; pub use renderer::Renderer;
pub use runtime::Runtime; pub use runtime::Runtime;
pub use shell::Shell;
pub use subscription::Subscription; pub use subscription::Subscription;
pub use user_interface::{Cache, UserInterface}; pub use user_interface::{Cache, UserInterface};
pub use widget::Widget; pub use widget::Widget;

View file

@ -10,7 +10,7 @@ use crate::event::{self, Event};
use crate::layout; use crate::layout;
use crate::mouse; use crate::mouse;
use crate::renderer; use crate::renderer;
use crate::{Clipboard, Hasher, Layout, Point, Rectangle, Size}; use crate::{Clipboard, Hasher, Layout, Point, Rectangle, Shell, Size};
/// An interactive component that can be displayed on top of other widgets. /// An interactive component that can be displayed on top of other widgets.
pub trait Overlay<Message, Renderer> pub trait Overlay<Message, Renderer>
@ -71,7 +71,7 @@ where
_cursor_position: Point, _cursor_position: Point,
_renderer: &Renderer, _renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
_messages: &mut Vec<Message>, _shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
event::Status::Ignored event::Status::Ignored
} }

View file

@ -4,7 +4,7 @@ use crate::event::{self, Event};
use crate::layout; use crate::layout;
use crate::mouse; use crate::mouse;
use crate::renderer; use crate::renderer;
use crate::{Clipboard, Hasher, Layout, Point, Rectangle, Size, Vector}; use crate::{Clipboard, Hasher, Layout, Point, Rectangle, Shell, Size, Vector};
/// A generic [`Overlay`]. /// A generic [`Overlay`].
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
@ -62,7 +62,7 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
self.overlay.on_event( self.overlay.on_event(
event, event,
@ -70,7 +70,7 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
messages, shell,
) )
} }
@ -136,9 +136,10 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<B>, shell: &mut Shell<'_, B>,
) -> event::Status { ) -> event::Status {
let mut original_messages = Vec::new(); let mut local_messages = Vec::new();
let mut local_shell = Shell::new(&mut local_messages);
let event_status = self.content.on_event( let event_status = self.content.on_event(
event, event,
@ -146,12 +147,10 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
&mut original_messages, &mut local_shell,
); );
original_messages shell.merge(local_shell, self.mapper);
.drain(..)
.for_each(|message| messages.push((self.mapper)(message)));
event_status event_status
} }

View file

@ -11,7 +11,7 @@ use crate::widget::scrollable::{self, Scrollable};
use crate::widget::Container; use crate::widget::Container;
use crate::{ use crate::{
Clipboard, Color, Element, Hasher, Layout, Length, Padding, Point, Clipboard, Color, Element, Hasher, Layout, Length, Padding, Point,
Rectangle, Size, Vector, Widget, Rectangle, Shell, Size, Vector, Widget,
}; };
pub use iced_style::menu::Style; pub use iced_style::menu::Style;
@ -222,7 +222,7 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
self.container.on_event( self.container.on_event(
event.clone(), event.clone(),
@ -230,7 +230,7 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
messages, shell,
) )
} }
@ -333,7 +333,7 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
_messages: &mut Vec<Message>, _shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
match event { match event {
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => {

54
native/src/shell.rs Normal file
View file

@ -0,0 +1,54 @@
/// A connection to the state of a shell.
///
/// A [`Widget`] can leverage a [`Shell`] to trigger changes in an application,
/// like publishing messages or invalidating the current layout.
///
/// [`Widget`]: crate::Widget
#[derive(Debug)]
pub struct Shell<'a, Message> {
messages: &'a mut Vec<Message>,
is_layout_invalid: bool,
}
impl<'a, Message> Shell<'a, Message> {
/// Creates a new [`Shell`] with the provided buffer of messages.
pub fn new(messages: &'a mut Vec<Message>) -> Self {
Self {
messages,
is_layout_invalid: false,
}
}
/// Triggers the given function if the layout is invalid, cleaning it in the
/// process.
pub fn with_invalid_layout(&mut self, f: impl FnOnce()) {
if self.is_layout_invalid {
self.is_layout_invalid = false;
f()
}
}
/// Publish the given `Message` for an application to process it.
pub fn publish(&mut self, message: Message) {
self.messages.push(message);
}
/// Invalidates the current application layout.
///
/// The shell will relayout the application widgets.
pub fn invalidate_layout(&mut self) {
self.is_layout_invalid = true;
}
/// Merges the current [`Shell`] with another one by applying the given
/// function to the messages of the latter.
///
/// This method is useful for composition.
pub fn merge<B>(&mut self, other: Shell<'_, B>, f: impl Fn(B) -> Message) {
self.messages.extend(other.messages.drain(..).map(f));
self.is_layout_invalid =
self.is_layout_invalid || other.is_layout_invalid;
}
}

View file

@ -3,7 +3,7 @@ use crate::layout;
use crate::mouse; use crate::mouse;
use crate::overlay; use crate::overlay;
use crate::renderer; use crate::renderer;
use crate::{Clipboard, Element, Layout, Point, Rectangle, Size}; use crate::{Clipboard, Element, Layout, Point, Rectangle, Shell, Size};
use std::hash::Hasher; use std::hash::Hasher;
@ -179,7 +179,7 @@ where
/// let event_statuses = user_interface.update( /// let event_statuses = user_interface.update(
/// &events, /// &events,
/// cursor_position, /// cursor_position,
/// &renderer, /// &mut renderer,
/// &mut clipboard, /// &mut clipboard,
/// &mut messages /// &mut messages
/// ); /// );
@ -196,16 +196,18 @@ where
&mut self, &mut self,
events: &[Event], events: &[Event],
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &mut Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, messages: &mut Vec<Message>,
) -> Vec<event::Status> { ) -> Vec<event::Status> {
let (base_cursor, overlay_statuses) = if let Some(mut overlay) = let (base_cursor, overlay_statuses) = if let Some(mut overlay) =
self.root.overlay(Layout::new(&self.base.layout)) self.root.overlay(Layout::new(&self.base.layout))
{ {
let layer = Self::overlay_layer( let bounds = self.bounds;
let mut layer = Self::overlay_layer(
self.overlay.take(), self.overlay.take(),
self.bounds, bounds,
&mut overlay, &mut overlay,
renderer, renderer,
); );
@ -214,14 +216,27 @@ where
.iter() .iter()
.cloned() .cloned()
.map(|event| { .map(|event| {
overlay.on_event( let mut shell = Shell::new(messages);
let event_status = overlay.on_event(
event, event,
Layout::new(&layer.layout), Layout::new(&layer.layout),
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
messages, &mut shell,
) );
shell.with_invalid_layout(|| {
layer = Self::overlay_layer(
None,
bounds,
&mut overlay,
renderer,
);
});
event_status
}) })
.collect(); .collect();
@ -245,15 +260,34 @@ where
.cloned() .cloned()
.zip(overlay_statuses.into_iter()) .zip(overlay_statuses.into_iter())
.map(|(event, overlay_status)| { .map(|(event, overlay_status)| {
let mut shell = Shell::new(messages);
let event_status = self.root.widget.on_event( let event_status = self.root.widget.on_event(
event, event,
Layout::new(&self.base.layout), Layout::new(&self.base.layout),
base_cursor, base_cursor,
renderer, renderer,
clipboard, clipboard,
messages, &mut shell,
); );
shell.with_invalid_layout(|| {
let hash = {
let hasher = &mut crate::Hasher::default();
self.root.hash_layout(hasher);
hasher.finish()
};
let layout = renderer.layout(
&self.root,
&layout::Limits::new(Size::ZERO, self.bounds),
);
self.base = Layer { layout, hash };
self.overlay = None;
});
event_status.merge(overlay_status) event_status.merge(overlay_status)
}) })
.collect() .collect()
@ -313,7 +347,7 @@ where
/// let event_statuses = user_interface.update( /// let event_statuses = user_interface.update(
/// &events, /// &events,
/// cursor_position, /// cursor_position,
/// &renderer, /// &mut renderer,
/// &mut clipboard, /// &mut clipboard,
/// &mut messages /// &mut messages
/// ); /// );

View file

@ -75,7 +75,7 @@ use crate::layout;
use crate::mouse; use crate::mouse;
use crate::overlay; use crate::overlay;
use crate::renderer; use crate::renderer;
use crate::{Clipboard, Hasher, Layout, Length, Point, Rectangle}; use crate::{Clipboard, Hasher, Layout, Length, Point, Rectangle, Shell};
/// A component that displays information and allows interaction. /// A component that displays information and allows interaction.
/// ///
@ -163,7 +163,7 @@ where
_cursor_position: Point, _cursor_position: Point,
_renderer: &Renderer, _renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
_messages: &mut Vec<Message>, _shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
event::Status::Ignored event::Status::Ignored
} }

View file

@ -9,7 +9,7 @@ use crate::renderer;
use crate::touch; use crate::touch;
use crate::{ use crate::{
Background, Clipboard, Color, Element, Hasher, Layout, Length, Padding, Background, Clipboard, Color, Element, Hasher, Layout, Length, Padding,
Point, Rectangle, Vector, Widget, Point, Rectangle, Shell, Vector, Widget,
}; };
use std::hash::Hash; use std::hash::Hash;
@ -197,7 +197,7 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
if let event::Status::Captured = self.content.on_event( if let event::Status::Captured = self.content.on_event(
event.clone(), event.clone(),
@ -205,7 +205,7 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
messages, shell,
) { ) {
return event::Status::Captured; return event::Status::Captured;
} }
@ -232,7 +232,7 @@ where
self.state.is_pressed = false; self.state.is_pressed = false;
if bounds.contains(cursor_position) { if bounds.contains(cursor_position) {
messages.push(on_press); shell.publish(on_press);
} }
return event::Status::Captured; return event::Status::Captured;

View file

@ -11,7 +11,7 @@ use crate::touch;
use crate::widget::{self, Row, Text}; use crate::widget::{self, Row, Text};
use crate::{ use crate::{
Alignment, Clipboard, Color, Element, Hasher, Layout, Length, Point, Alignment, Clipboard, Color, Element, Hasher, Layout, Length, Point,
Rectangle, Widget, Rectangle, Shell, Widget,
}; };
pub use iced_style::checkbox::{Style, StyleSheet}; pub use iced_style::checkbox::{Style, StyleSheet};
@ -171,7 +171,7 @@ where
cursor_position: Point, cursor_position: Point,
_renderer: &Renderer, _renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
match event { match event {
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
@ -179,7 +179,7 @@ where
let mouse_over = layout.bounds().contains(cursor_position); let mouse_over = layout.bounds().contains(cursor_position);
if mouse_over { if mouse_over {
messages.push((self.on_toggle)(!self.is_checked)); shell.publish((self.on_toggle)(!self.is_checked));
return event::Status::Captured; return event::Status::Captured;
} }

View file

@ -8,7 +8,7 @@ use crate::overlay;
use crate::renderer; use crate::renderer;
use crate::{ use crate::{
Alignment, Clipboard, Element, Hasher, Layout, Length, Padding, Point, Alignment, Clipboard, Element, Hasher, Layout, Length, Padding, Point,
Rectangle, Widget, Rectangle, Shell, Widget,
}; };
use std::u32; use std::u32;
@ -146,7 +146,7 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
self.children self.children
.iter_mut() .iter_mut()
@ -158,7 +158,7 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
messages, shell,
) )
}) })
.fold(event::Status::Ignored, event::Status::merge) .fold(event::Status::Ignored, event::Status::merge)

View file

@ -9,7 +9,7 @@ use crate::overlay;
use crate::renderer; use crate::renderer;
use crate::{ use crate::{
Background, Clipboard, Color, Element, Hasher, Layout, Length, Padding, Background, Clipboard, Color, Element, Hasher, Layout, Length, Padding,
Point, Rectangle, Widget, Point, Rectangle, Shell, Widget,
}; };
use std::u32; use std::u32;
@ -167,7 +167,7 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
self.content.widget.on_event( self.content.widget.on_event(
event, event,
@ -175,7 +175,7 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
messages, shell,
) )
} }

View file

@ -5,8 +5,8 @@ use crate::layout;
use crate::mouse; use crate::mouse;
use crate::renderer; use crate::renderer;
use crate::{ use crate::{
Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Size, Vector, Clipboard, Element, Hasher, Layout, Length, Point, Rectangle, Shell, Size,
Widget, Vector, Widget,
}; };
use std::hash::Hash; use std::hash::Hash;
@ -169,7 +169,7 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
_messages: &mut Vec<Message>, _shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
let bounds = layout.bounds(); let bounds = layout.bounds();
let is_mouse_over = bounds.contains(cursor_position); let is_mouse_over = bounds.contains(cursor_position);

View file

@ -34,8 +34,8 @@ use crate::overlay;
use crate::renderer; use crate::renderer;
use crate::touch; use crate::touch;
use crate::{ use crate::{
Clipboard, Color, Element, Hasher, Layout, Length, Point, Rectangle, Size, Clipboard, Color, Element, Hasher, Layout, Length, Point, Rectangle, Shell,
Vector, Widget, Size, Vector, Widget,
}; };
pub use iced_style::pane_grid::{Line, StyleSheet}; pub use iced_style::pane_grid::{Line, StyleSheet};
@ -205,7 +205,7 @@ where
&mut self, &mut self,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor_position: Point,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) { ) {
let mut clicked_region = let mut clicked_region =
self.elements.iter().zip(layout.children()).filter( self.elements.iter().zip(layout.children()).filter(
@ -214,7 +214,7 @@ where
if let Some(((pane, content), layout)) = clicked_region.next() { if let Some(((pane, content), layout)) = clicked_region.next() {
if let Some(on_click) = &self.on_click { if let Some(on_click) = &self.on_click {
messages.push(on_click(*pane)); shell.publish(on_click(*pane));
} }
if let Some(on_drag) = &self.on_drag { if let Some(on_drag) = &self.on_drag {
@ -226,7 +226,7 @@ where
self.state.pick_pane(pane, origin); self.state.pick_pane(pane, origin);
messages.push(on_drag(DragEvent::Picked { pane: *pane })); shell.publish(on_drag(DragEvent::Picked { pane: *pane }));
} }
} }
} }
@ -236,7 +236,7 @@ where
&mut self, &mut self,
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor_position: Point,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
if let Some((_, on_resize)) = &self.on_resize { if let Some((_, on_resize)) = &self.on_resize {
if let Some((split, _)) = self.state.picked_split() { if let Some((split, _)) = self.state.picked_split() {
@ -263,7 +263,7 @@ where
} }
}; };
messages.push(on_resize(ResizeEvent { split, ratio })); shell.publish(on_resize(ResizeEvent { split, ratio }));
return event::Status::Captured; return event::Status::Captured;
} }
@ -362,7 +362,7 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
let mut event_status = event::Status::Ignored; let mut event_status = event::Status::Ignored;
@ -395,15 +395,11 @@ where
if let Some((split, axis, _)) = clicked_split { if let Some((split, axis, _)) = clicked_split {
self.state.pick_split(&split, axis); self.state.pick_split(&split, axis);
} else { } else {
self.click_pane( self.click_pane(layout, cursor_position, shell);
layout,
cursor_position,
messages,
);
} }
} }
None => { None => {
self.click_pane(layout, cursor_position, messages); self.click_pane(layout, cursor_position, shell);
} }
} }
} }
@ -430,7 +426,7 @@ where
_ => DragEvent::Canceled { pane }, _ => DragEvent::Canceled { pane },
}; };
messages.push(on_drag(event)); shell.publish(on_drag(event));
} }
self.state.idle(); self.state.idle();
@ -445,7 +441,7 @@ where
Event::Mouse(mouse::Event::CursorMoved { .. }) Event::Mouse(mouse::Event::CursorMoved { .. })
| Event::Touch(touch::Event::FingerMoved { .. }) => { | Event::Touch(touch::Event::FingerMoved { .. }) => {
event_status = event_status =
self.trigger_resize(layout, cursor_position, messages); self.trigger_resize(layout, cursor_position, shell);
} }
_ => {} _ => {}
} }
@ -464,7 +460,7 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
messages, shell,
is_picked, is_picked,
) )
}) })

View file

@ -5,7 +5,9 @@ use crate::overlay;
use crate::renderer; use crate::renderer;
use crate::widget::container; use crate::widget::container;
use crate::widget::pane_grid::TitleBar; use crate::widget::pane_grid::TitleBar;
use crate::{Clipboard, Element, Hasher, Layout, Point, Rectangle, Size}; use crate::{
Clipboard, Element, Hasher, Layout, Point, Rectangle, Shell, Size,
};
/// The content of a [`Pane`]. /// The content of a [`Pane`].
/// ///
@ -160,7 +162,7 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
is_picked: bool, is_picked: bool,
) -> event::Status { ) -> event::Status {
let mut event_status = event::Status::Ignored; let mut event_status = event::Status::Ignored;
@ -174,7 +176,7 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
messages, shell,
); );
children.next().unwrap() children.next().unwrap()
@ -191,7 +193,7 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
messages, shell,
) )
}; };

View file

@ -5,7 +5,7 @@ use crate::overlay;
use crate::renderer; use crate::renderer;
use crate::widget::container; use crate::widget::container;
use crate::{ use crate::{
Clipboard, Element, Hasher, Layout, Padding, Point, Rectangle, Size, Clipboard, Element, Hasher, Layout, Padding, Point, Rectangle, Shell, Size,
}; };
/// The title bar of a [`Pane`]. /// The title bar of a [`Pane`].
@ -218,7 +218,7 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
let mut children = layout.children(); let mut children = layout.children();
let padded = children.next().unwrap(); let padded = children.next().unwrap();
@ -235,7 +235,7 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
messages, shell,
) )
} else { } else {
event::Status::Ignored event::Status::Ignored
@ -247,7 +247,7 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
messages, shell,
); );
control_status.merge(title_status) control_status.merge(title_status)

View file

@ -11,7 +11,7 @@ use crate::text::{self, Text};
use crate::touch; use crate::touch;
use crate::{ use crate::{
Clipboard, Element, Hasher, Layout, Length, Padding, Point, Rectangle, Clipboard, Element, Hasher, Layout, Length, Padding, Point, Rectangle,
Size, Widget, Shell, Size, Widget,
}; };
use std::borrow::Cow; use std::borrow::Cow;
@ -245,7 +245,7 @@ where
cursor_position: Point, cursor_position: Point,
_renderer: &Renderer, _renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
match event { match event {
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
@ -271,7 +271,7 @@ where
}; };
if let Some(last_selection) = self.last_selection.take() { if let Some(last_selection) = self.last_selection.take() {
messages.push((self.on_selected)(last_selection)); shell.publish((self.on_selected)(last_selection));
*self.is_open = false; *self.is_open = false;
@ -312,7 +312,7 @@ where
}; };
if let Some(next_option) = next_option { if let Some(next_option) = next_option {
messages.push((self.on_selected)(next_option.clone())); shell.publish((self.on_selected)(next_option.clone()));
} }
event::Status::Captured event::Status::Captured

View file

@ -11,7 +11,7 @@ use crate::touch;
use crate::widget::{self, Row, Text}; use crate::widget::{self, Row, Text};
use crate::{ use crate::{
Alignment, Clipboard, Color, Element, Hasher, Layout, Length, Point, Alignment, Clipboard, Color, Element, Hasher, Layout, Length, Point,
Rectangle, Widget, Rectangle, Shell, Widget,
}; };
pub use iced_style::radio::{Style, StyleSheet}; pub use iced_style::radio::{Style, StyleSheet};
@ -187,13 +187,13 @@ where
cursor_position: Point, cursor_position: Point,
_renderer: &Renderer, _renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
match event { match event {
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
| Event::Touch(touch::Event::FingerPressed { .. }) => { | Event::Touch(touch::Event::FingerPressed { .. }) => {
if layout.bounds().contains(cursor_position) { if layout.bounds().contains(cursor_position) {
messages.push(self.on_click.clone()); shell.publish(self.on_click.clone());
return event::Status::Captured; return event::Status::Captured;
} }

View file

@ -6,7 +6,7 @@ use crate::overlay;
use crate::renderer; use crate::renderer;
use crate::{ use crate::{
Alignment, Clipboard, Element, Hasher, Layout, Length, Padding, Point, Alignment, Clipboard, Element, Hasher, Layout, Length, Padding, Point,
Rectangle, Widget, Rectangle, Shell, Widget,
}; };
use std::hash::Hash; use std::hash::Hash;
@ -145,7 +145,7 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
self.children self.children
.iter_mut() .iter_mut()
@ -157,7 +157,7 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
messages, shell,
) )
}) })
.fold(event::Status::Ignored, event::Status::merge) .fold(event::Status::Ignored, event::Status::merge)

View file

@ -8,7 +8,7 @@ use crate::touch;
use crate::widget::Column; use crate::widget::Column;
use crate::{ use crate::{
Alignment, Background, Clipboard, Color, Element, Hasher, Layout, Length, Alignment, Background, Clipboard, Color, Element, Hasher, Layout, Length,
Padding, Point, Rectangle, Size, Vector, Widget, Padding, Point, Rectangle, Shell, Size, Vector, Widget,
}; };
use std::{f32, hash::Hash, u32}; use std::{f32, hash::Hash, u32};
@ -144,14 +144,14 @@ impl<'a, Message, Renderer: crate::Renderer> Scrollable<'a, Message, Renderer> {
&self, &self,
bounds: Rectangle, bounds: Rectangle,
content_bounds: Rectangle, content_bounds: Rectangle,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) { ) {
if content_bounds.height <= bounds.height { if content_bounds.height <= bounds.height {
return; return;
} }
if let Some(on_scroll) = &self.on_scroll { if let Some(on_scroll) = &self.on_scroll {
messages.push(on_scroll( shell.publish(on_scroll(
self.state.offset.absolute(bounds, content_bounds) self.state.offset.absolute(bounds, content_bounds)
/ (content_bounds.height - bounds.height), / (content_bounds.height - bounds.height),
)); ));
@ -251,7 +251,7 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
let bounds = layout.bounds(); let bounds = layout.bounds();
let is_mouse_over = bounds.contains(cursor_position); let is_mouse_over = bounds.contains(cursor_position);
@ -286,7 +286,7 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
messages, shell,
) )
}; };
@ -307,7 +307,7 @@ where
} }
} }
self.notify_on_scroll(bounds, content_bounds, messages); self.notify_on_scroll(bounds, content_bounds, shell);
return event::Status::Captured; return event::Status::Captured;
} }
@ -336,7 +336,7 @@ where
self.notify_on_scroll( self.notify_on_scroll(
bounds, bounds,
content_bounds, content_bounds,
messages, shell,
); );
} }
} }
@ -377,7 +377,7 @@ where
content_bounds, content_bounds,
); );
self.notify_on_scroll(bounds, content_bounds, messages); self.notify_on_scroll(bounds, content_bounds, shell);
return event::Status::Captured; return event::Status::Captured;
} }
@ -409,7 +409,7 @@ where
self.notify_on_scroll( self.notify_on_scroll(
bounds, bounds,
content_bounds, content_bounds,
messages, shell,
); );
return event::Status::Captured; return event::Status::Captured;

View file

@ -8,7 +8,7 @@ use crate::renderer;
use crate::touch; use crate::touch;
use crate::{ use crate::{
Background, Clipboard, Color, Element, Hasher, Layout, Length, Point, Background, Clipboard, Color, Element, Hasher, Layout, Length, Point,
Rectangle, Size, Widget, Rectangle, Shell, Size, Widget,
}; };
use std::hash::Hash; use std::hash::Hash;
@ -191,7 +191,7 @@ where
cursor_position: Point, cursor_position: Point,
_renderer: &Renderer, _renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
let is_dragging = self.state.is_dragging; let is_dragging = self.state.is_dragging;
@ -220,7 +220,7 @@ where
}; };
if (self.value.into() - new_value.into()).abs() > f64::EPSILON { if (self.value.into() - new_value.into()).abs() > f64::EPSILON {
messages.push((self.on_change)(new_value)); shell.publish((self.on_change)(new_value));
self.value = new_value; self.value = new_value;
} }
@ -241,7 +241,7 @@ where
| Event::Touch(touch::Event::FingerLost { .. }) => { | Event::Touch(touch::Event::FingerLost { .. }) => {
if is_dragging { if is_dragging {
if let Some(on_release) = self.on_release.clone() { if let Some(on_release) = self.on_release.clone() {
messages.push(on_release); shell.publish(on_release);
} }
self.state.is_dragging = false; self.state.is_dragging = false;

View file

@ -21,7 +21,7 @@ use crate::text::{self, Text};
use crate::touch; use crate::touch;
use crate::{ use crate::{
Clipboard, Color, Element, Hasher, Layout, Length, Padding, Point, Clipboard, Color, Element, Hasher, Layout, Length, Padding, Point,
Rectangle, Size, Vector, Widget, Rectangle, Shell, Size, Vector, Widget,
}; };
use std::u32; use std::u32;
@ -384,7 +384,7 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
match event { match event {
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
@ -509,7 +509,7 @@ where
editor.insert(c); editor.insert(c);
let message = (self.on_change)(editor.contents()); let message = (self.on_change)(editor.contents());
messages.push(message); shell.publish(message);
return event::Status::Captured; return event::Status::Captured;
} }
@ -521,7 +521,7 @@ where
match key_code { match key_code {
keyboard::KeyCode::Enter => { keyboard::KeyCode::Enter => {
if let Some(on_submit) = self.on_submit.clone() { if let Some(on_submit) = self.on_submit.clone() {
messages.push(on_submit); shell.publish(on_submit);
} }
} }
keyboard::KeyCode::Backspace => { keyboard::KeyCode::Backspace => {
@ -551,7 +551,7 @@ where
editor.backspace(); editor.backspace();
let message = (self.on_change)(editor.contents()); let message = (self.on_change)(editor.contents());
messages.push(message); shell.publish(message);
} }
keyboard::KeyCode::Delete => { keyboard::KeyCode::Delete => {
if platform::is_jump_modifier_pressed(modifiers) if platform::is_jump_modifier_pressed(modifiers)
@ -582,7 +582,7 @@ where
editor.delete(); editor.delete();
let message = (self.on_change)(editor.contents()); let message = (self.on_change)(editor.contents());
messages.push(message); shell.publish(message);
} }
keyboard::KeyCode::Left => { keyboard::KeyCode::Left => {
if platform::is_jump_modifier_pressed(modifiers) if platform::is_jump_modifier_pressed(modifiers)
@ -674,7 +674,7 @@ where
editor.delete(); editor.delete();
let message = (self.on_change)(editor.contents()); let message = (self.on_change)(editor.contents());
messages.push(message); shell.publish(message);
} }
keyboard::KeyCode::V => { keyboard::KeyCode::V => {
if self.state.keyboard_modifiers.command() { if self.state.keyboard_modifiers.command() {
@ -700,7 +700,7 @@ where
editor.paste(content.clone()); editor.paste(content.clone());
let message = (self.on_change)(editor.contents()); let message = (self.on_change)(editor.contents());
messages.push(message); shell.publish(message);
self.state.is_pasting = Some(content); self.state.is_pasting = Some(content);
} else { } else {

View file

@ -10,7 +10,7 @@ use crate::text;
use crate::widget::{Row, Text}; use crate::widget::{Row, Text};
use crate::{ use crate::{
Alignment, Clipboard, Element, Event, Hasher, Layout, Length, Point, Alignment, Clipboard, Element, Event, Hasher, Layout, Length, Point,
Rectangle, Widget, Rectangle, Shell, Widget,
}; };
pub use iced_style::toggler::{Style, StyleSheet}; pub use iced_style::toggler::{Style, StyleSheet};
@ -173,14 +173,14 @@ where
cursor_position: Point, cursor_position: Point,
_renderer: &Renderer, _renderer: &Renderer,
_clipboard: &mut dyn Clipboard, _clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
match event { match event {
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => {
let mouse_over = layout.bounds().contains(cursor_position); let mouse_over = layout.bounds().contains(cursor_position);
if mouse_over { if mouse_over {
messages.push((self.on_toggle)(!self.is_active)); shell.publish((self.on_toggle)(!self.is_active));
event::Status::Captured event::Status::Captured
} else { } else {

View file

@ -11,8 +11,8 @@ use crate::text;
use crate::widget::container; use crate::widget::container;
use crate::widget::text::Text; use crate::widget::text::Text;
use crate::{ use crate::{
Clipboard, Element, Event, Hasher, Layout, Length, Padding, Point, Size, Clipboard, Element, Event, Hasher, Layout, Length, Padding, Point, Shell,
Vector, Widget, Size, Vector, Widget,
}; };
/// An element to display a widget over another. /// An element to display a widget over another.
@ -130,7 +130,7 @@ where
cursor_position: Point, cursor_position: Point,
renderer: &Renderer, renderer: &Renderer,
clipboard: &mut dyn Clipboard, clipboard: &mut dyn Clipboard,
messages: &mut Vec<Message>, shell: &mut Shell<'_, Message>,
) -> event::Status { ) -> event::Status {
self.content.widget.on_event( self.content.widget.on_event(
event, event,
@ -138,7 +138,7 @@ where
cursor_position, cursor_position,
renderer, renderer,
clipboard, clipboard,
messages, shell,
) )
} }