Commit 100e7bf2 authored by Philip Withnall's avatar Philip Withnall

gs-star-widget: Split out rating refresh from other refresh

It’s quite expensive to destroy and recreate all the child widgets of a
`GsStarRating` every time its rating is changed. In particular, doing so
means re-loading the `starred-symbolic` image a lot.

Avoid that by separating refreshing the `rating` property from
refreshing everything else.

This avoids around 115KB of object allocations through refreshes.
Signed-off-by: Philip Withnall's avatarPhilip Withnall <withnall@endlessm.com>
parent e76567c3
Pipeline #184590 passed with stage
in 2 minutes and 54 seconds
...@@ -19,6 +19,7 @@ typedef struct ...@@ -19,6 +19,7 @@ typedef struct
gint rating; gint rating;
guint icon_size; guint icon_size;
GtkWidget *box1; GtkWidget *box1;
GtkImage *images[5];
} GsStarWidgetPrivate; } GsStarWidgetPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (GsStarWidget, gs_star_widget, GTK_TYPE_BIN) G_DEFINE_TYPE_WITH_PRIVATE (GsStarWidget, gs_star_widget, GTK_TYPE_BIN)
...@@ -37,6 +38,8 @@ enum { ...@@ -37,6 +38,8 @@ enum {
static GParamSpec *properties[PROP_RATING + 1] = { 0, }; static GParamSpec *properties[PROP_RATING + 1] = { 0, };
static guint signals [SIGNAL_LAST] = { 0 }; static guint signals [SIGNAL_LAST] = { 0 };
const gint rate_to_star[] = {20, 40, 60, 80, 100, -1};
static void gs_star_widget_refresh (GsStarWidget *star); static void gs_star_widget_refresh (GsStarWidget *star);
gint gint
...@@ -79,11 +82,33 @@ gs_star_widget_button_clicked_cb (GtkButton *button, GsStarWidget *star) ...@@ -79,11 +82,33 @@ gs_star_widget_button_clicked_cb (GtkButton *button, GsStarWidget *star)
g_signal_emit (star, signals[RATING_CHANGED], 0, priv->rating); g_signal_emit (star, signals[RATING_CHANGED], 0, priv->rating);
} }
/* Update the star styles to display the new rating */
static void
gs_star_widget_refresh_rating (GsStarWidget *star)
{
GsStarWidgetPrivate *priv = gs_star_widget_get_instance_private (star);
if (!gtk_widget_get_realized (GTK_WIDGET (star)))
return;
for (guint i = 0; i < G_N_ELEMENTS (priv->images); i++) {
GtkWidget *im = GTK_WIDGET (priv->images[i]);
gboolean enabled;
/* add fudge factor so we can actually get 5 stars in reality */
enabled = priv->rating >= rate_to_star[i] - 10;
gtk_style_context_add_class (gtk_widget_get_style_context (im),
enabled ? "star-enabled" : "star-disabled");
gtk_style_context_remove_class (gtk_widget_get_style_context (im),
enabled ? "star-disabled" : "star-enabled");
}
}
static void static void
gs_star_widget_refresh (GsStarWidget *star) gs_star_widget_refresh (GsStarWidget *star)
{ {
GsStarWidgetPrivate *priv = gs_star_widget_get_instance_private (star); GsStarWidgetPrivate *priv = gs_star_widget_get_instance_private (star);
const gint rate_to_star[] = {20, 40, 60, 80, 100, -1};
if (!gtk_widget_get_realized (GTK_WIDGET (star))) if (!gtk_widget_get_realized (GTK_WIDGET (star)))
return; return;
...@@ -91,7 +116,7 @@ gs_star_widget_refresh (GsStarWidget *star) ...@@ -91,7 +116,7 @@ gs_star_widget_refresh (GsStarWidget *star)
/* remove all existing widgets */ /* remove all existing widgets */
gs_container_remove_all (GTK_CONTAINER (priv->box1)); gs_container_remove_all (GTK_CONTAINER (priv->box1));
for (guint i = 0; i < 5; i++) { for (guint i = 0; i < G_N_ELEMENTS (priv->images); i++) {
GtkWidget *w; GtkWidget *w;
GtkWidget *im; GtkWidget *im;
...@@ -99,6 +124,7 @@ gs_star_widget_refresh (GsStarWidget *star) ...@@ -99,6 +124,7 @@ gs_star_widget_refresh (GsStarWidget *star)
im = gtk_image_new_from_icon_name ("starred-symbolic", im = gtk_image_new_from_icon_name ("starred-symbolic",
GTK_ICON_SIZE_DIALOG); GTK_ICON_SIZE_DIALOG);
gtk_image_set_pixel_size (GTK_IMAGE (im), (gint) priv->icon_size); gtk_image_set_pixel_size (GTK_IMAGE (im), (gint) priv->icon_size);
priv->images[i] = GTK_IMAGE (im);
/* create button */ /* create button */
if (priv->interactive) { if (priv->interactive) {
...@@ -115,13 +141,11 @@ gs_star_widget_refresh (GsStarWidget *star) ...@@ -115,13 +141,11 @@ gs_star_widget_refresh (GsStarWidget *star)
} }
gtk_widget_set_sensitive (w, priv->interactive); gtk_widget_set_sensitive (w, priv->interactive);
gtk_style_context_add_class (gtk_widget_get_style_context (w), "star"); gtk_style_context_add_class (gtk_widget_get_style_context (w), "star");
/* add fudge factor so we can actually get 5 stars in reality */
gtk_style_context_add_class (gtk_widget_get_style_context (im),
priv->rating >= rate_to_star[i] - 10 ?
"star-enabled" : "star-disabled");
gtk_widget_set_visible (w, TRUE); gtk_widget_set_visible (w, TRUE);
gtk_container_add (GTK_CONTAINER (priv->box1), w); gtk_container_add (GTK_CONTAINER (priv->box1), w);
} }
gs_star_widget_refresh_rating (star);
} }
void void
...@@ -152,7 +176,7 @@ gs_star_widget_set_rating (GsStarWidget *star, ...@@ -152,7 +176,7 @@ gs_star_widget_set_rating (GsStarWidget *star,
priv->rating = rating; priv->rating = rating;
g_object_notify_by_pspec (G_OBJECT (star), properties[PROP_RATING]); g_object_notify_by_pspec (G_OBJECT (star), properties[PROP_RATING]);
gs_star_widget_refresh (star); gs_star_widget_refresh_rating (star);
} }
static void static void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment