gtk-rs-core
gtk-rs-core copied to clipboard
[FEATURE REQUEST] Events as streams
Rust has great support for iterators, so I thought... Why not use them for event handling?
Also, the current callback situation is a pain when dealing with async methods, because the user has to spawn a future each time.
Providing a stream (which is async by conception) should provide a better API. With a stream API, the user doesn't have to worry about spawning the future. The spawning part is already handled by the Stream
methods.
Example of API usage with my proposal:
button.ev_clicked().1
.zip(0..)
.then(|_, n| fetch_page(n))
.map(|p| println!("Page content: {}", p));
API proposal:
fn connect_clicked() -> SignalHandlerId;
// For each `connect_*` method there's a corresponding `ev_*` method.
// calling `ev_clicked()` connects to the event and provides a stream.
fn ev_clicked() -> (SignalHandlerId, Stream<EventData>);
Alternative, realistic solution
I do understand creating a corresponding ev_*()
for each event is asking a bit too much.
As an alternative, we could provide a macro to transform a connect_*
method to an ev_*
method.
Imagine having a macro like this:
let (signal_id, stream) = event_stream!(button.connect_clicked);
Would you accept a PR introducing this event_stream!
macro?
I would prefer to experiment with such API first by having it implemented on top of the bindings externally. If that indeed turns out to be useable and an improvement, then we can consider including such API.
You might also want to take a look at relm btw.
By the way, if anyone is interested, I've created a crate to do this: https://github.com/ranfdev/ev-stream-gtk-rs.
That's nice. Do you have an example application making use of this, ideally even with a comparison to the same thing with callbacks?
Back when I found your futures post I was really hoping this would exist.
Since I wanted async signals and didn't find anything (I had come across the above link pretty late!), I also rolled my own (specifically, I wanted it for describing wp bindings). I took the approach of using traits instead of macros though (aside from a macro for simplifying trait boilerplate), so it can also cover #214 . The generics do get messy around closures unfortunately, mostly because rust still doesn't have proper Fn traits :disappointed: