commit 71a8cccb4b7c8ad33b2c7b998716d03839f331b6
parent 3feb64543e97ca48c37c57aa81c94509fff0f549
Author: Alexander Kojevnikov <alexander@kojevnikov.com>
Date: Sun, 16 May 2010 20:51:55 +1000
Factor out the ruler code
Diffstat:
3 files changed, 99 insertions(+), 45 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am
@@ -2,6 +2,7 @@ bin_PROGRAMS = spek
spek_SOURCES = \
spek.vala \
+ spek-ruler.vala \
spek-source.vala \
spek-spectrogram.vala \
spek-window.vala
diff --git a/src/spek-ruler.vala b/src/spek-ruler.vala
@@ -0,0 +1,86 @@
+/* spek-spectrogram.vala
+ *
+ * Copyright (C) 2010 Alexander Kojevnikov <alexander@kojevnikov.com>
+ *
+ * Spek 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.
+ *
+ * Spek 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 Spek. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using Cairo;
+
+namespace Spek {
+ class Ruler : GLib.Object {
+
+ private string sample_label;
+ private int[] factors;
+ private int units;
+ private UnitToPixel unit_to_pixel;
+ private FormatTick format_tick;
+
+ public delegate double UnitToPixel (int unit);
+ public delegate string FormatTick (int unit);
+
+ public Ruler (
+ string sample_label, int[] factors, int units,
+ UnitToPixel unit_to_pixel, FormatTick format_tick) {
+ this.sample_label = sample_label;
+ this.factors = factors;
+ this.units = units;
+ this.unit_to_pixel = unit_to_pixel;
+ this.format_tick = format_tick;
+ }
+
+ public void draw (Context cr) {
+ // Mesure the sample label.
+ TextExtents ext;
+ cr.text_extents (sample_label, out ext);
+ var label_width = ext.width;
+
+ // Select the factor to use, we want some space between the labels.
+ int factor = 0;
+ foreach (var f in factors) {
+ if (unit_to_pixel (f) >= 1.5 * label_width) {
+ factor = f;
+ break;
+ }
+ }
+
+ // Add the ticks.
+ int[] ticks = { 0, units };
+ if (factor > 0) {
+ for (var tick = factor; tick < units; tick += factor) {
+ if (unit_to_pixel (units - tick) < label_width) {
+ break;
+ }
+ ticks += tick;
+ }
+ // TODO: `ticks = ticks[0:-1]` crashes, file a bug.
+ }
+
+ // Draw the ticks.
+ double GAP = 10;
+ double TICK_LEN = 4;
+ foreach (var tick in ticks) {
+ var label = format_tick (tick);
+ var pos = unit_to_pixel (tick);
+ cr.text_extents (label, out ext);
+ // TODO: use font measurements instead ext.height
+ cr.move_to (pos - ext.width / 2, GAP + ext.height);
+ cr.show_text (label);
+ cr.move_to (pos, 0);
+ cr.rel_line_to (0, TICK_LEN);
+ cr.stroke ();
+ }
+ }
+ }
+}
+\ No newline at end of file
diff --git a/src/spek-spectrogram.vala b/src/spek-spectrogram.vala
@@ -123,46 +123,17 @@ namespace Spek {
cr.select_font_face ("sans-serif", FontSlant.NORMAL, FontWeight.NORMAL);
cr.set_font_size (10.0);
- // Mesure the label text.
- TextExtents ext;
- cr.text_extents ("00:00", out ext);
- double label_width = ext.width;
-
- // Select the factor to use, we want some space between the labels.
- int duration_seconds = (int) (source.duration / 1000000000);
- int[] time_factors = {1, 2, 5, 10, 20, 30, 1*60, 2*60, 5*60, 10*60, 20*60, 30*60};
- int time_factor = 0;
- foreach (var factor in time_factors) {
- if (time_to_px (factor, w, duration_seconds) >= 1.5 * label_width) {
- time_factor = factor;
- break;
- }
- }
-
- // Add the ticks.
- int[] ticks = { 0, duration_seconds };
- if (time_factor > 0) {
- for (var tick = time_factor; tick < duration_seconds; tick += time_factor) {
- if (time_to_px (duration_seconds - tick, w, duration_seconds) < label_width) {
- break;
- }
- ticks += tick;
- }
- // TODO: `ticks = ticks[0:-1]` crashes, file a bug.
- }
-
- // Draw the ticks.
- foreach (var tick in ticks) {
- var label = "%d:%02d".printf (tick / 60, tick % 60);
- var pos = PADDING + time_to_px (tick, w, duration_seconds);
- cr.text_extents (label, out ext);
- // TODO: use font measurements instead ext.height
- cr.move_to (pos - ext.width / 2, h - PADDING + GAP + ext.height);
- cr.show_text (label);
- cr.move_to (pos, h - PADDING);
- cr.rel_line_to (0, 4);
- cr.stroke ();
- }
+ // Time ruler.
+ var duration_seconds = (int) (source.duration / 1000000000);
+ var time_ruler = new Ruler (
+ "00:00",
+ {1, 2, 5, 10, 20, 30, 1*60, 2*60, 5*60, 10*60, 20*60, 30*60},
+ duration_seconds,
+ unit => (w - 2 * PADDING) * unit / duration_seconds,
+ unit => "%d:%02d".printf (unit / 60, unit % 60));
+ cr.translate (PADDING, h - PADDING);
+ time_ruler.draw (cr);
+ cr.identity_matrix ();
}
// Border around the spectrogram.
@@ -180,11 +151,6 @@ namespace Spek {
cr.identity_matrix ();
}
- // TODO: factor out the ruler logic and pass this as an anonymous method.
- private double time_to_px (int time, double w, int duration_seconds) {
- return (w - 2 * PADDING) * time / duration_seconds;
- }
-
private void put_pixel (ImageSurface surface, int x, int y, uint32 color) {
var i = y * surface.get_stride () + x * 4;
unowned uchar[] data = surface.get_data ();