Getting Started with CoreGTK

In general writing a program using CoreGTK is very similar to writing one in standard GTK+ C code (except that you get to use Objective-C as well!). GTK+ signal callbacks can be setup to target class methods (i.e. +(void) something) and/or instance methods (i.e. -(void) something).

The following is an example of a Hello World program written in standard GTK+ C and then one re-written in CoreGTK Objective-C.

Hello World program written in standard GTK+ C code:

#include <gtk/gtk.h>

/* This is a callback function. The data arguments are ignored
 * in this example. More on callbacks below. */
static void hello( GtkWidget *widget,
 gpointer data )
{
 g_print ("Hello World\n");
}

/* Another callback */
static void destroy( GtkWidget *widget,
 gpointer data )
{
 gtk_main_quit ();
}

int main( int argc,
 char *argv[] )
{
 /* GtkWidget is the storage type for widgets */
 GtkWidget *window;
 GtkWidget *button;

 /* This is called in all GTK applications. Arguments are parsed
 * from the command line and are returned to the application. */
 gtk_init (&argc, &argv);

 /* create a new window */
 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

 /* Here we connect the "destroy" event to a signal handler */
 g_signal_connect (window, "destroy",
 G_CALLBACK (destroy), NULL);

 /* Sets the border width of the window */
 gtk_container_set_border_width (GTK_CONTAINER (window), 10);

 /* Creates a new button with the label "Hello World" */
 button = gtk_button_new_with_label ("Hello World");

 /* When the button receives the "clicked" signal, it will call the
 * function hello() passing it NULL as its argument. The hello()
 * function is defined above. */
 g_signal_connect (button, "clicked",
 G_CALLBACK (hello), NULL);

 /* This packs the button into the window (a gtk container) */
 gtk_container_add (GTK_CONTAINER (window), button);

 /* The final step is to display this newly created widget */
 gtk_widget_show (button);

 /* and the window */
 gtk_widget_show (window);

 /* All GTK applications must have a gtk_main(). Control ends here
 * and waits for an event to occur (like a key press or
 * mouse event). */
 gtk_main ();

 return 0;
}

The same program written in CoreGTK and Objective-C code:

/*
 * Objective-C imports
 */
#import <Foundation/Foundation.h>
#import "CGTK.h"
#import "CGTKButton.h"
#import "CGTKSignalConnector.h"
#import "CGTKWindow.h"

/*
 * C imports
 */
#import <gtk/gtk.h>

@interface HelloWorld : NSObject
 /* This is a callback function. The data arguments are ignored
 * in this example. More on callbacks below. */
 +(void)hello;

 /* Another callback */
 +(void)destroy;
@end

@implementation HelloWorld
int main(int argc, char *argv[])
{
 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

 /* We could use also CGTKWidget but then we would need to cast */
 CGTKWindow *window;
 CGTKButton *button;

 /* This is called in all GTK applications. Arguments are parsed
 * from the command line and are returned to the application. */
 [CGTK autoInitWithArgc:argc andArgv:argv];

 /* Create a new window */
 window = [[CGTKWindow alloc] init:GTK_WINDOW_TOPLEVEL];

 /* Here we connect the "destroy" event to a signal handler in the HelloWorld class */
 [CGTKSignalConnector connectGpointer:[window WIDGET] withSignal:@"destroy"
toTarget:[HelloWorld class] withSelector:@selector(destroy) andData:NULL];

 /* Sets the border width of the window */
 [window setDefaultSizeWithWidth:400 andHeight:300];

 /* Creates a new button with the label "Hello World" */
 button = [[CGTKButton alloc] initWithLabel:@"Hello World"];

 /* When the button receives the "clicked" signal, it will call the
 * function hello() in the HelloWorld class (below) */
 [CGTKSignalConnector connectGpointer:[button WIDGET] withSignal:@"clicked" 
 toTarget:[HelloWorld class] withSelector:@selector(hello) andData:NULL];

 /* This packs the button into the window (a gtk container) */
 [window add:button];

 /* The final step is to display this newly created widget */
 [button show];

 /* and the window */
 [window show];

 /* All GTK applications must have a [CGTK main] call. Control ends here
 * and waits for an event to occur (like a key press or
 * mouse event). */
 [CGTK main];

 [pool release];

 return 0;
}

+(void)hello
{
 NSLog(@"Hello World");
}

+(void)destroy
{
 [CGTK mainQuit];
}
@end

You can also use CGTKBuilder to load an XML export from GLADE:

CGTKBuilder *builder = [[CGTKBuilder alloc] init];
if(![builder addFromFileWithFilename:@"test.glade" andErr:NULL] == 0)
{
    NSLog(@"Error loading GUI file");
    return 1;
}

[CGTKBuilder setDebug:YES];

NSDictionary *dic = [[NSDictionary alloc] initWithObjectsAndKeys:
                 [CGTKCallbackData withObject:[CGTK class] andSEL:@selector(mainQuit)], @"endMainLoop",
                 [CGTKCallbackData withObject:[HelloWorld class] andSEL:@selector(hello)], @"on_button2_clicked",
                 [CGTKCallbackData withObject:[HelloWorld class] andSEL:@selector(hello)], @"on_button1_activate",
                 nil];

/* CGTKBaseBuilder is a helper class to maps GLADE signals to Objective-C code */
[CGTKBaseBuilder connectSignalsToObjectsWithBuilder:builder andSignalDictionary:dic];

CGTKWidget *w = [CGTKBaseBuilder getWidgetFromBuilder:builder withName:@"window1"];
if(w != nil)
{
    [w showAll];
}

[builder release];

Fall back to regular old C if you need/want to:

// Use it as an Objective-C CoreGTK object!
CGTKWindow *window = [[CGTKWindow alloc] init:GTK_WINDOW_TOPLEVEL];

// Or as a C GTK+ window!
GtkWindow *cWindow = [window WINDOW];

// Or even as a C GtkWidget!
GtkWidget *cWidget = [window WIDGET];

// This...
[window show];

// ...is the same as this:
gtk_widget_show([window WIDGET]);