use std::ops::Deref;
pub use lyon::math::{Box2D as Bounds, Point, Size, Transform};
pub use layout::Spacer;
pub use modifiers::fixed::{Fixed, FixedHeight, FixedWidth};
pub use modifiers::padding::Padding;
pub use output::{gpu, svg, Output};
pub use shapes::{Circle, ContinuousRoundedRectangle, Ellipse, Rectangle, RoundedRectangle};
pub use shapes::{Path, Shape};
#[doc(inline)]
pub use text::Text;
use crate::{From, TryInto};
pub type Offsets = lyon::geom::euclid::default::SideOffsets2D<f32>;
mod output;
pub mod text;
pub mod gesture;
mod layout;
mod modifiers;
mod shapes;
#[cfg(feature = "default_ui")]
pub mod ui;
pub trait View: Sized {
fn size(&self) -> Size;
#[allow(unused_variables)]
fn event(&self, event: Event, offset: Point, bounds: Bounds) {}
fn draw(&self, bounds: Bounds, onto: &mut impl Output);
fn padding(self, top: f32, right: f32, bottom: f32, left: f32) -> Padding<Self> {
Padding {
offsets: Offsets::new(top, right, bottom, left),
view: self,
}
}
fn padding_top(self, pad: f32) -> Padding<Self> {
self.padding(pad, 0.0, 0.0, 0.0)
}
fn padding_right(self, pad: f32) -> Padding<Self> {
self.padding(0.0, pad, 0.0, 0.0)
}
fn padding_bottom(self, pad: f32) -> Padding<Self> {
self.padding(0.0, 0.0, pad, 0.0)
}
fn padding_left(self, pad: f32) -> Padding<Self> {
self.padding(0.0, 0.0, 0.0, pad)
}
fn padding_horizontal(self, pad: f32) -> Padding<Self> {
self.padding(0.0, pad, 0.0, pad)
}
fn padding_vertical(self, pad: f32) -> Padding<Self> {
self.padding(0.0, 0.0, pad, 0.0)
}
fn padding_both(self, horizontal: f32, vertical: f32) -> Padding<Self> {
self.padding(vertical, horizontal, vertical, horizontal)
}
fn padding_all(self, pad: f32) -> Padding<Self> {
self.padding(pad, pad, pad, pad)
}
fn fixed(self, width: f32, height: f32) -> impl View {
let size = self.size();
if size.is_empty() {
return Err(Fixed {
size: Size::new(width, height),
view: self,
});
}
let horizontal = (width - size.width) / 2.0;
let vertical = (height - size.height) / 2.0;
Ok(self.padding_both(horizontal, vertical))
}
fn width(self, width: f32) -> impl View {
let size = self.size();
if size.is_empty() {
return Err(FixedWidth { width, view: self });
}
let horizontal = (width - size.width) / 2.0;
Ok(self.padding_horizontal(horizontal))
}
fn height(self, height: f32) -> impl View {
let size = self.size();
if size.is_empty() {
return Err(FixedHeight { height, view: self });
}
let vertical = (height - size.height) / 2.0;
Ok(self.padding_vertical(vertical))
}
#[doc(hidden)]
#[inline(always)]
fn needs_layout(&self) -> bool {
false
}
#[doc(hidden)]
#[inline(always)]
fn update_layout(&self, _size: Size, _bounds: Bounds) {}
fn across(self) -> impl View {
self
}
}
impl<T: View> View for Box<T> {
#[inline(always)]
fn size(&self) -> Size {
self.deref().size()
}
#[inline(always)]
fn event(&self, event: Event, offset: Point, bounds: Bounds) {
self.deref().event(event, offset, bounds)
}
#[inline(always)]
fn draw(&self, bounds: Bounds, onto: &mut impl Output) {
self.deref().draw(bounds, onto)
}
}
impl<T: View> View for Option<T> {
fn size(&self) -> Size {
if let Some(view) = self {
return view.size();
}
Size::zero()
}
fn event(&self, event: Event, offset: Point, bounds: Bounds) {
if let Some(view) = self {
view.event(event, offset, bounds)
}
}
fn draw(&self, bounds: Bounds, onto: &mut impl Output) {
if let Some(view) = self {
view.draw(bounds, onto)
}
}
}
impl<T: View, E: View> View for Result<T, E> {
fn size(&self) -> Size {
match self {
Ok(view) => view.size(),
Err(view) => view.size(),
}
}
fn event(&self, event: Event, offset: Point, bounds: Bounds) {
match self {
Ok(view) => view.event(event, offset, bounds),
Err(view) => view.event(event, offset, bounds),
}
}
fn draw(&self, bounds: Bounds, onto: &mut impl Output) {
match self {
Ok(view) => view.draw(bounds, onto),
Err(view) => view.draw(bounds, onto),
}
}
}
#[allow(missing_docs)]
#[derive(Copy, Clone, From, TryInto)]
pub enum Event {
Gesture(Gesture),
Resize { width: u32, height: u32 },
Redraw,
}
#[derive(Copy, Clone)]
pub enum Gesture {
Began { n: u8 },
Moved { n: u8 },
Ended { n: u8 },
}