GTK

The following reference is a small extract from two books I read to become familiar with GTK programming. This is not a summary of this books but more for keeping things in mind. I hope not to hurt some license terms using some parts here. If so please write me and I will get rid of these things or prevent access with password. But for now I see no need for this. To learn such things it is necessary to read more about GTK than only read the part below.

Additionally to that the source code is free to download at http://www.gtkbook.com

My book recommendation:

Gtk

Basics:

Dialogs:

g_signal_connect

 gulong g_signal_connect(gpointer object, const gchar *signal_name, GCallback handler, gpointer data);
 g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), (gpointer) label);
 g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gtk_widget_destroy), (gpointer) window);
swaps the position of the object on which the signal is being emitted and the data parameter when running the callback function. This allows you to use gtk_widget_destroy() on the callback function, which will call gtk_widget_destroy(window). If the callback function only receives one parameter, the object will be ignored.
 g_signal_connect(G_OBJECT(button), "notify::relief", G_CALLBACK(property_changed), NULL);
 static void property_changed(GObject *button, GParamSpec *property, gpointer data)
 {
    printf("changed %s", property->name);
 }

Callback Functions (not events)

 static void callback_function(GtkWidget *widget, ..., gpointer data);

Emitting and Stopping Signals

 void g_signal_emit_by_name(gpointer instance, const gchar *signal_name, ...);
 void g_signal_stop_emission_by_name(gpointer instance, const gchar *signal_name);

Events

are initially emitted by the X Window System and then sent from the window manager to your application to be interpreted by the signal system provided by GLib.

static gboolean callback_function(GtkWidget *widget, GdkEvent *event, gpointer data);

Return value TRUE gtk+ assumes the event has already been handled. With FALSE gtk+ continue to handling the event.

If we know what kind of event we handle, we can adjust some parameters. Like here with GtkEventKey instead of GdkEvent.

 g_signal_connect(G_OBJECT(widget), "key-press-event", G_CALLBACK(key_press), NULL);
 static gboolean key_press(GtkWidget *widget, GtkEventKey *event, gpointer dat);

GtkLabel

 GtkWidget *label;
 label = gtk_label_new("Hello World");
 gtk_label_set_selectable(GTK_LABEL(label), TRUE);

 void gtk_label_set_text(GtkLabel *label, const gchar *str);
 void gtk_label_set_markup(GtkLabel *label, const gchar *str);
to set markup language like html. For example <b>, <tt> and <i>

GtkContainer

 gtk_container_set_border_width(GTK_CONTAINER(window), 10);
 void gtk_container_add(GtkContainer *container, GtkWidget *child);

GtkWidget

 void gtk_widget_destroy(GtkWidget *widget);
the widget, along with its children, will be destroyed and all memory freed
 void gtk_widget_set_size_request(GtkWidget *widget, gint width, gint height);
to set the minimum size of a widget. It will not, however, resize the widget so that it is too small to be functional or able to draw itself on the screen.
 void gtk_widget_grab_focus(GtkWidget *widget);
to force a widget to grab keyboard focus. This could be used to give focus to a GtkLabel that is selectable.
 void gtk_widget_set_sensitive(GtkWidget *widget, gboolean sensitive);
by calling it the specified widget and all of its children are disabled or enabled
 void gtk_widget_show_all(GtkWidget *widget);
 void gtk_widget_hide_all(GtkWidget *widget);

 gtk_button_new()
creates an empty GtkButton so you can add your own child to it at a later time.
 gtk_button_new_with_label()
creates new button with a GtkLabel as its child
 gtk_button_new_with_mnemonic("_Close")
