working render

This commit is contained in:
2024-11-20 15:47:27 +01:00
parent e55606b9cf
commit e4835b9efa
5 changed files with 62 additions and 95 deletions
+5 -43
View File
@@ -4,15 +4,8 @@
#include <pthread.h> #include <pthread.h>
#include <time.h> #include <time.h>
typedef struct extern boolean_t render(void* element);
{ extern void *event_loop(void* element);
uint32_t* state;
void* element;
} EventArgs;
extern void render(void* element, uint32_t state);
extern void event(void* element, uint32_t* state);
extern void init_event(void* element, uint32_t* state);
void sleep_ms(long milliseconds) void sleep_ms(long milliseconds)
{ {
@@ -22,49 +15,18 @@ void sleep_ms(long milliseconds)
nanosleep(&ts, NULL); nanosleep(&ts, NULL);
} }
void *event_checker(void *args)
{
EventArgs* event_args = (EventArgs*)args;
init_event(event_args->element, event_args->state);
while (1) {
if (event_args->state == 0) { return NULL; }
event(event_args->element, event_args->state);
}
return NULL;
}
void *command_checker(void *args)
{
EventArgs* event_args = (EventArgs*)args;
init_event(event_args->element, event_args->state);
while (1) {
if (event_args->state == 0) { return NULL; }
event(event_args->element, event_args->state);
}
return NULL;
}
boolean_t c_run(void* element) boolean_t c_run(void* element)
{ {
pthread_t thread; pthread_t thread;
uint32_t state = 3;
EventArgs event_args = { .element = element, .state = &state };
if (pthread_create(&thread, NULL, event_checker, &event_args) != 0) if (pthread_create(&thread, NULL, event_loop, element) != 0)
{ {
perror("Failed to create thread"); perror("Failed to create thread");
} }
while (1) while (render(element))
{ {
if (state == 0) {
free(element);
return 0;
} else if (state == 1) {
free(element);
return 1;
}
render(element, state);
sleep_ms(20); sleep_ms(20);
} }
return 0;
} }
+33 -28
View File
@@ -1,52 +1,55 @@
use crossterm::terminal::{disable_raw_mode, enable_raw_mode}; use crossterm::{
event::Event,
terminal::{disable_raw_mode, enable_raw_mode},
};
use crate::{ use crate::{
utils::{clear, create_frame, flush, get_term_size, hide_cursor, render_to_frame, show_cursor}, utils::{clear, create_frame, flush, get_term_size, hide_cursor, render_to_frame, show_cursor},
Element, State, StateChanger, Element, StateChanger,
}; };
use std::ffi::c_void; use std::{ffi::c_void, ptr::null};
extern "C" { extern "C" {
fn c_run(element: *mut c_void) -> bool; fn c_run(element: *mut c_void) -> bool;
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn render(ptr: *mut c_void, state: u32) { extern "C" fn render(ptr: *mut c_void) -> bool {
let element = unsafe { if ptr.is_null() {
assert!(!ptr.is_null(), "Pointer is null"); return false;
&mut *(ptr as *mut Element) }
}; let element = unsafe { &mut *(ptr as *mut Element) };
let (width, height) = get_term_size(); let (width, height) = get_term_size();
let mut frame: Vec<String> = create_frame(width, height); let mut frame: Vec<String> = create_frame(width, height);
render_to_frame(State::from_u32(state), width, &mut frame, element); render_to_frame(true, width, &mut frame, element);
clear(); clear();
print!("{}", frame.join("")); print!("{}", frame.join(""));
flush(); flush();
true
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn event(ptr: *mut c_void, state: *mut u32) { extern "C" fn event_loop(ptr: *mut c_void) -> *const c_void {
let event = crossterm::event::read().unwrap(); if ptr.is_null() {
let element = unsafe { return null() as *const c_void;
assert!(!ptr.is_null(), "Pointer is null"); }
&mut *(ptr as *mut Element) let element = unsafe { &mut *(ptr as *mut Element) };
}; let (width, height) = get_term_size();
element.update_data(width, height);
loop {
if ptr.is_null() {
break;
}
event(element, crossterm::event::read().unwrap())
}
null() as *const c_void
}
fn event(element: &mut Element, event: Event) {
if let crossterm::event::Event::Resize(width, height) = event { if let crossterm::event::Event::Resize(width, height) = event {
element.update_data(width as usize, height as usize); element.update_data(width as usize, height as usize);
} }
element.event(event, &StateChanger(state)); element.event(event, &StateChanger(&mut 0));
}
#[no_mangle]
pub extern "C" fn init_event(ptr: *mut c_void, state: *mut u32) {
let event = crossterm::event::Event::FocusGained;
let element = unsafe {
assert!(!ptr.is_null(), "Pointer is null");
&mut *(ptr as *mut Element)
};
let (width, height) = get_term_size();
element.update_data(width, height);
element.event(event, &StateChanger(state));
} }
pub fn run(element: &mut Element) -> bool { pub fn run(element: &mut Element) -> bool {
@@ -55,9 +58,11 @@ pub fn run(element: &mut Element) -> bool {
clear(); clear();
unsafe { unsafe {
let c = c_run(element as *mut Element as *mut c_void); let c = c_run(element as *mut Element as *mut c_void);
if !c {
show_cursor(); show_cursor();
disable_raw_mode().unwrap(); disable_raw_mode().unwrap();
clear(); clear();
}
return c; return c;
} }
} }
+2 -2
View File
@@ -94,8 +94,8 @@ pub trait ElementCore: Send + Sync {
} }
pub trait Component: ElementCore + std::fmt::Debug { pub trait Component: ElementCore + std::fmt::Debug {
fn render(&self, state: State) -> String { fn render(&self, focused: bool) -> String {
_ = state; _ = focused;
String::new() String::new()
} }
+12 -12
View File
@@ -29,7 +29,7 @@ use osui_element::{elem_fn, element};
pub struct Text {} pub struct Text {}
impl Component for Text<'_> { impl Component for Text<'_> {
fn render(&self, _: crate::State) -> String { fn render(&self, _: bool) -> String {
if let Children::Text(text) = &self.children { if let Children::Text(text) = &self.children {
text.clone() text.clone()
} else { } else {
@@ -66,23 +66,19 @@ pub struct Div {
} }
impl Component for Div<'_> { impl Component for Div<'_> {
fn render(&self, state: State) -> String { fn render(&self, focused: bool) -> String {
let mut frame = crate::utils::create_frame(self.width.get_value(), self.height.get_value()); let mut frame = crate::utils::create_frame(self.width.get_value(), self.height.get_value());
if let Children::Children(children, child) = &self.children { if let Children::Children(children, child) = &self.children {
for (i, elem) in children.iter().enumerate() { for (i, elem) in children.iter().enumerate() {
if i == *child {
crate::utils::render_to_frame(state, self.width.get_value(), &mut frame, elem);
} else {
crate::utils::render_to_frame( crate::utils::render_to_frame(
crate::State::Normal, focused && i == *child,
self.width.get_value(), self.width.get_value(),
&mut frame, &mut frame,
elem, elem,
); );
} }
} }
}
frame.join("\n") frame.join("\n")
} }
@@ -142,14 +138,18 @@ impl Component for Div<'_> {
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct Button { pub struct Button {
pub on_click: Handler<Button<'a>>, pub on_click: Handler<Button<'a>>,
pub state: &'a str,
} }
impl Component for Button<'_> { impl Component for Button<'_> {
fn render(&self, state: State) -> String { fn render(&self, focused: bool) -> String {
match state { if self.state == "click" {
State::Custom(_) => self.style.write("click", &self.children.get_text()), return self.style.write("click", &self.children.get_text());
State::Hover => self.style.write("hover", &self.children.get_text()), }
_ => self.style.write("", &self.children.get_text()), if focused {
self.style.write("hover", &self.children.get_text())
} else {
self.style.write("", &self.children.get_text())
} }
} }
+2 -2
View File
@@ -87,13 +87,13 @@ fn merge_line(frame_: &str, line_: &str, x: usize) -> String {
/// Render to a frame /// Render to a frame
pub fn render_to_frame( pub fn render_to_frame(
state: crate::State, focused: bool,
width: usize, width: usize,
frame: &mut Vec<String>, frame: &mut Vec<String>,
element: &Element, element: &Element,
) { ) {
let data = element.get_data(); let data = element.get_data();
for (i, line) in element.render(state).split('\n').enumerate() { for (i, line) in element.render(focused).split('\n').enumerate() {
if (data.1 + i) < frame.len() { if (data.1 + i) < frame.len() {
let frame_line = frame.get_mut(data.1 + i).unwrap(); let frame_line = frame.get_mut(data.1 + i).unwrap();
match data.0 { match data.0 {