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