use std::{
fmt::Debug,
sync::atomic::{AtomicU16, Ordering},
};
pub(crate) use self::widget::Node;
pub use self::{
type_erased::{Area, PrintInfo, RwArea, Ui, ui_is},
widget::Widget,
window::{Window, Windows},
};
use crate::{context::Handle, data::Pass};
pub mod layout;
pub mod traits;
mod type_erased;
mod widget;
mod window;
#[derive(Default, Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct Coord {
pub x: f32,
pub y: f32,
}
impl Coord {
pub const fn new(x: f32, y: f32) -> Self {
Self { x, y }
}
}
impl std::ops::Add for Coord {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self { x: self.x + rhs.x, y: self.y + rhs.y }
}
}
impl std::ops::Sub for Coord {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Self { x: self.x - rhs.x, y: self.y - rhs.y }
}
}
impl std::ops::Mul<f32> for Coord {
type Output = Self;
fn mul(self, rhs: f32) -> Self::Output {
Self { x: rhs * self.x, y: rhs * self.y }
}
}
impl std::ops::Mul<Coord> for f32 {
type Output = Coord;
fn mul(self, rhs: Coord) -> Self::Output {
Coord { x: self * rhs.x, y: self * rhs.y }
}
}
impl std::ops::Div<f32> for Coord {
type Output = Self;
fn div(self, rhs: f32) -> Self::Output {
Self { x: self.x / rhs, y: self.y / rhs }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Axis {
Horizontal,
Vertical,
}
impl Axis {
pub fn perp(&self) -> Self {
match self {
Axis::Horizontal => Axis::Vertical,
Axis::Vertical => Axis::Horizontal,
}
}
#[must_use]
pub fn is_hor(&self) -> bool {
matches!(self, Self::Horizontal)
}
#[must_use]
pub fn is_ver(&self) -> bool {
matches!(self, Self::Vertical)
}
}
impl From<PushSpecs> for Axis {
fn from(value: PushSpecs) -> Self {
match value.side {
Side::Above | Side::Below => Axis::Vertical,
_ => Axis::Horizontal,
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct PushSpecs {
pub side: Side,
pub width: Option<f32>,
pub height: Option<f32>,
pub hidden: bool,
pub cluster: bool,
}
impl Default for PushSpecs {
fn default() -> Self {
Self {
side: Side::Right,
width: None,
height: None,
hidden: false,
cluster: true,
}
}
}
impl PushSpecs {
pub const fn axis(&self) -> Axis {
match self.side {
Side::Above | Side::Below => Axis::Vertical,
Side::Right | Side::Left => Axis::Horizontal,
}
}
pub const fn comes_earlier(&self) -> bool {
matches!(self.side, Side::Left | Side::Above)
}
pub fn len_on(&self, axis: Axis) -> Option<f32> {
match axis {
Axis::Horizontal => self.width,
Axis::Vertical => self.height,
}
}
}
#[derive(Default, Debug, Clone, Copy)]
pub struct DynSpawnSpecs {
pub orientation: Orientation,
pub width: Option<f32>,
pub height: Option<f32>,
pub hidden: bool,
pub inside: bool,
}
impl DynSpawnSpecs {
pub const fn len_on(&self, axis: Axis) -> Option<f32> {
match axis {
Axis::Horizontal => self.width,
Axis::Vertical => self.height,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct StaticSpawnSpecs {
pub top_left: Coord,
pub size: Coord,
pub hidden: bool,
pub fractional_repositioning: Option<bool>,
}
impl StaticSpawnSpecs {
pub const fn len_on(&self, axis: Axis) -> f32 {
match axis {
Axis::Horizontal => self.size.x,
Axis::Vertical => self.size.y,
}
}
}
impl Default for StaticSpawnSpecs {
fn default() -> Self {
Self {
top_left: Coord { x: 0.0, y: 0.0 },
size: Coord { x: 50.0, y: 5.0 },
hidden: false,
fractional_repositioning: None,
}
}
}
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
pub enum Side {
Above,
#[default]
Right,
Below,
Left,
}
impl Side {
pub fn axis(&self) -> Axis {
match self {
Side::Above | Side::Below => Axis::Vertical,
Side::Right | Side::Left => Axis::Horizontal,
}
}
}
#[derive(Default, Debug, Clone, Copy)]
pub enum Orientation {
VerLeftAbove,
VerCenterAbove,
VerRightAbove,
#[default]
VerLeftBelow,
VerCenterBelow,
VerRightBelow,
HorTopLeft,
HorCenterLeft,
HorBottomLeft,
HorTopRight,
HorCenterRight,
HorBottomRight,
}
impl Orientation {
pub fn axis(&self) -> Axis {
match self {
Orientation::VerLeftAbove
| Orientation::VerCenterAbove
| Orientation::VerRightAbove
| Orientation::VerLeftBelow
| Orientation::VerCenterBelow
| Orientation::VerRightBelow => Axis::Vertical,
Orientation::HorTopLeft
| Orientation::HorCenterLeft
| Orientation::HorBottomLeft
| Orientation::HorTopRight
| Orientation::HorCenterRight
| Orientation::HorBottomRight => Axis::Horizontal,
}
}
pub fn prefers_before(&self) -> bool {
match self {
Orientation::VerLeftAbove
| Orientation::VerCenterAbove
| Orientation::VerRightAbove
| Orientation::HorTopLeft
| Orientation::HorCenterLeft
| Orientation::HorBottomLeft => true,
Orientation::VerLeftBelow
| Orientation::VerCenterBelow
| Orientation::VerRightBelow
| Orientation::HorTopRight
| Orientation::HorCenterRight
| Orientation::HorBottomRight => false,
}
}
}
pub trait PushTarget {
fn push_inner<PW: Widget>(&self, pa: &mut Pass, widget: PW, specs: PushSpecs) -> Handle<PW>;
fn push_outer<PW: Widget>(&self, pa: &mut Pass, widget: PW, specs: PushSpecs) -> Handle<PW>;
fn try_downcast<W: Widget>(&self) -> Option<Handle<W>>;
}
impl<W: Widget> PushTarget for Handle<W> {
#[doc(hidden)]
fn push_inner<PW: Widget>(&self, pa: &mut Pass, widget: PW, specs: PushSpecs) -> Handle<PW> {
self.push_inner_widget(pa, widget, specs)
}
#[doc(hidden)]
fn push_outer<PW: Widget>(&self, pa: &mut Pass, widget: PW, specs: PushSpecs) -> Handle<PW> {
self.push_outer_widget(pa, widget, specs)
}
fn try_downcast<DW: Widget>(&self) -> Option<Handle<DW>> {
self.try_downcast()
}
}
impl PushTarget for Window {
#[doc(hidden)]
fn push_inner<PW: Widget>(&self, pa: &mut Pass, widget: PW, specs: PushSpecs) -> Handle<PW> {
Window::push_inner(self, pa, widget, specs)
}
#[doc(hidden)]
fn push_outer<PW: Widget>(&self, pa: &mut Pass, widget: PW, specs: PushSpecs) -> Handle<PW> {
Window::push_outer(self, pa, widget, specs)
}
fn try_downcast<W: Widget>(&self) -> Option<Handle<W>> {
None
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SpawnId(u16);
impl SpawnId {
#[allow(clippy::new_without_default)]
pub(crate) fn new() -> Self {
static SPAWN_COUNT: AtomicU16 = AtomicU16::new(0);
Self(SPAWN_COUNT.fetch_add(1, Ordering::Relaxed))
}
}
impl std::fmt::Debug for SpawnId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "SpawnId({})", self.0)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PrintedLine {
pub number: usize,
pub is_wrapped: bool,
pub is_ghost: bool
}
pub struct Columns {
pub line: usize,
pub wrapped: usize,
pub len: usize,
}