switch away from handles to refs that must be upgraded once

This commit is contained in:
2025-12-20 01:36:07 -05:00
parent 32ca4ec5a6
commit c00ded78c0
11 changed files with 157 additions and 85 deletions

View File

@@ -7,7 +7,7 @@ use crate::{
use image::DynamicImage;
use std::{
ops::{Index, IndexMut},
sync::mpsc::{Receiver, Sender, channel},
sync::mpsc::{Receiver, channel},
};
mod active;
@@ -38,7 +38,6 @@ pub struct Ui {
pub root: Option<WidgetHandle>,
old_root: Option<WidgetId>,
recv: Receiver<WidgetId>,
send: Sender<WidgetId>,
resized: bool,
}
@@ -73,24 +72,20 @@ impl Ui {
&self.widgets.data(id.id()).unwrap().label
}
pub fn add_widget<W: Widget>(&mut self, w: W) -> WidgetHandle<W> {
WidgetHandle::new(self.widgets.add(w), self.send.clone())
}
pub fn new() -> Self {
Self::default()
}
pub fn get<I: IdLike>(&self, id: &I) -> Option<&I::Widget>
where
I::Widget: Sized,
I::Widget: Sized + Widget,
{
self.widgets.get(id)
}
pub fn get_mut<I: IdLike>(&mut self, id: &I) -> Option<&mut I::Widget>
where
I::Widget: Sized,
I::Widget: Sized + Widget,
{
self.widgets.get_mut(id)
}
@@ -105,6 +100,20 @@ impl Ui {
}
pub fn update(&mut self, events: &mut dyn EventsLike) {
if !self.widgets.waiting.is_empty() {
let len = self.widgets.waiting.len();
let all: Vec<_> = self
.widgets
.waiting
.iter()
.map(|&w| format!("'{}' ({w:?})", self.label(w)))
.collect();
panic!(
"{len} widget(s) were never upgraded\n\
this is likely a memory leak; consider upgrading to strong if you plan on using it later\n\
weak widgets: {all:#?}"
);
}
if self.root_changed() {
DrawState::new(self, events).redraw_all();
self.old_root = self.root.as_ref().map(|r| r.id());
@@ -169,7 +178,7 @@ impl Ui {
impl<I: IdLike> Index<I> for Ui
where
I::Widget: Sized,
I::Widget: Sized + Widget,
{
type Output = I::Widget;
@@ -180,7 +189,7 @@ where
impl<I: IdLike> IndexMut<I> for Ui
where
I::Widget: Sized,
I::Widget: Sized + Widget,
{
fn index_mut(&mut self, id: I) -> &mut Self::Output {
self.get_mut(&id).unwrap()
@@ -191,7 +200,7 @@ impl Default for Ui {
fn default() -> Self {
let (send, recv) = channel();
Self {
widgets: Default::default(),
widgets: Widgets::new(send),
active: Default::default(),
layers: Default::default(),
masks: Default::default(),
@@ -201,7 +210,6 @@ impl Default for Ui {
output_size: Vec2::ZERO,
root: None,
old_root: None,
send,
recv,
resized: false,
}