1 | #include <gtk/gtk.h> |
2 | |
3 | #ifdef SMALL |
4 | #define AVERAGE 15 |
5 | #define VARIANCE 10 |
6 | #else |
7 | #define AVERAGE 300 |
8 | #define VARIANCE 200 |
9 | #endif |
10 | |
11 | static void |
12 | setup_list_item (GtkSignalListItemFactory *factory, |
13 | GtkListItem *list_item) |
14 | { |
15 | GtkWidget *label = gtk_label_new (str: "" ); |
16 | |
17 | gtk_list_item_set_child (self: list_item, child: label); |
18 | } |
19 | |
20 | static void |
21 | bind_list_item (GtkSignalListItemFactory *factory, |
22 | GtkListItem *list_item) |
23 | { |
24 | GtkWidget *label; |
25 | gpointer item; |
26 | char *s; |
27 | |
28 | item = gtk_list_item_get_item (self: list_item); |
29 | |
30 | if (item) |
31 | s = g_strdup_printf (format: "%u: %s" , |
32 | gtk_list_item_get_position (self: list_item), |
33 | (const char *) g_object_get_data (object: item, key: "message" )); |
34 | else |
35 | s = NULL; |
36 | |
37 | label = gtk_list_item_get_child (self: list_item); |
38 | gtk_label_set_text (GTK_LABEL (label), str: s); |
39 | |
40 | g_free (mem: s); |
41 | } |
42 | |
43 | static GtkWidget * |
44 | create_widget_for_listbox (gpointer item, |
45 | gpointer unused) |
46 | { |
47 | const char *message = g_object_get_data (object: item, key: "message" ); |
48 | GtkWidget *widget; |
49 | |
50 | widget = gtk_label_new (str: message); |
51 | |
52 | return widget; |
53 | } |
54 | |
55 | static guint |
56 | get_number (GObject *item) |
57 | { |
58 | return GPOINTER_TO_UINT (g_object_get_data (item, "counter" )) % 1000; |
59 | } |
60 | |
61 | static void |
62 | add (GListStore *store) |
63 | { |
64 | static guint counter; |
65 | GObject *o; |
66 | char *message; |
67 | guint pos; |
68 | |
69 | counter++; |
70 | o = g_object_new (G_TYPE_OBJECT, NULL); |
71 | g_object_set_data (object: o, key: "counter" , GUINT_TO_POINTER (counter)); |
72 | message = g_strdup_printf (format: "Item %u" , counter); |
73 | g_object_set_data_full (object: o, key: "message" , data: message, destroy: g_free); |
74 | |
75 | pos = g_random_int_range (begin: 0, end: g_list_model_get_n_items (list: G_LIST_MODEL (ptr: store)) + 1); |
76 | g_list_store_insert (store, position: pos, item: o); |
77 | g_object_unref (object: o); |
78 | } |
79 | |
80 | static void |
81 | delete (GListStore *store) |
82 | { |
83 | guint pos; |
84 | |
85 | pos = g_random_int_range (begin: 0, end: g_list_model_get_n_items (list: G_LIST_MODEL (ptr: store))); |
86 | g_list_store_remove (store, position: pos); |
87 | } |
88 | |
89 | static gboolean |
90 | do_stuff (gpointer store) |
91 | { |
92 | if (g_random_int_range (AVERAGE - VARIANCE, AVERAGE + VARIANCE) < g_list_model_get_n_items (list: store)) |
93 | delete (store); |
94 | else |
95 | add (store); |
96 | |
97 | return G_SOURCE_CONTINUE; |
98 | } |
99 | |
100 | static gboolean |
101 | revert_sort (gpointer sorter) |
102 | { |
103 | if (gtk_numeric_sorter_get_sort_order (self: sorter) == GTK_SORT_ASCENDING) |
104 | gtk_numeric_sorter_set_sort_order (self: sorter, sort_order: GTK_SORT_DESCENDING); |
105 | else |
106 | gtk_numeric_sorter_set_sort_order (self: sorter, sort_order: GTK_SORT_ASCENDING); |
107 | |
108 | return G_SOURCE_CONTINUE; |
109 | } |
110 | |
111 | int |
112 | main (int argc, |
113 | char *argv[]) |
114 | { |
115 | GtkWidget *win, *hbox, *vbox, *sw, *listview, *listbox, *label; |
116 | GListStore *store; |
117 | GListModel *toplevels; |
118 | GtkSortListModel *sort; |
119 | GtkSorter *sorter; |
120 | guint i; |
121 | GtkListItemFactory *factory; |
122 | GtkSelectionModel *selection; |
123 | |
124 | gtk_init (); |
125 | |
126 | store = g_list_store_new (G_TYPE_OBJECT); |
127 | for (i = 0; i < AVERAGE; i++) |
128 | add (store); |
129 | sorter = GTK_SORTER (ptr: gtk_numeric_sorter_new (expression: gtk_cclosure_expression_new (G_TYPE_UINT, NULL, n_params: 0, NULL, callback_func: (GCallback)get_number, NULL, NULL))); |
130 | sort = gtk_sort_list_model_new (model: G_LIST_MODEL (ptr: store), sorter); |
131 | |
132 | win = gtk_window_new (); |
133 | gtk_window_set_default_size (GTK_WINDOW (win), width: 400, height: 600); |
134 | |
135 | hbox = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 4); |
136 | gtk_window_set_child (GTK_WINDOW (win), child: hbox); |
137 | |
138 | vbox = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 4); |
139 | gtk_box_append (GTK_BOX (hbox), child: vbox); |
140 | |
141 | label = gtk_label_new (str: "GtkListView" ); |
142 | gtk_box_append (GTK_BOX (vbox), child: label); |
143 | |
144 | sw = gtk_scrolled_window_new (); |
145 | gtk_widget_set_hexpand (widget: sw, TRUE); |
146 | gtk_widget_set_vexpand (widget: sw, TRUE); |
147 | gtk_box_append (GTK_BOX (vbox), child: sw); |
148 | |
149 | factory = gtk_signal_list_item_factory_new (); |
150 | g_signal_connect (factory, "setup" , G_CALLBACK (setup_list_item), NULL); |
151 | g_signal_connect (factory, "bind" , G_CALLBACK (bind_list_item), NULL); |
152 | listview = gtk_list_view_new (NULL, factory); |
153 | |
154 | gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), child: listview); |
155 | |
156 | vbox = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 4); |
157 | gtk_box_append (GTK_BOX (hbox), child: vbox); |
158 | |
159 | label = gtk_label_new (str: "GtkListBox" ); |
160 | gtk_box_append (GTK_BOX (vbox), child: label); |
161 | |
162 | sw = gtk_scrolled_window_new (); |
163 | gtk_widget_set_hexpand (widget: sw, TRUE); |
164 | gtk_widget_set_vexpand (widget: sw, TRUE); |
165 | gtk_box_append (GTK_BOX (vbox), child: sw); |
166 | |
167 | listbox = gtk_list_box_new (); |
168 | gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), child: listbox); |
169 | |
170 | selection = GTK_SELECTION_MODEL (ptr: gtk_single_selection_new (model: G_LIST_MODEL (ptr: sort))); |
171 | gtk_list_view_set_model (GTK_LIST_VIEW (listview), model: selection); |
172 | g_object_unref (object: selection); |
173 | gtk_list_box_bind_model (GTK_LIST_BOX (listbox), |
174 | model: G_LIST_MODEL (ptr: sort), |
175 | create_widget_func: create_widget_for_listbox, |
176 | NULL, NULL); |
177 | |
178 | g_timeout_add (interval: 100, function: do_stuff, data: store); |
179 | g_timeout_add_seconds (interval: 3, function: revert_sort, data: sorter); |
180 | |
181 | gtk_widget_show (widget: win); |
182 | |
183 | toplevels = gtk_window_get_toplevels (); |
184 | while (g_list_model_get_n_items (list: toplevels)) |
185 | g_main_context_iteration (NULL, TRUE); |
186 | |
187 | return 0; |
188 | } |
189 | |