use super::*; use crate::prelude::*; // these methods should "not require any context" (require unit) because they're in core widget_trait! { pub trait CoreWidget; fn pad(self, padding: impl Into) -> impl WidgetFn { |state| Pad { padding: padding.into(), inner: self.add_strong(state), exact_region: false, } } fn align(self, align: impl Into) -> impl WidgetFn { move |state| Aligned { inner: self.add_strong(state), align: align.into(), } } fn center(self) -> impl WidgetFn { self.align(Align::CENTER) } fn label(self, label: impl Into) -> impl WidgetIdFn { |state| { let id = self.add(state); state.ui_mut().widgets.set_label(id, label.into()); id } } fn sized(self, size: impl Into) -> impl WidgetFn { let size = size.into(); move |state| Sized { inner: self.add_strong(state), x: Some(size.x), y: Some(size.y), } } fn max_width(self, len: impl Into) -> impl WidgetFn { let len = len.into(); move |state| MaxSize { inner: self.add_strong(state), x: Some(len), y: None, } } fn max_height(self, len: impl Into) -> impl WidgetFn { let len = len.into(); move |state| MaxSize { inner: self.add_strong(state), x: None, y: Some(len), } } fn width(self, len: impl Into) -> impl WidgetFn { let len = len.into(); move |state| Sized { inner: self.add_strong(state), x: Some(len), y: None, } } fn height(self, len: impl Into) -> impl WidgetFn { let len = len.into(); move |state| Sized { inner: self.add_strong(state), x: None, y: Some(len), } } fn offset(self, amt: impl Into) -> impl WidgetFn { move |state| Offset { inner: self.add_strong(state), amt: amt.into(), } } /// Wrap this widget in a [`ScrollArea`] that pans along `axis`, with /// the wheel and a finger drag both registered -- how anything with a /// fixed layout becomes scrollable. /// /// `pin` says which end the area opens at and clings to as its content /// grows, and it is spelled out rather than defaulted because the two /// cases are not variations on each other: a composer wants the end, /// where what is being typed is, and a code fence opened at the end of /// its longest line, which is the middle of a word (seen in /// `iris/run-headless.sh phone`, 2026-09-08). /// /// One method with the axis and the pin passed in, rather than the /// three named variants this used to be (Iris, 2026-09-08: "can we /// make both scroll methods become `.scrollable`, and it takes an axis /// and a pin instead of having two?"). A code fence pans across its /// own long lines exactly the way a transcript pans down its rows, so /// the two are one mechanism with the direction passed in -- /// `DragArbiter::on` is the other half. /// /// A [`LazySpan`] has an inherent `scrollable` of its own that this /// does not reach: it owns a controller already and must not be /// wrapped in an area that would slide it about as a lump. fn scrollable(self, axis: Axis, pin: Pin) -> impl WidgetIdFn where Rsc: HasEvents { move |state| { let area = ScrollArea::new(self.add_strong(state), axis, pin); scroll_senses(area, axis)(state) } } fn masked(self) -> impl WidgetFn { move |state| Masked { shape: None, inner: self.add_strong(state), } } /// Clip to `shape` rather than to a plain box: `shape` is drawn /// behind this widget, filling the same region, and what clips is the /// primitive it drew -- so a rounded background and the corner its /// content is cut to are one rect, with no radius passed twice. /// Replaces `.masked().background(w)`, which drew the two but clipped /// to the box. fn masked_by(self, shape: impl WidgetLike) -> impl WidgetFn { move |state| Masked { shape: Some(shape.add_strong(state)), inner: self.add_strong(state), } } fn background(self, w: impl WidgetLike) -> impl WidgetFn { move |state| Stack { children: vec![w.add_strong(state), self.add_strong(state)], size: StackSize::Child(1), } } fn foreground(self, w: impl WidgetLike) -> impl WidgetFn { move |state| Stack { children: vec![self.add_strong(state), w.add_strong(state)], size: StackSize::Child(0), } } fn layer_offset(self, offset: usize) -> impl WidgetFn { move |state| LayerOffset { inner: self.add_strong(state), offset, } } fn to_any(self) -> impl WidgetIdFn { |state| self.add(state) } fn set_ptr(self, ptr: WeakWidget, state: &mut Rsc) { let id = self.add_strong(state); state.ui_mut().widgets[ptr].inner = Some(id); } } pub trait CoreWidgetArr, Tag> { fn span(self, dir: Dir) -> SpanBuilder; fn stack(self) -> StackBuilder; } impl, Tag> CoreWidgetArr for Wa { fn span(self, dir: Dir) -> SpanBuilder { SpanBuilder::new(self, dir) } fn stack(self) -> StackBuilder { StackBuilder::new(self) } }