Several updates - added support for second pattern engine and adding commands
[led-pattern-ed] / src / led-command-widget.vala
1 /* This file is part of LED Pattern Editor.
2  *
3  * Copyright (C) 2010 Philipp Zabel
4  *
5  * LED Pattern Editor is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * LED Pattern Editor is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with LED Pattern Editor. If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 class LedCommandWidget : Gtk.HBox {
20         private const double CYCLE_TIME_MS = 1000.0 / 32768.0;
21
22         LedPatternRX51 pattern;
23         unowned List<LedCommandRX51> engine;
24         LedCommandRX51 command;
25
26         public LedCommandWidget (LedPatternRX51 _pattern, List<LedCommandRX51> _engine,
27                                  LedCommandRX51 _command) {
28                 homogeneous = true;
29                 pattern = _pattern;
30                 engine = _engine;
31                 command = _command;
32
33                 var button = new Hildon.Button (Hildon.SizeType.FINGER_HEIGHT,
34                                                 Hildon.ButtonArrangement.VERTICAL);
35                 button.set_style (Hildon.ButtonStyle.PICKER);
36                 button.set_alignment (0, 0.5f, 0, 0.5f);
37
38                 switch (command.type) {
39                 case CommandType.UNKNOWN:
40                         button.set_title ("???");
41                         button.set_value ("0x%04x".printf (command.code));
42                         button.set_sensitive (false);
43                         break;
44                 case CommandType.RAMP_WAIT:
45                         button.set_title ((command.steps != 0) ? "Ramp" : "Wait");
46                         button.set_value ((command.steps != 0) ?
47                                           "%+d steps, %.2f ms each".printf (command.steps,
48                                                                             command.step_time) :
49                                           "%.2f ms".printf (command.duration));
50                         button.clicked.connect (on_ramp_wait_clicked);
51                         break;
52                 case CommandType.SET_PWM:
53                         button.set_title ("Set PWM");
54                         button.set_value ("Level = %d".printf (command.level));
55                         button.clicked.connect (on_set_pwm_clicked);
56                         break;
57                 case CommandType.RESET_MUX:
58                         button.set_title ("Reset Mux");
59                         break;
60                 case CommandType.GO_TO_START:
61                         button.set_title ("Go To Start");
62                         button.set_value ("");
63                         button.clicked.connect (on_end_or_go_to_start_clicked);
64                         break;
65                 case CommandType.BRANCH:
66                         button.set_title ("Branch");
67                         button.set_value ("0x%04x".printf (command.code));
68                         button.set_sensitive (false);
69                         break;
70                 case CommandType.END:
71                         button.set_title ("End");
72                         button.set_value ((command.steps == -255) ? "Reset" : "Hold");
73                         button.clicked.connect (on_end_or_go_to_start_clicked);
74                         break;
75                 case CommandType.TRIGGER:
76                         button.set_title ("Trigger");
77                         string text = "";
78                         if (0x0100 in command.code)
79                                 text += "wait 2 ";
80                         if (0x0004 in command.code)
81                                 text += "set 2 ";
82                         if (0x0080 in command.code)
83                                 text += "wait 1 ";
84                         if (0x0002 in command.code)
85                                 text += "set 1 ";
86                         if ((command.code & ~0xe186) != 0) {
87                                 text = "Unsupported: 0x%04x".printf (command.code);
88                                 button.set_sensitive (false);
89                         }
90                         button.set_value (text);
91                         button.clicked.connect (on_trigger_clicked);
92                         break;
93                 }
94                 pack_start (button, true, true, 0);
95         }
96
97         private void on_ramp_wait_clicked (Gtk.Button source) {
98                 double old_step_time = command.step_time;
99                 int old_steps = command.steps;
100                 var dialog = new Gtk.Dialog ();
101                 dialog.set_title ("Ramp / Wait");
102
103                 var content = (Gtk.VBox) dialog.get_content_area ();
104
105                 var lpv = new LedPatternView (pattern);
106                 lpv.set_size_request (-1, 70);
107                 content.pack_start (lpv, true, true, 0);
108
109                 var scale1 = new Gtk.HScale.with_range (1, 62, 1);
110                 int v = (int) (command.step_time / 16 / CYCLE_TIME_MS);
111                 if (v > 62)
112                         v /= 32;
113                 scale1.set_value (v);
114                 scale1.format_value.connect ((v) => {
115                         if (v < 32)
116                                 return "%.2f ms".printf (v * 16 * CYCLE_TIME_MS);
117                         else
118                                 return "%.1f ms".printf ((v - 31) * 512 * CYCLE_TIME_MS);
119                 });
120                 scale1.value_changed.connect ((s) => {
121                         int val = (int) s.get_value ();
122                         if (val < 32)
123                                 command.ramp_wait (val * 16 * CYCLE_TIME_MS, command.steps);
124                         else
125                                 command.ramp_wait ((val - 31) * 512 * CYCLE_TIME_MS, command.steps);
126                 });
127                 content.pack_start (scale1, true, true, 0);
128
129                 var hbox = new Gtk.HBox (false, 0);
130                 var hbox2 = new Gtk.HBox (true, 0);
131                 var radio_inc = (Gtk.RadioButton) Hildon.gtk_radio_button_new (Hildon.SizeType.FINGER_HEIGHT, null);
132                 radio_inc.set_mode (false);
133                 radio_inc.set_label ("+");
134                 hbox2.pack_start (radio_inc, false, false, 0);
135                 var radio_dec = (Gtk.RadioButton) Hildon.gtk_radio_button_new_from_widget (Hildon.SizeType.FINGER_HEIGHT, radio_inc);
136                 radio_dec.set_mode (false);
137                 radio_dec.set_label ("-");
138                 bool sign = command.steps < 0;
139                 radio_dec.set_active (sign);
140                 radio_dec.toggled.connect ((s) => {
141                         sign = s.get_active ();
142                         if (sign != (command.steps < 0))
143                                 command.ramp_wait (command.step_time, -command.steps);
144                 });
145                 hbox2.pack_start (radio_dec, false, false, 0);
146                 hbox.pack_start (hbox2, false, false, 0);
147                 var scale2 = new Gtk.HScale.with_range (0, 255, 1);
148                 scale2.set_value ((command.steps < 0) ? -command.steps : command.steps);
149                 scale2.set_value_pos (Gtk.PositionType.RIGHT);
150                 scale2.format_value.connect ((v) => {
151                         return "%+d".printf (sign ? -(int) v : (int) v);
152                 });
153                 scale2.value_changed.connect ((s) => {
154                         if (sign)
155                                 command.ramp_wait (command.step_time, -(int) scale2.get_value ());
156                         else
157                                 command.ramp_wait (command.step_time, (int) scale2.get_value ());
158                 });
159                 hbox.pack_start (scale2, true, true, 0);
160                 content.pack_start (hbox, false, false, 0);
161
162                 content.show_all ();
163                 dialog.add_button ("Delete", 1);
164                 dialog.add_button ("Done", Gtk.ResponseType.OK);
165
166                 int response = dialog.run ();
167                 if (response == Gtk.ResponseType.OK) {
168                         var button = source as Hildon.Button;
169                         button.set_title ((command.steps != 0) ? "Ramp" : "Wait");
170                         button.set_value ((command.steps != 0) ?
171                                           "%+d steps, %.2f ms each".printf (command.steps,
172                                                                             command.step_time) :
173                                           "%.2f ms".printf (command.duration));
174                 } else if (response == 1) {
175                         engine.remove (command);
176                         engine.first ().data.changed ();
177                         this.destroy ();
178                 } else {
179                         command.ramp_wait (old_step_time, old_steps);
180                 }
181                 dialog.destroy ();
182         }
183
184         private void on_set_pwm_clicked (Gtk.Button source) {
185                 int old_level = command.level;
186                 var dialog = new Gtk.Dialog ();
187                 dialog.set_title ("Set PWM");
188
189                 var content = (Gtk.VBox) dialog.get_content_area ();
190
191                 var lpv = new LedPatternView (pattern);
192                 lpv.set_size_request (-1, 70);
193                 content.pack_start (lpv, true, true, 0);
194
195                 var scale = new Gtk.HScale.with_range (0, 255, 1);
196                 scale.set_value (command.level);
197                 scale.value_changed.connect ((s) => {
198                         command.set_pwm ((int) s.get_value ());
199                 });
200                 content.pack_start (scale, true, true, 0);
201
202                 content.show_all ();
203                 dialog.add_button ("Delete", 1);
204                 dialog.add_button ("Done", Gtk.ResponseType.OK);
205
206                 int response = dialog.run ();
207                 if (response == Gtk.ResponseType.OK) {
208                         command.set_pwm ((int) scale.get_value ());
209
210                         var button = source as Hildon.Button;
211                         button.set_value ("Level = %d".printf (command.level));
212                 } else if (response == 1) {
213                         engine.remove (command);
214                         engine.first ().data.changed ();
215                         this.destroy ();
216                 } else {
217                         command.set_pwm (old_level);
218                 }
219                 dialog.destroy ();
220         }
221
222         private void on_end_or_go_to_start_clicked (Gtk.Button source) {
223                 CommandType old_type = command.type;
224                 int old_steps = command.steps;
225                 uint16 old_code = command.code;
226                 var dialog = new Gtk.Dialog ();
227                 if (command.type == CommandType.END)
228                         dialog.set_title ("End");
229                 else
230                         dialog.set_title ("Go To Start");
231
232                 var content = (Gtk.VBox) dialog.get_content_area ();
233
234                 var lpv = new LedPatternView (pattern);
235                 lpv.set_size_request (-1, 70);
236                 content.pack_start (lpv, true, true, 0);
237
238                 var hbox = new Gtk.HBox (true, 0);
239                 var radio_end = (Gtk.RadioButton) Hildon.gtk_radio_button_new (Hildon.SizeType.FINGER_HEIGHT, null);
240                 radio_end.set_mode (false);
241                 radio_end.set_label ("End");
242                 hbox.pack_start (radio_end, true, true, 0);
243                 var radio_go_to_start = (Gtk.RadioButton) Hildon.gtk_radio_button_new_from_widget (Hildon.SizeType.FINGER_HEIGHT, radio_end);
244                 radio_go_to_start.set_mode (false);
245                 radio_go_to_start.set_label ("Go To Start");
246                 hbox.pack_start (radio_go_to_start, true, true, 0);
247                 content.pack_start (hbox, true, true, 0);
248
249                 hbox = new Gtk.HBox (true, 0);
250                 var radio_hold = (Gtk.RadioButton) Hildon.gtk_radio_button_new (Hildon.SizeType.FINGER_HEIGHT, null);
251                 radio_hold.set_mode (false);
252                 radio_hold.set_label ("Hold");
253                 hbox.pack_start (radio_hold, true, true, 0);
254                 var radio_reset = (Gtk.RadioButton) Hildon.gtk_radio_button_new_from_widget (Hildon.SizeType.FINGER_HEIGHT, radio_hold);
255                 radio_reset.set_mode (false);
256                 radio_reset.set_label ("Reset");
257                 hbox.pack_start (radio_reset, true, true, 0);
258                 content.pack_start (hbox, true, true, 0);
259
260                 if (command.type == CommandType.END)
261                         radio_end.set_active (true);
262                 else
263                         radio_go_to_start.set_active (true);
264                 radio_hold.set_sensitive (command.type == CommandType.END);
265                 radio_reset.set_sensitive (command.type == CommandType.END);
266                 radio_reset.set_active (command.steps == -255);
267
268                 radio_end.toggled.connect ((s) => {
269                         if (s.get_active ()) {
270                                 command.end (radio_reset.get_active ());
271                                 radio_hold.set_sensitive (true);
272                                 radio_reset.set_sensitive (true);
273                                 dialog.set_title ("End");
274                         } else {
275                                 command.go_to_start ();
276                                 radio_hold.set_sensitive (false);
277                                 radio_reset.set_sensitive (false);
278                                 dialog.set_title ("Go To Start");
279                         }
280                         command.changed ();
281                 });
282                 radio_reset.toggled.connect ((s) => {
283                         if (command.type == CommandType.END) {
284                                 command.end (s.get_active ());
285                         }
286                 });
287
288                 content.show_all ();
289                 dialog.add_button ("Delete", 1);
290                 dialog.add_button ("Done", Gtk.ResponseType.OK);
291
292                 int response = dialog.run ();
293                 if (response == Gtk.ResponseType.OK) {
294                         var button = source as Hildon.Button;
295                         button.set_value ((command.type == CommandType.END) ?
296                                           "End" : "Go To Start");
297                         button.set_value ((command.type == CommandType.END) ?
298                                           ((command.steps == -255) ? "Reset" : "Hold") : "");
299                 } else if (response == 1) {
300                         engine.remove (command);
301                         engine.first ().data.changed ();
302                         this.destroy ();
303                 } else {
304                         command.type = old_type;
305                         command.steps = old_steps;
306                         command.code = old_code;
307                         command.changed ();
308                 }
309                 dialog.destroy ();
310         }
311
312         private void on_trigger_clicked (Gtk.Button source) {
313                 uint16 old_code = command.code;
314                 var dialog = new Gtk.Dialog ();
315                 dialog.set_title ("Trigger");
316
317                 var content = (Gtk.VBox) dialog.get_content_area ();
318
319                 var lpv = new LedPatternView (pattern);
320                 lpv.set_size_request (-1, 70);
321                 content.pack_start (lpv, true, true, 0);
322
323                 var check = new Hildon.CheckButton (Hildon.SizeType.FINGER_HEIGHT);
324                 check.set_label ("Set trigger");
325                 if ((command.code & 0x0006) != 0)
326                         check.set_active (true);
327                 check.toggled.connect ((s) => {
328                         int bit = (engine == pattern.engine1) ? 0x0004 : 0x0002;
329                         if (s.get_active ())
330                                 command.code |= bit;
331                         else
332                                 command.code &= ~bit;
333                         command.changed ();
334                 });
335                 content.pack_start (check, true, true, 0);
336
337                 check = new Hildon.CheckButton (Hildon.SizeType.FINGER_HEIGHT);
338                 check.set_label ("Wait for trigger");
339                 if ((command.code & 0x0180) != 0)
340                         check.set_active (true);
341                 check.toggled.connect ((s) => {
342                         int bit = (engine == pattern.engine1) ? 0x0100 : 0x0080;
343                         if (s.get_active ())
344                                 command.code |= bit;
345                         else
346                                 command.code &= ~bit;
347                         command.changed ();
348                 });
349                 content.pack_start (check, true, true, 0);
350
351                 content.show_all ();
352                 dialog.add_button ("Delete", 1);
353                 dialog.add_button ("Done", Gtk.ResponseType.OK);
354
355                 int response = dialog.run ();
356                 if (response == Gtk.ResponseType.OK) {
357                         var button = source as Hildon.Button;
358                         string text = "";
359                         if (0x0100 in command.code)
360                                 text += "wait 2 ";
361                         if (0x0004 in command.code)
362                                 text += "set 2 ";
363                         if (0x0080 in command.code)
364                                 text += "wait 1 ";
365                         if (0x0002 in command.code)
366                                 text += "set 1 ";
367                         if ((command.code & ~0xe186) != 0) {
368                                 text = "Unsupported: 0x%04x".printf (command.code);
369                                 button.set_sensitive (false);
370                         }
371                         button.set_value (text);
372                 } else if (response == 1) {
373                         engine.remove (command);
374                         engine.first ().data.changed ();
375                         this.destroy ();
376                 } else {
377                         command.code = old_code;
378                         command.changed ();
379                 }
380                 dialog.destroy ();
381         }
382 }