lerni/
frame.rs

1extern crate alloc;
2
3use alloc::{collections::VecDeque, sync::Arc};
4use leptos::prelude::{expect_context, provide_context, use_context};
5use std::sync::Mutex;
6
7/// Frame within which the widget will be rendered.
8#[derive(Clone, Default, Debug)]
9pub struct Frame {
10    /// X-coordinate (in pixels) of the to left corner.
11    pub x: i32,
12    /// Y-coordinate (in pixels) of the to left corner.
13    pub y: i32,
14    /// Width (in pixels).
15    pub width: i32,
16    /// Height (in pixels).
17    pub height: i32,
18}
19
20/// SVG frame area.
21#[derive(Clone, Default, Debug)]
22pub struct SvgFrame {
23    /// SVG frame width (in viewbox pixels).
24    pub width: i32,
25    /// SVG frame height (in viewbox pixels).
26    pub height: i32,
27    /// Client area width (in screen pixels).
28    pub client_width: i32,
29    /// Client area height (in screen pixels).
30    pub client_height: i32,
31}
32
33/// Frames stack.
34#[derive(Clone, Default, Debug)]
35pub struct Frames(VecDeque<Frame>);
36
37/// Frames stack reference.
38pub type FramesRef = Arc<Mutex<Frames>>;
39
40impl Frames {
41    /// Pushes a new child frame.
42    pub fn push(&mut self, frame: Frame) {
43        self.0.push_back(frame);
44    }
45
46    /// Pops the first child frame or initial frame if there are no children.
47    pub fn pop(&mut self) -> Frame {
48        let frames = &mut self.0;
49        if frames.len() > 1 {
50            frames.pop_back().unwrap()
51        } else {
52            frames.back().unwrap().clone()
53        }
54    }
55
56    /// Extends the stack with the given frames.
57    pub fn extend(&mut self, frames: impl IntoIterator<Item = Frame>) {
58        self.0.extend(frames);
59    }
60}
61
62/// Provides frame to the context.
63pub fn provide_frame(frame: Frame) {
64    let frames: Option<FramesRef> = use_context();
65    if let Some(frames) = frames {
66        frames.lock().unwrap().0.push_back(frame);
67    } else {
68        let frames = Frames([frame].into());
69        provide_context(Arc::new(Mutex::new(frames)));
70    }
71}
72
73/// Returns the current frame.
74pub fn use_frame() -> Frame {
75    let frames: FramesRef = expect_context();
76    let mut frames = frames.lock().unwrap();
77    frames.pop()
78}
79
80/// Returns frames stack from context.
81pub fn use_frames() -> FramesRef {
82    expect_context()
83}