some refractoring and dataholder
This commit is contained in:
+1
-1
@@ -22,6 +22,6 @@ crossterm = "0.28.1"
|
||||
regex = "1.11.1"
|
||||
lazy_static = "1.4"
|
||||
paste = "1.0.15"
|
||||
osui-element = "0.1.8"
|
||||
dyn-clone = "1.0.17"
|
||||
flume = "=0.10.12"
|
||||
osui-element = "0.1.11"
|
||||
|
||||
+8
-17
@@ -1,7 +1,4 @@
|
||||
use crossterm::{
|
||||
event::Event,
|
||||
terminal::{disable_raw_mode, enable_raw_mode},
|
||||
};
|
||||
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::utils::{clear, flush, get_term_size, hide_cursor, show_cursor, Frame};
|
||||
@@ -24,13 +21,6 @@ extern "C" {
|
||||
fn c_run(args: *mut c_void) -> bool;
|
||||
}
|
||||
|
||||
fn event(element: &mut Element, event: Event, document: &Document) {
|
||||
if let crossterm::event::Event::Resize(width, height) = event {
|
||||
element.update_data(width as usize, height as usize);
|
||||
}
|
||||
element.event(event, document);
|
||||
}
|
||||
|
||||
pub fn run(element: &mut Element) -> bool {
|
||||
hide_cursor();
|
||||
enable_raw_mode().unwrap();
|
||||
@@ -67,16 +57,17 @@ extern "C" fn event_loop(ptr: *mut c_void) -> *const c_void {
|
||||
};
|
||||
|
||||
let (width, height) = get_term_size();
|
||||
args.element.update_data(width, height);
|
||||
event(
|
||||
args.element,
|
||||
crossterm::event::Event::FocusGained,
|
||||
args.element.event(
|
||||
crossterm::event::Event::Resize(width as u16, height as u16),
|
||||
&document,
|
||||
);
|
||||
args.element
|
||||
.event(crossterm::event::Event::FocusGained, &document);
|
||||
document.render();
|
||||
|
||||
while args.running || !ptr.is_null() {
|
||||
event(args.element, crossterm::event::read().unwrap(), &document);
|
||||
args.element
|
||||
.event(crossterm::event::read().unwrap(), &document);
|
||||
document.render();
|
||||
}
|
||||
null() as *const c_void
|
||||
@@ -100,7 +91,7 @@ extern "C" fn cmd_loop(ptr: *mut c_void) -> *const c_void {
|
||||
args.rtx
|
||||
.send(if let Some(e) = args.element.get_element_by_id(&id) {
|
||||
crate::CommandResult::Element(e as *mut Element)
|
||||
} else if args.element.get_data().2 == id {
|
||||
} else if args.element.get_id() == id {
|
||||
crate::CommandResult::Element(args.element as *mut Element)
|
||||
} else {
|
||||
crate::CommandResult::None
|
||||
|
||||
+10
-2
@@ -3,8 +3,16 @@ use crate::prelude::*;
|
||||
pub fn examples() -> Element {
|
||||
rsx! {
|
||||
styling: Some(styling()),
|
||||
if (2 == 2) {
|
||||
rsx_elem! { button { class: "btn", "Hello, World!" } }
|
||||
button { class: "btn", on_click: Handler::new(|btn: &mut Button, _, document| {
|
||||
let data = document.get_element_by_id::<DataHolder<'_, String>>("my_data").unwrap();
|
||||
data.data += "!";
|
||||
btn.children.set_text(&data.data);
|
||||
}), "Hello, World!" }
|
||||
|
||||
{
|
||||
let mut data = dataholder::<String>();
|
||||
data.id = "my_data";
|
||||
data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-9
@@ -42,8 +42,8 @@ pub mod prelude {
|
||||
pub use crate::ui::Color::*;
|
||||
pub use crate::ui::Number::*;
|
||||
pub use crate::{self as osui, css, rsx, rsx_elem, ui::*, Handler};
|
||||
pub use crate::{call, Children, ElementCore, ElementWidget};
|
||||
pub use crate::{style, Command, Document, Element, Value};
|
||||
pub use crate::{call, Children, ElementCore, ElementWidget, Element};
|
||||
pub use crate::{style, Command, Document, RenderResult, RenderWriter, Value};
|
||||
pub use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind};
|
||||
pub fn sleep(ms: u64) {
|
||||
std::thread::sleep(std::time::Duration::from_millis(ms));
|
||||
@@ -60,17 +60,14 @@ pub type Element = Box<dyn ElementWidget>;
|
||||
/// Traits
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pub trait ElementCore: Send + Sync {
|
||||
fn get_data(&self) -> (Value<usize>, usize, String);
|
||||
fn update_data(&mut self, width: usize, height: usize);
|
||||
pub trait ElementCore {
|
||||
fn get_element_by_id(&mut self, id: &str) -> Option<&mut Element>;
|
||||
fn get_child(&mut self) -> Option<&mut Element>;
|
||||
fn set_styling(&mut self, styling: &HashMap<crate::ui::StyleName, crate::ui::Style>);
|
||||
fn get_id(&self) -> String;
|
||||
}
|
||||
|
||||
pub trait ElementWidget: ElementCore + std::fmt::Debug {
|
||||
fn render(&self, focused: bool) -> RenderResult;
|
||||
|
||||
pub trait ElementWidget: ElementCore + std::fmt::Debug + Send + Sync {
|
||||
fn render(&self, focused: bool) -> Option<RenderResult>;
|
||||
fn event(&mut self, event: Event, document: &Document) {
|
||||
_ = (event, document)
|
||||
}
|
||||
@@ -245,6 +242,13 @@ impl Children {
|
||||
children.push(element);
|
||||
}
|
||||
}
|
||||
pub fn get_child(&mut self) -> Option<&mut Element> {
|
||||
if let Children::Children(children, child) = self {
|
||||
children.get_mut(*child)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Handler<T> {
|
||||
|
||||
+2
-9
@@ -9,13 +9,6 @@ macro_rules! parse_rsx_param {
|
||||
}
|
||||
osui::parse_rsx_param!($elem, $($rest)*);
|
||||
};
|
||||
($elem:expr, if ($($if:tt)*) $code:block $($rest:tt)*) => {
|
||||
if $elem.children.is_none() {$elem.children = $crate::Children::Children(Vec::new(), 0)}
|
||||
if let $crate::Children::Children(children, _) = &mut $elem.children {
|
||||
if $($if)* {children.push($code)}
|
||||
}
|
||||
osui::parse_rsx_param!($elem, $($rest)*);
|
||||
};
|
||||
|
||||
($elem:expr, $($k:ident).+: $v:expr) => {
|
||||
$elem.$($k).+ = $v;
|
||||
@@ -46,10 +39,10 @@ macro_rules! parse_rsx_param {
|
||||
osui::parse_rsx_param!($elem, $($rest)*);
|
||||
};
|
||||
|
||||
($elem:expr, {$inner_elem:expr} $($rest:tt)*) => {
|
||||
($elem:expr, $code:block $($rest:tt)*) => {
|
||||
if $elem.children.is_none() {$elem.children = $crate::Children::Children(Vec::new(), 0)}
|
||||
if let $crate::Children::Children(children, _) = &mut $elem.children {
|
||||
children.push({$inner_elem});
|
||||
children.push($code);
|
||||
}
|
||||
osui::parse_rsx_param!($elem, $($rest)*);
|
||||
};
|
||||
|
||||
+31
-48
@@ -3,9 +3,10 @@
|
||||
/// # Modules
|
||||
/// - `styles`: A module for defining UI styles.
|
||||
pub mod styles;
|
||||
|
||||
pub use styles::*;
|
||||
|
||||
use crate::{prelude::*, RenderResult, RenderWriter};
|
||||
use crate::prelude::*;
|
||||
use osui_element::{elem_fn, element};
|
||||
|
||||
/// The `Text` element represents a piece of static text in the terminal UI.
|
||||
@@ -31,7 +32,7 @@ pub struct Text {
|
||||
}
|
||||
|
||||
impl ElementWidget for Text<'_> {
|
||||
fn render(&self, focused: bool) -> RenderResult {
|
||||
fn render(&self, focused: bool) -> Option<RenderResult> {
|
||||
let mut writer = RenderWriter::new(focused, self.style.clone());
|
||||
|
||||
writer.write(&{
|
||||
@@ -42,7 +43,7 @@ impl ElementWidget for Text<'_> {
|
||||
}
|
||||
});
|
||||
|
||||
writer.result()
|
||||
Some(writer.result())
|
||||
}
|
||||
fn event(&mut self, event: Event, document: &Document) {
|
||||
call!(self.on_event(event, document));
|
||||
@@ -77,7 +78,7 @@ pub struct Div {
|
||||
}
|
||||
|
||||
impl ElementWidget for Div<'_> {
|
||||
fn render(&self, focused: bool) -> RenderResult {
|
||||
fn render(&self, focused: bool) -> Option<RenderResult> {
|
||||
let mut writer = RenderWriter::new(focused, self.style.clone());
|
||||
let mut frame = crate::utils::Frame::new(crate::utils::get_term_size().0, 12);
|
||||
|
||||
@@ -88,7 +89,7 @@ impl ElementWidget for Div<'_> {
|
||||
}
|
||||
writer.write(&frame.output());
|
||||
|
||||
writer.result()
|
||||
Some(writer.result())
|
||||
}
|
||||
|
||||
fn event(&mut self, event: Event, document: &Document) {
|
||||
@@ -97,51 +98,11 @@ impl ElementWidget for Div<'_> {
|
||||
self.set_styling(&styling);
|
||||
}
|
||||
}
|
||||
match event {
|
||||
Event::Key(key) => {
|
||||
if let Children::Children(children, child) = &mut self.children {
|
||||
*child = match key.code {
|
||||
KeyCode::Up => crate::utils::closest_component(
|
||||
children,
|
||||
*child,
|
||||
crate::utils::Direction::Up,
|
||||
),
|
||||
|
||||
KeyCode::Down => crate::utils::closest_component(
|
||||
children,
|
||||
*child,
|
||||
crate::utils::Direction::Down,
|
||||
),
|
||||
|
||||
KeyCode::Left => crate::utils::closest_component(
|
||||
children,
|
||||
*child,
|
||||
crate::utils::Direction::Left,
|
||||
),
|
||||
|
||||
KeyCode::Right => crate::utils::closest_component(
|
||||
children,
|
||||
*child,
|
||||
crate::utils::Direction::Right,
|
||||
),
|
||||
|
||||
_ => {
|
||||
if let Some(c) = children.get_mut(*child) {
|
||||
c.event(event, document);
|
||||
}
|
||||
*child
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if let Some(child) = self.get_child() {
|
||||
if let Some(child) = self.children.get_child() {
|
||||
child.event(event, document);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[element]
|
||||
#[elem_fn]
|
||||
@@ -151,10 +112,10 @@ pub struct Button {
|
||||
}
|
||||
|
||||
impl ElementWidget for Button<'_> {
|
||||
fn render(&self, focused: bool) -> RenderResult {
|
||||
fn render(&self, focused: bool) -> Option<RenderResult> {
|
||||
let mut writer = RenderWriter::new(focused, self.style.clone());
|
||||
writer.write(&self.children.get_text());
|
||||
writer.result()
|
||||
Some(writer.result())
|
||||
}
|
||||
|
||||
fn event(&mut self, event: Event, document: &Document) {
|
||||
@@ -173,3 +134,25 @@ impl ElementWidget for Button<'_> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[element]
|
||||
#[derive(Debug)]
|
||||
pub struct DataHolder<'a, T> {
|
||||
pub data: T,
|
||||
}
|
||||
|
||||
pub fn dataholder<'a, T: std::default::Default>() -> Box<DataHolder<'a, T>> {
|
||||
Box::new(DataHolder {
|
||||
style: Style::default(),
|
||||
data: T::default(),
|
||||
children: Children::None,
|
||||
class: "",
|
||||
id: "",
|
||||
})
|
||||
}
|
||||
|
||||
impl<'a, T: std::fmt::Debug + Send + Sync> ElementWidget for DataHolder<'a, T> {
|
||||
fn render(&self, _: bool) -> Option<RenderResult> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
+3
-50
@@ -9,7 +9,7 @@
|
||||
/// let frame = create_frame(50, 10);
|
||||
/// render_to_frame(crate::State::Normal, 50, &mut frame, &text_element);
|
||||
/// ```
|
||||
use crate::{Element, Value};
|
||||
use crate::Element;
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
use std::{
|
||||
@@ -99,8 +99,7 @@ impl Frame {
|
||||
}
|
||||
}
|
||||
pub fn render(&mut self, focused: bool, element: &Element) {
|
||||
// let data = element.get_data();
|
||||
let output = element.render(focused);
|
||||
if let Some(output) = element.render(focused) {
|
||||
let x;
|
||||
let mut y = 0;
|
||||
match output.1.y {
|
||||
@@ -156,6 +155,7 @@ impl Frame {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn output(&self) -> String {
|
||||
self.frame.join("\n")
|
||||
}
|
||||
@@ -183,53 +183,6 @@ pub fn flush() {
|
||||
stdout().flush().unwrap();
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Direction {
|
||||
Left,
|
||||
Right,
|
||||
Up,
|
||||
Down,
|
||||
}
|
||||
|
||||
pub fn closest_component(
|
||||
components: &[Element],
|
||||
current_index: usize,
|
||||
direction: Direction,
|
||||
) -> usize {
|
||||
let current = &components[current_index].get_data();
|
||||
|
||||
components
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(i, comp_)| {
|
||||
let comp = comp_.get_data();
|
||||
match direction {
|
||||
Direction::Left => match comp.0 {
|
||||
Value::Custom(_) => {
|
||||
comp.0.get_value() < current.0.get_value() && comp.1 == current.1
|
||||
}
|
||||
Value::Default(_) => *i < current_index,
|
||||
}, // Left
|
||||
Direction::Right => match comp.0 {
|
||||
Value::Custom(_) => {
|
||||
comp.0.get_value() > current.0.get_value() && comp.1 == current.1
|
||||
}
|
||||
Value::Default(_) => *i > current_index,
|
||||
}, // Right
|
||||
Direction::Up => comp.1 < current.1 && comp.0.get_value() == current.0.get_value(), // Up
|
||||
Direction::Down => {
|
||||
comp.1 > current.1 && comp.0.get_value() == current.0.get_value()
|
||||
} // Down
|
||||
}
|
||||
})
|
||||
.min_by_key(|(_, comp_)| {
|
||||
let comp = comp_.get_data();
|
||||
current.0.get_value().abs_diff(comp.0.get_value()) + current.1.abs_diff(comp.1)
|
||||
}) // Find the closest component
|
||||
.map(|(index, _)| index) // Return the index of the closest component
|
||||
.unwrap_or(current_index) // If no component is found, return the current index
|
||||
}
|
||||
|
||||
pub fn get_term_size() -> (usize, usize) {
|
||||
let (width, height) = crossterm::terminal::size().unwrap();
|
||||
(width as usize, height as usize)
|
||||
|
||||
Reference in New Issue
Block a user