Use nested for lazy widgets

This commit is contained in:
Cory Forsstrom 2023-02-19 17:43:13 -08:00 committed by Héctor Ramón Jiménez
parent 4de6ee6fa1
commit b0205e03d8
No known key found for this signature in database
GPG key ID: 140CC052C94F138E
7 changed files with 77 additions and 49 deletions

View file

@ -47,6 +47,7 @@ pub mod clipboard;
pub mod command; pub mod command;
pub mod font; pub mod font;
pub mod keyboard; pub mod keyboard;
pub mod overlay;
pub mod program; pub mod program;
pub mod system; pub mod system;
pub mod user_interface; pub mod user_interface;

4
runtime/src/overlay.rs Normal file
View file

@ -0,0 +1,4 @@
//! Overlays for user interfaces.
mod nested;
pub use nested::Nested;

View file

@ -21,6 +21,12 @@ where
Self { overlay: element } Self { overlay: element }
} }
/// Returns the position of the [`Nested`] overlay.
pub fn position(&self) -> Point {
self.overlay.position()
}
/// Returns the layout [`Node`] of the [`Nested`] overlay.
pub fn layout( pub fn layout(
&mut self, &mut self,
renderer: &Renderer, renderer: &Renderer,
@ -36,7 +42,7 @@ where
where where
Renderer: renderer::Renderer, Renderer: renderer::Renderer,
{ {
let translation = position - Point::ORIGIN; let translation = position - element.position();
let node = element.layout(renderer, bounds, translation); let node = element.layout(renderer, bounds, translation);
@ -58,6 +64,7 @@ where
recurse(&mut self.overlay, renderer, bounds, position) recurse(&mut self.overlay, renderer, bounds, position)
} }
/// Draws the [`Nested`] overlay using the associated `Renderer`.
pub fn draw( pub fn draw(
&mut self, &mut self,
renderer: &mut Renderer, renderer: &mut Renderer,
@ -127,6 +134,7 @@ where
recurse(&mut self.overlay, layout, renderer, theme, style, cursor); recurse(&mut self.overlay, layout, renderer, theme, style, cursor);
} }
/// Applies a [`widget::Operation`] to the [`Nested`] overlay.
pub fn operate( pub fn operate(
&mut self, &mut self,
layout: Layout<'_>, layout: Layout<'_>,
@ -157,6 +165,7 @@ where
recurse(&mut self.overlay, layout, renderer, operation) recurse(&mut self.overlay, layout, renderer, operation)
} }
/// Processes a runtime [`Event`].
pub fn on_event( pub fn on_event(
&mut self, &mut self,
event: Event, event: Event,
@ -247,6 +256,7 @@ where
status status
} }
/// Returns the current [`mouse::Interaction`] of the [`Nested`] overlay.
pub fn mouse_interaction( pub fn mouse_interaction(
&mut self, &mut self,
layout: Layout<'_>, layout: Layout<'_>,
@ -298,6 +308,7 @@ where
.unwrap_or_default() .unwrap_or_default()
} }
/// Returns true if the cursor is over the [`Nested`] overlay.
pub fn is_over( pub fn is_over(
&mut self, &mut self,
layout: Layout<'_>, layout: Layout<'_>,

View file

@ -1,14 +1,12 @@
//! Implement your own event loop to drive a user interface. //! Implement your own event loop to drive a user interface.
mod overlay;
use crate::core::event::{self, Event}; use crate::core::event::{self, Event};
use crate::core::layout; use crate::core::layout;
use crate::core::mouse; use crate::core::mouse;
use crate::core::renderer; use crate::core::renderer;
use crate::core::widget; use crate::core::widget;
use crate::core::window; use crate::core::window;
use crate::core::{Clipboard, Point, Rectangle, Size}; use crate::core::{Clipboard, Element, Layout, Point, Rectangle, Shell, Size};
use crate::core::{Element, Layout, Shell}; use crate::overlay;
/// A set of interactive graphical elements with a specific [`Layout`]. /// A set of interactive graphical elements with a specific [`Layout`].
/// ///

View file

@ -20,6 +20,7 @@ use crate::core::Element;
use crate::core::{ use crate::core::{
self, Clipboard, Hasher, Length, Point, Rectangle, Shell, Size, self, Clipboard, Hasher, Length, Point, Rectangle, Shell, Size,
}; };
use crate::runtime::overlay::Nested;
use ouroboros::self_referencing; use ouroboros::self_referencing;
use std::cell::RefCell; use std::cell::RefCell;
@ -260,14 +261,17 @@ where
.unwrap(), .unwrap(),
tree: &mut tree.children[0], tree: &mut tree.children[0],
overlay_builder: |element, tree| { overlay_builder: |element, tree| {
element.as_widget_mut().overlay(tree, layout, renderer) element
.as_widget_mut()
.overlay(tree, layout, renderer)
.map(|overlay| RefCell::new(Nested::new(overlay)))
}, },
} }
.build(), .build(),
)); ));
let has_overlay = overlay let has_overlay =
.with_overlay_maybe(|overlay| overlay::Element::position(overlay)); overlay.with_overlay_maybe(|overlay| overlay.position());
has_overlay has_overlay
.map(|position| overlay::Element::new(position, Box::new(overlay))) .map(|position| overlay::Element::new(position, Box::new(overlay)))
@ -285,8 +289,8 @@ where
tree: &'a mut Tree, tree: &'a mut Tree,
#[borrows(mut element, mut tree)] #[borrows(mut element, mut tree)]
#[covariant] #[not_covariant]
overlay: Option<overlay::Element<'this, Message, Renderer>>, overlay: Option<RefCell<Nested<'this, Message, Renderer>>>,
} }
struct Overlay<'a, Message, Renderer>(Option<Inner<'a, Message, Renderer>>); struct Overlay<'a, Message, Renderer>(Option<Inner<'a, Message, Renderer>>);
@ -301,19 +305,20 @@ impl<'a, Message, Renderer> Drop for Overlay<'a, Message, Renderer> {
impl<'a, Message, Renderer> Overlay<'a, Message, Renderer> { impl<'a, Message, Renderer> Overlay<'a, Message, Renderer> {
fn with_overlay_maybe<T>( fn with_overlay_maybe<T>(
&self, &self,
f: impl FnOnce(&overlay::Element<'_, Message, Renderer>) -> T, f: impl FnOnce(&mut Nested<'_, Message, Renderer>) -> T,
) -> Option<T> { ) -> Option<T> {
self.0.as_ref().unwrap().borrow_overlay().as_ref().map(f) self.0.as_ref().unwrap().with_overlay(|overlay| {
overlay.as_ref().map(|nested| (f)(&mut nested.borrow_mut()))
})
} }
fn with_overlay_mut_maybe<T>( fn with_overlay_mut_maybe<T>(
&mut self, &mut self,
f: impl FnOnce(&mut overlay::Element<'_, Message, Renderer>) -> T, f: impl FnOnce(&mut Nested<'_, Message, Renderer>) -> T,
) -> Option<T> { ) -> Option<T> {
self.0 self.0.as_mut().unwrap().with_overlay_mut(|overlay| {
.as_mut() overlay.as_mut().map(|nested| (f)(nested.get_mut()))
.unwrap() })
.with_overlay_mut(|overlay| overlay.as_mut().map(f))
} }
} }
@ -329,9 +334,7 @@ where
position: Point, position: Point,
) -> layout::Node { ) -> layout::Node {
self.with_overlay_maybe(|overlay| { self.with_overlay_maybe(|overlay| {
let translation = position - overlay.position(); overlay.layout(renderer, bounds, position)
overlay.layout(renderer, bounds, translation)
}) })
.unwrap_or_default() .unwrap_or_default()
} }

