From 6d86e8a42baf5a9a780af3017521be881c1ae943 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Mon, 25 Nov 2024 22:15:32 +0100 Subject: [PATCH] huge improvedments --- .DS_Store | Bin 6148 -> 6148 bytes build.rs | 4 -- build.sh | 4 -- src/app.c | 21 --------- src/app.rs | 112 ------------------------------------------------ src/examples.rs | 14 +----- src/lib.rs | 93 +++++++++++++++++++++++++++++----------- src/macros.rs | 7 +++ src/main.rs | 2 +- src/rsx.rs | 6 +-- src/ui/mod.rs | 36 +--------------- 11 files changed, 82 insertions(+), 217 deletions(-) delete mode 100644 build.rs delete mode 100755 build.sh delete mode 100644 src/app.c delete mode 100644 src/app.rs diff --git a/.DS_Store b/.DS_Store index b4c51467bb0f93faeae1d267b2e19b70aefec959..3b35e3e03a7796aecbd1fac04779c75fe628b60a 100644 GIT binary patch delta 32 ocmZoMXfc@J&&abeU^gQp&t@K`V#dv49D*zp3(7aMbNuB80G&z+fB*mh delta 163 zcmZoMXfc@J&nU1lU^gS9z-At%V#azlh7yKEh9ZV^hE#@ -#include -#include -#include -#include - -extern void *event_loop(void* args); -extern void *cmd_loop(void* args); - -boolean_t c_run(void* args) -{ - pthread_t event_thread; - - if (pthread_create(&event_thread, NULL, event_loop, args) != 0) - { - perror("Failed to create thread"); - } - - cmd_loop(args); - return FALSE; -} \ No newline at end of file diff --git a/src/app.rs b/src/app.rs deleted file mode 100644 index 89d288f..0000000 --- a/src/app.rs +++ /dev/null @@ -1,112 +0,0 @@ -use crossterm::terminal::{disable_raw_mode, enable_raw_mode}; - -use crate::prelude::*; -use crate::utils::{clear, flush, get_term_size, hide_cursor, show_cursor, Frame}; -use std::{ffi::c_void, ptr::null, sync::mpsc}; - -struct LArgs<'a> { - pub element: &'a mut Element, - - // for sending commands - pub stx: mpsc::Sender, - pub srx: mpsc::Receiver, - - // for returning command output - pub rtx: mpsc::Sender, - pub rrx: mpsc::Receiver, - pub running: bool, -} - -extern "C" { - fn c_run(args: *mut c_void) -> bool; -} - -pub fn run(element: &mut Element) -> bool { - hide_cursor(); - enable_raw_mode().unwrap(); - clear(); - unsafe { - let (stx, srx) = mpsc::channel(); - let (rtx, rrx) = mpsc::channel(); - let c = c_run(&mut LArgs { - running: true, - element, - stx, - srx, - rtx, - rrx, - } as *mut LArgs as *mut c_void); - if !c { - show_cursor(); - disable_raw_mode().unwrap(); - clear(); - } - return c; - } -} - -#[no_mangle] -extern "C" fn event_loop(ptr: *mut c_void) -> *const c_void { - if ptr.is_null() { - return null() as *const c_void; - } - let args = unsafe { &mut *(ptr as *mut LArgs) }; - let document = Document { - cmd_sender: args.stx.clone(), - cmd_recv: &args.rrx as *const mpsc::Receiver as *const c_void, - }; - - let (width, height) = get_term_size(); - args.element.event( - crossterm::event::Event::Resize(width as u16, height as u16), - &document, - ); - args.element - .event(crossterm::event::Event::FocusGained, &document); - document.render(); - - while args.running || !ptr.is_null() { - args.element - .event(crossterm::event::read().unwrap(), &document); - document.render(); - } - null() as *const c_void -} - -#[no_mangle] -extern "C" fn cmd_loop(ptr: *mut c_void) -> *const c_void { - if ptr.is_null() { - return null() as *const c_void; - } - - let args = unsafe { &mut *(ptr as *mut LArgs) }; - - loop { - match args.srx.recv().unwrap() { - Command::Exit => { - args.running = false; - break; - } - Command::GetElementById(id) => { - args.rtx - .send(if let Some(e) = args.element.get_element_by_id(&id) { - crate::CommandResult::Element(e as *mut Element) - } else if args.element.get_id() == id { - crate::CommandResult::Element(args.element as *mut Element) - } else { - crate::CommandResult::None - }) - .unwrap(); - } - Command::Render => { - let (width, height) = get_term_size(); - let mut frame = Frame::new(width, height); - frame.render(true, args.element); - clear(); - print!("{}", frame.output_nnl()); - flush(); - } - } - } - null() -} diff --git a/src/examples.rs b/src/examples.rs index 28e1910..f08fbc4 100644 --- a/src/examples.rs +++ b/src/examples.rs @@ -3,24 +3,14 @@ use crate::prelude::*; pub fn examples() -> Element { rsx! { styling: Some(styling()), - button { class: "btn", on_click: Handler::new(|btn: &mut Button, _, document| { - let data = document.get_element_by_id::>("my_data").unwrap(); - data.data += "!"; - btn.children.set_text(&data.data); - }), "Hello, World!" } - - { - let mut data = dataholder::(); - data.id = "my_data"; - data - } + button { class: "btn", "Hello, World!" } } } pub fn styling() -> Css { css! { .btn { - x: 30%, + x: Center, y: Auto, color: Red, } diff --git a/src/lib.rs b/src/lib.rs index 6252a67..be7e663 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,9 +26,6 @@ use std::{ sync::{Arc, Mutex}, }; -use crossterm::event::Event; - -pub mod app; pub mod css; pub mod examples; pub mod macros; @@ -36,13 +33,11 @@ pub mod rsx; pub mod ui; pub mod utils; -pub use app::run; - pub mod prelude { pub use crate::ui::Color::*; pub use crate::ui::Number::*; - pub use crate::{self as osui, css, rsx, rsx_elem, ui::*, Handler}; - pub use crate::{call, Children, ElementCore, ElementWidget, Element}; + pub use crate::{self as osui, css, ersx, rsx, ui::*, Handler, launch}; + pub use crate::{call, Children, Element, ElementCore, ElementWidget}; pub use crate::{style, Command, Document, RenderResult, RenderWriter, Value}; pub use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind}; pub fn sleep(ms: u64) { @@ -68,7 +63,7 @@ pub trait ElementCore { pub trait ElementWidget: ElementCore + std::fmt::Debug + Send + Sync { fn render(&self, focused: bool) -> Option; - fn event(&mut self, event: Event, document: &Document) { + fn event(&mut self, event: crossterm::event::Event, document: &Document) { _ = (event, document) } } @@ -77,11 +72,13 @@ pub trait ElementWidget: ElementCore + std::fmt::Debug + Send + Sync { /// Structs ////////////////////////////////////////////////////////////////////////////////////////////////// -pub struct Handler(pub Arc>); +pub struct Handler( + pub Arc>, +); pub struct Document { - cmd_sender: std::sync::mpsc::Sender, - cmd_recv: *const std::ffi::c_void, + element: *mut Element, + running: *mut Option, } /// ``` @@ -169,28 +166,48 @@ impl Default for Value { impl Document { pub fn exit(&self) { - self.cmd_sender.send(Command::Exit).unwrap(); + if !self.running.is_null() { + unsafe { + *self.running = Some(false); + } + } + } + pub fn rebuild(&self) { + if !self.running.is_null() { + unsafe { + *self.running = Some(true); + } + } } pub fn get_element_by_id(&self, id: &str) -> Option<&mut Box> { if let Some(e) = self.get_element_by_id_raw(id) { - Some(convert(unsafe { &mut *e })) + Some(unsafe { &mut *(e as *mut Element as *mut Box) }) } else { None } } - pub fn get_element_by_id_raw(&self, id: &str) -> Option<*mut Element> { - self.cmd_sender - .send(Command::GetElementById(id.to_string())) - .unwrap(); - let rx = unsafe { &*(self.cmd_recv as *const std::sync::mpsc::Receiver) }; - if let Ok(CommandResult::Element(e)) = rx.recv() { - Some(e) + pub fn get_element_by_id_raw(&self, id: &str) -> Option<&mut Element> { + if !self.element.is_null() { + unsafe { + if (*self.element).get_id() == id { + Some(&mut *self.element) + } else { + (*self.element).get_element_by_id(id) + } + } } else { None } } pub fn render(&self) { - self.cmd_sender.send(Command::Render).unwrap(); + if !self.running.is_null() { + let (width, height) = utils::get_term_size(); + let mut frame = utils::Frame::new(width, height); + frame.render(true, unsafe { &*self.element }); + utils::clear(); + print!("{}", frame.output_nnl()); + utils::flush(); + } } } @@ -254,7 +271,7 @@ impl Children { impl Handler { pub fn new(handler_fn: F) -> Handler where - F: FnMut(&mut T, Event, &Document) + 'static + Send + Sync, + F: FnMut(&mut T, crossterm::event::Event, &Document) + 'static + Send + Sync, { Handler(Arc::new(Mutex::new(handler_fn))) } @@ -280,7 +297,9 @@ impl RenderWriter { impl Default for Handler { fn default() -> Self { - Handler(Arc::new(Mutex::new(|_: &mut T, _: Event, _: &Document| {}))) + Handler(Arc::new(Mutex::new( + |_: &mut T, _: crossterm::event::Event, _: &Document| {}, + ))) } } @@ -290,6 +309,30 @@ impl std::fmt::Debug for Handler { } } -pub fn convert(widget: &mut Box) -> &mut Box { - unsafe { &mut *(widget as *mut _ as *mut Box) } +pub fn run(element: &mut Element) -> bool { + let document = Document { + element: element, + running: &mut None, + }; + let (width, height) = crate::utils::get_term_size(); + element.event( + crossterm::event::Event::Resize(width as u16, height as u16), + &document, + ); + element.event(crossterm::event::Event::FocusGained, &document); + + utils::hide_cursor(); + crossterm::terminal::enable_raw_mode().unwrap(); + utils::clear(); + + while unsafe { *document.running } == None { + document.render(); + element.event(crossterm::event::read().unwrap(), &document); + } + + utils::show_cursor(); + crossterm::terminal::disable_raw_mode().unwrap(); + utils::clear(); + + unsafe { (*document.running).unwrap() } } diff --git a/src/macros.rs b/src/macros.rs index 71694dd..9804bd6 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -16,3 +16,10 @@ macro_rules! call { &$self.$handler; }}; } + +#[macro_export] +macro_rules! launch { + ($expr:expr) => { + while $crate::run(&mut $expr) {} + }; +} diff --git a/src/main.rs b/src/main.rs index 83d651b..6a2f33b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,5 +2,5 @@ use osui::examples; use osui::prelude::*; fn main() { - while osui::run(&mut examples::examples()) {} + launch!(examples::examples()); } diff --git a/src/rsx.rs b/src/rsx.rs index ce3f97b..8015222 100644 --- a/src/rsx.rs +++ b/src/rsx.rs @@ -50,7 +50,7 @@ macro_rules! parse_rsx_param { ($elem:expr, $elem_path:path { $($inner:tt)* } $($rest:tt)*) => { if $elem.children.is_none() {$elem.children = $crate::Children::Children(Vec::new(), 0)} if let $crate::Children::Children(children, _) = &mut $elem.children { - children.push(osui::rsx_elem!($elem_path { $($inner)* })); + children.push(osui::ersx!($elem_path { $($inner)* })); } osui::parse_rsx_param!($elem, $($rest)*) }; @@ -66,7 +66,7 @@ macro_rules! parse_rsx_param { } #[macro_export] -macro_rules! rsx_elem { +macro_rules! ersx { ($elem:path { $($inner:tt)* }) => {{ #[allow(unused_mut)] let mut elem = $elem(); @@ -89,7 +89,7 @@ macro_rules! rsx_elem { #[macro_export] macro_rules! rsx { ($($inner:tt)*) => { - $crate::rsx_elem!{ $crate::ui::div { $($inner)* } } + $crate::ersx!{ $crate::ui::div { $($inner)* } } }; } diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 23b8a79..f4813d2 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -9,21 +9,6 @@ pub use styles::*; use crate::prelude::*; use osui_element::{elem_fn, element}; -/// The `Text` element represents a piece of static text in the terminal UI. -/// -/// It is used to render plain text within a UI component. The `Text` element does not interact -/// with events and only outputs the text when rendered. -/// -/// # Example -/// ```rust -/// let text = Text::default(); -/// let rendered_text = text.render(crate::State::Normal); -/// println!("{}", rendered_text); -/// ``` -/// -/// ## Methods -/// - `render(state: crate::State) -> String`: Renders the text to a string, depending on the state. -/// If the element contains text as a child, it returns that text. Otherwise, it returns an empty string. #[element] #[elem_fn] #[derive(Default, Debug)] @@ -50,26 +35,6 @@ impl ElementWidget for Text<'_> { } } -/// The `Div` element represents a container for other UI elements. It can hold child components -/// and render them in a specific layout. The `Div` element also handles keyboard navigation through -/// its children. -/// -/// The `Div` element supports rendering a list of children and allows interactive navigation using -/// arrow keys (Up, Down, Left, Right). It renders the selected child element differently based on the state. -/// -/// # Example -/// ```rust -/// let div = Div::default(); -/// let rendered_div = div.render(crate::State::Normal); -/// println!("{}", rendered_div); -/// ``` -/// -/// ## Methods -/// - `render(state: crate::State) -> String`: Renders the `Div` and its child elements to a string. -/// The child elements are rendered according to the current selection (`child` index). -/// - `event(event: Event, state: &crate::StateChanger)`: Handles keyboard events for -/// navigation through child elements. Arrow keys (Up, Down, Left, Right) change the currently selected child. - #[element] #[elem_fn] #[derive(Default, Debug)] @@ -128,6 +93,7 @@ impl ElementWidget for Button<'_> { document.render(); sleep(100); self.style.set_state(""); + document.rebuild(); } } _ => {}