Krolyxon
Commit eed1fb9

Branches

Refs →

budctlcratesbudctl-guisrckept.rs

62 lines · 2.0 KB · Rust

1//! Canvas drawings kept between frames.
2//!
3//! The CPU renderer takes a canvas drawn afresh as changed on every frame, shape by shape, and
4//! repaints each shape's patch of the window on its own: with a few dozen icons and dots on a
5//! page, one hovered row repaints the window dozens of times over. A kept drawing stays the same
6//! drawing until what it shows changes, so only what really changed is painted again.
7
8use std::cell::Cell;
9
10use iced::widget::canvas::{Cache, Frame, Geometry};
11use iced::{Renderer, Size};
12
13/// A canvas's drawing of `K` (what it shows: its colors and values), drawn again only when `K`
14/// or the canvas's size changes. It lives in the canvas's state, so it outlasts the view.
15pub struct Kept<K> {
16 cache: Cache,
17 shows: Cell<Option<K>>,
18}
19
20impl<K> Default for Kept<K> {
21 fn default() -> Self {
22 Kept {
23 cache: Cache::new(),
24 shows: Cell::new(None),
25 }
26 }
27}
28
29impl<K: Copy + PartialEq> Kept<K> {
30 /// The drawing of `shows`, `size` large: the kept one, or a new one made by `draw`.
31 pub fn draw(&self, renderer: &Renderer, size: Size, shows: K, draw: impl FnOnce(&mut Frame)) -> Geometry {
32 if self.shows.get() != Some(shows) {
33 self.cache.clear();
34 self.shows.set(Some(shows));
35 }
36 self.cache.draw(renderer, size, draw)
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43 use iced::{Font, Pixels};
44
45 #[test]
46 fn draws_again_only_when_what_it_shows_changes() {
47 let renderer = Renderer::new(Font::DEFAULT, Pixels(16.0));
48 let kept = Kept::default();
49 let small = Size::new(10.0, 10.0);
50 let mut drawn = 0;
51 for (size, shows) in [
52 (small, 1),
53 (small, 1),
54 (small, 2),
55 (small, 2),
56 (Size::new(20.0, 10.0), 2),
57 ] {
58 let _ = kept.draw(&renderer, size, shows, |_| drawn += 1);
59 }
60 assert_eq!(drawn, 3, "drawn for 1, for 2, and for 2 at the new size");
61 }
62}