mirror of
https://github.com/alexkay/spek.git
synced 2025-04-17 00:52:20 +03:00
spek-ruler.cc
This commit is contained in:
parent
95d5c87fd2
commit
f41b33fbac
@ -14,6 +14,8 @@ spek_SOURCES = \
|
||||
spek-platform.hh \
|
||||
spek-preferences.cc \
|
||||
spek-preferences.hh \
|
||||
spek-ruler.cc \
|
||||
spek-ruler.hh \
|
||||
spek-spectrogram.cc \
|
||||
spek-spectrogram.hh \
|
||||
spek-window.cc \
|
||||
|
85
src/spek-ruler.cc
Normal file
85
src/spek-ruler.cc
Normal file
@ -0,0 +1,85 @@
|
||||
/* spek-ruler.cc
|
||||
*
|
||||
* Copyright (C) 2010-2012 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/>.
|
||||
*/
|
||||
|
||||
#include "spek-ruler.hh"
|
||||
|
||||
SpekRuler::SpekRuler(Position pos, wxString sample_label, int *factors, int units, double spacing) :
|
||||
pos(pos), sample_label(sample_label), factors(factors), units(units), spacing(spacing)
|
||||
{
|
||||
}
|
||||
|
||||
void SpekRuler::draw(wxDC& dc)
|
||||
{
|
||||
// Mesure the sample label.
|
||||
wxSize size = dc.GetTextExtent(sample_label);
|
||||
int len = this->pos == TOP || this->pos == BOTTOM ? size.GetWidth() : size.GetHeight();
|
||||
|
||||
// Select the factor to use, we want some space between the labels.
|
||||
int factor = 0;
|
||||
for (int i = 0; factors[i]; ++i) {
|
||||
if (this->measure(factors[i]) >= this->spacing * len) {
|
||||
factor = factors[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the ticks.
|
||||
this->draw_tick(dc, 0);
|
||||
this->draw_tick(dc, units);
|
||||
|
||||
if (factor > 0) {
|
||||
for (int tick = factor; tick < units; tick += factor) {
|
||||
if (this->measure(units - tick) < len * 1.2) {
|
||||
break;
|
||||
}
|
||||
this->draw_tick(dc, tick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpekRuler::draw_tick(wxDC& dc, int tick)
|
||||
{
|
||||
double GAP = 10;
|
||||
double TICK_LEN = 4;
|
||||
|
||||
wxString label = format(tick);
|
||||
double p = place(measure(this->pos == TOP || this->pos == BOTTOM ? tick : this->units - tick));
|
||||
wxSize size = dc.GetTextExtent(label);
|
||||
int w = size.GetWidth();
|
||||
int h = size.GetHeight();
|
||||
|
||||
if (this->pos == TOP) {
|
||||
dc.DrawText(label, p - w / 2, -GAP - h);
|
||||
} else if (this->pos == RIGHT){
|
||||
dc.DrawText(label, GAP, p + h / 4);
|
||||
} else if (this->pos == BOTTOM) {
|
||||
dc.DrawText(label, p - w / 2, GAP + h);
|
||||
} else if (this->pos == LEFT){
|
||||
dc.DrawText(label, -w - GAP, p + h / 4);
|
||||
}
|
||||
|
||||
if (this->pos == TOP) {
|
||||
dc.DrawLine(p, 0, p, -TICK_LEN);
|
||||
} else if (this->pos == RIGHT) {
|
||||
dc.DrawLine(0, p, TICK_LEN, p);
|
||||
} else if (this->pos == BOTTOM) {
|
||||
dc.DrawLine(p, 0, p, TICK_LEN);
|
||||
} else if (this->pos == LEFT) {
|
||||
dc.DrawLine(0, p, -TICK_LEN, p);
|
||||
}
|
||||
}
|
54
src/spek-ruler.hh
Normal file
54
src/spek-ruler.hh
Normal file
@ -0,0 +1,54 @@
|
||||
/* spek-ruler.hh
|
||||
*
|
||||
* Copyright (C) 2010-2012 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/>.
|
||||
*/
|
||||
|
||||
#ifndef SPEK_RULER_HH_
|
||||
#define SPEK_RULER_HH_
|
||||
|
||||
#include <wx/dc.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
class SpekRuler
|
||||
{
|
||||
public:
|
||||
enum Position
|
||||
{
|
||||
TOP,
|
||||
RIGHT,
|
||||
BOTTOM,
|
||||
LEFT
|
||||
};
|
||||
|
||||
SpekRuler(Position pos, wxString sample_label, int *factors, int units, double spacing);
|
||||
|
||||
void draw(wxDC& dc);
|
||||
|
||||
protected:
|
||||
virtual double measure(int unit) = 0;
|
||||
virtual double place(double p) = 0;
|
||||
virtual wxString format(int unit) = 0;
|
||||
|
||||
void draw_tick(wxDC& dc, int tick);
|
||||
|
||||
Position pos;
|
||||
wxString sample_label;
|
||||
int *factors;
|
||||
int units;
|
||||
double spacing;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,123 +0,0 @@
|
||||
/* spek-ruler.vala
|
||||
*
|
||||
* Copyright (C) 2010,2011 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;
|
||||
using Pango;
|
||||
|
||||
namespace Spek {
|
||||
class Ruler : GLib.Object {
|
||||
public enum Position {
|
||||
TOP,
|
||||
RIGHT,
|
||||
BOTTOM,
|
||||
LEFT
|
||||
}
|
||||
|
||||
private Position pos;
|
||||
private string sample_label;
|
||||
private int[] factors;
|
||||
private int units;
|
||||
private double spacing;
|
||||
private Measure measure;
|
||||
private Place place;
|
||||
private FormatTick format_tick;
|
||||
|
||||
public delegate double Measure (int unit);
|
||||
public delegate double Place (double p);
|
||||
public delegate string FormatTick (int unit);
|
||||
|
||||
public Ruler (
|
||||
Position pos, string sample_label,
|
||||
int[] factors, int units, double spacing,
|
||||
Measure measure, Place place, FormatTick format_tick) {
|
||||
this.pos = pos;
|
||||
this.sample_label = sample_label;
|
||||
this.factors = factors;
|
||||
this.units = units;
|
||||
this.spacing = spacing;
|
||||
this.measure = measure;
|
||||
this.place = place;
|
||||
this.format_tick = format_tick;
|
||||
}
|
||||
|
||||
public void draw (Cairo.Context cr, Pango.Layout layout) {
|
||||
// Mesure the sample label.
|
||||
int w, h;
|
||||
layout.set_text (sample_label, -1);
|
||||
layout.get_pixel_size (out w, out h);
|
||||
var size = pos == Position.TOP || pos == Position.BOTTOM ? w : h;
|
||||
|
||||
// Select the factor to use, we want some space between the labels.
|
||||
int factor = 0;
|
||||
foreach (var f in factors) {
|
||||
if (measure (f) >= spacing * size) {
|
||||
factor = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the ticks.
|
||||
int[] ticks = { 0, units };
|
||||
if (factor > 0) {
|
||||
for (var tick = factor; tick < units; tick += factor) {
|
||||
if (measure (units - tick) < size * 1.2) {
|
||||
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 p = place (measure (
|
||||
pos == Position.TOP || pos == Position.BOTTOM
|
||||
? tick : units - tick));
|
||||
layout.set_text (label, -1);
|
||||
layout.get_pixel_size (out w, out h);
|
||||
if (pos == Position.TOP) {
|
||||
cr.move_to (p - w / 2, -GAP - h);
|
||||
} else if (pos == Position.RIGHT){
|
||||
cr.move_to (GAP, p + h / 4);
|
||||
} else if (pos == Position.BOTTOM) {
|
||||
cr.move_to (p - w / 2, GAP + h);
|
||||
} else if (pos == Position.LEFT){
|
||||
cr.move_to (-w - GAP, p + h / 4);
|
||||
}
|
||||
cairo_show_layout_line (cr, layout.get_line (0));
|
||||
if (pos == Position.TOP) {
|
||||
cr.move_to (p, 0);
|
||||
cr.rel_line_to (0, -TICK_LEN);
|
||||
} else if (pos == Position.RIGHT) {
|
||||
cr.move_to (0, p);
|
||||
cr.rel_line_to (TICK_LEN, 0);
|
||||
} else if (pos == Position.BOTTOM) {
|
||||
cr.move_to (p, 0);
|
||||
cr.rel_line_to (0, TICK_LEN);
|
||||
} else if (pos == Position.LEFT) {
|
||||
cr.move_to (0, p);
|
||||
cr.rel_line_to (-TICK_LEN, 0);
|
||||
}
|
||||
cr.stroke ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -36,18 +36,6 @@ namespace Spek {
|
||||
surface.write_to_png (file_name);
|
||||
}
|
||||
|
||||
protected override bool expose_event (EventExpose event) {
|
||||
var window = get_window ();
|
||||
var cr = cairo_create (window);
|
||||
|
||||
// Clip to the exposed area.
|
||||
cr.rectangle (event.area.x, event.area.y, event.area.width, event.area.height);
|
||||
cr.clip ();
|
||||
|
||||
draw (cr);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void draw (Cairo.Context cr) {
|
||||
int text_width, text_height;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user