-
-
Notifications
You must be signed in to change notification settings - Fork 75
Missing documentation/examples for subclassing & few questions #279
Comments
Sorry for the late reply, I missed the github notification for this or didn't get one :)
I have that on my list, going through an example step by step. But my todo list is overflowing :) I have some tutorial-style stuff here for GStreamer: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/tree/master/gst-plugin-tutorial . The GObject parts of it also apply to GTK and anything else. Maybe that helps a bit for the time being. Note that all these don't really need the
There are 4 parts to the GObject here from a Rust point of view
I saw a crate for such an But I agree that we should find a nicer pattern here. The problem is mostly that in C you would always use And we can't unfortunately create most fields during creation of the private struct (1. above) because you most likely need access too the actual GObject (i.e. the
Not supported yet but from what I saw it's not difficult to add support for that. Someone who needs it and actually uses GTK will have to take a look at that at some point :) If you have any questions for the GObject-side of things there I'd be happy to help.
You can declare properties on your GObject and then pass values for these properties to During object construction then your
Not much, it's only needed because of macro hygiene.
Yes, can you create an issue for that? :) |
Oh I missed this part of your questions (did I miss anything else?). |
Thanks for the very helpful answer @sdroege ! I'll continue to implement subclassing in Shortwave, and will submit a more basic subclassing example to this repository soon. IMO a common use case is just subclassing a simple |
I was asking about the subclassing mechanism in the Matrix channel, and this issue was linked. The answer by @sdroege was very helpful, however I still had a few questions. I was asked to put them here so this issue could be used as a source for new documentation.
|
I have an example here https://github.com/sdroege/gobject-example-rs . You almost never want a custom
It's mapping (in this case) directly to the The
How would you create it directly? The only way to create a new GObject instance is via
Initialization order: You have to use You can call
You probably don't want the fields in your private struct to be public but if anything only some functions. Also not every virtual method directly maps to public functions on the type so there are quite a few that couldn't be directly called like this (or would misbehave at least). The difference between the two is that the private struct is the private state of your type's implementation, while the public one (the one generated by
I think that's answered above already. But conceptually the main reason would be encapsulation and protection of your state and its invariants.
Because Also from macros you can't look into trait implementations (macros are expanded before anything related to types is happening in the compiler), so even then the macro couldn't get the
For the same reason as above, but especially because of the type limitations of macros. The macro has to generate trait impls for each of the types in the class hierarchy but there's no way for a macro to know them as the compiler would only do anything related to types after the macros are expanded. Macros work on the syntax level, not the semantic level.
Same as above really. But for types declared e.g. by C libraries you would list in Most of this could be hidden away by having a complex procedural macro that would allow you to define new GObjects in some kind of DSL, but that requires someone to do that work first :) You could imagine some kind of |
Thanks, the explanations are very helpful for understanding how all of this works!
Something like this would be very helpful as a tutorial, especially with some kind of index (what example demonstrates what) and more thorough comments.
Is this some kind of override of a virtual
Oh, so it's a particularity of how GObject object creation works.
So in theory you could implement a more-Rusty "new with arguments" construction by passing the arguments via CONSTRUCT_ONLY properties and then calling the user-provided
I still don't quite understand. Couldn't I have just the private struct, with the same safe public methods as generated by
Perhaps this is close to what I'm imagining about how this should work. 😀 |
It's done by the Or do you mean something else?
No, because in If you initialize your struct fields with
The struct defined by Also note that the instance struct is always public, even if you mark your fields not Another reason for having two structs is to force a clean separation between implementation and public interface and not accidentally leak implementation details. |
I mean instead of writing match fn {
get_type => || SimpleWindowPrivate::get_type().to_glib(),
} you would write some kind of impl RequiredGLibWrapperFunctions for SimpleWindow {
fn get_type() -> glib::types::Type {
SimpleWindowPrivate::get_type()
}
}
My idea there was that this |
That doesn't work because the
That's certainly possible, yes. It would need some more higher-level API on top of what we have right now. |
I started to play with subclassing gtk-rs widgets. It took me a while, to understand few basic things. In my opinion we need more examples, or at least a more basic one with more explanations.
As a starter I had following questions:
ExampleObjectPrivate
and aExampleObject
structglib_wrapper!
macroExampleObject
struct stuff from theExampleObjectPrivate
structNow I managed to subclass my first widget. It resulted into this:
https://gitlab.gnome.org/World/Shortwave/commit/4a4e2442f9c15f92b5a2ea32c5eb0d874496793f
Now I wonder...
glib_wrapper!
macro turns it into a gtk-rs like usable object. But what's the object, before I wrap it? Is it a FFI-like object?OnceCell
s? Since I cannot initialize mySongRow
directly anymore, so I have to use a Cell or something as placeholder. The annoying thing is now, that I have to use.get().unwrap()
everytime, if I want to access one of the struct variables. I wonder if something likeOption
exists, but without having tounwrap()
it every time.https://gitlab.gnome.org/World/Shortwave/blob/master/src/ui/song_row.rs#L15
<template class="ExampleBox" parent="GtkBox">
) with subclassing (like as it is possible in Vala)? Example of composite template #275new()
, so I can initialize my struct directly? Like I have done it before: https://gitlab.gnome.org/World/Shortwave/blob/bf8e4a7d2bad3ec1412f0b2c4968f291bfe4a536/src/ui/song_row.rs#L30SongRowClass
field? It seems that I can enter here whatever I want.https://gitlab.gnome.org/World/Shortwave/blob/master/src/ui/song_row.rs#L50
I'm refering to this example:
https://github.com/gtk-rs/examples/blob/master/src/bin/basic_subclass.rs
And BTW, there's an issue with it:
Shouldn't be it
SimpleWindow
instead of theSimpleWindowPrivate
in the inspector?To be fair, I should admit that I have no knowledge with handling gobject boilerplate manually (Thanks Vala 😄 ), so I might missing few bits.
As soon as I understand everything correctly, I want to submit one more basic example for subclassing (like just subclassing a simple
gtk::Box
with more explanations)The text was updated successfully, but these errors were encountered: