Knob: instantiate SimpleKnobImageSource by default
[libprolooks.git] / prolooks / SimpleKnobImageSource.gs
blob6e6d02b0c92ccb7612948adfbac9867034b9e314
1 uses
2         Gtk
3         Cairo
4         GLib.Math
6 namespace Prolooks
7         class SimpleKnobImageSource : DrawingArea implements IKnobImageSource
8                 prop knob_width:  double
9                 prop knob_height: double
10                 prop x:           double
11                 prop y:           double
12                 prop led_color:   Gdk.Color
14                 def get_knob_width () : double
15                         return knob_width
17                 def get_knob_height () : double
18                         return knob_height
20                 def get_line_width () : double
21                         return knob_width / 10
23                 def get_radius () : double
24                         return knob_width / 2 - get_line_width ()
26                 init
27                         knob_width = 40
28                         knob_height = 40
29                         x = knob_width / 2
30                         y = knob_height / 2
31                         set_size_request (phases * (int)knob_width, variants * (int)knob_height);
32                         led_color = color_from_string ("#ff7f00")
33                 
34                 def override expose_event (event: Gdk.EventExpose) : bool
35                         var cr = Gdk.cairo_create (this.window);
36                         // Set clipping area in order to avoid unnecessary drawing
37                         Gdk.cairo_rectangle (cr, event.area);
38                         cr.clip ();
39                         
40                         cr.set_source_rgba(0.75, 0.75, 0.75, 0)
41                         cr.rectangle(0, 0, phases * knob_width, 4 * knob_height)
42                         cr.fill()
44                         for var variant = 0 to variants
45                                 var x = knob_width / 2
46                                 var y = knob_height * (variant + 0.5)
47                                 paint_knobs (cr, variant, x, y)
48                                 
49                         return true
51                 def paint_knob (cr: Context, knob_mode: KnobMode, phase: int, lwidth: double, radius: double, x: double, y: double)
52                         var radiusplus = radius + lwidth / 2
53                         var radiusminus = radius - lwidth / 2
54                         var radiusminus2 = radius - lwidth
55                         var radiusminus3 = radius - lwidth * 3 / 2
56                         var radiusint = (radius - lwidth / 2) * 0.25
57                         var value = 0.7
58                         var arrow = knob_width / 10.0
59                         
60                         var sangle = 0.0
61                         var eangle = 0.0
62                         var vangle = 0.0
63                         var nleds  = 0.0
65                         // Draw out the triangle using absolute coordinates
66                         value = phase * 1.0 / (phases - 1)
67                         if knob_mode != KnobMode.ENDLESS
68                                 sangle = (180 - 45) * PI / 180
69                                 eangle = (360 + 45) * PI / 180
70                                 nleds = 31
71                         else
72                                 sangle = (270) * PI / 180
73                                 eangle = (270 + 360) * PI / 180
74                                 nleds = 32
75                         vangle = sangle + value * (eangle - sangle)
76                         var c = cos(vangle)
77                         var s = sin(vangle)
79                         var midled = (nleds - 1) / 2
80                         var midphase = (phases - 1) / 2
81                         var thresholdP = midled + 1 + ((phase - midphase - 1) * 1.0 * (nleds - midled - 2) / (phases - midphase - 2))
82                         var thresholdN = midled - 1 - ((midphase - 1 - phase) * 1.0 * (nleds - midled - 2) / (midphase - 1))
83         
84                         var spacing = PI / nleds
85                         for var led = 0 to (nleds - 1)
86                                 var adelta = 0.0
87                                 if knob_mode == KnobMode.ENDLESS
88                                         adelta = (eangle - sangle) / (nleds)
89                                 else
90                                         adelta = (eangle - sangle - spacing) / (nleds - 1)
91                                 var lit = false
92                                 var glowlit = false
93                                 var glowval = 0.5
94                                 var hilite = false
95                                 var lvalue = led   * 1.0 / (nleds  - 1)
96                                 var pvalue = phase * 1.0 / (phases - 1)
97                                 if knob_mode == KnobMode.ENDLESS
98                                         // XXXKF works only for phases = 2 * leds
99                                         var exled = phase / 2.0
100                                         lit = (led == exled) or (phase == (phases - 1) and led == 0)
101                                         glowlit = led == (exled + 0.5) or led == (exled - 0.5)
102                                         glowval = 0.8
103                                         hilite = (phase % ((phases - 1) / 4)) == 0
104                                 if knob_mode == KnobMode.POSITIVE
105                                         lit = (pvalue == 1.0) or pvalue > lvalue
106                                 if knob_mode == KnobMode.BIPOLAR
107                                         if led == midled
108                                                 lit = (phase == midphase)
109                                                 //glowlit = (phase < midphase and thresholdN >= midled - 1) or (phase > midphase and thresholdP <= midled + 1)
110                                                 glowlit = false
111                                                 hilite = true
112                                         else if led > midled and phase > midphase
113                                                 // led = [midled + 1, nleds - 1]
114                                                 // phase = [midphase + 1, phases - 1]
115                                                 lit = led <= thresholdP
116                                                 glowlit = led <= thresholdP + 1
117                                                 glowval = 0.4
118                                         else if led < midled and phase < midphase
119                                                 lit = led >= thresholdN
120                                                 glowlit = led >= thresholdN - 1
121                                                 glowval = 0.4
122                                         else
123                                                 lit = false
124                                 if knob_mode == KnobMode.NEGATIVE
125                                         lit = pvalue == 0 or pvalue < lvalue
126                                 if not lit
127                                         if not glowlit
128                                                 cr.set_source_rgb(0, 0, 0)
129                                         else
130                                                 set_source_color(cr, shade_color (led_color, glowval))
131                                 else
132                                         if hilite
133                                                 cr.set_source_rgb(1, 1, 0)
134                                         else
135                                                 set_source_color(cr, led_color)
136                                 cr.set_line_width(3)
137                                 cr.arc(x, y, radius, sangle + adelta * led, sangle + adelta * led + spacing)
138                                 cr.stroke()
140                         var grad = new Cairo.Pattern.linear(x - radius / 2, y - radius / 2, x + radius / 2, y + radius / 2)
141                         grad.add_color_stop_rgb(0.0, 0.5, 0.5, 0.5)
142                         grad.add_color_stop_rgb(1.0, 0.8, 0.8, 0.8)
143                         cr.set_source(grad)
144                         cr.set_line_width(2)
145                         cr.arc(x, y, radiusminus2, 0, 2 * PI)
146                         cr.fill()
148                         grad = new Cairo.Pattern.linear(x - radius / 2, y - radius / 2, x + radius / 2, y + radius / 2)
149                         grad.add_color_stop_rgb(0.0, 0.8, 0.8, 0.8)
150                         grad.add_color_stop_rgb(1.0, 0.5, 0.5, 0.5)
151                         cr.set_source(grad)
152                         cr.arc(x, y, radiusminus3, 0, 2 * PI)
153                         cr.fill()
154                         cr.set_source_rgb(0, 0, 0)
155                         cr.set_line_width(2)
156                         cr.arc(x, y, radiusminus2, 0, 2 * PI)
157                         cr.stroke()
159                         cr.set_source_rgba(0, 0, 0, 0.5)
160                         cr.set_line_width(1)
161                         var mtx = Matrix (0,0,0,0,0,0)
162                         cr.get_matrix(out mtx)
163                         cr.translate(x + radiusminus2 * c, y + radiusminus2 * s)
164                         cr.rotate(vangle)
165                         cr.move_to(0, 0)
166                         cr.line_to(-radius/2, 0)
167                         cr.stroke()
168                         cr.set_matrix(mtx)