Siêu thị PDFTải ngay đi em, trời tối mất

Thư viện tri thức trực tuyến

Kho tài liệu với 50,000+ tài liệu học thuật

© 2023 Siêu thị PDF - Kho tài liệu học thuật hàng đầu Việt Nam

apress foundations_of gtk plus development 2007 phần 6 doc
PREMIUM
Số trang
60
Kích thước
1.5 MB
Định dạng
PDF
Lượt xem
1825

apress foundations_of gtk plus development 2007 phần 6 doc

Nội dung xem thử

Mô tả chi tiết

CHAPTER 8 ■ THE TREE VIEW WIDGET 271

Renderers and Columns

After creating the GtkTreeView, you need to add one or more columns to the view for it to be of

any use. Each GtkTreeViewColumn is composed of a header, which displays a short description

of its content, and at least one cell renderer. Tree view columns do not actually render any

content. Tree view columns hold one or more cell renderers that are used to draw the data on

the screen.

All cell renderers are derived from the GtkCellRenderer class and are referred to as

objects in this chapter, because GtkCellRenderer is derived directly from GtkObject, not from

GtkWidget. Each cell renderer contains a number of properties that determine how the data

will be drawn within a cell.

The GtkCellRenderer class provides common properties to all derivative renderers

including background color, size parameters, alignments, visibility, sensitivity, and padding.

A full list of GtkCellRenderer properties can be found in Appendix A. It also provides the

editing-canceled and editing-started signals, which allow you to implement editing in

custom cell renderers.

In Listing 8-1, you were introduced to GtkCellRendererText, which is capable of rendering

strings, numbers, and gboolean values as text. Textual cell renderers are initialized with

gtk_cell_renderer_text_new().

GtkCellRendererText provides a number of additional properties that dictate how each

cell will be rendered. You should always set the text property, which is the string that will be

displayed in the cell. The rest of the properties are similar to those used with text tags.

GtkCellRendererText contains a large number of properties that dictate how every row will

be rendered. g_object_set() was used in the following example to set the foreground color of

every piece of text in the renderer to orange. Some properties have a corresponding set prop￾erty as well, which must be set to TRUE if you want the value to be used. For example, you should

set foreground-set to TRUE for the changes will take effect.

g_object_set (G_OBJECT (renderer), "foreground", "Orange",

"foreground-set", TRUE, NULL);

After you create a cell renderer, it needs to be added to a GtkTreeViewColumn. Tree view col￾umns can be created with gtk_tree_view_column_new_with_attributes() if you only want the

column to display one cell renderer. In the following code, a tree view column is created with

the title “Buy” and a renderer with one attribute. This attribute will be referred to as BUY_IT

when the GtkListStore is populated.

column = gtk_tree_view_column_new_with_attributes ("Buy", renderer,

"text", BUY_IT, NULL);

The preceding function accepts a string to display in the column header, a cell renderer,

and a NULL-terminated list of attributes. Each attribute contains a string that refers to the ren￾derer property and the tree view column number. The important thing to realize is that the

column number provided to gtk_tree_view_column_new_with_attributes() refers to the tree

model column, which may not be the same as the number of tree model columns or cell

renderers used by the tree view.

7931.book Page 271 Thursday, February 22, 2007 9:09 PM

272 CHAPTER 8 ■ THE TREE VIEW WIDGET

The following four lines of code implement the same functionality that is provided

by gtk_tree_view_column_new_with_attributes(). An empty column is created with

gtk_tree_view_column_new(), and the column title is set to “Buy”.

column = gtk_tree_view_column_new ();

gtk_tree_view_column_set_title (column, "Buy");

gtk_tree_view_column_pack_start (column, renderer, FALSE);

gtk_tree_view_column_set_attributes (column, renderer, "text", BUY_IT, NULL);

Next, a cell renderer is added to the column. gtk_tree_view_column_pack_start() accepts

a third Boolean parameter, which instructs the column to expand horizontally to fill extra

space if set to TRUE. The last function, gtk_tree_view_column_set_attributes() adds the

NULL-terminated list of attributes that will be customized for every row you add to the tree view.

These attributes are applied to the specified renderer.

Calling gtk_tree_view_column_pack_start() will remove all attributes previously associ￾ated with the specified cell renderer. To circumvent this, you can use gtk_tree_view_column_

