I wonder how event handling will look in whatever rust gui library wins out.
What API alternatives are there to callbacks for widgets that may signal multiple events? One object would be to pass some implementation of some “Events” trait which would have methods to be called for each event kind. This is basically callbacks (I don’t think rust offers a way to make inline trait implementations and I don’t know if there’s a way to implicitly have default implementations that do nothing). This feels similar to in Java where you might subclass Button (I think. It’s been a while since I looked at any Java at all, let alone gui code).
One way to deal with events is a more imgui-like api where you write e.g.
if (make_button("click me")) {
/* just been clicked */
}
But I don’t see how this would work for lots of events (one option would be to have the return value be e.g. ButtonEvent option where the ButtonEvent type is an enum of all possible events a button may signal but there isn’t sub typing for variants so you either need lots of similar types for different controls and lots of pointless conversions or the types say that a control may signal events which it in fact never does. Also it may be possible to have multiple events hit a widget in a frame (eg mouseEnter, mouseMove; focus, mouseDown; mouseUp, click) so the option should be a sequence and you lose the ability to use “if let” when making the controls). A second issue is that this seems likely to add a frame of latency in many cases (eg if you have a wizard with a “next” buttons then you get the mouse event for the button being clicked by rerendering the dram as-is, and then on the next render you get to do the next page).
Perhaps I should just look at the code to see what Druid and crochet do.
We're still figuring this out, a discussion on the #crochet stream in our Zulip today is on this very topic. At a very high level though, many events (mouse movement, keyboard, etc) are handled by widgets, not by app logic, and those are dispatched to the widget by the toolkit calling into the widget Trait's `event` method. The idea that a button is clicked is different, we tend to call that an "action" rather than an event. In current Druid, it's a callback which is given access to mutable app state (often through a lens). In Crochet, it's placed in an "action queue" and the app logic is rerun when the queue is nonempty, then everything is rendered after the app logic has had a chance to make its mutations to the view tree.
We don't have the one frame latency, as it's not imgui under the hood. (There's a bug in the Crochet prototype on this, but it's known and will be fixed).
What about drag gesture? I.e. if you want to enable a particular widgets such as image display / text box to be draggable? How the event should be passed in and handled?
These gestures seems not internal to the widgets, but also mutate the widgets state in one way or another and need some abstraction to handle the common behavior.
Something tells me that you will end up in HTML/CSS/DOM and bubbling/sinking event propagation schema (used in browsers) as the most flexible one, see: https://en.wikipedia.org/wiki/Event_bubbling
I did quite a lot of different attempts to GUI Holy Grail in last 20 years ( https://sciter.com/10-years-road-to-sciter/ ) . I am pretty confident that DOM and DOM events is the most flexible (and so robust) foundation so far.
The problem is that to make it flexible in a way that allows for GUI construction blocks, with Rust one would end up with Rc<RefCell<>> everywhere, like it happens in Gtk-rs.
Is that all that bad of a thing? You could combine them into a single type, which then becomes a type marker for "is / related to a UI element" and perhaps more palatable to type.
Plenty, decrease in productivity, basically back to Objective-C before GC/ARC, or doing COM in C, lack of support in GUI designers that need to always map to the same types, and building on top of that a big attrition for component libraries.
Not sure if I'm missing something, but how does Rc<RefCell<...>> equate to "objective-c before gc/arc"? It seems roughly equivalent, in the same way that smart pointers are roughly equivalent: the lifetime is inferred by use, and retaining cycles are a problem. Arc could be a little bit more efficient (which does matter in some ui work), but I don't see how it'd change the use of a framework, and iOS and OSX devs have used objc with arc for years successfully and often happily.
What API alternatives are there to callbacks for widgets that may signal multiple events? One object would be to pass some implementation of some “Events” trait which would have methods to be called for each event kind. This is basically callbacks (I don’t think rust offers a way to make inline trait implementations and I don’t know if there’s a way to implicitly have default implementations that do nothing). This feels similar to in Java where you might subclass Button (I think. It’s been a while since I looked at any Java at all, let alone gui code).
One way to deal with events is a more imgui-like api where you write e.g.
But I don’t see how this would work for lots of events (one option would be to have the return value be e.g. ButtonEvent option where the ButtonEvent type is an enum of all possible events a button may signal but there isn’t sub typing for variants so you either need lots of similar types for different controls and lots of pointless conversions or the types say that a control may signal events which it in fact never does. Also it may be possible to have multiple events hit a widget in a frame (eg mouseEnter, mouseMove; focus, mouseDown; mouseUp, click) so the option should be a sequence and you lose the ability to use “if let” when making the controls). A second issue is that this seems likely to add a frame of latency in many cases (eg if you have a wizard with a “next” buttons then you get the mouse event for the button being clicked by rerendering the dram as-is, and then on the next render you get to do the next page).Perhaps I should just look at the code to see what Druid and crochet do.