WrapperWidget, Space

This commit is contained in:
Jonathan Johnson 2023-11-08 19:09:59 -08:00
parent 9596eaac17
commit 8e268615a1
No known key found for this signature in database
GPG key ID: A66D6A34D6620579
10 changed files with 379 additions and 123 deletions

View file

@ -468,7 +468,17 @@ impl<'context, 'window, 'clip, 'gfx, 'pass> GraphicsContext<'context, 'window, '
/// Invokes [`Widget::redraw()`](crate::widget::Widget::redraw) on this /// Invokes [`Widget::redraw()`](crate::widget::Widget::redraw) on this
/// context's widget. /// context's widget.
///
/// # Panics
///
/// This function panics if the widget being drawn has no layout set (via
/// [`LayoutContext::set_child_layout()`]).
pub fn redraw(&mut self) { pub fn redraw(&mut self) {
assert!(
self.last_layout().is_some(),
"redraw called without set_widget_layout"
);
self.current_node self.current_node
.tree .tree
.note_widget_rendered(self.current_node.id()); .note_widget_rendered(self.current_node.id());

View file

@ -264,17 +264,7 @@ impl<T> DynamicData<T> {
let mut changed = true; let mut changed = true;
let result = map(&mut state.wrapped.value, &mut changed); let result = map(&mut state.wrapped.value, &mut changed);
if changed { if changed {
state.wrapped.generation = state.wrapped.generation.next(); state.note_changed();
for callback in &mut state.callbacks {
callback.update(&state.wrapped);
}
for window in state.windows.drain(..) {
window.redraw();
}
for waker in state.wakers.drain(..) {
waker.wake();
}
} }
result result
@ -321,6 +311,22 @@ struct State<T> {
readers: usize, readers: usize,
} }
impl<T> State<T> {
fn note_changed(&mut self) {
self.wrapped.generation = self.wrapped.generation.next();
for callback in &mut self.callbacks {
callback.update(&self.wrapped);
}
for window in self.windows.drain(..) {
window.redraw();
}
for waker in self.wakers.drain(..) {
waker.wake();
}
}
}
impl<T> Debug for State<T> impl<T> Debug for State<T>
where where
T: Debug, T: Debug,
@ -353,6 +359,9 @@ struct GenerationalValue<T> {
} }
/// An exclusive reference to the contents of a [`Dynamic`]. /// An exclusive reference to the contents of a [`Dynamic`].
///
/// If the contents are accessed through [`DerefMut`], all obververs will be
/// notified of a change when this guard is dropped.
#[derive(Debug)] #[derive(Debug)]
pub struct DynamicGuard<'a, T> { pub struct DynamicGuard<'a, T> {
guard: MutexGuard<'a, State<T>>, guard: MutexGuard<'a, State<T>>,
@ -377,7 +386,7 @@ impl<'a, T> DerefMut for DynamicGuard<'a, T> {
impl<T> Drop for DynamicGuard<'_, T> { impl<T> Drop for DynamicGuard<'_, T> {
fn drop(&mut self) { fn drop(&mut self) {
if self.accessed_mut { if self.accessed_mut {
todo!("trigger callbacks") self.guard.note_changed();
} }
} }
} }

View file

@ -12,7 +12,7 @@ use kludgine::app::winit::event::{
DeviceId, Ime, KeyEvent, MouseButton, MouseScrollDelta, TouchPhase, DeviceId, Ime, KeyEvent, MouseButton, MouseScrollDelta, TouchPhase,
}; };
use kludgine::figures::units::{Px, UPx}; use kludgine::figures::units::{Px, UPx};
use kludgine::figures::{Point, Rect, Size}; use kludgine::figures::{IntoSigned, IntoUnsigned, Point, Rect, Size};
use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContext}; use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContext};
use crate::styles::components::VisualOrder; use crate::styles::components::VisualOrder;
@ -167,6 +167,263 @@ where
} }
} }
/// A [`Widget`] that contains a single child.
pub trait WrapperWidget: Debug + Send + UnwindSafe + 'static {
/// Returns the child widget.
fn child(&mut self) -> &mut WidgetRef;
/// Returns the rectangle that the child widget should occupy given
/// `available_space`.
#[allow(unused_variables)]
fn layout_child(
&mut self,
available_space: Size<ConstraintLimit>,
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
) -> Rect<Px> {
let child = self.child().mounted(&mut context.as_event_context());
context
.for_other(&child)
.layout(available_space)
.into_signed()
.into()
}
/// The widget has been mounted into a parent widget.
#[allow(unused_variables)]
fn mounted(&mut self, context: &mut EventContext<'_, '_>) {}
/// The widget has been removed from its parent widget.
#[allow(unused_variables)]
fn unmounted(&mut self, context: &mut EventContext<'_, '_>) {}
/// Returns true if this widget should respond to mouse input at `location`.
#[allow(unused_variables)]
fn hit_test(&mut self, location: Point<Px>, context: &mut EventContext<'_, '_>) -> bool {
false
}
/// The widget is currently has a cursor hovering it at `location`.
#[allow(unused_variables)]
fn hover(&mut self, location: Point<Px>, context: &mut EventContext<'_, '_>) {}
/// The widget is no longer being hovered.
#[allow(unused_variables)]
fn unhover(&mut self, context: &mut EventContext<'_, '_>) {}
/// This widget has been targeted to be focused. If this function returns
/// true, the widget will be focused. If false, Gooey will continue
/// searching for another focus target.
#[allow(unused_variables)]
fn accept_focus(&mut self, context: &mut EventContext<'_, '_>) -> bool {
false
}
/// The widget has received focus for user input.
#[allow(unused_variables)]
fn focus(&mut self, context: &mut EventContext<'_, '_>) {}
/// The widget is no longer focused for user input.
#[allow(unused_variables)]
fn blur(&mut self, context: &mut EventContext<'_, '_>) {}
/// The widget has become the active widget.
#[allow(unused_variables)]
fn activate(&mut self, context: &mut EventContext<'_, '_>) {}
/// The widget is no longer active.
#[allow(unused_variables)]
fn deactivate(&mut self, context: &mut EventContext<'_, '_>) {}
/// A mouse button event has occurred at `location`. Returns whether the
/// event has been handled or not.
///
/// If an event is handled, the widget will receive callbacks for
/// [`mouse_drag`](Self::mouse_drag) and [`mouse_up`](Self::mouse_up).
#[allow(unused_variables)]
fn mouse_down(
&mut self,
location: Point<Px>,
device_id: DeviceId,
button: MouseButton,
context: &mut EventContext<'_, '_>,
) -> EventHandling {
IGNORED
}
/// A mouse button is being held down as the cursor is moved across the
/// widget.
#[allow(unused_variables)]
fn mouse_drag(
&mut self,
location: Point<Px>,
device_id: DeviceId,
button: MouseButton,
context: &mut EventContext<'_, '_>,
) {
}
/// A mouse button is no longer being pressed.
#[allow(unused_variables)]
fn mouse_up(
&mut self,
location: Option<Point<Px>>,
device_id: DeviceId,
button: MouseButton,
context: &mut EventContext<'_, '_>,
) {
}
/// A keyboard event has been sent to this widget. Returns whether the event
/// has been handled or not.
#[allow(unused_variables)]
fn keyboard_input(
&mut self,
device_id: DeviceId,
input: KeyEvent,
is_synthetic: bool,
context: &mut EventContext<'_, '_>,
) -> EventHandling {
IGNORED
}
/// An input manager event has been sent to this widget. Returns whether the
/// event has been handled or not.
#[allow(unused_variables)]
fn ime(&mut self, ime: Ime, context: &mut EventContext<'_, '_>) -> EventHandling {
IGNORED
}
/// A mouse wheel event has been sent to this widget. Returns whether the
/// event has been handled or not.
#[allow(unused_variables)]
fn mouse_wheel(
&mut self,
device_id: DeviceId,
delta: MouseScrollDelta,
phase: TouchPhase,
context: &mut EventContext<'_, '_>,
) -> EventHandling {
IGNORED
}
}
impl<T> Widget for T
where
T: WrapperWidget,
{
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {
let child = self.child().mounted(&mut context.as_event_context());
context.for_other(&child).redraw();
}
fn layout(
&mut self,
available_space: Size<ConstraintLimit>,
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
) -> Size<UPx> {
let child = self.child().mounted(&mut context.as_event_context());
let layout = self.layout_child(available_space, context);
context.set_child_layout(&child, layout);
layout.size.into_unsigned()
}
fn mounted(&mut self, context: &mut EventContext<'_, '_>) {
T::mounted(self, context);
}
fn unmounted(&mut self, context: &mut EventContext<'_, '_>) {
T::unmounted(self, context);
}
fn hit_test(&mut self, location: Point<Px>, context: &mut EventContext<'_, '_>) -> bool {
T::hit_test(self, location, context)
}
fn hover(&mut self, location: Point<Px>, context: &mut EventContext<'_, '_>) {
T::hover(self, location, context);
}
fn unhover(&mut self, context: &mut EventContext<'_, '_>) {
T::unhover(self, context);
}
fn accept_focus(&mut self, context: &mut EventContext<'_, '_>) -> bool {
T::accept_focus(self, context)
}
fn focus(&mut self, context: &mut EventContext<'_, '_>) {
T::focus(self, context);
}
fn blur(&mut self, context: &mut EventContext<'_, '_>) {
T::blur(self, context);
}
fn activate(&mut self, context: &mut EventContext<'_, '_>) {
T::activate(self, context);
}
fn deactivate(&mut self, context: &mut EventContext<'_, '_>) {
T::deactivate(self, context);
}
fn mouse_down(
&mut self,
location: Point<Px>,
device_id: DeviceId,
button: MouseButton,
context: &mut EventContext<'_, '_>,
) -> EventHandling {
T::mouse_down(self, location, device_id, button, context)
}
fn mouse_drag(
&mut self,
location: Point<Px>,
device_id: DeviceId,
button: MouseButton,
context: &mut EventContext<'_, '_>,
) {
T::mouse_drag(self, location, device_id, button, context);
}
fn mouse_up(
&mut self,
location: Option<Point<Px>>,
device_id: DeviceId,
button: MouseButton,
context: &mut EventContext<'_, '_>,
) {
T::mouse_up(self, location, device_id, button, context);
}
fn keyboard_input(
&mut self,
device_id: DeviceId,
input: KeyEvent,
is_synthetic: bool,
context: &mut EventContext<'_, '_>,
) -> EventHandling {
T::keyboard_input(self, device_id, input, is_synthetic, context)
}
fn ime(&mut self, ime: Ime, context: &mut EventContext<'_, '_>) -> EventHandling {
T::ime(self, ime, context)
}
fn mouse_wheel(
&mut self,
device_id: DeviceId,
delta: MouseScrollDelta,
phase: TouchPhase,
context: &mut EventContext<'_, '_>,
) -> EventHandling {
T::mouse_wheel(self, device_id, delta, phase, context)
}
}
/// A type that can create a [`WidgetInstance`]. /// A type that can create a [`WidgetInstance`].
pub trait MakeWidget: Sized { pub trait MakeWidget: Sized {
/// Returns a new widget. /// Returns a new widget.

View file

@ -8,6 +8,7 @@ mod input;
mod label; mod label;
mod resize; mod resize;
pub mod scroll; pub mod scroll;
mod space;
pub mod stack; pub mod stack;
mod style; mod style;
mod tilemap; mod tilemap;
@ -20,6 +21,7 @@ pub use input::Input;
pub use label::Label; pub use label::Label;
pub use resize::Resize; pub use resize::Resize;
pub use scroll::Scroll; pub use scroll::Scroll;
pub use space::Space;
pub use stack::Stack; pub use stack::Stack;
pub use style::Style; pub use style::Style;
pub use tilemap::TileMap; pub use tilemap::TileMap;

View file

@ -3,10 +3,10 @@ use std::fmt::Debug;
use kludgine::figures::units::UPx; use kludgine::figures::units::UPx;
use kludgine::figures::{Fraction, IntoSigned, IntoUnsigned, Point, Rect, ScreenScale, Size}; use kludgine::figures::{Fraction, IntoSigned, IntoUnsigned, Point, Rect, ScreenScale, Size};
use crate::context::{AsEventContext, GraphicsContext, LayoutContext}; use crate::context::{AsEventContext, LayoutContext};
use crate::styles::{Dimension, Edges, FlexibleDimension}; use crate::styles::{Dimension, Edges, FlexibleDimension};
use crate::value::{IntoValue, Value}; use crate::value::{IntoValue, Value};
use crate::widget::{MakeWidget, Widget, WidgetRef}; use crate::widget::{MakeWidget, WidgetRef, WrapperWidget};
use crate::ConstraintLimit; use crate::ConstraintLimit;
/// A widget aligns its contents to its container's boundaries. /// A widget aligns its contents to its container's boundaries.
@ -145,31 +145,31 @@ impl FrameInfo {
} }
} }
impl Widget for Align { impl WrapperWidget for Align {
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) { fn child(&mut self) -> &mut WidgetRef {
let child = self.child.mounted(&mut context.as_event_context()); &mut self.child
context.for_other(&child).redraw();
} }
fn layout( fn layout_child(
&mut self, &mut self,
available_space: Size<ConstraintLimit>, available_space: Size<ConstraintLimit>,
context: &mut LayoutContext<'_, '_, '_, '_, '_>, context: &mut LayoutContext<'_, '_, '_, '_, '_>,
) -> Size<UPx> { ) -> Rect<kludgine::figures::units::Px> {
let child = self.child.mounted(&mut context.as_event_context());
let layout = self.measure(available_space, context); let layout = self.measure(available_space, context);
context.set_child_layout(
&child,
Rect::new(
Point::new(
layout.margin.left.into_signed(),
layout.margin.top.into_signed(),
),
layout.content.into_signed(),
),
);
layout.size().into_unsigned() Rect::new(
Point::new(
layout.margin.left.into_signed(),
layout.margin.top.into_signed(),
),
layout.content.into_signed(),
)
}
}
impl AsMut<WidgetRef> for Align {
fn as_mut(&mut self) -> &mut WidgetRef {
&mut self.child
} }
} }
@ -178,9 +178,3 @@ struct Layout {
margin: Edges<UPx>, margin: Edges<UPx>,
content: Size<UPx>, content: Size<UPx>,
} }
impl Layout {
pub fn size(&self) -> Size<UPx> {
self.margin.size() + self.content
}
}

