add section on GtkCList widget, contributed by Stefan Mars

Thu Jun 25 07:53:51 BST 1998  Tony Gale  <gale@gtk.org>

        * docs/gtk_tut.sgml: add section on GtkCList widget, contributed                                       by Stefan Mars <mars@lysator.liu.se>
        * examples/clist/clist.c examples/clist/Makefile: example code
          for GtkCList widget from the Tutorial
This commit is contained in:
BST 1998 Tony Gale 1998-06-25 08:57:29 +00:00 committed by Tony Gale
parent e5e47e6879
commit 713cecba4c
11 changed files with 1660 additions and 12 deletions

View File

@ -1,3 +1,10 @@
Thu Jun 25 07:53:51 BST 1998 Tony Gale <gale@gtk.org>
* docs/gtk_tut.sgml: add section on GtkCList widget, contributed
by Stefan Mars <mars@lysator.liu.se>
* examples/clist/clist.c examples/clist/Makefile: example code
for GtkCList widget from the Tutorial
Wed Jun 24 16:38:02 1998 Tim Janik <timj@gtk.org>
* gtk/gtkbin.c (gtk_bin_remove): do not avoid to queue for a resize

View File

@ -1,3 +1,10 @@
Thu Jun 25 07:53:51 BST 1998 Tony Gale <gale@gtk.org>
* docs/gtk_tut.sgml: add section on GtkCList widget, contributed
by Stefan Mars <mars@lysator.liu.se>
* examples/clist/clist.c examples/clist/Makefile: example code
for GtkCList widget from the Tutorial
Wed Jun 24 16:38:02 1998 Tim Janik <timj@gtk.org>
* gtk/gtkbin.c (gtk_bin_remove): do not avoid to queue for a resize

View File

@ -1,3 +1,10 @@
Thu Jun 25 07:53:51 BST 1998 Tony Gale <gale@gtk.org>
* docs/gtk_tut.sgml: add section on GtkCList widget, contributed
by Stefan Mars <mars@lysator.liu.se>
* examples/clist/clist.c examples/clist/Makefile: example code
for GtkCList widget from the Tutorial
Wed Jun 24 16:38:02 1998 Tim Janik <timj@gtk.org>
* gtk/gtkbin.c (gtk_bin_remove): do not avoid to queue for a resize

View File

@ -1,3 +1,10 @@
Thu Jun 25 07:53:51 BST 1998 Tony Gale <gale@gtk.org>
* docs/gtk_tut.sgml: add section on GtkCList widget, contributed
by Stefan Mars <mars@lysator.liu.se>
* examples/clist/clist.c examples/clist/Makefile: example code
for GtkCList widget from the Tutorial
Wed Jun 24 16:38:02 1998 Tim Janik <timj@gtk.org>
* gtk/gtkbin.c (gtk_bin_remove): do not avoid to queue for a resize

View File

@ -1,3 +1,10 @@
Thu Jun 25 07:53:51 BST 1998 Tony Gale <gale@gtk.org>
* docs/gtk_tut.sgml: add section on GtkCList widget, contributed
by Stefan Mars <mars@lysator.liu.se>
* examples/clist/clist.c examples/clist/Makefile: example code
for GtkCList widget from the Tutorial
Wed Jun 24 16:38:02 1998 Tim Janik <timj@gtk.org>
* gtk/gtkbin.c (gtk_bin_remove): do not avoid to queue for a resize

View File

@ -1,3 +1,10 @@
Thu Jun 25 07:53:51 BST 1998 Tony Gale <gale@gtk.org>
* docs/gtk_tut.sgml: add section on GtkCList widget, contributed
by Stefan Mars <mars@lysator.liu.se>
* examples/clist/clist.c examples/clist/Makefile: example code
for GtkCList widget from the Tutorial
Wed Jun 24 16:38:02 1998 Tim Janik <timj@gtk.org>
* gtk/gtkbin.c (gtk_bin_remove): do not avoid to queue for a resize

View File

@ -1,3 +1,10 @@
Thu Jun 25 07:53:51 BST 1998 Tony Gale <gale@gtk.org>
* docs/gtk_tut.sgml: add section on GtkCList widget, contributed
by Stefan Mars <mars@lysator.liu.se>
* examples/clist/clist.c examples/clist/Makefile: example code
for GtkCList widget from the Tutorial
Wed Jun 24 16:38:02 1998 Tim Janik <timj@gtk.org>
* gtk/gtkbin.c (gtk_bin_remove): do not avoid to queue for a resize

View File

@ -10,7 +10,7 @@
name="&lt;imain@gtk.org&gt;"></tt>,
Tony Gale <tt><htmlurl url="mailto:gale@gtk.org"
name="&lt;gale@gtk.org&gt;"></tt>
<date>June 2nd, 1998
<date>June 24th, 1998
<!-- ***************************************************************** -->
<sect>Introduction
@ -4374,9 +4374,719 @@ main (int argc, char *argv[])
}
/* example-end */
</verb></tscreen>
<!-- ***************************************************************** -->
<sect> List Widgets
<sect>CList Widget
<!-- ***************************************************************** -->
<!-- ----------------------------------------------------------------- -->
<p>
The GtkCList widget has replaced the GtkList widget (which is still
available).
The GtkCList widget is a multi-column list widget that is capable of
handling literally thousands of rows of information. Each column can
optionally have a title, which itself is optionally active, allowing
us to bind a function to it's selection.
<!-- ----------------------------------------------------------------- -->
<sect1>Creating a GtkCList widget
<p>
Creating a GtkCList is quite straightforward, once you have learned about
widgets in general. It provides the almost standard two ways, that is the
hard way, and the easy way. But before we create it, there is one thing we
should figure out beforehand: how many columns should it have?
Not all columns have to be visible and can be used to store data that is
related to a certain cell in the list.
<tscreen><verb>
GtkWidget *gtk_clist_new ( gint columns );
GtkWidget *gtk_clist_new_with_titles( gint columns,
gchar *titles[] );
</verb></tscreen>
The first form is very straight forward, the second might require some
explanation. Each column can have a title associated with it, and this
title can be a label or a button that reacts when we click on it. If we
use the second form, we must provide pointers to the title texts, and the
number of pointers should equal the number of columns specified. Of course
we can always use the first form, and manually add titles later.
<!-- ----------------------------------------------------------------- -->
<sect1>Modes of operation
<p>
There are several attributes that can be used to alter the behaviour of
a GtkCList. First there is
<tscreen><verb>
void gtk_clist_set_selection_mode( GtkCList *clist,
GtkSelectionMode mode );
</verb></tscreen>
which, as the name implies, sets the selection mode of the GtkCList. The first
argument is the GtkCList widget, and the second specifies the cell selection
mode (they are defined in gtkenums.h). At the time of this writing, the following
modes are available to us:
<itemize>
<item> GTK_SELECTION_SINGLE - The selection is either NULL or contains a GList
pointer for a single selected item.
<item> GTK_SELECTION_BROWSE - The selection is NULL if the list contains no
widgets or insensitive ones only, otherwise it contains a GList pointer for
one GList structure, and therefore exactly one list item.
<item> GTK_SELECTION_MULTIPLE - The selection is NULL if no list items are
selected or a GList pointer for the first selected item. That in turn points
to a GList structure for the second selected item and so on. This is currently
the <bf>default</bf> for the GtkCList widget.
<item> GTK_SELECTION_EXTENDED - The selection is always NULL.
</itemize>
Others might be added in later revisions of GTK.
Then there is
<tscreen><verb>
void gtk_clist_set_policy (GtkCList * clist,
GtkPolicyType vscrollbar_policy,
GtkPolicyType hscrollbar_policy);
</verb></tscreen>
which defines what happens to the scrollbars. The following values are possible
for both the vertical and the horizontal scrollbar:
<itemize>
<item> GTK_POLICY_ALWAYS - The scrollbar will always be there.
<item> GTK_POLICY_AUTOMATIC - The scrollbar will be there only when the number
of items in the GtkCList exceeds the number that can be shown in the widget.
</itemize>
We can also define what the border of the GtkCList widget should look like. It is
done through
<tscreen><verb>
void gtk_clist_set_border( GtkCList *clist,
GtkShadowType border );
</verb></tscreen>
And the possible values for the second argument are
<itemize>
<item> GTK_SHADOW_NONE
<item> GTK_SHADOW_IN
<item> GTK_SHADOW_OUT
<item> GTK_SHADOW_ETCHED_IN
<item> GTK_SHADOW_ETCHED_OUT
</itemize>
<!-- ----------------------------------------------------------------- -->
<sect1>Working with titles
<p>
When you create a GtkCList widget, you will also get a set of title buttons
automatically. They live in the top of the CList window, and can act either
as normal buttons that respond to being pressed, or they can be passive,
in which case they are nothing more than a title. There are four different
calls that aid us in setting the status of the title buttons.
<tscreen><verb>
void gtk_clist_column_title_active( GtkCList *clist,
gint column );
void gtk_clist_column_title_passive( GtkCList *clist,
gint column );
void gtk_clist_column_titles_active( GtkCList *clist );
void gtk_clist_column_titles_passive( GtkCList *clist );
</verb></tscreen>
An active title is one which acts as a normal button, a passive one is just
a label. The first two calls above will activate/deactivate the title button
above the specific column, while the last two calls activate/deactivate all
title buttons in the supplied clist widget.
But of course there are those cases when we don't want them at all, and so
they can be hidden and shown at will using the following two calls.
<tscreen><verb>
void gtk_clist_column_titles_show( GtkCList *clist );
void gtk_clist_column_titles_hide( GtkCList *clist );
</verb></tscreen>
For titles to be really useful we need a mechanism to set and change them,
and this is done using
<tscreen><verb>
void gtk_clist_set_column_title( GtkCList *clist,
gint column,
gchar *title );
</verb></tscreen>
Note that only the title of one column can be set at a time, so if all the
titles are known from the beginning, then I really suggest using
gtk_clist_new_with_titles (as described above) to set them. Saves you
coding time, and makes your program smaller. There are some cases where
getting the job done the manual way is better, and that's when not all
titles will be text. GtkCList provides us with title buttons that can in fact
incorporate whole widgets, for example a pixmap. It's all done through
<tscreen><verb>
void gtk_clist_set_column_widget( GtkCList *clist,
gint column,
GtkWidget *widget );
</verb></tscreen>
which should require no special explanation.
<!-- ----------------------------------------------------------------- -->
<sect1>Manipulating the list itself
<p>
It is possible to change the justification for a column, and it is done through
<tscreen><verb>
void gtk_clist_set_column_justification( GtkCList *clist,
gint column,
GtkJustification justification );
</verb></tscreen>
The GtkJustification type can take the following values:
<itemize>
<item>GTK_JUSTIFY_LEFT - The text in the column will begin from the left edge.
<item>GTK_JUSTIFY_RIGHT - The text in the column will begin from the right edge.
<item>GTK_JUSTIFY_CENTER - The text is placed in the center of the column.
<item>GTK_JUSTIFY_FILL - The text will use up all available space in the
column. It is normally done by inserting extra blank spaces between words
(or between inidvidual letters of it's a single word). Much in the same way as
any ordinary WYSIWYG text editor.
</itemize>
The next function is a very important one, and should be standard in the setup
of all GtkCList widgets. When the list is created, the width of the various
columns are chosen to match their titles, and since this is seldom the right
width we have to set it using
<tscreen><verb>
void gtk_clist_set_column_width( GtkCList *clist,
gint column,
gint width );
</verb></tscreen>
Note that the width is given in pixels and not letters. The same goes for the
height of the cells in the columns, but as the default value is the height of
the current font this isn't as critical to the application. Still, it is done through
<tscreen><verb>
void gtk_clist_set_row_height( GtkCList *clist,
gint height );
</verb></tscreen>
Again, note that the height is given in pixels.
We can also move the list around without user interaction, however, it does
require that we know what we are looking for. Or in other words, we need the row
and column of the item we want to scroll to.
<tscreen><verb>
void gtk_clist_moveto( GtkCList *clist,
gint row,
gint column,
gfloat row_align,
gfloat col_align );
</verb></tscreen>
The gfloat row_align is pretty important to understand. It's a value between 0.0 and
1.0, where 0.0 means that we should scroll the list so the row appears at the top,
while if the value of row_align is 1.0, the row will appear at the bottom instead. All
other values between 0.0 and 1.0 are also valid and will place the row between the top
and the bottom. The last argument, gfloat col_align works in the same way, though 0.0
marks left and 1.0 marks right instead.
Depending on the application's needs, we don't have to scroll to an item that is
already visible to us. So how do we know if it is visible? As usual, there is a function
to find that out as well.
<tscreen><verb>
GtkVisibility gtk_clist_row_is_visible( GtkCList *clist,
gint row );
</verb></tscreen>
The return value is is one of the following:
<itemize>
<item>GTK_VISIBILITY_NONE
<item>GTK_VISIBILITY_PARTIAL
<item>GTK_VISIBILITY_FULL
</itemize>
Note that it will only tell us if a row is visible. Currently there is no way to
determine this for a column. We can get partial information though, because if
the return is GTK_VISIBILITY_PARTIAL, then some of it is hidden, but we don't know if
it is the row that is being cut by the lower edge of the listbox, or if the row has
columns that are outside.
We can also change both the foreground and background colors of a particular
row. This is useful for marking the row selected by the user, and the two functions
that is used to do it are
<tscreen><verb>
void gtk_clist_set_foreground( GtkCList *clist,
gint row,
GdkColor *color );
void gtk_clist_set_background( GtkCList *clist,
gint row,
GdkColor *color );
</verb></tscreen>
Please note that the colors must have been previously allocated.
<!-- ----------------------------------------------------------------- -->
<sect1>Adding rows to the list
<p>
We can add rows in two ways. They can be appended at the end to the list using
<tscreen><verb>
gint gtk_clist_append( GtkCList *clist,
gchar *text[] );
</verb></tscreen>
or we can insert a row at a given place using
<tscreen><verb>
void gtk_clist_insert( GtkCList *clist,
gint row,
gchar *text[] );
</verb></tscreen>
In both calls we have to provide a collection of pointers that are the texts
we want to put in the columns. The number of pointers should equal the number
of columns in the list. If the text[] argument is NULL, then there will be no
text in the columns of the row. This is useful, for example, if we want to
add pixmaps instead (something that has to be done manually).
Also, please note that the numbering of both rows and columns start at 0.
To remove an individual row we use
<tscreen><verb>
void gtk_clist_remove( GtkCList *clist,
gint row );
</verb></tscreen>
There is also a call that removes all rows in the list. This is a lot faster
than calling gtk_clist_remove once for each row, which is the only alternative.
<tscreen><verb>
void gtk_clist_clear( GtkCList *clist );
</verb></tscreen>
There are also two convenience functions that should be used when a lot of
changes have to be made to the list. This is to prevent the list flickering while
being repeatedly updated, which may be highly annoying to the user. So instead it
is a good idea to freeze the list, do the updates to it, and finally thaw it which
causes the list to be updated on the screen.
<tscreen><verb>
void gtk_clist_freeze( GtkCList * clist );
void gtk_clist_thaw( GtkCList * clist );
</verb></tscreen>
<!-- ----------------------------------------------------------------- -->
<sect1>Setting text and pixmaps in the cells
<p>
A cell can contain a pixmap, text or both. To set them the following
functions are used.
<tscreen><verb>
void gtk_clist_set_text( GtkCList *clist,
gint row,
gint column,
gchar *text );
void gtk_clist_set_pixmap( GtkCList *clist,
gint row,
gint column,
GdkPixmap *pixmap,
GdkBitmap *mask );
void gtk_clist_set_pixtext( GtkCList *clist,
gint row,
gint column,
gchar *text,
guint8 spacing,
GdkPixmap *pixmap,
GdkBitmap *mask );
</verb></tscreen>
It's quite straightforward. All the calls have the GtkCList as the first
argument, followed by the row and column of the cell, follwed by the data to be
set. The gint8 spacing argument in gtk_clist_set_pixtext is the number of pixels
between the pixmap and the beginning of the text.
To read back the data, we instead use
<tscreen><verb>
gint gtk_clist_get_text( GtkCList *clist,
gint row,
gint column,
gchar **text );
gint gtk_clist_get_pixmap( GtkCList *clist,
gint row,
gint column,
GdkPixmap **pixmap,
GdkBitmap **mask );
gint gtk_clist_get_pixtext( GtkCList *clist,
gint row,
gint column,
gchar **text,
guint8 *spacing,
GdkPixmap **pixmap,
GdkBitmap **mask );
</verb></tscreen>
It isn't necessary to read it all back in case you aren't interested. Any
of the pointers that are meant for return values (all except the clist) can
be NULL. So if we want to read back only the text from a cell that is of
type pixtext, then we would do the following, assuming that clist, row and
column already exist:
<tscreen><verb>
gchar *mytext;
gtk_clist_get_pixtext(clist, row, column, &amp;mytext, NULL, NULL, NULL);
</verb></tscreen>
There is one more call that is related to what's inside a cell in the
clist, and that's
<tscreen><verb>
GtkCellType gtk_clist_get_cell_type( GtkCList *clist,
gint row,
gint column );
</verb></tscreen>
which returns the type of data in a cell. The return value is one of
<itemize>
<item>GTK_CELL_EMPTY
<item>GTK_CELL_TEXT
<item>GTK_CELL_PIXMAP
<item>GTK_CELL_PIXTEXT
<item>GTK_CELL_WIDGET
</itemize>
There is also a function that will let us set the indentation, both
vertical and horizontal, of a cell. The indentation value is of type gint,
given in pixels, and can be both positive and negative.
<tscreen><verb>
void gtk_clist_set_shift( GtkCList *clist,
gint row,
gint column,
gint vertical,
gint horizontal );
</verb></tscreen>
<!-- ----------------------------------------------------------------- -->
<sect1>Storing data pointers
<p>
With a GtkCList it is possible to set a data pointer for a row. This
pointer will not be visible for the user, but is merely a convinience for
the programmer to associate a row with a pointer to some additional data.
The functions should be fairly self-explanatory by now
<tscreen><verb>
void gtk_clist_set_row_data( GtkCList *clist,
gint row,
gpointer data );
void gtk_clist_set_row_data_full( GtkCList *clist,
gint row,
gpointer data,
GtkDestroyNotify destroy );
gpointer gtk_clist_get_row_data( GtkCList *clist,
gint row );
gint gtk_clist_find_row_from_data( GtkCList *clist,
gpointer data );
</verb></tscreen>
<!-- ----------------------------------------------------------------- -->
<sect1>Working with selections
<p>
There are also functions available that let us force the (un)selection
of a row. These are
<tscreen><verb>
void gtk_clist_select_row( GtkCList *clist,
gint row,
gint column );
void gtk_clist_unselect_row( GtkCList *clist,
gint row,
gint column );
</verb></tscreen>
And also a function that will take x and y coordinates (for example, read from
the mousepointer), and map that onto the list, returning the
corresponding row and column.
<tscreen><verb>
gint gtk_clist_get_selection_info( GtkCList *clist,
gint x,
gint y,
gint *row,
gint *column );
</verb></tscreen>
When we detect something of interest, it might be movement of the pointer, a
click somewhere in the list, we can read the pointer coordinates and find out
where in the list the pointer is. Cumbersome? Luckily, there is a more simple way...
<!-- ----------------------------------------------------------------- -->
<sect1>The signals that bring it together
<p>
As with all other widgets, there are a few signals that can be used. The
GtkCList widget is derived from the GtkContainer widget, and so has all the
same signals, but also the adds following:
<itemize>
<item>select_row - This signal will send the following information, in
order: GtkCList *clist, gint row, gint column, GtkEventButton *event
<item>unselect_row - When the user unselects a row, this signal is activated. It
sends the same information as select_row
<item>click_column - Send GtkCList *clist, gint column
</itemize>
So if we want to connect a callback to select_row, the callback function would
be declared like this
<tscreen><verb>
void select_row_callback(GtkWidget *widget,
gint row,
gint column,
GdkEventButton *event,
gpointer data);
</verb></tscreen>
The callback is connected as usual with
<tscreen><verb>
gtk_signal_connect(GTK_OBJECT( clist),
"select_row"
GTK_SIGNAL_FUNC(select_row_callback),
NULL);
</verb></tscreen>
<!-- ----------------------------------------------------------------- -->
<sect1>A GtkCList example
<p>
<tscreen><verb>
/* example-start clist clist.c */
#include <gtk/gtk.h>
#include <glib.h>
/* These are just the prototypes of the various callbacks */
void button_add_clicked( GtkWidget *button, gpointer data);
void button_clear_clicked( GtkWidget *button, gpointer data);
void button_hide_show_clicked( GtkWidget *button, gpointer data);
void selection_made( GtkWidget *clist, gint row, gint column,
GdkEventButton *event, gpointer data);
gint main (int argc, gchar *argv[])
{
GtkWidget *window;
GtkWidget *vbox, *hbox;
GtkWidget *clist;
GtkWidget *button_add, *button_clear, *button_hide_show;
gchar *titles[2] = {"Ingredients","Amount"};
gtk_init(&amp;argc, &amp;argv);
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_set_usize(GTK_WIDGET(window), 300, 150);
gtk_window_set_title(GTK_WINDOW(window), "GtkCList Example");
gtk_signal_connect(GTK_OBJECT(window),
"destroy",
GTK_SIGNAL_FUNC(gtk_main_quit),
NULL);
vbox=gtk_vbox_new(FALSE, 5);
gtk_container_border_width(GTK_CONTAINER(vbox), 5);
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_widget_show(vbox);
/* Create the GtkCList. For this example we use 2 columns */
clist = gtk_clist_new_with_titles( 2, titles);
/* When a selection is made, we want to know about it. The callback
* used is selection_made, and it's code can be found further down */
gtk_signal_connect(GTK_OBJECT(clist), "select_row",
GTK_SIGNAL_FUNC(selection_made),
NULL);
/* It isn't necessary to shadow the border, but it looks nice :) */
gtk_clist_set_border(GTK_CLIST(clist), GTK_SHADOW_OUT);
/* What however is important, is that we set the column widths as
* they will never be right otherwise. Note that the columns are
* numbered from 0 and up (to 1 in this case).
*/
gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150);
/* Scollbars _only when needed_ */
gtk_clist_set_policy(GTK_CLIST(clist), GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
/* Add the GtkCList widget to the vertical box and show it. */
gtk_box_pack_start(GTK_BOX(vbox), clist, TRUE, TRUE, 0);
gtk_widget_show(clist);
/* Create the buttons and add them to the window. See the button
* tutorial for more examples and comments on this.
*/
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
gtk_widget_show(hbox);
button_add = gtk_button_new_with_label("Add List");
button_clear = gtk_button_new_with_label("Clear List");
button_hide_show = gtk_button_new_with_label("Hide/Show titles");
gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0);
/* Connect our callbacks to the three buttons */
gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked",
GTK_SIGNAL_FUNC(button_add_clicked),
(gpointer) clist);
gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked",
GTK_SIGNAL_FUNC(button_clear_clicked),
(gpointer) clist);
gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked",
GTK_SIGNAL_FUNC(button_hide_show_clicked),
(gpointer) clist);
gtk_widget_show(button_add);
gtk_widget_show(button_clear);
gtk_widget_show(button_hide_show);
/* The interface is completely set up so we show the window and
* enter the gtk_main loop.
*/
gtk_widget_show(window);
gtk_main();
return 0;
}
/* User clicked the "Add List" button. */
void button_add_clicked( GtkWidget *button, gpointer data)
{
int indx;
/* Something silly to add to the list. 4 rows of 2 columns each */
gchar *drink[4][2] = {{"Milk", "3 Oz"},
{"Water", "6 l"},
{"Carrots", "2"},
{"Snakes", "55"}};
/* Here we do the actual adding of the text. It's done once for
* each row.
*/
for( indx=0; indx < 4; indx++)
gtk_clist_append( (GtkCList*) data, drink[indx]);
return;
}
/* User clicked the "Clear List" button. */
void button_clear_clicked( GtkWidget *button, gpointer data)
{
/* Clear the list using gtk_clist_clear. This is much faster than
* calling gtk_clist_remove once for each row.
*/
gtk_clist_clear((GtkCList*) data);
return;
}
/* The user clicked the "Hide/Show titles" button. */
void button_hide_show_clicked( GtkWidget *button, gpointer data)
{
/* Just a flag to remember the status. 0 = currently visible */
static short int flag = 0;
if (flag == 0)
{
/* Hide the titles and set the flag to 1 */
gtk_clist_column_titles_hide((GtkCList*) data);
flag++;
}
else
{
/* Show the titles and reset flag to 0 */
gtk_clist_column_titles_show((GtkCList*) data);
flag--;
}
return;
}
/* If we come here, then the user has selected a row in the list. */
void selection_made( GtkWidget *clist, gint row, gint column,
GdkEventButton *event, gpointer data)
{
gchar *text;
/* Get the text that is stored in the selected row and column
* which was clicked in. We will receive it as a pointer in the
* argument text.
*/
gtk_clist_get_text(GTK_CLIST(clist), row, column, &amp;text);
/* Just prints some information about the selected row */
g_print("You selected row %d. More specifically you clicked in column %d, and the text in this cell is %s\n\n", row, column, text);
return;
}
/* example-end */
</verb></tscreen>
<!-- ***************************************************************** -->
<sect> List Widget
<!-- ***************************************************************** -->
<p>
NOTE: The GtkList widget has been superseded by the GtkCList widget.
@ -5879,9 +6589,6 @@ from your time.
<sect1> Fixed Container
<p>
<!-- ----------------------------------------------------------------- -->
<sect1> CList
<p>
<!-- ----------------------------------------------------------------- -->
<sect1> Range Controls
<p>
<!-- ----------------------------------------------------------------- -->
@ -6557,6 +7264,8 @@ void input_callback( gpointer data,
GdkInputCondition condition );
</verb></tscreen>
Where <tt/source/ and <tt/condition/ are as specified above.
<!-- ----------------------------------------------------------------- -->
<sect1>Idle Functions
<p>

