Add LED pattern view
authorPhilipp Zabel <philipp.zabel@gmail.com>
Wed, 24 Feb 2010 16:59:37 +0000 (17:59 +0100)
committerPhilipp Zabel <philipp.zabel@gmail.com>
Wed, 24 Feb 2010 17:55:50 +0000 (18:55 +0100)
Makefile
src/led-pattern-view.vala [new file with mode: 0644]

index d817137..a7d73ad 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -24,6 +24,7 @@ led_pattern_editor_VALASOURCES = \
        src/led-pattern.vala \
        src/led-pattern-rx51.vala \
        src/led-pattern-dialog.vala \
+       src/led-pattern-view.vala \
        src/mce-ini-parse.vala
 
 led_pattern_editor_VALAFLAGS = --pkg hildon-1 --pkg libosso
diff --git a/src/led-pattern-view.vala b/src/led-pattern-view.vala
new file mode 100644 (file)
index 0000000..a4f7444
--- /dev/null
@@ -0,0 +1,212 @@
+/* This file is part of LED Pattern Editor.
+ *
+ * Copyright (C) 2010 Philipp Zabel
+ *
+ * LED Pattern Editor is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LED Pattern Editor is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with LED Pattern Editor. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+class LedPatternView : Gtk.DrawingArea {
+       public LedPatternRX51 pattern;
+       public double duration;
+
+       public LedPatternView (LedPatternRX51? _pattern = null) {
+               pattern = _pattern;
+               if (pattern != null)
+                       pattern.changed.connect (update);
+               update_duration ();
+       }
+
+       public void update_duration () {
+               duration = 1.0;
+               if (pattern != null) {
+                       while (pattern.duration > 1000 * duration) {
+                               duration += 1.0;
+                       }
+               }
+       }
+
+       public override bool expose_event (Gdk.EventExpose event) {
+
+               update_duration ();
+
+               var ctx = Gdk.cairo_create (window);
+               int height = allocation.height;
+               int width = allocation.width;
+               double pps = width / duration; // pixel per second
+
+               ctx.rectangle (event.area.x, event.area.y, event.area.width, event.area.height);
+               ctx.clip ();
+
+               ctx.set_source_rgb (0, 0, 0);
+               ctx.set_line_width (1.0);
+
+               ctx.set_line_join (Cairo.LineJoin.ROUND);
+
+               ctx.new_path ();
+               ctx.move_to (0, 0);
+               ctx.line_to (width, 0);
+               ctx.line_to (width, height);
+               ctx.line_to (0, height);
+               ctx.close_path ();
+               ctx.fill ();
+
+               ctx.set_source_rgb (0.33, 0.33, 0.33);
+               ctx.new_path ();
+
+               // 0%, 50%, 100%
+               ctx.move_to (0.5, 0.5);
+               ctx.line_to (width - 0.5, 0.5);
+
+               ctx.move_to (0.5, height / 2 - 0.5);
+               ctx.line_to (width - 0.5, height / 2 - 0.5);
+
+               ctx.move_to (0.5, height - 0.5);
+               ctx.line_to (width - 0.5, height - 0.5);
+
+               // 0s, 1s, 2s, 3s, 4s
+               for (double time = 0; time <= duration; time += 1.0) {
+                       ctx.move_to (time * pps + 0.5, 0.5);
+                       ctx.line_to (time * pps + 0.5, 139.5);
+               }
+               ctx.stroke ();
+
+               if (pattern != null) {
+                       ctx.new_path ();
+
+                       if (pattern.led_map == "r") {
+                               ctx.set_source_rgb (1, 0, 0);
+                       } else if (pattern.led_map == "g") {
+                               ctx.set_source_rgb (0, 1, 0);
+                       } else if (pattern.led_map == "b") {
+                               ctx.set_source_rgb (0, 0, 1);
+                       } else if (pattern.led_map == "rg") {
+                               ctx.set_source_rgb (1, 1, 0);
+                       } else if (pattern.led_map == "rb") {
+                               ctx.set_source_rgb (1, 0, 1);
+                       } else if (pattern.led_map == "gb") {
+                               ctx.set_source_rgb (0, 1, 1);
+                       } else if (pattern.led_map == "rgb") {
+                               ctx.set_source_rgb (1, 1, 1);
+                       } else {
+                               ctx.set_source_rgb (0.75, 0.75, 0.75);
+                       }
+                       ctx.set_line_width (3.0);
+
+                       double x = 0, y = 0;
+                       foreach (LedCommand command in pattern.engine1) {
+                               x = command.time * pps/1000.0;
+                               y = (255 - command.level) * (height - 1)/255.0;
+                               switch (command.type) {
+                               case CommandType.RAMP_WAIT:
+                                       x += command.duration * pps/1000.0;
+                                       y -= command.steps * (height - 1)/255.0;
+                                       if (y < 0)
+                                               y = 0;
+                                       if (y > (height - 1))
+                                               y = height - 1;
+                                       ctx.line_to (x, y);
+                                       break;
+                               default:
+                                       ctx.line_to (x, y);
+                                       break;
+                               }
+                       }
+                       ctx.stroke ();
+
+                       if (pattern.led_map == "r") {
+                               ctx.set_source_rgb (0.75, 0, 0);
+                       } else if (pattern.led_map == "g") {
+                               ctx.set_source_rgb (0, 0.75, 0);
+                       } else if (pattern.led_map == "b") {
+                               ctx.set_source_rgb (0, 0, 0.75);
+                       } else if (pattern.led_map == "rg") {
+                               ctx.set_source_rgb (0.75, 0.75, 0);
+                       } else if (pattern.led_map == "rb") {
+                               ctx.set_source_rgb (0.75, 0, 0.75);
+                       } else if (pattern.led_map == "gb") {
+                               ctx.set_source_rgb (0, 0.75, 0.75);
+                       } else if (pattern.led_map == "rgb") {
+                               ctx.set_source_rgb (0.75, 0.75, 0.75);
+                       } else {
+                               ctx.set_source_rgb (0.66, 0.66, 0.66);
+                       }
+                       ctx.set_line_width (1.0);
+
+                       CommandType type = CommandType.UNKNOWN;
+                       foreach (LedCommandRX51 command in pattern.engine1) {
+                               if (command.type == CommandType.STOP ||
+                                   command.type == CommandType.REPEAT) {
+                                       type = command.type;
+                                       break;
+                               }
+                       }
+
+                       if (type == CommandType.STOP) {
+                               ctx.new_path ();
+
+                               ctx.move_to (x, y);
+                               ctx.line_to (width - 0.5, y);
+
+                               ctx.stroke ();
+                       }
+                       if (type == CommandType.REPEAT && pattern.duration > 0.0) {
+                               ctx.new_path ();
+
+                               for (double offset = pattern.duration; (offset * pps/1000.0) <= width; offset += pattern.duration) {
+                                       ctx.move_to (x, y);
+                                       foreach (LedCommand command in pattern.engine1) {
+                                               x = (command.time + offset) * pps/1000.0;
+                                               y = (255 - command.level) * (height - 1)/255.0;
+                                               if (x >= width)
+                                                       break;
+                                               switch (command.type) {
+                                               case CommandType.RAMP_WAIT:
+                                                       x += command.duration * pps/1000.0;
+                                                       y -= command.steps * (height - 1)/255.0;
+                                                       if (y < 0)
+                                                               y = 0;
+                                                       if (y > (height - 1))
+                                                               y = height - 1;
+                                                       ctx.line_to (x, y);
+                                                       break;
+                                               default:
+                                                       ctx.line_to (x, y);
+                                                       break;
+                                               }
+                                       }
+                               }
+
+                               ctx.stroke ();
+                       }
+                       if (type == CommandType.REPEAT && pattern.duration == 0.0) {
+                               ctx.new_path ();
+
+
+                               ctx.move_to (x, y);
+                               ctx.line_to (width - 0.5, y);
+
+                               ctx.stroke ();
+                       }
+               }
+               return true;
+       }
+
+       public void update () {
+               unowned Gdk.Region region = window.get_clip_region ();
+
+               // redraw the cairo canvas completely by exposing it
+               window.invalidate_region (region, true);
+               window.process_updates (true);
+       }
+}