2021-07-28 14:52:38 +00:00
|
|
|
use anyhow::Result;
|
2022-01-01 04:53:37 +00:00
|
|
|
use crossterm::{
|
|
|
|
event::{DisableMouseCapture, EnableMouseCapture},
|
|
|
|
execute,
|
|
|
|
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
|
|
|
};
|
2021-07-28 14:52:38 +00:00
|
|
|
use dioxus::core::*;
|
2022-01-01 04:53:37 +00:00
|
|
|
use std::{collections::HashMap, io};
|
|
|
|
use stretch2::{prelude::Size, Stretch};
|
|
|
|
use tui::{backend::CrosstermBackend, style::Style as TuiStyle, Terminal};
|
|
|
|
|
|
|
|
mod attributes;
|
|
|
|
mod layout;
|
|
|
|
mod render;
|
|
|
|
|
|
|
|
pub use attributes::*;
|
|
|
|
pub use layout::*;
|
|
|
|
pub use render::*;
|
|
|
|
|
|
|
|
pub struct TuiNode<'a> {
|
|
|
|
pub layout: stretch2::node::Node,
|
|
|
|
pub block_style: TuiStyle,
|
|
|
|
pub node: &'a VNode<'a>,
|
2021-07-28 14:52:38 +00:00
|
|
|
}
|
|
|
|
|
2022-01-01 04:53:37 +00:00
|
|
|
pub fn render_vdom(vdom: &VirtualDom) -> Result<()> {
|
|
|
|
/*
|
|
|
|
-> collect all the nodes with their layout
|
|
|
|
-> solve their layout
|
|
|
|
-> render the nodes in the right place with tui/crosstream
|
|
|
|
-> while rendering, apply styling
|
|
|
|
|
|
|
|
use simd to compare lines for diffing?
|
|
|
|
|
|
|
|
*/
|
|
|
|
let mut layout = Stretch::new();
|
|
|
|
let mut nodes = HashMap::new();
|
|
|
|
|
|
|
|
let root_node = vdom.base_scope().root_node();
|
|
|
|
layout::collect_layout(&mut layout, &mut nodes, vdom, root_node);
|
|
|
|
|
|
|
|
/*
|
|
|
|
Get the terminal to calcualte the layout from
|
|
|
|
*/
|
|
|
|
enable_raw_mode().unwrap();
|
|
|
|
ctrlc::set_handler(move || {
|
|
|
|
disable_raw_mode().unwrap();
|
|
|
|
})
|
|
|
|
.expect("Error setting Ctrl-C handler");
|
|
|
|
let mut stdout = std::io::stdout();
|
|
|
|
execute!(stdout, EnterAlternateScreen, EnableMouseCapture).unwrap();
|
|
|
|
let backend = CrosstermBackend::new(io::stdout());
|
|
|
|
let mut terminal = Terminal::new(backend).unwrap();
|
|
|
|
|
|
|
|
let dims = terminal.size().unwrap();
|
|
|
|
let width = dims.width;
|
|
|
|
let height = dims.height;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Compute the layout given th terminal size
|
|
|
|
*/
|
|
|
|
let node_id = root_node.try_mounted_id().unwrap();
|
|
|
|
let root_layout = nodes[&node_id].layout;
|
|
|
|
layout.compute_layout(
|
|
|
|
root_layout,
|
|
|
|
Size {
|
|
|
|
width: stretch2::prelude::Number::Defined(width as f32),
|
|
|
|
height: stretch2::prelude::Number::Defined(height as f32),
|
|
|
|
},
|
|
|
|
)?;
|
|
|
|
|
|
|
|
terminal.draw(|frame| {
|
|
|
|
//
|
|
|
|
render::render_vnode(frame, &layout, &mut nodes, vdom, root_node);
|
|
|
|
assert!(nodes.is_empty());
|
|
|
|
})?;
|
|
|
|
|
|
|
|
std::thread::sleep(std::time::Duration::from_millis(5000));
|
|
|
|
|
|
|
|
disable_raw_mode()?;
|
|
|
|
execute!(
|
|
|
|
terminal.backend_mut(),
|
|
|
|
LeaveAlternateScreen,
|
|
|
|
DisableMouseCapture
|
|
|
|
)?;
|
|
|
|
terminal.show_cursor()?;
|
|
|
|
|
|
|
|
Ok(())
|
2021-07-28 14:52:38 +00:00
|
|
|
}
|
|
|
|
|
2022-01-01 04:53:37 +00:00
|
|
|
// enum InputEvent {
|
|
|
|
// UserInput(KeyEvent),
|
|
|
|
// Close,
|
|
|
|
// Tick,
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // Setup input handling
|
|
|
|
// let (tx, rx) = mpsc::channel();
|
|
|
|
// let tick_rate = Duration::from_millis(100);
|
|
|
|
// thread::spawn(move || {
|
|
|
|
// let mut last_tick = Instant::now();
|
|
|
|
// loop {
|
|
|
|
// // poll for tick rate duration, if no events, sent tick event.
|
|
|
|
// let timeout = tick_rate
|
|
|
|
// .checked_sub(last_tick.elapsed())
|
|
|
|
// .unwrap_or_else(|| Duration::from_secs(0));
|
|
|
|
|
|
|
|
// if event::poll(timeout).unwrap() {
|
|
|
|
// if let TermEvent::Key(key) = event::read().unwrap() {
|
|
|
|
// tx.send(InputEvent::UserInput(key)).unwrap();
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // if last_tick.elapsed() >= tick_rate {
|
|
|
|
// // tx.send(InputEvent::Tick).unwrap();
|
|
|
|
// // last_tick = Instant::now();
|
|
|
|
// // }
|
|
|
|
// }
|
|
|
|
// });
|
|
|
|
|
|
|
|
// terminal.clear()?;
|
|
|
|
|
|
|
|
// // loop {
|
|
|
|
// terminal.draw(|frame| {
|
|
|
|
// // draw the frame
|
|
|
|
// let size = frame.size();
|
|
|
|
// let root_node = vdom.base_scope().root_node();
|
|
|
|
// let block = render_vnode(frame, vdom, root_node);
|
|
|
|
|
|
|
|
// frame.render_widget(block, size);
|
|
|
|
// })?;
|
|
|
|
|
|
|
|
// // // terminal.draw(|f| ui::draw(f, &mut app))?;
|
|
|
|
// match rx.recv()? {
|
|
|
|
// InputEvent::UserInput(event) => match event.code {
|
|
|
|
// KeyCode::Char('q') => {
|
|
|
|
// disable_raw_mode()?;
|
|
|
|
// execute!(
|
|
|
|
// terminal.backend_mut(),
|
|
|
|
// LeaveAlternateScreen,
|
|
|
|
// DisableMouseCapture
|
|
|
|
// )?;
|
|
|
|
// terminal.show_cursor()?;
|
|
|
|
// // break;
|
|
|
|
// }
|
|
|
|
// _ => {} // handle event
|
|
|
|
// },
|
|
|
|
// InputEvent::Tick => {} // tick
|
|
|
|
// InputEvent::Close => {
|
|
|
|
// // break;
|
|
|
|
// }
|
|
|
|
// };
|