egui_cable/
custom_widget.rs

1use std::any::Any;
2use std::fmt::Debug;
3
4use egui::Widget;
5
6pub struct CustomWidget {
7    widget: Box<dyn Any + Send + Sync + 'static>,
8    debug: fn(&dyn Any) -> &dyn Debug,
9    ui: fn(Box<dyn Any>, &mut egui::Ui) -> egui::Response,
10}
11
12fn debug<T: Debug + 'static>(t: &dyn Any) -> &dyn Debug {
13    t.downcast_ref::<T>().unwrap()
14}
15
16fn ui<T: Widget + 'static>(widget: Box<dyn Any>, ui: &mut egui::Ui) -> egui::Response {
17    widget.downcast::<T>().unwrap().ui(ui)
18}
19
20impl Debug for CustomWidget {
21    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22        let debug = self.debug;
23        f.debug_struct("CustomWidget")
24            .field("widget", debug(&self.widget))
25            .finish()
26    }
27}
28
29// Cannot implement Widget for CustomWidget because it causes a conflict implementation with the following impl From<T>.
30impl CustomWidget {
31    pub(crate) fn ui(self, ui: &mut egui::Ui) -> egui::Response {
32        let ui_fn = self.ui;
33        ui_fn(self.widget, ui)
34    }
35}
36
37impl<T: Widget + Debug + Send + Sync + 'static> From<T> for CustomWidget {
38    fn from(widget: T) -> Self {
39        CustomWidget {
40            widget: Box::new(widget),
41            debug: debug::<T>,
42            ui: ui::<T>,
43        }
44    }
45}