2022-01-01 04:53:37 +00:00
|
|
|
use anyhow::Result;
|
|
|
|
use crossterm::{
|
|
|
|
event,
|
|
|
|
event::{DisableMouseCapture, EnableMouseCapture, Event as TermEvent, KeyCode, KeyEvent},
|
|
|
|
execute,
|
|
|
|
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
|
|
|
};
|
|
|
|
use dioxus::core::*;
|
|
|
|
use std::{
|
|
|
|
collections::HashMap,
|
|
|
|
io::{self, Stdout},
|
|
|
|
sync::mpsc,
|
|
|
|
thread,
|
|
|
|
time::{Duration, Instant},
|
|
|
|
};
|
|
|
|
use stretch2::{
|
|
|
|
geometry::Point,
|
|
|
|
prelude::{Layout, Size},
|
|
|
|
style::Style as StretchStyle,
|
|
|
|
Stretch,
|
|
|
|
};
|
|
|
|
use tui::{
|
|
|
|
backend::CrosstermBackend,
|
|
|
|
buffer::Buffer,
|
|
|
|
layout::Rect,
|
|
|
|
style::Style as TuiStyle,
|
|
|
|
text::Span,
|
|
|
|
widgets::{canvas::Label, Block, BorderType, Borders, Widget},
|
|
|
|
Terminal,
|
|
|
|
};
|
|
|
|
|
|
|
|
use crate::TuiNode;
|
|
|
|
|
|
|
|
pub fn render_vnode<'a>(
|
|
|
|
frame: &mut tui::Frame<CrosstermBackend<Stdout>>,
|
|
|
|
layout: &Stretch,
|
|
|
|
layouts: &mut HashMap<ElementId, TuiNode<'a>>,
|
|
|
|
vdom: &'a VirtualDom,
|
|
|
|
node: &'a VNode<'a>,
|
|
|
|
) {
|
|
|
|
match node {
|
|
|
|
VNode::Fragment(f) => {
|
|
|
|
for child in f.children {
|
|
|
|
render_vnode(frame, layout, layouts, vdom, child);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2022-02-04 13:24:02 +00:00
|
|
|
|
|
|
|
VNode::Component(vcomp) => {
|
|
|
|
let idx = vcomp.scope.get().unwrap();
|
|
|
|
let new_node = vdom.get_scope(idx).unwrap().root_node();
|
|
|
|
render_vnode(frame, layout, layouts, vdom, new_node);
|
|
|
|
return;
|
|
|
|
}
|
2022-01-01 04:53:37 +00:00
|
|
|
|
2022-02-04 20:52:01 +00:00
|
|
|
VNode::Placeholder(_) => return,
|
|
|
|
|
|
|
|
VNode::Element(_) | VNode::Text(_) => {}
|
2022-01-01 04:53:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let id = node.try_mounted_id().unwrap();
|
|
|
|
let node = layouts.remove(&id).unwrap();
|
|
|
|
|
|
|
|
let Layout { location, size, .. } = layout.layout(node.layout).unwrap();
|
|
|
|
|
|
|
|
let Point { x, y } = location;
|
|
|
|
let Size { width, height } = size;
|
|
|
|
|
|
|
|
match node.node {
|
|
|
|
VNode::Text(t) => {
|
|
|
|
#[derive(Default)]
|
|
|
|
struct Label<'a> {
|
|
|
|
text: &'a str,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Widget for Label<'a> {
|
|
|
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
|
|
|
buf.set_string(area.left(), area.top(), self.text, TuiStyle::default());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// let s = Span::raw(t.text);
|
|
|
|
|
|
|
|
// Block::default().
|
|
|
|
|
|
|
|
let label = Label { text: t.text };
|
|
|
|
let area = Rect::new(*x as u16, *y as u16, *width as u16, *height as u16);
|
|
|
|
|
|
|
|
frame.render_widget(label, area);
|
|
|
|
}
|
|
|
|
VNode::Element(el) => {
|
|
|
|
let block = Block::default().style(node.block_style);
|
|
|
|
let area = Rect::new(*x as u16, *y as u16, *width as u16, *height as u16);
|
|
|
|
|
|
|
|
frame.render_widget(block, area);
|
|
|
|
|
|
|
|
for el in el.children {
|
|
|
|
render_vnode(frame, layout, layouts, vdom, el);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VNode::Fragment(_) => todo!(),
|
|
|
|
VNode::Component(_) => todo!(),
|
|
|
|
VNode::Placeholder(_) => todo!(),
|
|
|
|
}
|
|
|
|
}
|