Continuing on the path to fixing GtkEntry, I discovered that I really
wasn't happy with the way GtkEntry interacts with GtkEditable.
The implementation of things like selections is split about 50-50
between GtkEditable and GtkEntry; but
a) GtkEditable can't be fixed because changing that would break
widgets deriving from GtkEditable, such as GtkText, GtkSCText, (there
are about 5 others in GNOME CVS.)
b) GtkEntry has to continue to be a GtkEditable because
there is a lot of code out there that uses GtkEditable
function calls on GtkEntry.
The solution I found was to use the new interfaces functionality in
GObject.
We turn GtkEditable into an interface, so code such as:
gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1)
continues to work, but GtkEntry doesn't need to share any code with
GtkEditable. The only code that needs to be changed is code such as:
GTK_EDITABLE (entry)->current_pos
which needs to be changed to;
gtk_editable_get_position (GTK_EDITABLE (entry));
The implementation that is currently in GtkEditable moves to a new
GtkOldEditable class. Fixing up legacy widgets such as GtkText becomes
99% just mechanical substitution.
The GtkEditable interface is then exported by both GtkEntry and
GtkOldEditable. It can also, in the future, be exported by objects
such as GtkTextView or GtkTextBuffer, which wasn't previously
possible; a fairly common request was to have editable widgets that
were derived from GtkContainer.
A possibly odd thing about GtkEditable is that to conform to the
GtkEditable interface, you need to not just export the vtable in the
GObject manner, you also need to have a 'editable' argument and
::cut_clipboard, ::copy_clipboard, and ::paste_clipboard action
signals.
I've appended gtkeditable.[ch] below and also gtkoldeditable.[ch]
as an example of a class exporting GtkEditable. I'd appreciate
if Tim in particular would take a look at this and see if
it matches his imagination for how the interfaces would be
used.
Notes on GInterface (in addition to the previous comment that
interfaces vtables should simply be initialized in the class_init
function):
- The GInterfaceInfo argument g_type_add_interface_static needs
to be const.
- There clearly needs to be G_TYPE_INSTANCE_GET_IFACE macro
to simplify:
#define GTK_EDITABLE_GET_IFACE(obj) \
((GtkEditableIface *)g_type_interface_peek (((GTypeInstance *)GTK_EDITABLE (obj))->g_class, \
GTK_TYPE_EDITABLE))
Other than that, the interface stuff seemed to work flawlessly.
Regards,
Owen
Attachment:
gtkeditable.c
Description: Binary data
Attachment:
gtkeditable.h
Description: Binary data
Attachment:
gtkoldeditable.c
Description: Binary data
Attachment:
gtkoldeditable.h
Description: Binary data