View file

@ -1,8 +1,9 @@
use kludgine::figures::units::UPx; use kludgine::figures::units::{Px, UPx};
use kludgine::figures::{IntoSigned, Rect, Size}; use kludgine::figures::{IntoSigned, Rect, Size};
use crate::context::{AsEventContext, GraphicsContext, LayoutContext}; use crate::context::{AsEventContext, LayoutContext};
use crate::widget::{MakeWidget, Widget, WidgetRef}; use crate::widget::{MakeWidget, WidgetRef, WrapperWidget};
use crate::widgets::Space;
use crate::ConstraintLimit; use crate::ConstraintLimit;
/// A widget that expands its child widget to fill the parent. /// A widget that expands its child widget to fill the parent.
@ -14,7 +15,7 @@ pub struct Expand {
/// The weight to use when splitting available space with multiple /// The weight to use when splitting available space with multiple
/// [`Expand`] widgets. /// [`Expand`] widgets.
pub weight: u8, pub weight: u8,
child: Option<WidgetRef>, child: WidgetRef,
} }
impl Default for Expand { impl Default for Expand {
@ -28,7 +29,7 @@ impl Expand {
#[must_use] #[must_use]
pub fn new(child: impl MakeWidget) -> Self { pub fn new(child: impl MakeWidget) -> Self {
Self { Self {
child: Some(WidgetRef::new(child)), child: WidgetRef::new(child),
weight: 1, weight: 1,
} }
} }
@ -37,7 +38,7 @@ impl Expand {
#[must_use] #[must_use]
pub fn empty() -> Self { pub fn empty() -> Self {
Self { Self {
child: None, child: WidgetRef::new(Space),
weight: 1, weight: 1,
} }
} }
@ -49,57 +50,44 @@ impl Expand {
#[must_use] #[must_use]
pub fn weighted(weight: u8, child: impl MakeWidget) -> Self { pub fn weighted(weight: u8, child: impl MakeWidget) -> Self {
Self { Self {
child: Some(WidgetRef::new(child)), child: WidgetRef::new(child),
weight, weight,
} }
} }
/// Returns a reference to the child widget. /// Returns a reference to the child widget.
#[must_use] #[must_use]
pub fn child(&self) -> Option<&WidgetRef> { pub const fn child(&self) -> &WidgetRef {
self.child.as_ref() &self.child
} }
} }
impl Widget for Expand { impl WrapperWidget for Expand {
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) { fn child(&mut self) -> &mut WidgetRef {
let Some(child) = &mut self.child else { return }; &mut self.child
let child = child.mounted(&mut context.as_event_context());
context.for_other(&child).redraw();
} }
fn layout( fn layout_child(
&mut self, &mut self,
available_space: Size<ConstraintLimit>, available_space: Size<ConstraintLimit>,
context: &mut LayoutContext<'_, '_, '_, '_, '_>, context: &mut LayoutContext<'_, '_, '_, '_, '_>,
) -> Size<UPx> { ) -> Rect<Px> {
let available_space = Size::new( let available_space = Size::new(
ConstraintLimit::Known(available_space.width.max()), ConstraintLimit::Known(available_space.width.max()),
ConstraintLimit::Known(available_space.height.max()), ConstraintLimit::Known(available_space.height.max()),
); );
let child = self let child = self.child.mounted(&mut context.as_event_context());
.child let size = context.for_other(&child).layout(available_space);
.as_mut()
.map(|child| child.mounted(&mut context.as_event_context()));
let size = if let Some(child) = &child {
context.for_other(child).layout(available_space)
} else {
Size::default()
};
let expanded_size = Size::new( Size::<UPx>::new(
available_space available_space
.width .width
.fit_measured(size.width, context.graphics.scale()), .fit_measured(size.width, context.graphics.scale()),
available_space available_space
.height .height
.fit_measured(size.height, context.graphics.scale()), .fit_measured(size.height, context.graphics.scale()),
); )
.into_signed()
if let Some(child) = child { .into()
context.set_child_layout(&child, Rect::from(expanded_size.into_signed()));
}
expanded_size
} }
} }

View file

@ -1,9 +1,8 @@
use kludgine::figures::units::UPx;
use kludgine::figures::{Fraction, IntoSigned, IntoUnsigned, Rect, ScreenScale, Size}; use kludgine::figures::{Fraction, IntoSigned, IntoUnsigned, Rect, ScreenScale, Size};
use crate::context::{AsEventContext, GraphicsContext, LayoutContext}; use crate::context::{AsEventContext, LayoutContext};
use crate::styles::Dimension; use crate::styles::Dimension;
use crate::widget::{MakeWidget, Widget, WidgetRef}; use crate::widget::{MakeWidget, WidgetRef, WrapperWidget};
use crate::ConstraintLimit; use crate::ConstraintLimit;
/// A widget that resizes its contained widget to an explicit size. /// A widget that resizes its contained widget to an explicit size.
@ -57,17 +56,16 @@ impl Resize {
} }
} }
impl Widget for Resize { impl WrapperWidget for Resize {
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) { fn child(&mut self) -> &mut WidgetRef {
let child = self.child.mounted(&mut context.as_event_context()); &mut self.child
context.for_other(&child).redraw();
} }
fn layout( fn layout_child(
&mut self, &mut self,
available_space: Size<ConstraintLimit>, available_space: Size<ConstraintLimit>,
context: &mut LayoutContext<'_, '_, '_, '_, '_>, context: &mut LayoutContext<'_, '_, '_, '_, '_>,
) -> Size<UPx> { ) -> Rect<kludgine::figures::units::Px> {
let child = self.child.mounted(&mut context.as_event_context()); let child = self.child.mounted(&mut context.as_event_context());
let size = if let (Some(width), Some(height)) = (self.width, self.height) { let size = if let (Some(width), Some(height)) = (self.width, self.height) {
Size::new( Size::new(
@ -85,8 +83,7 @@ impl Widget for Resize {
); );
context.for_other(&child).layout(available_space) context.for_other(&child).layout(available_space)
}; };
context.set_child_layout(&child, Rect::from(size.into_signed())); Rect::from(size.into_signed())
size
} }
} }

