[Gtk-sharp-list] Replacing/Enumerating IList usage

Lee Mallabone gnome@fonicmonkey.net
08 May 2003 21:11:11 +0100


Hi all,

First, I'm afraid this post is a little long, but I'm hoping it will act
as a motivator for some further discussion on what, if anything, to do
about list usage in Gtk#.

I've ignored Gst, Gda and GnomeDB for now, as my local gst# copy is
nothing like cvs, and I've not used/looked at Gda at all.

I thought it would be a good idea to list all the uses of GLib.List and
GLib.SList in the current Gtk# API. People greatly familiar with Gtk
will then either know what the function/property is doing, or can easily
look up the generated C# source code. Here are the method/property
signatures:

Atk.Attribute:
public static GLib.SList Free

Atk.EditableText:
bool SetRunAttributes(GLib.SList attrib_set, int start_offset, int
end_offset);

Atk.NoOpObject:
public GLib.SList DefaultAttributes
public bool SetRunAttributes(GLib.SList attrib_set, int start_offset,
int end_offset)
public GLib.SList GetRunAttributes(int offset, int start_offset, int
end_offset)

Atk.Text:
GLib.SList DefaultAttributes
GLib.SList GetRunAttributes(int offset, int start_offset, int
end_offset);

Gtk.Window:
public static GLib.List ListToplevels()
public static GLib.List DefaultIconList
public GLib.List IconList

Gtk.TreeView:
public GLib.List Columns

Gtk.TreeViewColumn:
public GLib.List CellRenderers

Gtk.TextChildAnchor:
public GLib.List Widgets

Gtk.Container:
public GLib.List Children
[These two probably need metadata to make them correct]
public void SetFocusChain(GLib.List focusable_widgets)
public bool GetFocusChain(GLib.List focusable_widgets)

Gtk.Combo:
public GLib.List PopdownStrings

Gtk.RadioButton:
public RadioButton(GLib.SList group)
public static RadioButton NewWithLabel(GLib.SList group, string label)
public RadioButton(GLib.SList group, string label)
public GLib.SList Group

Gtk.RadioMenuItem:
public RadioMenuItem(GLib.SList group)
public static RadioMenuItem NewWithLabel(GLib.SList group, string label)
public RadioMenuItem(GLib.SList group, string label)
public GLib.SList Group

Gtk.TextIter:
public GLib.SList Tags
public GLib.SList Marks
public GLib.SList GetToggledTags(bool toggled_on)

Gnome.IconList:
public GLib.List Selection

Gnome.CanvasPathDef:
public static Gnome.CanvasPathDef Concat(GLib.SList list)
public GLib.SList Split()

Gnome.Program:
public string LocateFile(Gnome.FileDomain domain, string file_name, bool
only_if_exists, GLib.SList ret_locations)

Glade.XML:
public GLib.List GetWidgetPrefix(string name)

Gdk.Window:
public static GLib.List Toplevels
public GLib.List Children
public GLib.List IconList
public GLib.List PeekChildren()

Pango.AttrIterator:
public void GetFont(Pango.FontDescription desc, Pango.Language language,
GLib.SList extra_attrs)

Pango.Layout:
public GLib.SList Lines

As you can see, the number of uses is not enormous. However, I think
it's worth making an effort to remove the explicit use of GLib lists for
a bunch of reasons. IIRC there was basic agreement on that point last
time I brought it up.

To consider a solution, I think it possibly helps to think of functions
that *return* lists separately from functions that accept lists.

Many or all of the functions that *return* GLib lists could be converted
into returning ILists by hacking GLib.ListBase to implement IList
instead of just ICollection. 

Alternatively, with some .custom writing, we could change the current
list return types into their relevant specific array types. Eg. instead
of returning a GLib.List for a 'Widgets' property, just return Widget[].
When the programmer doesn't want/need to modify the return type, I
personally favour the latter approach, as it's easier to see what the
API is doing just by glancing at the method signature.
I also suspect this has the advantage that once we've converted the list
data out of a GLib list, and into C# land, we can perform the relevant
_free() calls on the list, (though I'm speculating there).

Methods that take GLib lists as arguments might be much more difficult
to marshal into something that the C API is happy to accept... I think
accepting an "IList" as the argument is probably making more effort than
it's worth. Again, I think it might be good to accept an array of a
specific type, which is then internally converted to a GLib.(S)List
before being passed to the underlying C function. 

Any opinions on what I've suggested? My brain is a little fried right
now, but I suspect I could start write simple custom methods that
replace the methods/properties that currently return Glib lists with
array types.
Does anyone have a different approach that might be more appropriate?

Regards,

Lee.