/* Lists/Characters
*
* This demo shows a multi - column representation of some parts
* of the Unicode Character Database , or UCD . It also demonstrates
* the use of sections with headings to group items .
*
* The dataset used here has 33 796 items .
*/
#include <gtk/gtk.h>
#include "script-names.h"
#include "unicode-names.h"
#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;
GUnicodeScript script;
};
struct _UcdItemClass
{
GObjectClass parent_class;
};
enum
{
PROP_CODEPOINT = 1 ,
PROP_NAME,
PROP_SCRIPT,
NUM_PROPERTIES,
};
static GParamSpec *props[NUM_PROPERTIES] = { NULL, };
G_DEFINE_TYPE (UcdItem, ucd_item, G_TYPE_OBJECT)
static void
ucd_item_init (UcdItem *item)
{
}
static void
ucd_item_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
UcdItem *item = UCD_ITEM (object);
switch (prop_id)
{
case PROP_CODEPOINT:
g_value_set_uint (value, item->codepoint);
break ;
case PROP_NAME:
g_value_set_string (value, item->name);
break ;
case PROP_SCRIPT:
g_value_set_uint (value, item->script);
break ;
default :
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break ;
}
}
static void
ucd_item_class_init (UcdItemClass *class )
{
GObjectClass *object_class = G_OBJECT_CLASS (class );
object_class->get_property = ucd_item_get_property;
props[PROP_CODEPOINT] = g_param_spec_uint ("codepoint" , NULL, NULL,
0 , G_MAXUINT, 0 ,
G_PARAM_READABLE | G_PARAM_STATIC_NAME);
props[PROP_NAME] = g_param_spec_string ("name" , NULL, NULL,
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_NAME);
props[PROP_SCRIPT] = g_param_spec_uint ("script" , NULL, NULL,
0 , G_MAXUINT, 0 ,
G_PARAM_READABLE | G_PARAM_STATIC_NAME);
g_object_class_install_properties (object_class, NUM_PROPERTIES, props);
}
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;
item->script = g_unichar_get_script (codepoint);
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 GUnicodeScript
ucd_item_get_script (UcdItem *item)
{
return item->script;
}
static GListModel *
ucd_model_new (void )
{
GBytes *bytes;
GVariant *v;
GVariantIter *iter;
GListStore *store;
guint u;
char *name;
GtkExpression *expression;
GtkNumericSorter *sorter;
GtkSortListModel *sort;
bytes = g_resources_lookup_data ("/listview_ucd_data/ucdnames.data" , 0 , NULL);
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);
while (g_variant_iter_next (iter, "(u&s)" , &u, &name))
{
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);
expression = gtk_property_expression_new (ucd_item_get_type (),
NULL,
"codepoint" );
sorter = gtk_numeric_sorter_new (expression);
sort = gtk_sort_list_model_new (G_LIST_MODEL (store), GTK_SORTER (sorter));
expression = gtk_property_expression_new (ucd_item_get_type (),
NULL,
"script" );
sorter = gtk_numeric_sorter_new (expression);
gtk_sort_list_model_set_section_sorter (sort, GTK_SORTER (sorter));
g_object_unref (sorter);
return G_LIST_MODEL (sort);
}
static void
setup_centered_label (GtkSignalListItemFactory *factory,
GObject *listitem)
{
GtkWidget *label;
label = gtk_inscription_new ("" );
gtk_list_item_set_child (GTK_LIST_ITEM (listitem), label);
}
static void
setup_label (GtkSignalListItemFactory *factory,
GObject *listitem)
{
GtkWidget *label;
label = gtk_inscription_new ("" );
gtk_inscription_set_xalign (GTK_INSCRIPTION (label), 0 );
gtk_list_item_set_child (GTK_LIST_ITEM (listitem), label);
}
static void
setup_ellipsizing_label (GtkSignalListItemFactory *factory,
GObject *listitem)
{
GtkWidget *label;
label = gtk_inscription_new ("" );
gtk_inscription_set_xalign (GTK_INSCRIPTION (label), 0 );
gtk_inscription_set_text_overflow (GTK_INSCRIPTION (label), GTK_INSCRIPTION_OVERFLOW_ELLIPSIZE_END);
gtk_inscription_set_nat_chars (GTK_INSCRIPTION (label), 20 );
gtk_list_item_set_child (GTK_LIST_ITEM (listitem), label);
}
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_inscription_set_text (GTK_INSCRIPTION (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_inscription_set_text (GTK_INSCRIPTION (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_inscription_set_text (GTK_INSCRIPTION (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));
gtk_inscription_set_text (GTK_INSCRIPTION (label), get_unicode_type_name (g_unichar_type (codepoint)));
}
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));
gtk_inscription_set_text (GTK_INSCRIPTION (label), get_break_type_name (g_unichar_break_type (codepoint)));
}
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));
gtk_inscription_set_text (GTK_INSCRIPTION (label), get_combining_class_name (g_unichar_combining_class (codepoint)));
}
static void
setup_header (GtkSignalListItemFactory *factory,
GObject *listitem)
{
GtkWidget *label;
label = gtk_inscription_new ("" );
gtk_widget_add_css_class (label, "heading" );
gtk_widget_set_margin_start (label, 20 );
gtk_widget_set_margin_end (label, 20 );
gtk_widget_set_margin_top (label, 10 );
gtk_widget_set_margin_bottom (label, 10 );
gtk_inscription_set_xalign (GTK_INSCRIPTION (label), 0 );
gtk_list_header_set_child (GTK_LIST_HEADER (listitem), label);
}
static void
bind_header (GtkSignalListItemFactory *factory,
GObject *listitem)
{
GtkWidget *label;
GObject *item;
GUnicodeScript script;
label = gtk_list_header_get_child (GTK_LIST_HEADER (listitem));
item = gtk_list_header_get_item (GTK_LIST_HEADER (listitem));
script = ucd_item_get_script (UCD_ITEM (item));
gtk_inscription_set_text (GTK_INSCRIPTION (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_text (GTK_LABEL (label), buffer);
}
GtkWidget *
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 );
if (label)
g_signal_connect (selection, "notify::selected" , G_CALLBACK (selection_changed), label);
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);
g_object_unref (column);
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);
g_object_unref (column);
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup" , G_CALLBACK (setup_ellipsizing_label), NULL);
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);
g_object_unref (column);
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup" , G_CALLBACK (setup_ellipsizing_label), NULL);
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);
g_object_unref (column);
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup" , G_CALLBACK (setup_ellipsizing_label), NULL);
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);
g_object_unref (column);
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);
g_object_unref (column);
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup" , G_CALLBACK (setup_header), NULL);
g_signal_connect (factory, "bind" , G_CALLBACK (bind_header), NULL);
gtk_column_view_set_header_factory (GTK_COLUMN_VIEW (cv), factory);
g_object_unref (factory);
return cv;
}
static GtkWidget *window;
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);
}
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 ();
gtk_css_provider_load_from_string (provider, "label.enormous { font-size: 80px; }" );
gtk_style_context_add_provider_for_display (gdk_display_get_default (), GTK_STYLE_PROVIDER (provider), 800 );
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);
g_object_set_data_full (G_OBJECT (window), "provider" , provider, remove_provider);
}
if (!gtk_widget_get_visible (window))
gtk_widget_set_visible (window, TRUE );
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
Messung V0.5 in Prozent C=98 H=95 G=96
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-07-02)
¤
*© Formatika GbR, Deutschland