1/* Lists/Characters
2 *
3 * This demo shows a multi-column representation of some parts
4 * of the Unicode Character Database, or UCD.
5 *
6 * The dataset used here has 33 796 items.
7 */
8
9#include <gtk/gtk.h>
10#include "script-names.h"
11#include "unicode-names.h"
12
13
14#define UCD_TYPE_ITEM (ucd_item_get_type ())
15G_DECLARE_FINAL_TYPE (UcdItem, ucd_item, UCD, ITEM, GObject)
16
17struct _UcdItem
18{
19 GObject parent_instance;
20 gunichar codepoint;
21 const char *name;
22};
23
24struct _UcdItemClass
25{
26 GObjectClass parent_class;
27};
28
29G_DEFINE_TYPE (UcdItem, ucd_item, G_TYPE_OBJECT)
30
31static void
32ucd_item_init (UcdItem *item)
33{
34}
35
36static void
37ucd_item_class_init (UcdItemClass *class)
38{
39}
40
41static UcdItem *
42ucd_item_new (gunichar codepoint,
43 const char *name)
44{
45 UcdItem *item;
46
47 item = g_object_new (UCD_TYPE_ITEM, NULL);
48
49 item->codepoint = codepoint;
50 item->name = name;
51
52 return item;
53}
54
55static gunichar
56ucd_item_get_codepoint (UcdItem *item)
57{
58 return item->codepoint;
59}
60
61static const char *
62ucd_item_get_name (UcdItem *item)
63{
64 return item->name;
65}
66
67static GListModel *
68ucd_model_new (void)
69{
70 GBytes *bytes;
71 GVariant *v;
72 GVariantIter *iter;
73 GListStore *store;
74 guint u;
75 char *name;
76
77 bytes = g_resources_lookup_data (path: "/listview_ucd_data/ucdnames.data", lookup_flags: 0, NULL);
78 v = g_variant_ref_sink (value: g_variant_new_from_bytes (G_VARIANT_TYPE ("a(us)"), bytes, TRUE));
79
80 iter = g_variant_iter_new (value: v);
81
82 store = g_list_store_new (G_TYPE_OBJECT);
83 while (g_variant_iter_next (iter, format_string: "(u&s)", &u, &name))
84 {
85 if (u == 0)
86 continue;
87
88 UcdItem *item = ucd_item_new (codepoint: u, name);
89 g_list_store_append (store, item);
90 g_object_unref (object: item);
91 }
92
93 g_variant_iter_free (iter);
94 g_variant_unref (value: v);
95 g_bytes_unref (bytes);
96
97 return G_LIST_MODEL (ptr: store);
98}
99
100static void
101setup_centered_label (GtkSignalListItemFactory *factory,
102 GObject *listitem)
103{
104 GtkWidget *label;
105 label = gtk_label_new (str: "");
106 gtk_list_item_set_child (GTK_LIST_ITEM (listitem), child: label);
107}
108
109static void
110setup_label (GtkSignalListItemFactory *factory,
111 GObject *listitem)
112{
113 GtkWidget *label;
114 label = gtk_label_new (str: "");
115 gtk_label_set_xalign (GTK_LABEL (label), xalign: 0);
116 gtk_list_item_set_child (GTK_LIST_ITEM (listitem), child: label);
117}
118
119static void
120setup_ellipsizing_label (GtkSignalListItemFactory *factory,
121 GObject *listitem)
122{
123 GtkWidget *label;
124 label = gtk_label_new (str: "");
125 gtk_label_set_xalign (GTK_LABEL (label), xalign: 0);
126 gtk_label_set_ellipsize (GTK_LABEL (label), mode: PANGO_ELLIPSIZE_END);
127 gtk_label_set_width_chars (GTK_LABEL (label), n_chars: 20);
128 gtk_list_item_set_child (GTK_LIST_ITEM (listitem), child: label);
129}
130
131static void
132bind_codepoint (GtkSignalListItemFactory *factory,
133 GObject *listitem)
134{
135 GtkWidget *label;
136 GObject *item;
137 gunichar codepoint;
138 char buffer[16] = { 0, };
139
140 label = gtk_list_item_get_child (GTK_LIST_ITEM (listitem));
141 item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
142 codepoint = ucd_item_get_codepoint (item: UCD_ITEM (ptr: item));
143
144 g_snprintf (string: buffer, n: 10, format: "%#06x", codepoint);
145 gtk_label_set_label (GTK_LABEL (label), str: buffer);
146}
147
148static void
149bind_char (GtkSignalListItemFactory *factory,
150 GObject *listitem)
151{
152 GtkWidget *label;
153 GObject *item;
154 gunichar codepoint;
155 char buffer[16] = { 0, };
156
157 label = gtk_list_item_get_child (GTK_LIST_ITEM (listitem));
158 item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
159 codepoint = ucd_item_get_codepoint (item: UCD_ITEM (ptr: item));
160
161 if (g_unichar_isprint (c: codepoint))
162 g_unichar_to_utf8 (c: codepoint, outbuf: buffer);
163
164 gtk_label_set_label (GTK_LABEL (label), str: buffer);
165}
166
167static void
168bind_name (GtkSignalListItemFactory *factory,
169 GObject *listitem)
170{
171 GtkWidget *label;
172 GObject *item;
173 const char *name;
174
175 label = gtk_list_item_get_child (GTK_LIST_ITEM (listitem));
176 item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
177 name = ucd_item_get_name (item: UCD_ITEM (ptr: item));
178
179 gtk_label_set_label (GTK_LABEL (label), str: name);
180}
181
182static void
183bind_type (GtkSignalListItemFactory *factory,
184 GObject *listitem)
185{
186 GtkWidget *label;
187 GObject *item;
188 gunichar codepoint;
189
190 label = gtk_list_item_get_child (GTK_LIST_ITEM (listitem));
191 item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
192 codepoint = ucd_item_get_codepoint (item: UCD_ITEM (ptr: item));
193
194 gtk_label_set_label (GTK_LABEL (label), str: get_unicode_type_name (type: g_unichar_type (c: codepoint)));
195}
196
197static void
198bind_break_type (GtkSignalListItemFactory *factory,
199 GObject *listitem)
200{
201 GtkWidget *label;
202 GObject *item;
203 gunichar codepoint;
204
205 label = gtk_list_item_get_child (GTK_LIST_ITEM (listitem));
206 item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
207 codepoint = ucd_item_get_codepoint (item: UCD_ITEM (ptr: item));
208
209 gtk_label_set_label (GTK_LABEL (label), str: get_break_type_name (type: g_unichar_break_type (c: codepoint)));
210}
211
212static void
213bind_combining_class (GtkSignalListItemFactory *factory,
214 GObject *listitem)
215{
216 GtkWidget *label;
217 GObject *item;
218 gunichar codepoint;
219
220 label = gtk_list_item_get_child (GTK_LIST_ITEM (listitem));
221 item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
222 codepoint = ucd_item_get_codepoint (item: UCD_ITEM (ptr: item));
223
224 gtk_label_set_label (GTK_LABEL (label), str: get_combining_class_name (cclass: g_unichar_combining_class (uc: codepoint)));
225}
226
227static void
228bind_script (GtkSignalListItemFactory *factory,
229 GObject *listitem)
230{
231 GtkWidget *label;
232 GObject *item;
233 gunichar codepoint;
234 GUnicodeScript script;
235
236 label = gtk_list_item_get_child (GTK_LIST_ITEM (listitem));
237 item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
238 codepoint = ucd_item_get_codepoint (item: UCD_ITEM (ptr: item));
239 script = g_unichar_get_script (ch: codepoint);
240
241 gtk_label_set_label (GTK_LABEL (label), str: get_script_name (script));
242}
243
244static void
245selection_changed (GObject *object,
246 GParamSpec *pspec,
247 GtkWidget *label)
248{
249 UcdItem *item;
250 guint codepoint;
251 char buffer[16] = { 0, };
252
253 item = gtk_single_selection_get_selected_item (self: GTK_SINGLE_SELECTION (ptr: object));
254 codepoint = ucd_item_get_codepoint (item);
255
256 if (g_unichar_isprint (c: codepoint))
257 g_unichar_to_utf8 (c: codepoint, outbuf: buffer);
258
259 gtk_label_set_label (GTK_LABEL (label), str: buffer);
260}
261
262GtkWidget *
263create_ucd_view (GtkWidget *label)
264{
265 GtkWidget *cv;
266 GListModel *ucd_model;
267 GtkSingleSelection *selection;
268 GtkListItemFactory *factory;
269 GtkColumnViewColumn *column;
270
271 ucd_model = ucd_model_new ();
272
273 selection = gtk_single_selection_new (model: ucd_model);
274 gtk_single_selection_set_autoselect (self: selection, TRUE);
275 gtk_single_selection_set_can_unselect (self: selection, FALSE);
276 if (label)
277 g_signal_connect (selection, "notify::selected", G_CALLBACK (selection_changed), label);
278
279 cv = gtk_column_view_new (model: GTK_SELECTION_MODEL (ptr: selection));
280 gtk_column_view_set_show_column_separators (GTK_COLUMN_VIEW (cv), TRUE);
281
282 factory = gtk_signal_list_item_factory_new ();
283 g_signal_connect (factory, "setup", G_CALLBACK (setup_centered_label), NULL);
284 g_signal_connect (factory, "bind", G_CALLBACK (bind_codepoint), NULL);
285 column = gtk_column_view_column_new (title: "Codepoint", factory);
286 gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
287 g_object_unref (object: column);
288
289 factory = gtk_signal_list_item_factory_new ();
290 g_signal_connect (factory, "setup", G_CALLBACK (setup_centered_label), NULL);
291 g_signal_connect (factory, "bind", G_CALLBACK (bind_char), NULL);
292 column = gtk_column_view_column_new (title: "Char", factory);
293 gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
294 g_object_unref (object: column);
295
296 factory = gtk_signal_list_item_factory_new ();
297 g_signal_connect (factory, "setup", G_CALLBACK (setup_ellipsizing_label), NULL);
298 g_signal_connect (factory, "bind", G_CALLBACK (bind_name), NULL);
299 column = gtk_column_view_column_new (title: "Name", factory);
300 gtk_column_view_column_set_resizable (self: column, TRUE);
301 gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
302 g_object_unref (object: column);
303
304 factory = gtk_signal_list_item_factory_new ();
305 g_signal_connect (factory, "setup", G_CALLBACK (setup_ellipsizing_label), NULL);
306 g_signal_connect (factory, "bind", G_CALLBACK (bind_type), NULL);
307 column = gtk_column_view_column_new (title: "Type", factory);
308 gtk_column_view_column_set_resizable (self: column, TRUE);
309 gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
310 g_object_unref (object: column);
311
312 factory = gtk_signal_list_item_factory_new ();
313 g_signal_connect (factory, "setup", G_CALLBACK (setup_ellipsizing_label), NULL);
314 g_signal_connect (factory, "bind", G_CALLBACK (bind_break_type), NULL);
315 column = gtk_column_view_column_new (title: "Break Type", factory);
316 gtk_column_view_column_set_resizable (self: column, TRUE);
317 gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
318 g_object_unref (object: column);
319
320 factory = gtk_signal_list_item_factory_new ();
321 g_signal_connect (factory, "setup", G_CALLBACK (setup_label), NULL);
322 g_signal_connect (factory, "bind", G_CALLBACK (bind_combining_class), NULL);
323 column = gtk_column_view_column_new (title: "Combining Class", factory);
324 gtk_column_view_column_set_resizable (self: column, TRUE);
325 gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
326 g_object_unref (object: column);
327
328 factory = gtk_signal_list_item_factory_new ();
329 g_signal_connect (factory, "setup", G_CALLBACK (setup_label), NULL);
330 g_signal_connect (factory, "bind", G_CALLBACK (bind_script), NULL);
331 column = gtk_column_view_column_new (title: "Script", factory);
332 gtk_column_view_column_set_resizable (self: column, TRUE);
333 gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
334 g_object_unref (object: column);
335
336 return cv;
337}
338
339static GtkWidget *window;
340
341GtkWidget *
342do_listview_ucd (GtkWidget *do_widget)
343{
344 if (window == NULL)
345 {
346 GtkWidget *listview, *sw;
347 GtkWidget *box, *label;
348 GtkCssProvider *provider;
349
350 window = gtk_window_new ();
351 gtk_window_set_default_size (GTK_WINDOW (window), width: 800, height: 400);
352 gtk_window_set_title (GTK_WINDOW (window), title: "Characters");
353 gtk_window_set_display (GTK_WINDOW (window),
354 display: gtk_widget_get_display (widget: do_widget));
355 g_object_add_weak_pointer (G_OBJECT (window), weak_pointer_location: (gpointer *) &window);
356
357 box = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 0);
358 label = gtk_label_new (str: "");
359 gtk_label_set_width_chars (GTK_LABEL (label), n_chars: 2);
360 gtk_widget_add_css_class (widget: label, css_class: "enormous");
361 provider = gtk_css_provider_new ();
362 gtk_css_provider_load_from_data (css_provider: provider, data: "label.enormous { font-size: 80px; }", length: -1);
363 gtk_style_context_add_provider (context: gtk_widget_get_style_context (widget: label), GTK_STYLE_PROVIDER (provider), priority: 800);
364 gtk_widget_set_hexpand (widget: label, TRUE);
365 gtk_box_append (GTK_BOX (box), child: label);
366
367 sw = gtk_scrolled_window_new ();
368 gtk_scrolled_window_set_propagate_natural_width (GTK_SCROLLED_WINDOW (sw), TRUE);
369 listview = create_ucd_view (label);
370 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), child: listview);
371 gtk_box_prepend (GTK_BOX (box), child: sw);
372 gtk_window_set_child (GTK_WINDOW (window), child: box);
373 }
374
375 if (!gtk_widget_get_visible (widget: window))
376 gtk_widget_show (widget: window);
377 else
378 gtk_window_destroy (GTK_WINDOW (window));
379
380 return window;
381}
382
383

source code of gtk/demos/gtk-demo/listview_ucd.c