Support to declare GObject properties
hugopl opened this issue · 3 comments
This is meant to be a discussion about the implementation of user declared GObject properties.
IMO it must be as transparent as possible, i.e. a property
/setter
/getter
macro on GObject, overwriting the original Crystal Object macros.
class Foo < GObject::Object
# Creates a read/write GObject property
property foo : Int32
# Creates a read only GObject property
getter bar : Int32
# Creates a write only GObject property
setter moo : Int32
# Prop with blurb
property hey : String, blurb: "I'm the property blurb"
# Prop with cusom nick
property nicked : String, nick: "Nickey"
end
The nick can be the name.titleize, or custom. Blurb could be default to name.titleize too
These macros would create the variables on Crystal world, so people could use @foo
to read foo
property without overhead.
A possible implementation for this would be the macro generate something like
@[GObject::Property(blurb: "Prop blurb"]
@foo : String
So a finalize macro would catch all instance variables with this annotation and generate the set_property/get_property methods plus the class_init that register the properties.
I didn't test this yet, but if it works we could use the same schema to vfuncs, to avoid the bug that forbid a method starting with do_
to be declared if no vfuncs with that name exists, so instead vfuncs can just be:
@[GObject::VFunc]
def do_whatever
# or
@[GObject::VFunc(name: :whatever)]
def whatever_name
But this is another subject 😁
Back to properties... other options for properties can also be added as extra parameters in the macro, e.g.:
property foo : Int32, min: 0, max: 32
Not all crystal properties can be mapped to GObject properties, therefore I would suggest using an annotation, raising an error if there is no equivalent gtype.
Also, there are modules using the getter, setter, property macros so I think we should put blurb, nick and additional arguments into the annotation.
Example:
@[GObject::Property(min: 10, max: 20, access: :read)]
@some_int : Int32
@[GObject::Property(default: -1, blurb: "this is unused")]
property something : UInt64
We still have to override the setter/getter/property macros to emit a notify signal on property change.
I'm already working on an implementation, there I just looped over the instance vars using {% for Ivar in @type.instance_vars %}
and only generated a GObject property where the annotation is set.
Not all crystal properties can be mapped to GObject properties, therefore I would suggest using an annotation, raising an error if there is no equivalent gtype.
It's true, better just use the annotation so, and if the annotation is going to be explicit used, better put the property options there.
And I think we don't need to care about constructor-only properties.