Comments (7)
New proposal:
type Gadget struct {
gtk.Widget
Child gtk.Widgetter `glib:"child,Construct,ConstructOnly"`
}
var gadgetType = glib.RegisterSubclass[*Gadget](
glib.WithParamSpecs([]glib.ParamSpec{
// TODO
}),
)
func NewGadget(child gtk.Widgetter) *Gadget {
return gadgetType.NewWithProperties(map[string]any{
"child": child,
})
}
from gotk4.
Update: subclassing is now on the main branch. Things might be very unstable; please report bugs and crashes to issues.
A release will be made that points to the last working pre-subclassing commit, just to mitigate this potential instability.
from gotk4.
Generate these:
// OverrideWidget creates a new Widget from the given overrider.
func OverrideWidget(overrider WidgetOverrider) Widget {
obj := externglib.Register(externglib.Type(C.gtk_widget_get_type()), overrider)
return wrapWidget(obj)
}
To implement a new widget, the user can do this to subclass a widget:
type Widget struct {
gtk.Widget // ours
label *gtk.Label // theirs
}
// Note that we're making methods that implement Overrider. The actual
// Widget instance MIGHT NOT implement this.
var _ gtk.WidgetOverrider = (*Widget)(nil)
func NewWidget(label string) *Widget {
w := Widget{
label: gtk.NewLabel(label),
}
w.Widget = gtk.OverrideWidget(w)
return &w
}
func (w *Widget) Snapshot(s *gtk.Snapshot) {}
And they can use it like so:
w := NewWidget("Hello, world!")
b := gtk.NewBox(gtk.OrientationVertical, 0)
b.Append(w)
Or they can do this to implement an abstract class or interface:
type HTTPMedia struct {
gtk.MediaStream
}
func NewHTTPMedia() gtk.MediaStreamer {
h := HTTPMedia{}
h.MediaStream = gtk.OverrideMediaStreamer(&h)
return &h
}
func (h *HTTPMedia) Pause() {}
func (h *HTTPMedia) Play() {}
It might be worth it to make glib.Object work for both C and Go objects,
though. The user will no longer need to embed glib.GoObject if so.
If this is the case (and the examples are already applied as such), then
OverrideX functions will rely on glib.Object's specific methods to determine
if it's a C or Go object.
It is important to note that the Object's implementation for Go
subclassing/implementing will have to check that the Object instance isn't
already a valid C instance. Once the check passes, it can then create a new
Object and swap that in place.
It might be quite troublesome for a Go GObject class to extend another Go class,
because at that point, it wouldn't be dealing with just abstract classes
anymore, rather actual classes. This is basically dealing with inheritance,
which might not be a good idea.
Since GTK4 is shifting from the inheritance paradigm to a more composition-like
one, it might not be worth the effort to consider this in the implementation.
The user is expected to create a struct
that implements the overrider for each
layer, anyway.
For example, if someone makes a Window struct
that implements
WidgetOverrider
, and someone else wants to "extend" it, then that user is
expected to rewrite all the methods. Of course, Go's struct embedding will help
save some of that work, however, so it should just work normally. It's worth
noting that by going with this approach, each layer will have to create a new
GObject
on the C side, each with its own GType
.
The code will look roughly like this:
type OtherWidget struct {
Widget
box *gtk.Box
}
func NewOtherWidget() *OtherWidget {
w := OtherWidget{
Widget: NewWidget("Hello, world!"),
box: gtk.NewBox(),
}
w.Widget.Widget = gtk.OverrideWidget(&w)
return &w
}
The only quirk with this method is that it requires the caller to manually dive
down the embedding tree to override the inner widget instance while throwing
away the old Widget's internal object. This isn't very ideal. It could also be
the reason that doing code in Init()
would be a better idea.
Maybe externglib.Register
could recognize the previous Object allocated and
reuse that instead of creating a new one. It might not always be possible,
though.
There's also the issue of registering for signals. As for properties, it can
probably be done like this:
// NewOtherWidget...
w.AddProperties(map[string]interface{}{
"fold": false,
})
Old Draft:
Note that for all types that the user can override/implement, the methods
and functions will always take in an interface type, e.g. Widgetter. This
means that the functions will always check if the type is an Object or a
GoObject. In both cases, the type is expected to implement the entire
interface.
Also note that there's no need for the user to implement Init, Dispose and
Finalize. Those methods are only there so the user can use it, but there's
not really a good reason to do so. Objects that are inside the struct are
all GC'd in undefined order, which doesn't really matter, since by the time
they need to be finalized by the GC, everything wouldn't have been
referenced anymore.
Also note that NewClass will basically register a new GType, and that's it.
It should be a fairly cheap call, since sync.Map can prove to be very cheap
after a while, and we're only ever growing that map.
The map will probably be a reflect.Type to a GType map. It'll basically
provide type interning similar to GLib while abstracting the Type method
away from the user nicely.
The Register function will definitely need a valid GoObject instance, though
note that the user didn't have to construct the type. As long as we have a
valid zero-value of it, we can easily do that ourselves in Register. This
means the user will not have to do any heavy-lifting.
from gotk4.
Created the subclassing
branch to keep track of this.
from gotk4.
As for properties, it can
probably be done like this:
This API doesn't work. The properties have to be set during construction of the
object as well.
Perhaps this might:
func OverrideWidget(w gtk.WidgetOverrider, opts ...glib.ObjectOptions)
gtk.OverrideWidget(w, glib.WithProperties{
"fold": false,
})
from gotk4.
See ./gtype.c:4115
g_type_check_instance_cast
and ``G_TYPE_CIC`.
from gotk4.
Crashing with
2022/12/20 05:18:46 Critical: GLib-GObject: validate_and_install_class_property: assertion 'class->set_property != NULL' failed
2022/12/20 05:18:46 Critical: GLib-GObject: g_object_new_is_valid_property: object class 'AdaptiveFold' has no property named 'position'
This could be gotk4 not calling parent class initializers.
from gotk4.
Related Issues (20)
- Why go4.org/unsafe/assume-no-moving-gc ? HOT 4
- gir-generate failed to decode gir XML HOT 4
- Gstreamer bindings HOT 17
- Generator Workflow HOT 2
- Unusable GtkBuilderCScope API
- Memory is not freed when destroying Window HOT 1
- `DropTarget` panics when calling the `"drop"` signal handler HOT 10
- Bring back Unref methods
- Switch intern to KarpelesLab/weak
- why build time so slow? HOT 1
- run gtk4/simple get error
- Composite templates HOT 2
- SearchEntry does not appear to implement Editable interface correctly HOT 3
- Support binding Go objects to GObjects with `GObject.set_qdata`
- How to use GTK 4 GridView with gio.ListStore and gtk.BuilderListItemFactory HOT 2
- pkg-config not working from cgo in snap HOT 7
- gotk4 ApplicationWindow does not show after Hide()
- ASSUME_NO_MOVING_GC_UNSAFE_RISK_IT_WITH HOT 2
- Video Streaming HOT 26
- Custom glib.LogSetWriter HOT 8
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from gotk4.