added C for threading
This commit is contained in:
+39
-68
@@ -1,79 +1,50 @@
|
||||
use std::sync::{mpsc, Arc};
|
||||
use std::thread;
|
||||
use crossterm::terminal::enable_raw_mode;
|
||||
|
||||
use crate::{
|
||||
clear, create_frame, flush, get_term_size, hide_cursor, render_to_frame, Element, State, Value,
|
||||
};
|
||||
use crate::{clear, create_frame, flush, get_term_size, render_to_frame, Element, State, StateChanger, Value};
|
||||
use std::ffi::c_void;
|
||||
|
||||
/// Renders an element with a given state to the terminal.
|
||||
///
|
||||
/// This macro handles the process of creating a frame, rendering the element to it,
|
||||
/// clearing the terminal, and then printing the rendered frame.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// * `$element` - The element to be rendered.
|
||||
/// * `$state` - The current state of the element.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// This macro does not return a value. It performs side effects by printing to the terminal.
|
||||
macro_rules! render {
|
||||
($element:expr, $state:expr) => {
|
||||
let (width, height) = get_term_size();
|
||||
let mut frame: Vec<String> = create_frame(Value::new(width), Value::new(height));
|
||||
render_to_frame($state, width, &mut frame, $element);
|
||||
clear();
|
||||
print!("{}", frame.join(""));
|
||||
flush();
|
||||
};
|
||||
pub struct ElementWrapper<'a> {
|
||||
element: &'a mut Box<dyn Element>,
|
||||
}
|
||||
|
||||
pub fn run(element: Arc<dyn Element>) -> bool {
|
||||
hide_cursor();
|
||||
crossterm::terminal::enable_raw_mode().unwrap();
|
||||
clear();
|
||||
impl<'a> ElementWrapper<'a> {
|
||||
pub fn new(element: &'a mut Box<dyn Element>) -> *mut c_void {
|
||||
Box::into_raw(Box::new(ElementWrapper { element })) as *mut c_void
|
||||
}
|
||||
|
||||
let (tx, rx) = mpsc::channel();
|
||||
pub unsafe fn from_raw(ptr: *mut c_void) -> &'a mut Box<dyn Element> {
|
||||
assert!(!ptr.is_null(), "Pointer to ElementWrapper is null");
|
||||
let wrapper = ptr as *mut ElementWrapper;
|
||||
(*wrapper).element
|
||||
}
|
||||
}
|
||||
|
||||
let (exit_tx, exit_) = mpsc::channel::<()>();
|
||||
extern "C" {
|
||||
fn c_run(element: *mut c_void) -> bool;
|
||||
}
|
||||
|
||||
thread::spawn({
|
||||
let element_thread = Arc::clone(&element);
|
||||
move || loop {
|
||||
if exit_.try_recv().is_ok() {
|
||||
break;
|
||||
}
|
||||
let event = crossterm::event::read().unwrap();
|
||||
let e = Arc::clone(&element_thread);
|
||||
let command_handler = crate::CommandHandler(tx.clone());
|
||||
#[no_mangle]
|
||||
pub extern "C" fn render(ptr: *mut c_void, state: u32) {
|
||||
let element = unsafe { ElementWrapper::from_raw(ptr) };
|
||||
let (width, height) = get_term_size();
|
||||
let mut frame: Vec<String> = create_frame(Value::new(width), Value::new(height));
|
||||
render_to_frame(State::from_u32(state), width, &mut frame, element);
|
||||
clear();
|
||||
print!("{}", frame.join(""));
|
||||
flush();
|
||||
}
|
||||
|
||||
thread::spawn(move || {
|
||||
e.event(&command_handler, event);
|
||||
});
|
||||
}
|
||||
});
|
||||
#[no_mangle]
|
||||
pub extern "C" fn event(ptr: *mut c_void, state: *mut u32) {
|
||||
let event = crossterm::event::read().unwrap();
|
||||
let element = unsafe { ElementWrapper::from_raw(ptr) };
|
||||
element.event(event, &StateChanger(state));
|
||||
}
|
||||
|
||||
let mut current_state = State::Hover;
|
||||
loop {
|
||||
if let Ok(command) = rx.try_recv() {
|
||||
match command {
|
||||
crate::Command::SetState(state) => {
|
||||
current_state = state;
|
||||
}
|
||||
crate::Command::Exit => {
|
||||
exit_tx.send(()).unwrap();
|
||||
break;
|
||||
}
|
||||
crate::Command::Rebuild => {
|
||||
exit_tx.send(()).unwrap();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
render!(&element, current_state.clone());
|
||||
}
|
||||
thread::sleep(std::time::Duration::from_millis(20));
|
||||
pub fn run(data: &mut Box<dyn Element>) -> bool {
|
||||
enable_raw_mode().unwrap();
|
||||
unsafe {
|
||||
let element_ptr = ElementWrapper::new(data);
|
||||
return c_run(element_ptr);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user