Should this crash GTK?



Hi there, 

I am in the progress of learning GTK. The greatest thing of GTK is the object
system in my eyes. So I hacked a little program to explore a bit of it. It
shows a Tree with the Widget hierarchy and let the user select an object. This
object is then created and put into a Window.

While I know that this is not a valid usage of the Toolkit ;), I am sure it
should not segfault. In case this is a debugging aid here is the program:

Oh - BTW: init_types.c is generated with 

objdump --dynamic-syms libgtk.so|   \
    awk '/gtk_.*_get_type/ { print $7, "();"; }' >init_types.c

Sorry for the german comments - I am doing a tutorial on GTK+ in our
university, but I think the code is quite clear.

------------------------------
#include <gtk/gtk.h>

void    show_widget( GtkObject *item );

/*----[ create_class_tree ]-------------------------------------------------*\
    Hängt den Baum der Klassen mit der Basisklasse BASE in den Baum TREE 
    ein.
\*--------------------------------------------------------------------------*/
void    create_class_tree( GtkTree *tree, GtkType base )
{
    GList       *children;
    GtkWidget   *item;

    /* Erstelle einen Eintrag für die Klasse aus BASE und trage ihn in den 
     * Baum ein. */
    
    item = gtk_tree_item_new_with_label( gtk_type_name(base) );
    gtk_object_set_user_data( GTK_OBJECT(item), gtk_type_name(base) );
    gtk_signal_connect(GTK_OBJECT(item), "select", 
                       GTK_SIGNAL_FUNC(show_widget), NULL);
    gtk_tree_append(tree, item);
    
    /* Ermittle die Liste der abgeleiteten Klassen. */

    children = gtk_type_children_types(base);

    /* Nur, wenn welche vorhanden sind, erstellen wir einen Ast für 
     * diese Klassen. */

    if( children ) {
        GtkWidget   *subtree = gtk_tree_new();

        gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree);

        while( children ) {
            create_class_tree( GTK_TREE(subtree), 
                               GPOINTER_TO_UINT(children->data) );
            children = g_list_next( children );
        }
        /* den Ast NICHT anzeigen */
    }

    gtk_widget_show( GTK_WIDGET(item) );
}

GtkContainer    *showcase;
GtkWidget       *showcase_contents = NULL;

void    create_showcase( void )
{
    GtkWidget       *window;

    /* Der Schaukasten kommt in ein eigenes Fenster. */

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Schaukasten");
    gtk_widget_set_usize(window, 200, 100);
    gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE);

    gtk_widget_show(window);

    showcase = GTK_CONTAINER(window);
}

void    show_widget( GtkObject *item )
{
    GtkType     type; 
    GtkWidget   *widget;
    
    type = gtk_type_from_name( gtk_object_get_user_data(item) );
    widget = gtk_widget_new( type, NULL );
    
    if( showcase_contents )
        gtk_container_remove(showcase, showcase_contents);

    gtk_widget_show(widget);
    gtk_container_add(showcase, widget);
    showcase_contents = widget;
}

int main( int argc, char **argv )
{
    GtkWidget       *window, *vbox, *scrollwin, *tree, *button;
    
    gtk_init(&argc, &argv);

    #include "init_types.c"

    /* Erstelle das Hauptfenster */

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Klassenhierarchie von GTK");
    
    /* Im Hauptfenster erstellen wir eine vertikale Box für die 
       Liste und einen Exit-Button. */
    
    vbox = gtk_vbox_new(FALSE, 5);
    gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(vbox));
    gtk_widget_show(vbox);

    /* eine scrollende Box ist nicht schlecht... */

    scrollwin = gtk_scrolled_window_new(NULL, NULL);
    gtk_scrolled_window_set_policy(
                    GTK_SCROLLED_WINDOW(scrollwin),
                    GTK_POLICY_AUTOMATIC,
                    GTK_POLICY_AUTOMATIC);
    gtk_widget_set_usize(scrollwin, 150, 300);
    gtk_container_add(GTK_CONTAINER(vbox), scrollwin);
    gtk_widget_show(scrollwin);

    /* Wir erstellen einen Baum und packen ihn in die scrollwin. */

    tree = gtk_tree_new();
    create_class_tree(GTK_TREE(tree), GTK_TYPE_OBJECT);
    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollwin), tree);
    gtk_widget_show(tree);

    /* ein button dazu... */

    button = gtk_button_new_with_label("Genug");
    gtk_container_add(GTK_CONTAINER(vbox), button);
    gtk_box_set_child_packing( GTK_BOX(vbox), button, 
                               FALSE, FALSE, 5, GTK_PACK_END );
    gtk_widget_show(button);

    /* Wir zeigen das ganze Teil an... */

    gtk_widget_show( window );

    /* Einen Schaukasten hätten wir auch noch gerne... */

    create_showcase();
    
    /* Jetzt verbinden wir noch ein paar Signale, damit man das Programm 
     * auch abbrechen kann. */
    
    gtk_signal_connect(GTK_OBJECT(window), "destroy", 
                       GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
    gtk_signal_connect_object(
                    GTK_OBJECT(button), 
                    "clicked", 
                    GTK_SIGNAL_FUNC(gtk_widget_destroy), 
                    GTK_OBJECT(window) );

    /* Den Rest überlassen wir der Hauptschleife von GTK. */

    gtk_main();
    return 0;
}

/* vim: set ts=4 et: */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]