Skip to content
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

Extending gir_ffi / gir_ffi-gtk - how to define GtkWidgetClass? [Solved] #279

Open
spchamp opened this issue Dec 17, 2021 · 2 comments
Open
Assignees

Comments

@spchamp
Copy link

spchamp commented Dec 17, 2021

Hello,

In further update: I think I've figured out the porting here, at least insofar as for using GtkWidgetClass in gir_ffi-gtk3. In some abbreviated documentation, the ported class (previously using Ruby-GNOME gems) would call one or more of the following methods, in a class scope:

  • self.object_class.set_template(bytes) or self.object_class.set_template_from_resource(bundled_resource_path)
  • self.object_class.bind_template_child_full(id, ...) and I think the next args would be 'true' and '0'. I'll need to check if that's portable though
  • something in lieu of .init, which is used under Ruby-GNOME - I've wrapped this into a class method, 'init_template' which makes the API just a little cleaner really
  • at some point, GirFFI.define_type(self) in a class scope

Beyond the particular usage of GtkWidgetClass here, I'm working on figuring out more of the porting. Perhaps once that much is settled in the application, I may be able to contribute some documentation for porting from Ruby-GNOME to gir_ffi-gtk3, e.g

  • inheriting from GObject::Object in lieu of Ruby-GNOME's GLib::Object
  • using a different set of initialization arguments to Gtk::Application, e.g via super. Presumably, those args are described in the GNOME devhelp(1) documentation
  • probably more than this

I'll try testing out the ported code, once the porting seems complete. I believe it's figured out though, and this support request is closed.

In previous update: The following was written before I'd been able to locate the implementation of Gtk::WidgetClass in gir_ffi-gtk. e.g

irb(main):002:0> Gtk::Widget.object_class
=> #<Gtk::WidgetClass:0x000055734e68c3d0 @struct=#<Gtk::WidgetClass::Struct:0x000055734e68c1a0>>

Although it may not show up immediately within the code completion under IRB after loading gir_ffk-gtk, there's also the following

irb(main):009:0> Gtk::Widget.object_class.class.instance_method(:set_template)
=> #<UnboundMethod: Gtk::WidgetClass#set_template(*args, &block) /home/gimbal/.local/share/gem/ruby/3.0.0/gems/gir_ffi-0.15.9/lib/gir_ffi/builders/registered_type_builder.rb:79>

Albeit, I'm not able to locate a type_register method for Gtk::WidgetClass or GObject::ObjectClass [Solved]

Would GObject::type_register_static provide the type_register call in this API? I believe that's a testable question [Solved: calling GirFFI.define_type(self)] will try that now ...

Notwithstanding any initial questions about how one might use use type_register_static if defining an extension class, in Ruby, onto GLib or GTK - such as for how one might create a glib type info structure for such usage? - I believe that the following is now N/A, not applicable, and should be a closed support request.

I'm afraid that I may have thought that the classes were not available, simply for if they were not showing up under any interactive name completion in IRB, after gir_ffi-gtk is loaded.

Perhaps not all of the classes are defined initially? Perhaps this may be related to why the 'require' call returns rather more quickly than with the Ruby-GNOME gtk3 API ....

I'll take a look at how to approach type_register for the project denoted below - presently taking a look at GirFFI::Builders::UserDefinedBuilder, and I see there's also GirFFI::Core::define_type, so I believe there's something to call from some prototype code - pursuant towards porting an application from Ruby-GNOME to gir_ffi*


Initial text (updated):

May there be any advice available for how to define GtkWidgetClass and related object mappings in gir_ffi/gir_ffi-gtk APIs onto GTK3?

I would like to define, for instance, the method bind_template_child_full such that can be used together with Gtk::Builder (in Ruby) onto the Gtk function gtk_buildable_get_internal_child when e.g creating a a widget class that derives its implementation from a Glade UI XML file.

After searching the project examples and tests for gir_ffi and gir_ffi-gtk, I'm afraid I can only guess that perhaps GtkWidgetClass (and related functions) may not have been declared in the original GIR files installed with the GNOME libraries locally, such that - if declared - it might have an implementation already available in Ruby. I'm afraid that my own guesswork, as such, then reaches its effective stack depth at the question of how to implement GtkWidgetClass in this API. So, I thought one might ask for advice about the implementation onto this API?

If it may help to lend any sense of context to this support request:

Albeit while I'm still fairly new to the Ruby language, I've been working on an application that uses GtkBuildable and GtkWidgetClass under the GNOME-Ruby GTK bindings. It's not a fully usable application, as yet, and the source code does not conform to any single style. I've yet to push it to a public repository, simply working on it locally. I would be willing to provide example code here, if it may help to clarify the question.

