Next Previous Contents

4. Programming Interface

The SLgtk application programming interface (api) aims at providing a faithful mirror of the apis of the Gtk widget set and selected portions of its dependencies (e.g Gdk, GObject, GLib, and Pango). As such we do not attempt to exhaustively document here every function wrapped from these libraries, but rather will document the discrepancies between the two apis and refer the reader to the online GTK documentation.

Knowledgeable Gtk programmers should find the mapping from Gtk to SLgtk rather straightforward, and should be pleased by the absence of casting and memory management concerns, and the shorter, simpler code that results. Developers with no prior Gtk experience are encouraged to peruse the GTK tutorial, as well as the SLgtk examples and packages directories mentioned above.

The remaining sections describe the major discrepancies between the SLgtk and Gtk interfaces. The CHANGELOG file within the distribution also provides valuable supplemental information.

4.1 Memory Management

Two of the most significant benefits of coding Gtk guilets in S-Lang are that the user may remain largely ignorant of explicit memory management and type casting concerns. In contrast with Gtk C programs, which expose substantial use of casting macros, casting is never required in SLgtk guilets. There should likewise be virtually zero need to explicitly unref, sink, or destroy Gtk, Gdk, or GLib objects instantiated in S-Lang scope, as SLgtk will automatically call the appropriate finalizer when the S-Lang variable goes out of scope. In other words, it is not necessary to

The obvious exception to this is that if your S-Lang code explicitly adds a reference to an instance then it should likewise explicitly remove the reference later.

4.2 Gtk #define Macros

Several #define macros for querying or manipulating the state of GtkWidget instances have been wrapped for use in S-Lang scope. Currently these, and their corresponding S-Lang name, are:

        GTK_WIDGET_VISIBLE(widget)              gtk_widget_visible(widget)
        GTK_WIDGET_MAPPED(widget)               gtk_widget_mapped(widget)
        GTK_WIDGET_REALIZED(widget)             gtk_widget_realized(widget)
        GTK_WIDGET_TOPLEVEL(widget)             gtk_widget_toplevel(widget)
        GTK_WIDGET_STATE(widget)                gtk_widget_state(widget)
        GTK_WIDGET_IS_SENSITIVE(widget)         gtk_widget_is_sensitive(widget)
        GTK_WIDGET_SET_FLAGS(widget,flag)       gtk_widget_set_flags(widget,flag)
        GTK_WIDGET_UNSET_FLAGS(widget,flag)     gtk_widget_unset_flags(widget,flag)

4.3 Variable Length Argument Lists

Because the S-Lang interpreter records how many arguments have been passed to a function, those SLgtk functions which wrap C functions evincing a variable number of arguments generally do not require any special termination parameter. For example, it is not necessary to:

4.4 Widget Field Accessor Functions

In most cases it is good that S-Lang code is not permitted to peer within Gtk structure internals at runtime, since it enforces the encapsulation provided by the object abstraction. For those instances, though, where Gtk itself does not enforce object encapsulation (by allowing widget internals to be exposed in user code through direct structure field references, rather than object accessor functions), SLgtk provides a corresponding _get() wrapper function to access the field.

One example of such a function is gtk_dialog_get_vbox(). Another is gtk_color_selection_dialog_get_ok_button(), while the complete list can be found in the file src/faccessors_ftable.c generated during the SLgtk build.

4.5 Typing

As discussed below all Gtk object, widget, and structured types map to either structure or opaque S-Lang types. The latter should be viewed as handles to internal data of an unspecified type, created by the S-Lang memory managed type (MMT) mechanism. The reader is encouraged to read the documentation, available at the SLIRP website, to better understand how types are mapped between S-Lang and Gtk.

Unique S-Lang Opaque Types

At import time SLgtk introduces the following unique S-Lang types:

     +  void_ptr
        +  int_ptr
        +  double_ptr
        +  opaque_ptr
        +  file_ptr
        +  float_ptr
        +  long_ptr
        +  string_ptr
        +  uint_ptr
        +  short_ptr
        +  ulong_ptr
        +  ushort_ptr
        +  uchar_ptr
        +  GtkOpaque
           +  GObject
              +  GdkDrawable
                 +  GdkPixmap
                 +  GdkBitmap
              +  GdkGC
              +  GdkPixbuf
              +  GdkPixbufAnimation
                 +  GdkPixbufSimpleAnim
              +  GdkPixbufAnimationIter
              +  GtkObject
                 +  GtkCellRenderer
                    +  GtkCellRendererPixbuf
                    +  GtkCellRendererText
                    +  GtkCellRendererToggle
                 +  GtkItemFactory
                 +  GtkTreeViewColumn
                 +  GtkTooltips
                 +  GtkAdjustment
                 +  GtkWidget
           +  GdkCursor
           +  GdkRegion
           +  GtkIconSource
           +  GtkIconSet
           +  GtkTreeIter
           +  GtkTextIter
           +  GtkTreePath
