summaryrefslogtreecommitdiffstats
path: root/core/src/shell.rs
diff options
context:
space:
mode:
authorLibravatar Bingus <shankern@protonmail.com>2023-07-12 12:23:18 -0700
committerLibravatar Bingus <shankern@protonmail.com>2023-07-12 12:23:18 -0700
commit633f405f3f78bc7f82d2b2061491b0e011137451 (patch)
tree5ebfc1f45d216a5c14a90492563599e6969eab4d /core/src/shell.rs
parent41836dd80d0534608e7aedfbf2319c540a23de1a (diff)
parent21bd51426d900e271206f314e0c915dd41065521 (diff)
downloadiced-633f405f3f78bc7f82d2b2061491b0e011137451.tar.gz
iced-633f405f3f78bc7f82d2b2061491b0e011137451.tar.bz2
iced-633f405f3f78bc7f82d2b2061491b0e011137451.zip
Merge remote-tracking branch 'origin/master' into feat/multi-window-support
# Conflicts: # Cargo.toml # core/src/window/icon.rs # core/src/window/id.rs # core/src/window/position.rs # core/src/window/settings.rs # examples/integration/src/main.rs # examples/integration_opengl/src/main.rs # glutin/src/application.rs # native/src/subscription.rs # native/src/window.rs # runtime/src/window/action.rs # src/lib.rs # src/window.rs # winit/Cargo.toml # winit/src/application.rs # winit/src/icon.rs # winit/src/settings.rs # winit/src/window.rs
Diffstat (limited to 'core/src/shell.rs')
-rw-r--r--core/src/shell.rs108
1 files changed, 108 insertions, 0 deletions
diff --git a/core/src/shell.rs b/core/src/shell.rs
new file mode 100644
index 00000000..74a5c616
--- /dev/null
+++ b/core/src/shell.rs
@@ -0,0 +1,108 @@
+use crate::window;
+
+/// 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>,
+ redraw_request: Option<window::RedrawRequest>,
+ is_layout_invalid: bool,
+ are_widgets_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,
+ redraw_request: None,
+ is_layout_invalid: false,
+ are_widgets_invalid: false,
+ }
+ }
+
+ /// Returns true if the [`Shell`] contains no published messages
+ pub fn is_empty(&self) -> bool {
+ self.messages.is_empty()
+ }
+
+ /// Publish the given `Message` for an application to process it.
+ pub fn publish(&mut self, message: Message) {
+ self.messages.push(message);
+ }
+
+ /// Requests a new frame to be drawn at the given [`Instant`].
+ pub fn request_redraw(&mut self, request: window::RedrawRequest) {
+ match self.redraw_request {
+ None => {
+ self.redraw_request = Some(request);
+ }
+ Some(current) if request < current => {
+ self.redraw_request = Some(request);
+ }
+ _ => {}
+ }
+ }
+
+ /// Returns the requested [`Instant`] a redraw should happen, if any.
+ pub fn redraw_request(&self) -> Option<window::RedrawRequest> {
+ self.redraw_request
+ }
+
+ /// Returns whether the current layout is invalid or not.
+ pub fn is_layout_invalid(&self) -> bool {
+ self.is_layout_invalid
+ }
+
+ /// Invalidates the current application layout.
+ ///
+ /// The shell will relayout the application widgets.
+ pub fn invalidate_layout(&mut self) {
+ self.is_layout_invalid = true;
+ }
+
+ /// Triggers the given function if the layout is invalid, cleaning it in the
+ /// process.
+ pub fn revalidate_layout(&mut self, f: impl FnOnce()) {
+ if self.is_layout_invalid {
+ self.is_layout_invalid = false;
+
+ f()
+ }
+ }
+
+ /// Returns whether the widgets of the current application have been
+ /// invalidated.
+ pub fn are_widgets_invalid(&self) -> bool {
+ self.are_widgets_invalid
+ }
+
+ /// Invalidates the current application widgets.
+ ///
+ /// The shell will rebuild and relayout the widget tree.
+ pub fn invalidate_widgets(&mut self) {
+ self.are_widgets_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));
+
+ if let Some(at) = other.redraw_request {
+ self.request_redraw(at);
+ }
+
+ self.is_layout_invalid =
+ self.is_layout_invalid || other.is_layout_invalid;
+
+ self.are_widgets_invalid =
+ self.are_widgets_invalid || other.are_widgets_invalid;
+ }
+}