[gnome-software/1205-reviews-ratings-are-rounded-to-integer-stars: 32/34] Reviews: Ratings are rounded to integer stars
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software/1205-reviews-ratings-are-rounded-to-integer-stars: 32/34] Reviews: Ratings are rounded to integer stars
- Date: Tue, 1 Jun 2021 20:04:51 +0000 (UTC)
commit 02f17af1cbc880866a6cc5bd87d9a1ecc273a334
Author: Milan Crha <mcrha redhat com>
Date: Tue May 25 12:29:42 2021 +0200
Reviews: Ratings are rounded to integer stars
Introduce and use a new GsStarImage widget, which can show partial ratings.
Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/1205
src/gs-details-page.ui | 1 +
src/gs-star-image.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++
src/gs-star-image.h | 37 ++++++++++
src/gs-star-widget.c | 35 +++++----
src/meson.build | 1 +
5 files changed, 250 insertions(+), 15 deletions(-)
---
diff --git a/src/gs-details-page.ui b/src/gs-details-page.ui
index bafb11d15..b30ea9f04 100644
--- a/src/gs-details-page.ui
+++ b/src/gs-details-page.ui
@@ -144,6 +144,7 @@
<property name="visible">True</property>
<property name="halign">start</property>
<property name="valign">center</property>
+ <property name="icon-size">16</property>
</object>
</child>
</object>
diff --git a/src/gs-star-image.c b/src/gs-star-image.c
new file mode 100644
index 000000000..05a66fb99
--- /dev/null
+++ b/src/gs-star-image.c
@@ -0,0 +1,191 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "config.h"
+
+#include "gs-star-image.h"
+
+struct _GsStarImagePrivate {
+ gdouble fraction;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GsStarImage, gs_star_image, GTK_TYPE_WIDGET)
+
+enum {
+ PROP_FRACTION = 1
+};
+
+static void
+gs_star_image_outline_star (cairo_t *cr,
+ gint x,
+ gint y,
+ gint radius)
+{
+ const struct _points {
+ gdouble x, y;
+ } points[] = {
+ { 0.000000, -1.000000 },
+ { -0.224513, -0.309017 },
+ { -0.951057, -0.309017 },
+ { -0.363271, 0.118034 },
+ { -0.587785, 0.809017 },
+ { 0.0, 0.381966 },
+ { 0.587785, 0.809017 },
+ { 0.363271, 0.118034 },
+ { 0.951057, -0.309017 },
+ { 0.224513, -0.309017 }
+ };
+ gint ii, nn = G_N_ELEMENTS (points);
+
+ if (radius <= 0)
+ return;
+
+ cairo_translate (cr, radius, radius);
+ cairo_move_to (cr, points[0].x * radius, points[0].y * radius);
+
+ for (ii = 1; ii <= nn; ii++) {
+ cairo_line_to (cr, points[ii % nn].x * radius, points[ii % nn].y * radius);
+ }
+}
+
+static void
+gs_star_image_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (param_id) {
+ case PROP_FRACTION:
+ g_value_set_double (value, gs_star_image_get_fraction (GS_STAR_IMAGE (object)));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+gs_star_image_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (param_id) {
+ case PROP_FRACTION:
+ gs_star_image_set_fraction (GS_STAR_IMAGE (object), g_value_get_double (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static gboolean
+gs_star_image_draw (GtkWidget *widget,
+ cairo_t *cr)
+{
+ GtkAllocation allocation;
+ gdouble fraction;
+ gint radius;
+
+ fraction = gs_star_image_get_fraction (GS_STAR_IMAGE (widget));
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ radius = MIN (allocation.width, allocation.height) / 2;
+
+ if (radius > 0) {
+ GtkStyleContext *style_context;
+ GdkRGBA rgba;
+
+ style_context = gtk_widget_get_style_context (widget);
+ gtk_style_context_get_color (style_context,
+ gtk_style_context_get_state (style_context),
+ &rgba);
+
+ cairo_save (cr);
+ gdk_cairo_set_source_rgba (cr, &rgba);
+
+ cairo_save (cr);
+ gs_star_image_outline_star (cr, allocation.x, allocation.y, radius);
+ cairo_clip (cr);
+ cairo_rectangle (cr, -radius, -radius, 2 * radius * fraction, 2 * radius);
+ cairo_fill (cr);
+ cairo_restore (cr);
+
+ cairo_save (cr);
+ gs_star_image_outline_star (cr, allocation.x, allocation.y, radius);
+ cairo_set_antialias (cr, CAIRO_ANTIALIAS_SUBPIXEL);
+ cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke (cr);
+ cairo_restore (cr);
+
+ cairo_restore (cr);
+ }
+
+ return FALSE;
+}
+
+static void
+gs_star_image_class_init (GsStarImageClass *klass)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->get_property = gs_star_image_get_property;
+ object_class->set_property = gs_star_image_set_property;
+
+ widget_class = GTK_WIDGET_CLASS (klass);
+ widget_class->draw = gs_star_image_draw;
+
+ g_object_class_install_property (object_class,
+ PROP_FRACTION,
+ g_param_spec_double ("fraction", NULL, NULL,
+ 0.0, 1.0, 1.0,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
+}
+
+static void
+gs_star_image_init (GsStarImage *self)
+{
+ self->priv = gs_star_image_get_instance_private (self);
+ self->priv->fraction = 1.0;
+
+ gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
+ gtk_widget_set_size_request (GTK_WIDGET (self), 16, 16);
+}
+
+GtkWidget *
+gs_star_image_new (void)
+{
+ return g_object_new (GS_TYPE_STAR_IMAGE, NULL);
+}
+
+void
+gs_star_image_set_fraction (GsStarImage *self,
+ gdouble fraction)
+{
+ g_return_if_fail (GS_IS_STAR_IMAGE (self));
+
+ if (self->priv->fraction == fraction)
+ return;
+
+ self->priv->fraction = fraction;
+
+ g_object_notify (G_OBJECT (self), "fraction");
+
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+gdouble
+gs_star_image_get_fraction (GsStarImage *self)
+{
+ g_return_val_if_fail (GS_IS_STAR_IMAGE (self), -1.0);
+
+ return self->priv->fraction;
+}
diff --git a/src/gs-star-image.h b/src/gs-star-image.h
new file mode 100644
index 000000000..b3c6d04a5
--- /dev/null
+++ b/src/gs-star-image.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GS_TYPE_STAR_IMAGE (gs_star_image_get_type ())
+#define GS_STAR_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GS_TYPE_STAR_IMAGE, GsStarImage))
+#define GS_STAR_IMAGE_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GS_TYPE_STAR_IMAGE,
GsStarImageClass))
+#define GS_IS_STAR_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GS_TYPE_STAR_IMAGE))
+#define GS_IS_STAR_IMAGE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), GS_TYPE_STAR_IMAGE))
+#define GS_STAR_IMAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GS_TYPE_STAR_IMAGE,
GsStarImageClass))
+
+typedef struct _GsStarImagePrivate GsStarImagePrivate;
+
+typedef struct _GsStarImageClass {
+ GtkWidgetClass parent_class;
+} GsStarImageClass;
+
+typedef struct _GsStarImage {
+ GtkWidget parent;
+ GsStarImagePrivate *priv;
+} GsStarImage;
+
+GType gs_star_image_get_type (void) G_GNUC_CONST;
+GtkWidget * gs_star_image_new (void);
+void gs_star_image_set_fraction (GsStarImage *self,
+ gdouble fraction);
+gdouble gs_star_image_get_fraction (GsStarImage *self);
+
+G_END_DECLS
diff --git a/src/gs-star-widget.c b/src/gs-star-widget.c
index 4485af12f..560c40e19 100644
--- a/src/gs-star-widget.c
+++ b/src/gs-star-widget.c
@@ -12,6 +12,7 @@
#include <math.h>
#include "gs-common.h"
+#include "gs-star-image.h"
#include "gs-star-widget.h"
typedef struct
@@ -20,7 +21,7 @@ typedef struct
gint rating;
guint icon_size;
GtkWidget *box1;
- GtkImage *images[5];
+ GtkWidget *images[5];
} GsStarWidgetPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (GsStarWidget, gs_star_widget, GTK_TYPE_BIN)
@@ -94,15 +95,18 @@ gs_star_widget_refresh_rating (GsStarWidget *star)
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");
+ gdouble fraction;
+
+ if (priv->rating >= rate_to_star[i])
+ fraction = 1.0;
+ else if (!i)
+ fraction = priv->rating / 20.0;
+ else if (priv->rating > rate_to_star[i - 1])
+ fraction = (priv->rating - rate_to_star[i - 1]) / 20.0;
+ else
+ fraction = 0.0;
+
+ gs_star_image_set_fraction (GS_STAR_IMAGE (im), fraction);
}
}
@@ -122,10 +126,11 @@ gs_star_widget_refresh (GsStarWidget *star)
GtkWidget *im;
/* create image */
- im = gtk_image_new_from_icon_name ("starred-symbolic",
- GTK_ICON_SIZE_DIALOG);
- gtk_image_set_pixel_size (GTK_IMAGE (im), (gint) priv->icon_size);
- priv->images[i] = GTK_IMAGE (im);
+ im = gs_star_image_new ();
+ gtk_widget_set_size_request (im, (gint) priv->icon_size, (gint) priv->icon_size);
+ gtk_style_context_add_class (gtk_widget_get_style_context (im), "star-enabled");
+
+ priv->images[i] = im;
/* create button */
if (priv->interactive) {
@@ -274,7 +279,7 @@ gs_star_widget_class_init (GsStarWidgetClass *klass)
"Icon Size",
"Size of icons to use, in pixels",
0, G_MAXUINT, 12,
- G_PARAM_READWRITE);
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
/**
* GsStarWidget:interactive:
diff --git a/src/meson.build b/src/meson.build
index 430eb0c4b..1ffd665b4 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -63,6 +63,7 @@ gnome_software_sources = [
'gs-shell.c',
'gs-shell-search-provider.c',
'gs-sidebar.c',
+ 'gs-star-image.c',
'gs-star-widget.c',
'gs-summary-tile.c',
'gs-third-party-repo-row.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]