add_attribute() to add attributes to a column for a specific cell renderer one at a time. Both

of these functions are useful when a GtkTreeViewColumn will contain more than one cell

renderer.

void gtk_tree_view_column_add_attribute (GtkTreeViewColumn *column,

GtkCellRenderer *renderer,

const gchar *attribute,

gint column);

If you want to add multiple renderers to the tree view column, you will need to pack each

renderer and set its attributes separately. For example, in a file manager, you might want to

include a text and an image renderer in the same column. However, if every column only needs

one cell renderer, it is easiest to use gtk_tree_view_column_new_with_attributes().

■Note If you want a property, such as the foreground color, set to the same value for every row in the

column, you should apply that property directly to the cell renderer with g_object_set(). However, if the

property will vary depending on the row, you should add it as an attribute of the column for the given renderer.

After you have finished setting up a tree view column, it needs to be added to the tree

view with gtk_tree_view_append_column(). Columns may also be added into an arbitrary

position of the tree view with gtk_tree_view_insert_column() or removed from the view with

gtk_tree_view_remove_column().

Creating the GtkListStore

The tree view columns are now set up with the desired cell renderers, so it is time to create the

tree model that will interface between the renderers and the tree view. For the example found

in Listing 8-1, we used GtkListStore so that the items would be shown as a list of elements.

7931.book Page 272 Thursday, February 22, 2007 9:09 PM

CHAPTER 8 ■ THE TREE VIEW WIDGET 273

New list stores are created with gtk_list_store_new(). This function accepts the number

of columns and the type of the data each column will hold. In Listing 8-1, the list store has three

columns that store gboolean, integer, and string data types.

GtkListStore* gtk_list_store_new (gint n_columns,

/* List of column types */);

After creating the list store, you need to add rows with gtk_list_store_append() for it to be

of any use. This function will append a new row to the list store, and the iterator will be set to

point to the new row. You will learn more about tree iterators in a later section of this chapter.

For now, it is adequate for you to know that it points to the new tree view row.

void gtk_list_store_append (GtkListStore *store,

GtkTreeIter *iter);

There are multiple other functions for adding rows to a list store including gtk_list_

store_prepend() and gtk_list_store_insert(). A full list of available functions can be found

in the GtkListStore API documentation.

In addition to adding rows, you can also remove them with gtk_list_store_remove(). This

function will remove the row that GtkTreeIter refers to. After the row is removed, the iterator

will point to the next row in the list store, and the function will return TRUE. If the last row was

just removed, the iterator will become invalid, and the function will return FALSE.

gboolean gtk_list_store_remove (GtkListStore *store,

GtkTreeIter *iter);

In addition, gtk_list_store_clear() is provided, which can be used to remove all rows

from a list store. You will be left with a GtkListStore that contains no data. If the object will not

be used beyond this point, it should then be unreferenced.

Now that you have a row, you need to add data to it with gtk_list_store_set(). The

gtk_list_store_set() function receives a list of pairs of column numbers and value parame￾ters. For example, the first column in the following function call, referenced with BUY_IT,

accepts a Boolean value that defines whether the product should be purchased. These values

correspond to those set by gtk_list_store_new().

gtk_list_store_set (store, &iter, BUY_IT, list[i].buy,

QUANTITY, list[i].quantity, PRODUCT, list[i].product, -1);

The last element of gtk_list_store_set() must be set to -1 so that GTK+ knows that there

are no more parameters. Otherwise, your users will be presented with an endless list of warn￾ings and errors in the terminal output.

■Note GtkCellRendererText automatically converts Boolean values and numbers into text strings that

can be rendered on the screen. Therefore, the type of data applied to a text attribute column does not have

to be text itself, but just has to be consistent with the list store column type that was defined during initializa￾tion of the GtkListStore.

7931.book Page 273 Thursday, February 22, 2007 9:09 PM

274 CHAPTER 8 ■ THE TREE VIEW WIDGET

After the list store is created, you need to call gtk_tree_view_set_model() to add it to the

tree view. By calling this function, the reference count of the tree model will be incremented by

one. Therefore, if you want the tree model to be destroyed when the tree view is destroyed, you

will need to call g_object_unref() on the list store.

