Files
osui/src/lib.rs
T
2024-11-16 16:38:06 +01:00

148 lines
3.5 KiB
Rust

//! # OSUI
//!
//! A terminal user interface (TUI) library providing customizable components
//! to build command-line interfaces in Rust. OSUI enables users to create
//! interactive CLI applications with various UI elements and handle keyboard
//! input for real-time events.
//!
//! ## Example Usage
//!
//! ```rust
//! use osui::{self, rsx, ui::*};
//!
//! osui::app::run(&mut rsx! {
//! text { "Hello, World!" }
//! });
//! ```
//!
//! ## Modules
//! - `utils` - Utility functions for common TUI tasks such as clearing the screen.
//! - `ui` - Contains all user interface components, enabling rich CLI experiences.
pub mod macros;
pub mod ui;
pub mod utils;
pub use utils::*;
pub mod app;
/// Enum representing the wether it's the default or custom.
///
/// - `Default(usize)` - Uses a default value.
/// - `Custom(usize)` - Allows specifying a custom value.
#[derive(Debug, Clone, Copy)]
pub enum Value<T: Copy + PartialEq> {
Default(T),
Custom(T),
}
impl<T: Copy + PartialEq> Value<T> {
/// Creates a new Value.
///
/// # Returns
///
/// Value::Custom(usize)
pub fn new(value: T) -> Value<T> {
Value::Custom(value)
}
/// Retrieves the value.
///
/// # Returns
///
/// The value by the type T.
pub fn get_value(&self) -> T {
match self {
Value::Custom(s) => *s,
Value::Default(s) => *s,
}
}
/// Attempts to set the value if it is currently set to `Default`.
///
/// If the size is `Custom`, this function will not modify it.
///
/// # Arguments
///
/// * `value` - The value to change to.
pub fn try_set_value(&mut self, value: T) {
if let Value::Default(_) = *self {
*self = Value::Default(value);
}
}
}
/// A trait for defining UI elements in OSUI.
///
/// Elements must implement methods for updating and rendering data.
pub trait Element: Send + Sync {
fn get_data(&self) -> (Value<usize>, usize, String);
fn update_data(&mut self, width: usize, height: usize);
fn get_element_by_id(&mut self, id: &str) -> Option<&mut Box<dyn Element>>;
fn render(&self, state: State) -> String {
_ = state;
String::new()
}
fn event(&mut self, event: crossterm::event::Event, state: &StateChanger) {
(_, _) = (event, state)
}
}
pub struct Handler<T>(pub Box<dyn FnMut(&T, &StateChanger, crossterm::event::Event) + Send>);
impl<T> Handler<T> {
pub fn new<F>(handler_fn: F) -> Handler<T>
where
F: FnMut(&T, &StateChanger, crossterm::event::Event) + 'static + Send,
{
Handler(Box::new(handler_fn))
}
}
#[derive(Debug, Clone)]
pub enum State {
Exit,
Rebuild,
Normal,
Hover,
Custom(usize),
}
impl State {
pub fn from_u32(s: u32) -> State {
match s {
0 => State::Exit,
1 => State::Rebuild,
2 => State::Normal,
3 => State::Hover,
_ => State::Custom((s - 4) as usize),
}
}
pub fn to_u32(&self) -> u32 {
match self {
State::Exit => 0,
State::Rebuild => 1,
State::Normal => 2,
State::Hover => 3,
State::Custom(s) => (4 + s) as u32,
}
}
}
pub struct StateChanger(*mut u32);
impl StateChanger {
pub fn set_state(&self, s: State) {
unsafe {
(*self.0) = s.to_u32();
}
}
pub fn get_state(&self) -> State {
State::from_u32(unsafe { *self.0 })
}
}