polish: examples

This commit is contained in:
Jonathan Kelley committed 2021-09-24 00:05:56 -04:00
1 parent 4b6ca05f2c
commit 1a2f91ed91
19 files changed
+327 -183

No files matched your search

+26 -24
View File
@@ -1,41 +1,43 @@
//! Example: README.md showcase
//!
//! The example from the README.md
/*
This example shows how to use async and loops to implement a coroutine in a component. Coroutines can be controlled via
the `TaskHandle` object.
*/
use dioxus::prelude::*;
use gloo_timers::future::TimeoutFuture;
fn main() {
dioxus::desktop::launch(App, |c| c).expect("faield to launch");
dioxus::desktop::launch(App, |c| c).unwrap();
}
pub static App: FC<()> = |cx, props| {
pub static App: FC<()> = |cx, _| {
let count = use_state(cx, || 0);
let mut direction = use_state(cx, || 1);
let (async_count, dir) = (count.for_async(), *direction);
let (task, _result) = use_task(cx, move || async move {
let (task, _) = use_task(cx, move || async move {
loop {
gloo_timers::future::TimeoutFuture::new(250).await;
TimeoutFuture::new(250).await;
*async_count.get_mut() += dir;
}
});
cx.render(rsx! {
div {
h1 {"count is {count}"}
button {
"Stop counting"
onclick: move |_| task.stop()
}
button {
"Start counting"
onclick: move |_| task.resume()
}
button {
"Switch counting direcion"
onclick: move |_| {
direction *= -1;
task.restart();
}
rsx!(cx, div {
h1 {"count is {count}"}
button {
"Stop counting"
onclick: move |_| task.stop()
}
button {
"Start counting"
onclick: move |_| task.resume()
}
button {
"Switch counting direcion"
onclick: move |_| {
direction *= -1;
task.restart();
}
}
})
+15 -17
View File
@@ -1,20 +1,18 @@
#![allow(non_snake_case)]
//! Example: Extremely nested borrowing
//! -----------------------------------
//!
//! Dioxus manages borrow lifetimes for you. This means any child may borrow from its parent. However, it is not possible
//! to hand out an &mut T to children - all props are consumed by &P, so you'd only get an &&mut T.
//!
//! How does it work?
//!
//! Dioxus will manually drop closures and props - things that borrow data before the component is ran again. This is done
//! "bottom up" from the lowest child all the way to the initiating parent. As it traverses each listener and prop, the
//! drop implementation is manually called, freeing any memory and ensuring that memory is not leaked.
//!
//! We cannot drop from the parent to the children - if the drop implementation modifies the data, downstream references
//! might be broken since we take an &mut T and and &T to the data. Instead, we work bottom up, making sure to remove any
//! potential references to the data before finally giving out an &mut T. This prevents us from mutably aliasing the data,
//! and is proven to be safe with MIRI.
/*
Dioxus manages borrow lifetimes for you. This means any child may borrow from its parent. However, it is not possible
to hand out an &mut T to children - all props are consumed by &P, so you'd only get an &&mut T.
How does it work?
Dioxus will manually drop closures and props - things that borrow data before the component is ran again. This is done
"bottom up" from the lowest child all the way to the initiating parent. As it traverses each listener and prop, the
drop implementation is manually called, freeing any memory and ensuring that memory is not leaked.
We cannot drop from the parent to the children - if the drop implementation modifies the data, downstream references
might be broken since we take an &mut T and and &T to the data. Instead, we work bottom up, making sure to remove any
potential references to the data before finally giving out an &mut T. This prevents us from mutably aliasing the data,
and is proven to be safe with MIRI.
*/
use dioxus::prelude::*;
+54 -72
View File
@@ -1,25 +1,19 @@
//! Example: Calculator
//! -------------------------
fn main() {
env_logger::init();
dioxus::desktop::launch(App, |cfg| cfg).unwrap();
}
/*
This example is a simple iOS-style calculator. This particular example can run any platform - Web, Mobile, Desktop.
This calculator version uses React-style state management. All state is held as individual use_states.
*/
use dioxus::events::on::*;
use dioxus::prelude::*;
enum Operator {
Add,
Sub,
Mul,
Div,
fn main() {
dioxus::desktop::launch(APP, |cfg| cfg).unwrap();
}
const App: FC<()> = |cx, props| {
const APP: FC<()> = |cx, _| {
let cur_val = use_state(cx, || 0.0_f64);
let operator = use_state(cx, || None as Option<Operator>);
let display_value = use_state(cx, || "".to_string());
let operator = use_state(cx, || None);
let display_value = use_state(cx, || String::from(""));
let clear_display = display_value == "0";
let clear_text = if clear_display { "C" } else { "AC" };
@@ -62,11 +56,10 @@ const App: FC<()> = |cx, props| {
};
let keydownhandler = move |evt: KeyboardEvent| match evt.key_code() {
KeyCode::Backspace => {
if !display_value.as_str().eq("0") {
display_value.modify().pop();
}
}
KeyCode::Add => operator.set(Some(Operator::Add)),
KeyCode::Subtract => operator.set(Some(Operator::Sub)),
KeyCode::Divide => operator.set(Some(Operator::Div)),
KeyCode::Multiply => operator.set(Some(Operator::Mul)),
KeyCode::Num0 => input_digit(0),
KeyCode::Num1 => input_digit(1),
KeyCode::Num2 => input_digit(2),
@@ -77,73 +70,62 @@ const App: FC<()> = |cx, props| {
KeyCode::Num7 => input_digit(7),
KeyCode::Num8 => input_digit(8),
KeyCode::Num9 => input_digit(9),
KeyCode::Add => operator.set(Some(Operator::Add)),
KeyCode::Subtract => operator.set(Some(Operator::Sub)),
KeyCode::Divide => operator.set(Some(Operator::Div)),
KeyCode::Multiply => operator.set(Some(Operator::Mul)),
KeyCode::Backspace => {
if !display_value.as_str().eq("0") {
display_value.modify().pop();
}
}
_ => {}
};
cx.render(rsx! {
div { class: "calculator", onkeydown: {keydownhandler}
div { class: "input-keys"
div { class: "function-keys"
CalculatorKey { name: "key-clear", onclick: {clear_key} "{clear_text}" }
CalculatorKey { name: "key-sign", onclick: {toggle_sign}, "±"}
CalculatorKey { name: "key-percent", onclick: {toggle_percent} "%"}
}
div { class: "digit-keys"
CalculatorKey { name: "key-0", onclick: move |_| input_digit(0), "0" }
CalculatorKey { name: "key-dot", onclick: move |_| input_dot(), "●" }
use separator::Separatable;
let formatted_display = cur_val.separated_string();
{(1..9).map(|k| rsx!{
CalculatorKey { key: "{k}", name: "key-{k}", onclick: move |_| input_digit(k), "{k}" }
})}
}
div { class: "operator-keys"
CalculatorKey { name: "key-divide", onclick: move |_| operator.set(Some(Operator::Div)) "÷" }
CalculatorKey { name: "key-multiply", onclick: move |_| operator.set(Some(Operator::Mul)) "×" }
CalculatorKey { name: "key-subtract", onclick: move |_| operator.set(Some(Operator::Sub)) "−" }
CalculatorKey { name: "key-add", onclick: move |_| operator.set(Some(Operator::Add)) "+" }
CalculatorKey { name: "key-equals", onclick: move |_| perform_operation() "=" }
}
rsx!(cx, div {
class: "calculator", onkeydown: {keydownhandler}
div { class: "calculator-display", "{formatted_display}" }
div { class: "input-keys"
div { class: "function-keys"
CalculatorKey { name: "key-clear", onclick: {clear_key} "{clear_text}" }
CalculatorKey { name: "key-sign", onclick: {toggle_sign}, "±"}
CalculatorKey { name: "key-percent", onclick: {toggle_percent} "%"}
}
div { class: "digit-keys"
CalculatorKey { name: "key-0", onclick: move |_| input_digit(0), "0" }
CalculatorKey { name: "key-dot", onclick: move |_| input_dot(), "●" }
{(1..9).map(|k| rsx!{
CalculatorKey { key: "{k}", name: "key-{k}", onclick: move |_| input_digit(k), "{k}" }
})}
}
div { class: "operator-keys"
CalculatorKey { name: "key-divide", onclick: move |_| operator.set(Some(Operator::Div)) "÷" }
CalculatorKey { name: "key-multiply", onclick: move |_| operator.set(Some(Operator::Mul)) "×" }
CalculatorKey { name: "key-subtract", onclick: move |_| operator.set(Some(Operator::Sub)) "−" }
CalculatorKey { name: "key-add", onclick: move |_| operator.set(Some(Operator::Add)) "+" }
CalculatorKey { name: "key-equals", onclick: move |_| perform_operation() "=" }
}
}
})
};
enum Operator {
Add,
Sub,
Mul,
Div,
}
#[derive(Props)]
struct CalculatorKeyProps<'a> {
/// Name!
name: &'static str,
/// Click!
onclick: &'a dyn Fn(MouseEvent),
}
fn CalculatorKey<'a>(cx: Context<'a>, props: &'a CalculatorKeyProps) -> DomTree<'a> {
cx.render(rsx! {
button {
class: "calculator-key {props.name}"
onclick: {props.onclick}
{cx.children()}
}
})
}
#[derive(Props, PartialEq)]
struct CalculatorDisplayProps {
val: f64,
}
fn CalculatorDisplay<'a>(cx: Context<'a>, props: &CalculatorDisplayProps) -> DomTree<'a> {
use separator::Separatable;
// Todo, add float support to the num-format crate
let formatted = props.val.separated_string();
// TODO: make it autoscaling with css
cx.render(rsx! {
div { class: "calculator-display"
"{formatted}"
}
rsx!(cx, button {
class: "calculator-key {props.name}"
onclick: {props.onclick}
{cx.children()}
})
}