Merge pull request #12 from osui-rs/better-state-management
Better state management
This commit is contained in:
@@ -21,14 +21,15 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use osui::{style::Transform, Screen};
|
use osui::prelude::*;
|
||||||
|
|
||||||
fn main() -> std::io::Result<()> {
|
fn main() -> std::io::Result<()> {
|
||||||
let screen = Screen::new();
|
let screen = Screen::new();
|
||||||
|
|
||||||
screen
|
rsx! {
|
||||||
.draw(format!("Hello, World"))
|
"Hello, World"
|
||||||
.component(Transform::center());
|
}
|
||||||
|
.draw(&screen);
|
||||||
|
|
||||||
screen.run()
|
screen.run()
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -29,7 +29,7 @@ impl Element for Div {
|
|||||||
if let Some(t) = elem.get() {
|
if let Some(t) = elem.get() {
|
||||||
scope.set_transform(&t);
|
scope.set_transform(&t);
|
||||||
}
|
}
|
||||||
elem.0.lock().unwrap().render(scope);
|
elem.get_elem().render(scope);
|
||||||
if let Some(t) = elem.get() {
|
if let Some(t) = elem.get() {
|
||||||
scope.set_transform(&t);
|
scope.set_transform(&t);
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@ impl Element for Div {
|
|||||||
t.y += transform.y + transform.py;
|
t.y += transform.y + transform.py;
|
||||||
|
|
||||||
scope.draw();
|
scope.draw();
|
||||||
elem.0.lock().unwrap().after_render(scope);
|
elem.get_elem().after_render(scope);
|
||||||
}
|
}
|
||||||
scope.set_parent_size(w, h);
|
scope.set_parent_size(w, h);
|
||||||
self.size = (transform.width, transform.height);
|
self.size = (transform.width, transform.height);
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ impl Element for FlexRow {
|
|||||||
if let Some(t) = elem.get() {
|
if let Some(t) = elem.get() {
|
||||||
scope.set_transform(&t);
|
scope.set_transform(&t);
|
||||||
}
|
}
|
||||||
elem.0.lock().unwrap().render(scope);
|
elem.get_elem().render(scope);
|
||||||
if let Some(t) = elem.get() {
|
if let Some(t) = elem.get() {
|
||||||
scope.set_transform(&t);
|
scope.set_transform(&t);
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ impl Element for FlexRow {
|
|||||||
|
|
||||||
scope.draw();
|
scope.draw();
|
||||||
|
|
||||||
elem.0.lock().unwrap().after_render(scope);
|
elem.get_elem().after_render(scope);
|
||||||
}
|
}
|
||||||
scope.set_parent_size(w, h);
|
scope.set_parent_size(w, h);
|
||||||
self.size = (transform.width, transform.height);
|
self.size = (transform.width, transform.height);
|
||||||
@@ -104,7 +104,7 @@ impl Element for FlexCol {
|
|||||||
if let Some(t) = elem.get() {
|
if let Some(t) = elem.get() {
|
||||||
scope.set_transform(&t);
|
scope.set_transform(&t);
|
||||||
}
|
}
|
||||||
elem.0.lock().unwrap().render(scope);
|
elem.get_elem().render(scope);
|
||||||
if let Some(t) = elem.get() {
|
if let Some(t) = elem.get() {
|
||||||
scope.set_transform(&t);
|
scope.set_transform(&t);
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ impl Element for FlexCol {
|
|||||||
|
|
||||||
scope.draw();
|
scope.draw();
|
||||||
|
|
||||||
elem.0.lock().unwrap().after_render(scope);
|
elem.get_elem().after_render(scope);
|
||||||
}
|
}
|
||||||
scope.set_parent_size(w, h);
|
scope.set_parent_size(w, h);
|
||||||
self.size = (transform.width, transform.height);
|
self.size = (transform.width, transform.height);
|
||||||
|
|||||||
+28
-8
@@ -2,12 +2,14 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
state::DependencyHandler,
|
state::DependencyHandler,
|
||||||
widget::{Widget, WidgetLoad},
|
widget::{StaticWidget, Widget, WidgetLoad},
|
||||||
Screen,
|
Screen,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub enum RsxElement {
|
pub enum RsxElement {
|
||||||
Element(
|
Element(Arc<StaticWidget>, Rsx),
|
||||||
|
|
||||||
|
DynElement(
|
||||||
Box<dyn FnMut() -> WidgetLoad + Send + Sync>,
|
Box<dyn FnMut() -> WidgetLoad + Send + Sync>,
|
||||||
Vec<Box<dyn DependencyHandler>>,
|
Vec<Box<dyn DependencyHandler>>,
|
||||||
Rsx,
|
Rsx,
|
||||||
@@ -24,13 +26,13 @@ impl Rsx {
|
|||||||
pub fn draw_parent(self, screen: &Arc<Screen>, parent: Option<Arc<Widget>>) {
|
pub fn draw_parent(self, screen: &Arc<Screen>, parent: Option<Arc<Widget>>) {
|
||||||
for rsx_elem in self.0 {
|
for rsx_elem in self.0 {
|
||||||
match rsx_elem {
|
match rsx_elem {
|
||||||
RsxElement::Element(f, dep, child) => {
|
RsxElement::DynElement(f, dep, child) => {
|
||||||
let w = if let Some(parent) = &parent {
|
let w = if let Some(parent) = &parent {
|
||||||
let w = screen.draw_box(f);
|
let w = screen.draw_box_dyn(f);
|
||||||
parent.0.lock().unwrap().draw_child(&w);
|
parent.get_elem().draw_child(&w);
|
||||||
w
|
w
|
||||||
} else {
|
} else {
|
||||||
screen.draw_box(f)
|
screen.draw_box_dyn(f)
|
||||||
};
|
};
|
||||||
|
|
||||||
for d in dep {
|
for d in dep {
|
||||||
@@ -38,6 +40,17 @@ impl Rsx {
|
|||||||
}
|
}
|
||||||
child.draw_parent(screen, Some(w.clone()));
|
child.draw_parent(screen, Some(w.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RsxElement::Element(ws, child) => {
|
||||||
|
let w = Arc::new(Widget::Static(ws));
|
||||||
|
screen.draw_widget(w.clone());
|
||||||
|
|
||||||
|
if let Some(parent) = &parent {
|
||||||
|
parent.get_elem().draw_child(&w);
|
||||||
|
}
|
||||||
|
|
||||||
|
child.draw_parent(screen, Some(w.clone()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,8 +61,15 @@ impl Rsx {
|
|||||||
dependencies: Vec<Box<dyn DependencyHandler>>,
|
dependencies: Vec<Box<dyn DependencyHandler>>,
|
||||||
children: Rsx,
|
children: Rsx,
|
||||||
) {
|
) {
|
||||||
self.0
|
self.0.push(RsxElement::DynElement(
|
||||||
.push(RsxElement::Element(Box::new(load), dependencies, children));
|
Box::new(load),
|
||||||
|
dependencies,
|
||||||
|
children,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_element_static(&mut self, element: Arc<StaticWidget>, children: Rsx) {
|
||||||
|
self.0.push(RsxElement::Element(element, children));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expand(&mut self, other: &mut Rsx) {
|
pub fn expand(&mut self, other: &mut Rsx) {
|
||||||
|
|||||||
+28
-10
@@ -3,7 +3,7 @@ use std::sync::{Arc, Mutex};
|
|||||||
use crate::{
|
use crate::{
|
||||||
extensions::{Extension, Handler},
|
extensions::{Extension, Handler},
|
||||||
render_scope::RenderScope,
|
render_scope::RenderScope,
|
||||||
widget::{Element, Widget, WidgetLoad},
|
widget::{BoxedElement, DynWidget, Element, StaticWidget, Widget, WidgetLoad},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod elements;
|
pub mod elements;
|
||||||
@@ -53,20 +53,38 @@ impl Screen {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw<F: FnMut() -> WidgetLoad + 'static + Send + Sync>(
|
pub fn draw<E: Element + 'static + Send + Sync>(self: &Arc<Self>, element: E) -> Arc<Widget> {
|
||||||
self: &Arc<Self>,
|
let w = Arc::new(Widget::Static(Arc::new(StaticWidget::new(Box::new(
|
||||||
element: F,
|
element,
|
||||||
) -> Arc<Widget> {
|
)))));
|
||||||
let w = Arc::new(Widget::new(Box::new(element)));
|
|
||||||
self.widgets.lock().unwrap().push(w.clone());
|
self.widgets.lock().unwrap().push(w.clone());
|
||||||
w
|
w
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_box(
|
pub fn draw_box(self: &Arc<Self>, element: BoxedElement) -> Arc<Widget> {
|
||||||
|
let w = Arc::new(Widget::Static(Arc::new(StaticWidget::new(element))));
|
||||||
|
self.widgets.lock().unwrap().push(w.clone());
|
||||||
|
w
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_widget(self: &Arc<Self>, widget: Arc<Widget>) {
|
||||||
|
self.widgets.lock().unwrap().push(widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_dyn<F: FnMut() -> WidgetLoad + 'static + Send + Sync>(
|
||||||
|
self: &Arc<Self>,
|
||||||
|
element: F,
|
||||||
|
) -> Arc<Widget> {
|
||||||
|
let w = Arc::new(Widget::Dynamic(Arc::new(DynWidget::new(element))));
|
||||||
|
self.widgets.lock().unwrap().push(w.clone());
|
||||||
|
w
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_box_dyn(
|
||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
element: Box<dyn FnMut() -> WidgetLoad + Send + Sync>,
|
element: Box<dyn FnMut() -> WidgetLoad + Send + Sync>,
|
||||||
) -> Arc<Widget> {
|
) -> Arc<Widget> {
|
||||||
let w = Arc::new(Widget::new(Box::new(element)));
|
let w = Arc::new(Widget::Dynamic(Arc::new(DynWidget::new(element))));
|
||||||
self.widgets.lock().unwrap().push(w.clone());
|
self.widgets.lock().unwrap().push(w.clone());
|
||||||
w
|
w
|
||||||
}
|
}
|
||||||
@@ -122,14 +140,14 @@ impl Screen {
|
|||||||
ext.lock().unwrap().render_widget(&mut scope, elem);
|
ext.lock().unwrap().render_widget(&mut scope, elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
elem.0.lock().unwrap().render(&mut scope);
|
elem.get_elem().render(&mut scope);
|
||||||
|
|
||||||
if let Some(t) = elem.get() {
|
if let Some(t) = elem.get() {
|
||||||
scope.set_transform(&t);
|
scope.set_transform(&t);
|
||||||
}
|
}
|
||||||
scope.draw();
|
scope.draw();
|
||||||
|
|
||||||
elem.0.lock().unwrap().after_render(&mut scope);
|
elem.get_elem().after_render(&mut scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
elem.auto_refresh();
|
elem.auto_refresh();
|
||||||
|
|||||||
@@ -145,6 +145,12 @@ macro_rules! rsx {
|
|||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! rsx_inner {
|
macro_rules! rsx_inner {
|
||||||
|
// static
|
||||||
|
($r:expr, $(@$comp:expr;)* static $s:literal $($rest:tt)*) => {
|
||||||
|
$r.create_element_static(std::sync::Arc::new($crate::widget::StaticWidget::new(Box::new(format!($s)))) $(.component($comp))* .clone(), $crate::frontend::Rsx(Vec::new()));
|
||||||
|
$crate::rsx_inner! { $r, $($rest)* };
|
||||||
|
};
|
||||||
|
|
||||||
($r:expr, $(%$dep:ident)* $(@$comp:expr;)* $s:literal $($rest:tt)*) => {
|
($r:expr, $(%$dep:ident)* $(@$comp:expr;)* $s:literal $($rest:tt)*) => {
|
||||||
$r.create_element({ $(let $dep = $dep.clone();)* move || {
|
$r.create_element({ $(let $dep = $dep.clone();)* move || {
|
||||||
$crate::widget::WidgetLoad::new(format!($s)) $(.component($comp))*
|
$crate::widget::WidgetLoad::new(format!($s)) $(.component($comp))*
|
||||||
@@ -152,6 +158,18 @@ macro_rules! rsx_inner {
|
|||||||
$crate::rsx_inner! { $r, $($rest)* };
|
$crate::rsx_inner! { $r, $($rest)* };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// static
|
||||||
|
($r:expr, $(%$dep:ident)* $(@$comp:expr;)* static $name:path { $($inner:tt)* } ($($e:expr),*) $($rest:tt)*) => {
|
||||||
|
$r.create_element_static(std::sync::Arc::new($crate::widget::StaticWidget::new(Box::new(<$name>::new($($e),*)))) $(.component($comp))* .clone(), $crate::frontend::Rsx(Vec::new()));
|
||||||
|
$crate::rsx_inner! { $r, $($rest)* };
|
||||||
|
};
|
||||||
|
|
||||||
|
// static
|
||||||
|
($r:expr, $(@$comp:expr;)* static $name:path { $($inner:tt)* } $($rest:tt)*) => {
|
||||||
|
$r.create_element_static(std::sync::Arc::new($crate::widget::StaticWidget::new(Box::new(<$name>::new()))) $(.component($comp))* .clone(), $crate::frontend::Rsx(Vec::new()));
|
||||||
|
$crate::rsx_inner! { $r, $($rest)* };
|
||||||
|
};
|
||||||
|
|
||||||
($r:expr, $(%$dep:ident)* $(@$comp:expr;)* $name:path { $($inner:tt)* } ($($e:expr),*) $($rest:tt)*) => {
|
($r:expr, $(%$dep:ident)* $(@$comp:expr;)* $name:path { $($inner:tt)* } ($($e:expr),*) $($rest:tt)*) => {
|
||||||
$r.create_element({ $(let $dep = $dep.clone();)* move || {
|
$r.create_element({ $(let $dep = $dep.clone();)* move || {
|
||||||
$crate::widget::WidgetLoad::new(<$name>::new($($e),*)) $(.component($comp))*
|
$crate::widget::WidgetLoad::new(<$name>::new($($e),*)) $(.component($comp))*
|
||||||
|
|||||||
+14
-26
@@ -2,33 +2,21 @@ use osui::prelude::*;
|
|||||||
|
|
||||||
fn main() -> std::io::Result<()> {
|
fn main() -> std::io::Result<()> {
|
||||||
let screen = Screen::new();
|
let screen = Screen::new();
|
||||||
|
screen.extension(VelocityExtension);
|
||||||
|
|
||||||
app().draw(&screen);
|
let count = use_state(0);
|
||||||
|
|
||||||
|
rsx! {
|
||||||
|
@Velocity(20, 0);
|
||||||
|
@Transform::new();
|
||||||
|
static "Count: {count}"
|
||||||
|
}
|
||||||
|
.draw(&screen);
|
||||||
|
|
||||||
|
std::thread::spawn(move || loop {
|
||||||
|
**count.get() += 1;
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(100));
|
||||||
|
});
|
||||||
|
|
||||||
screen.run()
|
screen.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app() -> Rsx {
|
|
||||||
rsx! {
|
|
||||||
@Transform::new().padding(3, 3);
|
|
||||||
@Style { background: Background::RoundedOutline(0xff0000), foreground: None };
|
|
||||||
Div {
|
|
||||||
@Transform::new().padding(1, 1);
|
|
||||||
@Style { background: Background::RoundedOutline(0x00ff00), foreground: None };
|
|
||||||
FlexCol {
|
|
||||||
@Transform::new().padding(1, 1);
|
|
||||||
"Hello, World!"
|
|
||||||
@Transform::new().padding(1, 1);
|
|
||||||
"Hello, World!"
|
|
||||||
@Transform::new().padding(1, 1);
|
|
||||||
"Hello, World!"
|
|
||||||
@Transform::new().padding(1, 1);
|
|
||||||
"Hello, World!"
|
|
||||||
@Transform::new().padding(1, 1);
|
|
||||||
"Hello, World!"
|
|
||||||
@Transform::new().padding(1, 1);
|
|
||||||
"Hello, World!"
|
|
||||||
} (2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+186
-42
@@ -1,7 +1,7 @@
|
|||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex, MutexGuard},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{render_scope::RenderScope, state::DependencyHandler};
|
use crate::{render_scope::RenderScope, state::DependencyHandler};
|
||||||
@@ -25,15 +25,190 @@ pub trait Component: Send + Sync {
|
|||||||
fn as_any_mut(&mut self) -> &mut dyn Any;
|
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Widget(
|
pub struct WidgetLoad(BoxedElement, HashMap<TypeId, BoxedComponent>);
|
||||||
pub Mutex<BoxedElement>,
|
|
||||||
|
impl WidgetLoad {
|
||||||
|
pub fn new<E: Element + 'static>(e: E) -> Self {
|
||||||
|
Self(Box::new(e), HashMap::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn component<C: Component + 'static>(mut self, c: C) -> Self {
|
||||||
|
self.1.entry(c.type_id()).or_insert_with(|| Box::new(c));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_component<C: Component + 'static>(mut self, c: C) -> Self {
|
||||||
|
self.1.insert(c.type_id(), Box::new(c));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get<C: Component + 'static + Clone>(&self) -> Option<C> {
|
||||||
|
self.1
|
||||||
|
.get(&TypeId::of::<C>())
|
||||||
|
.and_then(|c| c.as_any().downcast_ref::<C>())
|
||||||
|
.map(|c| c.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Widget {
|
||||||
|
Static(Arc<StaticWidget>),
|
||||||
|
Dynamic(Arc<DynWidget>),
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Trait Implementation ===
|
||||||
|
impl Widget {
|
||||||
|
pub fn get_elem(&self) -> MutexGuard<BoxedElement> {
|
||||||
|
match self {
|
||||||
|
Widget::Static(w) => w.get_elem(),
|
||||||
|
Widget::Dynamic(w) => w.get_elem(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn after_render(&self) {
|
||||||
|
match self {
|
||||||
|
Widget::Static(w) => w.after_render(),
|
||||||
|
Widget::Dynamic(w) => w.after_render(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn component<C: Component + 'static>(self: &Arc<Self>, c: C) -> &Arc<Self> {
|
||||||
|
match &**self {
|
||||||
|
Widget::Static(w) => {
|
||||||
|
w.component(c);
|
||||||
|
}
|
||||||
|
Widget::Dynamic(w) => {
|
||||||
|
w.component(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_component<C: Component + 'static>(self: &Arc<Self>, c: C) -> &Arc<Self> {
|
||||||
|
match &**self {
|
||||||
|
Widget::Static(w) => {
|
||||||
|
w.set_component(c);
|
||||||
|
}
|
||||||
|
Widget::Dynamic(w) => {
|
||||||
|
w.set_component(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get<C: Component + 'static + Clone>(&self) -> Option<C> {
|
||||||
|
match self {
|
||||||
|
Widget::Static(w) => w.get(),
|
||||||
|
Widget::Dynamic(w) => w.get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inject<F: FnMut(WidgetLoad) -> WidgetLoad + 'static + Send + Sync>(
|
||||||
|
self: &Arc<Self>,
|
||||||
|
f: F,
|
||||||
|
) {
|
||||||
|
match &**self {
|
||||||
|
Widget::Dynamic(w) => {
|
||||||
|
w.inject(f);
|
||||||
|
}
|
||||||
|
Widget::Static(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn refresh(self: &Arc<Self>) {
|
||||||
|
match &**self {
|
||||||
|
Widget::Dynamic(w) => {
|
||||||
|
w.refresh();
|
||||||
|
}
|
||||||
|
Widget::Static(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn auto_refresh(self: &Arc<Self>) {
|
||||||
|
match &**self {
|
||||||
|
Widget::Dynamic(w) => {
|
||||||
|
w.auto_refresh();
|
||||||
|
}
|
||||||
|
Widget::Static(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dependency<D: DependencyHandler + 'static>(self: &Arc<Self>, d: D) -> &Arc<Self> {
|
||||||
|
match &**self {
|
||||||
|
Widget::Dynamic(w) => {
|
||||||
|
w.dependency(d);
|
||||||
|
}
|
||||||
|
Widget::Static(_) => {}
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dependency_box(self: &Arc<Self>, d: Box<dyn DependencyHandler>) -> &Arc<Self> {
|
||||||
|
match &**self {
|
||||||
|
Widget::Dynamic(w) => {
|
||||||
|
w.dependency_box(d);
|
||||||
|
}
|
||||||
|
Widget::Static(_) => {}
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Static Widget ===
|
||||||
|
pub struct StaticWidget(Mutex<BoxedElement>, Mutex<HashMap<TypeId, BoxedComponent>>);
|
||||||
|
|
||||||
|
impl StaticWidget {
|
||||||
|
fn after_render(&self) {}
|
||||||
|
fn get_elem(&self) -> MutexGuard<BoxedElement> {
|
||||||
|
self.0.lock().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StaticWidget {
|
||||||
|
pub fn new(e: BoxedElement) -> Self {
|
||||||
|
Self(Mutex::new(e), Mutex::new(HashMap::new()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn component<C: Component + 'static>(self: &Arc<Self>, c: C) -> &Arc<Self> {
|
||||||
|
self.1
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.entry(c.type_id())
|
||||||
|
.or_insert_with(|| Box::new(c));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_component<C: Component + 'static>(self: &Arc<Self>, c: C) -> &Arc<Self> {
|
||||||
|
self.1.lock().unwrap().insert(c.type_id(), Box::new(c));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get<C: Component + 'static + Clone>(&self) -> Option<C> {
|
||||||
|
self.1
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.get(&TypeId::of::<C>())
|
||||||
|
.and_then(|c| c.as_any().downcast_ref::<C>())
|
||||||
|
.map(Clone::clone)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Dynamic Widget ===
|
||||||
|
pub struct DynWidget(
|
||||||
|
Mutex<BoxedElement>,
|
||||||
Mutex<HashMap<TypeId, BoxedComponent>>,
|
Mutex<HashMap<TypeId, BoxedComponent>>,
|
||||||
Mutex<Box<dyn FnMut() -> WidgetLoad + Send + Sync>>,
|
Mutex<Box<dyn FnMut() -> WidgetLoad + Send + Sync>>,
|
||||||
Mutex<Vec<Box<dyn DependencyHandler>>>,
|
Mutex<Vec<Box<dyn DependencyHandler>>>,
|
||||||
Mutex<Option<Box<dyn FnMut(WidgetLoad) -> WidgetLoad + Send + Sync>>>,
|
Mutex<Option<Box<dyn FnMut(WidgetLoad) -> WidgetLoad + Send + Sync>>>,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl Widget {
|
impl DynWidget {
|
||||||
|
fn after_render(&self) {}
|
||||||
|
fn get_elem(&self) -> MutexGuard<BoxedElement> {
|
||||||
|
self.0.lock().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DynWidget {
|
||||||
pub fn new<F: FnMut() -> WidgetLoad + 'static + Send + Sync>(mut e: F) -> Self {
|
pub fn new<F: FnMut() -> WidgetLoad + 'static + Send + Sync>(mut e: F) -> Self {
|
||||||
let wl = e();
|
let wl = e();
|
||||||
Self(
|
Self(
|
||||||
@@ -49,26 +224,20 @@ impl Widget {
|
|||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
f: F,
|
f: F,
|
||||||
) {
|
) {
|
||||||
{
|
|
||||||
*self.4.lock().unwrap() = Some(Box::new(f));
|
*self.4.lock().unwrap() = Some(Box::new(f));
|
||||||
}
|
|
||||||
self.refresh();
|
self.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn refresh(self: &Arc<Self>) {
|
pub fn refresh(self: &Arc<Self>) {
|
||||||
let w = (self.2.lock().unwrap())();
|
let mut w = (self.2.lock().unwrap())();
|
||||||
match &mut *self.4.lock().unwrap() {
|
|
||||||
Some(inject) => {
|
if let Some(we) = &mut *self.4.lock().unwrap() {
|
||||||
let w = inject(w);
|
w = (we)(w);
|
||||||
|
}
|
||||||
|
|
||||||
*self.0.lock().unwrap() = w.0;
|
*self.0.lock().unwrap() = w.0;
|
||||||
*self.1.lock().unwrap() = w.1;
|
*self.1.lock().unwrap() = w.1;
|
||||||
}
|
}
|
||||||
None => {
|
|
||||||
*self.0.lock().unwrap() = w.0;
|
|
||||||
*self.1.lock().unwrap() = w.1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn auto_refresh(self: &Arc<Self>) {
|
pub fn auto_refresh(self: &Arc<Self>) {
|
||||||
for d in self.3.lock().unwrap().iter() {
|
for d in self.3.lock().unwrap().iter() {
|
||||||
@@ -110,31 +279,6 @@ impl Widget {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.get(&TypeId::of::<C>())
|
.get(&TypeId::of::<C>())
|
||||||
.and_then(|c| c.as_any().downcast_ref::<C>())
|
.and_then(|c| c.as_any().downcast_ref::<C>())
|
||||||
.map(|c| c.clone())
|
.map(Clone::clone)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct WidgetLoad(BoxedElement, HashMap<TypeId, BoxedComponent>);
|
|
||||||
|
|
||||||
impl WidgetLoad {
|
|
||||||
pub fn new<E: Element + 'static>(e: E) -> Self {
|
|
||||||
Self(Box::new(e), HashMap::new())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn component<C: Component + 'static>(mut self, c: C) -> Self {
|
|
||||||
self.1.entry(c.type_id()).or_insert_with(|| Box::new(c));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_component<C: Component + 'static>(mut self, c: C) -> Self {
|
|
||||||
self.1.insert(c.type_id(), Box::new(c));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get<C: Component + 'static + Clone>(&self) -> Option<C> {
|
|
||||||
self.1
|
|
||||||
.get(&TypeId::of::<C>())
|
|
||||||
.and_then(|c| c.as_any().downcast_ref::<C>())
|
|
||||||
.map(|c| c.clone())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user