Merge pull request #29 from osui-rs/iteration-patch
Added iteration and improved examples
This commit is contained in:
@@ -0,0 +1,32 @@
|
|||||||
|
use osui::prelude::*;
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()> {
|
||||||
|
let screen = Screen::new();
|
||||||
|
|
||||||
|
app().draw(&screen);
|
||||||
|
|
||||||
|
screen.run()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn app() -> Rsx {
|
||||||
|
let items: State<Vec<i32>> = use_state(vec![1, 2]);
|
||||||
|
|
||||||
|
std::thread::spawn({
|
||||||
|
let items = items.clone();
|
||||||
|
move || {
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||||
|
items.get().push(3);
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||||
|
items.get().remove(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
rsx! {
|
||||||
|
FlexRow {
|
||||||
|
for item in items {
|
||||||
|
static "{item}"
|
||||||
|
static "Idk {item}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,16 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use osui::prelude::*;
|
use osui::prelude::*;
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()> {
|
||||||
|
let screen = Screen::new();
|
||||||
|
screen.extension(InputExtension);
|
||||||
|
screen.extension(RelativeFocusExtension::new());
|
||||||
|
|
||||||
|
app(screen.clone()).draw(&screen);
|
||||||
|
|
||||||
|
screen.run()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn app(screen: Arc<Screen>) -> Rsx {
|
pub fn app(screen: Arc<Screen>) -> Rsx {
|
||||||
let count = use_state(0);
|
let count = use_state(0);
|
||||||
|
|
||||||
@@ -78,6 +78,12 @@ impl Element for FlexRow {
|
|||||||
element.inject(|w| w.component(NoRenderRoot));
|
element.inject(|w| w.component(NoRenderRoot));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn undraw_child(&mut self, element: &Arc<Widget>) {
|
||||||
|
if let Some(i) = self.children.iter().position(|v| Arc::ptr_eq(v, element)) {
|
||||||
|
self.children.remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn is_ghost(&mut self) -> bool {
|
fn is_ghost(&mut self) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_widgets(&self) -> MutexGuard<Vec<Arc<Widget>>> {
|
pub fn get_widgets(&'_ self) -> MutexGuard<'_, Vec<Arc<Widget>>> {
|
||||||
self.screen.widgets.lock().unwrap()
|
self.screen.widgets.lock().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+70
-1
@@ -25,6 +25,12 @@ pub enum RsxElement {
|
|||||||
Vec<Box<dyn DependencyHandler>>,
|
Vec<Box<dyn DependencyHandler>>,
|
||||||
Rsx,
|
Rsx,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
/// A dynamic iteration of widgets, keeping track of their state.
|
||||||
|
Iter(
|
||||||
|
Box<dyn FnMut() -> Rsx + Send + Sync>,
|
||||||
|
Box<dyn DependencyHandler>,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A container representing a group of RSX elements.
|
/// A container representing a group of RSX elements.
|
||||||
@@ -42,7 +48,13 @@ impl Rsx {
|
|||||||
/// Recursively draws the RSX tree with an optional parent widget.
|
/// Recursively draws the RSX tree with an optional parent widget.
|
||||||
///
|
///
|
||||||
/// Used internally to establish parent-child widget relationships.
|
/// Used internally to establish parent-child widget relationships.
|
||||||
pub fn draw_parent(self, screen: &Arc<Screen>, parent: Option<Arc<Widget>>) {
|
pub fn draw_parent(
|
||||||
|
self,
|
||||||
|
screen: &Arc<Screen>,
|
||||||
|
parent: Option<Arc<Widget>>,
|
||||||
|
) -> Option<Arc<Widget>> {
|
||||||
|
let mut first_widget = None;
|
||||||
|
|
||||||
for rsx_elem in self.0 {
|
for rsx_elem in self.0 {
|
||||||
match rsx_elem {
|
match rsx_elem {
|
||||||
RsxElement::DynElement(f, dep, child) => {
|
RsxElement::DynElement(f, dep, child) => {
|
||||||
@@ -57,6 +69,9 @@ impl Rsx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
child.draw_parent(screen, Some(w.clone()));
|
child.draw_parent(screen, Some(w.clone()));
|
||||||
|
if first_widget.is_none() {
|
||||||
|
first_widget = Some(w)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RsxElement::Element(ws, child) => {
|
RsxElement::Element(ws, child) => {
|
||||||
@@ -68,9 +83,49 @@ impl Rsx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
child.draw_parent(screen, Some(w.clone()));
|
child.draw_parent(screen, Some(w.clone()));
|
||||||
|
if first_widget.is_none() {
|
||||||
|
first_widget = Some(w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RsxElement::Iter(mut rsx, dep) => {
|
||||||
|
#[allow(unused)]
|
||||||
|
let mut rsx_len = 0;
|
||||||
|
let mut fw = {
|
||||||
|
let r = rsx();
|
||||||
|
rsx_len = r.0.len();
|
||||||
|
r.draw_parent(screen, parent.clone())
|
||||||
|
};
|
||||||
|
let parent = parent.clone();
|
||||||
|
let s = screen.clone();
|
||||||
|
|
||||||
|
screen.add_dependency(vec![dep], move || {
|
||||||
|
if let Some(fww) = &fw {
|
||||||
|
{
|
||||||
|
let mut widgets = s.widgets.lock().unwrap();
|
||||||
|
if let Some(i) = widgets.iter().position(|v| Arc::ptr_eq(v, fww)) {
|
||||||
|
for v in (i..(i + rsx_len)).rev() {
|
||||||
|
if let Some(w) = widgets.get(v) {
|
||||||
|
if let Some(p) = &parent {
|
||||||
|
p.get_elem().undraw_child(w);
|
||||||
|
}
|
||||||
|
widgets.remove(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fw = {
|
||||||
|
let r = rsx();
|
||||||
|
rsx_len = r.0.len();
|
||||||
|
r.draw_parent(&s, parent.clone())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
first_widget
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a dynamically constructed element to the RSX tree.
|
/// Adds a dynamically constructed element to the RSX tree.
|
||||||
@@ -96,8 +151,22 @@ impl Rsx {
|
|||||||
self.0.push(RsxElement::Element(element, children));
|
self.0.push(RsxElement::Element(element, children));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds a statically defined element to the RSX tree with its children.
|
||||||
|
pub fn iter<F: FnMut() -> Rsx + Send + Sync + 'static>(
|
||||||
|
&mut self,
|
||||||
|
rsx: F,
|
||||||
|
dependency: Box<dyn DependencyHandler>,
|
||||||
|
) {
|
||||||
|
self.0.push(RsxElement::Iter(Box::new(rsx), dependency));
|
||||||
|
}
|
||||||
|
|
||||||
/// Appends the elements from another `Rsx` tree into this one.
|
/// Appends the elements from another `Rsx` tree into this one.
|
||||||
pub fn expand(&mut self, other: &mut Rsx) {
|
pub fn expand(&mut self, other: &mut Rsx) {
|
||||||
self.0.append(&mut other.0);
|
self.0.append(&mut other.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Appends the elements from another `Rsx` tree into this one. nr stands for no reference
|
||||||
|
pub fn expand_nr(&mut self, mut other: Rsx) {
|
||||||
|
self.0.append(&mut other.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+34
@@ -35,6 +35,7 @@ use crate::{
|
|||||||
extensions::Extension,
|
extensions::Extension,
|
||||||
prelude::{Context, ElementRenderer},
|
prelude::{Context, ElementRenderer},
|
||||||
render_scope::RenderScope,
|
render_scope::RenderScope,
|
||||||
|
state::DependencyHandler,
|
||||||
widget::{BoxedElement, DynWidget, Element, StaticWidget, Widget, WidgetLoad},
|
widget::{BoxedElement, DynWidget, Element, StaticWidget, Widget, WidgetLoad},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -78,6 +79,13 @@ pub struct Screen {
|
|||||||
extensions: Mutex<Vec<Arc<Mutex<Box<dyn Extension + Send + Sync>>>>>,
|
extensions: Mutex<Vec<Arc<Mutex<Box<dyn Extension + Send + Sync>>>>>,
|
||||||
/// If it's still running
|
/// If it's still running
|
||||||
running: Mutex<bool>,
|
running: Mutex<bool>,
|
||||||
|
/// If it's still running
|
||||||
|
dependencies: Mutex<
|
||||||
|
Vec<(
|
||||||
|
Vec<Box<dyn DependencyHandler>>,
|
||||||
|
Box<dyn FnMut() + Send + Sync>,
|
||||||
|
)>,
|
||||||
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
event!(RenderWrapperEvent(*mut RenderScope));
|
event!(RenderWrapperEvent(*mut RenderScope));
|
||||||
@@ -104,6 +112,7 @@ impl Screen {
|
|||||||
widgets: Mutex::new(Vec::new()),
|
widgets: Mutex::new(Vec::new()),
|
||||||
extensions: Mutex::new(Vec::new()),
|
extensions: Mutex::new(Vec::new()),
|
||||||
running: Mutex::new(true),
|
running: Mutex::new(true),
|
||||||
|
dependencies: Mutex::new(Vec::new()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,6 +203,14 @@ impl Screen {
|
|||||||
|
|
||||||
scope.render_widget(&mut renderer, ctx, widget);
|
scope.render_widget(&mut renderer, ctx, widget);
|
||||||
}
|
}
|
||||||
|
for d in self.dependencies.lock().unwrap().iter_mut() {
|
||||||
|
for dh in &d.0 {
|
||||||
|
if dh.check() {
|
||||||
|
(d.1)();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,6 +225,23 @@ impl Screen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Screen {
|
||||||
|
pub fn add_dependency<F: FnMut() + Send + Sync + 'static>(
|
||||||
|
self: &Arc<Self>,
|
||||||
|
dependencies: Vec<Box<dyn DependencyHandler>>,
|
||||||
|
handler: F,
|
||||||
|
) {
|
||||||
|
for d in &dependencies {
|
||||||
|
d.add();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.dependencies
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.push((dependencies, Box::new(handler)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct ScreenRenderer;
|
struct ScreenRenderer;
|
||||||
|
|
||||||
impl ElementRenderer for ScreenRenderer {}
|
impl ElementRenderer for ScreenRenderer {}
|
||||||
|
|||||||
@@ -240,6 +240,20 @@ macro_rules! rsx {
|
|||||||
/// Would produce a nested `Rsx` tree of static and dynamic widgets.
|
/// Would produce a nested `Rsx` tree of static and dynamic widgets.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! rsx_inner {
|
macro_rules! rsx_inner {
|
||||||
|
// for loop (iter)
|
||||||
|
($r:expr, for $n:ident in $state:ident { $($inner:tt)* } $($rest:tt)*) => {
|
||||||
|
$r.iter({
|
||||||
|
let $state = $state.clone();
|
||||||
|
move || {
|
||||||
|
let mut r = $crate::frontend::Rsx(Vec::new());
|
||||||
|
for $n in $state.get().iter() {
|
||||||
|
r.expand_nr($crate::rsx!{ $($inner)* });
|
||||||
|
}
|
||||||
|
r
|
||||||
|
}}, Box::new($state));
|
||||||
|
$crate::rsx_inner! { $r, $($rest)* };
|
||||||
|
};
|
||||||
|
|
||||||
// static
|
// static
|
||||||
($r:expr, $(@$comp:expr;)* static $s:literal $($rest:tt)*) => {
|
($r:expr, $(@$comp:expr;)* static $s:literal $($rest:tt)*) => {
|
||||||
let w = $crate::widget::StaticWidget::new(Box::new(format!($s)));
|
let w = $crate::widget::StaticWidget::new(Box::new(format!($s)));
|
||||||
|
|||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
mod demos;
|
|
||||||
use osui::prelude::*;
|
|
||||||
|
|
||||||
fn main() -> std::io::Result<()> {
|
|
||||||
let screen = Screen::new();
|
|
||||||
screen.extension(InputExtension);
|
|
||||||
screen.extension(RelativeFocusExtension::new());
|
|
||||||
|
|
||||||
demos::app(screen.clone()).draw(&screen);
|
|
||||||
|
|
||||||
screen.run()
|
|
||||||
}
|
|
||||||
+7
-3
@@ -51,6 +51,10 @@ pub trait Element: Send + Sync {
|
|||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn draw_child(&mut self, element: &Arc<Widget>) {}
|
fn draw_child(&mut self, element: &Arc<Widget>) {}
|
||||||
|
|
||||||
|
/// Called to undraw child widgets, if any.
|
||||||
|
#[allow(unused)]
|
||||||
|
fn undraw_child(&mut self, element: &Arc<Widget>) {}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn event(&mut self, event: &dyn Event) {}
|
fn event(&mut self, event: &dyn Event) {}
|
||||||
|
|
||||||
@@ -166,7 +170,7 @@ impl Widget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_elem(&self) -> MutexGuard<BoxedElement> {
|
pub fn get_elem(&'_ self) -> MutexGuard<'_, BoxedElement> {
|
||||||
match self {
|
match self {
|
||||||
Widget::Static(w) => w.get_elem(),
|
Widget::Static(w) => w.get_elem(),
|
||||||
Widget::Dynamic(w) => w.get_elem(),
|
Widget::Dynamic(w) => w.get_elem(),
|
||||||
@@ -284,7 +288,7 @@ impl Widget {
|
|||||||
|
|
||||||
impl StaticWidget {
|
impl StaticWidget {
|
||||||
fn after_render(&self) {}
|
fn after_render(&self) {}
|
||||||
fn get_elem(&self) -> MutexGuard<BoxedElement> {
|
fn get_elem(&'_ self) -> MutexGuard<'_, BoxedElement> {
|
||||||
self.element.lock().unwrap()
|
self.element.lock().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -325,7 +329,7 @@ impl StaticWidget {
|
|||||||
|
|
||||||
impl DynWidget {
|
impl DynWidget {
|
||||||
fn after_render(&self) {}
|
fn after_render(&self) {}
|
||||||
fn get_elem(&self) -> MutexGuard<BoxedElement> {
|
fn get_elem(&'_ self) -> MutexGuard<'_, BoxedElement> {
|
||||||
self.element.lock().unwrap()
|
self.element.lock().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user