forked from AuroraMiddleware/gtk
testlistview: Create widgets only once
Previously, we were recreating all widgets every time the list item was rebound, which caused a lot of extra work every time we scrolled. Now we keep the widgets around and only set their properties again when the item changes.
This commit is contained in:
parent
7389e704dc
commit
d8eec549f0
@ -20,7 +20,8 @@ start_enumerate (GListStore *store)
|
||||
enumerate = g_file_enumerate_children (file,
|
||||
G_FILE_ATTRIBUTE_STANDARD_TYPE
|
||||
"," G_FILE_ATTRIBUTE_STANDARD_ICON
|
||||
"," G_FILE_ATTRIBUTE_STANDARD_NAME,
|
||||
"," G_FILE_ATTRIBUTE_STANDARD_NAME
|
||||
"," G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
|
||||
0,
|
||||
NULL,
|
||||
&error);
|
||||
@ -138,72 +139,116 @@ create_list_model_for_directory (gpointer file)
|
||||
return G_LIST_MODEL (sort);
|
||||
}
|
||||
|
||||
typedef struct _RowData RowData;
|
||||
struct _RowData
|
||||
{
|
||||
GtkWidget *depth_box;
|
||||
GtkWidget *expander;
|
||||
GtkWidget *icon;
|
||||
GtkWidget *name;
|
||||
|
||||
GtkTreeListRow *current_item;
|
||||
GBinding *expander_binding;
|
||||
};
|
||||
|
||||
static void row_data_notify_item (GtkListItem *item,
|
||||
GParamSpec *pspec,
|
||||
RowData *data);
|
||||
static void
|
||||
bind_widget (GtkListItem *list_item,
|
||||
gpointer unused)
|
||||
row_data_unbind (RowData *data)
|
||||
{
|
||||
if (data->current_item == NULL)
|
||||
return;
|
||||
|
||||
g_binding_unbind (data->expander_binding);
|
||||
|
||||
g_clear_object (&data->current_item);
|
||||
}
|
||||
|
||||
static void
|
||||
row_data_bind (RowData *data,
|
||||
GtkTreeListRow *item)
|
||||
{
|
||||
GFileInfo *info;
|
||||
GIcon *icon;
|
||||
guint depth;
|
||||
|
||||
row_data_unbind (data);
|
||||
|
||||
if (item == NULL)
|
||||
return;
|
||||
|
||||
data->current_item = g_object_ref (item);
|
||||
|
||||
depth = gtk_tree_list_row_get_depth (item);
|
||||
gtk_widget_set_size_request (data->depth_box, 16 * depth, 0);
|
||||
|
||||
gtk_widget_set_sensitive (data->expander, gtk_tree_list_row_is_expandable (item));
|
||||
data->expander_binding = g_object_bind_property (item, "expanded", data->expander, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
||||
|
||||
info = gtk_tree_list_row_get_item (item);
|
||||
|
||||
icon = g_file_info_get_icon (info);
|
||||
gtk_widget_set_visible (data->icon, icon != NULL);
|
||||
if (icon)
|
||||
gtk_image_set_from_gicon (GTK_IMAGE (data->icon), icon);
|
||||
|
||||
gtk_label_set_label (GTK_LABEL (data->name), g_file_info_get_display_name (info));
|
||||
|
||||
g_object_unref (info);
|
||||
}
|
||||
|
||||
static void
|
||||
row_data_notify_item (GtkListItem *item,
|
||||
GParamSpec *pspec,
|
||||
RowData *data)
|
||||
{
|
||||
row_data_bind (data, gtk_list_item_get_item (item));
|
||||
}
|
||||
|
||||
static void
|
||||
row_data_free (gpointer _data)
|
||||
{
|
||||
RowData *data = _data;
|
||||
|
||||
row_data_unbind (data);
|
||||
|
||||
g_slice_free (RowData, data);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_widget (GtkListItem *list_item,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkWidget *box, *child;
|
||||
GFileInfo *info;
|
||||
GFile *file;
|
||||
guint depth;
|
||||
GIcon *icon;
|
||||
gpointer item;
|
||||
char *s;
|
||||
RowData *data;
|
||||
|
||||
item = gtk_list_item_get_item (list_item);
|
||||
data = g_slice_new0 (RowData);
|
||||
g_signal_connect (list_item, "notify::item", G_CALLBACK (row_data_notify_item), data);
|
||||
g_object_set_data_full (G_OBJECT (list_item), "row-data", data, row_data_free);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
|
||||
gtk_list_item_set_child (list_item, box);
|
||||
|
||||
child = gtk_label_new (NULL);
|
||||
gtk_label_set_width_chars (GTK_LABEL (child), 5);
|
||||
gtk_label_set_xalign (GTK_LABEL (child), 1.0);
|
||||
g_object_bind_property (list_item, "position", child, "label", G_BINDING_SYNC_CREATE);
|
||||
gtk_box_append (GTK_BOX (box), child);
|
||||
|
||||
depth = gtk_tree_list_row_get_depth (item);
|
||||
if (depth > 0)
|
||||
{
|
||||
child = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_widget_set_size_request (child, 16 * depth, 0);
|
||||
gtk_box_append (GTK_BOX (box), child);
|
||||
}
|
||||
data->depth_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_box_append (GTK_BOX (box), data->depth_box);
|
||||
|
||||
if (gtk_tree_list_row_is_expandable (item))
|
||||
{
|
||||
GtkWidget *arrow;
|
||||
data->expander = g_object_new (GTK_TYPE_TOGGLE_BUTTON, "css-name", "expander-widget", NULL);
|
||||
gtk_button_set_has_frame (GTK_BUTTON (data->expander), FALSE);
|
||||
gtk_box_append (GTK_BOX (box), data->expander);
|
||||
child = g_object_new (GTK_TYPE_SPINNER, "css-name", "expander", NULL);
|
||||
g_object_bind_property (data->expander, "active", child, "spinning", G_BINDING_SYNC_CREATE);
|
||||
gtk_button_set_child (GTK_BUTTON (data->expander), child);
|
||||
|
||||
child = g_object_new (GTK_TYPE_TOGGLE_BUTTON, "css-name", "expander-widget", NULL);
|
||||
gtk_button_set_has_frame (GTK_BUTTON (child), FALSE);
|
||||
g_object_bind_property (item, "expanded", child, "active", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
||||
g_object_set_data_full (G_OBJECT (child), "make-sure-its-not-unreffed", g_object_ref (item), g_object_unref);
|
||||
data->icon = gtk_image_new ();
|
||||
gtk_box_append (GTK_BOX (box), data->icon);
|
||||
|
||||
arrow = g_object_new (GTK_TYPE_SPINNER, "css-name", "expander", NULL);
|
||||
g_object_bind_property (item, "expanded", arrow, "spinning", G_BINDING_SYNC_CREATE);
|
||||
gtk_button_set_child (GTK_BUTTON (child), arrow);
|
||||
}
|
||||
else
|
||||
{
|
||||
child = gtk_image_new (); /* empty whatever */
|
||||
}
|
||||
gtk_box_append (GTK_BOX (box), child);
|
||||
|
||||
info = gtk_tree_list_row_get_item (item);
|
||||
|
||||
icon = g_file_info_get_icon (info);
|
||||
if (icon)
|
||||
{
|
||||
child = gtk_image_new_from_gicon (icon);
|
||||
gtk_box_append (GTK_BOX (box), child);
|
||||
}
|
||||
|
||||
file = g_object_get_data (G_OBJECT (info), "file");
|
||||
s = g_file_get_basename (file);
|
||||
child = gtk_label_new (s);
|
||||
g_free (s);
|
||||
g_object_unref (info);
|
||||
|
||||
gtk_box_append (GTK_BOX (box), child);
|
||||
data->name = gtk_label_new (NULL);
|
||||
gtk_box_append (GTK_BOX (box), data->name);
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
@ -305,8 +350,8 @@ main (int argc, char *argv[])
|
||||
|
||||
listview = gtk_list_view_new ();
|
||||
gtk_list_view_set_functions (GTK_LIST_VIEW (listview),
|
||||
setup_widget,
|
||||
NULL,
|
||||
bind_widget,
|
||||
NULL, NULL);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), listview);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user