initialize new button with mnemonic label support (here if you press alt+c
 gtk_button_set_relief()
can be used to add a certain magnitude of relief around the GtkButton. Relief is a type of 3D border. Three types which differs in the number of edges they are around.

GObject Properties

 g_object_get(button, "relief", &value, NULL);
 g_object_set(button, "relief", GTK_RELIEF_NORMAL, NULL);

GObject has a table that associates a list of strings to a list of pointers. You can change entries with:

 void g_object_set_data(GObject *object, const gchar *key, gpointer data);

and with g_object_get_data() you can get data, which returns the pointer associated with key.

GtkButton

 gtk_button_new()
creates an empty GtkButton so you can add your own child to it at a later time.
 gtk_button_new_with_label()
creates new button with a GtkLabel as its child
 gtk_button_new_with_mnemonic("_Close")
initialize new button with mnemonic label support (here if you press alt+c
 gtk_button_set_relief()
can be used to add a certain magnitude of relief around the GtkButton. Relief is a type of 3D border. Three types which differs in the number of edges they are around.

Resizing Children

 gtk_widget_set_size_request()

Vertical Boxes

 gboolean homogeneous = TRUE;
 gint spacing = 5;
 GtkWidget *vbox = gtk_vbox_new(homogeneous, spacing);
 gtk_box_pack_start_defaults(GTK_BOX(vox), button); /* expand=TRUE,fill=TRUE */

 void gtk_box_pack_end(GtkBox *box
 gtk_box_pack_end(GTK_BOX(vbox), button, FALSE, FALSE, 5);

Horizontal and Vertical Panes

Special type of container widget that holds exactly two widgets with a resize bar between them.

 GtkWidget *hpaned = gtk_hpaned_new();
 gtk_paned_add1(GTK_PANED(hpaned), button1); 
 gtk_paned_add2(GTK_PANED(hpaned), button2);
 gtk_container_add(GTK_CONTAINER(window), hpaned);

 gtk_paned_pack1(GTK_PANED(hpaned), label1, FALSE, TRUE);
 gtk_paned_pack2(GTK_PANED(hpaned), label2, TRUE, TRUE);

 /* set position of the resize bar */
 void gtk_paned_set_position(GtkPaned *paned, gint position);
 gint gtk_paned_get_position(GtkPaned *paned);

Tables

 GtkWidget *table = gtk_table_new(guint rows, guint columns, gboolean homogeneous);
 void gtk_table_resize(GtkTable *table, guint rows, guint columns);
 void gtk_table_set_homogeneous(GtkTable *table, gboolean homogeneous);
 void gtk_table_attach(GtkTable *table
     , GtkWidget *child
     , guint left
     , guint right
     , guint top
     , guint bottom
     , GtkAttachOptions xoptions
     , GtkAttachOptions yoptions
     , guint xpadding
     , guint ypadding);
 gtk_table_attach(GTK_TABLE(table), label, 0, 2, 0, 1, GTK_EXPAND, GTK_SHRINK, 0, 0);
attachs the label to the first row (x=0,y=1) and in this row from 0 to coordinate 2 which means if the table has two columns the label spans itself over the whole row.
 void gtk_table_attach_defaults(GtkTable *table
     , GtkWidget *child
     , guint left
     , guint right
     , guint top
     , guint bottom);
sets the default value for options and padding which means GTK_EXPAND|GTK_FILL and no padding
 void gtk_table_set_col_spacings(GtkTable *table, guint spacing);
 void gtk_table_set_col_spacing(GtkTable *table, guint column, guint spacing);
 void gtk_table_set_col_spacings(GtkTable *table, guint spacing);

Fixed Containers

 void gtk_fixed_move(GtkFixed *fixed, GtkWidget *child, gint x_pos, gint y_pos);

Expanders

 GtkWidget *expander = gtk_expander_new_with_mnemonic("_Expand me");
 gtk_container_add(GTK_CONTAINER(expander), label);
 gtk_expander_set_expanded(GTK_EXPANDER(expander), TRUE);
 gtk_expander_set_spacing(GTK_EXPANDER(expander), guint spacing);
 gtk_container_add(GTK_CONTAINER(window), expander);

Handle Boxes

is another type of GtkBin container that allows its child to be removed from the parent window by dragging it with the mouse.

 GtkWidget *handle = gtk_handle_box_new();
 GtkWidget *label = gtk_label_new("asdf");
 gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(handle), GTK_POS_LEFT);
 gtk_handle_box_set_snap_edge(GTK_HANDLE_BOX(handle), GTK_POS_TOP);

Notebooks

 GtkWidget *notebook = gtk_notebook_new();
 label1 = gtk_label_new("Page One");
 label2 = gtk_label_new("Page Two");
 child1 = gtk_label_new("Content of Page One");
 child2 = gtk_label_new("Content of Page Two");
 g_signal_connect(G_OBJECT(child1), "clicked", G_CALLBACK(switch_page), (gpointer) notebook);
 g_signal_connect(G_OBJECT(child2), "clicked", G_CALLBACK(switch_page), (gpointer) notebook);
 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), child1, label1);
 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), child2, label2);

 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_BOTTOM);
 gtk_container_add(GTK_CONTAINER(window), notebook);

 gint gtk_notebook_append_page(GtkNotebook *notebook, GtkWidget *child, sGtkWidget *tab_label);
 gint gtk_notebook_insert_page(GtkNotebook *notebook, GtkWidget *child, GtkWidget *tab_label, gint position);
 void gtk_notebook_set_tab_pos(GtkNotebook *notebook, GtkPositionType position);
 void gtk_notebook_set_show_tabs(GtkNotebook *notebook, gboolean show_tabs);
 void gtk_notebook_set_scrollable(GtkNotebook *notebook, gboolean scrollable);

 void gtk_notebook_remove_page(GtkNotebook *notebook, gint page_number);
 void gtk_notebook_reorder_child(GtkNotebook *notebook, GtkWidget *child, gint position);
 void gtk_notebook_set_current_page(GtkNotebook *notebook, gint page_number);