Upcasts and downcasts may be safely performed between a parent type and any of its ancestors, and SLgtk will automatically cast a given opaque instance variable to the type most appropriate for a given call. Attempting a cast between siblings, or other incompatible types, will signal an error.

Note that the function gtk_object_type(), a wrapper for the GTK_OBJECT_TYPE() C macro, may be used to query the underlying Gtk type of the C variable encapsulated by an opaque S-Lang variable. Likewise, gtk_object_type_name(), which wraps the GTK_OBJECT_TYPE_NAME() C macro, may be used to query the name of underlying Gtk type.


Gtk to S-Lang Type Mappings

These new opaque types map most of the GObject and Gtk class hierarchy to S-Lang as follows, where S-Lang types are prefixed with a plus and C types are suffixed with an asterisk:

     +  void_ptr
        +  int_ptr
        +  double_ptr
        +  opaque_ptr
        +  file_ptr
        +  float_ptr
        +  long_ptr
        +  string_ptr
        +  uint_ptr
        +  short_ptr
        +  ulong_ptr
        +  ushort_ptr
        +  uchar_ptr
        +  GtkOpaque
           |  GList*
           |  GClosure*
           |  GScanner*
           |  GSList*
           |  GTypePlugin*
           |  GTypeInstance*
           |  GTypeClass*
           |  GValue*
           |  PangoFontDescription*
           |  PangoContext*
           |  PangoLayout*
           |  PangoAttrList*
           |  gpointer
           |  gconstpointer
           |  GtkArg*
           |  GtkRequisition*
           |  GtkSelectionData*
           |  GdkAtom
           |  GdkColormap*
           |  GdkDragContext*
           |  GdkEvent*
           |  GdkFont*
           |  GdkDisplay*
           |  GdkVisual*
           |  GdkScreen*
           |  GParamSpec*
           |  GtkTreeModel*
           |  cairo_t*
           |  cairo_surface_t*
           |  cairo_content_t*
           +  GObject
              |  GObject*
              |  GtkAccessible*
              |  AtkObject*
              |  GtkIconFactory*
              |  GtkRcStyle*
              |  GtkAction*
              |  GtkActionGroup*
              |  GtkSettings*
              |  GtkStyle*
              |  GtkTextMark*
              |  GtkTextTagTable*
              |  GtkTreeSelection*
              |  GtkWindowGroup*
              |  GdkDragContext*
              |  GdkImage*
              |  GdkPixbufFormat*
              |  GdkDevice*
              |  GtkAccelGroup*
              |  GtkListStore*
              |  GtkTreeStore*
              |  GtkTextBuffer*
              |  GtkTextChildAnchor*
              |  GtkTextTag*
              |  GtkUIManager*
              +  GdkDrawable
                 |  GdkDrawable*
                 |  GdkWindow*
                 +  GdkPixmap
                    |  GdkPixmap*
                 +  GdkBitmap
                    |  GdkBitmap*
              +  GdkGC
                 |  GdkGC*
              +  GdkPixbuf
                 |  GdkPixbuf*
              +  GdkPixbufAnimation
                 |  GdkPixbufAnimation*
                 +  GdkPixbufSimpleAnim
                    |  GdkPixbufSimpleAnim*
              +  GdkPixbufAnimationIter
                 |  GdkPixbufAnimationIter*
              +  GtkObject
                 |  GtkObject*
                 +  GtkCellRenderer
                    |  GtkCellRenderer*
                    +  GtkCellRendererPixbuf
                       |  GtkCellRendererPixbuf*
                    +  GtkCellRendererText
                       |  GtkCellRendererText*
                    +  GtkCellRendererToggle
                       |  GtkCellRendererToggle*
                 +  GtkItemFactory
                    |  GtkItemFactory*
                 +  GtkTreeViewColumn
                    |  GtkTreeViewColumn*
                 +  GtkTooltips
                    |  GtkTooltips*
                 +  GtkAdjustment
                    |  GtkAdjustment*
                 +  GtkWidget
                    |  GtkWidget*
                    |  GtkAccelLabel*
                    |  GtkAlignment*
                    |  GtkArrow*
                    |  GtkAspectFrame*
                    |  GtkBin*
                    |  GtkBox*
                    |  GtkButton*
                    |  GtkButtonBox*
                    |  GtkCalendar*
                    |  GtkCheckButton*
                    |  GtkCheckMenuItem*
                    |  GtkColorSelection*
                    |  GtkColorSelectionDialog*
                    |  GtkCombo*
                    |  GtkComboBox*
                    |  GtkContainer*
                    |  GtkCurve*
                    |  GtkData*
                    |  GtkDialog*
                    |  GtkDrawingArea*
                    |  GtkEditable*
                    |  GtkEntry*
                    |  GtkEventBox*
                    |  GtkExpander*
                    |  GtkFileSelection*
                    |  GtkFixed*
                    |  GtkFontSelection*
                    |  GtkFontSelectionDialog*
                    |  GtkFrame*
                    |  GtkGammaCurve*
                    |  GtkHandleBox*
                    |  GtkHBox*
                    |  GtkHButtonBox*
                    |  GtkHPaned*
                    |  GtkHRuler*
                    |  GtkHScale*
                    |  GtkHScrollbar*
                    |  GtkHSeparator*
                    |  GtkImage*
                    |  GtkInputDialog*
                    |  GtkInvisible*
                    |  GtkItem*
                    |  GtkLabel*
                    |  GtkLayout*
                    |  GtkMenu*
                    |  GtkMenuBar*
                    |  GtkMenuItem*
                    |  GtkMenuShell*
                    |  GtkMisc*
                    |  GtkNotebook*
                    |  GtkOptionMenu*
                    |  GtkPacker*
                    |  GtkPaned*
                    |  GtkPlug*
                    |  GtkPreview*
                    |  GtkProgress*
                    |  GtkProgressBar*
                    |  GtkRadioButton*
                    |  GtkRadioMenuItem*
                    |  GtkImageMenuItem*
                    |  GtkRange*
                    |  GtkRuler*
                    |  GtkScale*
                    |  GtkScrollbar*
                    |  GtkScrolledWindow*
                    |  GtkSeparator*
                    |  GtkSocket*
                    |  GtkSpinButton*
                    |  GtkStatusbar*
                    |  GtkTable*
                    |  GtkTearoffMenuItem*
                    |  GtkTextView*
                    |  GtkTipsQuery*
                    |  GtkToggleButton*
                    |  GtkToolbar*
                    |  GtkTreeView*
                    |  GtkVBox*
                    |  GtkVButtonBox*
                    |  GtkViewport*
                    |  GtkVPaned*
                    |  GtkVRuler*
                    |  GtkVScale*
                    |  GtkVScrollbar*
                    |  GtkVSeparator*
                    |  GtkWindow*
           +  GdkCursor
              |  GdkCursor*
           +  GdkRegion
              |  GdkRegion*
           +  GtkIconSource
              |  GtkIconSource*
           +  GtkIconSet
              |  GtkIconSet*
           +  GtkTreeIter
              |  GtkTreeIter*
           +  GtkTextIter
              |  GtkTextIter*
           +  GtkTreePath
              |  GtkTreePath*