I'm interested in porting my application to use gir_ffi, as personally I like the approach used in gir_ffi and I believe there may be more of the GNOME APIs available under gir_ffi.

The application uses Glade UI XML files and makes some class-level and instance-level calls under GNOME-Ruby. For instance in class definitions, using Gtk::Widget::type_register, and Gtk::Widget::set_template (gtk_widget_class_set_template), as well as using an instance method Gtk::Widget#get_internal_child within an instance constructor. This is used in the project for e.g creating new application windows from a UI template definition in Glade XML, such that multiple application windows can then be created as instances of the the new widget class (in Ruby) with that widget class (an application window) being derived largely from the UI definition in a Glade XML file.

In this application, the Ruby-GNOME method Gtk::Widget::bind_template_child_full is then used during class initialization, to ensure that a UI object from the Glade XML file will be accessible -- via Gtk::Buildable -- within an instance method under the defined class, namely calling Gtk::Widget#get_internal_child there. This can be used for instance to access a widget within a custom application window class, e.g a tree view, then to populate the widget with signal handler callbacks and data. This methodology differs somewhat, compared to using only Gtk::Buildable. For instance, it requires that the Application Window will be defined in the Glade UI XML file as a template, such that the template will be loaded within the class definition in Ruby, at around the time of calling GLib's type_register.

I see that there is a Gtk::Buildable defined in gir_ffi-gtk3. As such, the method Gtk::Widget#get_internal_child is already available under gir_ffi-gtk3.

I've not been able to locate any implementation of the GTK functions gtk_widget_class_set_template and gtk_widget_class_bind_template_child_full under this API. I'm not certain of whether it may be as simple as to define GtkWidgetClass and those functions locally, if they are not already defined with what's been installed.

Presently, I can only think to search the source files of a GTK build, to see if GtkWidgetClass is simply being defined in the GIR source files, such that - if it had been defined in the GIR byte-wise database as installed - perhaps there would already be an implementation available in this API? There are alternately the GIR files published by gtk-rs, albeit not exactly the same as what's been installed locally. There is the following, under the Gtk-3.0 GIR XML in that project:

<record name="WidgetClass" c:type="GtkWidgetClass" glib:is-gtype-struct-for="Widget">

I'm not certain if GtkWidgetClass is being declared under the GIR registry, locally - assuming it would have been provided with an implementation under gir_ffi-gtk3 in Ruby, if it had been declared?

Towards implementing this Gtk class undedr gir_ffi and gir_ffi-gtk: If there is a struct type GtkWidgetClass, would it be sufficient to define that type under gir_ffi, and then to define functions on that type? This is only a guess, of course, certainly nothing as complete as a patch with test files lol.

Thanks for any advice. I look forward to making use of this API, and to see how it works out on FreeBSD - testing under Arch Linux, presently. I'll try to work out a patch, meanwhile.

In update: Taking a look at how GtkWidgetClass has been approached under GNOME-Ruby, there is rbgtk-buildable.c under the Ruby-GNOME gtk3-no-gi gem. Assuming that the no-gi suffix may indicate that it's not using GIR, and seeing that there is an implementation presumably using GIR under the Ruby-GNOME gtk3 gem, I'm not certain why there's not a similar class and the methods for that class, showing up as available under the FFI binding here.

Maybe there's a module I've missed gir_ffi-gtk3? I'll continue trying to work out how to port the application, at this.

Health, all,
-- Sean

@spchamp spchamp changed the title Extending gir_ffi / gir_ffi-gtk - how to define GtkWidgetClass? Extending gir_ffi / gir_ffi-gtk - how to define GtkWidgetClass? [Solved] Dec 18, 2021
@mvz
Copy link
Owner

mvz commented Dec 18, 2021

Thanks for your detailed report, @spchamp. It made me realize that, at the very least, GirFFI needs better documentation.

I may be able to contribute some documentation for porting from Ruby-GNOME to gir_ffi-gtk3

I would appreciate that very much.

Perhaps not all of the classes are defined initially?

That is correct. A class will be loaded once the code attempts to access it. This uses the const_missing? method.

@mvz mvz self-assigned this Dec 18, 2021
@rubyFeedback
Copy link

Heya spchamp,

Could you also post the working examples somewhere? I would
love to learn from it. I found it easier to work on existing code that
works - that way I make fewer mistakes myself. I am an expert
copy/paster, StackOverflow trained 3.0! :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants