use async_trait::async_trait;
use r3bl_rs_utils_core::*;
use super::*;
use crate::*;
pub async fn paint(
pipeline: &RenderPipeline,
flush_kind: FlushKind,
shared_global_data: &SharedGlobalData,
) {
let maybe_saved_offscreen_buffer = shared_global_data
.read()
.await
.maybe_saved_offscreen_buffer
.clone();
let offscreen_buffer = pipeline.convert(shared_global_data).await;
match maybe_saved_offscreen_buffer {
None => {
perform_full_paint(&offscreen_buffer, flush_kind, shared_global_data).await;
}
Some(saved_offscreen_buffer) => {
match saved_offscreen_buffer.diff(&offscreen_buffer) {
OffscreenBufferDiffResult::NotComparable => {
perform_full_paint(&offscreen_buffer, flush_kind, shared_global_data)
.await;
}
OffscreenBufferDiffResult::Comparable(ref diff_chunks) => {
perform_diff_paint(diff_chunks, shared_global_data).await;
}
}
}
}
shared_global_data
.write()
.await
.maybe_saved_offscreen_buffer = Some(offscreen_buffer);
async fn perform_diff_paint(
diff_chunks: &PixelCharDiffChunks,
shared_global_data: &SharedGlobalData,
) {
match TERMINAL_LIB_BACKEND {
TerminalLibBackend::Crossterm => {
let mut crossterm_impl = OffscreenBufferPaintImplCrossterm {};
let render_ops = crossterm_impl.render_diff(diff_chunks).await;
crossterm_impl
.paint_diff(render_ops, shared_global_data)
.await;
}
TerminalLibBackend::Termion => todo!(), }
}
async fn perform_full_paint(
offscreen_buffer: &OffscreenBuffer,
flush_kind: FlushKind,
shared_global_data: &SharedGlobalData,
) {
match TERMINAL_LIB_BACKEND {
TerminalLibBackend::Crossterm => {
let mut crossterm_impl = OffscreenBufferPaintImplCrossterm {};
let render_ops = crossterm_impl.render(offscreen_buffer).await;
crossterm_impl
.paint(render_ops, flush_kind, shared_global_data)
.await;
}
TerminalLibBackend::Termion => todo!(), }
}
}
pub async fn sanitize_and_save_abs_position(
orig_abs_pos: Position,
shared_global_data: &SharedGlobalData,
local_data: &mut RenderOpsLocalData,
) -> Position {
let Size {
col_count: max_cols,
row_count: max_rows,
} = shared_global_data.read().await.window_size;
let mut sanitized_abs_pos: Position = orig_abs_pos;
if orig_abs_pos.col_index > max_cols {
sanitized_abs_pos.col_index = max_cols;
}
if orig_abs_pos.row_index > max_rows {
sanitized_abs_pos.row_index = max_rows;
}
local_data.cursor_position = sanitized_abs_pos;
debug(orig_abs_pos, sanitized_abs_pos);
return sanitized_abs_pos;
fn debug(orig_pos: Position, sanitized_pos: Position) {
call_if_true!(DEBUG_TUI_MOD, {
if sanitized_pos != orig_pos {
let msg = format!(
"pipeline : 📍🗜️ Attempt to set cursor position {orig_pos:?} \
outside of terminal window; clamping to nearest edge of window {sanitized_pos:?}"
);
log_info(msg);
}
});
call_if_true!(DEBUG_TUI_SHOW_PIPELINE_EXPANDED, {
let msg = format!(
"pipeline : 📍 Save the cursor position {sanitized_pos:?} \
to SharedGlobalData"
);
log_info(msg);
});
}
}
pub mod paint_exports {
use super::*;
#[async_trait]
pub trait PaintRenderOp {
async fn paint(
&mut self,
skip_flush: &mut bool,
render_op: &RenderOp,
shared_global_data: &SharedGlobalData,
local_data: &mut RenderOpsLocalData,
);
}
}
pub use paint_exports::*;