Still watching, but I was confused at first because I thought “Counter example in druid” meant it was a counterexample to show why a new approach was needed (and I thought that was funny, because it looked very reasonable), but it was actually an example of a counter. :-D
Playing around with this declarative ui thing using v9 ideas/the One Name Rule:
let mut window = Window::new("Hi");
// Window holds the app's state.
// You want as many discrete objects as possible.
struct Count {
n: i32,
}
window.register(Count { n: 0 });
let button = window.add::<Button>();
let label: Id<Label> = window.add::<Label>();
// Same as (PhantomData<W>, u64)
window.on(event::Press(button), |count: &mut Count| {
count.n += 1
// The mutable reference means that the Count object may have changed.
// So any dependencies will need to be updated.
});
window.set0(label, |widget: &mut Label, count: &Count| {
// This closure uses &Count, so we infer `label` to be a dependency.
widget.text = format!("Count: {}", count.n);
});
window.set1(label, |count: &Count| -> String {
// We can do this better.
// &mut Label is very broad, so instead of modifying the entire object,
// we could modify just one particular sub-object.
// `Label` implements a trait that allows it to handle `String` objects being thrown at it.
format!("Count: {}", count.n)
});
window.set2(label, |text: &mut String, count: &Count| {
// We could modify the sub-object by reference; not allocating is nice.
text.clear();
write!(text, "Count: {}", count.n);
});
// It's also acceptable to have a 0-argument closure.
window.set3(button, || String::from("Increment"));
// It doesn't need to be a closure, and it doesn't need to be a String.
// (These sorts of niceties would be specially provided by Widgets.)
window.set4(button, "Increment");
// (These set functions could all be overloaded to just `set`, but maybe not both set0 and set2.)
window.run();
Interesting ideas, I want to look into this more closely. How would you describe the advantages and disadvantages of this approach as opposed to what druid does?
IIUC druid must diff everything. This could be pretty bad for something like MS Word, where you’ve got a lot of state on screen, and the user is typing events at a rapid pace. With this other approach, the system can see more specifically what you’re changing. It could still run a diff, on a much smaller state, or just not bother & update always. With this setup the flow of control becomes less obvious, and there’s the possibility of an endless loop if diffing isn’t done.
It diffs from the top of the tree, but absolutely doesn’t need to touch all state while diffing. This is what the lenses and immutable data structures are about - they should be able to deliver a fine grained delta (at modest cost, usually O(log n)) when not much has changed. But we don’t know yet just how well this will work.
In any case, I think it’s possible to build a UI more along the lines you suggest, and I would like to understand better how that would work.
Still watching, but I was confused at first because I thought “Counter example in druid” meant it was a counterexample to show why a new approach was needed (and I thought that was funny, because it looked very reasonable), but it was actually an example of a counter. :-D
Playing around with this declarative ui thing using v9 ideas/the One Name Rule:
Interesting ideas, I want to look into this more closely. How would you describe the advantages and disadvantages of this approach as opposed to what druid does?
IIUC druid must diff everything. This could be pretty bad for something like MS Word, where you’ve got a lot of state on screen, and the user is typing events at a rapid pace. With this other approach, the system can see more specifically what you’re changing. It could still run a diff, on a much smaller state, or just not bother & update always. With this setup the flow of control becomes less obvious, and there’s the possibility of an endless loop if diffing isn’t done.
It diffs from the top of the tree, but absolutely doesn’t need to touch all state while diffing. This is what the lenses and immutable data structures are about - they should be able to deliver a fine grained delta (at modest cost, usually O(log n)) when not much has changed. But we don’t know yet just how well this will work.
In any case, I think it’s possible to build a UI more along the lines you suggest, and I would like to understand better how that would work.