--- /dev/null
+/* 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);
+ }
+}