View File

@ -10,7 +10,7 @@
name="&lt;imain@gtk.org&gt;"></tt>,
Tony Gale <tt><htmlurl url="mailto:gale@gtk.org"
name="&lt;gale@gtk.org&gt;"></tt>
<date>June 2nd, 1998
<date>June 24th, 1998
<!-- ***************************************************************** -->
<sect>Introduction
@ -4374,9 +4374,719 @@ main (int argc, char *argv[])
}
/* example-end */
</verb></tscreen>
<!-- ***************************************************************** -->
<sect> List Widgets
<sect>CList Widget
<!-- ***************************************************************** -->
<!-- ----------------------------------------------------------------- -->
<p>
The GtkCList widget has replaced the GtkList widget (which is still
available).
The GtkCList widget is a multi-column list widget that is capable of
handling literally thousands of rows of information. Each column can
optionally have a title, which itself is optionally active, allowing
us to bind a function to it's selection.
<!-- ----------------------------------------------------------------- -->
<sect1>Creating a GtkCList widget
<p>
Creating a GtkCList is quite straightforward, once you have learned about
widgets in general. It provides the almost standard two ways, that is the
hard way, and the easy way. But before we create it, there is one thing we
should figure out beforehand: how many columns should it have?
Not all columns have to be visible and can be used to store data that is
related to a certain cell in the list.
<tscreen><verb>
GtkWidget *gtk_clist_new ( gint columns );
GtkWidget *gtk_clist_new_with_titles( gint columns,
gchar *titles[] );
</verb></tscreen>
The first form is very straight forward, the second might require some
explanation. Each column can have a title associated with it, and this
title can be a label or a button that reacts when we click on it. If we
use the second form, we must provide pointers to the title texts, and the
number of pointers should equal the number of columns specified. Of course
we can always use the first form, and manually add titles later.
<!-- ----------------------------------------------------------------- -->
<sect1>Modes of operation
<p>
There are several attributes that can be used to alter the behaviour of
a GtkCList. First there is
<tscreen><verb>
void gtk_clist_set_selection_mode( GtkCList *clist,
GtkSelectionMode mode );
</verb></tscreen>
which, as the name implies, sets the selection mode of the GtkCList. The first
argument is the GtkCList widget, and the second specifies the cell selection
mode (they are defined in gtkenums.h). At the time of this writing, the following
modes are available to us:
<itemize>
<item> GTK_SELECTION_SINGLE - The selection is either NULL or contains a GList
pointer for a single selected item.
<item> GTK_SELECTION_BROWSE - The selection is NULL if the list contains no
widgets or insensitive ones only, otherwise it contains a GList pointer for
one GList structure, and therefore exactly one list item.
<item> GTK_SELECTION_MULTIPLE - The selection is NULL if no list items are
selected or a GList pointer for the first selected item. That in turn points
to a GList structure for the second selected item and so on. This is currently
the <bf>default</bf> for the GtkCList widget.
<item> GTK_SELECTION_EXTENDED - The selection is always NULL.
</itemize>
Others might be added in later revisions of GTK.
Then there is
<tscreen><verb>
void gtk_clist_set_policy (GtkCList * clist,
GtkPolicyType vscrollbar_policy,
GtkPolicyType hscrollbar_policy);
</verb></tscreen>
which defines what happens to the scrollbars. The following values are possible
for both the vertical and the horizontal scrollbar:
<itemize>
<item> GTK_POLICY_ALWAYS - The scrollbar will always be there.
<item> GTK_POLICY_AUTOMATIC - The scrollbar will be there only when the number
of items in the GtkCList exceeds the number that can be shown in the widget.
</itemize>
We can also define what the border of the GtkCList widget should look like. It is
done through
<tscreen><verb>
void gtk_clist_set_border( GtkCList *clist,
GtkShadowType border );
</verb></tscreen>
And the possible values for the second argument are
<itemize>
<item> GTK_SHADOW_NONE
<item> GTK_SHADOW_IN
<item> GTK_SHADOW_OUT
<item> GTK_SHADOW_ETCHED_IN
<item> GTK_SHADOW_ETCHED_OUT
</itemize>
<!-- ----------------------------------------------------------------- -->
<sect1>Working with titles
<p>
When you create a GtkCList widget, you will also get a set of title buttons
automatically. They live in the top of the CList window, and can act either
as normal buttons that respond to being pressed, or they can be passive,
in which case they are nothing more than a title. There are four different
calls that aid us in setting the status of the title buttons.
<tscreen><verb>
void gtk_clist_column_title_active( GtkCList *clist,
gint column );
void gtk_clist_column_title_passive( GtkCList *clist,
gint column );
void gtk_clist_column_titles_active( GtkCList *clist );
void gtk_clist_column_titles_passive( GtkCList *clist );
</verb></tscreen>
An active title is one which acts as a normal button, a passive one is just
a label. The first two calls above will activate/deactivate the title button
above the specific column, while the last two calls activate/deactivate all
title buttons in the supplied clist widget.
But of course there are those cases when we don't want them at all, and so
they can be hidden and shown at will using the following two calls.
<tscreen><verb>
void gtk_clist_column_titles_show( GtkCList *clist );
void gtk_clist_column_titles_hide( GtkCList *clist );
</verb></tscreen>
For titles to be really useful we need a mechanism to set and change them,
and this is done using
<tscreen><verb>
void gtk_clist_set_column_title( GtkCList *clist,
gint column,
gchar *title );
</verb></tscreen>
Note that only the title of one column can be set at a time, so if all the
titles are known from the beginning, then I really suggest using
gtk_clist_new_with_titles (as described above) to set them. Saves you
coding time, and makes your program smaller. There are some cases where
getting the job done the manual way is better, and that's when not all
titles will be text. GtkCList provides us with title buttons that can in fact
incorporate whole widgets, for example a pixmap. It's all done through
<tscreen><verb>
void gtk_clist_set_column_widget( GtkCList *clist,
gint column,
GtkWidget *widget );
</verb></tscreen>
which should require no special explanation.
<!-- ----------------------------------------------------------------- -->
<sect1>Manipulating the list itself
<p>
It is possible to change the justification for a column, and it is done through
<tscreen><verb>
void gtk_clist_set_column_justification( GtkCList *clist,
gint column,
GtkJustification justification );
</verb></tscreen>
The GtkJustification type can take the following values:
<itemize>
<item>GTK_JUSTIFY_LEFT - The text in the column will begin from the left edge.
<item>GTK_JUSTIFY_RIGHT - The text in the column will begin from the right edge.
<item>GTK_JUSTIFY_CENTER - The text is placed in the center of the column.
<item>GTK_JUSTIFY_FILL - The text will use up all available space in the
column. It is normally done by inserting extra blank spaces between words
(or between inidvidual letters of it's a single word). Much in the same way as
any ordinary WYSIWYG text editor.
</itemize>
The next function is a very important one, and should be standard in the setup
of all GtkCList widgets. When the list is created, the width of the various
columns are chosen to match their titles, and since this is seldom the right
width we have to set it using
<tscreen><verb>
void gtk_clist_set_column_width( GtkCList *clist,
gint column,
gint width );
</verb></tscreen>
Note that the width is given in pixels and not letters. The same goes for the
height of the cells in the columns, but as the default value is the height of
the current font this isn't as critical to the application. Still, it is done through
<tscreen><verb>
void gtk_clist_set_row_height( GtkCList *clist,
gint height );
</verb></tscreen>
Again, note that the height is given in pixels.
We can also move the list around without user interaction, however, it does
require that we know what we are looking for. Or in other words, we need the row
and column of the item we want to scroll to.
<tscreen><verb>
void gtk_clist_moveto( GtkCList *clist,
gint row,
gint column,
gfloat row_align,
gfloat col_align );
</verb></tscreen>
The gfloat row_align is pretty important to understand. It's a value between 0.0 and
1.0, where 0.0 means that we should scroll the list so the row appears at the top,
while if the value of row_align is 1.0, the row will appear at the bottom instead. All
other values between 0.0 and 1.0 are also valid and will place the row between the top
and the bottom. The last argument, gfloat col_align works in the same way, though 0.0
marks left and 1.0 marks right instead.
Depending on the application's needs, we don't have to scroll to an item that is
already visible to us. So how do we know if it is visible? As usual, there is a function
to find that out as well.
<tscreen><verb>
GtkVisibility gtk_clist_row_is_visible( GtkCList *clist,
gint row );
</verb></tscreen>
The return value is is one of the following:
<itemize>
<item>GTK_VISIBILITY_NONE
<item>GTK_VISIBILITY_PARTIAL
<item>GTK_VISIBILITY_FULL
</itemize>
Note that it will only tell us if a row is visible. Currently there is no way to
determine this for a column. We can get partial information though, because if
the return is GTK_VISIBILITY_PARTIAL, then some of it is hidden, but we don't know if
it is the row that is being cut by the lower edge of the listbox, or if the row has
columns that are outside.
We can also change both the foreground and background colors of a particular
row. This is useful for marking the row selected by the user, and the two functions
that is used to do it are
<tscreen><verb>
void gtk_clist_set_foreground( GtkCList *clist,
gint row,
GdkColor *color );
void gtk_clist_set_background( GtkCList *clist,
gint row,
GdkColor *color );
</verb></tscreen>
Please note that the colors must have been previously allocated.
<!-- ----------------------------------------------------------------- -->
<sect1>Adding rows to the list
<p>
We can add rows in two ways. They can be appended at the end to the list using
<tscreen><verb>
gint gtk_clist_append( GtkCList *clist,
gchar *text[] );
</verb></tscreen>
or we can insert a row at a given place using
<tscreen><verb>
void gtk_clist_insert( GtkCList *clist,
gint row,
gchar *text[] );
</verb></tscreen>
In both calls we have to provide a collection of pointers that are the texts
we want to put in the columns. The number of pointers should equal the number
of columns in the list. If the text[] argument is NULL, then there will be no
text in the columns of the row. This is useful, for example, if we want to
add pixmaps instead (something that has to be done manually).
Also, please note that the numbering of both rows and columns start at 0.
To remove an individual row we use
<tscreen><verb>
void gtk_clist_remove( GtkCList *clist,
gint row );
</verb></tscreen>
There is also a call that removes all rows in the list. This is a lot faster
than calling gtk_clist_remove once for each row, which is the only alternative.
<tscreen><verb>
void gtk_clist_clear( GtkCList *clist );
</verb></tscreen>
There are also two convenience functions that should be used when a lot of
changes have to be made to the list. This is to prevent the list flickering while
being repeatedly updated, which may be highly annoying to the user. So instead it
is a good idea to freeze the list, do the updates to it, and finally thaw it which
causes the list to be updated on the screen.
<tscreen><verb>
void gtk_clist_freeze( GtkCList * clist );
void gtk_clist_thaw( GtkCList * clist );
</verb></tscreen>
<!-- ----------------------------------------------------------------- -->
<sect1>Setting text and pixmaps in the cells
<p>
A cell can contain a pixmap, text or both. To set them the following
functions are used.
<tscreen><verb>
void gtk_clist_set_text( GtkCList *clist,
gint row,
gint column,
gchar *text );
void gtk_clist_set_pixmap( GtkCList *clist,
gint row,
gint column,
GdkPixmap *pixmap,
GdkBitmap *mask );
void gtk_clist_set_pixtext( GtkCList *clist,
gint row,
gint column,
gchar *text,
guint8 spacing,
GdkPixmap *pixmap,
GdkBitmap *mask );
</verb></tscreen>
It's quite straightforward. All the calls have the GtkCList as the first
argument, followed by the row and column of the cell, follwed by the data to be
set. The gint8 spacing argument in gtk_clist_set_pixtext is the number of pixels
between the pixmap and the beginning of the text.
To read back the data, we instead use
<tscreen><verb>
gint gtk_clist_get_text( GtkCList *clist,
gint row,
gint column,
gchar **text );
gint gtk_clist_get_pixmap( GtkCList *clist,
gint row,
gint column,
GdkPixmap **pixmap,
GdkBitmap **mask );
gint gtk_clist_get_pixtext( GtkCList *clist,
gint row,
gint column,
gchar **text,
guint8 *spacing,
GdkPixmap **pixmap,
GdkBitmap **mask );
</verb></tscreen>
It isn't necessary to read it all back in case you aren't interested. Any
of the pointers that are meant for return values (all except the clist) can
be NULL. So if we want to read back only the text from a cell that is of
type pixtext, then we would do the following, assuming that clist, row and
column already exist:
<tscreen><verb>
gchar *mytext;
gtk_clist_get_pixtext(clist, row, column, &amp;mytext, NULL, NULL, NULL);
</verb></tscreen>
There is one more call that is related to what's inside a cell in the
clist, and that's
<tscreen><verb>
GtkCellType gtk_clist_get_cell_type( GtkCList *clist,
gint row,
gint column );
</verb></tscreen>
which returns the type of data in a cell. The return value is one of
<itemize>
<item>GTK_CELL_EMPTY
<item>GTK_CELL_TEXT
<item>GTK_CELL_PIXMAP
<item>GTK_CELL_PIXTEXT
<item>GTK_CELL_WIDGET
</itemize>
There is also a function that will let us set the indentation, both
vertical and horizontal, of a cell. The indentation value is of type gint,
given in pixels, and can be both positive and negative.
<tscreen><verb>
void gtk_clist_set_shift( GtkCList *clist,
gint row,
gint column,
gint vertical,
gint horizontal );
</verb></tscreen>
<!-- ----------------------------------------------------------------- -->
<sect1>Storing data pointers
<p>
With a GtkCList it is possible to set a data pointer for a row. This
pointer will not be visible for the user, but is merely a convinience for
the programmer to associate a row with a pointer to some additional data.
The functions should be fairly self-explanatory by now
<tscreen><verb>
void gtk_clist_set_row_data( GtkCList *clist,
gint row,
gpointer data );
void gtk_clist_set_row_data_full( GtkCList *clist,
gint row,
gpointer data,
GtkDestroyNotify destroy );
gpointer gtk_clist_get_row_data( GtkCList *clist,
gint row );
gint gtk_clist_find_row_from_data( GtkCList *clist,
gpointer data );
</verb></tscreen>
<!-- ----------------------------------------------------------------- -->
<sect1>Working with selections
<p>
There are also functions available that let us force the (un)selection
of a row. These are
<tscreen><verb>
void gtk_clist_select_row( GtkCList *clist,
gint row,
gint column );
void gtk_clist_unselect_row( GtkCList *clist,
gint row,
gint column );
</verb></tscreen>
And also a function that will take x and y coordinates (for example, read from
the mousepointer), and map that onto the list, returning the
corresponding row and column.
<tscreen><verb>
gint gtk_clist_get_selection_info( GtkCList *clist,
gint x,
gint y,
gint *row,
gint *column );
</verb></tscreen>
When we detect something of interest, it might be movement of the pointer, a
click somewhere in the list, we can read the pointer coordinates and find out
where in the list the pointer is. Cumbersome? Luckily, there is a more simple way...
<!-- ----------------------------------------------------------------- -->
<sect1>The signals that bring it together
<p>
As with all other widgets, there are a few signals that can be used. The
GtkCList widget is derived from the GtkContainer widget, and so has all the
same signals, but also the adds following:
<itemize>
<item>select_row - This signal will send the following information, in
order: GtkCList *clist, gint row, gint column, GtkEventButton *event
<item>unselect_row - When the user unselects a row, this signal is activated. It
sends the same information as select_row
<item>click_column - Send GtkCList *clist, gint column
</itemize>
So if we want to connect a callback to select_row, the callback function would
be declared like this
<tscreen><verb>
void select_row_callback(GtkWidget *widget,
gint row,
gint column,
GdkEventButton *event,
gpointer data);
</verb></tscreen>
The callback is connected as usual with
<tscreen><verb>
gtk_signal_connect(GTK_OBJECT( clist),
"select_row"
GTK_SIGNAL_FUNC(select_row_callback),
NULL);
</verb></tscreen>
<!-- ----------------------------------------------------------------- -->
<sect1>A GtkCList example
<p>
<tscreen><verb>
/* example-start clist clist.c */
#include <gtk/gtk.h>
#include <glib.h>
/* These are just the prototypes of the various callbacks */
void button_add_clicked( GtkWidget *button, gpointer data);
void button_clear_clicked( GtkWidget *button, gpointer data);
void button_hide_show_clicked( GtkWidget *button, gpointer data);
void selection_made( GtkWidget *clist, gint row, gint column,
GdkEventButton *event, gpointer data);
gint main (int argc, gchar *argv[])
{
GtkWidget *window;
GtkWidget *vbox, *hbox;
GtkWidget *clist;
GtkWidget *button_add, *button_clear, *button_hide_show;
gchar *titles[2] = {"Ingredients","Amount"};
gtk_init(&amp;argc, &amp;argv);
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_set_usize(GTK_WIDGET(window), 300, 150);
gtk_window_set_title(GTK_WINDOW(window), "GtkCList Example");
gtk_signal_connect(GTK_OBJECT(window),
"destroy",
GTK_SIGNAL_FUNC(gtk_main_quit),
NULL);
vbox=gtk_vbox_new(FALSE, 5);
gtk_container_border_width(GTK_CONTAINER(vbox), 5);
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_widget_show(vbox);
/* Create the GtkCList. For this example we use 2 columns */
clist = gtk_clist_new_with_titles( 2, titles);
/* When a selection is made, we want to know about it. The callback
* used is selection_made, and it's code can be found further down */
gtk_signal_connect(GTK_OBJECT(clist), "select_row",
GTK_SIGNAL_FUNC(selection_made),
NULL);
/* It isn't necessary to shadow the border, but it looks nice :) */
gtk_clist_set_border(GTK_CLIST(clist), GTK_SHADOW_OUT);
/* What however is important, is that we set the column widths as
* they will never be right otherwise. Note that the columns are
* numbered from 0 and up (to 1 in this case).
*/
gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150);
/* Scollbars _only when needed_ */
gtk_clist_set_policy(GTK_CLIST(clist), GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
/* Add the GtkCList widget to the vertical box and show it. */
gtk_box_pack_start(GTK_BOX(vbox), clist, TRUE, TRUE, 0);
gtk_widget_show(clist);
/* Create the buttons and add them to the window. See the button
* tutorial for more examples and comments on this.
*/
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
gtk_widget_show(hbox);
button_add = gtk_button_new_with_label("Add List");
button_clear = gtk_button_new_with_label("Clear List");
button_hide_show = gtk_button_new_with_label("Hide/Show titles");
gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0);
/* Connect our callbacks to the three buttons */
gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked",
GTK_SIGNAL_FUNC(button_add_clicked),
(gpointer) clist);
gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked",
GTK_SIGNAL_FUNC(button_clear_clicked),
(gpointer) clist);
gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked",
GTK_SIGNAL_FUNC(button_hide_show_clicked),
(gpointer) clist);
gtk_widget_show(button_add);
gtk_widget_show(button_clear);
gtk_widget_show(button_hide_show);
/* The interface is completely set up so we show the window and
* enter the gtk_main loop.
*/
gtk_widget_show(window);
gtk_main();
return 0;
}
/* User clicked the "Add List" button. */
void button_add_clicked( GtkWidget *button, gpointer data)
{
int indx;
/* Something silly to add to the list. 4 rows of 2 columns each */
gchar *drink[4][2] = {{"Milk", "3 Oz"},
{"Water", "6 l"},
{"Carrots", "2"},
{"Snakes", "55"}};
/* Here we do the actual adding of the text. It's done once for
* each row.
*/
for( indx=0; indx < 4; indx++)
gtk_clist_append( (GtkCList*) data, drink[indx]);
return;
}
/* User clicked the "Clear List" button. */
void button_clear_clicked( GtkWidget *button, gpointer data)
{
/* Clear the list using gtk_clist_clear. This is much faster than
* calling gtk_clist_remove once for each row.
*/
gtk_clist_clear((GtkCList*) data);
return;
}
/* The user clicked the "Hide/Show titles" button. */
void button_hide_show_clicked( GtkWidget *button, gpointer data)
{
/* Just a flag to remember the status. 0 = currently visible */
static short int flag = 0;
if (flag == 0)
{
/* Hide the titles and set the flag to 1 */
gtk_clist_column_titles_hide((GtkCList*) data);
flag++;
}
else
{
/* Show the titles and reset flag to 0 */
gtk_clist_column_titles_show((GtkCList*) data);
flag--;
}
return;
}
/* If we come here, then the user has selected a row in the list. */
void selection_made( GtkWidget *clist, gint row, gint column,
GdkEventButton *event, gpointer data)
{
gchar *text;
/* Get the text that is stored in the selected row and column
* which was clicked in. We will receive it as a pointer in the
* argument text.
*/
gtk_clist_get_text(GTK_CLIST(clist), row, column, &amp;text);
/* Just prints some information about the selected row */
g_print("You selected row %d. More specifically you clicked in column %d, and the text in this cell is %s\n\n", row, column, text);
return;
}
/* example-end */
</verb></tscreen>
<!-- ***************************************************************** -->
<sect> List Widget
<!-- ***************************************************************** -->
<p>
NOTE: The GtkList widget has been superseded by the GtkCList widget.
@ -5879,9 +6589,6 @@ from your time.
<sect1> Fixed Container
<p>
<!-- ----------------------------------------------------------------- -->
<sect1> CList
<p>
<!-- ----------------------------------------------------------------- -->
<sect1> Range Controls
<p>
<!-- ----------------------------------------------------------------- -->
@ -6557,6 +7264,8 @@ void input_callback( gpointer data,
GdkInputCondition condition );
</verb></tscreen>
Where <tt/source/ and <tt/condition/ are as specified above.
<!-- ----------------------------------------------------------------- -->
<sect1>Idle Functions
<p>