GTypes and Properties

Most of dynamic typing system provided by GLib is not wrapped, so users cannot presently register S-Lang-scoped types as GTypes. There should be very little call for this in S-Lang scripts, but should the need arise the developer would be better off defining such types in C scope and upwardly promoting the registered GType instances to S-Lang scope, rather than trying to map a pure S-Lang type downward to a C-scoped GType.

The batch widget construction and property setting mechanisms, which accept variable length, variable-typed argument lists (e.g., gtk_widget_new() or g_object_set()), are likewise unsupported.

GdkColor

The S-Lang version of gdk_color_parse() is cleaner, simpler to use, and more powerful than its C counterpart. Color parsing and allocation are achieved in one step, with no variable references needed. Compare

        variable red = gdk_color_parse("red");
in S-Lang with the comparable code in C
        GdkColor red;
        gdk_color_parse("red", &color);
        gdk_color_alloc(gdk_colormap_get_system(), &color);
Also, since it returns a GdkColor structure instead of a gboolean, the SLgtk wrapper for gdk_color_parse() will return NULL when it cannot either parse or allocate the color requested.

The gtk_color_selection_get_current_color() routine has been likewise modified to take only 1 argument and return its GdkColor result on the stack (or NULL on failure).

The gdk_color_copy() and gdk_color_free() routines are intentionally not wrapped. The need for the latter is questionable, while the functionality of the former can be achieved with the S-Lang @ operator:

        variable red = gdk_color_parse("red");
        variable red_copy = @red;
