cosmic/widget/rectangle_tracker/
subscription.rs1use iced::Rectangle;
2use iced::futures::channel::mpsc::{UnboundedReceiver, unbounded};
3use iced::futures::{StreamExt, stream};
4use iced_futures::Subscription;
5use std::collections::HashMap;
6use std::fmt::Debug;
7use std::hash::Hash;
8
9use super::RectangleTracker;
10
11#[cold]
12pub fn rectangle_tracker_subscription<
13 I: 'static + Hash + Copy + Send + Sync + Debug,
14 R: 'static + Hash + Copy + Send + Sync + Debug + Eq,
15>(
16 id: I,
17) -> Subscription<(I, RectangleUpdate<R>)> {
18 Subscription::run_with(id, |id| {
19 let id = *id;
20 stream::unfold(State::Ready, move |state| start_listening(id, state))
21 })
22}
23
24pub enum State<I> {
25 Ready,
26 Waiting(UnboundedReceiver<(I, Rectangle)>, HashMap<I, Rectangle>),
27 Finished,
28}
29
30async fn start_listening<I: Copy, R: 'static + Hash + Copy + Send + Sync + Debug + Eq>(
31 id: I,
32 mut state: State<R>,
33) -> Option<((I, RectangleUpdate<R>), State<R>)> {
34 loop {
35 let (update, new_state) = match state {
36 State::Ready => {
37 let (tx, rx) = unbounded();
38
39 (
40 Some((id, RectangleUpdate::Init(RectangleTracker { tx }))),
41 State::Waiting(rx, HashMap::new()),
42 )
43 }
44 State::Waiting(mut rx, mut map) => match rx.next().await {
45 Some(u) => {
46 if let Some(prev) = map.get(&u.0) {
47 let new = u.1;
48 if (prev.width - new.width).abs() > 0.1
49 || (prev.height - new.height).abs() > 0.1
50 || (prev.x - new.x).abs() > 0.1
51 || (prev.y - new.y).abs() > 0.1
52 {
53 map.insert(u.0, new);
54 (
55 Some((id, RectangleUpdate::Rectangle(u))),
56 State::Waiting(rx, map),
57 )
58 } else {
59 (None, State::Waiting(rx, map))
60 }
61 } else {
62 map.insert(u.0, u.1);
63 (
64 Some((id, RectangleUpdate::Rectangle(u))),
65 State::Waiting(rx, map),
66 )
67 }
68 }
69 None => (None, State::Finished),
70 },
71 State::Finished => return None,
72 };
73 state = new_state;
74 if let Some(u) = update {
75 return Some((u, state));
76 }
77 }
78}
79
80#[derive(Clone, Debug)]
81pub enum RectangleUpdate<I>
82where
83 I: 'static + Hash + Copy + Send + Sync + Debug,
84{
85 Rectangle((I, Rectangle)),
86 Init(RectangleTracker<I>),
87}