/*
- Copyright (C) 2002-2007 Paul Davis
+ Copyright (C) 2002-2007 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*/
-#include <libgnomecanvasmm/canvas.h>
-#include <libgnomecanvasmm/group.h>
+#include "canvas/line.h"
+#include "canvas/canvas.h"
+#include "canvas/debug.h"
#include "tempo_lines.h"
#include "ardour_ui.h"
-ArdourCanvas::SimpleLine *
-TempoLines::get_line ()
+using namespace std;
+
+TempoLines::TempoLines (ArdourCanvas::Canvas& canvas, ArdourCanvas::Group* group, double screen_height)
+ : _canvas (canvas)
+ , _group (group)
+ , _height (screen_height)
{
- ArdourCanvas::SimpleLine *line;
-
- if (_free_lines.empty()) {
- line = new ArdourCanvas::SimpleLine (*_group);
- _used_lines.push_back (line);
- } else {
- line = _free_lines.front();
- _free_lines.erase (_free_lines.begin());
- _used_lines.push_back (line);
- }
+}
- return line;
+void
+TempoLines::tempo_map_changed()
+{
+ /* remove all lines from the group, put them in the cache (to avoid
+ * unnecessary object destruction+construction later), and clear _lines
+ */
+
+ _group->clear ();
+ _cache.insert (_cache.end(), _lines.begin(), _lines.end());
+ _lines.clear ();
}
+void
+TempoLines::show ()
+{
+ _group->show ();
+}
void
TempoLines::hide ()
{
- for (Lines::iterator i = _used_lines.begin(); i != _used_lines.end(); ++i) {
- (*i)->hide();
- _free_lines.push_back (*i);
- }
- _used_lines.clear ();
+ _group->hide ();
}
-
void
-TempoLines::draw (ARDOUR::TempoMap::BBTPointList& points, double frames_per_unit)
+TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
+ const ARDOUR::TempoMap::BBTPointList::const_iterator& end,
+ double samples_per_pixel)
{
- ARDOUR::TempoMap::BBTPointList::iterator i;
- ArdourCanvas::SimpleLine *line;
- gdouble xpos;
- double who_cares;
- double x1, x2, y1, y2, beat_density;
+ ARDOUR::TempoMap::BBTPointList::const_iterator i;
+ ArdourCanvas::Rect const visible = _canvas.visible_area ();
+ double beat_density;
uint32_t beats = 0;
uint32_t bars = 0;
uint32_t color;
- _canvas.get_scroll_region (x1, y1, x2, who_cares);
- _canvas.root()->get_bounds(who_cares, who_cares, who_cares, y2);
-
/* get the first bar spacing */
- i = points.end();
+ i = end;
i--;
- bars = (*i).bar - (*points.begin()).bar;
- beats = points.size() - bars;
+ bars = (*i).bar - (*begin).bar;
+ beats = distance (begin, end) - bars;
- beat_density = (beats * 10.0f) / _canvas.get_width ();
+ beat_density = (beats * 10.0f) / visible.width ();
if (beat_density > 4.0f) {
- /* if the lines are too close together, they become useless
- */
+ /* if the lines are too close together, they become useless */
+ tempo_map_changed();
return;
}
- for (i = points.begin(); i != points.end(); ++i) {
-
- switch ((*i).type) {
- case ARDOUR::TempoMap::Bar:
- break;
+ tempo_map_changed ();
- case ARDOUR::TempoMap::Beat:
-
- if ((*i).beat == 1) {
- color = ARDOUR_UI::config()->canvasvar_MeasureLineBar.get();
- } else {
- color = ARDOUR_UI::config()->canvasvar_MeasureLineBeat.get();
+ for (i = begin; i != end; ++i) {
- if (beat_density > 2.0) {
- /* only draw beat lines if the gaps between beats are large.
- */
- break;
- }
+ if ((*i).is_bar()) {
+ color = ARDOUR_UI::config()->get_canvasvar_MeasureLineBar();
+ } else {
+ if (beat_density > 2.0) {
+ continue; /* only draw beat lines if the gaps between beats are large. */
}
+ color = ARDOUR_UI::config()->get_canvasvar_MeasureLineBeat();
+ }
+
+ ArdourCanvas::Coord xpos = rint(((framepos_t)(*i).frame) / (double)samples_per_pixel);
- xpos = rint(((nframes64_t)(*i).frame) / (double)frames_per_unit);
- line = get_line ();
- line->property_x1() = xpos;
- line->property_x2() = xpos;
- line->property_y2() = y2;
- line->property_color_rgba() = color;
- //line->raise_to_top();
- line->show();
- break;
+ ArdourCanvas::Line* line;
+
+ if (!_cache.empty()) {
+ line = _cache.back ();
+ _cache.pop_back ();
+ line->reparent (_group);
+ } else {
+ line = new ArdourCanvas::Line (_group);
+ CANVAS_DEBUG_NAME (line, "tempo measure line");
+ line->set_ignore_events (true);
}
+
+ /* move to 0.5 offset to ensure single pixel lines (see Cairo
+ * FAQ for info on why we do this).
+ */
+
+ line->set_x0 (xpos + 0.5);
+ line->set_x1 (xpos + 0.5);
+ line->set_y0 (0.0);
+ line->set_y1 (_height);
+ line->set_outline_color (color);
+ line->show ();
}
}
+