use crate::piet::{FixedGradient, LinearGradient, PaintBrush, RadialGradient};
use crate::widget::prelude::*;
use crate::{Color, Data, Key};
use tracing::instrument;
pub struct Painter<T>(Box<dyn FnMut(&mut PaintCtx, &T, &Env)>);
#[non_exhaustive]
#[allow(missing_docs)]
pub enum BackgroundBrush<T> {
Color(Color),
ColorKey(Key<Color>),
Linear(LinearGradient),
Radial(RadialGradient),
Fixed(FixedGradient),
Painter(Painter<T>),
}
impl<T> Painter<T> {
pub fn new(f: impl FnMut(&mut PaintCtx, &T, &Env) + 'static) -> Self {
Painter(Box::new(f))
}
}
impl<T: Data> BackgroundBrush<T> {
pub fn update(&mut self, ctx: &mut UpdateCtx, old_data: &T, data: &T, env: &Env) {
match self {
Self::ColorKey(key) if ctx.env_key_changed(key) => {
ctx.request_paint();
}
Self::Painter(p) => p.update(ctx, old_data, data, env),
_ => (),
}
}
pub fn paint(&mut self, ctx: &mut PaintCtx, data: &T, env: &Env) {
let bounds = ctx.size().to_rect();
match self {
Self::Color(color) => ctx.fill(bounds, color),
Self::ColorKey(key) => ctx.fill(bounds, &env.get(key)),
Self::Linear(grad) => ctx.fill(bounds, grad),
Self::Radial(grad) => ctx.fill(bounds, grad),
Self::Fixed(grad) => ctx.fill(bounds, grad),
Self::Painter(painter) => painter.paint(ctx, data, env),
}
}
}
impl<T: Data> Widget<T> for Painter<T> {
fn event(&mut self, _: &mut EventCtx, _: &Event, _: &mut T, _: &Env) {}
fn lifecycle(&mut self, _: &mut LifeCycleCtx, _: &LifeCycle, _: &T, _: &Env) {}
#[instrument(name = "Painter", level = "trace", skip(self, ctx, old_data, data))]
fn update(&mut self, ctx: &mut UpdateCtx, old_data: &T, data: &T, _: &Env) {
if !old_data.same(data) {
ctx.request_paint();
}
}
#[instrument(name = "Painter", level = "trace", skip(self, _ctx, bc))]
fn layout(&mut self, _ctx: &mut LayoutCtx, bc: &BoxConstraints, _: &T, _: &Env) -> Size {
bc.max()
}
#[instrument(name = "Painter", level = "trace", skip(self, ctx, data, env))]
fn paint(&mut self, ctx: &mut PaintCtx, data: &T, env: &Env) {
(self.0)(ctx, data, env)
}
}
impl<T> From<Color> for BackgroundBrush<T> {
fn from(src: Color) -> BackgroundBrush<T> {
BackgroundBrush::Color(src)
}
}
impl<T> From<Key<Color>> for BackgroundBrush<T> {
fn from(src: Key<Color>) -> BackgroundBrush<T> {
BackgroundBrush::ColorKey(src)
}
}
impl<T> From<LinearGradient> for BackgroundBrush<T> {
fn from(src: LinearGradient) -> BackgroundBrush<T> {
BackgroundBrush::Linear(src)
}
}
impl<T> From<RadialGradient> for BackgroundBrush<T> {
fn from(src: RadialGradient) -> BackgroundBrush<T> {
BackgroundBrush::Radial(src)
}
}
impl<T> From<FixedGradient> for BackgroundBrush<T> {
fn from(src: FixedGradient) -> BackgroundBrush<T> {
BackgroundBrush::Fixed(src)
}
}
impl<T> From<Painter<T>> for BackgroundBrush<T> {
fn from(src: Painter<T>) -> BackgroundBrush<T> {
BackgroundBrush::Painter(src)
}
}
impl<T> From<PaintBrush> for BackgroundBrush<T> {
fn from(src: PaintBrush) -> BackgroundBrush<T> {
match src {
PaintBrush::Linear(grad) => BackgroundBrush::Linear(grad),
PaintBrush::Radial(grad) => BackgroundBrush::Radial(grad),
PaintBrush::Fixed(grad) => BackgroundBrush::Fixed(grad),
PaintBrush::Color(color) => BackgroundBrush::Color(color),
}
}
}