2020-10-05 01:21:44 +00:00
|
|
|
|
/* Lists/Characters
|
|
|
|
|
*
|
|
|
|
|
* This demo shows a multi-column representation of some parts
|
|
|
|
|
* of the Unicode Character Database, or UCD.
|
2020-10-05 18:43:38 +00:00
|
|
|
|
*
|
|
|
|
|
* The dataset used here has 33 796 items.
|
2020-10-05 01:21:44 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
|
#include "script-names.h"
|
2020-10-05 13:56:04 +00:00
|
|
|
|
#include "unicode-names.h"
|
2020-10-05 01:21:44 +00:00
|
|
|
|
|
|
|
|
|
#define UCD_TYPE_ITEM (ucd_item_get_type ())
|
|
|
|
|
G_DECLARE_FINAL_TYPE (UcdItem, ucd_item, UCD, ITEM, GObject)
|
|
|
|
|
|
|
|
|
|
struct _UcdItem
|
|
|
|
|
{
|
|
|
|
|
GObject parent_instance;
|
|
|
|
|
gunichar codepoint;
|
|
|
|
|
const char *name;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct _UcdItemClass
|
|
|
|
|
{
|
|
|
|
|
GObjectClass parent_class;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (UcdItem, ucd_item, G_TYPE_OBJECT)
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ucd_item_init (UcdItem *item)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ucd_item_class_init (UcdItemClass *class)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static UcdItem *
|
|
|
|
|
ucd_item_new (gunichar codepoint,
|
|
|
|
|
const char *name)
|
|
|
|
|
{
|
|
|
|
|
UcdItem *item;
|
|
|
|
|
|
|
|
|
|
item = g_object_new (UCD_TYPE_ITEM, NULL);
|
|
|
|
|
|
|
|
|
|
item->codepoint = codepoint;
|
|
|
|
|
item->name = name;
|
|
|
|
|
|
|
|
|
|
return item;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gunichar
|
|
|
|
|
ucd_item_get_codepoint (UcdItem *item)
|
|
|
|
|
{
|
|
|
|
|
return item->codepoint;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
|
ucd_item_get_name (UcdItem *item)
|
|
|
|
|
{
|
|
|
|
|
return item->name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GListModel *
|
|
|
|
|
ucd_model_new (void)
|
|
|
|
|
{
|
|
|
|
|
GBytes *bytes;
|
|
|
|
|
GVariant *v;
|
|
|
|
|
GVariantIter *iter;
|
|
|
|
|
GListStore *store;
|
|
|
|
|
guint u;
|
|
|
|
|
char *name;
|
|
|
|
|
|
2020-10-09 11:51:57 +00:00
|
|
|
|
bytes = g_resources_lookup_data ("/listview_ucd_data/ucdnames.data", 0, NULL);
|
2020-10-05 01:21:44 +00:00
|
|
|
|
v = g_variant_ref_sink (g_variant_new_from_bytes (G_VARIANT_TYPE ("a(us)"), bytes, TRUE));
|
|
|
|
|
|
|
|
|
|
iter = g_variant_iter_new (v);
|
|
|
|
|
|
|
|
|
|
store = g_list_store_new (G_TYPE_OBJECT);
|
2020-11-10 02:04:52 +00:00
|
|
|
|
while (g_variant_iter_next (iter, "(u&s)", &u, &name))
|
2020-10-05 01:21:44 +00:00
|
|
|
|
{
|
|
|
|
|
if (u == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
UcdItem *item = ucd_item_new (u, name);
|
|
|
|
|
g_list_store_append (store, item);
|
|
|
|
|
g_object_unref (item);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_variant_iter_free (iter);
|
|
|
|
|
g_variant_unref (v);
|
|
|
|
|
g_bytes_unref (bytes);
|
|
|
|
|
|
|
|
|
|
return G_LIST_MODEL (store);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setup_centered_label (GtkSignalListItemFactory *factory,
|
|
|
|
|
GObject *listitem)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *label;
|
|
|
|
|
label = gtk_label_new ("");
|
|
|
|
|
gtk_list_item_set_child (GTK_LIST_ITEM (listitem), label);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setup_label (GtkSignalListItemFactory *factory,
|
|
|
|
|
GObject *listitem)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *label;
|
|
|
|
|
label = gtk_label_new ("");
|
|
|
|
|
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
|
|
|
|
gtk_list_item_set_child (GTK_LIST_ITEM (listitem), label);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-08 19:55:22 +00:00
|
|
|
|
static void
|
|
|
|
|
setup_ellipsizing_label (GtkSignalListItemFactory *factory,
|
|
|
|
|
GObject *listitem)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *label;
|
|
|
|
|
label = gtk_label_new ("");
|
|
|
|
|
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
|
|
|
|
gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
|
|
|
|
|
gtk_label_set_width_chars (GTK_LABEL (label), 20);
|
|
|
|
|
gtk_list_item_set_child (GTK_LIST_ITEM (listitem), label);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-05 01:21:44 +00:00
|
|
|
|
static void
|
|
|
|
|
bind_codepoint (GtkSignalListItemFactory *factory,
|
|
|
|
|
GObject *listitem)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *label;
|
|
|
|
|
GObject *item;
|
|
|
|
|
gunichar codepoint;
|
|
|
|
|
char buffer[16] = { 0, };
|
|
|
|
|
|
|
|
|
|
label = gtk_list_item_get_child (GTK_LIST_ITEM (listitem));
|
|
|
|
|
item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
|
|
|
|
|
codepoint = ucd_item_get_codepoint (UCD_ITEM (item));
|
|
|
|
|
|
|
|
|
|
g_snprintf (buffer, 10, "%#06x", codepoint);
|
|
|
|
|
gtk_label_set_label (GTK_LABEL (label), buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
bind_char (GtkSignalListItemFactory *factory,
|
|
|
|
|
GObject *listitem)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *label;
|
|
|
|
|
GObject *item;
|
|
|
|
|
gunichar codepoint;
|
|
|
|
|
char buffer[16] = { 0, };
|
|
|
|
|
|
|
|
|
|
label = gtk_list_item_get_child (GTK_LIST_ITEM (listitem));
|
|
|
|
|
item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
|
|
|
|
|
codepoint = ucd_item_get_codepoint (UCD_ITEM (item));
|
|
|
|
|
|
|
|
|
|
if (g_unichar_isprint (codepoint))
|
|
|
|
|
g_unichar_to_utf8 (codepoint, buffer);
|
|
|
|
|
|
|
|
|
|
gtk_label_set_label (GTK_LABEL (label), buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
bind_name (GtkSignalListItemFactory *factory,
|
|
|
|
|
GObject *listitem)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *label;
|
|
|
|
|
GObject *item;
|
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
|
|
label = gtk_list_item_get_child (GTK_LIST_ITEM (listitem));
|
|
|
|
|
item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
|
|
|
|
|
name = ucd_item_get_name (UCD_ITEM (item));
|
|
|
|
|
|
|
|
|
|
gtk_label_set_label (GTK_LABEL (label), name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
bind_type (GtkSignalListItemFactory *factory,
|
|
|
|
|
GObject *listitem)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *label;
|
|
|
|
|
GObject *item;
|
|
|
|
|
gunichar codepoint;
|
|
|
|
|
|
|
|
|
|
label = gtk_list_item_get_child (GTK_LIST_ITEM (listitem));
|
|
|
|
|
item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
|
|
|
|
|
codepoint = ucd_item_get_codepoint (UCD_ITEM (item));
|
|
|
|
|
|
2020-10-05 13:56:04 +00:00
|
|
|
|
gtk_label_set_label (GTK_LABEL (label), get_unicode_type_name (g_unichar_type (codepoint)));
|
2020-10-05 01:21:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
bind_break_type (GtkSignalListItemFactory *factory,
|
|
|
|
|
GObject *listitem)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *label;
|
|
|
|
|
GObject *item;
|
|
|
|
|
gunichar codepoint;
|
|
|
|
|
|
|
|
|
|
label = gtk_list_item_get_child (GTK_LIST_ITEM (listitem));
|
|
|
|
|
item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
|
|
|
|
|
codepoint = ucd_item_get_codepoint (UCD_ITEM (item));
|
|
|
|
|
|
2020-10-05 13:56:04 +00:00
|
|
|
|
gtk_label_set_label (GTK_LABEL (label), get_break_type_name (g_unichar_break_type (codepoint)));
|
2020-10-05 01:21:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
bind_combining_class (GtkSignalListItemFactory *factory,
|
|
|
|
|
GObject *listitem)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *label;
|
|
|
|
|
GObject *item;
|
|
|
|
|
gunichar codepoint;
|
|
|
|
|
|
|
|
|
|
label = gtk_list_item_get_child (GTK_LIST_ITEM (listitem));
|
|
|
|
|
item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
|
|
|
|
|
codepoint = ucd_item_get_codepoint (UCD_ITEM (item));
|
|
|
|
|
|
2020-10-05 13:56:04 +00:00
|
|
|
|
gtk_label_set_label (GTK_LABEL (label), get_combining_class_name (g_unichar_combining_class (codepoint)));
|
2020-10-05 01:21:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
bind_script (GtkSignalListItemFactory *factory,
|
|
|
|
|
GObject *listitem)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *label;
|
|
|
|
|
GObject *item;
|
|
|
|
|
gunichar codepoint;
|
|
|
|
|
GUnicodeScript script;
|
|
|
|
|
|
|
|
|
|
label = gtk_list_item_get_child (GTK_LIST_ITEM (listitem));
|
|
|
|
|
item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
|
|
|
|
|
codepoint = ucd_item_get_codepoint (UCD_ITEM (item));
|
|
|
|
|
script = g_unichar_get_script (codepoint);
|
|
|
|
|
|
|
|
|
|
gtk_label_set_label (GTK_LABEL (label), get_script_name (script));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
selection_changed (GObject *object,
|
|
|
|
|
GParamSpec *pspec,
|
|
|
|
|
GtkWidget *label)
|
|
|
|
|
{
|
|
|
|
|
UcdItem *item;
|
|
|
|
|
guint codepoint;
|
|
|
|
|
char buffer[16] = { 0, };
|
|
|
|
|
|
|
|
|
|
item = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (object));
|
|
|
|
|
codepoint = ucd_item_get_codepoint (item);
|
|
|
|
|
|
|
|
|
|
if (g_unichar_isprint (codepoint))
|
|
|
|
|
g_unichar_to_utf8 (codepoint, buffer);
|
|
|
|
|
|
|
|
|
|
gtk_label_set_label (GTK_LABEL (label), buffer);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-10 01:07:09 +00:00
|
|
|
|
GtkWidget *
|
2020-10-05 01:21:44 +00:00
|
|
|
|
create_ucd_view (GtkWidget *label)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *cv;
|
|
|
|
|
GListModel *ucd_model;
|
|
|
|
|
GtkSingleSelection *selection;
|
|
|
|
|
GtkListItemFactory *factory;
|
|
|
|
|
GtkColumnViewColumn *column;
|
|
|
|
|
|
|
|
|
|
ucd_model = ucd_model_new ();
|
|
|
|
|
|
|
|
|
|
selection = gtk_single_selection_new (ucd_model);
|
|
|
|
|
gtk_single_selection_set_autoselect (selection, TRUE);
|
|
|
|
|
gtk_single_selection_set_can_unselect (selection, FALSE);
|
2020-11-10 01:07:09 +00:00
|
|
|
|
if (label)
|
|
|
|
|
g_signal_connect (selection, "notify::selected", G_CALLBACK (selection_changed), label);
|
2020-10-05 01:21:44 +00:00
|
|
|
|
|
|
|
|
|
cv = gtk_column_view_new (GTK_SELECTION_MODEL (selection));
|
|
|
|
|
gtk_column_view_set_show_column_separators (GTK_COLUMN_VIEW (cv), TRUE);
|
|
|
|
|
|
|
|
|
|
factory = gtk_signal_list_item_factory_new ();
|
|
|
|
|
g_signal_connect (factory, "setup", G_CALLBACK (setup_centered_label), NULL);
|
|
|
|
|
g_signal_connect (factory, "bind", G_CALLBACK (bind_codepoint), NULL);
|
|
|
|
|
column = gtk_column_view_column_new ("Codepoint", factory);
|
|
|
|
|
gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
|
2020-11-16 04:03:30 +00:00
|
|
|
|
g_object_unref (column);
|
2020-10-05 01:21:44 +00:00
|
|
|
|
|
|
|
|
|
factory = gtk_signal_list_item_factory_new ();
|
|
|
|
|
g_signal_connect (factory, "setup", G_CALLBACK (setup_centered_label), NULL);
|
|
|
|
|
g_signal_connect (factory, "bind", G_CALLBACK (bind_char), NULL);
|
|
|
|
|
column = gtk_column_view_column_new ("Char", factory);
|
|
|
|
|
gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
|
2020-11-16 04:03:30 +00:00
|
|
|
|
g_object_unref (column);
|
2020-10-05 01:21:44 +00:00
|
|
|
|
|
|
|
|
|
factory = gtk_signal_list_item_factory_new ();
|
2020-10-08 19:55:22 +00:00
|
|
|
|
g_signal_connect (factory, "setup", G_CALLBACK (setup_ellipsizing_label), NULL);
|
2020-10-05 01:21:44 +00:00
|
|
|
|
g_signal_connect (factory, "bind", G_CALLBACK (bind_name), NULL);
|
|
|
|
|
column = gtk_column_view_column_new ("Name", factory);
|
|
|
|
|
gtk_column_view_column_set_resizable (column, TRUE);
|
|
|
|
|
gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
|
2020-11-16 04:03:30 +00:00
|
|
|
|
g_object_unref (column);
|
2020-10-05 01:21:44 +00:00
|
|
|
|
|
|
|
|
|
factory = gtk_signal_list_item_factory_new ();
|
2020-10-08 19:55:22 +00:00
|
|
|
|
g_signal_connect (factory, "setup", G_CALLBACK (setup_ellipsizing_label), NULL);
|
2020-10-05 01:21:44 +00:00
|
|
|
|
g_signal_connect (factory, "bind", G_CALLBACK (bind_type), NULL);
|
|
|
|
|
column = gtk_column_view_column_new ("Type", factory);
|
|
|
|
|
gtk_column_view_column_set_resizable (column, TRUE);
|
|
|
|
|
gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
|
2020-11-16 04:03:30 +00:00
|
|
|
|
g_object_unref (column);
|
2020-10-05 01:21:44 +00:00
|
|
|
|
|
|
|
|
|
factory = gtk_signal_list_item_factory_new ();
|
2020-10-08 19:55:22 +00:00
|
|
|
|
g_signal_connect (factory, "setup", G_CALLBACK (setup_ellipsizing_label), NULL);
|
2020-10-05 01:21:44 +00:00
|
|
|
|
g_signal_connect (factory, "bind", G_CALLBACK (bind_break_type), NULL);
|
|
|
|
|
column = gtk_column_view_column_new ("Break Type", factory);
|
|
|
|
|
gtk_column_view_column_set_resizable (column, TRUE);
|
|
|
|
|
gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
|
2020-11-16 04:03:30 +00:00
|
|
|
|
g_object_unref (column);
|
2020-10-05 01:21:44 +00:00
|
|
|
|
|
|
|
|
|
factory = gtk_signal_list_item_factory_new ();
|
|
|
|
|
g_signal_connect (factory, "setup", G_CALLBACK (setup_label), NULL);
|
|
|
|
|
g_signal_connect (factory, "bind", G_CALLBACK (bind_combining_class), NULL);
|
|
|
|
|
column = gtk_column_view_column_new ("Combining Class", factory);
|
|
|
|
|
gtk_column_view_column_set_resizable (column, TRUE);
|
|
|
|
|
gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
|
2020-11-16 04:03:30 +00:00
|
|
|
|
g_object_unref (column);
|
2020-10-05 01:21:44 +00:00
|
|
|
|
|
|
|
|
|
factory = gtk_signal_list_item_factory_new ();
|
|
|
|
|
g_signal_connect (factory, "setup", G_CALLBACK (setup_label), NULL);
|
|
|
|
|
g_signal_connect (factory, "bind", G_CALLBACK (bind_script), NULL);
|
|
|
|
|
column = gtk_column_view_column_new ("Script", factory);
|
|
|
|
|
gtk_column_view_column_set_resizable (column, TRUE);
|
|
|
|
|
gtk_column_view_append_column (GTK_COLUMN_VIEW (cv), column);
|
2020-11-16 04:03:30 +00:00
|
|
|
|
g_object_unref (column);
|
2020-10-05 01:21:44 +00:00
|
|
|
|
|
|
|
|
|
return cv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GtkWidget *window;
|
|
|
|
|
|
2022-10-22 00:58:26 +00:00
|
|
|
|
static void
|
|
|
|
|
remove_provider (gpointer data)
|
|
|
|
|
{
|
|
|
|
|
GtkStyleProvider *provider = GTK_STYLE_PROVIDER (data);
|
|
|
|
|
|
|
|
|
|
gtk_style_context_remove_provider_for_display (gdk_display_get_default (), provider);
|
|
|
|
|
g_object_unref (provider);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-05 01:21:44 +00:00
|
|
|
|
GtkWidget *
|
|
|
|
|
do_listview_ucd (GtkWidget *do_widget)
|
|
|
|
|
{
|
|
|
|
|
if (window == NULL)
|
|
|
|
|
{
|
|
|
|
|
GtkWidget *listview, *sw;
|
|
|
|
|
GtkWidget *box, *label;
|
|
|
|
|
GtkCssProvider *provider;
|
|
|
|
|
|
|
|
|
|
window = gtk_window_new ();
|
|
|
|
|
gtk_window_set_default_size (GTK_WINDOW (window), 800, 400);
|
|
|
|
|
gtk_window_set_title (GTK_WINDOW (window), "Characters");
|
|
|
|
|
gtk_window_set_display (GTK_WINDOW (window),
|
|
|
|
|
gtk_widget_get_display (do_widget));
|
|
|
|
|
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
|
|
|
|
|
|
|
|
|
|
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
|
|
|
|
label = gtk_label_new ("");
|
|
|
|
|
gtk_label_set_width_chars (GTK_LABEL (label), 2);
|
|
|
|
|
gtk_widget_add_css_class (label, "enormous");
|
|
|
|
|
provider = gtk_css_provider_new ();
|
2023-05-13 23:44:42 +00:00
|
|
|
|
gtk_css_provider_load_from_string (provider, "label.enormous { font-size: 80px; }");
|
2022-10-22 00:58:26 +00:00
|
|
|
|
gtk_style_context_add_provider_for_display (gdk_display_get_default (), GTK_STYLE_PROVIDER (provider), 800);
|
2020-10-05 01:21:44 +00:00
|
|
|
|
gtk_widget_set_hexpand (label, TRUE);
|
|
|
|
|
gtk_box_append (GTK_BOX (box), label);
|
|
|
|
|
|
|
|
|
|
sw = gtk_scrolled_window_new ();
|
|
|
|
|
gtk_scrolled_window_set_propagate_natural_width (GTK_SCROLLED_WINDOW (sw), TRUE);
|
|
|
|
|
listview = create_ucd_view (label);
|
|
|
|
|
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), listview);
|
|
|
|
|
gtk_box_prepend (GTK_BOX (box), sw);
|
|
|
|
|
gtk_window_set_child (GTK_WINDOW (window), box);
|
2022-10-22 00:58:26 +00:00
|
|
|
|
|
|
|
|
|
g_object_set_data_full (G_OBJECT (window), "provider", provider, remove_provider);
|
2020-10-05 01:21:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!gtk_widget_get_visible (window))
|
2022-11-28 04:03:14 +00:00
|
|
|
|
gtk_widget_set_visible (window, TRUE);
|
2020-10-05 01:21:44 +00:00
|
|
|
|
else
|
|
|
|
|
gtk_window_destroy (GTK_WINDOW (window));
|
|
|
|
|
|
|
|
|
|
return window;
|
|
|
|
|
}
|
|
|
|
|
|