Event Boxes

Various widgets including GtkLabel do not respond to GDK events, because they do not have an associated GDK window. For those cases the event box exists.

 GtkWidget *eventbox = gtk_event_box_new();
 gtk_event_box_set_above_child(GTK_EVENT_BOX(eventbox), FALSE);
 g_signal_connect(G_OBJECT(eventbox), "button_press_event", G_CALLBACK(button_pressed), (gpointer) label);
 gtk_widget_set_events(eventbox, GDK_BUTTON_PRESS_MASK);
 gtk_widget_realize(eventbox);
 gdk_window_set_cursor(eventbox->window, gdk_cursor_new(GDK_HAND1));
 gtk_widget_show_all(window);

 static gboolean button_pressed(GtkWidget *eventbox, GdkEventButton *event, GtkLabel *label)
 {
   if(event->type == GDK_2BUTTON_PRESS) 
   {}
 }

Using Stock Items

 button = gtk_button_new_from_stock(GTK_STOCK_FLOPPY)
 g_signal_connect_swapped(G_OBJECT(BUTTON), "clicked", G_CALLBACK(open_floppy_handler), (gpointer)window);

Toggle Buttons

The GtkTobbleButton widget is a type of GtkButton that holds its active or inactive state after it is clicked. It is shown as pressed down when active. Clicking an active tobble button will cause it to return to its normal state. There are two widgets derived from GtkTobbleButton:

  1. GtkCheckButton
  2. GtkRadioButton
 GtkWidget *tobble1 = gtk_toggle_button_new_with_mnemonic("_Press down");
 g_signal_connect(G_OBJECT(toggle1), "toggled", G_CALLBACK(button_toggled), toggle2);

 static void button_toggled(GtkToggleButton *toggle, GtkWidget *other_toggle)
 { 
    gtk_widget_set_sensitive(other_toggle, TRUE);
 }

Sensitivity is actually only one of many widget flags provided by the GtkWidgetFlags enumeration. For more Flags see here.

 gboolean gtk_toggle_button_get_active()
 void gtk_toggle_button_set_active(GtkTobbleButton *toggle, gboolean active);

Check Buttons

 GtkWidget *check1 = gtk_check_button_new_with_label("Click here");
 GtkWidget *check2 = gtk_check_button_new_with_label("or here");

 /* Only enable the second check button when the first is enabled. */
 gtk_widget_set_sensitive(check2, FALSE); 
 g_signal_connect(G_OBJECT(check), "toggled", G_CALLBACK(check_toggled), (gpointer) check2);

 static void check_toggled(GtkToggleButton *check1, GtkWidget *check2)
 {
    g_printf("toggled-signal raised\n");
 }

