use async_trait::async_trait; use crate::widgets::{ Background, Border, Either2, Either3, Float, JoinSegment, Layer, Padding, Resize, }; use crate::{Frame, Size, WidthDb}; // TODO Feature-gate these traits pub trait Widget { fn size( &self, widthdb: &mut WidthDb, max_width: Option, max_height: Option, ) -> Result; fn draw(self, frame: &mut Frame) -> Result<(), E>; } #[async_trait] pub trait AsyncWidget { async fn size( &self, widthdb: &mut WidthDb, max_width: Option, max_height: Option, ) -> Result; async fn draw(self, frame: &mut Frame) -> Result<(), E>; } pub trait WidgetExt: Sized { fn background(self) -> Background { Background::new(self) } fn border(self) -> Border { Border::new(self) } fn first2(self) -> Either2 { Either2::First(self) } fn second2(self) -> Either2 { Either2::Second(self) } fn first3(self) -> Either3 { Either3::First(self) } fn second3(self) -> Either3 { Either3::Second(self) } fn third3(self) -> Either3 { Either3::Third(self) } fn float(self) -> Float { Float::new(self) } fn segment(self) -> JoinSegment { JoinSegment::new(self) } fn below(self, above: W) -> Layer { Layer::new(self, above) } fn above(self, below: W) -> Layer { Layer::new(below, self) } fn padding(self) -> Padding { Padding::new(self) } fn resize(self) -> Resize { Resize::new(self) } } // It would be nice if this could be restricted to types implementing Widget. // However, Widget (and AsyncWidget) have the E type parameter, which WidgetExt // doesn't have. We sadly can't have unconstrained type parameters like that in // impl blocks. // // If WidgetExt had a type parameter E, we'd need to specify that parameter // everywhere we use the trait. This is less ergonomic than just constructing // the types manually. // // Blanket-implementing this trait is not great, but usually works fine. impl WidgetExt for W {}