[java-gnome-hackers] Mixing generated and hand-written classes
Brought to you by:
afcowie
From: Colin W. <wa...@ve...> - 2008-03-21 05:52:36
|
Hi, I just today tried to use java-gnome for the first time, and ran into the issue of the TextBuffer/TextView not being bound. What I didn't understand at first was why that blocked me from instantiating a TextView at all - if we're generating code as I'd heard java-gnome 4.x is, then certainly I'd have access at least to the constructor? Now, I just read through http://java-gnome.sourceforge.net/4.0/doc/design/5a-Architecture.html and I understand what's going on. I think the design has a lot of good ideas, but the crucial bit that strikes me as wrong is this: "2. inheritance hierarchies — who is extending what? Given that any native G entity has two parts on the Java side (the hand written part with the API that we expose, and the machinery that we generate..." If you look at PyGTK, their approach is to have *one* class, with hand-written "overrides". The huge advantage of this approach is it means that you automatically get access to *almost* everything - it may not be as *nice* as you'd like, but it's there. The current java-gnome approach seems to me it is still much like writing manual bindings, just the generated layer is nicer than JNI. Going back to the "Great Owen Thread" from 2005, he said this: "Well, I wouldn't characterize that as my core objection ... my core objection is really the lack of a consistent and predictable mapping between the GObject signature of an object and the Java signature." The way I think of this is that completeness and correctness are more important than being the slickest Java API. The problem is that as soon as you deviate at all from autogeneration, it is an ongoing maintenance and documentation burden. This is another point about PyGTK - they automatically generate their documentation from the existing gtk-doc. Here is a concrete goal - when someone adds a method to the GTK platform, say in the new GIO work, there is 0 work required in java-gnome to expose that method, including the gtk-doc documentation from it. What this means is that I think we need an architecture, like what PyGTK has, for generating a *single* class from two sources: 1) Autogenerated code from .defs file, possibly filtered 2) Hand-written overrides There's a number of ways to do this. Let's take a quick look at a sample PyGTK override: override gtk_text_view_buffer_to_window_coords kwargs static PyObject * _wrap_gtk_text_view_buffer_to_window_coords(PyGObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { "win", "buffer_x", "buffer_y", NULL }; GtkTextWindowType win; gint buffer_x, buffer_y, window_x = 0, window_y = 0; PyObject *py_win; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oii:GtkTextView.buffer_to_window_coords", kwlist, &py_win, &buffer_x, &buffer_y)) return NULL; if (pyg_enum_get_value(GTK_TYPE_TEXT_WINDOW_TYPE, py_win, (gint *)&win)) return NULL; gtk_text_view_buffer_to_window_coords(GTK_TEXT_VIEW(self->obj), win, buffer_x, buffer_y, &window_x, &window_y); return Py_BuildValue("(ii)", window_x, window_y); } Imagine that we defined an overrides file like this: public class GtkTextView { public int[] bufferToWindowCoords(int x, int y) { int[] retval = new int[2]; int[] windowX; int[] windowY; gtk_text_view_buffer_to_window_coords(pointerOf(self), numOf(win), bufferX, bufferY, windowX, windowY); retval[0] = windowX[0]; retval[1] = windowY[1]; return retval; } } What would happen at the build process is that we'd parse that Java file, detect a method named bufferToWindowCoords which maps to gtk_text_view_buffer_to_window_coords, and remove the autogenerated method. Instead of parsing Java code, we could have a magic comment like // generator override gtk_text_view_buffer_to_window_coords I don't think something like this would be too hard to achieve with the current code generator - if we tweak the class name to match the formerly hand coded version, remove the explicit "self" passing (I don't understand why that's there?), then we could start to merge in the existing hand-coded classes with generated ones, and keep what parts of the hand-coded things that are nicer. Taking a concrete example here - the hand-coded GtkAboutDialog.java API is basically identical to the generated GtkAboutDialog, except for the static method transformation. The javadoc appears to be handcoded to be nicer, but again I think the approach of generating from gtk-doc is the right thing to do, except for explicit overrides. What do you think? |