Radio Buttons

In a group, when one radio button is selected, all others will be deselected.

 GtkWidget *radio1, ...
 radio1 = gtk_radio_button_new_with_label(NULL, "option1");
 radio2 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio1), "option2");
 radio3 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio2), "option2");
note that you could give every radio button that is already a member of the group as here radio2 already is.

To create the first member of the group:

 GtkWidget* gtk_radio_button_new(GSList *group);
 GtkWidget* gtk_radio_button_new_with_label(GSList *group, const gchar *label);
 GtkWidget* gtk_radio_button_new_with_mnemonic(GSList *group, const gchar *label);

To create the rest of the group:

 GtkWidget* gtk_radio_button_new_from_widget(GtkRadioButton *group);
 GtkWidget* gtk_radio_button_new_with_label_from_widget(GtkRadioButton *group, const gchar *label);
 GtkWidget* gtk_radio_button_new_with_mnemonic_from_widget(GtkRadioButton *group, const gchar *label);

Every radio button in the group must be connected to the toggled signal.

Text Entries

  GtkWidget *window, *vbox, *hbox, *question, *label, *pass;
  gchar *str;

  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window), "Password?");
  gtk_container_set_border_width (GTK_CONTAINER (window), 10);

  g_signal_connect (G_OBJECT (window), "destroy",
                    G_CALLBACK (destroy), NULL);

  str = g_strconcat ("What is the password for ", g_get_user_name(), "?", NULL);
  question = gtk_label_new (str);
  label = gtk_label_new ("Password:");

  /* Create a new GtkEntry widget and hide its content from view. */
  pass = gtk_entry_new ();
  gtk_entry_set_visibility (GTK_ENTRY (pass), FALSE);
  gtk_entry_set_invisible_char (GTK_ENTRY (pass), '*');

  hbox = gtk_hbox_new (FALSE, 5);
  gtk_box_pack_start_defaults (GTK_BOX (hbox), label);
  gtk_box_pack_start_defaults (GTK_BOX (hbox), pass);

  vbox = gtk_vbox_new (FALSE, 5);
  gtk_box_pack_start_defaults (GTK_BOX (vbox), question);
  gtk_box_pack_start_defaults (GTK_BOX (vbox), hbox);

  gtk_container_add (GTK_CONTAINER (window), vbox);
  gtk_widget_show_all (window);

  gtk_main ();

 void gtk_editable_set_editable(GtkEditable *editable, gboolean is_editable);
 void gtk_entry_set_max_length(GtkEntry *entry, gtin max_length);
 void gtk_entry_set_invisible_char(GtkEntry *entry, gunichar inv_char);
 void gtk_entry_set_visibility(GtkEntry *entry, gboolean visible);
 void gtk_entry_set_text(GtkEntry *entry, const gchar *text);
 void gtk_editable_insert_text(GtkEditable *editable, const gchar *text
                               , gint length_of_text, gint *position);
give position 0 for begin of the string and -1 for the end of the string
 void gtk_editable_delete_text(GtkEditable *editable, gint start_pos, gint end_pos);
 void gtk_editable_select_region(GtkEditable *editable, gint start_pos, gint end_pos);
 void gtk_editable_delete_selection(GtkEditable *editable);
 gchar* gtk_editable_get_chars(GtkEditable *editable, gint start_pos, gint end_pos);

 /* the following functions are built into entries by default */
 void gtk_editable_cut_clipboard(GtkEditable *editable);
 void gtk_editable_copy_clipboard(GtkEditable *editable);
 void gtk_editable_paste_clipboard(GtkEditable *editable);

Spin Buttons

The GtkSpinButton widget is a number selection widget that is capable of handling integers and floating-point numbers. Ti is derived from GtkEntry, so GtkSpinButton inherits all of its functions and signals.

 GtkObject* gtk_adjustment_new(gdouble initial_value,
   gdouble lower_range,
    gdouble upper_range,
   gdouble step_increment,
   gdouble page_increment,
   gdouble page_size);

 float_pt = GTK_ADJUSTMENT(gtk_adjustment_new(0.5, 0.0, 1.0, 0.1, 0.5, 0.5));
 spin_float = gtk_spin_button_new(float_pt, 0.1, 1);
 gtk_box_pack_start_defaults(GTK_BOX(vbox), spin-float);

