[gnome-software/1205-reviews-ratings-are-rounded-to-integer-stars: 78/79] 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: 78/79] Reviews: Ratings are rounded to integer stars
- Date: Tue, 22 Jun 2021 06:39:32 +0000 (UTC)
commit 69df42088fc8c327fbdd8fa8d244f684e3fa99f8
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 | 238 +++++++++++++++++++++++++++++++++++++++++++++++++
src/gs-star-image.h | 22 +++++
src/gs-star-widget.c | 34 +++----
src/gtk-style-hc.css | 9 +-
src/gtk-style.css | 8 +-
src/meson.build | 1 +
7 files changed, 288 insertions(+), 25 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..3b61c79a7
--- /dev/null
+++ b/src/gs-star-image.c
@@ -0,0 +1,238 @@
+/* -*- 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+
+ */
+
+/**
+ * SECTION:gs-star-image
+ * @title: GsStarImage
+ * @stability: Unstable
+ * @short_description: Draw a star image, which can be partially filled
+ *
+ * Depending on the #GsStarImage:fraction property, the star image can be
+ * drawn as filled only partially or fully or not at all. This is accomplished
+ * by using a `color` style property for the filled part and a
+ * `star-bg` style property for the unfilled part of the star.
+ * The `background` style property controls the area outside the star.
+ *
+ * Since: 41
+ */
+
+#include "config.h"
+
+#include "gs-star-image.h"
+
+struct _GsStarImage
+{
+ GtkWidget parent_instance;
+
+ gdouble fraction;
+};
+
+G_DEFINE_TYPE (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,
+ gint *out_min_x,
+ gint *out_max_x)
+{
+ /* Coordinates of the vertices of the star,
+ * where (0, 0) is the centre of the star.
+ * These range from -1 to +1 in both dimensions,
+ * and will be scaled to @radius when drawn. */
+ const struct _points {
+ gdouble x, y;
+ } points[] = {
+ { 0.000000, -1.000000 },
+ { -1.000035, -0.424931 },
+ { -0.668055, 0.850680 },
+ { 0.668055, 0.850680 },
+ { 1.000035, -0.424931 }
+ };
+ gint ii, nn = G_N_ELEMENTS (points), xx, yy;
+
+ if (radius <= 0)
+ return;
+
+ cairo_translate (cr, radius, radius);
+
+ xx = points[0].x * radius;
+ yy = points[0].y * radius;
+
+ if (out_min_x)
+ *out_min_x = xx;
+
+ if (out_max_x)
+ *out_max_x = xx;
+
+ cairo_move_to (cr, xx, yy);
+
+ for (ii = 2; ii <= 2 * nn; ii += 2) {
+ xx = points[ii % nn].x * radius;
+ yy = points[ii % nn].y * radius;
+
+ if (out_min_x && *out_min_x > xx)
+ *out_min_x = xx;
+
+ if (out_max_x && *out_max_x < xx)
+ *out_max_x = xx;
+
+ cairo_line_to (cr, xx, yy);
+ }
+}
+
+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 *star_bg = NULL;
+ GdkRGBA star_fg;
+ gint min_x = -radius, max_x = radius;
+
+ gtk_widget_style_get (widget,
+ "star-bg", &star_bg,
+ NULL);
+
+ style_context = gtk_widget_get_style_context (widget);
+ gtk_style_context_get_color (style_context,
+ gtk_style_context_get_state (style_context),
+ &star_fg);
+
+ cairo_save (cr);
+ gs_star_image_outline_star (cr, allocation.x, allocation.y, radius, &min_x, &max_x);
+ cairo_clip (cr);
+ if (star_bg)
+ gdk_cairo_set_source_rgba (cr, star_bg);
+ else
+ cairo_set_source_rgb (cr, 0xde / 255.0, 0xdd / 255.0, 0xda / 255.0);
+ cairo_rectangle (cr, -radius, -radius, 2 * radius, 2 * radius);
+ cairo_fill (cr);
+
+ gdk_cairo_set_source_rgba (cr, &star_fg);
+ cairo_rectangle (cr, min_x, -radius, (max_x - min_x) * fraction, 2 * radius);
+ cairo_fill (cr);
+ cairo_restore (cr);
+
+ g_clear_pointer (&star_bg, gdk_rgba_free);
+ }
+
+ 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));
+
+ gtk_widget_class_install_style_property (widget_class,
+ g_param_spec_boxed ("star-bg", NULL, NULL,
+ GDK_TYPE_RGBA,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ gtk_widget_class_set_css_name (widget_class, "star-image");
+}
+
+static void
+gs_star_image_init (GsStarImage *self)
+{
+ self->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->fraction == fraction)
+ return;
+
+ self->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->fraction;
+}
diff --git a/src/gs-star-image.h b/src/gs-star-image.h
new file mode 100644
index 000000000..f1f99fea0
--- /dev/null
+++ b/src/gs-star-image.h
@@ -0,0 +1,22 @@
+/* -*- 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 ())
+
+G_DECLARE_FINAL_TYPE (GsStarImage, gs_star_image, GS, STAR_IMAGE, GtkWidget)
+
+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..60747dfe7 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,10 @@ 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);
+
+ priv->images[i] = im;
/* create button */
if (priv->interactive) {
@@ -274,7 +278,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/gtk-style-hc.css b/src/gtk-style-hc.css
index 0f24dbee4..4dabb2c4a 100644
--- a/src/gtk-style-hc.css
+++ b/src/gtk-style-hc.css
@@ -210,18 +210,15 @@ button.star, .button.star {
outline-offset: -1px;
}
-/* for the review dialog */
-.star-enabled {
+star-image {
color: #000000;
+ -GsStarImage-star-bg: #777777;
}
+
.star-disabled {
color: #777777;
}
-/* for the app details shell */
-.star-enabled:disabled {
- color: #000000;
-}
.star-disabled:disabled {
color: #777777;
}
diff --git a/src/gtk-style.css b/src/gtk-style.css
index 4b18fe4a7..5e6d635bd 100644
--- a/src/gtk-style.css
+++ b/src/gtk-style.css
@@ -478,11 +478,11 @@ flowboxchild {
padding: 0px;
}
-/* for the review dialog */
-.star-enabled,
-.star-enabled:disabled {
- color: shade(@theme_fg_color, 0.8);
+star-image {
+ color: #e5a50a;
+ -GsStarImage-star-bg: #deddda;
}
+
.star-disabled,
.star-disabled:disabled {
color: @unfocused_insensitive_color;
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]