Other SLgtk wrappers of C routines which accept a GdkColor* likewise do not require that a GdkColor reference be passed. For example, consider the C implementation of gtk_widget_modify_fg(), called idiomatically as
        GdkColor color;
        ...
        gdk_color_parse("red",&color);
        ...
        gtk_widget_modify_fg(...,&color);
The matching SLgtk idiom is
        variable color = gdk_color_parse("red");
        ...
        gtk_widget_modify_fg(...,color);

GdkRectangle

GdkRectangle structures may be instantiated in S-Lang scope by either calling the function

        rect1 = gdk_rectangle_new(x,y,width,height);
or using the S-Lang dereference operator on an existing GdkRectangle instance:
        rect2 = @rect1;
Note that gdk_rectangle_new() does not exist in Gdk proper, but rather is provided by SLgtk as a convenience.

GtkAllocation

The GtkAllocation structure is simply a GdkRectangle typedef. Thus the GtkAllocation type is mirrored in S-Lang scope as a proper structure.

GdkPoint

Likewise, GdkPoint structures may be instantiated in S-Lang scope either by calling the convenience function

        p1 = gdk_point_new(x,y);
or using the S-Lang dereference operator on an existing GdkPoint instance:
        p2 = @p1;

GdkEvent

Each S-Lang GdkEvent structure will reflect the three core GdkEventAny fields: type, window, and send_event. Additionally, motion notify and button events contain integral x and y coordinate fields, while keypress events also contain a keyval field, and expose events will reflect the area field.

GtkTextIter

The family of GtkTextBuffer routines which return a GtkTextIter do so by putting the result on the stack, instead of using a reference parameter as in the C api. This fosters natural S-Lang usages, such as

        variable iter = gtk_text_buffer_get_iter_at_offset(buffer,0);
which are cleaner and simpler than their C equivalents:
        GtkTextIter iter;
        gtk_text_buffer_get_iter_at_offset(buffer,&iter,0);

GError

Unlike in C, it is not necessary to explicitly NULL out GError variables intended to receive a GError reference upon return from a function invocation. Such variables are guaranteed to have a legal S-Lang value (possibly NULL) upon return.

GtkMenu

Note that the Gtk menu popup function has been simplified in SLgtk from

        gtk_menu_popup(menu, parent_menu_shell, parent_menu_item,
                        menu_position_func, func_data, mouse_button_num,
                        activate_time);
to
        gtk_menu_popup(menu, mouse_button_num, activate_time);
Per the Gtk documentation, the parent menu and position function parameters are typically unused.

Screen Depths

gdk_query_depths(int **depths, int *num) has been wrapped so that it may be called from S-Lang scope with zero arguments, with the depths array returned on the stack:

        Integer_Type[]  gdk_query_depths()

4.6 Signal Handlers and Callbacks

Gtk and GObject functions which install timeout or signal handlers -- such as g_signal_connect(), gtk_timeout_add(), or gtk_idle_add() -- return a positive integer uniquely identifying the registered callback or, though this does not appear to be stated explicitly in the Gtk reference, zero upon error.

The core signal connection mechanisms, g_signal_connect() and g_signal_connect_swapped() are considerably more flexible than their C counterparts, in that both transparently construct GObject closures when called. When registering signal handlers the caller may thus specify as many callback data parameters as desired, including zero. The same holds true for callback functions registered via gtk_idle_add, gtk_quit_add, gtk_timeout_add, and gtk_container_foreach.

4.7 Callback Errors

If an S-Lang callback function -- or other S-Lang function(s) called from within an S-Lang callback -- signals a non-recoverable error (as indicated by the C-scoped SLang_Error variable having a value less than zero), then the top level window will be destroyed and the outermost main loop will be terminated via gtk_main_quit(). In the typical case, since many scripted GUIs will not nest gtk_main() loops, this will cause the GUI to terminate entirely.

If such functions signal a recoverable error, then the SLang interpreter will be restarted and execution resumed normally, possibly with detritus left on the stack.


Next Previous Contents