CalfKnobImage -> SimpleKnobImage (in the files)
[libprolooks.git] / prolooks / StepEditor.vala
blobef63149aafddf53b89c8e146d39479bf52d8c470
1 using Gtk;
2 using Gdk;
4 // template for new widgets
6 namespace Prolooks {
8 public class StepEditor : DrawingArea {
10 private float [] _step_values;
11 private uint _steps;
12 public uint steps {
13 set {
14 _steps = value;
15 float[] oldsteps = _step_values;
16 _step_values = new float[_steps];
17 if (oldsteps != null) {
18 for (int i = 0; i < oldsteps.length && i < _step_values.length; i++)
19 _step_values[i] = oldsteps[i];
21 queue_draw();
23 get { return _steps; }
26 private uint _spacing;
27 public uint spacing {
28 set { _spacing = value; queue_draw();}
29 get { return _spacing; }
32 protected int edited_step = -1;
34 private float first_step = 0.0f;
36 public StepEditor () {
38 _steps = 16;
39 _spacing = 1;
41 // Enable the events you wish to get notified about.
42 // The 'expose' event is already enabled by the DrawingArea.
43 add_events (Gdk.EventMask.BUTTON_PRESS_MASK
44 | Gdk.EventMask.BUTTON_RELEASE_MASK
45 | Gdk.EventMask.POINTER_MOTION_MASK);
47 set_size_request(-1, 64);
50 public override void size_request (out Gtk.Requisition requisition) {
51 // width/height is hardwired at 40px now
52 requisition.width = (int)(_steps * 12 - _spacing);
53 requisition.height = this.requisition.height;
58 /* Widget is asked to draw itself */
59 public override bool expose_event (Gdk.EventExpose event) {
61 // Create a Cairo context
62 var cr = Gdk.cairo_create (this.window);
64 // Set clipping area in order to avoid unnecessary drawing
65 cr.rectangle (event.area.x, event.area.y,
66 event.area.width, event.area.height);
67 cr.clip ();
69 int w = allocation.width;
70 int h = allocation.height;
72 cr.set_source_rgba(0.0, 0.0, 0.0, 1);
73 cr.rectangle(allocation.x, allocation.y, w, h);
74 cr.fill();
76 for (int i = 0; i < steps; i++) {
77 int pos = (int)(h * get_step(i));
78 int p1 = (int)(allocation.x + i * (w + _spacing) / _steps);
79 int p2 = (int)(allocation.x + (i + 1) * (w + _spacing) / _steps - _spacing);
80 cr.set_source_rgba(0.1, 0.1, 0.1, 1);
81 cr.rectangle(p1, allocation.y, p2 - p1, h - pos);
82 cr.fill();
83 cr.set_source_rgba(0.2, 0.5, 0.3, 1);
84 cr.rectangle(p1, allocation.y + h - pos, p2 - p1, pos);
85 cr.fill();
88 // ...
90 return false;
93 /* Mouse button got pressed over widget */
94 public override bool button_press_event (Gdk.EventButton event) {
95 edited_step = (int)(event.x * _steps / allocation.width);
96 set_step(edited_step, (float)(1.0 - event.y / allocation.height));
97 grab_focus ();
98 grab_add (this);
99 queue_draw();
100 // ...
101 return false;
104 /* Mouse button got released */
105 public override bool button_release_event (Gdk.EventButton event) {
106 if (has_grab ())
107 grab_remove (this);
108 edited_step = -1;
109 return false;
112 /* Mouse pointer moved over widget */
113 public override bool motion_notify_event (Gdk.EventMotion event) {
114 if (edited_step != -1)
115 set_step(edited_step, (float)(1.0 - event.y / allocation.height));
116 // ...
117 return false;
120 public float get_step(uint step)
122 return _step_values[step];
125 public void set_step(uint step, float value)
127 if (value < 0.0f)
128 value = 0.0f;
129 if (value > 1.0f)
130 value = 1.0f;
131 _step_values[step] = value;
132 queue_draw();
135 static int main (string[] args) {
136 Gtk.init (ref args);
137 var window = new Gtk.Window (Gtk.WindowType.TOPLEVEL);
138 var widget = new StepEditor ();
139 widget.steps = 16;
140 for (int i = 0; i < 16; i++)
141 widget.set_step(i, (float)(i / 15.0));
144 window.add (widget);
145 window.destroy += Gtk.main_quit;
146 window.show_all ();
147 Gtk.main ();
148 return 0;
152 } // namespace Prolooks