use std::any::TypeId; use mlua::{AnyUserData, ExternalError}; use super::{Bar, Border, Clear, Gauge, Line, List, Table, Text}; use crate::{Error, elements::Area}; #[derive(Clone, Debug)] pub enum Renderable { Line(Line), Text(Text), List(Box), Bar(Bar), Clear(Clear), Border(Border), Gauge(Box), Table(Box), } impl Renderable { pub fn area(&self) -> Area { match self { Self::Line(line) => line.area, Self::Text(text) => text.area, Self::List(list) => list.area, Self::Bar(bar) => bar.area, Self::Clear(clear) => clear.area, Self::Border(border) => border.area, Self::Gauge(gauge) => gauge.area, Self::Table(table) => table.area, } } pub fn with_area(mut self, area: impl Into) -> Self { let area = area.into(); match &mut self { Self::Line(line) => line.area = area, Self::Text(text) => text.area = area, Self::List(list) => list.area = area, Self::Bar(bar) => bar.area = area, Self::Clear(clear) => clear.area = area, Self::Border(border) => border.area = area, Self::Gauge(gauge) => gauge.area = area, Self::Table(table) => table.area = area, } self } pub fn render(self, rect: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer) { match self { Self::Line(line) => line.render(rect, buf), Self::Text(text) => text.render(rect, buf), Self::List(list) => list.render(rect, buf), Self::Bar(bar) => bar.render(rect, buf), Self::Clear(clear) => clear.render(rect, buf), Self::Border(border) => border.render(rect, buf), Self::Gauge(gauge) => gauge.render(rect, buf), Self::Table(table) => table.render(rect, buf), } } pub fn render_with(self, buf: &mut ratatui::buffer::Buffer, trans: T) where T: FnOnce(yazi_config::popup::Position) -> ratatui::layout::Rect, { let rect = self.area().transform(trans); self.render(rect, buf); } } impl TryFrom<&AnyUserData> for Renderable { type Error = mlua::Error; fn try_from(ud: &AnyUserData) -> Result { Ok(match ud.type_id() { Some(t) if t == TypeId::of::() => Self::Line(ud.take()?), Some(t) if t == TypeId::of::() => Self::Text(ud.take()?), Some(t) if t == TypeId::of::() => Self::List(Box::new(ud.take()?)), Some(t) if t == TypeId::of::() => Self::Bar(ud.take()?), Some(t) if t == TypeId::of::() => Self::Clear(ud.take()?), Some(t) if t == TypeId::of::() => Self::Border(ud.take()?), Some(t) if t == TypeId::of::() => Self::Gauge(Box::new(ud.take()?)), Some(t) if t == TypeId::of::
() => Self::Table(Box::new(ud.take()?)), _ => Err(format!("expected a UserData of renderable element, not: {ud:#?}").into_lua_err())?, }) } } impl TryFrom for Renderable { type Error = mlua::Error; fn try_from(ud: AnyUserData) -> Result { Self::try_from(&ud) } } impl From for Renderable { fn from(error: Error) -> Self { Self::Text(Text { inner: error.into_string().into(), wrap: ratatui::widgets::Wrap { trim: false }.into(), ..Default::default() }) } }