First working ThorwilKnob
[libprolooks.git] / prolooks / ThorwilKnobImageSource.vala
blobd05d015662e52e318a1c6258de4fff18beae2356
1 using Gtk;
2 using Cairo;
4 namespace Prolooks {
5 class ThorwilKnobImageSource : DrawingArea, IKnobImageSource {
6 public double knob_width { get; set; }
7 public double knob_height { get; set; }
8 public double x { get; set; }
9 public double y { get; set; }
10 public Gdk.Color lamp_color { get; set; }
11 public double scale_factor { get; set; default = 0.380952381; }
13 public double get_knob_width () {
14 return knob_width * scale_factor;
17 public double get_knob_height () {
18 return knob_height * scale_factor;
21 public double get_line_width () {
22 return 0.0;
25 public double get_radius () {
26 return knob_width * scale_factor / 2.0;
29 public string to_string () {
30 return "SimpleKnobImageSource: Dimens: (%f, %f); linewidth: %f; radius: %f; led-color: %s".printf (
31 get_knob_width (),
32 get_knob_height (),
33 get_line_width (),
34 get_radius (),
35 Prolooks.color_to_string(lamp_color));
39 construct {
40 knob_width = 105;
41 knob_height = 105;
42 x = knob_width / 2;
43 y = knob_height / 2;
44 set_size_request ((int)(phases * scale_factor * knob_width), (int) (scale_factor * knob_height));
45 lamp_color = color_from_string ("#ff7f00");
48 public override bool expose_event (Gdk.EventExpose event) {
49 var cr = Gdk.cairo_create (this.window);
50 // Set clipping area in order to avoid unnecessary drawing
51 Gdk.cairo_rectangle (cr, event.area);
52 cr.clip ();
54 cr.set_source_rgba(0.75, 0.75, 0.75, 0);
56 cr.rectangle(0, 0, phases * knob_width, 4 * knob_height);
57 cr.fill();
59 for (int variant = 0; variant < 1; variant++) {
60 // x/y = the middle of the knob
61 var x = knob_width / 2;
62 var y = knob_height * (variant + 0.5);
63 paint_knobs (cr, (KnobMode)variant, x, y);
66 //paint_knob (cr, KnobMode.POSITIVE, 30, 20, 50, x, y);
68 return true;
71 public void paint_knob (Cairo.Context cr, KnobMode knob_mode, int phase, double lwidth, double radius, double x, double y) {
72 var knob_rim_radius = 31.5;
74 var start_angle = 0.0;
75 var end_angle = 0.0;
76 var value_angle = 0.0;
78 // Draw out the triangle using absolute coordinates
79 var value = phase * 1.0 / (phases - 1);
81 if (knob_mode != KnobMode.ENDLESS) {
82 start_angle = (180 - 45) * Math.PI / 180;
83 end_angle = (360 + 45) * Math.PI / 180;
84 } else {
85 start_angle = (270) * Math.PI / 180;
86 end_angle = (270 + 360) * Math.PI / 180;
89 value_angle = start_angle + value * (end_angle - start_angle);
91 var cos_value = Math.cos(value_angle);
92 var sin_value = Math.sin(value_angle);
93 var cos_start_angle = Math.cos(start_angle);
94 var sin_start_angle = Math.sin(start_angle);
95 var cos_end_angle = Math.cos(end_angle);
96 var sin_end_angle = Math.sin(end_angle);
98 cr.save ();
99 x /= scale_factor;
100 y += knob_height / 3.0;
101 cr.scale (scale_factor, scale_factor);
103 // KnobRim
104 cr.set_source (create_gradient_str (32, 16, 75, 16, "#d4c8b9", "#ae977b"));
105 cr.set_line_width (2.0);
106 cr.arc (x, y, 31.5, 0.0, 2 * Math.PI);
107 cr.stroke ();
109 var progress_width = 20.0;
110 var progress_radius = 40.0;
111 var progress_radius_inner = progress_radius - progress_width / 2.0;
112 var progress_radius_outer = progress_radius + progress_width / 2.0;
114 // ProgressBackground
115 cr.set_source (create_gradient_str (20, 20, 89, 87, "#2f2f4c", "#090a0d"));
116 cr.set_line_width (progress_width);
117 cr.arc (x, y, progress_radius, start_angle, end_angle);
118 cr.stroke ();
120 // ProgressLamp
121 cr.set_source (create_gradient_str (20, 20, 89, 87, "#b9feff", "#3aacaa"));
122 cr.set_line_width (progress_width);
123 cr.arc (x, y, progress_radius, start_angle, value_angle);
124 cr.stroke ();
126 // ProgressShadow
127 // TODO (Performace ?)
129 cr.set_line_cap (LineCap.ROUND);
130 var progress_rim_width = 2.0;
131 cr.set_line_width (progress_rim_width);
133 // ProgressBeginRim
134 cr.set_source (create_gradient_str (18, 79, 35, 79, "#dfd5c9", "#dfd5c9", 1.0, 0.0));
135 cr.move_to (x + progress_radius_outer * cos_start_angle,
136 y + progress_radius_outer * sin_start_angle);
137 cr.line_to (x + progress_radius_inner * cos_start_angle,
138 y + progress_radius_inner * sin_start_angle);
139 cr.stroke ();
141 // ProgressEndRim
142 set_source_color_string (cr, "#b3a190");
143 cr.move_to (x + progress_radius_outer * cos_end_angle,
144 y + progress_radius_outer * sin_end_angle);
145 cr.line_to (x + progress_radius_inner * cos_end_angle,
146 y + progress_radius_inner * sin_end_angle);
147 cr.stroke ();
149 // ProgressRim
150 cr.set_source (create_gradient_str (95, 6, 5, 44, "#dfd5c9", "#b0a090"));
151 cr.arc (x, y, progress_radius_outer, start_angle, end_angle);
152 cr.stroke ();
154 cr.set_line_cap (LineCap.BUTT);
156 // ProgressLampReflection
157 // TODO?: blur 2.0
158 cr.set_source (create_gradient_str (20, 20, 89, 87, "#b9feff", "#3aacaa", 0.25, 0.25));
159 cr.set_line_width (progress_width);
160 cr.arc (x, y, progress_radius, start_angle, value_angle + Math.PI / 180.0);
161 cr.stroke ();
163 // ProgressBackgroundShine
165 Cairo.Pattern progress_shine = create_gradient_str (89, 73, 34, 16, "#ffffff", "#ffffff", 0.3, 0.04);
166 progress_shine.add_color_stop_rgba (0.5, 1.0, 1.0, 1.0, 0.0);
167 progress_shine.add_color_stop_rgba (0.75, 1.0, 1.0, 1.0, 0.3);
169 cr.set_source (progress_shine);
170 cr.set_line_width (progress_width);
171 cr.arc (x, y, progress_radius, start_angle, end_angle);
172 cr.stroke ();
174 // KnobShadow
175 // TODO?: blur 2.0
176 cr.set_line_width (progress_rim_width);
177 cr.set_source (create_gradient_str (86, 77, 38, 25, "#151928", "#151928", 1.0, 0.5));
178 cr.arc (x, y, progress_radius_inner, 0, 2 * Math.PI);
179 cr.stroke ();
181 // KnobRimPlain
182 cr.set_line_width (1.0);
183 cr.set_source_rgb (0.0, 0.0, 0.0);
184 cr.arc (x, y, progress_radius_inner, 0, 2 * Math.PI);
185 cr.stroke ();
187 var knob_disc_radius = knob_rim_radius - progress_rim_width;
189 // KnobDiscBackground
190 cr.set_line_width (0.0);
191 cr.set_source (create_gradient_str (42, 34, 68, 70, "#e7ecef", "#9cafb8"));
192 cr.arc (x, y, knob_disc_radius, 0, 2 * Math.PI);
193 cr.fill ();
195 double degrees = Math.PI / 180.0;
197 // KnobRimShadow
198 // TODO
200 // KnobShineBright
201 cr.set_source (create_gradient_str (38, 34, 70, 68, "#ffffff", "#caddf2", 0.2, 0.2));
202 cr.move_to (x,y);
203 cr.arc (x, y, knob_disc_radius, -154 * degrees, -120 * degrees);
204 cr.move_to (x,y);
205 cr.arc (x, y, knob_disc_radius, Math.PI / 2.0 - 60 * degrees, Math.PI / 2.0 - 29 * degrees);
206 cr.fill ();
208 // KnobShineDark
209 cr.set_source (create_gradient_str (50, 40, 62, 60, "#a1adb6", "#47535c", 0.07, 0.15));
210 cr.move_to (x,y);
211 cr.arc (x, y, knob_disc_radius, - 67 * degrees, - 27 * degrees);
212 cr.move_to (x,y);
213 cr.arc (x, y, knob_disc_radius, Math.PI - 67 * degrees, Math.PI- 27 * degrees);
214 cr.fill ();
216 // KnobShineRipples
217 Cairo.Pattern knob_ripples = new Cairo.Pattern.radial (x, y, 0, x, y, 4);
218 add_color_stop_str (knob_ripples, 0.0, "#e7ecef", 0.05);
219 add_color_stop_str (knob_ripples, 0.5, "#58717d", 0.05);
220 add_color_stop_str (knob_ripples, 0.75, "#d1d9de", 0.05);
221 add_color_stop_str (knob_ripples, 1.0, "#5d7682", 0.05);
222 knob_ripples.set_extend(Cairo.Extend.REPEAT);
224 cr.set_line_width (0.0);
225 cr.set_source (knob_ripples);
226 cr.arc (x, y, knob_disc_radius, 0, 2 * Math.PI);
227 cr.fill ();
229 cr.save();
231 cr.translate (x + progress_radius_inner * cos_value,
232 y + progress_radius_inner * sin_value);
234 cr.rotate (value_angle - Math.PI);
236 // KnobIndicatorBay
237 cr.set_source (create_gradient_str (16, -2, 9, 13, "#e7ecef", "#9cafb8", 0.8, 0.8));
238 cr.move_to (0, 4);
239 cr.line_to (17, 4);
240 cr.curve_to (19, 4, 21, 2, 21, 0);
241 cr.curve_to (21, -2, 19, -4, 17, -4);
242 cr.line_to (0, -4);
243 cr.close_path();
244 cr.fill();
246 // KnobIndicator
247 cr.set_source (create_gradient_str (9, -2, 9, 2, "#68625c", "#44494b"));
248 cr.move_to (0, 2);
249 cr.line_to (16, 2);
250 cr.curve_to (17, 2, 18, 1, 18, 0);
251 cr.curve_to (18, -1, 17, -2, 16, -2);
252 cr.line_to (0, -2);
253 cr.close_path();
254 cr.fill();
256 cr.restore ();
258 // KnobDiscRim
259 cr.set_line_width (2.0);
260 cr.set_source (create_gradient_str (38, 32, 70, 67, "#3d3d3d", "#000000"));
261 cr.arc (x, y, progress_radius_inner, 0, 2 * Math.PI);
262 cr.stroke ();
264 cr.restore ();
267 } // namespace Prolooks