small improvements

This commit is contained in:
2025-01-31 00:58:47 +01:00
parent 65c8bb03d8
commit a35f420b68
4 changed files with 34 additions and 101 deletions
+2 -36
View File
@@ -1,41 +1,7 @@
use crossterm::event::{Event, MouseButton, MouseEvent, MouseEventKind};
use crate::Element; use crate::Element;
impl Element for &str { impl Element for &str {
fn render(&self) -> String { fn render(&self, frame: &mut dyn crate::Framing) {
self.to_string() frame.draw_str("test");
}
}
impl Element for String {
fn render(&self) -> String {
self.to_owned()
}
}
pub struct Button {
pub on_click: crate::Handler<dyn FnMut()>,
pub text: String,
}
impl Element for Button {
fn render(&self) -> String {
self.text.to_owned()
}
fn event(&self, event: crossterm::event::Event) {
match event {
Event::Mouse(MouseEvent {
kind: MouseEventKind::Down(MouseButton::Left),
..
}) => (self.on_click.clone().lock().unwrap())(),
_ => {}
}
}
}
impl Element for crate::Ui {
fn render(&self) -> String {
String::new()
} }
} }
+27 -36
View File
@@ -9,7 +9,6 @@ use std::{io::Write, sync::Arc};
pub mod prelude { pub mod prelude {
pub use crate::{ pub use crate::{
elements::*,
func, func,
style::{Color, Style}, style::{Color, Style},
utils::init, utils::init,
@@ -18,15 +17,20 @@ pub mod prelude {
#[cfg(feature = "state")] #[cfg(feature = "state")]
pub use crate::state::use_state; pub use crate::state::use_state;
pub use crossterm::event::read;
} }
// Traits // Traits
pub trait Framing { pub trait Framing {
fn draw(&mut self, element: &mut dyn Element, props: &Props); fn draw(&mut self, element: &mut dyn Element, props: &Props);
fn draw_str(&mut self, s: &str) {
_ = s
}
} }
pub trait Element { pub trait Element {
fn render(&self) -> String; fn render(&self, frame: &mut dyn Framing);
fn event(&self, event: crossterm::event::Event) { fn event(&self, event: crossterm::event::Event) {
_ = event _ = event
} }
@@ -43,7 +47,6 @@ pub struct Props {
width: style::Dimension, width: style::Dimension,
height: style::Dimension, height: style::Dimension,
style: style::Style, style: style::Style,
style_state: std::collections::HashMap<String, style::Style>,
} }
/// Represents the console state, containing a frame for rendering and a mouse capture flag. /// Represents the console state, containing a frame for rendering and a mouse capture flag.
@@ -53,7 +56,6 @@ pub struct Console<'a> {
height: u16, height: u16,
handle: Option<std::io::StdoutLock<'a>>, handle: Option<std::io::StdoutLock<'a>>,
pub mouse_position: Option<(u16, u16)>, pub mouse_position: Option<(u16, u16)>,
pub event: Option<crossterm::event::Event>,
} }
impl Props { impl Props {
@@ -64,7 +66,6 @@ impl Props {
width: style::Dimension::Auto, width: style::Dimension::Auto,
height: style::Dimension::Auto, height: style::Dimension::Auto,
style: style::Style::default(), style: style::Style::default(),
style_state: std::collections::HashMap::new(),
} }
} }
@@ -79,7 +80,6 @@ impl Props {
width: style::Dimension::Auto, width: style::Dimension::Auto,
height: style::Dimension::Auto, height: style::Dimension::Auto,
style: style::Style::default(), style: style::Style::default(),
style_state: std::collections::HashMap::new(),
} }
} }
@@ -90,7 +90,6 @@ impl Props {
width: style::Dimension::Auto, width: style::Dimension::Auto,
height: style::Dimension::Auto, height: style::Dimension::Auto,
style: style::Style::default(), style: style::Style::default(),
style_state: std::collections::HashMap::new(),
} }
} }
@@ -101,7 +100,6 @@ impl Props {
width: style::Dimension::Auto, width: style::Dimension::Auto,
height: style::Dimension::Auto, height: style::Dimension::Auto,
style: style::Style::default(), style: style::Style::default(),
style_state: std::collections::HashMap::new(),
} }
} }
@@ -120,11 +118,6 @@ impl Props {
self.clone() self.clone()
} }
pub fn state(&mut self, state: &str, style: style::Style) -> Self {
self.style_state.insert(state.to_string(), style);
self.clone()
}
pub fn width(&mut self, w: u16) -> Self { pub fn width(&mut self, w: u16) -> Self {
self.width = style::Dimension::Num(w); self.width = style::Dimension::Num(w);
self.clone() self.clone()
@@ -148,7 +141,8 @@ impl Props {
impl Framing for Console<'_> { impl Framing for Console<'_> {
fn draw(&mut self, element: &mut dyn Element, props: &Props) { fn draw(&mut self, element: &mut dyn Element, props: &Props) {
let mut written = element.render(); let mut written = String::new();
element.render(&mut written);
let (written_width, written_height) = utils::str_size(&written); let (written_width, written_height) = utils::str_size(&written);
@@ -162,36 +156,23 @@ impl Framing for Console<'_> {
props.y.get(height, self.height), props.y.get(height, self.height),
); );
let mut style = props.style; let ansi = if props.style.background == style::Color::NoColor {
format!("\x1b[{}m", props.style.color.ansi_number(true))
if let Some((mouse_x, mouse_y)) = self.mouse_position {
if (x..x + width).contains(&mouse_x) && (y..y + height).contains(&mouse_y) {
if let Some(hover_style) = props.style_state.get("hover") {
style = hover_style.clone();
}
}
}
let ansi = if style.background == style::Color::NoColor {
format!("\x1b[{}m", style.color.ansi_number(true))
} else { } else {
format!( format!(
"\x1b[{};{}m", "\x1b[{};{}m",
style.color.ansi_number(true), props.style.color.ansi_number(true),
style.background.ansi_number(false) props.style.background.ansi_number(false)
) )
}; };
if let Some(event) = &self.event { let (x, y) = (x - props.style.px, y - props.style.py);
element.event(event.clone()); let px = " ".repeat(props.style.px as usize);
} written
.push_str(&format!("\n{}", " ".repeat(width as usize)).repeat(props.style.py as usize));
let (x, y) = (x - style.px, y - style.py);
let px = " ".repeat(style.px as usize);
written.push_str(&format!("\n{}", " ".repeat(width as usize)).repeat(style.py as usize));
written.insert_str( written.insert_str(
0, 0,
&format!("{}\n", " ".repeat(width as usize)).repeat(style.py as usize), &format!("{}\n", " ".repeat(width as usize)).repeat(props.style.py as usize),
); );
if let Some(handle) = &mut self.handle { if let Some(handle) = &mut self.handle {
@@ -234,6 +215,16 @@ impl Console<'_> {
} }
} }
impl crate::Framing for String {
fn draw(&mut self, element: &mut dyn crate::Element, _props: &crate::Props) {
element.render(self);
}
fn draw_str(&mut self, s: &str) {
*self += s;
}
}
pub fn func<T>(t: T) -> Handler<T> { pub fn func<T>(t: T) -> Handler<T> {
std::sync::Arc::new(std::sync::Mutex::new(t)) std::sync::Arc::new(std::sync::Mutex::new(t))
} }
+4 -27
View File
@@ -3,42 +3,19 @@ use std::sync::Arc;
use osmium_engine::prelude::*; use osmium_engine::prelude::*;
fn main() -> Result<()> { fn main() -> Result<()> {
let mut console = init(true)?; let mut console = init(false)?;
let ui = app(); let ui = app();
loop {
console.render(ui.clone())?; console.render(ui.clone())?;
match crossterm::event::read()? {
crossterm::event::Event::Mouse(crossterm::event::MouseEvent { read()?;
kind: crossterm::event::MouseEventKind::Moved,
row,
column,
..
}) => console.mouse_position = Some((column, row)),
crossterm::event::Event::Resize(_, _) => {}
e => console.event = Some(e),
}
}
console.close() console.close()
} }
pub fn app() -> Ui { pub fn app() -> Ui {
let mut count = use_state(0);
Arc::new(move |frame| { Arc::new(move |frame| {
frame.draw( frame.draw(&mut "test", &Props::center());
&mut Button {
on_click: func(move || count += 1),
text: format!("Count: {count}"),
},
&Props::center().state(
"hover",
Style {
color: Color::Red,
..Default::default()
},
),
);
}) })
} }
-1
View File
@@ -114,6 +114,5 @@ pub fn init<'a>(mouse: bool) -> crate::Result<crate::Console<'a>> {
mouse, mouse,
handle: None, handle: None,
mouse_position: None, mouse_position: None,
event: None,
}) })
} }