use alloc::format;
use denise::Color;
use denise::Pen;
use crate::widget::{PaintCtx, Widget};
use crate::widgets::describe::{
Describe, DynDescribe, Group, Mismatch, Property, PropertyKind, Value,
};
#[derive(Clone, Debug)]
pub struct Video {
ground: Color,
}
impl Video {
pub fn new() -> Self {
Self {
ground: Color::rgb(0, 0, 0),
}
}
pub fn with_ground(mut self, ground: Color) -> Self {
self.ground = ground;
self
}
}
impl Default for Video {
fn default() -> Self {
Self::new()
}
}
impl<M: 'static> Widget<M> for Video {
fn describe(&self) -> Option<&dyn DynDescribe> {
Some(self)
}
fn describe_mut(&mut self) -> Option<&mut dyn DynDescribe> {
Some(self)
}
fn paint(&self, ctx: &mut PaintCtx<'_>, canvas: &mut Pen<'_>) {
canvas.fill_rect(ctx.bounds, self.ground);
}
}
fn ground_from_hex(text: &str) -> Option<Color> {
let digits = text.strip_prefix('#').unwrap_or(text);
if digits.len() != 6 || !digits.bytes().all(|b| b.is_ascii_hexdigit()) {
return None;
}
u32::from_str_radix(digits, 16).ok().map(Color::from_rgb888)
}
impl Describe for Video {
const KIND: &'static str = "video";
const DOC: &'static str = "The rectangle a video plane is shown in.";
const GROUP: Group = Group::Media;
const ICON: &'static denise::icon::Icon = &super::icons::VIDEO;
const PROPERTIES: &'static [Property] = &[Property::new(
"ground",
PropertyKind::Color,
"The letterbox colour behind the plane, as `\"#RRGGBB\"`.",
)];
fn get(&self, name: &str) -> Option<Value> {
Some(match name {
"ground" => Value::Text(format!("#{:06X}", self.ground.to_argb8888() & 0x00FF_FFFF)),
_ => return None,
})
}
fn apply(&mut self, name: &str, value: Value) -> Result<(), Mismatch> {
match name {
"ground" => {
self.ground = ground_from_hex(&value.as_text()?).ok_or(Mismatch::WrongType {
expected: PropertyKind::Color,
})?;
}
_ => return Err(Mismatch::Unknown),
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_video_placeholder_takes_no_input() {
let v = Video::new();
assert!(!Widget::<usize>::focusable(&v));
assert!(!Widget::<usize>::accepts_pointer(&v));
}
}