jhass / crystal-gobject

gobject-introspection for Crystal
BSD 3-Clause "New" or "Revised" License
127 stars 13 forks source link

How to explore methods of Gtk? #39

Closed Calamari closed 4 years ago

Calamari commented 4 years ago

This is probably a noob question, so I admit I am pretty unfamiliar with Gtk and relatively new in Crystal. But I think the former is great to get a real app build and the latter is just a breeze to write. So here come the question:

How is the best way to find out, what classes are available and how the methods are called on them? I am reading the GTK docs and also found great course material about TextView but they explain and describe the C code.

An example: Making a GTK TextView object editable seems to be done in C using

gtk_text_view_set_editable (text_view, true);

But to do this in Crystal I have to do this:

gtk_text_view_set_editable (text_view, true);

And how gtk_text_buffer_get_iter_at_line(…) translates to Crystal I have no clue, cannot find a similar method on the Gtk::TextBuffer instance. For this I use a macro that prints out all methods of a class.

So, what transformations are done with all the classes and methods? How do the C code translate to Crystal code? How is the best way to explore it? I somehow cannot really read it from the code in this Repo, so it seems still magic to me. :)

I appreciate a hint where to look and I strongly appreciate this Library and the work you put into it. Great stuff. Also, the examples also helped a bit (although the CSS example does not work for me, but that's probably another story I can figure out, when I know how to figure stuff out...)

So: Thanks again and in advance :+1:

jhass commented 4 years ago

I guess you mean text_view.editable = true in the second example and just did a copy paste error :)

If you have a lot of patience, there's an experimental documentation generator which you can run by cloning this repository, running shards build inside and then bin/gi-doc Gtk for example. Building will take some time since it actually builds half of the Crystal compiler and then doc generation will take even longer and generate about a gigabyte of documentation.

But that'll just be a little bit more convenient for looking at the generated API than you macro. Crossreferencing with the C API docs and examples and taking a look at the samples in this repo like you've been doing is the way to go for now.

Another trick is piping the generator output to a file and searching through that, crystal src/generator/build_namespace.cr -- Gtk > gtk.cr for example (or lib/gobject/src/generator/build_namespace.cr from a depending shard).

Currently there's basically no hand-written Crystalish convenience wrappers around the C API, so a lot of things will still feel kind of alien. For gtk_text_buffer_get_iter_at_line I would expect something like

iter = Gtk::TextIter.new
text_buffer.iter_at_line(iter, 23)

to do something, from a quick look at the generated API. If you have some minimal example code that's maybe not quite working but shows a good usecase of this I might be able to get it working and add as a sample so it stays working :)

Calamari commented 4 years ago

Yes, I meant exactly that. It was a type indeed.

Hmm, ok. Then I know, that I am not completely on the wrong foot. I will probably post up something that does not quite work :) Thanks.

Calamari commented 4 years ago

Just now, I am wondering if the PANGO lib is also available, so I can style the texts? Could not find it.

I am trying to do textView.buffer.create_tag("bold", "style", PANGO_STYLE_BOLD, NULL) or

    font = pango_font_description_from_string("Calibri 20")
    textView.buffer.create_tag("fonty", "font-desc", font, NULL)
jhass commented 4 years ago

So I really didn't understand GValue yet, but I think for your usecase you can just sidestep Pango's FontDescription for now and do something like:

italic = Gtk::TextTag.new("italic")
italic.font = "Sans Italic 12"
text.buffer.tag_table.add italic
start = Gtk::TextIter.new
text.buffer.iter_at_offset start, 0
ending = Gtk::TextIter.new
text.buffer.apply_tag italic, start, ending

Really not pretty but works...

gtk_text_buffer_create_tag doesn't seem to be available in the GIR, maybe due to the varargs :man_shrugging:

Calamari commented 4 years ago

Thank you.

I also try to set the .style property of the TextTag with a 2 (which I read here is the value of italic) but that did not work either. What you wrote works at least :)

I will play around further, and I guess at some point, write an abstraction layer, that hides all this "prettyness" away. Maybe I should call that "Carpet" then :D

Calamari commented 4 years ago

I have another strange thing about those Gtk::TextTags. If you try settings tag.pixels_below_lines = 10 then you get presented the error

Error: undefined constant GObject::Type::INT32

When I look into the lib/gobject/src/g_object/type.cr file, then I do not see any INT32 type, but there is one INT64. Should it be there?

jhass commented 4 years ago

So https://developer.gnome.org/gobject/stable/gobject-Type-Information.html#G-TYPE-INT:CAPS describes no INT32, only a INT and says it would correspond to an gint, which https://developer.gnome.org/glib/stable/glib-Basic-Types.html#gint describes as an alias for the standard C int, whose size is platform dependent.

Now the GIR describes the pixels_below_line as having the type tag INT32, https://developer.gnome.org/gi/stable/gi-Common-Types.html#GITypeTag. Also note that there's no INT in there. In order to set a property we have to wrap the value into a GValue: https://developer.gnome.org/gobject/stable/gobject-Generic-values.html Oh well, those docs aren't super helpful, from the example we can learn there's a g_value_set_int, but it's not even documented in the same page... Anyway, we need to set the matching gtype in the value. But what's the gtype for an INT32? From the fundamentals defined above we only have the platform dependent INT! But then peeking at the GIR for g_value_set_int, its argument has that INT32 type tag again. And the example that uses g_value_set_int sets the GValues gtype to G_TYPE_INT.

So I guess it's okay to map INT32 to G_TYPE_INT, but it feels weird. Anyway I did that now in the latest commit. It compiles for me now, but I couldn't make out a visual effect :man_shrugging:

Calamari commented 4 years ago

Well, the current master builds, but it does not bring the expected outcome. Indeed setting pixels_below_lines does not yield any change at all. Very frustrating.

jhass commented 4 years ago

It might be interesting to build a minimal C example to see if that works there.