1#include <gtk/gtk.h>
2
3#include <string.h>
4
5typedef struct _Row Row;
6typedef struct _RowClass RowClass;
7
8struct _Row
9{
10 GtkListBoxRow parent_instance;
11 GtkWidget *label;
12 int sort_id;
13};
14
15struct _RowClass
16{
17 GtkListBoxRowClass parent_class;
18};
19
20const char *css =
21 "list row {"
22 " border-width: 1px;"
23 " border-style: solid;"
24 " border-color: blue;"
25 "}"
26 "list row:hover {"
27 "background-color: green;"
28 "}"
29 "list row:active {"
30 "background-color: red;"
31 "}";
32
33static GType row_get_type (void);
34G_DEFINE_TYPE (Row, row, GTK_TYPE_LIST_BOX_ROW)
35
36static void
37row_init (Row *row)
38{
39}
40
41static void
42row_class_init (RowClass *class)
43{
44}
45
46static GtkWidget *
47row_new (const char * text, int sort_id) {
48 Row *row;
49
50 row = g_object_new (object_type: row_get_type (), NULL);
51 if (text != NULL)
52 {
53 row->label = gtk_label_new (str: text);
54 gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), child: row->label);
55 }
56 row->sort_id = sort_id;
57
58 return GTK_WIDGET (row);
59}
60
61
62static void
63update_header_cb (Row *row, Row *before, gpointer data)
64{
65 GtkWidget *hbox, *l, *b;
66
67 if (before == NULL ||
68 (row->label != NULL &&
69 strcmp (s1: gtk_label_get_text (GTK_LABEL (row->label)), s2: "blah3") == 0))
70 {
71 /* Create header if needed */
72 if (gtk_list_box_row_get_header (GTK_LIST_BOX_ROW (row)) == NULL)
73 {
74 hbox = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 0);
75 l = gtk_label_new (str: "Header");
76 gtk_box_append (GTK_BOX (hbox), child: l);
77 b = gtk_button_new_with_label (label: "button");
78 gtk_box_append (GTK_BOX (hbox), child: b);
79 gtk_list_box_row_set_header (GTK_LIST_BOX_ROW (row), header: hbox);
80 }
81
82 hbox = gtk_list_box_row_get_header(GTK_LIST_BOX_ROW (row));
83
84 l = gtk_widget_get_first_child (widget: hbox);
85 gtk_label_set_text (GTK_LABEL (l), str: g_strdup_printf (format: "Header %d", row->sort_id));
86 }
87 else
88 {
89 gtk_list_box_row_set_header(GTK_LIST_BOX_ROW (row), NULL);
90 }
91}
92
93static int
94sort_cb (Row *a, Row *b, gpointer data)
95{
96 return a->sort_id - b->sort_id;
97}
98
99static int
100reverse_sort_cb (Row *a, Row *b, gpointer data)
101{
102 return b->sort_id - a->sort_id;
103}
104
105static gboolean
106filter_cb (Row *row, gpointer data)
107{
108 const char *text;
109
110 if (row->label != NULL)
111 {
112 text = gtk_label_get_text (GTK_LABEL (row->label));
113 return strcmp (s1: text, s2: "blah3") != 0;
114 }
115
116 return TRUE;
117}
118
119static void
120row_activated_cb (GtkListBox *list_box,
121 GtkListBoxRow *row)
122{
123 g_print (format: "activated row %p\n", row);
124}
125
126static void
127row_selected_cb (GtkListBox *list_box,
128 GtkListBoxRow *row)
129{
130 g_print (format: "selected row %p\n", row);
131}
132
133static void
134sort_clicked_cb (GtkButton *button,
135 gpointer data)
136{
137 GtkListBox *list = data;
138
139 gtk_list_box_set_sort_func (box: list, sort_func: (GtkListBoxSortFunc)sort_cb, NULL, NULL);
140}
141
142static void
143reverse_sort_clicked_cb (GtkButton *button,
144 gpointer data)
145{
146 GtkListBox *list = data;
147
148 gtk_list_box_set_sort_func (box: list, sort_func: (GtkListBoxSortFunc)reverse_sort_cb, NULL, NULL);
149}
150
151static void
152filter_clicked_cb (GtkButton *button,
153 gpointer data)
154{
155 GtkListBox *list = data;
156
157 gtk_list_box_set_filter_func (box: list, filter_func: (GtkListBoxFilterFunc)filter_cb, NULL, NULL);
158}
159
160static void
161unfilter_clicked_cb (GtkButton *button,
162 gpointer data)
163{
164 GtkListBox *list = data;
165
166 gtk_list_box_set_filter_func (box: list, NULL, NULL, NULL);
167}
168
169static void
170change_clicked_cb (GtkButton *button,
171 gpointer data)
172{
173 Row *row = data;
174
175 if (strcmp (s1: gtk_label_get_text (GTK_LABEL (row->label)), s2: "blah3") == 0)
176 {
177 gtk_label_set_text (GTK_LABEL (row->label), str: "blah5");
178 row->sort_id = 5;
179 }
180 else
181 {
182 gtk_label_set_text (GTK_LABEL (row->label), str: "blah3");
183 row->sort_id = 3;
184 }
185 gtk_list_box_row_changed (GTK_LIST_BOX_ROW (row));
186}
187
188static void
189add_clicked_cb (GtkButton *button,
190 gpointer data)
191{
192 GtkListBox *list = data;
193 GtkWidget *new_row;
194 static int new_button_nr = 1;
195
196 new_row = row_new( text: g_strdup_printf (format: "blah2 new %d", new_button_nr), sort_id: new_button_nr);
197 gtk_list_box_insert (GTK_LIST_BOX (list), child: new_row, position: -1);
198 new_button_nr++;
199}
200
201static void
202separate_clicked_cb (GtkButton *button,
203 gpointer data)
204{
205 GtkListBox *list = data;
206
207 gtk_list_box_set_header_func (box: list, update_header: (GtkListBoxUpdateHeaderFunc)update_header_cb, NULL, NULL);
208}
209
210static void
211unseparate_clicked_cb (GtkButton *button,
212 gpointer data)
213{
214 GtkListBox *list = data;
215
216 gtk_list_box_set_header_func (box: list, NULL, NULL, NULL);
217}
218
219static void
220visibility_clicked_cb (GtkButton *button,
221 gpointer data)
222{
223 GtkWidget *row = data;
224
225 gtk_widget_set_visible (widget: row, visible: !gtk_widget_get_visible (widget: row));
226}
227
228static void
229selection_mode_changed (GtkComboBox *combo, gpointer data)
230{
231 GtkListBox *list = data;
232
233 gtk_list_box_set_selection_mode (box: list, mode: gtk_combo_box_get_active (combo_box: combo));
234}
235
236static void
237single_click_clicked (GtkButton *check, gpointer data)
238{
239 GtkListBox *list = data;
240
241 g_print (format: "single: %d\n", gtk_check_button_get_active (GTK_CHECK_BUTTON (check)));
242 gtk_list_box_set_activate_on_single_click (box: list, single: gtk_check_button_get_active (GTK_CHECK_BUTTON (check)));
243}
244
245int
246main (int argc, char *argv[])
247{
248 GtkCssProvider *provider;
249 GtkWidget *window, *hbox, *vbox, *list, *row, *row3, *row_vbox, *row_hbox, *l;
250 GtkWidget *check, *button, *combo, *scrolled;
251
252 gtk_init ();
253
254 window = gtk_window_new ();
255 hbox = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 0);
256 gtk_window_set_child (GTK_WINDOW (window), child: hbox);
257
258 provider = gtk_css_provider_new ();
259 gtk_css_provider_load_from_data (css_provider: provider, data: css, length: -1);
260 gtk_style_context_add_provider_for_display (display: gtk_widget_get_display (widget: window),
261 GTK_STYLE_PROVIDER (provider),
262 GTK_STYLE_PROVIDER_PRIORITY_USER);
263
264
265 list = gtk_list_box_new ();
266
267 vbox = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 0);
268 gtk_box_append (GTK_BOX (hbox), child: vbox);
269
270 combo = gtk_combo_box_text_new ();
271 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo),
272 text: "GTK_SELECTION_NONE");
273 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo),
274 text: "GTK_SELECTION_SINGLE");
275 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo),
276 text: "GTK_SELECTION_BROWSE");
277 g_signal_connect (combo, "changed", G_CALLBACK (selection_mode_changed), list);
278 gtk_box_append (GTK_BOX (vbox), child: combo);
279 gtk_combo_box_set_active (GTK_COMBO_BOX (combo), index_: gtk_list_box_get_selection_mode (GTK_LIST_BOX (list)));
280 check = gtk_check_button_new_with_label (label: "single click mode");
281 gtk_check_button_set_active (GTK_CHECK_BUTTON (check), setting: gtk_list_box_get_activate_on_single_click (GTK_LIST_BOX (list)));
282 g_signal_connect (check, "toggled", G_CALLBACK (single_click_clicked), list);
283 gtk_box_append (GTK_BOX (vbox), child: check);
284
285 scrolled = gtk_scrolled_window_new ();
286 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), hscrollbar_policy: GTK_POLICY_NEVER, vscrollbar_policy: GTK_POLICY_AUTOMATIC);
287 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled), child: list);
288 gtk_box_append (GTK_BOX (hbox), child: scrolled);
289
290 g_signal_connect (list, "row-activated", G_CALLBACK (row_activated_cb), NULL);
291 g_signal_connect (list, "row-selected", G_CALLBACK (row_selected_cb), NULL);
292
293 row = row_new (text: "blah4", sort_id: 4);
294 gtk_list_box_insert (GTK_LIST_BOX (list), child: row, position: -1);
295 row3 = row = row_new (text: "blah3", sort_id: 3);
296 gtk_list_box_insert (GTK_LIST_BOX (list), child: row, position: -1);
297 row = row_new (text: "blah1", sort_id: 1);
298 gtk_list_box_insert (GTK_LIST_BOX (list), child: row, position: -1);
299 row = row_new (text: "blah2", sort_id: 2);
300 gtk_list_box_insert (GTK_LIST_BOX (list), child: row, position: -1);
301
302 row = row_new (NULL, sort_id: 0);
303 row_vbox = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 0);
304 row_hbox = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 0);
305 l = gtk_label_new (str: "da box for da man");
306 gtk_box_append (GTK_BOX (row_hbox), child: l);
307 check = gtk_check_button_new ();
308 gtk_box_append (GTK_BOX (row_hbox), child: check);
309 button = gtk_button_new_with_label (label: "ya!");
310 gtk_box_append (GTK_BOX (row_hbox), child: button);
311 gtk_box_append (GTK_BOX (row_vbox), child: row_hbox);
312 check = gtk_check_button_new ();
313 gtk_box_append (GTK_BOX (row_vbox), child: check);
314 gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), child: row_vbox);
315 gtk_list_box_insert (GTK_LIST_BOX (list), child: row, position: -1);
316
317 row = row_new (NULL, sort_id: 0);
318 button = gtk_button_new_with_label (label: "focusable row");
319 gtk_widget_set_hexpand (widget: button, FALSE);
320 gtk_widget_set_halign (widget: button, align: GTK_ALIGN_START);
321 gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), child: button);
322 gtk_list_box_insert (GTK_LIST_BOX (list), child: row, position: -1);
323
324 vbox = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 0);
325 gtk_box_append (GTK_BOX (hbox), child: vbox);
326
327 button = gtk_button_new_with_label (label: "sort");
328 gtk_box_append (GTK_BOX (vbox), child: button);
329 g_signal_connect (button, "clicked", G_CALLBACK (sort_clicked_cb), list);
330
331 button = gtk_button_new_with_label (label: "reverse");
332 gtk_box_append (GTK_BOX (vbox), child: button);
333 g_signal_connect (button, "clicked", G_CALLBACK (reverse_sort_clicked_cb), list);
334
335 button = gtk_button_new_with_label (label: "change");
336 gtk_box_append (GTK_BOX (vbox), child: button);
337 g_signal_connect (button, "clicked", G_CALLBACK (change_clicked_cb), row3);
338
339 button = gtk_button_new_with_label (label: "filter");
340 gtk_box_append (GTK_BOX (vbox), child: button);
341 g_signal_connect (button, "clicked", G_CALLBACK (filter_clicked_cb), list);
342
343 button = gtk_button_new_with_label (label: "unfilter");
344 gtk_box_append (GTK_BOX (vbox), child: button);
345 g_signal_connect (button, "clicked", G_CALLBACK (unfilter_clicked_cb), list);
346
347 button = gtk_button_new_with_label (label: "add");
348 gtk_box_append (GTK_BOX (vbox), child: button);
349 g_signal_connect (button, "clicked", G_CALLBACK (add_clicked_cb), list);
350
351 button = gtk_button_new_with_label (label: "separate");
352 gtk_box_append (GTK_BOX (vbox), child: button);
353 g_signal_connect (button, "clicked", G_CALLBACK (separate_clicked_cb), list);
354
355 button = gtk_button_new_with_label (label: "unseparate");
356 gtk_box_append (GTK_BOX (vbox), child: button);
357 g_signal_connect (button, "clicked", G_CALLBACK (unseparate_clicked_cb), list);
358
359 button = gtk_button_new_with_label (label: "visibility");
360 gtk_box_append (GTK_BOX (vbox), child: button);
361 g_signal_connect (button, "clicked", G_CALLBACK (visibility_clicked_cb), row3);
362
363 gtk_widget_show (widget: window);
364
365 while (TRUE)
366 g_main_context_iteration (NULL, TRUE);
367
368 return 0;
369}
370

source code of gtk/tests/testlist.c