#[cfg(not(feature = "tokio"))]
use std::sync::mpsc::Sender;
#[cfg(feature = "tokio")]
use tokio::sync::mpsc::UnboundedSender as Sender;
use image::Rgba;
use ratatui::prelude::{Buffer, Rect};
use crate::{
Resize, ResizeEncodeRender,
errors::Errors,
protocol::{StatefulProtocol, StatefulProtocolType},
};
pub struct ResizeRequest {
protocol: StatefulProtocol,
resize: Resize,
area: Rect,
id: u64,
}
impl ResizeRequest {
pub fn resize_encode(mut self) -> Result<ResizeResponse, Errors> {
self.protocol.resize_encode(&self.resize, self.area);
self.protocol
.last_encoding_result()
.expect("The resize has just been performed")?;
Ok(ResizeResponse {
protocol: self.protocol,
id: self.id,
})
}
}
pub struct ResizeResponse {
protocol: StatefulProtocol,
id: u64,
}
pub struct ThreadProtocol {
inner: Option<StatefulProtocol>,
tx: Sender<ResizeRequest>,
id: u64,
}
impl ThreadProtocol {
pub fn new(tx: Sender<ResizeRequest>, inner: Option<StatefulProtocol>) -> ThreadProtocol {
Self { inner, tx, id: 0 }
}
pub fn replace_protocol(&mut self, proto: StatefulProtocol) {
self.inner = Some(proto);
self.increment_id();
}
pub fn protocol_type(&self) -> Option<&StatefulProtocolType> {
self.inner.as_ref().map(|inner| inner.protocol_type())
}
pub fn protocol_type_owned(self) -> Option<StatefulProtocolType> {
self.inner.map(|inner| inner.protocol_type_owned())
}
pub fn background_color(&self) -> Option<Rgba<u8>> {
self.inner.as_ref().map(|inner| inner.background_color())
}
pub fn empty_protocol(&mut self) {
self.inner = None;
self.increment_id();
}
pub fn update_resized_protocol(&mut self, completed: ResizeResponse) -> bool {
let equal = self.id == completed.id;
if equal {
self.inner = Some(completed.protocol)
}
equal
}
pub fn size_for(&self, resize: Resize, area: Rect) -> Option<Rect> {
self.inner
.as_ref()
.map(|protocol| protocol.size_for(resize, area))
}
fn increment_id(&mut self) {
self.id = self.id.wrapping_add(1);
}
}
impl ResizeEncodeRender for ThreadProtocol {
fn needs_resize(&self, resize: &Resize, area: Rect) -> Option<Rect> {
self.inner
.as_ref()
.and_then(|protocol| protocol.needs_resize(resize, area))
}
fn resize_encode(&mut self, resize: &Resize, area: Rect) {
let _ = self.inner.take().map(|protocol| {
self.increment_id();
_ = self.tx.send(ResizeRequest {
protocol,
resize: resize.clone(),
area,
id: self.id,
});
});
}
fn render(&mut self, area: Rect, buf: &mut Buffer) {
let _ = self
.inner
.as_mut()
.map(|protocol| protocol.render(area, buf));
}
}