22
src/widgets/space.rs Normal file
View file

@ -0,0 +1,22 @@
use kludgine::figures::units::UPx;
use kludgine::figures::Size;
use crate::context::{GraphicsContext, LayoutContext};
use crate::widget::Widget;
use crate::ConstraintLimit;
/// A widget that does nothing and draws nothing.
#[derive(Debug, Clone)]
pub struct Space;
impl Widget for Space {
fn redraw(&mut self, _context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {}
fn layout(
&mut self,
_available_space: Size<ConstraintLimit>,
_context: &mut LayoutContext<'_, '_, '_, '_, '_>,
) -> Size<UPx> {
Size::default()
}
}

View file

@ -1,5 +1,5 @@
//! A widget that combines an array of [`Widgets`] into one. //! A widget that combines a collection of [`Children`] widgets into one.
// TODO on scale change, all Lp children need to resize // TODO on scale change, all `Lp` children need to resize
use std::ops::Deref; use std::ops::Deref;
@ -11,10 +11,10 @@ use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContex
use crate::styles::Dimension; use crate::styles::Dimension;
use crate::value::{Generation, IntoValue, Value}; use crate::value::{Generation, IntoValue, Value};
use crate::widget::{Children, ManagedWidget, Widget, WidgetRef}; use crate::widget::{Children, ManagedWidget, Widget, WidgetRef};
use crate::widgets::{Expand, Label, Resize}; use crate::widgets::{Expand, Resize};
use crate::ConstraintLimit; use crate::ConstraintLimit;
/// A widget that displays a collection of [`Widgets`] in a /// A widget that displays a collection of [`Children`] widgets in a
/// [direction](StackDirection). /// [direction](StackDirection).
#[derive(Debug)] #[derive(Debug)]
pub struct Stack { pub struct Stack {
@ -87,21 +87,12 @@ impl Stack {
let guard = widget.lock(); let guard = widget.lock();
let (mut widget, dimension) = let (mut widget, dimension) =
if let Some(expand) = guard.downcast_ref::<Expand>() { if let Some(expand) = guard.downcast_ref::<Expand>() {
if let Some(child) = expand.child() { (
( expand.child().clone(),
child.clone(), StackDimension::Fractional {
StackDimension::Fractional { weight: expand.weight,
weight: expand.weight, },
}, )
)
} else {
(
WidgetRef::new(Label::new("")), // TODO this should be an empty widget.
StackDimension::Fractional {
weight: expand.weight,
},
)
}
} else if let Some((child, size)) = } else if let Some((child, size)) =
guard.downcast_ref::<Resize>().and_then(|r| { guard.downcast_ref::<Resize>().and_then(|r| {
match self.layout.orientation.orientation { match self.layout.orientation.orientation {

View file

@ -1,10 +1,6 @@
use kludgine::figures::units::UPx; use crate::context::EventContext;
use kludgine::figures::Size;
use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContext};
use crate::styles::Styles; use crate::styles::Styles;
use crate::widget::{MakeWidget, Widget, WidgetRef}; use crate::widget::{MakeWidget, WidgetRef, WrapperWidget};
use crate::ConstraintLimit;
/// A widget that applies a set of [`Styles`] to all contained widgets. /// A widget that applies a set of [`Styles`] to all contained widgets.
#[derive(Debug)] #[derive(Debug)]
@ -24,22 +20,12 @@ impl Style {
} }
} }
impl Widget for Style { impl WrapperWidget for Style {
fn child(&mut self) -> &mut WidgetRef {
&mut self.child
}
fn mounted(&mut self, context: &mut EventContext<'_, '_>) { fn mounted(&mut self, context: &mut EventContext<'_, '_>) {
context.attach_styles(self.styles.clone()); context.attach_styles(self.styles.clone());
} }
fn redraw(&mut self, context: &mut GraphicsContext<'_, '_, '_, '_, '_>) {
let child = self.child.mounted(&mut context.as_event_context());
context.for_other(&child).redraw();
}
fn layout(
&mut self,
available_space: Size<ConstraintLimit>,
context: &mut LayoutContext<'_, '_, '_, '_, '_>,
) -> Size<UPx> {
let child = self.child.mounted(&mut context.as_event_context());
context.for_other(&child).layout(available_space)
}
} }