feather_ui/
lib.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2025 Fundament Research Institute <https://fundament.institute>
3
4//! # Reactive Data-Driven UI
5//!
6//! Feather is a reactive data-driven UI framework that only mutates application state in
7//! response to user inputs or events, using event streams and reactive properties, and
8//! represents application state using persistent data structures, which then efficiently
9//! render only the parts of the UI that changed using either a standard GPU compositor
10//! or custom shaders.
11//!
12//! Examples can be found in [feather-ui/examples](feather-ui/examples), and can be run
13//! via `cargo run --example <example_name>`.
14
15extern crate alloc;
16
17pub mod color;
18pub mod component;
19mod editor;
20pub mod event;
21pub mod graphics;
22pub mod input;
23pub mod layout;
24#[cfg(feature = "lua")]
25pub mod lua;
26pub mod persist;
27mod propbag;
28pub mod render;
29pub mod resource;
30mod rtree;
31mod shaders;
32pub mod text;
33pub mod util;
34
35use crate::component::window::Window;
36use crate::graphics::Driver;
37use crate::render::atlas::AtlasKind;
38use crate::render::compositor::CompositorView;
39use bytemuck::NoUninit;
40use component::window::WindowStateMachine;
41use component::{Component, StateMachineWrapper};
42use core::f32;
43use dyn_clone::DynClone;
44use eyre::OptionExt;
45pub use guillotiere::euclid;
46use guillotiere::euclid::{Point2D, Size2D, Vector2D};
47use parking_lot::RwLock;
48use persist::FnPersist2;
49use smallvec::SmallVec;
50use std::any::Any;
51use std::cmp::PartialEq;
52use std::collections::{BTreeMap, HashMap};
53use std::convert::Infallible;
54use std::ffi::c_void;
55use std::fmt::Display;
56use std::hash::{Hash, Hasher};
57use std::marker::PhantomData;
58use std::ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign};
59use std::sync::atomic::AtomicU64;
60use std::sync::{Arc, mpsc};
61use wgpu::{InstanceDescriptor, InstanceFlags};
62use wide::{CmpGe, CmpGt, f32x4};
63use winit::event::WindowEvent;
64use winit::event_loop::{ActiveEventLoop, EventLoop};
65use winit::window::WindowId;
66pub use {cosmic_text, eyre, im, notify, wgpu, wide, winit};
67
68type Mat4x4 = euclid::default::Transform3D<f32>;
69
70#[cfg(feature = "lua")]
71pub use mlua;
72
73/// While the ID scope provides a .next() method to generate a new, unique ID, this
74/// macro allows you to generate a unique ID with the file name and line embedded in
75/// it. This helps when debugging, because it'll tell you exactly what line of code
76/// generated the element causing the problem.
77///
78/// # Examples:
79///
80/// ```
81/// use feather_ui::{gen_id, ScopeID};
82///
83/// fn app(id: &mut ScopeID) {
84///   let unique_id = gen_id!(id); // unique_id now contains the source location where gen_id! was invoked.
85/// }
86/// ```
87#[macro_export]
88macro_rules! gen_id {
89    ($idx:expr) => {
90        $idx.child($crate::DataID::Named(concat!(file!(), ":", line!())))
91    };
92    ($idx:expr, $i:expr) => {
93        $idx.child($crate::DataID::Int($i as i64))
94    };
95}
96
97use std::any::TypeId;
98#[derive(thiserror::Error, Debug)]
99pub enum Error {
100    #[error("Not an error, this component simply has no layout state.")]
101    Stateless,
102    #[error("Enum object didn't match tag {0}! Expected {1:?} but got {2:?}")]
103    MismatchedEnumTag(u64, TypeId, TypeId),
104    #[error("Invalid enum tag: {0}")]
105    InvalidEnumTag(u64),
106    #[error("Event handler didn't handle this method.")]
107    UnhandledEvent,
108    #[error("Frame aborted due to pending Texture Atlas resize.")]
109    ResizeTextureAtlas(u32, crate::render::atlas::AtlasKind),
110    #[error("Internal texture atlas reservation failure.")]
111    AtlasReservationFailure,
112    #[error("Internal texture atlas cache lookup failure.")]
113    AtlasCacheFailure,
114    #[error("Internal glyph render failure.")]
115    GlyphRenderFailure,
116    #[error("Internal glyph cache lookup failure.")]
117    GlyphCacheFailure,
118    #[error("An assumption about internal state was incorrect.")]
119    InternalFailure,
120    #[error("A filesystem error occurred: {0}")]
121    FileError(std::io::Error),
122    #[error("An error happened when loading a resource: {0:?}")]
123    ResourceError(Box<dyn std::fmt::Debug + Send + Sync>),
124    #[error(
125        "The resource was in an unrecognized format. Are you sure you enabled the right feature flags?"
126    )]
127    UnknownResourceFormat,
128    #[error("An index was out of range: {0}")]
129    OutOfRange(usize),
130    #[error("Type mismatch occured when attempting a downcast that should never fail!")]
131    RuntimeTypeMismatch,
132}
133
134impl From<std::io::Error> for Error {
135    fn from(value: std::io::Error) -> Self {
136        Self::FileError(value)
137    }
138}
139
140/// Represents an axis that is "unsized", which is roughly equivelent to CSS `auto`. It will
141/// set the size of the axis either to the size of the children, if the layout has any, or to
142/// the intrinsic size of the element, if one exists. Otherwise it will evaluate to 0.
143pub const UNSIZED_AXIS: f32 = f32::MAX;
144
145/// The standard base DPI, by convention, is 96, which corresponds to a scale factor of 1.0 -
146/// all other DPI values are divided by this to get the appropriate scale factor.
147pub const BASE_DPI: RelDim = RelDim::new(96.0, 96.0);
148
149const MINUS_BOTTOMRIGHT: f32x4 = f32x4::new([1.0, 1.0, -1.0, -1.0]);
150
151/// This macro automates away some boilerplate necessary to make a vector of children that
152/// can be passed into a component. The first argument is the required layout of the parent,
153/// followed by a list of children to include (by value).
154///
155/// # Examples
156///
157/// ```
158/// use feather_ui::{DRect, FILL_DRECT, gen_id, color::sRGB, wide, UNSIZED_AXIS, DAbsPoint, AbsRect, APP_SOURCE_ID};
159/// use feather_ui::layout::fixed;
160/// use feather_ui::component::{region::Region, shape};
161/// use std::sync::Arc;
162///
163/// let rect = shape::round_rect::<DRect>(
164///     gen_id!(Arc::new(APP_SOURCE_ID)),
165///     FILL_DRECT,
166///     0.0,
167///     0.0,
168///     wide::f32x4::splat(10.0),
169///     sRGB::new(0.2, 0.7, 0.4, 1.0),
170///     sRGB::transparent(),
171///     DAbsPoint::zero(),
172/// );
173/// let region = Region::<DRect>::new(
174///     gen_id!(Arc::new(APP_SOURCE_ID)),
175///      AbsRect::new(45.0, 45.0, 0.0, 0.0).into(),
176///     feather_ui::children![fixed::Prop, rect],
177/// );
178/// ```
179#[macro_export]
180macro_rules! children {
181    () => { [] };
182    ($prop:path, $($param:expr),+ $(,)?) => { $crate::im::Vector::from_iter([$(Some(Box::new($param) as Box<$crate::component::ChildOf<dyn $prop>>)),+]) };
183}
184
185#[macro_export]
186macro_rules! handlers {
187    () => { [] };
188    ($app:path, $($param:ident),+ $(,)?) => { Vec::from_iter([$((stringify!($param).to_string(), Box::new($param) as $crate::AppEvent<$app>)),+]) };
189}
190
191#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
192/// Represents display-independent pixels, or logical units
193pub struct Logical {}
194#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
195/// Represents relative values
196pub struct Relative {}
197#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
198/// Represents an actual pixel
199pub struct Pixel {}
200#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
201/// Represents a combination of DIP and Pixels that have been resolved for the current DPI
202pub struct Resolved {}
203
204/// A 2D point in logical units (display-independent pixels)
205pub type AbsPoint = Point2D<f32, Logical>;
206/// A 2D point in physical device pixels
207pub type PxPoint = Point2D<f32, Pixel>;
208/// A 2D point in relative coordinates
209pub type RelPoint = Point2D<f32, Relative>;
210/// A 2D point in resolved physical pixels that hasn't yet been combined with it's paired relative coordinates.
211pub type ResPoint = Point2D<f32, Resolved>;
212
213/// A 2D vector in logical units (display-independent pixels)
214pub type AbsVector = Vector2D<f32, Logical>;
215/// A 2D vector in physical device pixels
216pub type PxVector = Vector2D<f32, Pixel>;
217/// A 2D vector in relative coordinates
218pub type RelVector = Vector2D<f32, Relative>;
219/// A 2D vector in resolved physical pixels that hasn't yet been combined with it's paired relative coordinates.
220pub type ResVector = Vector2D<f32, Resolved>;
221
222/// A 2D dimension (or size) in logical units (display-independent pixels)
223pub type AbsDim = Size2D<f32, Logical>;
224/// A 2D dimension (or size) in physical device pixels
225pub type PxDim = Size2D<f32, Pixel>;
226/// A 2D dimension (or size) in relative coordinates
227pub type RelDim = Size2D<f32, Relative>;
228/// A 2D dimension (or size) in resolved physical pixels that hasn't yet been combined with it's paired relative coordinates.
229pub type ResDim = Size2D<f32, Resolved>;
230
231/// Internal trait for "unresolving" a set of physical pixels into logical units.
232trait UnResolve<U> {
233    fn unresolve(self, dpi: RelDim) -> U;
234}
235
236impl UnResolve<AbsVector> for PxVector {
237    fn unresolve(self, dpi: RelDim) -> AbsVector {
238        AbsVector::new(self.x / dpi.width, self.y / dpi.height)
239    }
240}
241
242impl UnResolve<AbsPoint> for PxPoint {
243    fn unresolve(self, dpi: RelDim) -> AbsPoint {
244        AbsPoint::new(self.x / dpi.width, self.y / dpi.height)
245    }
246}
247
248/// Internal trait for allowing conversions between foreign types that we're not
249/// allowed to implement From or Into on.
250trait Convert<U> {
251    fn to(self) -> U;
252}
253
254impl Convert<Size2D<u32, Pixel>> for winit::dpi::PhysicalSize<u32> {
255    fn to(self) -> Size2D<u32, Pixel> {
256        Size2D::<u32, Pixel>::new(self.width, self.height)
257    }
258}
259
260impl Convert<Size2D<u32, Logical>> for winit::dpi::LogicalSize<u32> {
261    fn to(self) -> Size2D<u32, Logical> {
262        Size2D::<u32, Logical>::new(self.width, self.height)
263    }
264}
265
266impl Convert<Point2D<f32, Pixel>> for winit::dpi::PhysicalPosition<f32> {
267    fn to(self) -> Point2D<f32, Pixel> {
268        Point2D::<f32, Pixel>::new(self.x, self.y)
269    }
270}
271
272impl Convert<Point2D<f64, Pixel>> for winit::dpi::PhysicalPosition<f64> {
273    fn to(self) -> Point2D<f64, Pixel> {
274        Point2D::<f64, Pixel>::new(self.x, self.y)
275    }
276}
277
278/// Represents a 2D Rectangle, similar to the Euclid rectangle, but SSE optimized
279/// and uses a LTRB absolute representation, instead of a position and a size.
280#[derive(Copy, Clone, Debug, Default, PartialEq)]
281pub struct Rect<U> {
282    pub v: f32x4,
283    #[doc(hidden)]
284    pub _unit: PhantomData<U>,
285}
286
287/// A 2D rectangle in logical units (display-independent pixels)
288pub type AbsRect = Rect<Logical>;
289/// A 2D rectangle in physical pixels
290pub type PxRect = Rect<Pixel>;
291/// A 2D rectangle in relative values
292pub type RelRect = Rect<Relative>;
293/// A 2D rectangle in resolved pixels that haven't been merged with their paired relative component
294pub type ResRect = Rect<Resolved>;
295
296unsafe impl<U: Copy + 'static> NoUninit for Rect<U> {}
297
298pub const ZERO_RECT: AbsRect = AbsRect::zero();
299
300impl<U> Rect<U> {
301    #[inline]
302    pub const fn new(left: f32, top: f32, right: f32, bottom: f32) -> Self {
303        Self {
304            v: f32x4::new([left, top, right, bottom]),
305            _unit: PhantomData,
306        }
307    }
308
309    pub const fn splat(x: f32) -> Self {
310        Self {
311            v: f32x4::new([x, x, x, x]), // f32x4::splat isn't a constant function (for some reason)
312            _unit: PhantomData,
313        }
314    }
315
316    #[inline]
317    pub const fn corners(topleft: Point2D<f32, U>, bottomright: Point2D<f32, U>) -> Self {
318        Self {
319            v: f32x4::new([topleft.x, topleft.y, bottomright.x, bottomright.y]),
320            _unit: PhantomData,
321        }
322    }
323
324    #[inline]
325    pub fn contains(&self, p: Point2D<f32, U>) -> bool {
326        //let test: u32x4 = bytemuck::cast(f32x4::new([p.x, p.y, p.x, p.y]).cmp_ge(self.0));
327
328        f32x4::new([p.x, p.y, p.x, p.y]).cmp_ge(self.v).move_mask() == 0b0011
329
330        /*p.x >= self.0[0]
331        && p.y >= self.0[1]
332        && p.x < self.0[2]
333        && p.y < self.0[3]*/
334    }
335
336    #[inline]
337    pub fn collides(&self, rhs: &Self) -> bool {
338        let r = rhs.v.as_array_ref();
339        f32x4::new([r[2], r[3], -r[0], -r[1]])
340            .cmp_gt(self.v * MINUS_BOTTOMRIGHT)
341            .all()
342
343        /*rhs.0[2] > self.0[0]
344        && rhs.0[3] > self.0[1]
345        && rhs.0[0] < self.0[2]
346        && rhs.0[1] < self.0[3]*/
347    }
348
349    #[inline]
350    pub fn intersect(&self, rhs: Self) -> Self {
351        let rect =
352            (self.v * MINUS_BOTTOMRIGHT).fast_max(rhs.v * MINUS_BOTTOMRIGHT) * MINUS_BOTTOMRIGHT;
353
354        // This rect is potentially degenerate, where topleft > bottomright, so we have to guard against this.
355        let a = rect.to_array();
356        Self {
357            v: rect.fast_max(f32x4::new([a[0], a[1], a[0], a[1]])),
358            _unit: PhantomData,
359        }
360
361        /*let r = rhs.0.as_array_ref();
362        let l = self.0.as_array_ref();
363        AbsRect::new(
364            l[0].max(r[0]),
365            l[1].max(r[1]),
366            l[2].min(r[2]),
367            l[3].min(r[3]),
368        )*/
369    }
370
371    #[inline]
372    pub fn extend(&self, rhs: Self) -> Self {
373        /*AbsRect {
374            topleft: self.topleft().min_by_component(rhs.topleft()),
375            bottomright: self.bottomright().max_by_component(rhs.bottomright()),
376        }*/
377        Self {
378            v: (self.v * MINUS_BOTTOMRIGHT).fast_min(rhs.v * MINUS_BOTTOMRIGHT) * MINUS_BOTTOMRIGHT,
379            _unit: PhantomData,
380        }
381    }
382
383    #[inline]
384    pub fn topleft(&self) -> Point2D<f32, U> {
385        let ltrb = self.v.as_array_ref();
386        Point2D::new(ltrb[0], ltrb[1])
387    }
388
389    #[inline]
390    pub fn set_topleft(&mut self, v: Point2D<f32, U>) {
391        let ltrb = self.v.as_array_mut();
392        ltrb[0] = v.x;
393        ltrb[1] = v.y;
394    }
395
396    #[inline]
397    pub fn bottomright(&self) -> Point2D<f32, U> {
398        let ltrb = self.v.as_array_ref();
399        Point2D::new(ltrb[2], ltrb[3])
400    }
401
402    #[inline]
403    pub fn set_bottomright(&mut self, v: Point2D<f32, U>) {
404        let ltrb = self.v.as_array_mut();
405        ltrb[2] = v.x;
406        ltrb[3] = v.y;
407    }
408
409    #[inline]
410    pub fn dim(&self) -> Size2D<f32, U> {
411        let ltrb = self.v.as_array_ref();
412        Size2D::new(ltrb[2] - ltrb[0], ltrb[3] - ltrb[1])
413    }
414
415    #[inline]
416    pub const fn zero() -> Self {
417        Self {
418            v: f32x4::ZERO,
419            _unit: PhantomData,
420        }
421    }
422
423    #[inline]
424    pub const fn unit() -> Self {
425        Self {
426            v: f32x4::new([0.0, 0.0, 1.0, 1.0]),
427            _unit: PhantomData,
428        }
429    }
430
431    /// Discard the units
432    #[inline]
433    pub fn to_untyped(self) -> PxRect {
434        self.cast_unit()
435    }
436
437    /// Cast the unit
438    #[inline]
439    pub fn cast_unit<V>(self) -> Rect<V> {
440        Rect::<V> {
441            v: self.v,
442            _unit: PhantomData,
443        }
444    }
445}
446
447impl<U> Display for Rect<U> {
448    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
449        let ltrb = self.v.as_array_ref();
450        write!(
451            f,
452            "Rect[({},{});({},{})]",
453            ltrb[0], ltrb[1], ltrb[2], ltrb[3]
454        )
455    }
456}
457
458impl<U> From<[f32; 4]> for Rect<U> {
459    #[inline]
460    fn from(value: [f32; 4]) -> Self {
461        Self {
462            v: f32x4::new(value),
463            _unit: PhantomData,
464        }
465    }
466}
467
468#[inline]
469const fn splat_point<U>(v: Point2D<f32, U>) -> f32x4 {
470    f32x4::new([v.x, v.y, v.x, v.y])
471}
472
473#[inline]
474const fn splat_size<U>(v: Size2D<f32, U>) -> f32x4 {
475    f32x4::new([v.width, v.height, v.width, v.height])
476}
477
478impl<U> Add<Point2D<f32, U>> for Rect<U> {
479    type Output = Self;
480
481    #[inline]
482    fn add(self, rhs: Point2D<f32, U>) -> Self::Output {
483        Self {
484            v: self.v + splat_point(rhs),
485            _unit: PhantomData,
486        }
487    }
488}
489
490impl<U> AddAssign<Point2D<f32, U>> for Rect<U> {
491    #[inline]
492    fn add_assign(&mut self, rhs: Point2D<f32, U>) {
493        self.v += splat_point(rhs)
494    }
495}
496
497impl<U> Add<Vector2D<f32, U>> for Rect<U> {
498    type Output = Self;
499
500    #[inline]
501    fn add(self, rhs: Vector2D<f32, U>) -> Self::Output {
502        Self {
503            v: self.v + splat_point(rhs.to_point()),
504            _unit: PhantomData,
505        }
506    }
507}
508
509impl<U> AddAssign<Vector2D<f32, U>> for Rect<U> {
510    #[inline]
511    fn add_assign(&mut self, rhs: Vector2D<f32, U>) {
512        self.v += splat_point(rhs.to_point())
513    }
514}
515
516impl<U> Sub<Point2D<f32, U>> for Rect<U> {
517    type Output = Self;
518
519    #[inline]
520    fn sub(self, rhs: Point2D<f32, U>) -> Self::Output {
521        Self {
522            v: self.v - splat_point(rhs),
523            _unit: PhantomData,
524        }
525    }
526}
527
528impl<U> SubAssign<Point2D<f32, U>> for Rect<U> {
529    #[inline]
530    fn sub_assign(&mut self, rhs: Point2D<f32, U>) {
531        self.v -= splat_point(rhs)
532    }
533}
534
535impl<U> Neg for Rect<U> {
536    type Output = Rect<U>;
537
538    fn neg(self) -> Self::Output {
539        Self::Output {
540            v: -self.v,
541            _unit: PhantomData,
542        }
543    }
544}
545
546impl<U> From<Size2D<f32, U>> for Rect<U> {
547    fn from(value: Size2D<f32, U>) -> Self {
548        Self {
549            v: f32x4::new([0.0, 0.0, value.width, value.height]),
550            _unit: PhantomData,
551        }
552    }
553}
554
555/// A perimeter has the same top/left/right/bottom elements as a rectangle, but when
556/// used in calculations, the bottom and right elements are subtracted, not added.
557#[derive(Copy, Clone, Debug, Default, PartialEq)]
558pub struct Perimeter<U> {
559    pub v: f32x4,
560    #[doc(hidden)]
561    pub _unit: PhantomData<U>,
562}
563
564impl<U> Perimeter<U> {
565    #[inline]
566    pub fn topleft(&self) -> Size2D<f32, U> {
567        let ltrb = self.v.as_array_ref();
568        Size2D::<f32, U> {
569            width: ltrb[0],
570            height: ltrb[1],
571            _unit: PhantomData,
572        }
573    }
574
575    #[inline]
576    pub fn bottomright(&self) -> Size2D<f32, U> {
577        let ltrb = self.v.as_array_ref();
578        Size2D::<f32, U> {
579            width: ltrb[2],
580            height: ltrb[3],
581            _unit: PhantomData,
582        }
583    }
584
585    /// Discard the units
586    #[inline]
587    pub fn to_untyped(self) -> Perimeter<euclid::UnknownUnit> {
588        self.cast_unit()
589    }
590
591    /// Cast the unit
592    #[inline]
593    pub fn cast_unit<V>(self) -> Perimeter<V> {
594        Perimeter::<V> {
595            v: self.v,
596            _unit: PhantomData,
597        }
598    }
599}
600
601pub type PxPerimeter = Perimeter<Pixel>;
602
603impl<U> Add<Perimeter<U>> for Rect<U> {
604    type Output = Self;
605
606    #[inline]
607    fn add(self, rhs: Perimeter<U>) -> Self::Output {
608        Self {
609            v: self.v + (rhs.v * MINUS_BOTTOMRIGHT),
610            _unit: PhantomData,
611        }
612    }
613}
614
615impl<U> AddAssign<Perimeter<U>> for AbsRect {
616    #[inline]
617    fn add_assign(&mut self, rhs: Perimeter<U>) {
618        self.v += rhs.v * MINUS_BOTTOMRIGHT
619    }
620}
621
622#[derive(Copy, Clone, Debug, Default, PartialEq)]
623/// A rectangle with both pixel and display independent units, but no relative component.
624pub struct DAbsRect {
625    dp: AbsRect,
626    px: PxRect,
627}
628
629pub const ZERO_DABSRECT: DAbsRect = DAbsRect {
630    dp: AbsRect::zero(),
631    px: PxRect::zero(),
632};
633
634impl DAbsRect {
635    fn resolve(&self, dpi: RelDim) -> PxRect {
636        PxRect {
637            v: self.px.v + (self.dp.v * splat_size(dpi)),
638            _unit: PhantomData,
639        }
640    }
641
642    fn as_perimeter(&self, dpi: RelDim) -> PxPerimeter {
643        PxPerimeter {
644            v: self.resolve(dpi).v,
645            _unit: PhantomData,
646        }
647    }
648}
649
650impl From<AbsRect> for DAbsRect {
651    fn from(value: AbsRect) -> Self {
652        DAbsRect {
653            dp: value,
654            px: PxRect::zero(),
655        }
656    }
657}
658
659impl From<PxRect> for DAbsRect {
660    fn from(value: PxRect) -> Self {
661        DAbsRect {
662            dp: AbsRect::zero(),
663            px: value,
664        }
665    }
666}
667
668impl Neg for DAbsRect {
669    type Output = DAbsRect;
670
671    fn neg(self) -> Self::Output {
672        Self::Output {
673            dp: -self.dp,
674            px: -self.px,
675        }
676    }
677}
678
679#[derive(Copy, Clone, Debug, Default, PartialEq)]
680/// A point with both pixel and display independent units, but no relative component. Must be
681/// constructed manually or from a [`PxPoint`] or [`AbsPoint`]. This is commonly used in DPI
682/// sensitive values that could theoretically have pixels, or logical units, or both, but where
683/// a relative value doesn't make any sense (such as the intrinsic size of a shape).
684///
685/// # Examples
686/// ```
687/// use feather_ui::{DAbsPoint, AbsPoint, PxPoint, RelPoint};
688/// let foo: DAbsPoint = AbsPoint::new(1.0,2.0).into();
689///
690/// let bar: DAbsPoint = PxPoint::new(2.0,3.0).into();
691///
692/// let foobar = foo + bar;
693///
694/// let test = DAbsPoint{
695///     px: PxPoint::new(1.0,2.0),
696///     dp: AbsPoint::new(1.0,4.0),
697/// };
698///
699/// let bartest = bar + test;
700/// ```
701pub struct DAbsPoint {
702    pub dp: AbsPoint,
703    pub px: PxPoint,
704}
705
706impl DAbsPoint {
707    pub const fn zero() -> Self {
708        Self {
709            dp: AbsPoint::new(0.0, 0.0),
710            px: PxPoint::new(0.0, 0.0),
711        }
712    }
713
714    pub const fn unit() -> Self {
715        Self {
716            dp: AbsPoint::new(1.0, 1.0),
717            px: PxPoint::new(1.0, 1.0),
718        }
719    }
720
721    fn resolve(&self, dpi: RelDim) -> ResPoint {
722        ResPoint {
723            x: self.px.x + (self.dp.x * dpi.width),
724            y: self.px.y + (self.dp.y * dpi.height),
725            _unit: PhantomData,
726        }
727        //self.px + resolve_point(self.dp, dpi)
728    }
729}
730
731impl From<AbsPoint> for DAbsPoint {
732    fn from(value: AbsPoint) -> Self {
733        DAbsPoint {
734            dp: value,
735            px: PxPoint::zero(),
736        }
737    }
738}
739
740impl From<PxPoint> for DAbsPoint {
741    fn from(value: PxPoint) -> Self {
742        DAbsPoint {
743            dp: AbsPoint::zero(),
744            px: value,
745        }
746    }
747}
748
749impl Add<DAbsPoint> for DAbsPoint {
750    type Output = DAbsPoint;
751
752    fn add(self, rhs: DAbsPoint) -> Self::Output {
753        Self::Output {
754            dp: self.dp + rhs.dp.to_vector(),
755            px: self.px + rhs.px.to_vector(),
756        }
757    }
758}
759
760impl AddAssign<DAbsPoint> for DAbsPoint {
761    fn add_assign(&mut self, rhs: DAbsPoint) {
762        self.dp += rhs.dp.to_vector();
763        self.px += rhs.px.to_vector();
764    }
765}
766
767impl Neg for DAbsPoint {
768    type Output = DAbsPoint;
769
770    fn neg(self) -> Self::Output {
771        Self::Output {
772            dp: -self.dp,
773            px: -self.px,
774        }
775    }
776}
777
778#[inline]
779pub fn build_aabb<U>(a: Point2D<f32, U>, b: Point2D<f32, U>) -> Rect<U> {
780    Rect::<U>::corners(a.min(b), a.max(b))
781}
782
783#[derive(Copy, Clone, Debug, Default, PartialEq)]
784/// Partially resolved unified coordinate
785pub struct UPoint(f32x4);
786
787pub const ZERO_UPOINT: UPoint = UPoint(f32x4::ZERO);
788
789impl UPoint {
790    #[inline]
791    pub const fn new(abs: ResPoint, rel: RelPoint) -> Self {
792        Self(f32x4::new([abs.x, abs.y, rel.x, rel.y]))
793    }
794    #[inline]
795    pub fn abs(&self) -> ResPoint {
796        let ltrb = self.0.as_array_ref();
797        ResPoint {
798            x: ltrb[0],
799            y: ltrb[1],
800            _unit: PhantomData,
801        }
802    }
803    #[inline]
804    pub fn rel(&self) -> RelPoint {
805        let ltrb = self.0.as_array_ref();
806        RelPoint {
807            x: ltrb[2],
808            y: ltrb[3],
809            _unit: PhantomData,
810        }
811    }
812}
813
814impl Add for UPoint {
815    type Output = Self;
816
817    #[inline]
818    fn add(self, rhs: Self) -> Self {
819        Self(self.0 + rhs.0)
820    }
821}
822
823impl Sub for UPoint {
824    type Output = Self;
825
826    #[inline]
827    fn sub(self, rhs: Self) -> Self {
828        Self(self.0 - rhs.0)
829    }
830}
831
832impl Mul<PxDim> for UPoint {
833    type Output = PxPoint;
834
835    #[inline]
836    fn mul(self, rhs: PxDim) -> Self::Output {
837        let rel = self.rel();
838        self.abs()
839            .add_size(&Size2D::<f32, Resolved>::new(
840                rel.x * rhs.width,
841                rel.y * rhs.height,
842            ))
843            .cast_unit()
844    }
845}
846
847impl Neg for UPoint {
848    type Output = UPoint;
849
850    fn neg(self) -> Self::Output {
851        UPoint(-self.0)
852    }
853}
854
855/// Unified Display Point with both per-pixel and display-independent pixels. Unlike a Rect, must
856/// be constructed manually or from a [`PxPoint`], [`AbsPoint`] or [`RelPoint`].
857///
858/// # Examples
859/// ```
860/// use feather_ui::{DPoint, AbsPoint, PxPoint, RelPoint};
861/// let foo: DPoint = AbsPoint::new(1.0,2.0).into();
862///
863/// let bar: DPoint = PxPoint::new(2.0,3.0).into();
864///
865/// let foobar = foo + bar;
866///
867/// let test = DPoint{
868///     px: PxPoint::new(1.0,2.0),
869///     dp: AbsPoint::new(1.0,4.0),
870///     rel: RelPoint::new(3.0,4.0),
871/// };
872///
873/// let bartest = bar + test;
874/// ```
875#[derive(Copy, Clone, Debug, Default, PartialEq)]
876pub struct DPoint {
877    pub dp: AbsPoint,
878    pub px: PxPoint,
879    pub rel: RelPoint,
880}
881
882pub const ZERO_DPOINT: DPoint = DPoint {
883    px: PxPoint {
884        x: 0.0,
885        y: 0.0,
886        _unit: PhantomData,
887    },
888    dp: AbsPoint {
889        x: 0.0,
890        y: 0.0,
891        _unit: PhantomData,
892    },
893    rel: RelPoint {
894        x: 0.0,
895        y: 0.0,
896        _unit: PhantomData,
897    },
898};
899
900impl DPoint {
901    const fn resolve(&self, dpi: RelDim) -> UPoint {
902        UPoint(f32x4::new([
903            self.px.x + (self.dp.x * dpi.width),
904            self.px.y + (self.dp.y * dpi.height),
905            self.rel.x,
906            self.rel.y,
907        ]))
908    }
909}
910
911impl From<AbsPoint> for DPoint {
912    fn from(value: AbsPoint) -> Self {
913        Self {
914            dp: value,
915            px: PxPoint::zero(),
916            rel: RelPoint::zero(),
917        }
918    }
919}
920
921impl From<PxPoint> for DPoint {
922    fn from(value: PxPoint) -> Self {
923        Self {
924            dp: AbsPoint::zero(),
925            px: value,
926            rel: RelPoint::zero(),
927        }
928    }
929}
930
931impl From<RelPoint> for DPoint {
932    fn from(value: RelPoint) -> Self {
933        Self {
934            dp: AbsPoint::zero(),
935            px: PxPoint::zero(),
936            rel: value,
937        }
938    }
939}
940
941impl Add<DPoint> for DPoint {
942    type Output = Self;
943
944    #[inline]
945    fn add(self, rhs: DPoint) -> Self::Output {
946        Self::Output {
947            dp: self.dp + rhs.dp.to_vector(),
948            px: self.px + rhs.px.to_vector(),
949            rel: self.rel + rhs.rel.to_vector(),
950        }
951    }
952}
953
954impl Sub<DPoint> for DPoint {
955    type Output = Self;
956
957    #[inline]
958    fn sub(self, rhs: DPoint) -> Self::Output {
959        self + (-rhs)
960    }
961}
962
963impl Neg for DPoint {
964    type Output = DPoint;
965
966    fn neg(self) -> Self::Output {
967        Self::Output {
968            dp: -self.dp,
969            px: -self.px,
970            rel: -self.rel,
971        }
972    }
973}
974
975#[derive(Copy, Clone, Debug, Default, PartialEq)]
976/// Partially resolved unified coordinate rectangle
977pub struct URect {
978    pub abs: ResRect,
979    pub rel: RelRect,
980}
981
982impl URect {
983    #[inline]
984    pub fn topleft(&self) -> UPoint {
985        let abs = self.abs.v.as_array_ref();
986        let rel = self.rel.v.as_array_ref();
987        UPoint(f32x4::new([abs[0], abs[1], rel[0], rel[1]]))
988    }
989
990    #[inline]
991    pub fn bottomright(&self) -> UPoint {
992        let abs = self.abs.v.as_array_ref();
993        let rel = self.rel.v.as_array_ref();
994        UPoint(f32x4::new([abs[2], abs[3], rel[2], rel[3]]))
995    }
996
997    #[inline]
998    pub fn resolve(&self, rect: PxRect) -> PxRect {
999        let ltrb = rect.v.as_array_ref();
1000        let topleft = f32x4::new([ltrb[0], ltrb[1], ltrb[0], ltrb[1]]);
1001        let bottomright = f32x4::new([ltrb[2], ltrb[3], ltrb[2], ltrb[3]]);
1002
1003        PxRect {
1004            v: topleft + self.abs.v + self.rel.v * (bottomright - topleft),
1005            _unit: PhantomData,
1006        }
1007    }
1008
1009    #[inline]
1010    pub fn to_perimeter(&self, rect: PxRect) -> PxPerimeter {
1011        PxPerimeter {
1012            v: self.resolve(rect).v,
1013            _unit: PhantomData,
1014        }
1015    }
1016}
1017
1018pub const ZERO_URECT: URect = URect {
1019    abs: ResRect::zero(),
1020    rel: RelRect::zero(),
1021};
1022
1023pub const FILL_URECT: URect = URect {
1024    abs: ResRect::zero(),
1025    rel: RelRect::unit(),
1026};
1027
1028pub const AUTO_URECT: URect = URect {
1029    abs: ResRect::zero(),
1030    rel: RelRect::new(0.0, 0.0, UNSIZED_AXIS, UNSIZED_AXIS),
1031};
1032
1033impl Mul<PxRect> for URect {
1034    type Output = PxRect;
1035
1036    #[inline]
1037    fn mul(self, rhs: PxRect) -> Self::Output {
1038        self.resolve(rhs)
1039    }
1040}
1041
1042impl Mul<PxDim> for URect {
1043    type Output = PxRect;
1044
1045    #[inline]
1046    fn mul(self, rhs: PxDim) -> Self::Output {
1047        Self::Output {
1048            v: self.abs.v + self.rel.v * splat_size(rhs),
1049            _unit: PhantomData,
1050        }
1051    }
1052}
1053
1054impl Neg for URect {
1055    type Output = URect;
1056
1057    fn neg(self) -> Self::Output {
1058        URect {
1059            abs: -self.abs,
1060            rel: -self.rel,
1061        }
1062    }
1063}
1064
1065/// Unified Display Rectangle with both per-pixel and display-independent pixels. Can be
1066/// constructed by adding together any combination of [`PxRect`], [`AbsRect`] or [`RelRect`].
1067///
1068/// # Examples
1069/// ```
1070/// use feather_ui::{DRect, AbsRect, PxRect, RelRect};
1071/// let foo: DRect = AbsRect::new(1.0,2.0,3.0,4.0).into();
1072///
1073/// let bar = AbsRect::new(1.0,2.0,3.0,4.0) + PxRect::new(1.0,2.0,3.0,4.0);
1074///
1075/// let baz = RelRect::new(1.0,2.0,3.0,4.0) + PxRect::new(1.0,2.0,3.0,4.0);
1076///
1077/// // These can be added together because bar turned into a `DRect` from adding `PxRect`
1078/// // and `AbsRect` together
1079/// let foobar = foo + bar;
1080///
1081/// let test = DRect{
1082///     px: PxRect::new(1.0,2.0,3.0,4.0),
1083///     dp: AbsRect::new(1.0,2.0,3.0,4.0),
1084///     rel: RelRect::new(1.0,2.0,3.0,4.0),
1085/// };
1086///
1087/// let baztest = baz + test;
1088/// ```
1089#[derive(Copy, Clone, Debug, Default, PartialEq)]
1090pub struct DRect {
1091    pub px: PxRect,
1092    pub dp: AbsRect,
1093    pub rel: RelRect,
1094}
1095
1096impl DRect {
1097    fn resolve(&self, dpi: RelDim) -> URect {
1098        URect {
1099            abs: ResRect {
1100                v: self.px.v + (self.dp.v * splat_size(dpi)),
1101                _unit: PhantomData,
1102            },
1103            rel: self.rel,
1104        }
1105    }
1106
1107    /// Returns the top-left corner of the unified display rectangle as a unified
1108    /// display point.
1109    pub fn topleft(&self) -> DPoint {
1110        DPoint {
1111            dp: self.dp.topleft(),
1112            px: self.px.topleft(),
1113            rel: self.rel.topleft(),
1114        }
1115    }
1116
1117    /// Returns the bottom-right corner of the unified display rectangle. This
1118    /// is ***not*** the size of the rectangle! To get the actual size of the
1119    /// rectangle, you must subtract the top-left corner from the bottom-right
1120    /// corner, or call [`DRect::size`] which does this for you.
1121    pub fn bottomright(&self) -> DPoint {
1122        DPoint {
1123            dp: self.dp.bottomright(),
1124            px: self.px.bottomright(),
1125            rel: self.rel.bottomright(),
1126        }
1127    }
1128
1129    /// Returns the size of the rectangle as a unified display point.
1130    pub fn size(&self) -> DPoint {
1131        self.bottomright() - self.topleft()
1132    }
1133
1134    /// Returns a degenerate zero-sized rectangle.
1135    pub const fn zero() -> Self {
1136        Self {
1137            px: PxRect::zero(),
1138            dp: AbsRect::zero(),
1139            rel: RelRect::zero(),
1140        }
1141    }
1142
1143    /// Returns a DRect with a relative component mapped to the entire available area. This
1144    /// is often used for any element that should be the same size as it's parent container.
1145    pub const fn fill() -> Self {
1146        DRect {
1147            px: PxRect::zero(),
1148            dp: AbsRect::zero(),
1149            rel: RelRect::unit(),
1150        }
1151    }
1152
1153    /// Returns a DRect with two [`UNSIZED_AXIS`], meaning they will be set to the size of the
1154    /// children of the element, or the element's intrinsic size (or zero if it doesn't have
1155    /// any).
1156    pub const fn auto() -> Self {
1157        DRect {
1158            px: PxRect::zero(),
1159            dp: AbsRect::zero(),
1160            rel: RelRect::new(0.0, 0.0, UNSIZED_AXIS, UNSIZED_AXIS),
1161        }
1162    }
1163}
1164
1165pub const ZERO_DRECT: DRect = DRect::zero();
1166pub const FILL_DRECT: DRect = DRect::fill();
1167pub const AUTO_DRECT: DRect = DRect::auto();
1168
1169impl Add<DRect> for DRect {
1170    type Output = Self;
1171
1172    #[inline]
1173    fn add(self, rhs: DRect) -> Self::Output {
1174        Self::Output {
1175            dp: AbsRect {
1176                v: self.dp.v + rhs.dp.v,
1177                _unit: PhantomData,
1178            },
1179            px: PxRect {
1180                v: self.px.v + rhs.px.v,
1181                _unit: PhantomData,
1182            },
1183            rel: RelRect {
1184                v: self.rel.v + rhs.rel.v,
1185                _unit: PhantomData,
1186            },
1187        }
1188    }
1189}
1190
1191impl Sub<DRect> for DRect {
1192    type Output = Self;
1193
1194    #[inline]
1195    fn sub(self, rhs: DRect) -> Self::Output {
1196        self + (-rhs)
1197    }
1198}
1199
1200impl Neg for DRect {
1201    type Output = DRect;
1202
1203    fn neg(self) -> Self::Output {
1204        Self::Output {
1205            dp: -self.dp,
1206            px: -self.px,
1207            rel: -self.rel,
1208        }
1209    }
1210}
1211
1212impl From<AbsRect> for DRect {
1213    fn from(value: AbsRect) -> Self {
1214        Self {
1215            px: PxRect::zero(),
1216            dp: value,
1217            rel: RelRect::zero(),
1218        }
1219    }
1220}
1221
1222impl From<PxRect> for DRect {
1223    fn from(value: PxRect) -> Self {
1224        Self {
1225            px: value,
1226            dp: AbsRect::zero(),
1227            rel: RelRect::zero(),
1228        }
1229    }
1230}
1231
1232impl From<RelRect> for DRect {
1233    fn from(value: RelRect) -> Self {
1234        Self {
1235            px: PxRect::zero(),
1236            dp: AbsRect::zero(),
1237            rel: value,
1238        }
1239    }
1240}
1241
1242impl<T, U: Into<DRect>> Add<U> for Rect<T>
1243where
1244    Self: Into<DRect>,
1245{
1246    type Output = DRect;
1247
1248    fn add(self, rhs: U) -> Self::Output {
1249        self.into() + rhs.into()
1250    }
1251}
1252
1253/// The Limits type represents both a minimum size and a maximum size for a given unit. Adding limits
1254/// together actually merges them, by taking the largest minimum size and the smallest maximum size of
1255/// either. You aren't expected to construct this type manually, however - the Limits constructor takes
1256/// a range parameter to make it easier to represent the minimum and maximum range of sizes you want.
1257///
1258/// # Examples
1259/// ```
1260/// use feather_ui::euclid::Size2D;
1261/// use feather_ui::{AbsLimits, RelLimits, Logical, Relative};
1262///
1263/// // Results in a minimum size of [-inf, 10.0] and a maximum size of [inf, 200.0]
1264/// let limits = AbsLimits::new(.., 10.0..200.0);
1265/// assert_eq!(limits.min(), Size2D::<f32, Logical>::new(f32::NEG_INFINITY, 10.0));
1266/// assert_eq!(limits.max(), Size2D::<f32, Logical>::new(f32::INFINITY, 200.0));
1267///
1268/// // Results in a minimum size of [-inf, -inf] and a maximum size of [1.0, inf]
1269/// let rlimits = RelLimits::new(..1.0, ..);
1270/// assert_eq!(rlimits.min(), Size2D::<f32, Relative>::new(f32::NEG_INFINITY, f32::NEG_INFINITY));
1271/// assert_eq!(rlimits.max(), Size2D::<f32, Relative>::new(1.0, f32::INFINITY));
1272///
1273/// // Result in a minimum size of [0.0, 10.0] and a maximum size of [inf, 100.0]
1274/// let merged = AbsLimits::new(0.0.., 5.0..100.0) + limits;
1275/// assert_eq!(merged.min(), Size2D::<f32, Logical>::new(0.0, 10.0));
1276/// assert_eq!(merged.max(), Size2D::<f32, Logical>::new(f32::INFINITY, 100.0));
1277/// ```
1278#[derive(Copy, Clone, Debug, PartialEq)]
1279pub struct Limits<U> {
1280    pub v: f32x4,
1281    #[doc(hidden)]
1282    pub _unit: PhantomData<U>,
1283}
1284
1285pub type PxLimits = Limits<Pixel>;
1286pub type AbsLimits = Limits<Logical>;
1287pub type RelLimits = Limits<Relative>;
1288pub type ResLimits = Limits<Resolved>;
1289
1290//pub const Unbounded: std::ops::Range<f32> = std::ops::Range
1291// It would be cheaper to avoid using actual infinities here but we currently need them to make the math work
1292
1293/// Represents the default limit values for any limit type. This simply represents a minimum size
1294/// of [`f32::NEG_INFINITY`] and a maximum size of [`f32::INFINITY`]
1295pub const DEFAULT_LIMITS: f32x4 = f32x4::new([
1296    f32::NEG_INFINITY,
1297    f32::NEG_INFINITY,
1298    f32::INFINITY,
1299    f32::INFINITY,
1300]);
1301
1302/// Represents the default absolute value limit with a minimum size of [`f32::NEG_INFINITY`] and a
1303/// maximum size of [`f32::INFINITY`]
1304pub const DEFAULT_ABSLIMITS: AbsLimits = AbsLimits {
1305    v: DEFAULT_LIMITS,
1306    _unit: PhantomData,
1307};
1308
1309/// Represents the default relative value limit with a minimum size of [`f32::NEG_INFINITY`] and a
1310/// maximum size of [`f32::INFINITY`]
1311pub const DEFAULT_RLIMITS: RelLimits = RelLimits {
1312    v: DEFAULT_LIMITS,
1313    _unit: PhantomData,
1314};
1315
1316impl<U> Limits<U> {
1317    #[inline]
1318    const fn from_bound(bound: std::ops::Bound<&f32>, inf: f32) -> f32 {
1319        match bound {
1320            std::ops::Bound::Included(v) | std::ops::Bound::Excluded(v) => *v,
1321            std::ops::Bound::Unbounded => inf,
1322        }
1323    }
1324    pub fn new(x: impl std::ops::RangeBounds<f32>, y: impl std::ops::RangeBounds<f32>) -> Self {
1325        Self {
1326            v: f32x4::new([
1327                Self::from_bound(x.start_bound(), f32::NEG_INFINITY),
1328                Self::from_bound(y.start_bound(), f32::NEG_INFINITY),
1329                Self::from_bound(x.end_bound(), f32::INFINITY),
1330                Self::from_bound(y.end_bound(), f32::INFINITY),
1331            ]),
1332            _unit: PhantomData,
1333        }
1334    }
1335
1336    #[inline]
1337    pub fn min(&self) -> Size2D<f32, U> {
1338        let minmax = self.v.as_array_ref();
1339        Size2D::new(minmax[0], minmax[1])
1340    }
1341    #[inline]
1342    pub fn max(&self) -> Size2D<f32, U> {
1343        let minmax = self.v.as_array_ref();
1344        Size2D::new(minmax[2], minmax[3])
1345    }
1346
1347    #[inline]
1348    pub fn set_min(&mut self, bound: Size2D<f32, U>) {
1349        let minmax = self.v.as_array_mut();
1350        minmax[0] = bound.width;
1351        minmax[1] = bound.height;
1352    }
1353
1354    #[inline]
1355    pub fn set_max(&mut self, bound: Size2D<f32, U>) {
1356        let minmax = self.v.as_array_mut();
1357        minmax[2] = bound.width;
1358        minmax[3] = bound.height;
1359    }
1360
1361    /// Discard the units
1362    #[inline]
1363    pub fn to_untyped(self) -> Limits<euclid::UnknownUnit> {
1364        self.cast_unit()
1365    }
1366
1367    /// Cast the unit
1368    #[inline]
1369    pub fn cast_unit<V>(self) -> Limits<V> {
1370        Limits::<V> {
1371            v: self.v,
1372            _unit: PhantomData,
1373        }
1374    }
1375}
1376
1377impl<U> Default for Limits<U> {
1378    #[inline]
1379    fn default() -> Self {
1380        Self {
1381            v: DEFAULT_LIMITS,
1382            _unit: PhantomData,
1383        }
1384    }
1385}
1386
1387impl<U> Add<Limits<U>> for Limits<U> {
1388    type Output = Self;
1389
1390    #[inline]
1391    fn add(self, rhs: Limits<U>) -> Self::Output {
1392        let minmax = self.v.as_array_ref();
1393        let r = rhs.v.as_array_ref();
1394
1395        Self {
1396            v: f32x4::new([
1397                minmax[0].max(r[0]),
1398                minmax[1].max(r[1]),
1399                minmax[2].min(r[2]),
1400                minmax[3].min(r[3]),
1401            ]),
1402            _unit: PhantomData,
1403        }
1404    }
1405}
1406
1407#[derive(Copy, Clone, Debug, Default)]
1408pub struct DLimits {
1409    dp: AbsLimits,
1410    px: PxLimits,
1411}
1412
1413pub const DEFAULT_DLIMITS: DLimits = DLimits {
1414    dp: AbsLimits {
1415        v: DEFAULT_LIMITS,
1416        _unit: PhantomData,
1417    },
1418    px: PxLimits {
1419        v: DEFAULT_LIMITS,
1420        _unit: PhantomData,
1421    },
1422};
1423
1424impl DLimits {
1425    pub fn resolve(&self, dpi: RelDim) -> PxLimits {
1426        self.px.cast_unit()
1427            + PxLimits {
1428                v: self.dp.v * splat_size(dpi),
1429                _unit: PhantomData,
1430            }
1431    }
1432}
1433
1434impl From<AbsLimits> for DLimits {
1435    fn from(value: AbsLimits) -> Self {
1436        DLimits {
1437            dp: value,
1438            px: Default::default(),
1439        }
1440    }
1441}
1442
1443impl From<PxLimits> for DLimits {
1444    fn from(value: PxLimits) -> Self {
1445        DLimits {
1446            dp: Default::default(),
1447            px: value,
1448        }
1449    }
1450}
1451
1452impl Mul<PxDim> for RelLimits {
1453    type Output = PxLimits;
1454
1455    #[inline]
1456    fn mul(self, rhs: PxDim) -> Self::Output {
1457        let (unsized_x, unsized_y) = crate::layout::check_unsized_dim(rhs);
1458        let minmax = self.v.as_array_ref();
1459        Self::Output {
1460            v: f32x4::new([
1461                if unsized_x {
1462                    minmax[0]
1463                } else {
1464                    minmax[0] * rhs.width
1465                },
1466                if unsized_y {
1467                    minmax[1]
1468                } else {
1469                    minmax[1] * rhs.height
1470                },
1471                if unsized_x {
1472                    minmax[2]
1473                } else {
1474                    minmax[2] * rhs.width
1475                },
1476                if unsized_y {
1477                    minmax[3]
1478                } else {
1479                    minmax[3] * rhs.height
1480                },
1481            ]),
1482            _unit: PhantomData,
1483        }
1484    }
1485}
1486
1487#[derive(Debug, Copy, Clone, PartialEq, Default)]
1488pub struct UValue {
1489    pub abs: f32,
1490    pub rel: f32,
1491}
1492
1493impl UValue {
1494    pub const fn resolve(&self, outer_dim: f32) -> f32 {
1495        if self.rel == UNSIZED_AXIS {
1496            UNSIZED_AXIS
1497        } else {
1498            self.abs + (self.rel * outer_dim)
1499        }
1500    }
1501    pub const fn is_unsized(&self) -> bool {
1502        self.rel == UNSIZED_AXIS
1503    }
1504}
1505
1506impl From<f32> for UValue {
1507    fn from(value: f32) -> Self {
1508        Self {
1509            abs: value,
1510            rel: 0.0,
1511        }
1512    }
1513}
1514
1515#[derive(Debug, Copy, Clone, PartialEq, Default)]
1516pub struct DValue {
1517    pub dp: f32,
1518    pub px: f32,
1519    pub rel: f32,
1520}
1521
1522impl DValue {
1523    pub const fn resolve(&self, dpi: f32) -> UValue {
1524        UValue {
1525            abs: self.px + (self.dp * dpi),
1526            rel: self.rel,
1527        }
1528    }
1529    pub const fn is_unsized(&self) -> bool {
1530        self.rel == UNSIZED_AXIS
1531    }
1532}
1533
1534impl From<f32> for DValue {
1535    fn from(value: f32) -> Self {
1536        Self {
1537            dp: value,
1538            px: 0.0,
1539            rel: 0.0,
1540        }
1541    }
1542}
1543
1544/// Represents a particular layout direction, which is used in several layout operations. Note
1545/// that this is also used for a Grid's layout directions, but [`RowDirection::TopToBottom`]
1546/// doesn't make sense for a grid and instead means a combination of
1547/// [`RowDirection::RightToLeft`] and [`RowDirection::BottomToTop`]. While this is confusing,
1548/// Rust does not allow us to create two variants with the same discriminator, so we can't make
1549/// a `RowDirection::RightToLeftAndBottomToTop` option without duplicating the entire enum
1550/// for Grid. [Tracking issue](https://github.com/Fundament-Institute/feather-ui/issues/159).
1551#[derive(
1552    Debug, Copy, Clone, PartialEq, Eq, Default, derive_more::TryFrom, derive_more::Display,
1553)]
1554#[try_from(repr)]
1555#[repr(u8)]
1556pub enum RowDirection {
1557    #[default]
1558    LeftToRight = 0,
1559    RightToLeft = 1,
1560    BottomToTop = 2,
1561    TopToBottom = 3,
1562}
1563
1564// If a component provides a CrossReferenceDomain, it's children can register themselves with it.
1565// Registered children will write their fully resolved area to the mapping, which can then be
1566// retrieved during the render step via a source ID.
1567#[derive(Default)]
1568pub struct CrossReferenceDomain {
1569    mappings: RwLock<im::HashMap<Arc<SourceID>, PxRect>>,
1570}
1571
1572impl CrossReferenceDomain {
1573    pub fn write_area(&self, target: Arc<SourceID>, area: PxRect) {
1574        self.mappings.write().insert(target, area);
1575    }
1576
1577    pub fn get_area(&self, target: &Arc<SourceID>) -> Option<PxRect> {
1578        self.mappings.read().get(target).copied()
1579    }
1580
1581    pub fn remove_self(&self, target: &Arc<SourceID>) {
1582        // TODO: Is this necessary? Does it even make sense? Do you simply need to wipe the mapping for every new layout instead?
1583        self.mappings.write().remove(target);
1584    }
1585}
1586
1587/// Object-safe version of Hash + PartialEq
1588pub trait DynHashEq: DynClone + std::fmt::Debug {
1589    fn dyn_hash(&self, state: &mut dyn Hasher);
1590    fn dyn_eq(&self, other: &dyn Any) -> bool;
1591}
1592
1593dyn_clone::clone_trait_object!(DynHashEq);
1594
1595impl<H: Hash + PartialEq + std::cmp::Eq + Clone + std::fmt::Debug + Any> DynHashEq for H {
1596    fn dyn_hash(&self, mut state: &mut dyn Hasher) {
1597        self.hash(&mut state);
1598    }
1599    fn dyn_eq(&self, other: &dyn Any) -> bool {
1600        if let Some(o) = other.downcast_ref::<H>() {
1601            self == o
1602        } else {
1603            false
1604        }
1605    }
1606}
1607
1608/// Represents different kinds of IDs that can be used to populate a [`SourceID`]. Provides
1609/// both static strings and owned strings, plus a way to create your own ID using a dynamic
1610/// hash object.
1611///
1612/// Might be [replaced in the future](https://github.com/Fundament-Institute/feather-ui/issues/156) with pointer-based IDs instead.
1613#[derive(Clone, Default, Debug)]
1614pub enum DataID {
1615    Named(&'static str),
1616    Owned(String),
1617    Int(i64),
1618    Other(Box<dyn DynHashEq + Sync + Send>),
1619    #[default]
1620    None, // Marks an invalid default ID, crashes if you ever try to actually use it.
1621}
1622
1623impl Hash for DataID {
1624    fn hash<H: Hasher>(&self, state: &mut H) {
1625        match self {
1626            DataID::Named(s) => s.hash(state),
1627            DataID::Owned(s) => s.hash(state),
1628            DataID::Int(i) => i.hash(state),
1629            DataID::Other(hash_comparable) => hash_comparable.dyn_hash(state),
1630            DataID::None => {
1631                panic!("Invalid ID! Did you forget to initialize a component node's ID field?")
1632            }
1633        }
1634    }
1635}
1636
1637impl std::cmp::Eq for DataID {}
1638impl PartialEq for DataID {
1639    fn eq(&self, other: &Self) -> bool {
1640        match self {
1641            DataID::Named(s) => {
1642                if let DataID::Named(name) = other {
1643                    name == s
1644                } else {
1645                    false
1646                }
1647            }
1648            DataID::Owned(s) => {
1649                if let DataID::Owned(name) = other {
1650                    name == s
1651                } else {
1652                    false
1653                }
1654            }
1655            DataID::Int(i) => {
1656                if let DataID::Int(integer) = other {
1657                    integer == i
1658                } else {
1659                    false
1660                }
1661            }
1662            DataID::Other(hash_comparable) => {
1663                if let DataID::Other(h) = other {
1664                    hash_comparable.dyn_eq(h)
1665                } else {
1666                    false
1667                }
1668            }
1669            DataID::None => panic!("Invalid ID!"),
1670        }
1671    }
1672}
1673
1674/// Represents a unique ID out of a linked list of [`DataID`]. Taken together, all the IDs in a program
1675/// form a tree that doesn't just ensure uniqueness, but also allows tracking the structure of the data
1676/// being used and how each piece of data depends on another piece of data. As a result, the tree structure
1677/// of IDs generally diverges from the component tree of the actual UI, and may or may not actually resemble
1678/// the storage structure of the data.
1679#[derive(Clone, Default, Debug)]
1680pub struct SourceID {
1681    parent: Option<std::sync::Arc<SourceID>>,
1682    id: DataID,
1683}
1684
1685impl SourceID {
1686    /// Creates a new [`SourceID`] out of the given [`DataID`], with ourselves as its parent
1687    pub fn child(self: &Arc<Self>, id: DataID) -> Arc<Self> {
1688        Self {
1689            parent: self.clone().into(),
1690            id,
1691        }
1692        .into()
1693    }
1694
1695    /// Creates a new, unique duplicate ID using this as the parent and the strong count
1696    /// of this Rc as the child [`DataID`]. This is used to enable cloning certain components,
1697    /// like [`component::shape::Shape`], while automatically generating a new unique ID for
1698    /// the cloned component.
1699    pub fn duplicate(self: &Arc<Self>) -> Arc<Self> {
1700        self.child(DataID::Int(Arc::strong_count(self) as i64))
1701    }
1702
1703    #[allow(dead_code)] // TODO: not sure if we'll need this later
1704    #[cfg(debug_assertions)]
1705    #[allow(clippy::mutable_key_type)]
1706    pub(crate) fn parents(self: &Arc<Self>) -> std::collections::HashSet<&Arc<Self>> {
1707        let mut set = std::collections::HashSet::new();
1708
1709        let mut cur = self.parent.as_ref();
1710        while let Some(id) = cur {
1711            if set.contains(id) {
1712                panic!("Loop detected in IDs! {:?} already existed!", id.id);
1713            }
1714            set.insert(id);
1715            cur = id.parent.as_ref();
1716        }
1717        set
1718    }
1719}
1720impl std::cmp::Eq for SourceID {}
1721impl PartialEq for SourceID {
1722    fn eq(&self, other: &Self) -> bool {
1723        if let Some(parent) = self.parent.as_ref() {
1724            if let Some(pother) = other.parent.as_ref() {
1725                parent == pother && self.id == other.id
1726            } else {
1727                false
1728            }
1729        } else {
1730            other.parent.is_none() && self.id == other.id
1731        }
1732    }
1733}
1734impl Hash for SourceID {
1735    fn hash<H: Hasher>(&self, state: &mut H) {
1736        if let Some(parent) = self.parent.as_ref() {
1737            parent.id.hash(state);
1738        }
1739        self.id.hash(state);
1740    }
1741}
1742impl Display for SourceID {
1743    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1744        if let Some(parent) = self.parent.as_ref() {
1745            parent.fmt(f)?;
1746        }
1747
1748        match (&self.id, self.parent.is_some()) {
1749            (DataID::Named(_), true) | (DataID::Owned(_), true) => f.write_str(" -> "),
1750            (DataID::Other(_), true) => f.write_str(" "),
1751            _ => Ok(()),
1752        }?;
1753
1754        match &self.id {
1755            DataID::Named(s) => f.write_str(s),
1756            DataID::Owned(s) => f.write_str(s),
1757            DataID::Int(i) => write!(f, "[{i}]"),
1758            DataID::Other(dyn_hash_eq) => {
1759                let mut h = std::hash::DefaultHasher::new();
1760                dyn_hash_eq.dyn_hash(&mut h);
1761                write!(f, "{{{}}}", h.finish())
1762            }
1763            DataID::None => Ok(()),
1764        }
1765    }
1766}
1767
1768pub struct ScopeIterID<'a, T> {
1769    base: ScopeID<'a>,
1770    it: T,
1771}
1772
1773impl<'a, T: Iterator> ScopeIterID<'a, T> {
1774    fn new(parent: &'a mut ScopeID<'_>, it: T) -> Self {
1775        Self {
1776            base: parent.scope(),
1777            it,
1778        }
1779    }
1780}
1781
1782impl<T> Iterator for ScopeIterID<'_, T>
1783where
1784    T: Iterator,
1785{
1786    type Item = (T::Item, Arc<SourceID>);
1787
1788    #[inline]
1789    fn next(&mut self) -> Option<Self::Item> {
1790        let x = self.it.next()?;
1791        let id = self.base.create();
1792        Some((x, id))
1793    }
1794
1795    #[inline]
1796    fn size_hint(&self) -> (usize, Option<usize>) {
1797        self.it.size_hint()
1798    }
1799
1800    #[inline]
1801    fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
1802        while let Some(x) = Iterator::next(self) {
1803            if n == 0 {
1804                return Some(x);
1805            }
1806            n -= 1;
1807        }
1808        None
1809    }
1810
1811    #[inline]
1812    fn fold<Acc, F>(mut self, init: Acc, mut f: F) -> Acc
1813    where
1814        F: FnMut(Acc, Self::Item) -> Acc,
1815    {
1816        let mut accum = init;
1817        while let Some(x) = Iterator::next(&mut self) {
1818            accum = f(accum, x);
1819        }
1820        accum
1821    }
1822}
1823
1824/// Represents a scope with a particular ID assigned to it. Used to generate new IDs for anything created
1825/// inside this scope, with this scope's ID as parents, or to generate a new [`ScopeID`] with this scope as
1826/// its parent. Includes [`ScopeID::iter`] and [`ScopeID::cond`] to make it easier to generate stable IDs
1827/// across control flow boundaries. It can be used in conjunction with [`gen_id`] to generate child IDs with
1828/// source and line numbers.
1829///
1830/// # Examples
1831/// ```
1832/// use feather_ui::layout::fixed;
1833/// use feather_ui::component::{shape, region::Region};
1834/// use feather_ui::{ScopeID, gen_id, DRect, DAbsPoint, color::sRGB, FILL_DRECT, children };
1835///
1836/// fn foobar(mut id: ScopeID<'_>) {
1837///
1838/// let rect = shape::round_rect::<DRect>(
1839///     gen_id!(id),
1840///     FILL_DRECT,
1841///     0.0,
1842///     0.0,
1843///     wide::f32x4::splat(10.0),
1844///     sRGB::new(0.2, 0.7, 0.4, 1.0),
1845///     sRGB::transparent(),
1846///     DAbsPoint::zero(),
1847/// );
1848///
1849/// let region = Region::<DRect>::new(
1850///     id.create(),
1851///     FILL_DRECT,
1852///     children![fixed::Prop, rect],
1853/// );
1854/// }
1855///
1856/// ```
1857pub struct ScopeID<'a> {
1858    // This is only used to force a mutable borrow of the parent, which ensures you cannot fork ID scopes
1859    _parent: PhantomData<&'a mut ()>,
1860    base: Arc<SourceID>,
1861    count: i64,
1862}
1863
1864impl<'a> ScopeID<'a> {
1865    /// Gets the underlying ID for this scope. This is sometimes useful when creating custom scopes that belong
1866    /// to a specific component.
1867    pub fn id(&mut self) -> &Arc<SourceID> {
1868        &self.base
1869    }
1870
1871    /// Creates a new unique [`SourceID`] using an internal counter with this scope as it's parent.
1872    ///
1873    /// # Examples
1874    /// ```
1875    /// use feather_ui::component::shape;
1876    /// use feather_ui::{ScopeID, DRect, DAbsPoint, color::sRGB, FILL_DRECT };
1877    ///
1878    /// fn foobar(mut id: ScopeID<'_>) {
1879    /// let rect = shape::round_rect::<DRect>(
1880    ///     id.create(),
1881    ///     FILL_DRECT,
1882    ///     0.0,
1883    ///     0.0,
1884    ///     wide::f32x4::splat(10.0),
1885    ///     sRGB::new(0.2, 0.7, 0.4, 1.0),
1886    ///     sRGB::transparent(),
1887    ///     DAbsPoint::zero(),
1888    /// );
1889    /// }
1890    ///
1891    /// ```
1892    pub fn create(&mut self) -> Arc<SourceID> {
1893        let node = self.base.child(crate::DataID::Int(self.count));
1894        self.count += 1;
1895        node
1896    }
1897
1898    /// Creates a new scoped ID with this scope as it's parent that can then be passed into a function.
1899    pub fn scope(&mut self) -> ScopeID<'_> {
1900        ScopeID {
1901            base: self.create(),
1902            _parent: PhantomData,
1903            count: 0,
1904        }
1905    }
1906
1907    /// Creates a new unique SourceID using the provided DataID, which bypasses the internal counter.
1908    /// This can be used to either manually create a new SourceID from a custom DataID by the user, or
1909    /// by calling [`gen_id`], which calls this function internally.
1910    pub fn child(&mut self, id: DataID) -> Arc<SourceID> {
1911        self.base.child(id)
1912    }
1913
1914    /// Wraps another iterator and returns a pair of both a unique ID and the result of the iterator.
1915    /// Required for outline functions that use a for loop when iterating through data.
1916    ///  
1917    /// # Examples
1918    /// ```
1919    /// use feather_ui::component::shape;
1920    /// use feather_ui::{ScopeID, DRect, DAbsPoint, color::sRGB, FILL_DRECT };
1921    ///
1922    /// fn foobar(count: usize, mut scope: ScopeID<'_>) {
1923    /// for (i, id) in scope.iter(0..count) {
1924    ///     let _ = shape::round_rect::<DRect>(
1925    ///         id,
1926    ///         FILL_DRECT,
1927    ///         i as f32,
1928    ///         0.0,
1929    ///         wide::f32x4::splat(4.0),
1930    ///         sRGB::transparent(),
1931    ///         sRGB::transparent(),
1932    ///         DAbsPoint::zero(),
1933    ///     );
1934    /// }
1935    /// }
1936    /// ```
1937    pub fn iter<U: IntoIterator>(&mut self, other: U) -> ScopeIterID<'_, U::IntoIter> {
1938        ScopeIterID::new(self, other.into_iter())
1939    }
1940
1941    /// Wraps the true and false branches of a condition, ensuring the IDs for both are maintained seperately
1942    /// regardless of which branch is picked.
1943    ///
1944    /// # Examples
1945    /// ```
1946    /// use feather_ui::component::{shape, ComponentWrap, text::Text};
1947    /// use feather_ui::{ScopeID, DRect, DAbsPoint, color::sRGB, FILL_DRECT };
1948    /// fn foobar(cond: bool, mut scope: ScopeID<'_>) {
1949    /// let _ = scope.cond::<Box<dyn ComponentWrap<dyn feather_ui::layout::base::Empty>>>(
1950    ///     cond,
1951    ///     |mut id: ScopeID<'_>| Box::new(shape::round_rect::<DRect>(
1952    ///         id.create(),
1953    ///         FILL_DRECT,
1954    ///         0.0,
1955    ///         0.0,
1956    ///         wide::f32x4::splat(4.0),
1957    ///         sRGB::transparent(),
1958    ///         sRGB::transparent(),
1959    ///         DAbsPoint::zero(),
1960    ///     )),
1961    ///     |mut id: ScopeID<'_>| {
1962    ///         Box::new(Text::<DRect> {
1963    ///             id: id.create(),
1964    ///             props: FILL_DRECT.into(),
1965    ///             text: "Foobar".to_string(),
1966    ///             font_size: 40.0,
1967    ///             line_height: 56.0,
1968    ///             ..Default::default()
1969    ///         })
1970    ///     });
1971    /// }
1972    /// ```
1973    pub fn cond<R>(
1974        &mut self,
1975        condition: bool,
1976        tvalue: impl FnOnce(ScopeID<'_>) -> R,
1977        fvalue: impl FnOnce(ScopeID<'_>) -> R,
1978    ) -> R {
1979        let (id_true, id_false) = (self.create(), self.create());
1980
1981        if condition {
1982            tvalue(ScopeID {
1983                base: id_true,
1984                _parent: PhantomData,
1985                count: 0,
1986            })
1987        } else {
1988            fvalue(ScopeID {
1989                base: id_false,
1990                _parent: PhantomData,
1991                count: 0,
1992            })
1993        }
1994    }
1995
1996    // Used internally to generate the root scope encapsulating the hardcoded [`APP_SOURCE_ID`]
1997    fn root() -> ScopeID<'a> {
1998        ScopeID {
1999            _parent: PhantomData,
2000            base: Arc::new(APP_SOURCE_ID),
2001            count: 0,
2002        }
2003    }
2004}
2005
2006/// This replaces [`Result`] and allows event handlers to consume an event with [`InputResult::Consume`] (preventing any further
2007/// processing), forward an event with [`InputResult::Forward`] (allow other components to process the event), or return an error.
2008pub enum InputResult<T> {
2009    Consume(T),
2010    Forward(T),
2011    Error(eyre::ErrReport),
2012}
2013
2014impl<T, E: std::error::Error + Send + Sync + 'static> From<Result<T, E>> for InputResult<T> {
2015    fn from(value: Result<T, E>) -> Self {
2016        match value {
2017            Ok(v) => InputResult::Consume(v),
2018            Err(e) => InputResult::Error(e.into()),
2019        }
2020    }
2021}
2022
2023impl<T> InputResult<T> {
2024    /// Maps the [`InputResult`] inner value to a different type, just like [`Result::map`].
2025    fn map<U>(self, f: impl FnOnce(T) -> U) -> InputResult<U> {
2026        match self {
2027            InputResult::Consume(v) => InputResult::Consume(f(v)),
2028            InputResult::Forward(v) => InputResult::Forward(f(v)),
2029            InputResult::Error(error) => InputResult::Error(error),
2030        }
2031    }
2032
2033    fn is_accept(&self) -> bool {
2034        matches!(*self, InputResult::Consume(_))
2035    }
2036    fn is_reject(&self) -> bool {
2037        matches!(*self, InputResult::Forward(_))
2038    }
2039    fn is_err(&self) -> bool {
2040        matches!(*self, InputResult::Error(_))
2041    }
2042}
2043
2044#[derive(Clone)]
2045pub struct Slot(pub Arc<SourceID>, pub u64);
2046
2047/// Represents a wrapped lambda that can act as an top-level event handler using the AppState.
2048pub type AppEvent<State> = Box<dyn FnMut(DispatchPair, AccessCell<State>) -> InputResult<()>>;
2049
2050/// This trait is used to wrap rust lambdas into [`AppEvent<AppData>`] objects that can be boxed for
2051/// use in [`App::new`]. These lambdas must always take the form of `|evt: AnEventEnum, state: AccessCell<AppData>| -> InputResult<()> {}`
2052/// After implorting this extension trait, you will be able to call [`WrapEventEx::wrap`] on a
2053/// qualifying lambda.
2054///
2055/// # Examples
2056/// ```
2057/// use feather_ui::component::{ mouse_area, window::Window };
2058/// use feather_ui::persist::{ FnPersist2, FnPersistStore };
2059/// use feather_ui::{ SourceID, ScopeID, App, AccessCell };
2060/// use std::sync::Arc;
2061///
2062/// #[derive(Clone, PartialEq)]
2063/// struct MyState {
2064///   count: i32
2065/// }
2066///
2067/// // Remember to use the extension trait here so you can call `.wrap()` on a qualifying lambda.
2068/// use crate::feather_ui::WrapEventEx;
2069///
2070/// let onclick = |_: mouse_area::MouseAreaEvent,
2071///  mut appdata: AccessCell<MyState>|
2072///  -> feather_ui::InputResult<()> {
2073///     {
2074///         appdata.count += 1;
2075///         feather_ui::InputResult::Consume(())
2076///     }
2077/// }
2078/// .wrap();
2079///
2080/// struct MyApp {}
2081///
2082/// impl FnPersistStore for MyApp { type Store = (); }
2083///
2084/// impl FnPersist2<MyState, ScopeID<'_>, im::HashMap<Arc<SourceID>, Option<Window>>> for MyApp {
2085///     fn init(&self) -> Self::Store { () }
2086///
2087///     fn call(&mut self,  _: Self::Store,  _: MyState, _: ScopeID<'_>) -> (Self::Store, im::HashMap<Arc<SourceID>, Option<Window>>) {
2088///         ((), im::HashMap::new())
2089///     }
2090/// }
2091///
2092/// App::<MyState, MyApp>::new::<()>(MyState { count: 0 }, vec![Box::new(onclick)], MyApp {}, |_| ());
2093/// ```
2094pub trait WrapEventEx<State: 'static + PartialEq, Input: Dispatchable + 'static> {
2095    /// Wraps a lambda with the appropriate type signature. See [`WrapEventEx`] for examples.
2096    fn wrap(self) -> impl FnMut(DispatchPair, AccessCell<State>) -> InputResult<()>;
2097}
2098
2099impl<AppData: 'static + PartialEq, Input: Dispatchable + 'static, T> WrapEventEx<AppData, Input>
2100    for T
2101where
2102    T: FnMut(Input, AccessCell<AppData>) -> InputResult<()>,
2103{
2104    fn wrap(mut self) -> impl FnMut(DispatchPair, AccessCell<AppData>) -> InputResult<()> {
2105        move |pair, state| (self)(Input::restore(pair).unwrap(), state)
2106    }
2107}
2108
2109/// Used internally for event routing.
2110pub type DispatchPair = (u64, Box<dyn Any>);
2111
2112pub trait Dispatchable
2113where
2114    Self: Sized,
2115{
2116    const SIZE: usize;
2117    fn extract(self) -> DispatchPair;
2118    fn restore(pair: DispatchPair) -> Result<Self, Error>;
2119}
2120
2121impl Dispatchable for Infallible {
2122    const SIZE: usize = 0;
2123
2124    fn extract(self) -> DispatchPair {
2125        (0, Box::new(self))
2126    }
2127
2128    fn restore(_: DispatchPair) -> Result<Self, Error> {
2129        Err(Error::Stateless)
2130    }
2131}
2132
2133/// Represents any potentially stateful component. All components must implement this trait
2134/// because all components are tracked by the state manager even if they are stateless. A
2135/// derive macro [`feather_macro::StateMachineChild`] is provided to make it easier for
2136/// stateless components to correctly implement StateMachineChild and correctly propagate
2137/// events to their children. It is important that this is done correctly, as a component
2138/// can be stateless itself, but have stateful children.
2139///
2140/// # Examples
2141/// ```
2142/// use feather_ui::component::ChildOf;
2143/// use feather_ui::layout::fixed;
2144/// use feather_ui::{ StateMachineChild, SourceID};
2145/// use std::sync::Arc;
2146/// use std::rc::Rc;
2147///
2148/// pub struct MyComponent<T> {
2149///     pub id: Arc<SourceID>,
2150///     pub props: Rc<T>,
2151///     pub children: im::Vector<Option<Box<ChildOf<dyn fixed::Prop>>>>,
2152/// }
2153///
2154/// impl<T: Default> StateMachineChild for MyComponent<T> {
2155///     fn id(&self) -> std::sync::Arc<SourceID> {
2156///         self.id.clone()
2157///     }
2158///     fn apply_children(
2159///         &self,
2160///         f: &mut dyn FnMut(&dyn StateMachineChild) -> eyre::Result<()>,
2161///     ) -> eyre::Result<()> {
2162///         self.children
2163///             .iter()
2164///             .try_for_each(|x| f(x.as_ref().unwrap().as_ref()))
2165///     }
2166/// }
2167/// ```
2168pub trait StateMachineChild {
2169    #[allow(unused_variables)]
2170    fn init(
2171        &self,
2172        driver: &std::sync::Weak<Driver>,
2173    ) -> Result<Box<dyn StateMachineWrapper>, crate::Error> {
2174        Err(crate::Error::Stateless)
2175    }
2176    fn apply_children(
2177        &self,
2178        _: &mut dyn FnMut(&dyn StateMachineChild) -> eyre::Result<()>,
2179    ) -> eyre::Result<()> {
2180        // Default implementation assumes no children
2181        Ok(())
2182    }
2183    fn id(&self) -> Arc<SourceID>;
2184}
2185
2186// This was originally supposed to use a pointer, but rust moves things all over the place, so a version that
2187// doesn't store the ID would have to be pinned (which likely isn't even possible inside an appstate).
2188/*pub struct StateCell<T> {
2189    value: T,
2190    id: Arc<SourceID>,
2191}
2192
2193impl<T> StateCell<T> {
2194    pub fn new(v: T, id: Arc<SourceID>) -> Self {
2195        Self { value: v, id }
2196    }
2197
2198    pub fn borrow_mut<'a>(&'a mut self, manager: &mut StateManager) -> &'a mut T {
2199        manager.mutate_id(&self.id);
2200        &mut self.value
2201    }
2202}
2203
2204impl<T> std::borrow::Borrow<T> for StateCell<T> {
2205    fn borrow(&self) -> &T {
2206        &self.value
2207    }
2208}
2209
2210impl<T> std::ops::Deref for StateCell<T> {
2211    type Target = T;
2212
2213    #[inline]
2214    fn deref(&self) -> &T {
2215        &self.value
2216    }
2217}*/
2218
2219/// `AccessCell` allows feather to track when a value passed into a function has actually been
2220/// changed, by tracking if a mutable borrow has been requested. Like [`std::cell::RefCell`], it
2221/// implements [`std::borrow::Borrow`] and [`std::borrow::BorrowMut`], but also implements the
2222/// [`std::ops::Deref`] and [`std::ops::DerefMut`] operators so it can be used more like a smart
2223/// pointer.
2224///
2225/// Generally speaking, **this type should never be constructed** - it is used at Feather's API
2226/// boundaries where appropriate.
2227///
2228/// # Examples
2229///
2230/// ```
2231/// use feather_ui::AccessCell;
2232///
2233/// struct FooBar {
2234///   i: i32,
2235/// }
2236///
2237/// fn change(change: bool, mut v: AccessCell<FooBar>) {
2238///     if change {
2239///         // FooBar only marked as changed once this mutable access happens
2240///         v.i = 4;
2241///     }
2242/// }
2243///
2244/// ```
2245///
2246/// # Future-proofing
2247/// Currently, `AccessCell` does not attempt to determine if the new value is actually *different*
2248/// than what was previously stored, because this would be a very expensive comparison. However,
2249/// in the future, a specialization of AccessCell for Persistent data structures that only marks
2250/// the value as changed if it is actually different when the AccessCell is dropped might be
2251/// implemented. As a result, you should assume that AccessCell implements [`Drop`] even if it
2252/// technically doesn't right now.
2253pub struct AccessCell<'a, 'b, T> {
2254    value: &'a mut T,
2255    changed: &'b mut bool,
2256}
2257
2258impl<'a, 'b, T> std::borrow::BorrowMut<T> for AccessCell<'a, 'b, T> {
2259    #[inline]
2260    fn borrow_mut(&mut self) -> &mut T {
2261        // TODO: Later, this can be optimized for persistent data structures by cloning the state here,
2262        // then comparing the resulting value with the original value when this cell is dropped and only
2263        // setting changed to true if it was actually modified.
2264        *self.changed = true;
2265        self.value
2266    }
2267}
2268
2269impl<'a, 'b, T> std::borrow::Borrow<T> for AccessCell<'a, 'b, T> {
2270    #[inline]
2271    fn borrow(&self) -> &T {
2272        self.value
2273    }
2274}
2275
2276impl<'a, 'b, T> std::ops::Deref for AccessCell<'a, 'b, T> {
2277    type Target = T;
2278
2279    #[inline]
2280    fn deref(&self) -> &T {
2281        self.value
2282    }
2283}
2284
2285impl<'a, 'b, T> std::ops::DerefMut for AccessCell<'a, 'b, T> {
2286    fn deref_mut(&mut self) -> &mut Self::Target {
2287        *self.changed = true;
2288        self.value
2289    }
2290}
2291
2292#[test]
2293fn test_access_cell() {
2294    struct FooBar {
2295        i: i32,
2296    }
2297
2298    fn change(change: bool, mut v: AccessCell<FooBar>) {
2299        if change {
2300            v.i = 4;
2301        }
2302    }
2303    let mut foobar = FooBar { i: 1 };
2304    let mut tracker = false;
2305
2306    let accessor = AccessCell {
2307        value: &mut foobar,
2308        changed: &mut tracker,
2309    };
2310    change(false, accessor);
2311    assert_eq!(foobar.i, 1);
2312    assert_eq!(tracker, false);
2313
2314    let accessor = AccessCell {
2315        value: &mut foobar,
2316        changed: &mut tracker,
2317    };
2318    change(true, accessor);
2319    assert_eq!(foobar.i, 4);
2320    assert_eq!(tracker, true);
2321}
2322
2323/// `StateManager` is used to manage the mutable state associated with a particular component's ID.
2324/// Because components technically only exist while a layout tree is being calculated, this is
2325/// where a component is expected to store all it's durable state that must survive through the
2326/// next layout pass. The StateManager also requires that all components implement
2327/// [`StateMachineChild`], even if they are stateless. A derive macro is provided for this case.
2328/// Likewise, the internal state object must implement [`event::EventRouter`], even if it doesn't process
2329/// any events, in which case it can simply set Input and Output to [`std::convert::Infallible`]
2330///
2331///
2332/// All components can access their own state by calling [`StateManager::get`] with their ID and
2333/// the [`component::StateMachine`] wrapper type around their internal state object, which should have been
2334/// created earlier by feather automatically calling [`StateMachineChild::init`].
2335///
2336/// # Examples
2337///
2338/// ```
2339/// use feather_ui::{SourceID, StateManager, component::StateMachine, event::EventRouter};
2340/// use std::sync::Arc;
2341/// use std::convert::Infallible;
2342///
2343/// #[derive(Clone, PartialEq)]
2344/// struct FooBar {
2345///   i: i32
2346/// }
2347///
2348/// impl EventRouter for FooBar {
2349///    type Input = Infallible;
2350///    type Output = Infallible;
2351/// }
2352///
2353/// fn layout(id: Arc<SourceID>, manager: &mut StateManager) {
2354///     let outer = manager.get_mut::<StateMachine<FooBar, 0>>(&id).unwrap();
2355///     outer.state.i = 3;
2356/// }
2357/// ```
2358///
2359/// A component can even retrieve a *different* component's internal state as long as it has the
2360/// ID and knows the type of the inner state. This is how most feather components get the DPI
2361/// for the current window.
2362///
2363/// ```
2364/// use feather_ui::{SourceID, StateManager, component::StateMachine, event::EventRouter};
2365/// use std::sync::Arc;
2366/// use std::convert::Infallible;
2367/// use feather_ui::component::window::WindowStateMachine;
2368///
2369/// #[derive(Clone, PartialEq)]
2370/// struct FooBar {
2371///   i: i32
2372/// }
2373///
2374/// impl EventRouter for FooBar {
2375///    type Input = Infallible;
2376///    type Output = Infallible;
2377/// }
2378///
2379/// fn layout(
2380///     manager: &mut StateManager,
2381///     window: &Arc<SourceID>,
2382/// ) {
2383/// let dpi = manager
2384///     .get::<WindowStateMachine>(window)
2385///     .map(|x| x.state.dpi)
2386///     .unwrap_or(feather_ui::BASE_DPI);
2387/// println!("{dpi:?}");
2388/// }
2389/// ```
2390#[derive(Default)]
2391pub struct StateManager {
2392    states: HashMap<Arc<SourceID>, Box<dyn StateMachineWrapper>>,
2393    pointers: HashMap<*const c_void, Arc<SourceID>>,
2394    changed: bool,
2395}
2396
2397impl StateManager {
2398    pub fn register_pointer<T>(&mut self, p: *const T, id: Arc<SourceID>) -> Option<Arc<SourceID>> {
2399        let ptr = p as *const c_void;
2400        self.pointers.insert(ptr, id)
2401    }
2402
2403    pub fn invalidate_pointer<T>(&mut self, p: *const T) -> Option<Arc<SourceID>> {
2404        let ptr = p as *const c_void;
2405        self.pointers.remove(&ptr)
2406    }
2407
2408    pub fn mutate_pointer<T>(&mut self, p: *const T) {
2409        let ptr = p as *const c_void;
2410        let id = self
2411            .pointers
2412            .get(&ptr)
2413            .expect("Tried to mutate pointer that wasn't registered!")
2414            .clone();
2415
2416        self.mutate_id(&id);
2417    }
2418
2419    fn mutate_id(&mut self, id: &Arc<SourceID>) {
2420        if let Some(state) = self.states.get_mut(id) {
2421            state.set_changed(true);
2422            self.propagate_change(id);
2423        }
2424    }
2425
2426    #[allow(dead_code)]
2427    fn init_default<State: 'static + component::StateMachineWrapper + Default>(
2428        &mut self,
2429        id: Arc<SourceID>,
2430    ) -> eyre::Result<&mut State> {
2431        if !self.states.contains_key(&id) {
2432            self.states.insert(id.clone(), Box::new(State::default()));
2433        }
2434        let v = &mut *self
2435            .states
2436            .get_mut(&id)
2437            .ok_or_eyre("Failed to insert state!")?
2438            .as_mut() as &mut dyn Any;
2439        v.downcast_mut().ok_or(Error::RuntimeTypeMismatch.into())
2440    }
2441    fn init(&mut self, id: Arc<SourceID>, state: Box<dyn StateMachineWrapper>) {
2442        if !self.states.contains_key(&id) {
2443            self.states.insert(id.clone(), state);
2444        }
2445    }
2446
2447    /// Gets a reference to a state for the given `id`. Returns an error if the state doesn't
2448    /// exist or if the requested type doesn't match.
2449    pub fn get<'a, State: 'static + component::StateMachineWrapper>(
2450        &'a self,
2451        id: &SourceID,
2452    ) -> eyre::Result<&'a State> {
2453        let v = self
2454            .states
2455            .get(id)
2456            .ok_or_eyre("State does not exist")?
2457            .as_ref() as &dyn Any;
2458        v.downcast_ref().ok_or(Error::RuntimeTypeMismatch.into())
2459    }
2460
2461    /// Gets a **mutable** reference to a state for the given `id`. Returns an error if the
2462    /// state doesn't exist or if the requested type doesn't match.
2463    pub fn get_mut<'a, State: 'static + component::StateMachineWrapper>(
2464        &'a mut self,
2465        id: &SourceID,
2466    ) -> eyre::Result<&'a mut State> {
2467        let v = &mut *self
2468            .states
2469            .get_mut(id)
2470            .ok_or_eyre("State does not exist")?
2471            .as_mut() as &mut dyn Any;
2472        v.downcast_mut().ok_or(Error::RuntimeTypeMismatch.into())
2473    }
2474
2475    #[allow(clippy::borrowed_box)]
2476    fn get_trait<'a>(&'a self, id: &SourceID) -> eyre::Result<&'a Box<dyn StateMachineWrapper>> {
2477        self.states.get(id).ok_or_eyre("State does not exist")
2478    }
2479
2480    fn propagate_change(&mut self, mut id: &Arc<SourceID>) {
2481        while let Some(parent) = id.parent.as_ref() {
2482            if let Some(state) = self.states.get_mut(parent) {
2483                if state.changed() {
2484                    // If this state is marked change, then this change must have already propagated upwards and we have no more work to do.
2485                    return;
2486                }
2487                state.set_changed(true);
2488            }
2489            id = parent;
2490        }
2491    }
2492
2493    fn process(
2494        &mut self,
2495        event: DispatchPair,
2496        slot: &Slot,
2497        dpi: RelDim,
2498        area: PxRect,
2499        extent: PxRect,
2500        driver: &std::sync::Weak<crate::Driver>,
2501    ) -> eyre::Result<bool> {
2502        type IterTuple = (Box<dyn Any>, u64, Option<Slot>);
2503
2504        // We use smallvec here so we can satisfy the borrow checker without making yet another heap allocation in most cases
2505        let mut handled = false;
2506        let iter: SmallVec<[IterTuple; 2]> = {
2507            let state = self.states.get_mut(&slot.0).ok_or_eyre("Invalid slot")?;
2508            let v = match state.process(event, slot.1, dpi, area, extent, driver) {
2509                InputResult::Consume(v) => {
2510                    handled |= v.is_empty();
2511                    v
2512                }
2513                InputResult::Forward(v) => v,
2514                InputResult::Error(error) => return Err(error),
2515            };
2516            if state.changed() {
2517                self.changed = true;
2518                self.propagate_change(&slot.0);
2519            }
2520
2521            let state = self.states.get(&slot.0).ok_or(Error::InternalFailure)?;
2522
2523            v.into_iter()
2524                .map(|(i, e)| (e, i, state.output_slot(i.ilog2() as usize).unwrap().clone()))
2525        }
2526        .collect();
2527
2528        for (e, index, slot) in iter {
2529            if let Some(s) = slot.as_ref() {
2530                handled |= self.process((index, e), s, dpi, area, extent, driver)?;
2531            }
2532        }
2533
2534        Ok(handled)
2535    }
2536
2537    fn init_child(
2538        &mut self,
2539        target: &dyn StateMachineChild,
2540        driver: &std::sync::Weak<Driver>,
2541    ) -> eyre::Result<()> {
2542        if !self.states.contains_key(&target.id()) {
2543            match target.init(driver) {
2544                Ok(v) => self.init(target.id().clone(), v),
2545                Err(Error::Stateless) => (),
2546                Err(e) => return Err(e.into()),
2547            };
2548        }
2549
2550        target.apply_children(&mut |child| self.init_child(child, driver))
2551    }
2552}
2553
2554/// This is the root ID for the application itself, representing the user's AppState. All IDs are derived
2555/// from this root ID, and this is the only ID that is allowed to have a parent of [`None`]
2556#[allow(clippy::declare_interior_mutable_const)]
2557pub const APP_SOURCE_ID: SourceID = SourceID {
2558    parent: None,
2559    id: DataID::Named("__fg_AppData_ID__"),
2560};
2561
2562type OutlineReturn = im::HashMap<Arc<SourceID>, Option<Window>>;
2563pub type EventPair<AppData> = (u64, AppEvent<AppData>);
2564
2565/// Represents a feather application with a given `AppData` and persistent outline function `O`.
2566/// The outline function must always be a persistent function that takes two parameters, a copy
2567/// of the AppData, and a ScopeID. It must always return [`OutlineReturn`].
2568///
2569/// An App creates all the top level structures needed for Feather to function. It stores all
2570/// wgpu, winit, and any other global state needed. See [`App::new`] for examples.
2571pub struct App<AppData, O: FnPersist2<AppData, ScopeID<'static>, OutlineReturn>> {
2572    pub instance: wgpu::Instance,
2573    pub driver: std::sync::Weak<graphics::Driver>,
2574    pub state: StateManager,
2575    store: Option<O::Store>,
2576    outline: O,
2577    _parents: BTreeMap<DataID, DataID>,
2578    root: component::Root, // Root component node containing all windows
2579    driver_init: Option<Box<dyn FnOnce(std::sync::Weak<Driver>) + 'static>>,
2580    _phantom: PhantomData<AppData>,
2581    handle_sync: mpsc::Receiver<EventPair<AppData>>,
2582}
2583
2584pub struct AppDataMachine<AppData> {
2585    pub state: AppData,
2586    handlers: HashMap<usize, AppEvent<AppData>>,
2587    changed: bool,
2588}
2589
2590impl<AppData: 'static + PartialEq> StateMachineWrapper for AppDataMachine<AppData> {
2591    fn output_slot(&self, _: usize) -> eyre::Result<&Option<Slot>> {
2592        Ok(&None)
2593    }
2594
2595    fn input_mask(&self) -> u64 {
2596        0
2597    }
2598
2599    fn changed(&self) -> bool {
2600        self.changed
2601    }
2602
2603    fn set_changed(&mut self, changed: bool) {
2604        self.changed = changed;
2605    }
2606
2607    fn process(
2608        &mut self,
2609        input: DispatchPair,
2610        index: u64,
2611        _: RelDim,
2612        _: PxRect,
2613        _: PxRect,
2614        _: &std::sync::Weak<crate::Driver>,
2615    ) -> InputResult<SmallVec<[DispatchPair; 1]>> {
2616        if let Some(f) = self.handlers.get_mut(&(index as usize)) {
2617            let cell = AccessCell {
2618                value: &mut self.state,
2619                changed: &mut self.changed,
2620            };
2621            f(input, cell).map(|_| SmallVec::new())
2622        } else {
2623            InputResult::Error(Error::InternalFailure.into())
2624        }
2625    }
2626}
2627#[cfg(target_os = "windows")]
2628use winit::platform::windows::EventLoopBuilderExtWindows;
2629
2630//  This logic is the same for both X11 and Wayland because the any_thread variable is the same on both
2631#[cfg(target_os = "linux")]
2632use winit::platform::x11::EventLoopBuilderExtX11;
2633
2634impl<AppData: Clone + PartialEq + 'static, O: FnPersist2<AppData, ScopeID<'static>, OutlineReturn>>
2635    App<AppData, O>
2636{
2637    /// Creates a new feather application. `app_state` represents the initial state of the application, and
2638    /// will override any value returned by `<O as FnPersist2>::init()`. `inputs` must be an array of
2639    /// [`AppEvent`], which can be acquired by boxing and wrapping lambdas using [`WrapEventEx`]. The `outline`
2640    /// must by a persistent function that takes two arguments (and implements [`FnPersist2`]): a copy
2641    /// of the AppData, and a ScopeID. It must always return [`OutlineReturn`].
2642    ///
2643    /// `driver_init` is an *optional* hook used to enable hotloading of resources. For most basic applications,
2644    /// it can be set to the empty lambda: `|_| ()`.
2645    ///
2646    /// This function returns 4 values - the [`App`] object itself, the [`EventLoop`] that you must call
2647    /// [`EventLoop::run_app`] on to actually start the application, a channel for sending dynamic `AppEvent`
2648    /// handlers, and an atomic integer representing the current dynamic slot for any additional events. If
2649    /// your handlers are not going to change after the app has been created, you can ignore the last 2 returns.
2650    ///
2651    /// # Examples
2652    /// ```
2653    /// use feather_ui::component::window::Window;
2654    /// use feather_ui::persist::{ FnPersist2, FnPersistStore };
2655    /// use feather_ui::{ SourceID, ScopeID, App };
2656    /// use std::sync::Arc;
2657    ///
2658    /// #[derive(Clone, PartialEq)]
2659    /// struct MyState {
2660    ///   count: i32
2661    /// }
2662    ///
2663    /// struct MyApp {}
2664    ///
2665    /// impl FnPersistStore for MyApp { type Store = (); }
2666    ///
2667    /// impl FnPersist2<MyState, ScopeID<'_>, im::HashMap<Arc<SourceID>, Option<Window>>> for MyApp {
2668    ///     fn init(&self) -> Self::Store { () }
2669    ///
2670    ///     fn call(&mut self,  _: Self::Store,  _: MyState, _: ScopeID<'_>) -> (Self::Store, im::HashMap<Arc<SourceID>, Option<Window>>) {
2671    ///         ((), im::HashMap::new())
2672    ///     }
2673    /// }
2674    ///
2675    /// let (mut app, event_loop, _, _) = App::<MyState, MyApp>::new::<()>(MyState { count: 0 }, Vec::new(), MyApp {}, |_| ()).unwrap();
2676    ///
2677    /// // You would then run the app like so (commented out because docs can't test UIs)
2678    /// // event_loop.run_app(&mut app).unwrap();
2679    /// ```
2680    #[allow(clippy::type_complexity)]
2681    pub fn new<T: 'static>(
2682        app_state: AppData,
2683        inputs: Vec<AppEvent<AppData>>,
2684        outline: O,
2685        driver_init: impl FnOnce(std::sync::Weak<Driver>) + 'static,
2686    ) -> eyre::Result<(
2687        Self,
2688        EventLoop<T>,
2689        mpsc::Sender<EventPair<AppData>>,
2690        AtomicU64,
2691    )> {
2692        #[cfg(test)]
2693        let any_thread = true;
2694        #[cfg(not(test))]
2695        let any_thread = false;
2696
2697        Self::new_any_thread(app_state, inputs, outline, any_thread, driver_init)
2698    }
2699
2700    /// This is the same as [`App::new`], but it allows overriding the main thread detection that winit uses. This is necessary
2701    /// for running tests, which don't run on the main thread.
2702    #[allow(clippy::type_complexity)]
2703    pub fn new_any_thread<T: 'static>(
2704        app_state: AppData,
2705        inputs: Vec<AppEvent<AppData>>,
2706        outline: O,
2707        any_thread: bool,
2708        driver_init: impl FnOnce(std::sync::Weak<Driver>) + 'static,
2709    ) -> eyre::Result<(
2710        Self,
2711        EventLoop<T>,
2712        mpsc::Sender<EventPair<AppData>>,
2713        AtomicU64,
2714    )> {
2715        let count = AtomicU64::new(inputs.len() as u64);
2716        let mut manager: StateManager = Default::default();
2717        manager.init(
2718            Arc::new(APP_SOURCE_ID),
2719            Box::new(AppDataMachine {
2720                handlers: HashMap::from_iter(inputs.into_iter().enumerate()),
2721                state: app_state,
2722                changed: true,
2723            }),
2724        );
2725
2726        #[cfg(target_os = "windows")]
2727        let event_loop = EventLoop::with_user_event()
2728            .with_any_thread(any_thread)
2729            .with_dpi_aware(true)
2730            .build()?;
2731        #[cfg(not(target_os = "windows"))]
2732        let event_loop = EventLoop::with_user_event()
2733            .with_any_thread(any_thread)
2734            .build()
2735            .map_err(|e| {
2736                if e.to_string()
2737                    .eq_ignore_ascii_case("Could not find wayland compositor")
2738                {
2739                    eyre::eyre!(
2740                        "Wayland initialization failed! winit cannot automatically fall back to X11 (). Try running the program with `WAYLAND_DISPLAY=\"\"`"
2741                    )
2742                } else {
2743                    e.into()
2744                }
2745            })?;
2746
2747        #[cfg(debug_assertions)]
2748        let desc = InstanceDescriptor {
2749            flags: InstanceFlags::debugging(),
2750            ..Default::default()
2751        };
2752        #[cfg(not(debug_assertions))]
2753        let desc = InstanceDescriptor {
2754            flags: InstanceFlags::DISCARD_HAL_LABELS,
2755            ..Default::default()
2756        };
2757
2758        let (sender, recv) = mpsc::channel();
2759        Ok((
2760            Self {
2761                instance: wgpu::Instance::new(&desc),
2762                driver: std::sync::Weak::<graphics::Driver>::new(),
2763                store: None,
2764                outline,
2765                state: manager,
2766                _parents: Default::default(),
2767                root: component::Root::new(),
2768                driver_init: Some(Box::new(driver_init)),
2769                _phantom: PhantomData,
2770                handle_sync: recv,
2771            },
2772            event_loop,
2773            sender,
2774            count,
2775        ))
2776    }
2777
2778    #[allow(clippy::borrow_interior_mutable_const)]
2779    fn update_outline(&mut self, event_loop: &ActiveEventLoop, store: O::Store) {
2780        let app_state: &mut AppDataMachine<AppData> = self.state.get_mut(&APP_SOURCE_ID).unwrap();
2781
2782        for (idx, handler) in self.handle_sync.try_iter() {
2783            app_state.handlers.insert(idx as usize, handler);
2784        }
2785
2786        let (store, windows) = self
2787            .outline
2788            .call(store, app_state.state.clone(), ScopeID::root());
2789        debug_assert!(
2790            APP_SOURCE_ID.parent.is_none(),
2791            "Something set the APP_SOURCE parent! This should never happen!"
2792        );
2793
2794        self.store.replace(store);
2795        self.root.children = windows;
2796        #[cfg(debug_assertions)]
2797        self.root.validate_ids().unwrap();
2798
2799        let (root, manager, graphics, instance, driver_init) = (
2800            &mut self.root,
2801            &mut self.state,
2802            &mut self.driver,
2803            &mut self.instance,
2804            &mut self.driver_init,
2805        );
2806
2807        root.layout_all(manager, graphics, driver_init, instance, event_loop)
2808            .unwrap();
2809
2810        root.stage_all(manager).unwrap();
2811    }
2812}
2813
2814impl<
2815    AppData: Clone + PartialEq + 'static,
2816    T: 'static,
2817    O: FnPersist2<AppData, ScopeID<'static>, OutlineReturn>,
2818> winit::application::ApplicationHandler<T> for App<AppData, O>
2819{
2820    fn resumed(&mut self, event_loop: &ActiveEventLoop) {
2821        // If this is our first resume, call the start function that can create the necessary graphics context
2822        let store = self.store.take();
2823        self.update_outline(event_loop, store.unwrap_or_else(|| O::init(&self.outline)));
2824    }
2825    fn window_event(
2826        &mut self,
2827        event_loop: &ActiveEventLoop,
2828        window_id: WindowId,
2829        event: WindowEvent,
2830    ) {
2831        let mut delete = None;
2832        if let Some(root) = self.root.states.get_mut(&window_id) {
2833            let Some(rtree) = root.staging.as_ref().map(|x| x.get_rtree()) else {
2834                panic!("Got root state without valid staging!");
2835            };
2836
2837            if let Some(window) = self.root.children.get(&root.id) {
2838                let window = window.as_ref().unwrap();
2839                let mut resized = false;
2840                let _ = match event {
2841                    WindowEvent::CloseRequested => {
2842                        let v = Window::on_window_event(
2843                            window.id(),
2844                            rtree,
2845                            event,
2846                            &mut self.state,
2847                            self.driver.clone(),
2848                        );
2849                        if v.is_accept() {
2850                            delete = Some(window.id());
2851                        }
2852                        v
2853                    }
2854                    WindowEvent::RedrawRequested => {
2855                        if let Ok(state) = self.state.get_mut::<WindowStateMachine>(&window.id())
2856                            && let Some(driver) = self.driver.upgrade()
2857                        {
2858                            if let Some(staging) = root.staging.as_ref() {
2859                                let inner = &mut state.state;
2860                                let surface_dim = inner.surface_dim().to_f32();
2861
2862                                loop {
2863                                    // Construct a default compositor view with no offset.
2864                                    let mut viewer = CompositorView {
2865                                        index: 0,
2866                                        window: &mut inner.compositor,
2867                                        layer0: &mut driver.layer_composite[0].write(),
2868                                        layer1: &mut driver.layer_composite[1].write(),
2869                                        clipstack: &mut inner.clipstack,
2870                                        offset: PxVector::zero(),
2871                                        surface_dim,
2872                                        pass: 0,
2873                                        slice: 0,
2874                                    };
2875
2876                                    // Reset our layer tracker before beginning a render
2877                                    inner.layers.clear();
2878                                    viewer.clipstack.clear();
2879                                    if let Err(e) = staging.render(
2880                                        PxPoint::zero(),
2881                                        &driver,
2882                                        &mut viewer,
2883                                        &mut inner.layers,
2884                                    ) {
2885                                        match e {
2886                                            Error::ResizeTextureAtlas(layers, kind) => {
2887                                                // Resize the texture atlas with the requested number of layers (the extent has already been changed)
2888                                                match kind {
2889                                                    AtlasKind::Primary => driver.atlas.write(),
2890                                                    AtlasKind::Layer0 => {
2891                                                        driver.layer_atlas[0].write()
2892                                                    }
2893                                                    AtlasKind::Layer1 => {
2894                                                        driver.layer_atlas[1].write()
2895                                                    }
2896                                                }
2897                                                .resize(&driver.device, &driver.queue, layers);
2898                                                viewer.window.cleanup();
2899                                                viewer.layer0.cleanup();
2900                                                viewer.layer1.cleanup();
2901                                                continue; // Retry frame
2902                                            }
2903                                            e => panic!("Fatal draw error: {e}"),
2904                                        }
2905                                    }
2906                                    break;
2907                                }
2908                            }
2909
2910                            let mut encoder = driver.device.create_command_encoder(
2911                                &wgpu::CommandEncoderDescriptor {
2912                                    label: Some("Root Encoder"),
2913                                },
2914                            );
2915
2916                            driver.atlas.write().process_mipmaps(&driver, &mut encoder);
2917                            driver.atlas.read().draw(&driver, &mut encoder);
2918
2919                            let max_depth = driver.layer_composite[0]
2920                                .read()
2921                                .segments
2922                                .len()
2923                                .max(driver.layer_composite[1].read().segments.len());
2924
2925                            for i in 0..2 {
2926                                let surface_dim = driver.layer_atlas[i].read().texture.size();
2927                                driver.layer_composite[i].write().prepare(
2928                                    &driver,
2929                                    &mut encoder,
2930                                    Size2D::<u32, Pixel>::new(
2931                                        surface_dim.width,
2932                                        surface_dim.height,
2933                                    )
2934                                    .to_f32(),
2935                                );
2936                            }
2937
2938                            // A depth of "zero" means the window compositor, so we only go down to 1.
2939                            for i in (1..max_depth).rev() {
2940                                // Odd is layer0, even is layer1, so we add one before modulo to reverse the result
2941                                let idx: usize = (i + 1) % 2;
2942                                let mut compositor = driver.layer_composite[idx].write();
2943                                let atlas = driver.layer_atlas[idx].read();
2944
2945                                // We create one render pass for each slice of the layer atlas
2946                                for slice in 0..atlas.texture.depth_or_array_layers() {
2947                                    let name = format!(
2948                                        "Layer {idx} (depth {i}) Atlas (slice {slice}) Pass"
2949                                    );
2950                                    let mut pass =
2951                                        encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
2952                                            label: Some(&name),
2953                                            color_attachments: &[Some(
2954                                                wgpu::RenderPassColorAttachment {
2955                                                    view: &atlas.targets[slice as usize],
2956                                                    resolve_target: None,
2957                                                    depth_slice: None,
2958                                                    ops: wgpu::Operations {
2959                                                        load: if true {
2960                                                            wgpu::LoadOp::Clear(
2961                                                                wgpu::Color::TRANSPARENT,
2962                                                            )
2963                                                        } else {
2964                                                            wgpu::LoadOp::Load
2965                                                        },
2966                                                        store: wgpu::StoreOp::Store,
2967                                                    },
2968                                                },
2969                                            )],
2970                                            depth_stencil_attachment: None,
2971                                            timestamp_writes: None,
2972                                            occlusion_query_set: None,
2973                                        });
2974
2975                                    pass.set_viewport(
2976                                        0.0,
2977                                        0.0,
2978                                        atlas.texture.width() as f32,
2979                                        atlas.texture.height() as f32,
2980                                        0.0,
2981                                        1.0,
2982                                    );
2983
2984                                    compositor.draw(&driver, &mut pass, i as u8, slice as u8);
2985                                }
2986                            }
2987
2988                            state.state.draw(encoder);
2989                            driver.layer_composite[0].write().cleanup();
2990                            driver.layer_composite[1].write().cleanup();
2991                        }
2992
2993                        InputResult::Consume(())
2994                    }
2995                    WindowEvent::Resized(_) => {
2996                        resized = true;
2997                        Window::on_window_event(
2998                            window.id(),
2999                            rtree,
3000                            event,
3001                            &mut self.state,
3002                            self.driver.clone(),
3003                        )
3004                    }
3005                    _ => Window::on_window_event(
3006                        window.id(),
3007                        rtree,
3008                        event,
3009                        &mut self.state,
3010                        self.driver.clone(),
3011                    ),
3012                };
3013
3014                if self.state.changed || resized {
3015                    self.state.changed = false;
3016                    let store = self.store.take().unwrap();
3017                    self.update_outline(event_loop, store);
3018                }
3019            }
3020        }
3021
3022        if let Some(id) = delete {
3023            self.root.children.remove(&id);
3024        }
3025
3026        if self.root.children.is_empty() {
3027            event_loop.exit();
3028        }
3029    }
3030
3031    fn device_event(
3032        &mut self,
3033        event_loop: &ActiveEventLoop,
3034        device_id: winit::event::DeviceId,
3035        event: winit::event::DeviceEvent,
3036    ) {
3037        let _ = (event_loop, device_id, event);
3038    }
3039
3040    fn user_event(&mut self, event_loop: &ActiveEventLoop, _: T) {
3041        event_loop.exit();
3042    }
3043
3044    fn suspended(&mut self, event_loop: &ActiveEventLoop) {
3045        let _ = event_loop;
3046    }
3047}
3048
3049#[cfg(test)]
3050struct TestApp {}
3051
3052#[cfg(test)]
3053impl crate::persist::FnPersistStore for TestApp {
3054    type Store = (u8, OutlineReturn);
3055}
3056
3057#[cfg(test)]
3058impl FnPersist2<u8, ScopeID<'static>, OutlineReturn> for TestApp {
3059    fn init(&self) -> Self::Store {
3060        (0, im::HashMap::new())
3061    }
3062
3063    fn call(
3064        &mut self,
3065        store: Self::Store,
3066        _: u8,
3067        mut id: ScopeID<'static>,
3068    ) -> (Self::Store, OutlineReturn) {
3069        use crate::color::sRGB;
3070        use crate::component::shape::Shape;
3071
3072        let rect = Shape::<DRect, { component::shape::ShapeKind::RoundRect as u8 }>::new(
3073            gen_id!(id),
3074            crate::FILL_DRECT.into(),
3075            0.0,
3076            0.0,
3077            f32x4::splat(0.0),
3078            sRGB::new(1.0, 0.0, 0.0, 1.0),
3079            sRGB::transparent(),
3080            DAbsPoint::zero(),
3081        );
3082        let window = Window::new(
3083            gen_id!(id),
3084            winit::window::Window::default_attributes()
3085                .with_title("test_blank")
3086                .with_resizable(true),
3087            Box::new(rect),
3088        );
3089
3090        let mut windows = im::HashMap::new();
3091        windows.insert(window.id().clone(), Some(window));
3092
3093        (store, windows)
3094    }
3095}
3096
3097#[test]
3098fn test_basic() {
3099    let (mut app, event_loop, _, _) =
3100        App::<u8, TestApp>::new::<()>(0u8, vec![], TestApp {}, |_| ()).unwrap();
3101
3102    let proxy = event_loop.create_proxy();
3103    proxy.send_event(()).unwrap();
3104    event_loop.run_app(&mut app).unwrap();
3105}
3106
3107#[test]
3108fn test_absrect_contain() {
3109    let target = AbsRect::new(0.0, 0.0, 2.0, 2.0);
3110
3111    for x in 0..=2 {
3112        for y in 0..=2 {
3113            if x == 2 || y == 2 {
3114                assert!(!target.contains(AbsPoint::new(x as f32, y as f32)));
3115            } else {
3116                assert!(
3117                    target.contains(AbsPoint::new(x as f32, y as f32)),
3118                    "{x} {y} not inside {target}"
3119                );
3120            }
3121        }
3122    }
3123
3124    assert!(target.contains(AbsPoint::new(1.999, 1.999)));
3125
3126    for y in -1..=3 {
3127        assert!(!target.contains(AbsPoint::new(-1.0, y as f32)));
3128        assert!(!target.contains(AbsPoint::new(3.0, y as f32)));
3129        assert!(!target.contains(AbsPoint::new(3000000.0, y as f32)));
3130    }
3131
3132    for x in -1..=3 {
3133        assert!(!target.contains(AbsPoint::new(x as f32, -1.0)));
3134        assert!(!target.contains(AbsPoint::new(x as f32, 3.0)));
3135        assert!(!target.contains(AbsPoint::new(x as f32, -3000000.0)));
3136    }
3137}
3138
3139#[test]
3140fn test_absrect_collide() {
3141    let target = AbsRect::new(0.0, 0.0, 4.0, 4.0);
3142
3143    for l in 0..=3 {
3144        for t in 0..=3 {
3145            for r in 1..=4 {
3146                for b in 1..=4 {
3147                    let rhs = AbsRect::new(l as f32, t as f32, r as f32, b as f32);
3148                    assert!(
3149                        target.collides(&rhs),
3150                        "{target} not detected as touching {rhs}"
3151                    );
3152                }
3153            }
3154        }
3155    }
3156
3157    for l in -2..=3 {
3158        for t in -2..=3 {
3159            for r in 1..=4 {
3160                for b in 1..=4 {
3161                    assert!(target.collides(&AbsRect::new(l as f32, t as f32, r as f32, b as f32)));
3162                }
3163            }
3164        }
3165    }
3166
3167    for l in 1..=3 {
3168        for t in 1..=3 {
3169            for r in 3..=6 {
3170                if r > t {
3171                    for b in 3..=6 {
3172                        if b > t {
3173                            let rhs = AbsRect::new(l as f32, t as f32, r as f32, b as f32);
3174                            assert!(
3175                                target.collides(&rhs),
3176                                "{target} not detected as touching {rhs}"
3177                            );
3178                        }
3179                    }
3180                }
3181            }
3182        }
3183    }
3184
3185    assert!(!target.collides(&AbsRect::new(1.0, 4.0, 5.0, 5.0)));
3186
3187    // Because our rectangles are technically supposed to be inclusive-exclusive, they should not collide if the bottomright is coincident with the topleft.
3188    assert!(!target.collides(&AbsRect::new(4.0, 4.0, 5.0, 5.0)));
3189    assert!(!target.collides(&AbsRect::new(4.0, 0.0, 5.0, 4.0)));
3190    assert!(!target.collides(&AbsRect::new(0.0, 4.0, 4.0, 5.0)));
3191
3192    assert!(!target.collides(&AbsRect::new(-1.0, -1.0, 0.0, 0.0)));
3193    assert!(!target.collides(&AbsRect::new(-1.0, 0.0, 0.0, 4.0)));
3194    assert!(!target.collides(&AbsRect::new(0.0, -1.0, 4.0, 0.0)));
3195}
3196
3197#[test]
3198fn test_absrect_intersect() {
3199    let target = AbsRect::new(0.0, 0.0, 4.0, 4.0);
3200
3201    assert!(target.intersect(AbsRect::new(2.0, 2.0, 6.0, 6.0)) == AbsRect::new(2.0, 2.0, 4.0, 4.0));
3202    assert!(
3203        target.intersect(AbsRect::new(-2.0, -2.0, 2.0, 2.0)) == AbsRect::new(0.0, 0.0, 2.0, 2.0)
3204    );
3205
3206    assert!(
3207        target.intersect(AbsRect::new(-2.0, -2.0, -1.0, -1.0)) == AbsRect::new(0.0, 0.0, 0.0, 0.0)
3208    );
3209
3210    assert!(target.intersect(AbsRect::new(6.0, 6.0, 8.0, 8.0)) == AbsRect::new(6.0, 6.0, 6.0, 6.0));
3211}
3212
3213#[test]
3214fn test_absrect_extend() {
3215    let target = AbsRect::new(0.0, 0.0, 4.0, 4.0);
3216
3217    assert!(target.extend(AbsRect::new(2.0, 2.0, 6.0, 6.0)) == AbsRect::new(0.0, 0.0, 6.0, 6.0));
3218    assert!(
3219        target.extend(AbsRect::new(-2.0, -2.0, 2.0, 2.0)) == AbsRect::new(-2.0, -2.0, 4.0, 4.0)
3220    );
3221}
3222
3223#[test]
3224fn test_limits_add() {
3225    let limits = AbsLimits::new(.., 10.0..200.0);
3226    assert_eq!(
3227        limits.min(),
3228        Size2D::<f32, Logical>::new(f32::NEG_INFINITY, 10.0)
3229    );
3230    assert_eq!(
3231        limits.max(),
3232        Size2D::<f32, Logical>::new(f32::INFINITY, 200.0)
3233    );
3234
3235    let rlimits = RelLimits::new(..1.0, ..);
3236    assert_eq!(
3237        rlimits.min(),
3238        Size2D::<f32, Relative>::new(f32::NEG_INFINITY, f32::NEG_INFINITY)
3239    );
3240    assert_eq!(
3241        rlimits.max(),
3242        Size2D::<f32, Relative>::new(1.0, f32::INFINITY)
3243    );
3244
3245    let merged = AbsLimits::new(0.0.., 5.0..100.0) + limits;
3246    assert_eq!(merged.min(), Size2D::<f32, Logical>::new(0.0, 10.0));
3247    assert_eq!(
3248        merged.max(),
3249        Size2D::<f32, Logical>::new(f32::INFINITY, 100.0)
3250    );
3251}