Horizontal and Vertical Scales

 scale_float = gtk_hscale_new_with_range(0.0, 1.0, 0.1);
 gtk_scale_set_digits(GTK_SCALE(scale_float), 1);
 gtk_scale_set_value_pos(GTK_SCALE(scale_float), GTK_POS_LEFT);

Widget Styles

 typedef struct
 {
   GtkStyle *style;
   GtkRequisition requisition;
   GtkAllocation allocation;
   GdkWindow *window;
   GtkWidget *parent;
 } GtkWidget;

Widget states:

  1. GTK_STATE_NORMAL
  2. GTK_STATE_ACTIVE
  3. GTK_STATE_PRELIGHT
  4. GTK_STATE_PRELIGHT
  5. GTK_STATE_SELECTED
  6. GTK_STATE_INSENSITIVE

FileChooser

 chooser = gtk_file_chooser_button_new("Choose a Folder", GTK_FILE_CHOOSER_ACTION_OPEN);
 g_signal_connect(G_OBJECT(chooser), "selection_changed", G_CALLBACK(file_changed), (gpointer)label);
 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(chooser), g_get_homedir());
 filter = gtk_file_filter_new();
 gtk_file_filter_set_name(filter, "Image Files");
 gtk_file_filter_add_pattern(filter, "*.png");
 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(chooser), filter);

 static void file_changed(GtkFileChooser *chooser, GtkLabel *label)
 {
    gchar *file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooser));
    gtk_label_set_text(label, file);
    g_free(file);
 }

 void gtk_file_filter_add_mime_type(GtkFileFilter *filter, const char *mime_type);

Dialogs

 typedef struct
 {
   GtkWidget *vbox;
   GtkWidget *action_area;
 } GtkDialog;

 gtk_box_pack_start_defaults(GTK_BOX(dialog->vbox), child);

Example

 { /* event handler of one of the events of main loop */
 dialog = gtk_dialog_new_with_buttons("Information", 
     parent, 
     GTK_DIALOG_MODAL, 
     GTK_STOCK_OK, 
     GTK_RESPONSE_OK, 
     NULL);
 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
 label = gtk_label_new("BLABLA");
 image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG);
  /* GtkWidget* gtk_image_new_from_stock(const gchar *stock_id, GtkIconSize size); */
 .
 .
 gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox);
 gtk_dialog_run(GTK_DIALOG(dialog));
 gtk_widget_destroy();
 }

 GtkWidget *gtk_image_new_from_file(const gchar *filename);
 GtkWidget *gtk_image_new_from_pixbuf(GdkPixbuf *pixbuf);

Nonmodal Dialog

In order to create a nonmodal dialog, you need to connect to GtkDialog's response signal.

 dialog = gtk_dialog_new_with_buttons("Info", 
    parent, 
    GTK_DIALOG_DESTROY_WITH_PARENT, 
    GTK_STOCK_OK, 
    GTK_RESPONSE_OK, 
    NULL);

 result = gtk_dialog_run(GTK_DIALOG(dialog));
 switch( result )
 {
   case(GTK_RESPONSE_OK):
    break;
   case(GTK_RESPONSE_APPLY):
    break;
 }
 gtk_widget_destroy(dialog);

Built-in Dialogs

GtkMessageDialog

 dialog = gtk_message_dialog_new(parent, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "hello");
 gtk_window_set_title(GTK_WINDOW(dialog), "info");
 gtk_dialog_run(GTK_DIALOG(dialog));
 gtk_widget_destroy(dialog);
 gtk_message_dialog_new_with_markup()
allows you to use pango text markup language. This is same as do creation with gtk_message_dialog_new() and set text with gtk_message_dialog_set_markup()
 void gtk_message_dialog_set_format_secondary_text(GtkMessageDialog *dialog, const gchar *message_format, ...);

