This commit is contained in:
iris committed 2026-01-12 18:40:27 -05:00
1 parent a9c76e4326
commit 79813db3ba
35 files changed
+378 -403

No files matched your search

+50 -14
View File
@@ -1,7 +1,7 @@
use std::sync::mpsc::Sender;
use std::sync::mpsc::{Receiver, Sender, channel};
use crate::{
IdLike, Widget, WidgetData, WidgetHandle, WidgetId, WidgetRef,
IdLike, StrongWidget, WeakWidget, Widget, WidgetData, WidgetId,
util::{DynBorrower, HashSet, SlotVec, forget_mut, to_mut},
};
@@ -9,16 +9,19 @@ pub struct Widgets {
pub needs_redraw: HashSet<WidgetId>,
vec: SlotVec<WidgetData>,
send: Sender<WidgetId>,
recv: Receiver<WidgetId>,
pub(crate) waiting: HashSet<WidgetId>,
}
impl Widgets {
pub fn new(send: Sender<WidgetId>) -> Self {
pub fn new() -> Self {
let (send, recv) = channel();
Self {
needs_redraw: Default::default(),
vec: Default::default(),
waiting: Default::default(),
send,
recv,
}
}
@@ -61,25 +64,27 @@ impl Widgets {
self.get_dyn_mut(id.id())?.as_any_mut().downcast_mut()
}
pub fn add_strong<W: Widget>(&mut self, widget: W) -> WidgetHandle<W> {
pub fn add_strong<W: Widget>(&mut self, widget: W) -> StrongWidget<W> {
let id = self.vec.add(WidgetData::new(widget));
WidgetHandle::new(id, self.send.clone())
StrongWidget::new(id, self.send.clone())
}
pub fn add_weak<W: Widget>(&mut self, widget: W) -> WidgetRef<W> {
pub fn add_weak<W: Widget>(&mut self, widget: W) -> WeakWidget<W> {
let id = self.vec.add(WidgetData::new(widget));
self.waiting.insert(id);
WidgetRef::new(id)
WeakWidget::new(id)
}
#[track_caller]
pub fn upgrade<W: ?Sized>(&mut self, rf: WidgetRef<W>) -> WidgetHandle<W> {
pub fn upgrade<W: ?Sized>(&mut self, rf: WeakWidget<W>) -> StrongWidget<W> {
if !self.waiting.remove(&rf.id()) {
let label = self.label(rf);
let id = rf.id();
panic!("widget '{label}' ({id:?}) was already added\ncannot add a widget twice; consider creating two")
panic!(
"widget '{label}' ({id:?}) was already added\ncannot add a widget twice; consider creating two"
)
}
WidgetHandle::new(rf.id(), self.send.clone())
StrongWidget::new(rf.id(), self.send.clone())
}
pub fn data(&self, id: impl IdLike) -> Option<&WidgetData> {
@@ -90,14 +95,19 @@ impl Widgets {
&self.data(id.id()).unwrap().label
}
/// useful for debugging
pub fn set_label(&mut self, id: impl IdLike, label: String) {
self.data_mut(id.id()).unwrap().label = label;
}
pub fn data_mut(&mut self, id: impl IdLike) -> Option<&mut WidgetData> {
self.vec.get_mut(id.id())
}
pub fn delete(&mut self, id: impl IdLike) {
self.vec.free(id.id());
// not sure if there's any point in this
// self.updates.remove(&id);
pub fn free(&mut self) {
for id in self.recv.try_iter() {
self.vec.free(id.id());
}
}
#[allow(clippy::len_without_is_empty)]
@@ -106,4 +116,30 @@ impl Widgets {
}
}
impl Default for Widgets {
fn default() -> Self {
Self::new()
}
}
pub type WidgetWrapper<'a> = DynBorrower<'a, dyn Widget>;
impl<I: IdLike> std::ops::Index<I> for Widgets
where
I::Widget: Sized + Widget,
{
type Output = I::Widget;
fn index(&self, id: I) -> &Self::Output {
self.get(&id).unwrap()
}
}
impl<I: IdLike> std::ops::IndexMut<I> for Widgets
where
I::Widget: Sized + Widget,
{
fn index_mut(&mut self, id: I) -> &mut Self::Output {
self.get_mut(&id).unwrap()
}
}