-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Connecting to the 'draw' signal #39
Comments
I'm blocked on this problem as well. The code is generated in https://github.com/bodil/vgtk/blob/master/macros/src/gtk.rs#L273-L288. I'm not sure how to deduce the type, but I'm going to see if I can come up with something today. |
So I feel like this should work, but it doesn't: let inhibit = if body_string.contains("Inhibit(true)") {
quote!(vgtk::lib::glib::signal::Inhibit(true))
} else if body_string.contains("Inhibit(false)") {
quote!(vgtk::lib::glib::signal::Inhibit(false))
} else {
quote!()
};
let inner_block = if async_keyword.is_some() {
quote!({
let scope = scope.clone();
vgtk::lib::glib::MainContext::ref_thread_default().spawn_local(
async move {
let msg = async move { #body_s }.await;
scope.send_message(msg);
#inhibit
}
)
})
} else {
quote!({
let msg = { #body_s };
scope.send_message(msg);
#inhibit
})
}; It still complains about the same thing, although |
Maybe another idea would be to allow returning a tuple with the message type and the callback's return type? I'm not sure offhand though if there are any other GTK callbacks with return types other than |
I'm honestly not sure this is a problem that can be solved at all in a straightforward way. The tuple return value sounds compelling, but I'm not sure it's going to be possible to implement - I imagine it would require some creative use of the |
The Tuple return value was a great idea! I was able to get it working by deconstructing the result of In gtk.rs: let inner_block = if async_keyword.is_some() {
quote!({
let scope = scope.clone();
vgtk::lib::glib::MainContext::ref_thread_default().spawn_local(
async move {
let (msg, ret) = async move { #body_s }.await;
scope.send_message(msg);
ret
}
)
})
} else {
quote!({
let (msg, ret) = { #body_s };
scope.send_message(msg);
ret
})
}; Used like so: <Application::new_unwrap(Some("example.signal.app"), ApplicationFlags::empty())>
<Window on destroy=|_| (Message::Exit, ())>
<DrawingArea on draw=|_,_| (Message::NoOp, Inhibit(false)) />
</Window>
</Application> This needs some more work to work with custom components though. The |
To complicate things even further: |
Hey there, I just tried the fork of marhkb, by adding a I would love to use vgtk in my next project, but this issue keeps me hesitating. |
I have found a potential workaround for this problem. <Layout on realize=|l| { l.connect_draw(draw_layout); Message::None } /> I just added a dummy message because the update function isn't supposed to do anything with it I think. I think the downside of this is that the draw callback can't send a message to the update function. So the procedural Cairo drawing code will just live in its own little bubble. Coming to think of it, it also can't access the state, which makes it kind of useless beyond drawing hello world? |
If I understand the solution by @LiHRaM correctly, that would require all signals to return a tuple, which is a breaking change and kinda inconvenient when most return
Could you clarify what is the problem here? Trying to look into it now. I came up with a conversion trait and a blanket implementation that lets you return your Message type, and implement this trait to tell how your message type maps to I think this does not need special handling int subcomponents, since a subcomponent is never going to require returning an |
I hacked together a syntax addition to solve this issue for myself a while ago (and to learn more about lalrpop): duvholt@620ca4f Return values from handlers can be specified like this: I don't really remember why I went with |
Oooh! I was completely unaware of lalrpop. I guess that explains some of the macro magic. I'll look into that, thanks. In terms of actually solving this issue, what do you think of the different solutions so far? Any downsides to my trait compared to your macro syntax? I think I mostly agree with Bodil that it'd be good to minimize special syntax. It makes things less complex and less surprising. |
Okay, I merged my solution, but will keep this issue open for using the draw signal to do anything useful.
I'm kinda thinking of adding a new API to I guess the dream would be a JSX SVG vgtk kinda thing, but that might be out of my league for now. Anything that allows me to draw things based on my model would be nice. |
Hey @pepijndevos, have you tried |
The
The macro would have to be expanded to allow |
Seems like.
I tried it on a small example on a slider that I had locally and it worked. The compiler only wanted to know the parameter type for the callback, so you will be required to add it. |
I started adding a handlers.push(VHandler {
name: "clicked",
id: "#0 bytes(1331..1332)",
set: std::boxed::Box::new(
move |object: &vgtk::lib::glib::Object, scope: &Scope<_>| {
use vgtk::lib::glib::object::Cast;
let object: &Button =
object.downcast_ref().unwrap_or_else(|| {
::std::rt::begin_panic_fmt(
&::core::fmt::Arguments::new_v1(
&[
"downcast to ",
" failed in signal setter",
],
&match (&Button::static_type(),) {
(arg0,) => {
[::core::fmt::ArgumentV1::new(
arg0,
::core::fmt::Debug::fmt,
)]
}
},
),
)
});
let scope: Scope<_> = scope.clone();
object.connect_clicked(move |_| {
let msg = { Message::Inc };
scope.send_message(msg);
})
},
),
}); So why does it work to define your own While looking into that I ran into this proc-macro-hack stuff that I don't understand, and from there found that it is superseded by native support for whatever it was doing. But so far I've been unsuccessful in untangling this mess to get rid of it. |
For https://gtk-rs.org/docs/gtk/trait.WidgetExt.html#tymethod.connect_draw the callback is expected to return
Inhibit
instead of nothing, which causes issues since the provided callback is expected to return aMessage
type and is wrapped in another function that always returns()
To reproduce, add
<DrawingArea on draw=|w, c| Message::Exit />
to the UI inexamples/inc/src/main.rs
The text was updated successfully, but these errors were encountered: