1#[cfg(not(feature = "tokio"))]
8use std::sync::mpsc::Sender;
9#[cfg(feature = "tokio")]
10use tokio::sync::mpsc::UnboundedSender as Sender;
11
12use image::Rgba;
13use ratatui::{
14 layout::Size,
15 prelude::{Buffer, Rect},
16};
17
18use crate::{
19 Resize, ResizeEncodeRender,
20 errors::Errors,
21 protocol::{StatefulProtocol, StatefulProtocolType},
22};
23
24pub struct ResizeRequest {
26 protocol: StatefulProtocol,
27 resize: Resize,
28 size: Size,
29 id: u64,
30}
31
32impl ResizeRequest {
33 pub fn resize_encode(mut self) -> Result<ResizeResponse, Errors> {
34 self.protocol.resize_encode(&self.resize, self.size);
35 self.protocol
36 .last_encoding_result()
37 .expect("The resize has just been performed")?;
38 Ok(ResizeResponse {
39 protocol: self.protocol,
40 id: self.id,
41 })
42 }
43}
44
45pub struct ResizeResponse {
47 protocol: StatefulProtocol,
48 id: u64,
49}
50
51pub struct ThreadProtocol {
56 inner: Option<StatefulProtocol>,
57 tx: Sender<ResizeRequest>,
58 id: u64,
59}
60
61impl ThreadProtocol {
62 pub fn new(tx: Sender<ResizeRequest>, inner: Option<StatefulProtocol>) -> ThreadProtocol {
63 Self { inner, tx, id: 0 }
64 }
65
66 pub fn replace_protocol(&mut self, proto: StatefulProtocol) {
67 self.inner = Some(proto);
68 self.increment_id();
69 }
70
71 pub fn protocol_type(&self) -> Option<&StatefulProtocolType> {
72 self.inner.as_ref().map(|inner| inner.protocol_type())
73 }
74
75 pub fn protocol_type_owned(self) -> Option<StatefulProtocolType> {
76 self.inner.map(|inner| inner.protocol_type_owned())
77 }
78
79 pub fn background_color(&self) -> Option<Rgba<u8>> {
81 self.inner
82 .as_ref()
83 .and_then(|inner| inner.background_color())
84 }
85
86 pub fn empty_protocol(&mut self) {
88 self.inner = None;
89 self.increment_id();
90 }
91
92 pub fn update_resized_protocol(&mut self, completed: ResizeResponse) -> bool {
93 let equal = self.id == completed.id;
94 if equal {
95 self.inner = Some(completed.protocol)
96 }
97 equal
98 }
99
100 pub fn size_for(&self, resize: Resize, size: Size) -> Option<Size> {
101 self.inner
102 .as_ref()
103 .map(|protocol| protocol.size_for(resize, size))
104 }
105
106 fn increment_id(&mut self) {
107 self.id = self.id.wrapping_add(1);
108 }
109}
110
111impl ResizeEncodeRender for ThreadProtocol {
112 fn needs_resize(&self, resize: &Resize, size: Size) -> Option<Size> {
113 self.inner
114 .as_ref()
115 .and_then(|protocol| protocol.needs_resize(resize, size))
116 }
117
118 fn resize_encode(&mut self, resize: &Resize, size: Size) {
120 let _ = self.inner.take().map(|protocol| {
121 self.increment_id();
122 _ = self.tx.send(ResizeRequest {
123 protocol,
124 resize: resize.clone(),
125 size,
126 id: self.id,
127 });
128 });
129 }
130
131 fn render(&mut self, area: Rect, buf: &mut Buffer) {
133 let _ = self
134 .inner
135 .as_mut()
136 .map(|protocol| protocol.render(area, buf));
137 }
138}