GTK-SHEET TUTORIAL |
GTK-EXTRA
Reference Manual Author: Victor Mierla aka Kornos <kornos@softhome.net>
. |
INDEX 1. Introduction 2. Creating a sheet 3. Sheet signals 4. Modifying cell contents
4.1 - functions that modify a cell 4.2 - functions that modify a range of cells 4.3 - functions that modify all cells from the sheet 4.4 - functions that set row/column titles , sheet title , etc
5. Modifying sheet state
6. Selections 7. Row/column operations
Remark : This tutorial does not cover all functions from GtkSheet library. It it only a reference to the most important(used) functions. This tutorial may contain errors or inaccuracies .Please mail me <kornos@softhome.net> in such a case.
1.Introduction
GtkSheet is a spreadsheet widget for Gtk (an Excel-like table) Internally, GtkSheet allocates memory for the sheet cells contents using an array of pointers to GtkSheetEntry widgets. A GtkSheetEntry widget( a cell in fact) is a GtkEntry subclass with the following differences : - It doesn't draw the border. - It is dinamically resized as the text is typed. - It allows right/left/center text justification (gtk_entry_size_allocate & entry_adjust_scroll) In a cell you may pack text , pictures or other widgets. Unfortunately, GtkEntry is a one text-line widget, so if you are searching for a Word-cell like behaviour(a multi -line cell) , you should probably consider checking other widgets(?!) or rewrite GtkSheet :-) The maximum number of rows/columns in a sheet is stored in a guint so in fact the maximum size of the sheet practically depends on the available memory in your system. 2. Creating a sheet The first step when you write a program using GtkSheet is to create the sheet widget and to pack it into a scrolled window. If you'll pack the sheet into a normal window you'll receive some warnings about adjustment signals.
window = gtk_window_new (GTK_WINDOW_TOPLEVEL); ............................... window_box= gtk_vbox_new (FALSE,TRUE); scrolled_window=gtk_scrolled_window_new(NULL, NULL); gtk_container_add (GTK_CONTAINER (window), window_box); gtk_box_pack_start (GTK_BOX (window_box), scrolled_window, 1,1,1); sheet=gtk_sheet_new(3,11,"Edit table"); GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_AUTORESIZE); gtk_container_add(GTK_CONTAINER(scrolled_window), sheet); gtk_widget_show_all(window); |
You should set the GTK_SHEET_AUTORESIZE flag so the cell would resize as you type. GtkSheet can be created with a custom entry widget. You can use GtkEntry or a GtkEntry subclass
(e.g. GtkSheetEntry, GtkSpinButton) or a box or table containing a GtkEntry subclass (e.g. GtkCombo)
gtk_sheet_new_with_custom_entry (gint nrows, gint ncols, GtkType *entry_type); |
if you want to construct a non-editable spreadsheet ( called "browser sheet") , just fow viewing purposes use:
gtk_sheet_construct_browser(GtkSheet *sheet,guint rows,guint columns, const gchar *title); |
The lines and columns(white coloured
by default) are numbered from 0 to max row/col number.
The gray row/col are numbered -1 .
Screenshot :
![]() |
3. Sheet signals The interaction between user and sheet is done(as in all Gtk programs) through signals. In GtkSheet the next signals are implemented : SELECT_ROW, SELECT_COLUMN, SELECT_RANGE, CLIP_RANGE, RESIZE_RANGE, MOVE_RANGE, TRAVERSE, DEACTIVATE, ACTIVATE, SET_CELL, CLEAR_CELL, CHANGED, NEW_COL_WIDTH, NEW_ROW_HEIGHT, LAST_SIGNAL If you're trying to catch these signals , you should connect them to a callback(function that treats the signal/event). If these notions seem strange to you , perhaps it's better to read the Gtk/Gnome documentation . The most used signals (by me at least) are : ACTIVATE,DEACTIVATE,TRAVERSE. Callback functions for different signals have different parameters. For a correct use you should check out the Gtk-Extra Reference Manual , the examples or Gtk-Extra source code. Incorrect use of the callback function parameters should have an undefined result(in the worst cases) The ACTIVATE signal should be connected if you want to do something when a cell is clicked:
gtk_signal_connect(GTK_OBJECT(sheet), "activate", (GtkSignalFunc) alarm_activate, NULL); The callback function should have these parameters: gint alarm_activate(GtkWidget *sheet, gint row, gint col, gpointer data) { ................ } |
If you have different functions that require the same cell to behave in a different way , I suggest that
instead of writing "n" alarm_activate() callbacks , write just one callback function that looks like this:
gtk_signal_connect(GTK_OBJECT(sheet), "activate", (GtkSignalFunc) alarm_activate, (gpointer)function_name); When the signal is connected , pass the function name (for example) as the last parameter. gint alarm_activate(GtkWidget *sheet, gint row, gint col, gpointer function_name) { if(strcmp(function_name,"table_new")==0){ .....do_some_stuf() } else if(strcmp(function_name,"table_edit")==0){ .....do_other_stuf() } } In this way , you'll have a much cleaner code , with as few functions as possible. It is better to have a single callback function that treats all posible behaviour cases , |
A very important signal is TRAVERSE.
gtk_signal_connect(GTK_OBJECT(sheet), "traverse", (GtkSignalFunc) alarm_traverse, NULL); The callback function should have these parameters: gint alarm_traverse(GtkWidget *widget, gint row, gint col, gint *new_row, gint *new_col, gpointer data) { ........... } |
The "traverse" signal is emited before "deactivate_cell" and allows to veto the movement. In such case, the entry will remain in the site, and the other signals will not be emited. The traverse signal is useful when you need to know in what cell have you previously clicked or what was selected. The explanation for the the other signals is quite straightforward so if you want more details you should check
GtkExtra Reference Manual or the GtkExtra source code. REMARK: Adrian told me that a callback function should ALWAYS return TRUE or FALSE. Otherwise BUGZ may occur. 4. Modifying cell contents As previously stated , a cell may contain text, picture or other widgets. GtkSheet functions can be categorized after the number of modified cells: 4.1 - functions that modify a cell 4.2 - functions that modify a range of cells 4.3 - functions that modify all cells from the sheet 4.4 - functions that set row/column titles , sheet title , etc 4.1 Functions that modify a cell * A cell text is set by:
/* Set a cell text with justification */ void gtk_sheet_set_cell (GtkSheet *sheet, gint row, gint col, GtkJustification justification, const gchar *text); /* No justification is made */ void gtk_sheet_set_cell_text (GtkSheet *sheet, gint row, gint col, const gchar *text); |
The text string will be strdup()'ed by the gtkextra library so you may free your string after this line. Do not free the internally allocated string ! This will be done by the library at the destruction of the sheet or when the gtk_sheet_set_cell is called again. The text justification in the cell may be : GTK_JUSTIFY_LEFT, GTK_JUSTIFY_RIGHT, GTK_JUSTIFY_CENTER * A cell text may be read by :
gchar * gtk_sheet_cell_get_text (GtkSheet *sheet, gint row, gint col); |
Screenshot:
![]() |
* A cell text may be deleted by :
void gtk_sheet_cell_clear(GtkSheet *sheet, gint row, gint col); - delete cell contents |
* You may change background/foreground color of cell (a cell, a range of cells or the whole sheet). See the example in the manual . * You can pack a xpm into a cell like this :
GtkWidget *sheet,*bullet; |
Screenshot:
![]() |
* You can pack a combo box into a cell like this ( my way,it needs improvement ) :
GtkWidget *sheet,*combo; |
Screenshot :
The widgets can be added to a cell using these functions.
Some of them expand/shrink cell depending of widget size ,others don't.
See the GtkSheet manual for details
/* Attach widget at (row x,col y) starting at the upper left of the cell */ |
* You can set a link for each cell. This is in fact a pointer you want to be associated to the cell.
void gtk_sheet_link_cell(GtkSheet *sheet, gint row, gint col,gpointer link); |
4.2
Functions that modify a range of cells
A range of cells is in fact :
struct _GtkSheetRange |
Some functions operating on range of cells:
void gtk_sheet_get_visible_range (GtkSheet *sheet,GtkSheetRange *range); |
Remark:
/* When you declare a range like this:*/ |
Screenshot: Modifying the background color of a range
![]() |
4.3 Functions that modify all cells from the sheet
These functions are used
if you want the cells to contain the same widget.
These are some of them:
GtkWidget *gtk_sheet_new_with_custom_entry (guint rows, guint columns, const gchar *title,GtkType entry_type); |
* A row/column title can be set with:
void gtk_sheet_row_button_add_label (GtkSheet *sheet, gint row, const gchar *label); |
gtk_sheet_set_row_title()
is used for setting an internal label associated with a row.
Some people told that this is useless but i find it very usefull in some cases.
And one more thing : please don't ask again on the mailing list what this function
does.
The secret is unveiled now :-)
* The sheet title may be set with :
void gtk_sheet_set_title (GtkSheet *sheet, const gchar *title); |
* The dimensions
of the row/column titles may be set with the next functions.
These functions exist because you may want to resize the width of a column or
height of a row,
unless you set the autoresize flag, which will do it automaticaly for you.
void gtk_sheet_set_row_titles_width(GtkSheet *sheet, guint width); |
* Row/column
title justification is done with:
void gtk_sheet_set_row_titles_width(GtkSheet *sheet, guint width); |
* You can freeze/unfreeze
the sheet with:
void gtk_sheet_freeze (GtkSheet *sheet); |
* Set if cell contents can be edited or not in the given range:
void gtk_sheet_range_set_editable (GtkSheet *sheet, const GtkSheetRange *range, gint editable); |
*REMARK : From GtkExtra 1.0 sheet state will be set with functions:
void gtk_sheet_set_autoresize (GtkSheet *sheet, gboolean autoresize); gboolean gtk_sheet_autoresize (GtkSheet *sheet); void gtk_sheet_set_autoscroll (GtkSheet *sheet, gboolean autoscroll); gboolean gtk_sheet_autoscroll(GtkSheet *sheet); void gtk_sheet_set_clip_text (GtkSheet *sheet, gboolean clip_text); gboolean gtk_sheet_clip_text (GtkSheet *sheet); void gtk_sheet_set_locked (GtkSheet *sheet, gboolean lock); void gtk_sheet_locked (GtkSheet *sheet); void gtk_sheet_rows_set_resizable (GtkSheet *sheet, gboolean resizable); gboolean gtk_sheet_rows_resizable (GtkSheet *sheet); void gtk_sheet_columns_set_resizable (GtkSheet *sheet, gboolean resizable); gboolean gtk_sheet_columns_resizable (GtkSheet *sheet); void gtk_sheet_show_column_titles (GtkSheet *sheet); void gtk_sheet_show_row_titles (GtkSheet *sheet); void gtk_sheet_hide_column_titles (GtkSheet *sheet); void gtk_sheet_hide_row_titles (GtkSheet *sheet); gboolean gtk_sheet_column_titles_visible (GtkSheet *sheet); gboolean gtk_sheet_row_titles_visible (GtkSheet *sheet); void gtk_sheet_set_justify_entry (GtkSheet *sheet, gboolean justify); gboolean gtk_sheet_justify_entry (GtkSheet *sheet); |
*Up to (including) GtkExtra 0.99.17 Sheet state is mainly set by a set of macros:
GTK_SHEET_AUTORESIZE(sheet) |
* Select a row/column:
void gtk_sheet_select_row (GtkSheet * sheet,gint row); |
* (Un)Select a
range:
void gtk_sheet_select_range (GtkSheet *sheet, const GtkSheetRange *range); |
A row/column selection can be catched using "select_row" and "select_column" signals:
void (*select_row) (GtkSheet *sheet, gint row); |
The most common row/column operations are:
- insertion
- deletion
- finding the number of row/cols
void gtk_sheet_add_column (GtkSheet *sheet, guint ncols); |
|
|
|