diff --git a/core/src/attr.rs b/core/src/attr.rs index 99d4151..6d0a28e 100644 --- a/core/src/attr.rs +++ b/core/src/attr.rs @@ -1,15 +1,15 @@ -use crate::{HasUi, WidgetIdFn, WidgetLike, WidgetRef}; +use crate::{UiRsc, WidgetIdFn, WidgetLike, WeakWidget}; pub trait WidgetAttr { type Input; - fn run(rsc: &mut Rsc, id: WidgetRef, input: Self::Input); + fn run(rsc: &mut Rsc, id: WeakWidget, input: Self::Input); } pub trait Attrable { fn attr>(self, input: A::Input) -> impl WidgetIdFn; } -impl, Tag> Attrable for WL { +impl, Tag> Attrable for WL { fn attr>( self, input: A::Input, diff --git a/core/src/event/ctx.rs b/core/src/event/ctx.rs index a16cfd9..0997e1f 100644 --- a/core/src/event/ctx.rs +++ b/core/src/event/ctx.rs @@ -1,4 +1,4 @@ -use crate::{HasEvents, HasUi, Widget, WidgetRef}; +use crate::{HasEvents, WeakWidget, Widget}; pub struct EventCtx<'a, Rsc: HasEvents, Data> { pub state: &'a mut Rsc::State, @@ -6,13 +6,13 @@ pub struct EventCtx<'a, Rsc: HasEvents, Data> { } pub struct EventIdCtx<'a, Rsc: HasEvents, Data, W: ?Sized> { - pub widget: WidgetRef, + pub widget: WeakWidget, pub state: &'a mut Rsc::State, pub data: Data, } -impl EventIdCtx<'_, Rsc, Data, W> { +impl EventIdCtx<'_, Rsc, Data, W> { pub fn widget<'a>(&self, rsc: &'a mut Rsc) -> &'a mut W { - &mut rsc.ui_mut()[self.widget] + &mut rsc.widgets_mut()[self.widget] } } diff --git a/core/src/event/manager.rs b/core/src/event/manager.rs index 5876eeb..6896478 100644 --- a/core/src/event/manager.rs +++ b/core/src/event/manager.rs @@ -1,6 +1,6 @@ use crate::{ ActiveData, Event, EventCtx, EventFn, EventIdCtx, EventLike, HasEvents, IdLike, LayerId, - Widget, WidgetEventFn, WidgetId, WidgetRef, + Widget, WidgetEventFn, WidgetId, WeakWidget, util::{HashMap, HashSet, TypeMap}, }; use std::{any::TypeId, rc::Rc}; @@ -26,7 +26,7 @@ impl EventManager { pub fn register( &mut self, - id: WidgetRef, + id: WeakWidget, event: E, f: impl WidgetEventFn::Data, W>, ) { @@ -114,7 +114,7 @@ impl Default for TypeEventManager { impl TypeEventManager { fn register( &mut self, - widget: WidgetRef, + widget: WeakWidget, event: impl EventLike, f: impl WidgetEventFn, ) { diff --git a/core/src/event/rsc.rs b/core/src/event/rsc.rs index 0ef2ba8..bcd174f 100644 --- a/core/src/event/rsc.rs +++ b/core/src/event/rsc.rs @@ -1,18 +1,18 @@ use crate::{ - Event, EventCtx, EventLike, EventManager, HasUi, IdLike, Widget, WidgetEventFn, WidgetRef, + Event, EventCtx, EventLike, EventManager, IdLike, UiRsc, Widget, WidgetEventFn, WeakWidget, }; pub trait HasState: 'static { type State; } -pub trait HasEvents: Sized + HasUi + HasState { +pub trait HasEvents: Sized + UiRsc + HasState { fn events(&self) -> &EventManager; fn events_mut(&mut self) -> &mut EventManager; fn register_event( &mut self, - id: WidgetRef, + id: WeakWidget, event: E, f: impl WidgetEventFn::Data, W>, ) { diff --git a/core/src/primitive/mod.rs b/core/src/primitive/mod.rs index 8284a05..7d81635 100644 --- a/core/src/primitive/mod.rs +++ b/core/src/primitive/mod.rs @@ -7,3 +7,12 @@ pub use color::*; pub use layer::*; pub use text::*; pub use texture::*; + +use crate::{Mask, util::TrackedArena}; + +#[derive(Default)] +pub struct PainterData { + pub textures: Textures, + pub text: TextData, + pub masks: TrackedArena, +} diff --git a/core/src/primitive/text.rs b/core/src/primitive/text.rs index 663af0f..820d1f0 100644 --- a/core/src/primitive/text.rs +++ b/core/src/primitive/text.rs @@ -3,7 +3,7 @@ use cosmic_text::{ Attrs, AttrsList, Buffer, CacheKey, Color, Family, FontSystem, Metrics, Placement, SwashCache, SwashContent, }; -use image::{GenericImageView, RgbaImage}; +use image::{DynamicImage, GenericImageView, RgbaImage}; use std::simd::{Simd, num::SimdUint}; /// TODO: properly wrap this @@ -185,3 +185,7 @@ pub struct RenderedText { pub top_left_offset: Vec2, pub size: Vec2, } + +pub trait HasTextures { + fn add_texture(&mut self, image: DynamicImage) -> TextureHandle; +} diff --git a/core/src/render/mod.rs b/core/src/render/mod.rs index dece8a8..65ad0a1 100644 --- a/core/src/render/mod.rs +++ b/core/src/render/mod.rs @@ -1,7 +1,7 @@ use std::num::NonZero; use crate::{ - Ui, + Textures, UiRenderState, render::{data::PrimitiveInstance, texture::GpuTextures, util::ArrBuf}, util::HashMap, }; @@ -59,7 +59,13 @@ impl UiRenderNode { } } - pub fn update(&mut self, device: &Device, queue: &Queue, ui: &mut Ui) { + pub fn update( + &mut self, + device: &Device, + queue: &Queue, + ui: &mut UiRenderState, + textures: &mut Textures, + ) { self.active.clear(); for (i, primitives) in ui.layers.iter_mut() { self.active.push(i); @@ -101,7 +107,7 @@ impl UiRenderNode { } } let mut changed = false; - changed |= self.textures.update(&mut ui.textures); + changed |= self.textures.update(textures); if ui.masks.changed { ui.masks.changed = false; self.masks.update(device, queue, &ui.masks[..]); diff --git a/core/src/ui/draw_state.rs b/core/src/ui/draw_state.rs index 555acb7..02b1d19 100644 --- a/core/src/ui/draw_state.rs +++ b/core/src/ui/draw_state.rs @@ -1,22 +1,34 @@ use crate::{ - ActiveData, Axis, EventsLike, Painter, SizeCtx, Ui, UiRegion, UiVec2, WidgetId, + ActiveData, Axis, EventsLike, Painter, PainterData, SizeCtx, StrongWidget, UiRegion, + UiRenderState, UiVec2, WidgetId, Widgets, render::MaskIdx, util::{HashSet, forget_ref}, }; -use std::ops::{Deref, DerefMut}; /// state maintained between widgets during painting -pub struct DrawState<'a> { - pub(super) ui: &'a mut Ui, +pub struct Drawer<'a> { + pub(super) widgets: &'a mut Widgets, + pub(super) data: &'a mut PainterData, pub(super) events: &'a mut dyn EventsLike, + pub(super) render: &'a mut UiRenderState, + root: Option<&'a StrongWidget>, draw_started: HashSet, } -impl<'a> DrawState<'a> { - pub fn new(ui: &'a mut Ui, events: &'a mut dyn EventsLike) -> Self { +impl<'a> Drawer<'a> { + pub fn new( + widgets: &'a mut Widgets, + data: &'a mut PainterData, + render: &'a mut UiRenderState, + events: &'a mut dyn EventsLike, + root: Option<&'a StrongWidget>, + ) -> Self { Self { - ui, + widgets, + data, events, + render, + root, draw_started: Default::default(), } } @@ -34,13 +46,17 @@ impl<'a> DrawState<'a> { self.draw_started.remove(&id); // check if parent depends on the desired size of this, if so then redraw it first for axis in [Axis::X, Axis::Y] { - if let Some(&(outer, old)) = self.cache.size.axis_dyn(axis).get(&id) - && let Some(current) = self.active.get(&id) + if let Some(&(outer, old)) = self.render.cache.size.axis_dyn(axis).get(&id) + && let Some(current) = self.render.active.get(&id) && let Some(pid) = current.parent { - self.cache.size.axis_dyn(axis).remove(&id); + self.render.cache.size.axis_dyn(axis).remove(&id); let new = self.size_ctx(id, outer).len_axis(id, axis); - self.cache.size.axis_dyn(axis).insert(id, (outer, new)); + self.render + .cache + .size + .axis_dyn(axis) + .insert(id, (outer, new)); if new != old { self.redraw(pid); } @@ -68,27 +84,27 @@ impl<'a> DrawState<'a> { pub(super) fn size_ctx<'b>(&'b mut self, source: WidgetId, outer: UiVec2) -> SizeCtx<'b> { SizeCtx { source, - cache: &mut self.ui.cache, - text: &mut self.ui.text, - textures: &mut self.ui.textures, - widgets: &self.ui.widgets, + cache: &mut self.render.cache, + text: &mut self.data.text, + textures: &mut self.data.textures, + widgets: &self.widgets, outer, - output_size: self.ui.output_size, + output_size: self.render.output_size, id: source, } } pub fn redraw_all(&mut self) { // free all resources & cache - for (_, active) in self.ui.active.drain() { + for (_, active) in self.render.active.drain() { self.events.undraw(&active); } - self.ui.cache.clear(); + self.render.cache.clear(); self.ui.free(self.events); - self.layers.clear(); + self.render.layers.clear(); self.widgets.needs_redraw.clear(); - if let Some(id) = &self.ui.root { + if let Some(id) = self.root { self.draw_inner(0, id.id(), UiRegion::FULL, None, MaskIdx::NONE, None); } } @@ -103,8 +119,8 @@ impl<'a> DrawState<'a> { old_children: Option>, ) { let mut old_children = old_children.unwrap_or_default(); - if let Some(active) = self.ui.active.get_mut(&id) - && !self.ui.widgets.needs_redraw.contains(&id) + if let Some(active) = self.render.active.get_mut(&id) + && !self.widgets.needs_redraw.contains(&id) { // check to see if we can skip drawing first if active.region == region { @@ -124,7 +140,7 @@ impl<'a> DrawState<'a> { self.draw_started.insert(id); let mut painter = Painter { - state: self, + drawer: self, region, mask, layer, @@ -134,12 +150,12 @@ impl<'a> DrawState<'a> { children: Vec::new(), }; - let mut widget = painter.state.widgets.get_dyn_dynamic(id); + let mut widget = painter.drawer.widgets.get_dyn_dynamic(id); widget.draw(&mut painter); drop(widget); let Painter { - state: _, + drawer: _, region, mask, textures, @@ -170,13 +186,13 @@ impl<'a> DrawState<'a> { // update modules self.events.draw(&active); - self.active.insert(id, active); + self.render.active.insert(id, active); } fn mov(&mut self, id: WidgetId, from: UiRegion, to: UiRegion) { - let active = self.ui.active.get_mut(&id).unwrap(); + let active = self.render.active.get_mut(&id).unwrap(); for h in &active.primitives { - let region = self.ui.layers[h.layer].region_mut(h); + let region = self.render.layers[h.layer].region_mut(h); *region = region.outside(&from).within(&to); } active.region = active.region.outside(&from).within(&to); @@ -189,16 +205,16 @@ impl<'a> DrawState<'a> { /// NOTE: instance textures are cleared and self.textures freed fn remove(&mut self, id: WidgetId, undraw: bool) -> Option { - let mut active = self.active.remove(&id); + let mut active = self.render.active.remove(&id); if let Some(active) = &mut active { for h in &active.primitives { - let mask = self.layers.free(h); + let mask = self.render.layers.free(h); if mask != MaskIdx::NONE { - self.masks.remove(mask); + self.data.masks.remove(mask); } } active.textures.clear(); - self.textures.free(); + self.data.textures.free(); if undraw { self.events.undraw(active); } @@ -207,7 +223,7 @@ impl<'a> DrawState<'a> { } fn remove_rec(&mut self, id: WidgetId) -> Option { - self.cache.remove(id); + self.render.cache.remove(id); let inst = self.remove(id, true); if let Some(inst) = &inst { for c in &inst.children { @@ -217,16 +233,3 @@ impl<'a> DrawState<'a> { inst } } - -impl Deref for DrawState<'_> { - type Target = Ui; - - fn deref(&self) -> &Self::Target { - self.ui - } -} -impl DerefMut for DrawState<'_> { - fn deref_mut(&mut self) -> &mut Self::Target { - self.ui - } -} diff --git a/core/src/ui/mod.rs b/core/src/ui/mod.rs index aa14ec7..f6eaf77 100644 --- a/core/src/ui/mod.rs +++ b/core/src/ui/mod.rs @@ -1,211 +1,22 @@ -use crate::{ - EventsLike, IdLike, Mask, PixelRegion, PrimitiveLayers, TextData, TextureHandle, Textures, - Widget, WidgetHandle, WidgetId, Widgets, - ui::draw_state::DrawState, - util::{HashMap, TrackedArena, Vec2}, -}; -use image::DynamicImage; -use std::{ - ops::{Index, IndexMut}, - sync::mpsc::{Receiver, channel}, -}; +use crate::{WeakWidget, Widget, Widgets}; mod active; mod cache; mod draw_state; mod painter; +mod render_state; mod size; mod state; pub use active::*; -use cache::*; pub use painter::Painter; +pub use render_state::*; pub use size::*; -pub struct Ui { - // TODO: edit visibilities - pub widgets: Widgets, +pub struct Ui {} - // retained painter state - pub active: HashMap, - pub layers: PrimitiveLayers, - pub textures: Textures, - pub text: TextData, - output_size: Vec2, - pub masks: TrackedArena, - pub cache: Cache, - - pub root: Option, - old_root: Option, - recv: Receiver, - resized: bool, -} - -pub trait HasUi: Sized { - fn ui(&self) -> &Ui; - fn ui_mut(&mut self) -> &mut Ui; -} - -impl HasUi for Ui { - fn ui(&self) -> &Ui { - self - } - - fn ui_mut(&mut self) -> &mut Ui { - self - } -} - -impl Ui { - /// useful for debugging - pub fn set_label(&mut self, id: impl IdLike, label: String) { - self.widgets.data_mut(id.id()).unwrap().label = label; - } - - pub fn label(&self, id: impl IdLike) -> &String { - &self.widgets.data(id.id()).unwrap().label - } - - pub fn new() -> Self { - Self::default() - } - - pub fn get(&self, id: &I) -> Option<&I::Widget> - where - I::Widget: Sized + Widget, - { - self.widgets.get(id) - } - - pub fn get_mut(&mut self, id: &I) -> Option<&mut I::Widget> - where - I::Widget: Sized + Widget, - { - self.widgets.get_mut(id) - } - - pub fn add_texture(&mut self, image: DynamicImage) -> TextureHandle { - self.textures.add(image) - } - - pub fn resize(&mut self, size: impl Into) { - self.output_size = size.into(); - self.resized = true; - } - - 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()); - } else if self.widgets.has_updates() { - DrawState::new(self, events).redraw_updates(); - } - if self.resized { - self.resized = false; - DrawState::new(self, events).redraw_all(); - } - } - - /// free any resources that don't have references anymore - fn free(&mut self, events: &mut dyn EventsLike) { - for id in self.recv.try_iter() { - events.remove(id); - self.widgets.delete(id); - } - self.textures.free(); - } - - pub fn root_changed(&self) -> bool { - self.root.as_ref().map(|r| r.id()) != self.old_root - } - - pub fn needs_redraw(&self) -> bool { - self.root_changed() || self.widgets.has_updates() - } - - pub fn num_widgets(&self) -> usize { - self.widgets.len() - } - - pub fn active_widgets(&self) -> usize { - self.active.len() - } - - pub fn debug_layers(&self) { - for ((idx, depth), primitives) in self.layers.iter_depth() { - let indent = " ".repeat(depth * 2); - let len = primitives.instances().len(); - print!("{indent}{idx}: {len} primitives"); - if len >= 1 { - print!(" ({})", primitives.instances()[0].binding); - } - println!(); - } - } - - pub fn window_region(&self, id: &impl IdLike) -> Option { - let region = self.active.get(&id.id())?.region; - Some(region.to_px(self.output_size)) - } - - pub fn debug(&self, label: &str) -> impl Iterator { - self.active.iter().filter_map(move |(&id, inst)| { - let l = self.widgets.label(id); - if l == label { Some(inst) } else { None } - }) - } -} - -impl Index for Ui -where - I::Widget: Sized + Widget, -{ - type Output = I::Widget; - - fn index(&self, id: I) -> &Self::Output { - self.get(&id).unwrap() - } -} - -impl IndexMut for Ui -where - I::Widget: Sized + Widget, -{ - fn index_mut(&mut self, id: I) -> &mut Self::Output { - self.get_mut(&id).unwrap() - } -} - -impl Default for Ui { - fn default() -> Self { - let (send, recv) = channel(); - Self { - widgets: Widgets::new(send), - active: Default::default(), - layers: Default::default(), - masks: Default::default(), - text: Default::default(), - textures: Default::default(), - cache: Default::default(), - output_size: Vec2::ZERO, - root: None, - old_root: None, - recv, - resized: false, - } - } +pub trait UiRsc: Sized { + fn add_widget(&mut self, widget: W) -> WeakWidget; + fn widgets(&self) -> &Widgets; + fn widgets_mut(&mut self) -> &mut Widgets; } diff --git a/core/src/ui/painter.rs b/core/src/ui/painter.rs index dc707b2..e48c774 100644 --- a/core/src/ui/painter.rs +++ b/core/src/ui/painter.rs @@ -1,14 +1,14 @@ use crate::{ - Axis, Len, RenderedText, Size, SizeCtx, TextAttrs, TextBuffer, TextData, TextureHandle, - UiRegion, Widget, WidgetHandle, WidgetId, + Axis, Len, RenderedText, Size, SizeCtx, StrongWidget, TextAttrs, TextBuffer, TextData, + TextureHandle, UiRegion, Widget, WidgetId, render::{Mask, MaskIdx, Primitive, PrimitiveHandle, PrimitiveInst}, - ui::draw_state::DrawState, + ui::draw_state::Drawer, util::Vec2, }; /// makes your surfaces look pretty pub struct Painter<'a, 'b> { - pub(super) state: &'a mut DrawState<'b>, + pub(super) drawer: &'a mut Drawer<'b>, pub(super) region: UiRegion, pub(super) mask: MaskIdx, @@ -21,7 +21,7 @@ pub struct Painter<'a, 'b> { impl<'a, 'c> Painter<'a, 'c> { fn primitive_at(&mut self, primitive: P, region: UiRegion) { - let h = self.state.layers.write( + let h = self.drawer.layers.write( self.layer, PrimitiveInst { id: self.id, @@ -32,7 +32,7 @@ impl<'a, 'c> Painter<'a, 'c> { ); if self.mask != MaskIdx::NONE { // TODO: I have no clue if this works at all :joy: - self.state.masks.push_ref(self.mask); + self.drawer.masks.push_ref(self.mask); } self.primitives.push(h); } @@ -48,23 +48,23 @@ impl<'a, 'c> Painter<'a, 'c> { pub fn set_mask(&mut self, region: UiRegion) { assert!(self.mask == MaskIdx::NONE); - self.mask = self.state.masks.push(Mask { region }); + self.mask = self.drawer.masks.push(Mask { region }); } /// Draws a widget within this widget's region. - pub fn widget(&mut self, id: &WidgetHandle) { + pub fn widget(&mut self, id: &StrongWidget) { self.widget_at(id, self.region); } /// Draws a widget somewhere within this one. /// Useful for drawing child widgets in select areas. - pub fn widget_within(&mut self, id: &WidgetHandle, region: UiRegion) { + pub fn widget_within(&mut self, id: &StrongWidget, region: UiRegion) { self.widget_at(id, region.within(&self.region)); } - fn widget_at(&mut self, id: &WidgetHandle, region: UiRegion) { + fn widget_at(&mut self, id: &StrongWidget, region: UiRegion) { self.children.push(id.id()); - self.state + self.drawer .draw_inner(self.layer, id.id(), region, Some(self.id), self.mask, None); } @@ -85,21 +85,21 @@ impl<'a, 'c> Painter<'a, 'c> { /// returns (handle, offset from top left) pub fn render_text(&mut self, buffer: &mut TextBuffer, attrs: &TextAttrs) -> RenderedText { - self.state + self.drawer .ui .text - .draw(buffer, attrs, &mut self.state.ui.textures) + .draw(buffer, attrs, &mut self.drawer.ui.textures) } pub fn region(&self) -> UiRegion { self.region } - pub fn size(&mut self, id: &WidgetHandle) -> Size { + pub fn size(&mut self, id: &StrongWidget) -> Size { self.size_ctx().size(id) } - pub fn len_axis(&mut self, id: &WidgetHandle, axis: Axis) -> Len { + pub fn len_axis(&mut self, id: &StrongWidget, axis: Axis) -> Len { match axis { Axis::X => self.size_ctx().width(id), Axis::Y => self.size_ctx().height(id), @@ -107,27 +107,27 @@ impl<'a, 'c> Painter<'a, 'c> { } pub fn output_size(&self) -> Vec2 { - self.state.output_size + self.drawer.output_size } pub fn px_size(&mut self) -> Vec2 { - self.region.size().to_abs(self.state.output_size) + self.region.size().to_abs(self.drawer.output_size) } pub fn text_data(&mut self) -> &mut TextData { - &mut self.state.text + &mut self.drawer.text } pub fn child_layer(&mut self) { - self.layer = self.state.layers.child(self.layer); + self.layer = self.drawer.layers.child(self.layer); } pub fn next_layer(&mut self) { - self.layer = self.state.layers.next(self.layer); + self.layer = self.drawer.layers.next(self.layer); } pub fn label(&self) -> &str { - &self.state.widgets.data(self.id).unwrap().label + &self.drawer.widgets.data(self.id).unwrap().label } pub fn id(&self) -> &WidgetId { @@ -135,6 +135,6 @@ impl<'a, 'c> Painter<'a, 'c> { } pub fn size_ctx(&mut self) -> SizeCtx<'_> { - self.state.size_ctx(self.id, self.region.size()) + self.drawer.size_ctx(self.id, self.region.size()) } } diff --git a/core/src/ui/render_state.rs b/core/src/ui/render_state.rs new file mode 100644 index 0000000..aad10dd --- /dev/null +++ b/core/src/ui/render_state.rs @@ -0,0 +1,116 @@ +use crate::{ + ActiveData, EventsLike, IdLike, PixelRegion, PrimitiveLayers, StrongWidget, WidgetId, Widgets, + ui::{cache::Cache, draw_state::Drawer}, + util::{HashMap, Vec2}, +}; + +pub struct UiRenderState { + pub active: HashMap, + pub layers: PrimitiveLayers, + pub(super) output_size: Vec2, + pub cache: Cache, + + old_root: Option, + resized: bool, +} + +impl UiRenderState { + pub fn new() -> Self { + Self { + active: Default::default(), + layers: Default::default(), + cache: Default::default(), + output_size: Vec2::ZERO, + old_root: None, + resized: false, + } + } + + pub fn resize(&mut self, size: impl Into) { + self.output_size = size.into(); + self.resized = true; + } + + pub fn update<'a>( + &mut self, + root: impl Into>, + widgets: &mut Widgets, + events: &mut dyn EventsLike, + ) { + // safety mechanism for memory leaks; might wanna return a result instead so user can + // decide whether to panic or not + if !widgets.waiting.is_empty() { + let len = widgets.waiting.len(); + let all: Vec<_> = widgets + .waiting + .iter() + .map(|&w| format!("'{}' ({w:?})", widgets.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(root) { + Drawer::new(self, events).redraw_all(); + self.old_root = root.into().map(|r| r.id()); + } else if widgets.has_updates() { + Drawer::new(self, events).redraw_updates(); + } + if self.resized { + self.resized = false; + Drawer::new(self, events).redraw_all(); + } + } + + pub fn root_changed<'a>(&self, root: impl Into>) -> bool { + root.into().map(|r| r.id()) != self.old_root + } + + pub fn needs_redraw<'a>( + &self, + root: impl Into>, + widgets: &Widgets, + ) -> bool { + self.root_changed(root) || widgets.has_updates() + } + + pub fn active_widgets(&self) -> usize { + self.active.len() + } + + pub fn debug(&self, widgets: &Widgets, label: &str) -> impl Iterator { + self.active.iter().filter_map(move |(&id, inst)| { + let l = widgets.label(id); + if l == label { Some(inst) } else { None } + }) + } + + pub fn debug_layers(&self) { + for ((idx, depth), primitives) in self.layers.iter_depth() { + let indent = " ".repeat(depth * 2); + let len = primitives.instances().len(); + print!("{indent}{idx}: {len} primitives"); + if len >= 1 { + print!(" ({})", primitives.instances()[0].binding); + } + println!(); + } + } + + pub fn window_region(&self, id: &impl IdLike) -> Option { + let region = self.active.get(&id.id())?.region; + Some(region.to_px(self.output_size)) + } +} + +pub trait HasRoot { + fn set_root(&mut self, root: StrongWidget); +} + +impl Default for UiRenderState { + fn default() -> Self { + Self::new() + } +} diff --git a/core/src/widget/handle.rs b/core/src/widget/handle.rs index 98e6951..7b52275 100644 --- a/core/src/widget/handle.rs +++ b/core/src/widget/handle.rs @@ -1,7 +1,7 @@ use std::{marker::Unsize, ops::CoerceUnsized, sync::mpsc::Sender}; use crate::{ - HasUi, Widget, + UiRsc, Widget, util::{RefCounter, SlotId}, }; @@ -12,7 +12,7 @@ pub type WidgetId = SlotId; /// a signal is sent to the owning UI to clean up the resources. /// /// TODO: ergonomic clones when they get put in rust-analyzer & don't cause ICEs? -pub struct WidgetHandle { +pub struct StrongWidget { pub(super) id: WidgetId, counter: RefCounter, send: Sender, @@ -21,24 +21,19 @@ pub struct WidgetHandle { /// A weak handle to a widget. /// Will not keep it alive, but can still be used for indexing like WidgetHandle. -pub struct WidgetRef { +pub struct WeakWidget { pub(super) id: WidgetId, #[allow(unused)] ty: *const W, } -pub struct WidgetHandles { - pub h: WidgetHandle, - pub r: WidgetRef, -} - -impl> WidgetHandle { - pub fn any(self) -> WidgetHandle { +impl> StrongWidget { + pub fn any(self) -> StrongWidget { self } } -impl WidgetHandle { +impl StrongWidget { pub(crate) fn new(id: WidgetId, send: Sender) -> Self { Self { id, @@ -56,18 +51,13 @@ impl WidgetHandle { self.counter.refs() } - pub fn weak(&self) -> WidgetRef { + pub fn weak(&self) -> WeakWidget { let Self { ty, id, .. } = *self; - WidgetRef { ty, id } - } - - pub fn handles(self) -> WidgetHandles { - let r = self.weak(); - WidgetHandles { h: self, r } + WeakWidget { ty, id } } } -impl WidgetRef { +impl WeakWidget { pub(crate) fn new(id: WidgetId) -> Self { Self { id, ty: null_ptr() } } @@ -77,12 +67,12 @@ impl WidgetRef { } #[track_caller] - pub fn upgrade(self, ui: &mut impl HasUi) -> WidgetHandle { - ui.ui_mut().widgets.upgrade(self) + pub fn upgrade(self, ui: &mut impl UiRsc) -> StrongWidget { + ui.widgets_mut().upgrade(self) } } -impl Drop for WidgetHandle { +impl Drop for StrongWidget { fn drop(&mut self) { if self.counter.drop() { let _ = self.send.send(self.id); @@ -90,29 +80,29 @@ impl Drop for WidgetHandle { } } -pub trait WidgetIdFn: FnOnce(&mut Rsc) -> WidgetRef {} -impl WidgetRef> WidgetIdFn for F {} +pub trait WidgetIdFn: FnOnce(&mut Rsc) -> WeakWidget {} +impl WeakWidget> WidgetIdFn for F {} pub trait IdLike { type Widget: ?Sized; fn id(&self) -> WidgetId; } -impl IdLike for &WidgetHandle { +impl IdLike for &StrongWidget { type Widget = W; fn id(&self) -> WidgetId { self.id } } -impl IdLike for WidgetHandle { +impl IdLike for StrongWidget { type Widget = W; fn id(&self) -> WidgetId { self.id } } -impl IdLike for WidgetRef { +impl IdLike for WeakWidget { type Widget = W; fn id(&self) -> WidgetId { self.id @@ -126,38 +116,38 @@ impl IdLike for WidgetId { } } -impl, U: ?Sized> CoerceUnsized> for WidgetHandle {} -impl, U: ?Sized> CoerceUnsized> for WidgetRef {} +impl, U: ?Sized> CoerceUnsized> for StrongWidget {} +impl, U: ?Sized> CoerceUnsized> for WeakWidget {} -impl Clone for WidgetRef { +impl Clone for WeakWidget { fn clone(&self) -> Self { *self } } -impl Copy for WidgetRef {} -impl PartialEq for WidgetRef { +impl Copy for WeakWidget {} +impl PartialEq for WeakWidget { fn eq(&self, other: &Self) -> bool { self.id == other.id } } -impl PartialEq for WidgetHandle { +impl PartialEq for StrongWidget { fn eq(&self, other: &Self) -> bool { self.id == other.id } } -impl std::fmt::Debug for WidgetHandle { +impl std::fmt::Debug for StrongWidget { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.id.fmt(f) } } -impl<'a, W: Widget + 'a, State: HasUi> FnOnce<(&'a mut State,)> for WidgetRef { +impl<'a, W: Widget + 'a, State: UiRsc> FnOnce<(&'a mut State,)> for WeakWidget { type Output = &'a mut W; extern "rust-call" fn call_once(self, args: (&'a mut State,)) -> Self::Output { - &mut args.0.ui_mut()[self] + &mut args.0.widgets_mut()[self] } } @@ -170,5 +160,5 @@ fn null_ptr() -> *const W { } } -unsafe impl Send for WidgetRef {} -unsafe impl Sync for WidgetRef {} +unsafe impl Send for WeakWidget {} +unsafe impl Sync for WeakWidget {} diff --git a/core/src/widget/like.rs b/core/src/widget/like.rs index 5937f03..fe4b0ea 100644 --- a/core/src/widget/like.rs +++ b/core/src/widget/like.rs @@ -1,20 +1,20 @@ -use crate::HasUi; +use crate::{HasRoot, UiRsc}; use super::*; use std::marker::Unsize; -pub trait WidgetLike: Sized { +pub trait WidgetLike: Sized { type Widget: Widget + ?Sized + Unsize; - fn add(self, rsc: &mut Rsc) -> WidgetRef; + fn add(self, rsc: &mut Rsc) -> WeakWidget; - fn add_strong(self, rsc: &mut Rsc) -> WidgetHandle { - self.add(rsc).upgrade(rsc.ui_mut()) + fn add_strong(self, rsc: &mut Rsc) -> StrongWidget { + self.add(rsc).upgrade(rsc) } fn with_id( self, - f: impl FnOnce(&mut Rsc, WidgetRef) -> WidgetRef, + f: impl FnOnce(&mut Rsc, WeakWidget) -> WeakWidget, ) -> impl WidgetIdFn { move |state| { let id = self.add(state); @@ -22,14 +22,12 @@ pub trait WidgetLike: Sized { } } - fn set_root(self, state: &mut Rsc) { - let id = self.add(state); - let ui = state.ui_mut(); - ui.root = Some(id.upgrade(ui)); - } - - fn handles(self, state: &mut Rsc) -> WidgetHandles { - self.add(state).upgrade(state.ui_mut()).handles() + fn set_root(self, rsc: &mut Rsc) + where + Rsc: HasRoot, + { + let id = self.add_strong(rsc); + rsc.set_root(id); } } @@ -50,12 +48,12 @@ macro_rules! impl_widget_arr { impl_widget_arr!($n;$($W)*;$(${concat($W,Tag)})*); }; ($n:expr;$($W:ident)*;$($Tag:ident)*) => { - impl,$Tag,)*> WidgetArrLike for ($($W,)*) { + impl,$Tag,)*> WidgetArrLike for ($($W,)*) { fn add(self, rsc: &mut Rsc) -> WidgetArr<$n> { #[allow(non_snake_case)] let ($($W,)*) = self; WidgetArr::new( - [$($W.add(rsc).upgrade(rsc.ui_mut()),)*], + [$($W.add(rsc).upgrade(rsc),)*], ) } } diff --git a/core/src/widget/mod.rs b/core/src/widget/mod.rs index b47cf67..a0f084c 100644 --- a/core/src/widget/mod.rs +++ b/core/src/widget/mod.rs @@ -61,27 +61,27 @@ pub trait WidgetFn: FnOnce(&mut State) -> W {} impl W> WidgetFn for F {} pub struct WidgetArr { - pub arr: [WidgetHandle; LEN], + pub arr: [StrongWidget; LEN], } impl WidgetArr { - pub fn new(arr: [WidgetHandle; LEN]) -> Self { + pub fn new(arr: [StrongWidget; LEN]) -> Self { Self { arr } } } pub trait WidgetOption { - fn get(self, state: &mut State) -> Option; + fn get(self, state: &mut State) -> Option; } impl WidgetOption for () { - fn get(self, _: &mut State) -> Option { + fn get(self, _: &mut State) -> Option { None } } -impl Option> WidgetOption for F { - fn get(self, state: &mut State) -> Option { +impl Option> WidgetOption for F { + fn get(self, state: &mut State) -> Option { self(state) } } diff --git a/core/src/widget/tag.rs b/core/src/widget/tag.rs index e7c9454..dc51221 100644 --- a/core/src/widget/tag.rs +++ b/core/src/widget/tag.rs @@ -1,19 +1,19 @@ use super::*; -use crate::HasUi; +use crate::UiRsc; use std::marker::Unsize; pub struct WidgetTag; -impl WidgetLike for W { +impl WidgetLike for W { type Widget = W; - fn add(self, rsc: &mut Rsc) -> WidgetRef { - rsc.ui_mut().widgets.add_weak(self) + fn add(self, rsc: &mut Rsc) -> WeakWidget { + rsc.add_widget(self) } } pub struct FnTag; -impl W> WidgetLike for F { +impl W> WidgetLike for F { type Widget = W; - fn add(self, rsc: &mut Rsc) -> WidgetRef { + fn add(self, rsc: &mut Rsc) -> WeakWidget { self(rsc).add(rsc) } } @@ -23,36 +23,38 @@ pub trait WidgetFnTrait { fn run(self, rsc: &mut Rsc) -> Self::Widget; } pub struct FnTraitTag; -impl> WidgetLike for T { +impl> WidgetLike for T { type Widget = T::Widget; #[track_caller] - fn add(self, rsc: &mut Rsc) -> WidgetRef { + fn add(self, rsc: &mut Rsc) -> WeakWidget { self.run(rsc).add(rsc) } } pub struct RefTag; -impl> WidgetLike for WidgetRef { +impl> WidgetLike + for WeakWidget +{ type Widget = W; - fn add(self, _: &mut Rsc) -> WidgetRef { + fn add(self, _: &mut Rsc) -> WeakWidget { self } } pub struct RefFnTag; -impl, F: FnOnce(&mut Rsc) -> WidgetRef> +impl, F: FnOnce(&mut Rsc) -> WeakWidget> WidgetLike for F { type Widget = W; - fn add(self, rsc: &mut Rsc) -> WidgetRef { + fn add(self, rsc: &mut Rsc) -> WeakWidget { self(rsc) } } pub struct ViewTag; -impl WidgetLike for V { +impl WidgetLike for V { type Widget = V::Widget; - fn add(self, _: &mut Rsc) -> WidgetRef { + fn add(self, _: &mut Rsc) -> WeakWidget { self.root() } } diff --git a/core/src/widget/view.rs b/core/src/widget/view.rs index 3e6bfe5..042f9b8 100644 --- a/core/src/widget/view.rs +++ b/core/src/widget/view.rs @@ -1,16 +1,16 @@ use std::marker::Unsize; -use crate::{Widget, WidgetRef}; +use crate::{Widget, WeakWidget}; pub trait WidgetView { type Widget: Widget + ?Sized + Unsize; - fn root(&self) -> WidgetRef; + fn root(&self) -> WeakWidget; } pub trait HasWidget { type Widget: Widget + ?Sized + Unsize; } -impl + ?Sized> HasWidget for WidgetRef { +impl + ?Sized> HasWidget for WeakWidget { type Widget = W; } diff --git a/core/src/widget/widgets.rs b/core/src/widget/widgets.rs index 751ddbf..19ecbeb 100644 --- a/core/src/widget/widgets.rs +++ b/core/src/widget/widgets.rs @@ -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, vec: SlotVec, send: Sender, + recv: Receiver, pub(crate) waiting: HashSet, } impl Widgets { - pub fn new(send: Sender) -> 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(&mut self, widget: W) -> WidgetHandle { + pub fn add_strong(&mut self, widget: W) -> StrongWidget { let id = self.vec.add(WidgetData::new(widget)); - WidgetHandle::new(id, self.send.clone()) + StrongWidget::new(id, self.send.clone()) } - pub fn add_weak(&mut self, widget: W) -> WidgetRef { + pub fn add_weak(&mut self, widget: W) -> WeakWidget { let id = self.vec.add(WidgetData::new(widget)); self.waiting.insert(id); - WidgetRef::new(id) + WeakWidget::new(id) } #[track_caller] - pub fn upgrade(&mut self, rf: WidgetRef) -> WidgetHandle { + pub fn upgrade(&mut self, rf: WeakWidget) -> StrongWidget { 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 std::ops::Index for Widgets +where + I::Widget: Sized + Widget, +{ + type Output = I::Widget; + + fn index(&self, id: I) -> &Self::Output { + self.get(&id).unwrap() + } +} + +impl std::ops::IndexMut for Widgets +where + I::Widget: Sized + Widget, +{ + fn index_mut(&mut self, id: I) -> &mut Self::Output { + self.get_mut(&id).unwrap() + } +} diff --git a/examples/tabs/main.rs b/examples/tabs/main.rs index 6bb1e37..fa90797 100644 --- a/examples/tabs/main.rs +++ b/examples/tabs/main.rs @@ -12,7 +12,7 @@ fn main() { #[derive(DefaultUiState)] pub struct Client { ui_state: DefaultUiState, - info: WidgetRef, + info: WeakWidget, } impl DefaultAppState for Client { @@ -147,7 +147,7 @@ impl DefaultAppState for Client { let main = WidgetPtr::new().add(rsc); let vals = Rc::new(RefCell::new((0, Vec::new()))); - let mut switch_button = |color, to: WidgetRef, label| { + let mut switch_button = |color, to: WeakWidget, label| { let to = to.upgrade(rsc); let vec = &mut vals.borrow_mut().1; let i = vec.len(); diff --git a/examples/view.rs b/examples/view.rs index 5c8bcc3..5557b72 100644 --- a/examples/view.rs +++ b/examples/view.rs @@ -14,7 +14,7 @@ type Rsc = DefaultRsc; #[derive(Clone, Copy, WidgetView)] struct Test { #[root] - root: WidgetRef, + root: WeakWidget, } impl Test { diff --git a/src/default/attr.rs b/src/default/attr.rs index fc0f933..f387d56 100644 --- a/src/default/attr.rs +++ b/src/default/attr.rs @@ -8,9 +8,9 @@ impl WidgetAttr for Selector where Rsc::State: HasDefaultUiState, { - type Input = WidgetRef; + type Input = WeakWidget; - fn run(rsc: &mut Rsc, container: WidgetRef, id: Self::Input) { + fn run(rsc: &mut Rsc, container: WeakWidget, id: Self::Input) { rsc.register_event(container, CursorSense::click_or_drag(), move |ctx, rsc| { let region = rsc.ui().window_region(&id).unwrap(); let id_pos = region.top_left; @@ -30,7 +30,7 @@ where { type Input = (); - fn run(rsc: &mut Rsc, id: WidgetRef, _: Self::Input) { + fn run(rsc: &mut Rsc, id: WeakWidget, _: Self::Input) { rsc.register_event(id, CursorSense::click_or_drag(), move |ctx, rsc| { select( rsc, @@ -47,7 +47,7 @@ where fn select( rsc: &mut impl HasUi, state: &mut impl HasDefaultUiState, - id: WidgetRef, + id: WeakWidget, pos: Vec2, size: Vec2, dragging: bool, diff --git a/src/default/mod.rs b/src/default/mod.rs index f41ab57..106e5b7 100644 --- a/src/default/mod.rs +++ b/src/default/mod.rs @@ -32,7 +32,7 @@ pub type Proxy = EventLoopProxy; pub struct DefaultUiState { pub renderer: UiRenderer, pub input: Input, - pub focus: Option>, + pub focus: Option>, pub clipboard: Clipboard, pub window: Arc, pub ime: usize, diff --git a/src/event.rs b/src/event.rs index 5cd0691..dfb3422 100644 --- a/src/event.rs +++ b/src/event.rs @@ -75,7 +75,7 @@ impl< } pub struct AsyncEventIdCtx { - pub widget: WidgetRef, + pub widget: WeakWidget, pub data: Data, pub task: TaskCtx, } diff --git a/src/widget/mask.rs b/src/widget/mask.rs index 5b16337..cc075e9 100644 --- a/src/widget/mask.rs +++ b/src/widget/mask.rs @@ -1,7 +1,7 @@ use crate::prelude::*; pub struct Masked { - pub inner: WidgetHandle, + pub inner: StrongWidget, } impl Widget for Masked { diff --git a/src/widget/position/align.rs b/src/widget/position/align.rs index c475b4b..1a6d6a5 100644 --- a/src/widget/position/align.rs +++ b/src/widget/position/align.rs @@ -1,7 +1,7 @@ use crate::prelude::*; pub struct Aligned { - pub inner: WidgetHandle, + pub inner: StrongWidget, pub align: Align, } diff --git a/src/widget/position/layer.rs b/src/widget/position/layer.rs index ef55139..fb2ced3 100644 --- a/src/widget/position/layer.rs +++ b/src/widget/position/layer.rs @@ -1,7 +1,7 @@ use crate::prelude::*; pub struct LayerOffset { - pub inner: WidgetHandle, + pub inner: StrongWidget, pub offset: usize, } diff --git a/src/widget/position/max_size.rs b/src/widget/position/max_size.rs index 83071d8..1a9aa39 100644 --- a/src/widget/position/max_size.rs +++ b/src/widget/position/max_size.rs @@ -1,7 +1,7 @@ use crate::prelude::*; pub struct MaxSize { - pub inner: WidgetHandle, + pub inner: StrongWidget, pub x: Option, pub y: Option, } diff --git a/src/widget/position/offset.rs b/src/widget/position/offset.rs index e7a19d8..da54f69 100644 --- a/src/widget/position/offset.rs +++ b/src/widget/position/offset.rs @@ -1,7 +1,7 @@ use crate::prelude::*; pub struct Offset { - pub inner: WidgetHandle, + pub inner: StrongWidget, pub amt: UiVec2, } diff --git a/src/widget/position/pad.rs b/src/widget/position/pad.rs index 26554ee..5619d0f 100644 --- a/src/widget/position/pad.rs +++ b/src/widget/position/pad.rs @@ -2,7 +2,7 @@ use crate::prelude::*; pub struct Pad { pub padding: Padding, - pub inner: WidgetHandle, + pub inner: StrongWidget, } impl Widget for Pad { diff --git a/src/widget/position/scroll.rs b/src/widget/position/scroll.rs index c414b11..c789acc 100644 --- a/src/widget/position/scroll.rs +++ b/src/widget/position/scroll.rs @@ -1,7 +1,7 @@ use crate::prelude::*; pub struct Scroll { - inner: WidgetHandle, + inner: StrongWidget, axis: Axis, amt: f32, snap_end: bool, @@ -41,7 +41,7 @@ impl Widget for Scroll { } impl Scroll { - pub fn new(inner: WidgetHandle, axis: Axis) -> Self { + pub fn new(inner: StrongWidget, axis: Axis) -> Self { Self { inner, axis, diff --git a/src/widget/position/sized.rs b/src/widget/position/sized.rs index 8aed65e..aa1fc58 100644 --- a/src/widget/position/sized.rs +++ b/src/widget/position/sized.rs @@ -1,7 +1,7 @@ use crate::prelude::*; pub struct Sized { - pub inner: WidgetHandle, + pub inner: StrongWidget, pub x: Option, pub y: Option, } diff --git a/src/widget/position/span.rs b/src/widget/position/span.rs index 9c4c802..ad4f932 100644 --- a/src/widget/position/span.rs +++ b/src/widget/position/span.rs @@ -2,7 +2,7 @@ use crate::prelude::*; use std::marker::PhantomData; pub struct Span { - pub children: Vec, + pub children: Vec, pub dir: Dir, pub gap: f32, } @@ -62,11 +62,11 @@ impl Span { self } - pub fn push(&mut self, w: WidgetHandle) { + pub fn push(&mut self, w: StrongWidget) { self.children.push(w); } - pub fn pop(&mut self) -> Option { + pub fn pop(&mut self) -> Option { self.children.pop() } @@ -193,7 +193,7 @@ impl, Tag> } impl std::ops::Deref for Span { - type Target = Vec; + type Target = Vec; fn deref(&self) -> &Self::Target { &self.children diff --git a/src/widget/position/stack.rs b/src/widget/position/stack.rs index 44f751a..fb4a591 100644 --- a/src/widget/position/stack.rs +++ b/src/widget/position/stack.rs @@ -3,7 +3,7 @@ use std::marker::PhantomData; use crate::prelude::*; pub struct Stack { - pub children: Vec, + pub children: Vec, pub size: StackSize, } diff --git a/src/widget/ptr.rs b/src/widget/ptr.rs index ebe8cb9..1e6241b 100644 --- a/src/widget/ptr.rs +++ b/src/widget/ptr.rs @@ -2,7 +2,7 @@ use crate::prelude::*; use std::marker::{Sized, Unsize}; pub struct WidgetPtr { - pub inner: Option, + pub inner: Option, } impl Widget for WidgetPtr { @@ -38,14 +38,14 @@ impl WidgetPtr { inner: Default::default(), } } - pub fn set>(&mut self, to: WidgetHandle) { + pub fn set>(&mut self, to: StrongWidget) { self.inner = Some(to) } pub fn replace>( &mut self, - to: WidgetHandle, - ) -> Option { + to: StrongWidget, + ) -> Option { self.inner.replace(to) } } diff --git a/src/widget/text/mod.rs b/src/widget/text/mod.rs index 54375a1..cc9c94f 100644 --- a/src/widget/text/mod.rs +++ b/src/widget/text/mod.rs @@ -22,11 +22,11 @@ pub struct TextView { // cache tex: Option, width: Option, - pub hint: Option, + pub hint: Option, } impl TextView { - pub fn new(buf: TextBuffer, attrs: TextAttrs, hint: Option) -> Self { + pub fn new(buf: TextBuffer, attrs: TextAttrs, hint: Option) -> Self { Self { attrs: attrs.into(), buf: buf.into(), diff --git a/src/widget/trait_fns.rs b/src/widget/trait_fns.rs index b526d40..87af7fe 100644 --- a/src/widget/trait_fns.rs +++ b/src/widget/trait_fns.rs @@ -125,7 +125,7 @@ widget_trait! { |state| self.add(state) } - fn set_ptr(self, ptr: WidgetRef, state: &mut Rsc) { + fn set_ptr(self, ptr: WeakWidget, state: &mut Rsc) { let id = self.add_strong(state); state.ui_mut()[ptr].inner = Some(id); }