Using GtkTreeStore

There is one other type of built-in tree model called GtkTreeStore, which organizes rows into a

multilevel tree structure. It is possible to implement a list with a GtkTreeStore tree model as

well, but this is not recommended because some overhead is added when the object assumes

that the row may have one or more children.

Figure 8-5 shows an example tree store, which contains two root elements, each with chil￾dren of its own. By clicking the expander to the left of a row with children, you can show or hide

its children. This is similar to the functionality provided by the GtkExpander widget.

Figure 8-5. A tree view widget using a GtkTreeStore tree model

The only difference between a GtkTreeView implemented with a GtkTreeStore instead of a

GtkListStore is in the creation of the store. Adding columns and renderers is performed in the

same manner with both models, because columns are a part of the view not the model, so

Listing 8-2 excludes the implementation of setup_tree_view().

Listing 8-2 revises the original Grocery List application, splitting the products into catego￾ries. This list includes two categories: Cleaning Supplies and Food, which both have children of

their own. The quantity of each category is set initially to zero, because this is calculated during

runtime.

7931.book Page 274 Thursday, February 22, 2007 9:09 PM

CHAPTER 8 ■ THE TREE VIEW WIDGET 275

Listing 8-2. Creating a GtkTreeStore (treestore.c)

#include <gtk/gtk.h>

enum

{

BUY_IT = 0,

QUANTITY,

PRODUCT,

COLUMNS

};

enum

{

PRODUCT_CATEGORY,

PRODUCT_CHILD

};

typedef struct

{

gint product_type;

gboolean buy;

gint quantity;

gchar *product;

} GroceryItem;

GroceryItem list[] =

{

{ PRODUCT_CATEGORY, TRUE, 0, "Cleaning Supplies" },

{ PRODUCT_CHILD, TRUE, 1, "Paper Towels" },

{ PRODUCT_CHILD, TRUE, 3, "Toilet Paper" },

{ PRODUCT_CATEGORY, TRUE, 0, "Food" },

{ PRODUCT_CHILD, TRUE, 2, "Bread" },

{ PRODUCT_CHILD, FALSE, 1, "Butter" },

{ PRODUCT_CHILD, TRUE, 1, "Milk" },

{ PRODUCT_CHILD, FALSE, 3, "Chips" },

{ PRODUCT_CHILD, TRUE, 4, "Soda" },

{ PRODUCT_CATEGORY, FALSE, 0, NULL }

};

/* The implementation of this function is the same as in Listing 8-1. */

static void setup_tree_view (GtkWidget*);

7931.book Page 275 Thursday, February 22, 2007 9:09 PM

276 CHAPTER 8 ■ THE TREE VIEW WIDGET

int main (int argc,

char *argv[])

{

GtkWidget *window, *treeview, *scrolled_win;

GtkTreeStore *store;

GtkTreeIter iter, child;

guint i = 0, j;

gtk_init (&argc, &argv);

window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

gtk_window_set_title (GTK_WINDOW (window), "Grocery List");

gtk_container_set_border_width (GTK_CONTAINER (window), 10);

gtk_widget_set_size_request (window, 275, 300);

treeview = gtk_tree_view_new ();

setup_tree_view (treeview);

store = gtk_tree_store_new (COLUMNS, G_TYPE_BOOLEAN, G_TYPE_INT, G_TYPE_STRING);

while (list[i].product != NULL)

{

/* If the product type is a category, count the quantity of all of the products

* in the category that are going to be bought. */

if (list[i].product_type == PRODUCT_CATEGORY)

{

j = i + 1;

/* Calculate how many products will be bought in the category. */

while (list[j].product != NULL && list[j].product_type != PRODUCT_CATEGORY)

{

if (list[j].buy)

list[i].quantity += list[j].quantity;

j++;

}

/* Add the category as a new root element. */

gtk_tree_store_append (store, &iter, NULL);

gtk_tree_store_set (store, &iter, BUY_IT, list[i].buy,

QUANTITY, list[i].quantity, PRODUCT, list[i].product, -1);

}

7931.book Page 276 Thursday, February 22, 2007 9:09 PM

Tải ngay đi em, còn do dự, trời tối mất!
apress foundations_of gtk plus development 2007 phần 6 doc | Siêu Thị PDF