8
examples/clist/Makefile Normal file
View File

@ -0,0 +1,8 @@
CC = gcc
clist: clist.c
$(CC) `gtk-config --cflags` `gtk-config --libs` clist.c -o clist
clean:
rm -f *.o clist

173
examples/clist/clist.c Normal file
View File

@ -0,0 +1,173 @@
/* example-start clist clist.c */
#include <gtk/gtk.h>
#include <glib.h>
/* These are just the prototypes of the various callbacks */
void button_add_clicked( GtkWidget *button, gpointer data);
void button_clear_clicked( GtkWidget *button, gpointer data);
void button_hide_show_clicked( GtkWidget *button, gpointer data);
void selection_made( GtkWidget *clist, gint row, gint column,
GdkEventButton *event, gpointer data);
gint main (int argc, gchar *argv[])
{
GtkWidget *window;
GtkWidget *vbox, *hbox;
GtkWidget *clist;
GtkWidget *button_add, *button_clear, *button_hide_show;
gchar *titles[2] = {"Ingredients","Amount"};
gtk_init(&argc, &argv);
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_set_usize(GTK_WIDGET(window), 300, 150);
gtk_window_set_title(GTK_WINDOW(window), "GtkCList Example");
gtk_signal_connect(GTK_OBJECT(window),
"destroy",
GTK_SIGNAL_FUNC(gtk_main_quit),
NULL);
vbox=gtk_vbox_new(FALSE, 5);
gtk_container_border_width(GTK_CONTAINER(vbox), 5);
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_widget_show(vbox);
/* Create the GtkCList. For this example we use 2 columns */
clist = gtk_clist_new_with_titles( 2, titles);
/* When a selection is made, we want to know about it. The callback
* used is selection_made, and it's code can be found further down */
gtk_signal_connect(GTK_OBJECT(clist), "select_row",
GTK_SIGNAL_FUNC(selection_made),
NULL);
/* It isn't necessary to shadow the border, but it looks nice :) */
gtk_clist_set_border(GTK_CLIST(clist), GTK_SHADOW_OUT);
/* What however is important, is that we set the column widths as
* they will never be right otherwise. Note that the columns are
* numbered from 0 and up (to 1 in this case).
*/
gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150);
/* Scollbars _only when needed_ */
gtk_clist_set_policy(GTK_CLIST(clist), GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
/* Add the GtkCList widget to the vertical box and show it. */
gtk_box_pack_start(GTK_BOX(vbox), clist, TRUE, TRUE, 0);
gtk_widget_show(clist);
/* Create the buttons and add them to the window. See the button
* tutorial for more examples and comments on this.
*/
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
gtk_widget_show(hbox);
button_add = gtk_button_new_with_label("Add List");
button_clear = gtk_button_new_with_label("Clear List");
button_hide_show = gtk_button_new_with_label("Hide/Show titles");
gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0);
/* Connect our callbacks to the three buttons */
gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked",
GTK_SIGNAL_FUNC(button_add_clicked),
(gpointer) clist);
gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked",
GTK_SIGNAL_FUNC(button_clear_clicked),
(gpointer) clist);
gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked",
GTK_SIGNAL_FUNC(button_hide_show_clicked),
(gpointer) clist);
gtk_widget_show(button_add);
gtk_widget_show(button_clear);
gtk_widget_show(button_hide_show);
/* The interface is completely set up so we show the window and
* enter the gtk_main loop.
*/
gtk_widget_show(window);
gtk_main();
return 0;
}
/* User clicked the "Add List" button. */
void button_add_clicked( GtkWidget *button, gpointer data)
{
int indx;
/* Something silly to add to the list. 4 rows of 2 columns each */
gchar *drink[4][2] = {{"Milk", "3 Oz"},
{"Water", "6 l"},
{"Carrots", "2"},
{"Snakes", "55"}};
/* Here we do the actual adding of the text. It's done once for
* each row.
*/
for( indx=0; indx < 4; indx++)
gtk_clist_append( (GtkCList*) data, drink[indx]);
return;
}
/* User clicked the "Clear List" button. */
void button_clear_clicked( GtkWidget *button, gpointer data)
{
/* Clear the list using gtk_clist_clear. This is much faster than
* calling gtk_clist_remove once for each row.
*/
gtk_clist_clear((GtkCList*) data);
return;
}
/* The user clicked the "Hide/Show titles" button. */
void button_hide_show_clicked( GtkWidget *button, gpointer data)
{
/* Just a flag to remember the status. 0 = currently visible */
static short int flag = 0;
if (flag == 0)
{
/* Hide the titles and set the flag to 1 */
gtk_clist_column_titles_hide((GtkCList*) data);
flag++;
}
else
{
/* Show the titles and reset flag to 0 */
gtk_clist_column_titles_show((GtkCList*) data);
flag--;
}
return;
}
/* If we come here, then the user has selected a row in the list. */
void selection_made( GtkWidget *clist, gint row, gint column,
GdkEventButton *event, gpointer data)
{
gchar *text;
/* Get the text that is stored in the selected row and column
* which was clicked in. We will receive it as a pointer in the
* argument text.
*/
gtk_clist_get_text(GTK_CLIST(clist), row, column, &text);
/* Just prints some information about the selected row */
g_print("You selected row %d. More specifically you clicked in column %d, and the text in this cell is %s\n\n", row, column, text);
return;
}
/* example-end */