yuno 0.1.0

A declarative UI layout and rendering framework powered by Skia.
use crate::drawing::{Drawable, Plan};
use crate::layouts::{HasPlanner, Layout};
use crate::story_board::StoryBoard;
use skia_safe::{Canvas, Color4f, Paint, Path, Point, RRect, Rect};
use std::cell::RefCell;
use std::rc::Rc;

pub struct PlayPauseIcon {
    pub is_paused: RefCell<bool>,
    pub pp_state: RefCell<StoryBoard>,
    pub rotation_state: RefCell<StoryBoard>,

    pub(crate) play_path: Path,
    pub(crate) ring_paint: Paint,
    pub(crate) icon_paint: Paint,
    pub(crate) planner: RefCell<Option<Rc<dyn Layout>>>,
}

impl HasPlanner for PlayPauseIcon {
    fn planner(&self) -> &RefCell<Option<Rc<dyn Layout>>> {
        &self.planner
    }
    fn set_planner(&self, p: Option<Rc<dyn Layout>>) {
        *self.planner.borrow_mut() = p;
    }
}

impl Drawable for PlayPauseIcon {
    fn draw(&self, canvas: &Canvas) -> anyhow::Result<()> {
        let area = self.get_planned_drawing_area(canvas);
        let cx = area.left + area.width() / 2.0;
        let cy = area.top + area.height() / 2.0;
        let radius = area.width().min(area.height()) / 2.0;

        canvas.save();
        canvas.translate(Point::new(cx, cy));

        // 1. Draw Rotating Ring
        canvas.save();
        let rotation_angle = f64::from(&*self.rotation_state.borrow()) as f32;
        canvas.rotate(rotation_angle.to_degrees(), None);

        let ring_rect = Rect::from_xywh(-radius, -radius, radius * 2.0, radius * 2.0);
        canvas.draw_arc(ring_rect, 0.0, 120.0, false, &self.ring_paint);
        canvas.draw_arc(ring_rect, 180.0, 120.0, false, &self.ring_paint);
        canvas.restore();

        // 2. Draw Morphing Icon (Play/Pause Crossfade)
        let pp_val = f64::from(&*self.pp_state.borrow()) as f32;
        let is_paused = *self.is_paused.borrow();
        let (play_alpha, pause_alpha) = if is_paused {
            (pp_val, 1.0 - pp_val)
        } else {
            (1.0 - pp_val, pp_val)
        };

        if play_alpha > 0.01 {
            let mut p = self.icon_paint.clone();
            p.set_color4f(Color4f::new(1.0, 1.0, 1.0, play_alpha), None);
            canvas.draw_path(&self.play_path, &p);
        }

        if pause_alpha > 0.01 {
            let mut p = self.icon_paint.clone();
            p.set_color4f(Color4f::new(1.0, 1.0, 1.0, pause_alpha), None);
            let bar_w = 3.75;
            let bar_h = 15.0;
            let gap = 4.5;

            canvas.draw_rrect(
                RRect::new_rect_xy(
                    Rect::from_xywh(-bar_w - gap / 2.0, -bar_h / 2.0, bar_w, bar_h),
                    1.5,
                    1.5,
                ),
                &p,
            );
            canvas.draw_rrect(
                RRect::new_rect_xy(
                    Rect::from_xywh(gap / 2.0, -bar_h / 2.0, bar_w, bar_h),
                    1.5,
                    1.5,
                ),
                &p,
            );
        }

        canvas.restore();
        Ok(())
    }
    fn get_horizontal_plan(&self) -> Plan {
        Plan::Fill
    }
    fn get_vertical_plan(&self) -> Plan {
        Plan::Fill
    }
}