added positioning in rsx
This commit is contained in:
@@ -10,6 +10,8 @@ documentation = "https://osui.netlify.app/docs/"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
rsx = []
|
rsx = []
|
||||||
|
frontend = ["rsx"]
|
||||||
|
portable = []
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "osui"
|
name = "osui"
|
||||||
|
|||||||
+7
-7
@@ -26,20 +26,20 @@ pub fn end() -> crate::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Console {
|
impl Console {
|
||||||
pub fn draw(&self, f: Element) -> crate::Result<()> {
|
pub fn draw(&mut self, ui: Element, event: Option<Event>) -> crate::Result<()> {
|
||||||
crate::utils::clear()?;
|
self.0.clear()?;
|
||||||
f(&self.0)
|
ui(&mut self.0, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self, ui: Element) -> crate::Result<()> {
|
pub fn run(&mut self, ui: Element) -> crate::Result<()> {
|
||||||
|
self.draw(ui.clone(), None)?;
|
||||||
loop {
|
loop {
|
||||||
self.draw(ui.clone())?;
|
|
||||||
let event = read()?;
|
let event = read()?;
|
||||||
if let Event::Resize(w, h) = event {
|
if let Event::Resize(w, h) = event {
|
||||||
self.0.area.width = w;
|
self.0.width = w;
|
||||||
self.0.area.height = h;
|
self.0.height = h;
|
||||||
}
|
}
|
||||||
|
self.draw(ui.clone(), Some(event))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+102
-57
@@ -12,7 +12,7 @@ pub mod prelude {
|
|||||||
|
|
||||||
pub use std::io::Result;
|
pub use std::io::Result;
|
||||||
|
|
||||||
pub type Element = std::sync::Arc<dyn Fn(&Frame) -> crate::Result<()>>;
|
pub type Element = std::sync::Arc<dyn Fn(&mut Frame, Option<console::Event>) -> crate::Result<()>>;
|
||||||
|
|
||||||
pub trait Widget {
|
pub trait Widget {
|
||||||
fn render(&self) -> String;
|
fn render(&self) -> String;
|
||||||
@@ -21,25 +21,59 @@ pub trait Widget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum Pos {
|
||||||
|
Auto,
|
||||||
|
Center,
|
||||||
|
Num(u16),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pos {
|
||||||
|
pub fn get(self, auto: u16, width: u16, frame: u16) -> u16 {
|
||||||
|
match self {
|
||||||
|
Self::Auto => auto,
|
||||||
|
Self::Center => (frame - width) / 2,
|
||||||
|
Self::Num(n) => n,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum Size {
|
||||||
|
Auto,
|
||||||
|
Num(u16),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Size {
|
||||||
|
fn get_(self, written: u16) -> u16 {
|
||||||
|
match self {
|
||||||
|
Self::Auto => written,
|
||||||
|
Self::Num(n) => n,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(self, written: u16, _frame: u16) -> u16 {
|
||||||
|
self.get_(written)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Area {
|
pub struct Area {
|
||||||
width: u16,
|
pub width: Size,
|
||||||
height: u16,
|
pub height: Size,
|
||||||
x: u16,
|
pub x: Pos,
|
||||||
y: u16,
|
pub y: Pos,
|
||||||
center_x: bool,
|
|
||||||
center_y: bool,
|
|
||||||
width_auto: bool,
|
|
||||||
height_auto: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy)]
|
#[derive(Debug, Default, Clone, Copy)]
|
||||||
pub struct Frame {
|
pub struct Frame {
|
||||||
pub area: Area,
|
pub width: u16,
|
||||||
|
pub height: u16,
|
||||||
|
last_elem: (u16, u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Frame {
|
impl Frame {
|
||||||
pub fn draw<W>(&self, w: &W, mut props: Area) -> Result<()>
|
pub fn draw<W>(&mut self, w: &W, props: Area) -> Result<()>
|
||||||
where
|
where
|
||||||
W: Widget,
|
W: Widget,
|
||||||
{
|
{
|
||||||
@@ -47,49 +81,47 @@ impl Frame {
|
|||||||
|
|
||||||
let (ww, wh) = utils::str_size(&written);
|
let (ww, wh) = utils::str_size(&written);
|
||||||
|
|
||||||
if props.width_auto {
|
let (width, height) = (
|
||||||
props.width = ww;
|
props.width.get(ww, self.width),
|
||||||
}
|
props.height.get(wh, self.height),
|
||||||
if props.height_auto {
|
);
|
||||||
props.height = wh;
|
|
||||||
}
|
|
||||||
|
|
||||||
if props.width > self.area.width {
|
let (x, y) = (
|
||||||
props.width -= props.width - self.area.width;
|
props.x.get(self.last_elem.0, width, self.width),
|
||||||
}
|
props.y.get(self.last_elem.1, height, self.height),
|
||||||
|
);
|
||||||
if props.width > self.area.width {
|
|
||||||
props.width -= props.width - self.area.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
if props.center_x {
|
|
||||||
props.x = (self.area.width - ww) / 2;
|
|
||||||
}
|
|
||||||
if props.center_y {
|
|
||||||
props.y = (self.area.height - wh) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i, line) in written.lines().enumerate() {
|
for (i, line) in written.lines().enumerate() {
|
||||||
if i as u16 > props.height {
|
if i as u16 > height {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"\x1b[{};{}H{}",
|
"\x1b[{};{}H{}",
|
||||||
props.y + (i as u16) + 1,
|
y + (i as u16) + 1,
|
||||||
props.x + 1,
|
x + 1,
|
||||||
line.chars().take(props.width as usize).collect::<String>()
|
line.chars().take(width as usize).collect::<String>()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.last_elem.0 = x + width;
|
||||||
|
self.last_elem.1 = y + height;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self) -> Result<()> {
|
||||||
|
self.last_elem.0 = 0;
|
||||||
|
self.last_elem.1 = 0;
|
||||||
|
utils::clear()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new((width, height): (u16, u16)) -> Self {
|
pub fn new((width, height): (u16, u16)) -> Self {
|
||||||
let mut f = Self::default();
|
Self {
|
||||||
f.area.width(width);
|
width,
|
||||||
f.area.height(height);
|
height,
|
||||||
f
|
last_elem: (0, 0),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,59 +130,72 @@ impl Area {
|
|||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "portable")]
|
||||||
pub fn center_x() -> Self {
|
pub fn center_x() -> Self {
|
||||||
let mut s = Self::default();
|
let mut s = Self::default();
|
||||||
s.center_x = true;
|
s.x = Pos::Center;
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "portable")]
|
||||||
pub fn center_y() -> Self {
|
pub fn center_y() -> Self {
|
||||||
let mut s = Self::default();
|
let mut s = Self::default();
|
||||||
s.center_y = true;
|
s.y = Pos::Center;
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "portable")]
|
||||||
pub fn center() -> Self {
|
pub fn center() -> Self {
|
||||||
let mut s = Self::default();
|
let mut s = Self::default();
|
||||||
s.center_x = true;
|
s.x = Pos::Center;
|
||||||
s.center_y = true;
|
s.y = Pos::Center;
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn width(&mut self, w: u16) -> Self {
|
#[cfg(feature = "portable")]
|
||||||
|
pub fn set_width(&mut self, w: Size) -> Self {
|
||||||
self.width = w;
|
self.width = w;
|
||||||
self.width_auto = false;
|
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn height(&mut self, h: u16) -> Self {
|
#[cfg(feature = "portable")]
|
||||||
|
pub fn set_height(&mut self, h: Size) -> Self {
|
||||||
self.height = h;
|
self.height = h;
|
||||||
self.height_auto = false;
|
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn x(&mut self, x: u16) -> Self {
|
#[cfg(feature = "portable")]
|
||||||
|
pub fn set_x(&mut self, x: Pos) -> Self {
|
||||||
self.x = x;
|
self.x = x;
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn y(&mut self, y: u16) -> Self {
|
#[cfg(feature = "portable")]
|
||||||
|
pub fn set_y(&mut self, y: Pos) -> Self {
|
||||||
self.y = y;
|
self.y = y;
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "portable")]
|
||||||
|
pub fn x_auto(&mut self) -> Self {
|
||||||
|
self.x = Pos::Auto;
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "portable")]
|
||||||
|
pub fn y_zero(&mut self) -> Self {
|
||||||
|
self.y = Pos::Num(0);
|
||||||
|
*self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Area {
|
impl Default for Area {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
width: 0,
|
width: Size::Auto,
|
||||||
height: 0,
|
height: Size::Auto,
|
||||||
x: 0,
|
x: Pos::Num(0),
|
||||||
y: 0,
|
y: Pos::Auto,
|
||||||
center_x: false,
|
|
||||||
center_y: false,
|
|
||||||
width_auto: true,
|
|
||||||
height_auto: true,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-11
@@ -3,20 +3,16 @@ use osui::prelude::*;
|
|||||||
fn main() -> osui::Result<()> {
|
fn main() -> osui::Result<()> {
|
||||||
let mut con = console::init()?;
|
let mut con = console::init()?;
|
||||||
|
|
||||||
let (ui, _count) = app();
|
con.run(app())?;
|
||||||
con.run(ui).unwrap();
|
|
||||||
|
|
||||||
console::end()
|
console::end()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn app() -> (Element, state::State<i32>) {
|
pub fn app() -> Element {
|
||||||
let count = use_state(0);
|
|
||||||
let count1 = count.copy_state();
|
|
||||||
|
|
||||||
(
|
|
||||||
rsx! {
|
rsx! {
|
||||||
"{count}"
|
"X" (x-Center)
|
||||||
},
|
"Y" (y-Center)
|
||||||
count1,
|
|
||||||
)
|
"Hello, World" (x-Center, y-Center)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+77
-5
@@ -1,13 +1,85 @@
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! rsx {
|
macro_rules! rsx {
|
||||||
($($e:literal)*) => {
|
($($inner:tt)*) => {
|
||||||
std::sync::Arc::new(
|
std::sync::Arc::new(
|
||||||
move |frame: &$crate::Frame| -> $crate::Result<()> {
|
move |frame: &mut $crate::Frame, event: Option<$crate::console::Event>| -> $crate::Result<()> {
|
||||||
$(
|
$crate::rsx_inner!(frame, event; $($inner)*);
|
||||||
frame.draw(&format!($e), Area::center())?;
|
|
||||||
)*
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! rsx_inner {
|
||||||
|
($frame:expr, $event:expr;
|
||||||
|
$elem:literal ($($inner:tt)*)
|
||||||
|
$($rest:tt)*) => {
|
||||||
|
let mut area = $crate::Area::new();
|
||||||
|
$crate::tw_area!(area, $($inner)*);
|
||||||
|
$frame.draw(&format!($elem), area)?;
|
||||||
|
$crate::rsx_inner!($frame, $event; $($rest)*);
|
||||||
|
};
|
||||||
|
|
||||||
|
($frame:expr, $event:expr;
|
||||||
|
$elem:literal
|
||||||
|
$($rest:tt)*) => {
|
||||||
|
$frame.draw(&format!($elem), Area::new())?;
|
||||||
|
$crate::rsx_inner!($frame, $event; $($rest)*);
|
||||||
|
};
|
||||||
|
|
||||||
|
($frame:expr, $event:expr;) => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! tw_area {
|
||||||
|
($a:expr, $n:ident) => {
|
||||||
|
$a.$n;
|
||||||
|
};
|
||||||
|
|
||||||
|
// X
|
||||||
|
($a:expr, x-$v:ident $(, $($rest:tt)*)?) => {
|
||||||
|
$a.x = $crate::Pos::$v;
|
||||||
|
$crate::tw_area!($a, $($($rest)*)?);
|
||||||
|
};
|
||||||
|
|
||||||
|
($a:expr, x-$v:literal $(, $($rest:tt)*)?) => {
|
||||||
|
$a.x = $crate::Pos::Num($v);
|
||||||
|
$crate::tw_area!($a, $($($rest)*)?);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Y
|
||||||
|
($a:expr, y-$v:ident $(, $($rest:tt)*)?) => {
|
||||||
|
$a.y = $crate::Pos::$v;
|
||||||
|
$crate::tw_area!($a, $($($rest)*)?);
|
||||||
|
};
|
||||||
|
|
||||||
|
($a:expr, y-$v:literal $(, $($rest:tt)*)?) => {
|
||||||
|
$a.y = $crate::Pos::Num($v);
|
||||||
|
$crate::tw_area!($a, $($($rest)*)?);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Width
|
||||||
|
($a:expr, width-$v:ident $(, $($rest:tt)*)?) => {
|
||||||
|
$a.width = $crate::Size::$v;
|
||||||
|
$crate::tw_area!($a, $($($rest)*)?);
|
||||||
|
};
|
||||||
|
|
||||||
|
($a:expr, width-$v:literal $(, $($rest:tt)*)?) => {
|
||||||
|
$a.width = $crate::Size::Num($v);
|
||||||
|
$crate::tw_area!($a, $($($rest)*)?);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Height
|
||||||
|
($a:expr, height-$v:ident $(, $($rest:tt)*)?) => {
|
||||||
|
$a.height = $crate::Size::$v;
|
||||||
|
$crate::tw_area!($a, $($($rest)*)?);
|
||||||
|
};
|
||||||
|
|
||||||
|
($a:expr, height-$v:literal $(, $($rest:tt)*)?) => {
|
||||||
|
$a.height = $crate::Size::Num($v);
|
||||||
|
$crate::tw_area!($a, $($($rest)*)?);
|
||||||
|
};
|
||||||
|
|
||||||
|
($a:expr,) => {};
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#[derive(Clone, Copy)]
|
||||||
pub struct State<T>(pub(crate) *mut T);
|
pub struct State<T>(pub(crate) *mut T);
|
||||||
|
|
||||||
impl<T: std::fmt::Display> std::fmt::Display for State<T> {
|
impl<T: std::fmt::Display> std::fmt::Display for State<T> {
|
||||||
|
|||||||
Reference in New Issue
Block a user