use crate::{Content, Element, Handle, Hatmel};
use std::ops::Deref;
use termit::prelude::*;
#[derive(Default)]
pub struct W3t<A: AppEvent> {
ui: UiNode<A>,
}
impl<A: AppEvent> Widget<Hatmel, A> for W3t<A> {
fn update(
&mut self,
model: &mut Hatmel,
input: &termit::prelude::Event<A>,
screen: &mut termit::Screen,
painter: &termit::Painter,
) -> termit::prelude::Window {
self.ui.handle = Some(0);
self.ui.update(model, input, screen, painter)
}
}
pub struct UiNode<A: AppEvent> {
handle: Option<Handle>,
revision: usize,
ui: Box<dyn Widget<Hatmel, A> + 'static>,
}
impl<A: AppEvent> Default for UiNode<A> {
fn default() -> Self {
Self {
handle: None,
revision: usize::MAX,
ui: Box::new(()),
}
}
}
impl<A: AppEvent> UiNode<A> {
pub fn new(handle: Handle) -> Self {
Self {
handle: Some(handle),
revision: usize::MAX,
ui: Box::new(()),
}
}
}
impl<A: AppEvent> Widget<Hatmel, A> for UiNode<A> {
fn update(
&mut self,
model: &mut Hatmel,
input: &Event<A>,
screen: &mut Screen,
painter: &Painter,
) -> Window {
if model.revision() != self.revision {
let (handle, content) = match self
.handle
.and_then(|handle| model.get(handle).map(|content| (handle, content)))
{
None => {
*self = Self::default();
return painter.scope().trim(point(0, 0));
}
Some(some) => some,
};
let mut dent = 4;
let mut stack = Stack::south_east(vec![]);
match content {
Content::Element(Element { name, .. }) => match name.deref() {
"head" => return painter.scope().trim(point(0, 0)),
"html" => {
let mut title = model.get_title();
if title.is_empty() {
title = "-untitled-".into();
}
let len = title.len() as u16;
dent = 0;
stack = stack.add_box(
Canvas::new(String::from(title).width(len))
.back(Color::rgb(0, 30, 0))
.front(Color::white())
.height(1)
.top(0),
)
}
_ => {
stack = stack.add_box(
Canvas::new(format!("{content}"))
.back(Color::black())
.front(Color::yellow(false))
.place()
.height(1)
.top(0),
)
}
},
Content::Document => dent = 0,
Content::DocType { .. } => {}
Content::Text { text } => {
stack = stack.add_box(text.trim().to_string().front(Color::white()));
}
_ => {
stack = stack.add_box(
Canvas::new(format!("{content}"))
.back(Color::black())
.front(Color::yellow(false))
.place()
.height(1)
.top(0),
)
}
};
let mut content = Stack::south_east(vec![]);
for handle in model.children(handle) {
content = content.add_box(UiNode::new(handle))
}
self.ui = Box::new(stack.add_box(content.left(dent)));
self.revision = model.revision();
}
self.ui.update(model, input, screen, painter)
}
}