using Gtk;
public class RatingWidget : DrawingArea {
- private int rating;
+ private int _rating;
private bool button_pressed;
private Gdk.Color active_color;
private Gdk.Color disabled_color;
+ public int rating {
+ get {
+ return _rating;
+ }
+ set {
+ if (_rating == value)
+ return;
+
+ _rating = value;
+
+ unowned Gdk.Region region = this.window.get_clip_region ();
+ // redraw the cairo canvas completely by exposing it
+ this.window.invalidate_region (region, true);
+ this.window.process_updates (true);
+ }
+ }
+
public RatingWidget () {
var style = Gtk.rc_get_style_by_paths (this.get_settings (), "GtkButton", null, typeof (Gtk.Button));
if (!style.lookup_color ("ActiveTextColor", out active_color))
public override bool expose_event (Gdk.EventExpose event) {
var cr = Gdk.cairo_create (this.window);
+ var radius = double.min (this.allocation.width / 20,
+ this.allocation.height / 2);
cr.rectangle (event.area.x, event.area.y, event.area.width, event.area.height);
cr.clip ();
- for (int i = 0; i < 10; i++) {
- draw_star (cr, i, (i >= rating) ? disabled_color : active_color);
- }
+ cr.save ();
+ cr.rectangle (radius * rating / 5.0, 0, this.allocation.width - radius * rating / 5.0, this.allocation.height);
+ cr.clip ();
+ for (int i = rating/10; i < 10; i++)
+ draw_star (cr, i, radius, disabled_color);
+ cr.restore ();
+
+ cr.new_path ();
+ cr.rectangle (0, 0, radius * rating / 5.0, this.allocation.height);
+ cr.clip ();
+ for (int i = 0; i < (rating+5)/10; i++)
+ draw_star (cr, i, radius, active_color);
return false;
}
- private void draw_star (Cairo.Context cr, int n, Gdk.Color color) {
- var radius = double.min (this.allocation.width / 20,
- this.allocation.height / 2);
+ private void draw_star (Cairo.Context cr, int n, double radius, Gdk.Color color) {
var x = radius * (2 * n + 1);
var y = this.allocation.height / 2;
public override bool button_press_event (Gdk.EventButton event) {
button_pressed = true;
- rate (10 * event.x / this.allocation.width);
+ rate (event.x);
return false;
}
public override bool motion_notify_event (Gdk.EventMotion event) {
if (button_pressed)
- rate (10 * event.x / this.allocation.width);
+ rate (event.x);
return false;
}
- private void rate (double r) {
- if (r <= 0)
- rating = 0;
- else
- rating = (int) r + 1;
- if (rating > 10)
- rating = 10;
-
- unowned Gdk.Region region = this.window.get_clip_region ();
- // redraw the cairo canvas completely by exposing it
- this.window.invalidate_region (region, true);
- this.window.process_updates (true);
- }
-
- public int get_rating () {
- return rating;
+ private void rate (double x) {
+ int r;
+
+ x = 10 * x / this.allocation.width;
+ if (x <= 0) {
+ r = 0;
+ } else {
+ int star = (int) x;
+ r = 10 * (star + 1);
+ x -= star;
+ if (x <= 0.333)
+ r -= 5;
+ if (r > 100)
+ r = 100;
+ }
+ rating = r;
}
}