mouse events

This commit is contained in:
2025-01-21 21:06:10 +01:00
parent 09d1ee21bf
commit 52f4dcfb2f
6 changed files with 72 additions and 104 deletions
-1
View File
@@ -10,7 +10,6 @@ documentation = "https://osui.netlify.app/docs/"
[features] [features]
no_rsx = [] no_rsx = []
portable = []
no_elem = [] no_elem = []
[lib] [lib]
+12 -1
View File
@@ -71,10 +71,21 @@ impl Console {
if let Event::Resize(w, h) = event { if let Event::Resize(w, h) = event {
self.0.width = w; self.0.width = w;
self.0.height = h; self.0.height = h;
} } else if let Event::Mouse(crossterm::event::MouseEvent {
kind: crossterm::event::MouseEventKind::Moved,
row,
column,
..
}) = event
{
self.0.mouse_pos = Some((column, row));
self.draw(ui.clone(), None)?;
} else {
self.draw(ui.clone(), Some(event))?; self.draw(ui.clone(), Some(event))?;
} }
} }
}
/// Ends the console session, restoring the terminal state. /// Ends the console session, restoring the terminal state.
/// ///
+1 -1
View File
@@ -40,7 +40,7 @@ impl Widget for Button {
} }
impl Button { impl Button {
pub fn draw<W>(&mut self, w: &W, props: crate::Area) -> crate::Result<()> pub fn draw<W>(&mut self, w: &W, props: crate::Props) -> crate::Result<()>
where where
W: Widget, W: Widget,
{ {
+23 -56
View File
@@ -20,9 +20,11 @@ pub mod utils;
/// Commonly used imports for convenience. /// Commonly used imports for convenience.
pub mod prelude { pub mod prelude {
pub use crate::console::*;
pub use crate::elements::*; pub use crate::elements::*;
pub use crate::*; pub use crate::rsx;
pub use console::Event; pub use crate::utils;
pub use crate::{Element, Frame, Pos, Props, Result, Size, Widget};
pub use crossterm::event::{KeyCode, KeyEvent}; pub use crossterm::event::{KeyCode, KeyEvent};
} }
@@ -46,9 +48,9 @@ pub trait Widget {
} }
} }
/// Struct representing a rectangular area in the terminal. /// Struct representing a rectangular props in the terminal.
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Area { pub struct Props {
pub width: Size, pub width: Size,
pub height: Size, pub height: Size,
pub x: Pos, pub x: Pos,
@@ -60,6 +62,7 @@ pub struct Area {
pub struct Frame { pub struct Frame {
pub width: u16, pub width: u16,
pub height: u16, pub height: u16,
mouse_pos: Option<(u16, u16)>,
last_elem: (u16, u16), last_elem: (u16, u16),
} }
@@ -111,61 +114,14 @@ impl Size {
} }
} }
impl Area { impl Props {
/// Creates a new `Area` with default values. /// Creates a new `Props` with default values.
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
/// Center the `Area` horizontally. Only available with the `portable` feature.
#[cfg(feature = "portable")]
pub fn center_x() -> Self {
let mut s = Self::default();
s.x = Pos::center;
s
} }
/// Center the `Area` vertically. Only available with the `portable` feature. impl Default for Props {
#[cfg(feature = "portable")]
pub fn center_y() -> Self {
let mut s = Self::default();
s.y = Pos::center;
s
}
/// Center the `Area` both horizontally and vertically. Only available with the `portable` feature.
#[cfg(feature = "portable")]
pub fn center() -> Self {
let mut s = Self::default();
s.x = Pos::center;
s.y = Pos::center;
s
}
// Additional utility methods for setting properties are available with the `portable` feature.
#[cfg(feature = "portable")]
pub fn set_width(&mut self, w: Size) -> Self {
self.width = w;
*self
}
#[cfg(feature = "portable")]
pub fn set_height(&mut self, h: Size) -> Self {
self.height = h;
*self
}
#[cfg(feature = "portable")]
pub fn set_x(&mut self, x: Pos) -> Self {
self.x = x;
*self
}
#[cfg(feature = "portable")]
pub fn set_y(&mut self, y: Pos) -> Self {
self.y = y;
*self
}
}
impl Default for Area {
fn default() -> Self { fn default() -> Self {
Self { Self {
width: Size::Auto, width: Size::Auto,
@@ -178,7 +134,7 @@ impl Default for Area {
impl Frame { impl Frame {
/// Draws a widget on the frame. /// Draws a widget on the frame.
pub fn draw<W>(&mut self, w: &W, props: Area) -> Result<()> pub fn draw<W>(&mut self, w: &W, props: Props) -> Result<()>
where where
W: Widget, W: Widget,
{ {
@@ -196,13 +152,23 @@ impl Frame {
props.y.get(self.last_elem.1, height, self.height), props.y.get(self.last_elem.1, height, self.height),
); );
let ansi = if let Some((mouse_x, mouse_y)) = &self.mouse_pos {
if (x..x + width).contains(mouse_x) && (y..y + height).contains(mouse_y) {
"\x1b[32m"
} else {
""
}
} else {
""
};
for (i, line) in written.lines().enumerate() { for (i, line) in written.lines().enumerate() {
if i as u16 > height { if i as u16 > height {
break; break;
} }
println!( println!(
"\x1b[{};{}H{}", "\x1b[{};{}H{ansi}{}\x1b[0m",
y + (i as u16) + 1, y + (i as u16) + 1,
x + 1, x + 1,
line.chars().take(width as usize).collect::<String>() line.chars().take(width as usize).collect::<String>()
@@ -228,6 +194,7 @@ impl Frame {
width, width,
height, height,
last_elem: (0, 0), last_elem: (0, 0),
mouse_pos: None,
} }
} }
} }
+3 -5
View File
@@ -1,7 +1,7 @@
use osui::prelude::*; use osui::prelude::*;
fn main() -> osui::Result<()> { fn main() -> Result<()> {
let mut con = console::init(false)?; let mut con = init(true)?;
con.run(app())?; con.run(app())?;
@@ -10,8 +10,6 @@ fn main() -> osui::Result<()> {
pub fn app() -> Element { pub fn app() -> Element {
rsx! { rsx! {
btn { on_click: Box::new(|| { btn { "Click me" } (x-center y-center)
panic!("Testing");
}), "Click me" }
} }
} }
+30 -37
View File
@@ -35,6 +35,14 @@ macro_rules! rsx {
/// **Don't use this macro manually** use `rsx!` instead /// **Don't use this macro manually** use `rsx!` instead
#[macro_export] #[macro_export]
macro_rules! rsx_inner { macro_rules! rsx_inner {
// Field
($frame:expr, $event:expr;
$n:ident: $v:expr
$(, $($rest:tt)*)?) => {
$frame.$n = $v;
$crate::rsx_inner!($frame, $event; $($($rest)*)?);
};
// For loop // For loop
($frame:expr, $event:expr; ($frame:expr, $event:expr;
for ($i:pat in $e:expr) $(%$s:ident),* {$($inner:tt)*} for ($i:pat in $e:expr) $(%$s:ident),* {$($inner:tt)*}
@@ -77,59 +85,44 @@ macro_rules! rsx_inner {
($frame:expr, $event:expr; ($frame:expr, $event:expr;
$elem:literal ($($inner:tt)*) $elem:literal ($($inner:tt)*)
$($rest:tt)*) => { $($rest:tt)*) => {
let mut area = $crate::Area::new(); let mut props = $crate::Props::new();
$crate::tw_area!(area, $($inner)*); $crate::tw_props!(props, $($inner)*);
$frame.draw(&format!($elem), area)?; $frame.draw(&format!($elem), props)?;
$crate::rsx_inner!($frame, $event; $($rest)*); $crate::rsx_inner!($frame, $event; $($rest)*);
}; };
($frame:expr, $event:expr; ($frame:expr, $event:expr;
$elem:literal $elem:literal
$($rest:tt)*) => { $($rest:tt)*) => {
$frame.draw(&format!($elem), Area::new())?; $frame.draw(&format!($elem), Props::new())?;
$crate::rsx_inner!($frame, $event; $($rest)*); $crate::rsx_inner!($frame, $event; $($rest)*);
}; };
// Name { rsx } ( area ) // Name { rsx } ( props )
($frame:expr, $event:expr; ($frame:expr, $event:expr;
$elem:path { $elem:path {
$($n:ident: $v:expr),+
$(,
$($inner:tt)* $($inner:tt)*
)? } ($($props_inner:tt)*)
} ($($area_inner:tt)*)
$($rest:tt)*) => { $($rest:tt)*) => {
let mut area = $crate::Area::new(); let mut props = $crate::Props::new();
$crate::tw_area!(area, $($area_inner)*); $crate::tw_props!(props, $($props_inner)*);
let mut e = $elem();
$(
e.$n = $v;
)*
$(
$crate::rsx_inner!(e, $event; $($inner)*);
)?
$frame.draw(&e, area)?; let mut e = $elem();
$crate::rsx_inner!(e, $event; $($inner)*);
$frame.draw(&e, props)?;
$crate::rsx_inner!($frame, $event; $($rest)*); $crate::rsx_inner!($frame, $event; $($rest)*);
}; };
// Name { rsx } // Name { rsx }
($frame:expr, $event:expr; ($frame:expr, $event:expr;
$elem:path { $elem:path {
$($n:ident: $v:expr),+
$(,
$($inner:tt)* $($inner:tt)*
)?
} }
$($rest:tt)*) => { $($rest:tt)*) => {
let mut e = $elem(); let mut e = $elem();
$(
e.$n = $v;
)*
$(
$crate::rsx_inner!(e, $event; $($inner)*); $crate::rsx_inner!(e, $event; $($inner)*);
)?
$frame.draw(&e, $crate::Area::new())?; $frame.draw(&e, $crate::Props::new())?;
$crate::rsx_inner!($frame, $event; $($rest)*); $crate::rsx_inner!($frame, $event; $($rest)*);
}; };
@@ -140,7 +133,7 @@ macro_rules! rsx_inner {
/// ///
/// **Don't use this macro manually** use `rsx!` instead /// **Don't use this macro manually** use `rsx!` instead
#[macro_export] #[macro_export]
macro_rules! tw_area { macro_rules! tw_props {
($a:expr, $n:ident) => { ($a:expr, $n:ident) => {
$a.$n; $a.$n;
}; };
@@ -148,45 +141,45 @@ macro_rules! tw_area {
// X // X
($a:expr, x-$v:ident $($rest:tt)*) => { ($a:expr, x-$v:ident $($rest:tt)*) => {
$a.x = $crate::Pos::$v; $a.x = $crate::Pos::$v;
$crate::tw_area!($a, $($rest)*); $crate::tw_props!($a, $($rest)*);
}; };
($a:expr, x-$v:literal $($rest:tt)*) => { ($a:expr, x-$v:literal $($rest:tt)*) => {
$a.x = $crate::Pos::Num($v); $a.x = $crate::Pos::Num($v);
$crate::tw_area!($a, $($rest)*); $crate::tw_props!($a, $($rest)*);
}; };
// Y // Y
($a:expr, y-$v:ident $($rest:tt)*) => { ($a:expr, y-$v:ident $($rest:tt)*) => {
$a.y = $crate::Pos::$v; $a.y = $crate::Pos::$v;
$crate::tw_area!($a, $($rest)*); $crate::tw_props!($a, $($rest)*);
}; };
($a:expr, y-$v:literal $($rest:tt)*) => { ($a:expr, y-$v:literal $($rest:tt)*) => {
$a.y = $crate::Pos::Num($v); $a.y = $crate::Pos::Num($v);
$crate::tw_area!($a, $($rest)*); $crate::tw_props!($a, $($rest)*);
}; };
// Width // Width
($a:expr, width-$v:ident $($rest:tt)*) => { ($a:expr, width-$v:ident $($rest:tt)*) => {
$a.width = $crate::Size::$v; $a.width = $crate::Size::$v;
$crate::tw_area!($a, $($rest)*); $crate::tw_props!($a, $($rest)*);
}; };
($a:expr, width-$v:literal $($rest:tt)*) => { ($a:expr, width-$v:literal $($rest:tt)*) => {
$a.width = $crate::Size::Num($v); $a.width = $crate::Size::Num($v);
$crate::tw_area!($a, $($rest)*); $crate::tw_props!($a, $($rest)*);
}; };
// Height // Height
($a:expr, height-$v:ident $($rest:tt)*) => { ($a:expr, height-$v:ident $($rest:tt)*) => {
$a.height = $crate::Size::$v; $a.height = $crate::Size::$v;
$crate::tw_area!($a, $($rest)*); $crate::tw_props!($a, $($rest)*);
}; };
($a:expr, height-$v:literal $($rest:tt)*) => { ($a:expr, height-$v:literal $($rest:tt)*) => {
$a.height = $crate::Size::Num($v); $a.height = $crate::Size::Num($v);
$crate::tw_area!($a, $($rest)*); $crate::tw_props!($a, $($rest)*);
}; };
($a:expr,) => {}; ($a:expr,) => {};