1 | #include <gtk/gtk.h> |
2 | |
3 | #include <string.h> |
4 | |
5 | typedef struct _Row Row; |
6 | typedef struct _RowClass RowClass; |
7 | |
8 | struct _Row |
9 | { |
10 | GtkListBoxRow parent_instance; |
11 | GtkWidget *label; |
12 | int sort_id; |
13 | }; |
14 | |
15 | struct _RowClass |
16 | { |
17 | GtkListBoxRowClass parent_class; |
18 | }; |
19 | |
20 | const 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 | |
33 | static GType row_get_type (void); |
34 | G_DEFINE_TYPE (Row, row, GTK_TYPE_LIST_BOX_ROW) |
35 | |
36 | static void |
37 | row_init (Row *row) |
38 | { |
39 | } |
40 | |
41 | static void |
42 | row_class_init (RowClass *class) |
43 | { |
44 | } |
45 | |
46 | static GtkWidget * |
47 | row_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 | |
62 | static void |
63 | (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 | |
93 | static int |
94 | sort_cb (Row *a, Row *b, gpointer data) |
95 | { |
96 | return a->sort_id - b->sort_id; |
97 | } |
98 | |
99 | static int |
100 | reverse_sort_cb (Row *a, Row *b, gpointer data) |
101 | { |
102 | return b->sort_id - a->sort_id; |
103 | } |
104 | |
105 | static gboolean |
106 | filter_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 | |
119 | static void |
120 | row_activated_cb (GtkListBox *list_box, |
121 | GtkListBoxRow *row) |
122 | { |
123 | g_print (format: "activated row %p\n" , row); |
124 | } |
125 | |
126 | static void |
127 | row_selected_cb (GtkListBox *list_box, |
128 | GtkListBoxRow *row) |
129 | { |
130 | g_print (format: "selected row %p\n" , row); |
131 | } |
132 | |
133 | static void |
134 | sort_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 | |
142 | static void |
143 | reverse_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 | |
151 | static void |
152 | filter_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 | |
160 | static void |
161 | unfilter_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 | |
169 | static void |
170 | change_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 | |
188 | static void |
189 | add_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 | |
201 | static void |
202 | separate_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 | |
210 | static void |
211 | unseparate_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 | |
219 | static void |
220 | visibility_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 | |
228 | static void |
229 | selection_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 | |
236 | static void |
237 | single_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 | |
245 | int |
246 | main (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 | |