*ThorwilKnob: KnobRim done
[libprolooks.git] / prolooks / VuMeter.vala
blob4ee2743122bd12a1122f7f999c42be1bbe4c20c7
1 /*
2 Copyright 2009 by Hans Baier, Krzysztof Foltman
3 License: LGPLv2+
4 */
6 using Gtk;
8 namespace Prolooks {
10 public class VuMeter : DrawingArea {
12 public enum Mode {
13 STANDARD,
14 MONOCHROME,
15 MONOCHROME_REVERSE
18 private Cairo.Surface? cache_surface = null;
19 private Mode _mode = Mode.STANDARD; private double _value = 0.5;
22 [Description(blurb="the displayed value, ranging from 0.0 to 1.0")]
23 public double value {
24 set {
25 if (Math.fabs(_value - value) >= 0.0001)
26 queue_draw();
27 _value = value;
29 get {
30 return _value;
34 private double r = 1;
35 private double g = 1;
36 private double b = 0;
38 [Description(nick="monochrome color", blurb="sets the meter color in monochrome color mode, can contain a string as accepted by gdk_color_parse (), eg: #a0b1c2")]
39 public string color {
40 set {
41 if (value != null & value != "") {
42 gdk_color_to_cairo_color (color_from_string (value), ref r, ref g, ref b);
43 cache_surface = null;
44 queue_draw ();
45 } else {
46 r = 1; g = 1; b = 0;
51 [Description(nick="mode", blurb="whether the vu meter should be red/yellow/green (standard), or one color (monochrome) or one color but flipped left to right (monochrome reversed)")]
52 public Mode mode {
53 set {
54 if (value != _mode) {
55 _mode = value;
56 cache_surface = null;
57 queue_draw();
60 get {
61 return _mode;
65 construct {
66 // Set favored widget size
67 set_size_request (100, 14);
70 public override void size_allocate (Gdk.Rectangle allocation) {
71 base.size_allocate (allocation);
72 cache_surface = null;
75 /* Widget is asked to draw itself */
76 public override bool expose_event (Gdk.EventExpose event) {
77 int ox = 1, oy = 1;
78 int sx = allocation.width - 2, sy = allocation.height - 2;
80 // Create a Cairo context
81 var cr = Gdk.cairo_create (this.window);
83 if (cache_surface == null)
85 int x;
86 // looks like its either first call or the widget has been resized.
87 // create the cache_surface.
88 cache_surface = new Cairo.Surface.similar (cr.get_target(),
89 Cairo.Content.COLOR,
90 allocation.width,
91 allocation.height );
93 // And render the meterstuff again.
95 Cairo.Context cache_cr = new Cairo.Context ( cache_surface );
96 cache_cr.set_source_rgba (0, 0, 0, 0);
97 cache_cr.rectangle (ox, oy, sx, sy);
98 cache_cr.fill ();
99 cache_cr.set_line_width (1);
101 for (x = ox; x <= ox + sx; x += 3)
103 double ts = (x - ox) * 1.0 / sx;
104 switch(mode)
106 case Mode.STANDARD:
107 default:
108 if (ts < 0.75) {
109 r = ts / 0.75;
110 g = 1;
111 b = 0;
113 else {
114 r = 1;
115 g = 1 - (ts - 0.75) / 0.25;
116 b = 0;
118 break;
119 case Mode.MONOCHROME_REVERSE:
120 break;
121 case Mode.MONOCHROME:
122 break;
124 cache_cr.set_source_rgb(r, g, b);
125 cache_cr.move_to (x, oy);
126 cache_cr.line_to (x, oy + sy + 1);
127 cache_cr.move_to (x, oy + sy);
128 cache_cr.line_to (x, oy );
129 cache_cr.stroke ();
133 // Set clipping area in order to avoid unnecessary drawing
134 cr.rectangle (event.area.x, event.area.y,
135 event.area.width, event.area.height);
136 cr.clip ();
138 cr.set_source_surface (cache_surface, 0, 0);
139 cr.paint ();
140 cr.set_source_rgba (0, 0, 0, 0.5);
142 if( mode == Mode.MONOCHROME_REVERSE )
143 cr.rectangle (ox, oy, _value * (sx - ox) + 1, sy - oy + 1);
144 else
145 cr.rectangle (ox + _value * (sx - ox), oy, sx - ox + 1, sy - oy + 1);
147 cr.fill ();
149 return false;
153 } // namespace Prolooks