some more structural changes
This commit is contained in:
@@ -19,3 +19,4 @@ crossterm = "0.28.1"
|
|||||||
regex = "*"
|
regex = "*"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
dyn-clone = "1.0.17"
|
dyn-clone = "1.0.17"
|
||||||
|
paste = "1.0.15"
|
||||||
+22
-48
@@ -3,7 +3,7 @@
|
|||||||
//! A terminal user interface (TUI) library providing customizable components
|
//! A terminal user interface (TUI) library providing customizable components
|
||||||
//! to build command-line interfaces in Rust. OSUI enables users to create
|
//! to build command-line interfaces in Rust. OSUI enables users to create
|
||||||
//! interactive CLI applications with various UI elements and handle keyboard
|
//! interactive CLI applications with various UI elements and handle keyboard
|
||||||
//! input for real-time updates.
|
//! input for real-time events.
|
||||||
//!
|
//!
|
||||||
//! ## Example Usage
|
//! ## Example Usage
|
||||||
//!
|
//!
|
||||||
@@ -21,14 +21,14 @@
|
|||||||
//! - `utils` - Utility functions for common TUI tasks such as clearing the screen.
|
//! - `utils` - Utility functions for common TUI tasks such as clearing the screen.
|
||||||
//! - `ui` - Contains all user interface components, enabling rich CLI experiences.
|
//! - `ui` - Contains all user interface components, enabling rich CLI experiences.
|
||||||
|
|
||||||
|
pub mod event;
|
||||||
pub mod key;
|
pub mod key;
|
||||||
pub mod macros;
|
pub mod macros;
|
||||||
mod test;
|
mod test;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
use event::{Event, EventResponse};
|
||||||
pub use utils::*;
|
pub use utils::*;
|
||||||
|
|
||||||
pub mod app {
|
pub mod app {
|
||||||
//! Application entry point and main event loop for OSUI.
|
//! Application entry point and main event loop for OSUI.
|
||||||
//!
|
//!
|
||||||
@@ -37,9 +37,11 @@ pub mod app {
|
|||||||
//! using custom commands such as rendering, updating, or exiting.
|
//! using custom commands such as rendering, updating, or exiting.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
clear, create_frame, flush, get_term_size, hide_cursor,
|
clear, create_frame,
|
||||||
key::{read_key, Key},
|
event::{Command, Event, EventResponse},
|
||||||
render_to_frame, show_cursor, Command, Element, UpdateResponse, Value,
|
flush, get_term_size, hide_cursor,
|
||||||
|
key::read_key,
|
||||||
|
render_to_frame, show_cursor, Element, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Renders a single frame of the UI to the terminal.
|
/// Renders a single frame of the UI to the terminal.
|
||||||
@@ -63,7 +65,7 @@ pub mod app {
|
|||||||
|
|
||||||
/// Updates the UI element based on keyboard input and issues any commands in response.
|
/// Updates the UI element based on keyboard input and issues any commands in response.
|
||||||
///
|
///
|
||||||
/// Processes the result of `Element::update` to handle commands like rendering,
|
/// Processes the result of `Element::event` to handle commands like rendering,
|
||||||
/// updating, and exiting. Commands can be a single action or a list of actions.
|
/// updating, and exiting. Commands can be a single action or a list of actions.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
@@ -75,12 +77,12 @@ pub mod app {
|
|||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
/// `true` if an `Exit` command is issued, signaling the application to terminate.
|
/// `true` if an `Exit` command is issued, signaling the application to terminate.
|
||||||
fn update(elem: &mut Box<dyn Element>, state: usize, k: Key) -> bool {
|
fn update(elem: &mut Box<dyn Element>, event: Event) -> bool {
|
||||||
match elem.event(state, k.clone()) {
|
match elem.event(event) {
|
||||||
UpdateResponse::Command(command) => run_command(command, elem, k.clone()),
|
EventResponse::Command(command) => run_command(command, elem),
|
||||||
UpdateResponse::CommandList(commands) => {
|
EventResponse::CommandList(commands) => {
|
||||||
for command in commands {
|
for command in commands {
|
||||||
if run_command(command, elem, k.clone()) {
|
if run_command(command, elem) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,13 +104,13 @@ pub mod app {
|
|||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
/// `true` if the command is `Exit`, ending the application loop.
|
/// `true` if the command is `Exit`, ending the application loop.
|
||||||
fn run_command(command: Command, elem: &mut Box<dyn Element>, k: Key) -> bool {
|
fn run_command(command: Command, elem: &mut Box<dyn Element>) -> bool {
|
||||||
match command {
|
match command {
|
||||||
Command::Render(state) => {
|
Command::Render(state) => {
|
||||||
render(elem, state);
|
render(elem, state);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
Command::Update(state) => update(elem, state, k),
|
Command::Event(event) => update(elem, event),
|
||||||
Command::Sleep(duration) => {
|
Command::Sleep(duration) => {
|
||||||
std::thread::sleep(std::time::Duration::from_millis(duration));
|
std::thread::sleep(std::time::Duration::from_millis(duration));
|
||||||
false
|
false
|
||||||
@@ -137,8 +139,7 @@ pub mod app {
|
|||||||
clear();
|
clear();
|
||||||
loop {
|
loop {
|
||||||
render(elem, 1);
|
render(elem, 1);
|
||||||
let k = read_key();
|
if update(elem, Event::Key(read_key())) {
|
||||||
if update(elem, 1, k) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,14 +240,13 @@ pub trait Element: DynClone {
|
|||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `_state` - The current state of the element; if one or higher, it indicates the element is active.
|
/// * `_event` - The current event.
|
||||||
/// * `_k` - The key input triggering the update.
|
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
/// An `UpdateResponse` enum indicating the result of the update.
|
/// An `EventResponse` enum indicating the result of the event.
|
||||||
fn event(&mut self, _state: usize, _k: crate::key::Key) -> UpdateResponse {
|
fn event(&mut self, _event: Event) -> EventResponse {
|
||||||
UpdateResponse::None
|
EventResponse::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,32 +272,6 @@ pub struct ElementData {
|
|||||||
pub id: String,
|
pub id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enum representing the possible responses from an element update.
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub enum UpdateResponse {
|
|
||||||
/// Indicates that the update is complete.
|
|
||||||
Done,
|
|
||||||
/// Indicates no response.
|
|
||||||
None,
|
|
||||||
/// Issues a single command.
|
|
||||||
Command(Command),
|
|
||||||
/// Issues a list of commands.
|
|
||||||
CommandList(Vec<Command>),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Enum defining commands that can be issued by an `Element`.
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub enum Command {
|
|
||||||
/// Renders the element with the specified state.
|
|
||||||
Render(usize),
|
|
||||||
/// Exits the application.
|
|
||||||
Exit,
|
|
||||||
/// Updates the element with the specified state.
|
|
||||||
Update(usize),
|
|
||||||
/// Pauses execution for the specified duration in milliseconds.
|
|
||||||
Sleep(u64),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run_test() {
|
pub fn run_test() {
|
||||||
test::main_();
|
app::run(&mut test::app());
|
||||||
}
|
}
|
||||||
|
|||||||
+96
-3
@@ -24,6 +24,57 @@
|
|||||||
/// - `functions`: Functions to implement for the element (e.g., rendering, updating).
|
/// - `functions`: Functions to implement for the element (e.g., rendering, updating).
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! element {
|
macro_rules! element {
|
||||||
|
(
|
||||||
|
$(#[$meta_style:meta])*
|
||||||
|
style $style:ident {
|
||||||
|
$($sn:ident: $st:ty),*$(,)?
|
||||||
|
}
|
||||||
|
$(#[$meta:meta])*
|
||||||
|
$name:ident {
|
||||||
|
$( $inner:tt )*
|
||||||
|
}
|
||||||
|
defaults {$( $defaults:tt )*}
|
||||||
|
$( $functions:tt )*
|
||||||
|
) => {
|
||||||
|
$(#[$meta_style])*
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct $style {
|
||||||
|
pub color: Color,
|
||||||
|
pub background: Color,
|
||||||
|
pub font: Font,
|
||||||
|
pub hover_color: Color,
|
||||||
|
pub hover_background: Color,
|
||||||
|
pub hover_font: Font,
|
||||||
|
$(pub $sn: $st),*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for $style {
|
||||||
|
fn default() -> $style {
|
||||||
|
$style {
|
||||||
|
color: Color::default(),
|
||||||
|
background: Color::default(),
|
||||||
|
font: Font::default(),
|
||||||
|
hover_color: Color::default(),
|
||||||
|
hover_background: Color::default(),
|
||||||
|
hover_font: Font::default(),
|
||||||
|
$($sn: <$st>::default()),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
element! {
|
||||||
|
$(#[$meta])*
|
||||||
|
$name {
|
||||||
|
pub style: $style,
|
||||||
|
$( $inner )*
|
||||||
|
}
|
||||||
|
defaults {
|
||||||
|
style: $style::default(),
|
||||||
|
$($defaults)*
|
||||||
|
}
|
||||||
|
$( $functions )*
|
||||||
|
}
|
||||||
|
};
|
||||||
(
|
(
|
||||||
$(#[$meta:meta])*
|
$(#[$meta:meta])*
|
||||||
$name:ident {
|
$name:ident {
|
||||||
@@ -129,11 +180,11 @@ macro_rules! element {
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// # Parameters
|
/// # Parameters
|
||||||
/// - A list of commands to be included in the `UpdateResponse::CommandList`.
|
/// - A list of commands to be included in the `EventResponse::CommandList`.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! command {
|
macro_rules! command {
|
||||||
($($cmd:expr),*) => {
|
($($cmd:expr),*) => {
|
||||||
UpdateResponse::CommandList(vec![$($cmd),*])
|
EventResponse::CommandList(vec![$($cmd),*])
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +322,7 @@ macro_rules! rsx {
|
|||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
/// css!(Style; color: "red"; background: "white");
|
/// css!(Style; color: Color::Red; background: "white");
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// This macro creates a new style based on the provided properties, applying default values
|
/// This macro creates a new style based on the provided properties, applying default values
|
||||||
@@ -289,6 +340,7 @@ macro_rules! css {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Macro for defining a `Arc<Mutex< T >>`
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! arc {
|
macro_rules! arc {
|
||||||
($a:expr) => {
|
($a:expr) => {
|
||||||
@@ -296,9 +348,50 @@ macro_rules! arc {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Macro for defining a `Value< T >`
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! val {
|
macro_rules! val {
|
||||||
($a:expr) => {
|
($a:expr) => {
|
||||||
osui::Value::new($a)
|
osui::Value::new($a)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Macro for writing when requested to render
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// write!(self, clicked, "Hello, World!") // For custom styles, You need (color, background, font)
|
||||||
|
///
|
||||||
|
/// write!((self, state), "Hello, World!") // When you don't need a custom style, you use () and put self and the state of the render
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// This macro returns a `String` depending on the state or the kind of style
|
||||||
|
/// When on "state" mode it returns the default style if the state is 0
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! write {
|
||||||
|
// Default state styling
|
||||||
|
(($self:ident, $state:expr), $expr:expr) => {{
|
||||||
|
if $state == 0 {
|
||||||
|
return format!("{}{}{}{}\x1b[0m", $self.style.color.ansi(), $self.style.background.ansi_bg(), $self.style.font.ansi(), $expr);
|
||||||
|
}
|
||||||
|
format!("{}{}{}{}\x1b[0m", $self.style.hover_color.ansi(), $self.style.hover_background.ansi_bg(), $self.style.hover_font.ansi(), $expr)
|
||||||
|
}};
|
||||||
|
|
||||||
|
// Custom styles
|
||||||
|
($self:ident, $kind:ident, $expr:expr) => {{
|
||||||
|
use paste::paste;
|
||||||
|
format!(
|
||||||
|
"{}{}{}{}\x1b[0m",
|
||||||
|
paste! {
|
||||||
|
$self.style.[<$kind _color>].ansi()
|
||||||
|
},
|
||||||
|
paste! {
|
||||||
|
$self.style.[<$kind _background>].ansi_bg()
|
||||||
|
},
|
||||||
|
paste! {
|
||||||
|
$self.style.[<$kind _font>].ansi()
|
||||||
|
},
|
||||||
|
$expr
|
||||||
|
)
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|||||||
+48
-26
@@ -1,8 +1,15 @@
|
|||||||
use std::{collections::HashMap, sync::{Arc, Mutex}};
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
command, element, key::Key, render_to_frame, ui::Style, Command, Direction, Element,
|
command, element,
|
||||||
ElementData, Value, UpdateResponse,
|
event::{Command, Event},
|
||||||
|
key::Key,
|
||||||
|
render_to_frame,
|
||||||
|
ui::{Color, Font},
|
||||||
|
write, Direction, Element, ElementData, EventResponse, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
element! {
|
element! {
|
||||||
@@ -17,6 +24,12 @@ element! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
element! {
|
element! {
|
||||||
|
style ButtonStyle {
|
||||||
|
clicked_color: Color,
|
||||||
|
clicked_background: Color,
|
||||||
|
clicked_font: Font,
|
||||||
|
}
|
||||||
|
|
||||||
/// A clickable button element.
|
/// A clickable button element.
|
||||||
///
|
///
|
||||||
/// The `Button` element can be clicked, triggering an `on_click` function. Its appearance changes
|
/// The `Button` element can be clicked, triggering an `on_click` function. Its appearance changes
|
||||||
@@ -24,35 +37,38 @@ element! {
|
|||||||
Button {
|
Button {
|
||||||
/// A callback function executed when the button is clicked.
|
/// A callback function executed when the button is clicked.
|
||||||
pub on_click: Arc<Mutex<dyn FnMut(&mut Button)>>,
|
pub on_click: Arc<Mutex<dyn FnMut(&mut Button)>>,
|
||||||
pub style: Style,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defaults {
|
defaults {
|
||||||
on_click: Arc::new(Mutex::new(|_btn: &mut Button<'_>| {})),
|
on_click: Arc::new(Mutex::new(|_btn: &mut Button<'_>| {})),
|
||||||
style: Style::default(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&self, state: usize) -> String {
|
fn render(&self, state: usize) -> String {
|
||||||
let writer = self.style.use_style(&state);
|
|
||||||
if state == 2 {
|
if state == 2 {
|
||||||
return writer.write_clicked(&self.text);
|
return write!(self, clicked, self.text);
|
||||||
}
|
}
|
||||||
writer.write(&self.text)
|
write!((self, state), self.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn event(&mut self, _state: usize, k: Key) -> UpdateResponse {
|
fn event(&mut self, event: Event) -> EventResponse {
|
||||||
if k == Key::Enter {
|
match event {
|
||||||
let mut btn = self.clone();
|
Event::Key(k) => {
|
||||||
let mut on_click = self.on_click.lock().unwrap();
|
if k == Key::Enter {
|
||||||
(on_click)(&mut btn);
|
let mut btn = self.clone();
|
||||||
drop(on_click);
|
let mut on_click = self.on_click.lock().unwrap();
|
||||||
*self = btn;
|
(on_click)(&mut btn);
|
||||||
return command!(
|
drop(on_click);
|
||||||
Command::Render(2),
|
*self = btn;
|
||||||
Command::Sleep(120)
|
return command!(
|
||||||
);
|
Command::Render(2),
|
||||||
|
Command::Sleep(120)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
UpdateResponse::None
|
|
||||||
|
EventResponse::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,12 +102,18 @@ element! {
|
|||||||
frame.join("\n")
|
frame.join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn event(&mut self, state: usize, k: Key) -> UpdateResponse {
|
fn event(&mut self, event: Event) -> EventResponse {
|
||||||
if let Some(direction) = self.keybinds.get(&k) {
|
match event.clone() {
|
||||||
self.child = crate::closest_component(&self.children, self.child, direction.clone());
|
Event::Key(k) => {
|
||||||
} else if let Some(child) = self.get_child() {
|
if let Some(direction) = self.keybinds.get(&k) {
|
||||||
return child.event(state, k);
|
self.child = crate::closest_component(&self.children, self.child, direction.clone());
|
||||||
|
} else if let Some(child) = self.get_child() {
|
||||||
|
return child.event(event.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
UpdateResponse::None
|
|
||||||
|
EventResponse::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-4
@@ -27,10 +27,7 @@ pub fn text<'a>() -> Box<Text<'a>> {
|
|||||||
///
|
///
|
||||||
/// A `Box<Button>` containing a new `Button` element instance.
|
/// A `Box<Button>` containing a new `Button` element instance.
|
||||||
pub fn button<'a>() -> Box<Button<'a>> {
|
pub fn button<'a>() -> Box<Button<'a>> {
|
||||||
let mut btn = Button::new();
|
Box::new(Button::new())
|
||||||
btn.style.clicked_bg = styles::Color::White;
|
|
||||||
btn.style.clicked_fg = styles::Color::Black;
|
|
||||||
Box::new(btn)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new `Div` container element.
|
/// Creates a new `Div` container element.
|
||||||
|
|||||||
+12
-177
@@ -1,180 +1,3 @@
|
|||||||
/// Represents a style configuration for TUI elements, including background,
|
|
||||||
/// foreground, outline colors, and font settings for different element states
|
|
||||||
/// (hovered, clicked, selected).
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub struct Style {
|
|
||||||
/// Background color of the element.
|
|
||||||
pub bg: Color,
|
|
||||||
/// Foreground color of the element.
|
|
||||||
pub fg: Color,
|
|
||||||
/// Outline color of the element.
|
|
||||||
pub outline: Color,
|
|
||||||
/// Font style for the element.
|
|
||||||
pub font: Font,
|
|
||||||
|
|
||||||
/// Background color when the element is hovered.
|
|
||||||
pub hover_bg: Color,
|
|
||||||
/// Foreground color when the element is hovered.
|
|
||||||
pub hover_fg: Color,
|
|
||||||
/// Outline color when the element is hovered.
|
|
||||||
pub hover_outline: Color,
|
|
||||||
/// Font style when the element is hovered.
|
|
||||||
pub hover_font: Font,
|
|
||||||
/// Foreground color for the cursor when hovered.
|
|
||||||
pub hover_cursor_fg: Color,
|
|
||||||
/// Background color for the cursor when hovered.
|
|
||||||
pub hover_cursor_bg: Color,
|
|
||||||
|
|
||||||
/// Background color when the element is clicked.
|
|
||||||
pub clicked_bg: Color,
|
|
||||||
/// Foreground color when the element is clicked.
|
|
||||||
pub clicked_fg: Color,
|
|
||||||
/// Outline color when the element is clicked.
|
|
||||||
pub clicked_outline: Color,
|
|
||||||
/// Font style when the element is clicked.
|
|
||||||
pub clicked_font: Font,
|
|
||||||
|
|
||||||
/// Background color when the element is selected.
|
|
||||||
pub selected_bg: Color,
|
|
||||||
/// Foreground color when the element is selected.
|
|
||||||
pub selected_fg: Color,
|
|
||||||
/// Font style when the element is selected.
|
|
||||||
pub selected_font: Font,
|
|
||||||
|
|
||||||
/// Foreground color for the cursor.
|
|
||||||
pub cursor_fg: Color,
|
|
||||||
/// Background color for the cursor.
|
|
||||||
pub cursor_bg: Color,
|
|
||||||
|
|
||||||
/// Indicates if the style is active, affecting its state-based styling.
|
|
||||||
pub is_active: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Style {
|
|
||||||
/// Creates a default `Style` instance with `None` for all color and font fields
|
|
||||||
/// and inactive (`is_active` set to false).
|
|
||||||
fn default() -> Style {
|
|
||||||
Style {
|
|
||||||
bg: Color::None,
|
|
||||||
fg: Color::None,
|
|
||||||
outline: Color::None,
|
|
||||||
font: Font::None,
|
|
||||||
hover_bg: Color::None,
|
|
||||||
hover_fg: Color::None,
|
|
||||||
hover_outline: Color::None,
|
|
||||||
hover_font: Font::None,
|
|
||||||
hover_cursor_fg: Color::None,
|
|
||||||
hover_cursor_bg: Color::None,
|
|
||||||
clicked_bg: Color::None,
|
|
||||||
clicked_fg: Color::None,
|
|
||||||
clicked_outline: Color::None,
|
|
||||||
clicked_font: Font::None,
|
|
||||||
selected_bg: Color::None,
|
|
||||||
selected_fg: Color::None,
|
|
||||||
selected_font: Font::None,
|
|
||||||
cursor_fg: Color::None,
|
|
||||||
cursor_bg: Color::None,
|
|
||||||
is_active: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Style {
|
|
||||||
/// Generates the ANSI code for the current style, using the active color
|
|
||||||
/// and font if `is_active` is true.
|
|
||||||
pub fn get(&self) -> String {
|
|
||||||
if self.is_active {
|
|
||||||
format!(
|
|
||||||
"{}{}{}",
|
|
||||||
self.fg.prioritize(&self.hover_fg).ansi(),
|
|
||||||
self.bg.prioritize(&self.hover_bg).ansi_bg(),
|
|
||||||
self.font.prioritize(&self.hover_font).ansi()
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
format!(
|
|
||||||
"{}{}{}",
|
|
||||||
self.fg.ansi(),
|
|
||||||
self.bg.ansi_bg(),
|
|
||||||
self.font.ansi()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the outline color in ANSI format, applying hover style if active.
|
|
||||||
pub fn get_outline(&self) -> String {
|
|
||||||
if self.is_active {
|
|
||||||
self.outline.prioritize(&self.hover_outline).ansi()
|
|
||||||
} else {
|
|
||||||
self.outline.ansi()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieves the clicked style ANSI sequence for the element.
|
|
||||||
pub fn get_clicked(&self) -> String {
|
|
||||||
format!(
|
|
||||||
"{}{}{}",
|
|
||||||
self.fg.prioritize(&self.clicked_fg).ansi(),
|
|
||||||
self.bg.prioritize(&self.clicked_bg).ansi_bg(),
|
|
||||||
self.font.prioritize(&self.clicked_font).ansi()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieves the selected style ANSI sequence for the element.
|
|
||||||
pub fn get_selected(&self) -> String {
|
|
||||||
format!(
|
|
||||||
"{}{}{}",
|
|
||||||
self.fg.prioritize(&self.selected_fg).ansi(),
|
|
||||||
self.bg.prioritize(&self.selected_bg).ansi_bg(),
|
|
||||||
self.font.prioritize(&self.selected_font).ansi()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieves the cursor style ANSI sequence for the element, considering hover.
|
|
||||||
pub fn get_cursor(&self) -> String {
|
|
||||||
if self.is_active {
|
|
||||||
format!(
|
|
||||||
"{}{}",
|
|
||||||
self.cursor_fg.prioritize(&self.hover_cursor_fg).ansi(),
|
|
||||||
self.cursor_bg.prioritize(&self.hover_cursor_bg).ansi_bg(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
format!("{}{}", self.cursor_fg.ansi(), self.cursor_bg.ansi_bg())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Writes the given string with the active style's ANSI sequences.
|
|
||||||
pub fn write(&self, s: &str) -> String {
|
|
||||||
format!("{}{}\x1b[0m", self.get(), s)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Writes a string with the outline color applied.
|
|
||||||
pub fn write_outline(&self, s: &str) -> String {
|
|
||||||
format!("{}{}\x1b[0m", self.get_outline(), s)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Writes a string with the clicked style applied.
|
|
||||||
pub fn write_clicked(&self, s: &str) -> String {
|
|
||||||
format!("{}{}\x1b[0m", self.get_clicked(), s)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Writes a string with the selected style applied.
|
|
||||||
pub fn write_selected(&self, s: &str) -> String {
|
|
||||||
format!("{}{}\x1b[0m", self.get_selected(), s)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Writes a string with the cursor style applied.
|
|
||||||
pub fn write_cursor(&self, s: &str) -> String {
|
|
||||||
format!("{}{}\x1b[0m", self.get_cursor(), s)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Clones the style and sets `is_active` based on the given state.
|
|
||||||
pub fn use_style(&self, state: &usize) -> Style {
|
|
||||||
let mut style = self.clone();
|
|
||||||
style.is_active = *state == 1;
|
|
||||||
style
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents different font styles that can be applied to TUI elements.
|
/// Represents different font styles that can be applied to TUI elements.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Font {
|
pub enum Font {
|
||||||
@@ -280,3 +103,15 @@ impl Color {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Color {
|
||||||
|
fn default() -> Self {
|
||||||
|
Color::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Font {
|
||||||
|
fn default() -> Self {
|
||||||
|
Font::None
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user