* podcast/rb-podcast-manager.c: (rb_podcast_manager_add_post): add
[rhythmbox.git] / widgets / rb-rating.c
blobf956f0c9ff745affa23deefc7cd6655d6a6f96f0
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3 * arch-tag: Implementation of rating renderer object
5 * Copyright (C) 2002 Olivier Martin <oleevye@wanadoo.fr>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "config.h"
25 #include <string.h>
26 #include <gtk/gtk.h>
28 #include "rb-rating.h"
29 #include "rb-rating-helper.h"
30 #include "rb-stock-icons.h"
31 #include "rb-cut-and-paste-code.h"
33 /* Offset at the beggining of the widget */
34 #define X_OFFSET 0
36 /* Vertical offset */
37 #define Y_OFFSET 2
39 /* Number of stars */
40 #define MAX_SCORE 5
42 #define COLOR_OFFSET 120
44 static void rb_rating_class_init (RBRatingClass *class);
45 static void rb_rating_init (RBRating *label);
46 static void rb_rating_finalize (GObject *object);
47 static void rb_rating_get_property (GObject *object,
48 guint param_id,
49 GValue *value,
50 GParamSpec *pspec);
51 static void rb_rating_set_property (GObject *object,
52 guint param_id,
53 const GValue *value,
54 GParamSpec *pspec);
55 static void rb_rating_size_request (GtkWidget *widget,
56 GtkRequisition *requisition);
57 static gboolean rb_rating_expose (GtkWidget *widget,
58 GdkEventExpose *event);
59 static gboolean rb_rating_button_press_cb (GtkWidget *widget,
60 GdkEventButton *event,
61 RBRating *rating);
63 struct RBRatingPrivate
65 double rating;
66 RBRatingPixbufs *pixbufs;
69 G_DEFINE_TYPE (RBRating, rb_rating, GTK_TYPE_EVENT_BOX)
70 #define RB_RATING_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_RATING, RBRatingPrivate))
72 enum
74 PROP_0,
75 PROP_RATING
78 enum
80 RATED,
81 LAST_SIGNAL
84 static guint rb_rating_signals[LAST_SIGNAL] = { 0 };
86 static void
87 rb_rating_class_init (RBRatingClass *klass)
89 GObjectClass *object_class = G_OBJECT_CLASS (klass);
90 GtkWidgetClass *widget_class;
92 widget_class = (GtkWidgetClass*) klass;
94 object_class->finalize = rb_rating_finalize;
95 object_class->get_property = rb_rating_get_property;
96 object_class->set_property = rb_rating_set_property;
98 widget_class->expose_event = rb_rating_expose;
99 widget_class->size_request = rb_rating_size_request;
101 rb_rating_install_rating_property (object_class, PROP_RATING);
103 rb_rating_signals[RATED] =
104 g_signal_new ("rated",
105 G_OBJECT_CLASS_TYPE (object_class),
106 G_SIGNAL_RUN_LAST,
107 G_STRUCT_OFFSET (RBRatingClass, rated),
108 NULL, NULL,
109 g_cclosure_marshal_VOID__DOUBLE,
110 G_TYPE_NONE,
112 G_TYPE_DOUBLE);
114 g_type_class_add_private (klass, sizeof (RBRatingPrivate));
117 static void
118 rb_rating_init (RBRating *rating)
120 rating->priv = RB_RATING_GET_PRIVATE (rating);
122 /* create the needed icons */
123 rating->priv->pixbufs = rb_rating_pixbufs_new ();
125 /* register some signals */
126 g_signal_connect_object (G_OBJECT (rating),
127 "button_press_event",
128 G_CALLBACK (rb_rating_button_press_cb),
129 rating, 0);
132 static void
133 rb_rating_finalize (GObject *object)
135 RBRating *rating;
137 rating = RB_RATING (object);
139 if (rating->priv->pixbufs != NULL) {
140 rb_rating_pixbufs_free (rating->priv->pixbufs);
143 G_OBJECT_CLASS (rb_rating_parent_class)->finalize (object);
146 static void
147 rb_rating_get_property (GObject *object,
148 guint param_id,
149 GValue *value,
150 GParamSpec *pspec)
152 RBRating *rating = RB_RATING (object);
154 switch (param_id) {
155 case PROP_RATING:
156 g_value_set_double (value, rating->priv->rating);
157 break;
158 default:
159 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
160 break;
164 static void
165 rb_rating_set_property (GObject *object,
166 guint param_id,
167 const GValue *value,
168 GParamSpec *pspec)
170 RBRating *rating= RB_RATING (object);
172 switch (param_id) {
173 case PROP_RATING:
174 rating->priv->rating = g_value_get_double (value);
175 gtk_widget_queue_draw (GTK_WIDGET (rating));
176 break;
177 default:
178 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
179 break;
183 RBRating *
184 rb_rating_new ()
186 RBRating *rating;
188 rating = g_object_new (RB_TYPE_RATING, NULL, NULL);
190 g_return_val_if_fail (rating->priv != NULL, NULL);
192 return rating;
195 static void
196 rb_rating_size_request (GtkWidget *widget,
197 GtkRequisition *requisition)
199 int icon_size;
201 g_return_if_fail (requisition != NULL);
203 gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_size, NULL);
205 requisition->width = RB_RATING_MAX_SCORE * icon_size + X_OFFSET;
206 requisition->height = icon_size + Y_OFFSET * 2;
209 static gboolean
210 rb_rating_expose (GtkWidget *widget,
211 GdkEventExpose *event)
213 int icon_size;
214 gboolean ret;
216 g_return_val_if_fail (RB_IS_RATING (widget), FALSE);
218 gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_size, NULL);
220 ret = FALSE;
222 if (GTK_WIDGET_DRAWABLE (widget) == TRUE) {
223 RBRating *rating = RB_RATING (widget);
225 /* make the widget prettier */
226 gtk_paint_flat_box (widget->style, widget->window,
227 GTK_STATE_NORMAL, GTK_SHADOW_IN,
228 NULL, widget, "entry_bg", 0, 0,
229 widget->allocation.width,
230 widget->allocation.height);
232 gtk_paint_shadow (widget->style, widget->window,
233 GTK_STATE_NORMAL, GTK_SHADOW_IN,
234 NULL, widget, "text", 0, 0,
235 widget->allocation.width,
236 widget->allocation.height);
238 /* draw the stars */
239 if (rating->priv->pixbufs != NULL) {
240 ret = rb_rating_render_stars (widget,
241 widget->window,
242 rating->priv->pixbufs,
243 0, 0,
244 X_OFFSET, Y_OFFSET,
245 rating->priv->rating,
246 FALSE);
250 return ret;
253 static gboolean
254 rb_rating_button_press_cb (GtkWidget *widget,
255 GdkEventButton *event,
256 RBRating *rating)
258 int mouse_x, mouse_y;
259 double new_rating;
261 g_return_val_if_fail (widget != NULL, FALSE);
262 g_return_val_if_fail (RB_IS_RATING (rating), FALSE);
264 gtk_widget_get_pointer (widget, &mouse_x, &mouse_y);
266 new_rating = rb_rating_get_rating_from_widget (widget, mouse_x,
267 widget->allocation.width,
268 rating->priv->rating);
270 if (new_rating == -1.0) {
271 return FALSE;
272 } else {
273 g_signal_emit (G_OBJECT (rating),
274 rb_rating_signals[RATED],
275 0, new_rating);
276 return TRUE;