GtkAboutDialog

 dialog = gtk_about_dialog_new();
 logo = gdk_pixbuf_new_from_file("/path/logo.png", &error);
 if( error==NULL )
    gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(dialog), logo);
 GdkPixbuf* gdk_pixbuf_scale_simple(const GdkPixbuf *src, int dest_width, int dest_height, GdkInterpType interpolation);
 gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(dialog), "dialog");
 gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), "1.0");
 gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(dialog), "(C) 2007 Firstname Backname");
 gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog), "All About ...");
 gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(dialog), "blabla");
 gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(dialog), "http://www.nowhere.to");
 gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(dialog), "www.nowhere.to");

 const gchar *authors[] = {
    "author1",
    "author2",
    NULL
 };
 gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(dialog), authors);
 gtk_about_dialog_set_documenters(GTK_ABOUT_DIALOG(dialog), authors);
 gtk_about_dialog_set_translator_credits(GTK_ABOUT_DIALOG(dialog), "line1 \n line2");

 gtk_dialog_run(GTK_DIALOG(dialog));
 gtk_widget_destroy(dialog);

GError

 struct GError
 {
GQuark domain;
   gchar *message;
   gint code;
 }

 if( error->domain==GDK_PIXBUF_ERROR)
   g_print("GdkPixbufError: %s\n", error->message);

FileChooserDialog

Saving Files

 dialog = gtk_file_chooser_dialog_new("Save File as ...", window
     , GTK_FILE_CHOOSER_ACTION_SAVE
     , GTK_STOCK_CANCEL
     , GTK_RESPONSE_CANCEL
     , GTK_STOCK_SAVE
     , GTK_RESPONSE_ACCEPT
     , NULL);
 gint result = gtk_dialog_run(GTK_DIALOG(dialog));
 if(result==GTK_RESPONSE_ACCEPT)
 {
     filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
     gtk_button_set_label(button, filename);
 }
 gtk_widget_destroy(dialog);

Creating a Folder

 dialog = gtk_file_chooser_dialog_new("Save File as ...", window
     , GTK_FILE_CHOOSER_CREATE_FOLDER
     , GTK_STOCK_CANCEL
     , GTK_RESPONSE_CANCEL
     , GTK_STOCK_OK
     , GTK_RESPONSE_OK
     , NULL);
 gint result = gtk_dialog_run(GTK_DIALOG(dialog));
 if(result==GTK_RESPONSE_OK)
 {
     filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
     g_print("no need to make folder %s. This provides the dialog itself.\n", filename);
 }
 gtk_widget_destroy(dialog);

Selecting Multiple Files

The difference between GtkFileChooserDialog and GtkFileChooserButton using the GTK_FILE_CHOOSER_ACTION_OPEN type is that dialogs are capable of selecting multiple files while buttons are restricted to one file.

 dialog = gtk_file_chooser_dialog_new("Open File(s) ...", window
     , GTK_FILE_CHOOSER_ACTION_OPEN
     , GTK_STOCK_CANCEL
     , GTK_RESPONSE_CANCEL
     , GTK_STOCK_OPEN
     , GTK_RESPONSE_ACCEPT
     , NULL);
 gtk_file_chosser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
 gint result = gtk_dialog_run(GTK_DIALOG(dialog));
 if(result==GTK_RESPONSE_ACCEPT)
 {
     GSList *filenames = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
     while( filenames !=NULL )
     {
         g_print("%s was selected.\n", (gchar*) filenames->data); 
         filenames = filenames->next;
     }
 }
 gtk_widget_destroy(dialog);

Color Selection Dialogs: GtkColorSelectionDialog

Font Selection Dialogs: GtkFontSelectionDialog

Dialogs with Multiple Pages

with GtkAssistant.

 index = gtk_assistant_append_page(GTK_ASSISTANT(assistant), widget);

Page type:

 void gtk_assistant_set_page_complete(GtkAssistant *assistant, GtkWidget *page, gboolean complete);

