cushy/examples/todo.rs
Jonathan Johnson 3f8885efbe
Callback handles are now managed
Installing a callback now returns a CallbackHandle. All map-style APIs
install this handle automatically on the created dynamic, which keeps
the callback installed until the dynamic is freed. All other APIs
return the handle for the caller to either call persist() or store
somewhere.

Now, the dynamic system can be used for application-long data with
almost no fear of leaking data due to how callbacks are being installed.
Technically cycles are still possible by moving clones into the
callbacks, so a WeakDynamic type might be worth exposing.
2023-12-01 13:31:42 -08:00

62 lines
1.7 KiB
Rust

use gooey::value::Dynamic;
use gooey::widget::{Children, MakeWidget, WidgetInstance};
use gooey::widgets::input::InputValue;
use gooey::widgets::{Button, Label, Scroll, Stack};
use gooey::Run;
fn main() -> gooey::Result {
let tasks = Dynamic::default();
let children = Dynamic::default();
tasks
.for_each(children.with_clone(|children| {
move |tasks: &Vec<Task>| {
update_task_widgets(tasks, &mut children.lock());
}
}))
.persist();
let task_text = Dynamic::default();
let valid = task_text.map_each(|text: &String| !text.is_empty());
let task_form = Stack::columns(
task_text.clone().into_input().expand().and(
Button::new("Add Task")
.on_click(move |_| {
tasks.lock().push(Task::new(task_text.take()));
})
.into_default()
.with_enabled(valid),
),
);
let tasks = Scroll::vertical(Stack::rows(children));
Stack::rows(task_form.and(tasks)).expand().run()
}
struct Task {
widget: WidgetInstance,
}
impl Task {
pub fn new(text: String) -> Self {
let widget = Label::new(Dynamic::new(text)).align_left().make_widget();
Self { widget }
}
}
fn update_task_widgets(tasks: &[Task], children: &mut Children) {
'tasks: for (index, task) in tasks.iter().enumerate() {
for child in index..children.len() {
if children[child].id() == task.widget.id() {
if child != index {
children.swap(child, index);
}
continue 'tasks;
}
}
children.insert(index, task.widget.clone());
}
children.truncate(tasks.len());
}