mouse events
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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,) => {};
|
||||||
|
|||||||
Reference in New Issue
Block a user