use std::{fmt::{Debug, Formatter, Result},
ops::{Deref, DerefMut}};
use r3bl_rs_utils_core::*;
use serde::{Deserialize, Serialize};
use super::TERMINAL_LIB_BACKEND;
use crate::*;
#[macro_export]
macro_rules! render_ops {
() => {
RenderOps::default()
};
(
@new
$( /* Start a repetition. */
$arg_render_op: expr /* Expression. */
) /* End repetition. */
, /* Comma separated. */
* /* Zero or more times. */
$(,)* /* Optional trailing comma https://stackoverflow.com/a/43143459/2085356. */
) => {
{
let mut render_ops = RenderOps::default();
$(
render_ops.list.push($arg_render_op);
)*
render_ops
}
};
(
@add_to
$arg_render_ops: expr
=>
$( /* Start a repetition. */
$arg_render_op: expr /* Expression. */
) /* End repetition. */
, /* Comma separated. */
* /* Zero or more times. */
$(,)* /* Optional trailing comma https://stackoverflow.com/a/43143459/2085356. */
) => {
{
$(
$arg_render_ops.list.push($arg_render_op);
)*
}
};
(
@render_styled_texts_into
$arg_render_ops: expr
=>
$( /* Start a repetition. */
$arg_styled_texts: expr/* Expression. */
) /* End repetition. */
, /* Comma separated. */
* /* Zero or more times. */
$(,)* /* Optional trailing comma https://stackoverflow.com/a/43143459/2085356. */
) => {
{
$(
$arg_styled_texts.render_into(&mut $arg_render_ops);
)*
}
};
}
#[derive(Default, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub struct RenderOps {
pub list: Vec<RenderOp>,
}
#[derive(Default, Debug)]
pub struct RenderOpsLocalData {
pub cursor_position: Position,
}
pub mod render_ops_impl {
use std::ops::AddAssign;
use super::*;
impl RenderOps {
pub async fn execute_all(
&self,
skip_flush: &mut bool,
shared_global_data: &SharedGlobalData,
) {
let mut local_data = RenderOpsLocalData::default();
for render_op in self.list.iter() {
RenderOps::route_paint_render_op_to_backend(
&mut local_data,
skip_flush,
render_op,
shared_global_data,
)
.await;
}
}
pub async fn route_paint_render_op_to_backend(
local_data: &mut RenderOpsLocalData,
skip_flush: &mut bool,
render_op: &RenderOp,
shared_global_data: &SharedGlobalData,
) {
match TERMINAL_LIB_BACKEND {
TerminalLibBackend::Crossterm => {
RenderOpImplCrossterm {}
.paint(skip_flush, render_op, shared_global_data, local_data)
.await;
}
TerminalLibBackend::Termion => todo!(), }
}
}
impl Deref for RenderOps {
type Target = Vec<RenderOp>;
fn deref(&self) -> &Self::Target { &self.list }
}
impl DerefMut for RenderOps {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.list }
}
impl AddAssign<RenderOp> for RenderOps {
fn add_assign(&mut self, rhs: RenderOp) { self.list.push(rhs); }
}
impl Debug for RenderOps {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut vec_lines: Vec<String> = vec![];
let first_line: String = format!("RenderOps.len(): {}", self.list.len());
vec_lines.push(first_line);
for render_op in self.iter() {
let line: String = format!("[{render_op:?}]");
vec_lines.push(line);
}
write!(f, "\n - {}", vec_lines.join("\n - "))
}
}
}
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum RenderOp {
EnterRawMode,
ExitRawMode,
MoveCursorPositionAbs( Position),
MoveCursorPositionRelTo(
Position,
Position,
),
ClearScreen,
SetFgColor(TuiColor),
SetBgColor(TuiColor),
ResetColor,
ApplyColors(Option<Style>),
PaintTextWithAttributes(String, Option<Style>),
CompositorNoClipTruncPaintTextWithAttributes(String, Option<Style>),
Noop,
}
mod render_op_impl {
use super::*;
impl Default for RenderOp {
fn default() -> Self { Self::Noop }
}
impl Debug for RenderOp {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
match TERMINAL_LIB_BACKEND {
TerminalLibBackend::Crossterm => {
CrosstermDebugFormatRenderOp {}.debug_format(self, f)
}
TerminalLibBackend::Termion => todo!(), }
}
}
}
mod render_op_impl_trait_flush {
use super::*;
impl Flush for RenderOp {
fn flush(&mut self) {
match TERMINAL_LIB_BACKEND {
TerminalLibBackend::Crossterm => {
RenderOpImplCrossterm {}.flush();
}
TerminalLibBackend::Termion => todo!(), }
}
fn clear_before_flush(&mut self) {
match TERMINAL_LIB_BACKEND {
TerminalLibBackend::Crossterm => {
RenderOpImplCrossterm {}.clear_before_flush();
}
TerminalLibBackend::Termion => todo!(), }
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum FlushKind {
JustFlush,
ClearBeforeFlush,
}
pub trait Flush {
fn flush(&mut self);
fn clear_before_flush(&mut self);
}
pub trait DebugFormatRenderOp {
fn debug_format(&self, this: &RenderOp, f: &mut Formatter<'_>) -> Result;
}