GtkProgressBar

 while( percent<=100.0 )
 {
    gchar *message = g_strdup_printf("%.0f complete", percent);
    gtk_progress_bar_set_fraction(progress, percent/100.0 );
    gtk_progress_bar_set_text(progress, message);
    while( gtk_events_pending())
       gtk_main_iteration();
    g_usleep(3600);
    percent += 3.141529;
 }

to set progress step:

 gtk_progress_bar_set_pulse_step()

Create you own PageForwardFunc

 void gtk_assistant_set_forward_page_func(...);

Text View Widget (GtkTextView)

Scrolled Windows

Both scrollbars int the scrolled window have associated GtkAdjustment objects. These adjustments are used to track the current position and range of a scrollbar.

 swin = gtk_scrolled_window_new(NULL,NULL);
 horizontal = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(swin));
 vertical = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(swin));
 gtk_container_set_border_width(GTK_CONTAINER(swin), 5);
 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(swin), table1);

Each text view is used to display the contents of a class called GtkTextBuffer.

A simple GtkTextView Example:

  1. include <gtk/gtk.h>

int main(int argc, char **argv) {

        GtkWidget *window, *scrolled_win, *textview;
        GtkTextBuffer *buffer;
        gtk_init(&argc, &argv);
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_window_set_title(GTK_WINDOW(window), "title");
        gtk_container_set_border_width(GTK_CONTAINER(window), 10);
        gtk_widget_set_size_request(window, 250,150);
        textview = gtk_text_view_new();
        buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
        gtk_text_buffer_set_text(buffer, "This you first text view widget!!!!", -1);
        scrolled_win = gtk_scrolled_window_new(NULL, NULL);
        gtk_container_add(GTK_CONTAINER(scrolled_win), textview);
        gtk_container_add(GTK_CONTAINER(window), scrolled_win);
        gtk_widget_show_all(window);
        gtk_main();
        return 0;

}

 gtk_text_view_set_wrap_mode()
 gtk_widget_set_sensitive()
used to prevent the user interacting with widget
 gtk_text_view_set_cursor_visible()

When manipulating text within a GtkTextBuffer, there are two objects that can be used to keep track of a position within the buffer: GtkTextIter and GtkTextMark

Text iterators are used to represent a position between two characters in a buffer. The problem presented by text iterators is that they automatically become invalidated when a text buffer is edited. For keeping track of a position throughout changes within a text buffer, the GtkTextMark object is provided.

 void gtk_text_buffer_get_iter_at_mark();
provides iterator pointing to a text mark
 typdef struct { GtkWidget *entry, *textview; } Widgets
 Widgets *w = g_slice_new(Widgets);
 ...
 w->textview = gtk_text_view_new();
 w->entry = gtk_entry_new();
 g_signal_connect(G_OBJECT(insert), "clicked", G_CALLBACK(insert_text), (gpointer) w);
 scrolled_win = gtk_scrolled_window_new(NULL, NULL);
 gtk_container_add(GTK_CONTAINER(scrolled_win), w->textview);
 gtk_container_add(GTK_CONTAINER(window), vbox);
 gtk_widget_show_all(window);

 insert_text()
 {
  GtkTextBuffer *buffer;
GtkTextMark *mark;
 GtkTextIter iter;
  const gchar *text;
  buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(w->textview));
 text = gtk_entry_get_text(GTK_ENTRY(w->entry));
  mark = gtk_text_buffer_get_insert(buffer);
  gtk_trxt_buffer_get_iter_at_mark(buffer, &iter, mark);
 gtk_text_buffer_insert(buffer, &iter, text, -1);
 }

Retrieving Text Iterators and Marks

 mark = gtk_text_buffer_get_insert();
 gtk_text_buffer_get_iter_at_mark();
 gtk_text_buffer_get_bounds();
 gtk_text_buffer_get_text();
 gtk_text_buffer_get_iter_at_offset();
 gtk_text_buffer_get_iter_at_line();

Changing Text Buffer Contents

 gtk_text_buffer_get_insert();
 gtk_text_buffer_insert_at_cursor()
 gtk_text_buffer_delete();

Cutting Copying and Pasting Text