From 7fd54ef741d55232f7ab107eec293b3bc894a278 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sun, 2 Aug 2026 12:22:59 -0700 Subject: [PATCH] Add `BoxedWidget`: dynamically dispatched widgets (#8378) ## Summary - Add `BoxedWidget` and `Widget::boxed` for heterogeneous widget collections. --- crates/egui/src/widgets/mod.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/crates/egui/src/widgets/mod.rs b/crates/egui/src/widgets/mod.rs index 21346d64a..ea2e17046 100644 --- a/crates/egui/src/widgets/mod.rs +++ b/crates/egui/src/widgets/mod.rs @@ -6,6 +6,12 @@ use crate::{Response, Ui}; +/// A dynamically dispatched [`Widget`]. +/// +/// [`Widget`] is not dyn compatible because [`Widget::ui`] takes `self` by value. +/// This alias uses a closure, which implements [`Widget`]. +pub type BoxedWidget<'a> = Box Response + 'a>; + mod button; mod checkbox; pub mod color_picker; @@ -63,6 +69,20 @@ pub trait Widget { /// /// Tip: you can `impl Widget for &mut YourObject { }`. fn ui(self, ui: &mut Ui) -> Response; + + /// Box this widget for dynamic dispatch. + #[inline] + fn boxed<'a>(self) -> BoxedWidget<'a> + where + Self: Sized + 'a, + { + Box::new(move |ui: &mut Ui| ui.add(self)) + } +} + +#[test] +fn widgets_can_be_boxed() { + let _: BoxedWidget<'static> = Button::new("boxed").boxed(); } /// This enables functions that return `impl Widget`, so that you can