use std::f64::INFINITY;
use crate::shell::kurbo::Size;
use crate::{BoxConstraints, Data, Env, Event, EventCtx, LayoutCtx, PaintCtx, UpdateCtx, Widget};
pub struct SizedBox<T: Data> {
inner: Option<Box<dyn Widget<T>>>,
width: Option<f64>,
height: Option<f64>,
}
impl<T: Data> SizedBox<T> {
pub fn new(inner: impl Widget<T> + 'static) -> Self {
Self {
inner: Some(Box::new(inner)),
width: None,
height: None,
}
}
pub fn empty() -> Self {
Self {
inner: None,
width: None,
height: None,
}
}
pub fn width(mut self, width: f64) -> Self {
self.width = Some(width);
self
}
pub fn height(mut self, height: f64) -> Self {
self.height = Some(height);
self
}
pub fn expand(mut self) -> Self {
self.width = Some(INFINITY);
self.height = Some(INFINITY);
self
}
}
impl<T: Data> Widget<T> for SizedBox<T> {
fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) {
if let Some(ref mut inner) = self.inner {
inner.event(ctx, event, data, env);
}
}
fn update(&mut self, ctx: &mut UpdateCtx, old_data: Option<&T>, data: &T, env: &Env) {
if let Some(ref mut inner) = self.inner {
inner.update(ctx, old_data, data, env);
}
}
fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints, data: &T, env: &Env) -> Size {
bc.debug_check("SizedBox");
match self.inner {
Some(ref mut inner) => {
let (min_width, max_width) = match self.width {
Some(width) => {
let w = width.max(bc.min().width).min(bc.max().width);
(w, w)
}
None => (bc.min().width, bc.max().width),
};
let (min_height, max_height) = match self.height {
Some(height) => {
let h = height.max(bc.min().height).min(bc.max().height);
(h, h)
}
None => (bc.min().height, bc.max().height),
};
let child_bc = BoxConstraints::new(
Size::new(min_width, min_height),
Size::new(max_width, max_height),
);
inner.layout(ctx, &child_bc, data, env)
}
None => bc.constrain((self.width.unwrap_or(0.0), self.height.unwrap_or(0.0))),
}
}
fn paint(&mut self, paint_ctx: &mut PaintCtx, data: &T, env: &Env) {
if let Some(ref mut inner) = self.inner {
inner.paint(paint_ctx, data, env);
}
}
}