View file

@ -9,6 +9,7 @@ use crate::core::widget::tree::{self, Tree};
use crate::core::{ use crate::core::{
self, Clipboard, Element, Length, Point, Rectangle, Shell, Size, Widget, self, Clipboard, Element, Length, Point, Rectangle, Shell, Size, Widget,
}; };
use crate::runtime::overlay::Nested;
use ouroboros::self_referencing; use ouroboros::self_referencing;
use std::cell::RefCell; use std::cell::RefCell;
@ -455,11 +456,18 @@ where
overlay_builder: |instance, tree| { overlay_builder: |instance, tree| {
instance.state.get_mut().as_mut().unwrap().with_element_mut( instance.state.get_mut().as_mut().unwrap().with_element_mut(
move |element| { move |element| {
element.as_mut().unwrap().as_widget_mut().overlay( element
&mut tree.children[0], .as_mut()
layout, .unwrap()
renderer, .as_widget_mut()
) .overlay(
&mut tree.children[0],
layout,
renderer,
)
.map(|overlay| {
RefCell::new(Nested::new(overlay))
})
}, },
) )
}, },
@ -468,7 +476,7 @@ where
)); ));
let has_overlay = overlay.0.as_ref().unwrap().with_overlay(|overlay| { let has_overlay = overlay.0.as_ref().unwrap().with_overlay(|overlay| {
overlay.as_ref().map(overlay::Element::position) overlay.as_ref().map(|nested| nested.borrow().position())
}); });
has_overlay.map(|position| { has_overlay.map(|position| {
@ -503,8 +511,8 @@ struct Inner<'a, 'b, Message, Renderer, Event, S> {
types: PhantomData<(Message, Event, S)>, types: PhantomData<(Message, Event, S)>,
#[borrows(mut instance, mut tree)] #[borrows(mut instance, mut tree)]
#[covariant] #[not_covariant]
overlay: Option<overlay::Element<'this, Event, Renderer>>, overlay: Option<RefCell<Nested<'this, Event, Renderer>>>,
} }
struct OverlayInstance<'a, 'b, Message, Renderer, Event, S> { struct OverlayInstance<'a, 'b, Message, Renderer, Event, S> {
@ -516,7 +524,7 @@ impl<'a, 'b, Message, Renderer, Event, S>
{ {
fn with_overlay_maybe<T>( fn with_overlay_maybe<T>(
&self, &self,
f: impl FnOnce(&overlay::Element<'_, Event, Renderer>) -> T, f: impl FnOnce(&mut Nested<'_, Event, Renderer>) -> T,
) -> Option<T> { ) -> Option<T> {
self.overlay self.overlay
.as_ref() .as_ref()
@ -524,14 +532,14 @@ impl<'a, 'b, Message, Renderer, Event, S>
.0 .0
.as_ref() .as_ref()
.unwrap() .unwrap()
.borrow_overlay() .with_overlay(|overlay| {
.as_ref() overlay.as_ref().map(|nested| (f)(&mut nested.borrow_mut()))
.map(f) })
} }
fn with_overlay_mut_maybe<T>( fn with_overlay_mut_maybe<T>(
&mut self, &mut self,
f: impl FnOnce(&mut overlay::Element<'_, Event, Renderer>) -> T, f: impl FnOnce(&mut Nested<'_, Event, Renderer>) -> T,
) -> Option<T> { ) -> Option<T> {
self.overlay self.overlay
.as_mut() .as_mut()
@ -539,7 +547,9 @@ impl<'a, 'b, Message, Renderer, Event, S>
.0 .0
.as_mut() .as_mut()
.unwrap() .unwrap()
.with_overlay_mut(|overlay| overlay.as_mut().map(f)) .with_overlay_mut(|overlay| {
overlay.as_mut().map(|nested| (f)(nested.get_mut()))
})
} }
} }
@ -556,9 +566,7 @@ where
position: Point, position: Point,
) -> layout::Node { ) -> layout::Node {
self.with_overlay_maybe(|overlay| { self.with_overlay_maybe(|overlay| {
let translation = position - overlay.position(); overlay.layout(renderer, bounds, position)
overlay.layout(renderer, bounds, translation)
}) })
.unwrap_or_default() .unwrap_or_default()
} }

View file

@ -9,6 +9,7 @@ use crate::core::{
self, Clipboard, Element, Length, Point, Rectangle, Shell, Size, Widget, self, Clipboard, Element, Length, Point, Rectangle, Shell, Size, Widget,
}; };
use crate::horizontal_space; use crate::horizontal_space;
use crate::runtime::overlay::Nested;
use ouroboros::self_referencing; use ouroboros::self_referencing;
use std::cell::{RefCell, RefMut}; use std::cell::{RefCell, RefMut};
@ -298,13 +299,13 @@ where
element element
.as_widget_mut() .as_widget_mut()
.overlay(tree, content_layout, renderer) .overlay(tree, content_layout, renderer)
.map(|overlay| RefCell::new(Nested::new(overlay)))
}, },
} }
.build(); .build();
let has_overlay = overlay.with_overlay(|overlay| { let has_overlay =
overlay.as_ref().map(overlay::Element::position) overlay.with_overlay_maybe(|overlay| overlay.position());
});
has_overlay has_overlay
.map(|position| overlay::Element::new(position, Box::new(overlay))) .map(|position| overlay::Element::new(position, Box::new(overlay)))
@ -329,23 +330,27 @@ struct Overlay<'a, 'b, Message, Renderer> {
types: PhantomData<Message>, types: PhantomData<Message>,
#[borrows(mut content, mut tree)] #[borrows(mut content, mut tree)]
#[covariant] #[not_covariant]
overlay: Option<overlay::Element<'this, Message, Renderer>>, overlay: Option<RefCell<Nested<'this, Message, Renderer>>>,
} }
impl<'a, 'b, Message, Renderer> Overlay<'a, 'b, Message, Renderer> { impl<'a, 'b, Message, Renderer> Overlay<'a, 'b, Message, Renderer> {
fn with_overlay_maybe<T>( fn with_overlay_maybe<T>(
&self, &self,
f: impl FnOnce(&overlay::Element<'_, Message, Renderer>) -> T, f: impl FnOnce(&mut Nested<'_, Message, Renderer>) -> T,
) -> Option<T> { ) -> Option<T> {
self.borrow_overlay().as_ref().map(f) self.with_overlay(|overlay| {
overlay.as_ref().map(|nested| (f)(&mut nested.borrow_mut()))
})
} }
fn with_overlay_mut_maybe<T>( fn with_overlay_mut_maybe<T>(
&mut self, &mut self,
f: impl FnOnce(&mut overlay::Element<'_, Message, Renderer>) -> T, f: impl FnOnce(&mut Nested<'_, Message, Renderer>) -> T,
) -> Option<T> { ) -> Option<T> {
self.with_overlay_mut(|overlay| overlay.as_mut().map(f)) self.with_overlay_mut(|overlay| {
overlay.as_mut().map(|nested| (f)(nested.get_mut()))
})
} }
} }
@ -361,9 +366,7 @@ where
position: Point, position: Point,
) -> layout::Node { ) -> layout::Node {
self.with_overlay_maybe(|overlay| { self.with_overlay_maybe(|overlay| {
let translation = position - overlay.position(); overlay.layout(renderer, bounds, position)
overlay.layout(renderer, bounds, translation)
}) })
.unwrap_or_default() .unwrap_or_default()
} }