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