merge with master and fix 2 conflicts
[ardour.git] / gtk2_ardour / tempo_lines.cc
1 /*
2     Copyright (C) 2002-2007 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include "canvas/line.h"
21 #include "canvas/canvas.h"
22 #include "canvas/debug.h"
23 #include "tempo_lines.h"
24 #include "ardour_ui.h"
25
26 using namespace std;
27
28 TempoLines::TempoLines (ArdourCanvas::Canvas& canvas, ArdourCanvas::Group* group, double h)
29         : _canvas (canvas)
30         , _group (group)
31         , _height (h)
32 {
33 }
34
35 void
36 TempoLines::tempo_map_changed()
37 {
38         /* remove all lines from the group, put them in the cache (to avoid
39          * unnecessary object destruction+construction later), and clear _lines
40          */
41          
42         _group->clear ();
43         _cache.insert (_cache.end(), _lines.begin(), _lines.end());
44         _lines.clear ();
45 }
46
47 void
48 TempoLines::show ()
49 {
50         _group->show ();
51 }
52
53 void
54 TempoLines::hide ()
55 {
56         _group->hide ();
57 }
58
59 void
60 TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin, 
61                   const ARDOUR::TempoMap::BBTPointList::const_iterator& end, 
62                   double samples_per_pixel)
63 {
64         ARDOUR::TempoMap::BBTPointList::const_iterator i;
65         ArdourCanvas::Rect const visible = _canvas.visible_area ();
66         double  beat_density;
67
68         uint32_t beats = 0;
69         uint32_t bars = 0;
70         uint32_t color;
71
72         /* get the first bar spacing */
73
74         i = end;
75         i--;
76         bars = (*i).bar - (*begin).bar; 
77         beats = distance (begin, end) - bars;
78
79         beat_density = (beats * 10.0f) / visible.width ();
80
81         if (beat_density > 4.0f) {
82                 /* if the lines are too close together, they become useless */
83                 tempo_map_changed();
84                 return;
85         }
86
87         tempo_map_changed ();
88
89         for (i = begin; i != end; ++i) {
90
91                 if ((*i).is_bar()) {
92                         color = ARDOUR_UI::config()->get_canvasvar_MeasureLineBar();
93                 } else {
94                         if (beat_density > 2.0) {
95                                 continue; /* only draw beat lines if the gaps between beats are large. */
96                         }
97                         color = ARDOUR_UI::config()->get_canvasvar_MeasureLineBeat();
98                 }
99
100                 ArdourCanvas::Coord xpos = rint(((framepos_t)(*i).frame) / (double)samples_per_pixel);
101
102                 ArdourCanvas::Line* line;
103
104                 if (!_cache.empty()) {
105                         line = _cache.back ();
106                         _cache.pop_back ();
107                         line->reparent (_group);
108                 } else {
109                         line = new ArdourCanvas::Line (_group);
110                         CANVAS_DEBUG_NAME (line, "tempo measure line");
111                         line->set_ignore_events (true);
112                 }
113
114                 /* move to 0.5 offset to ensure single pixel lines (see Cairo
115                  * FAQ for info on why we do this).
116                  */
117
118                 line->set_x0 (xpos + 0.5);
119                 line->set_x1 (xpos + 0.5);
120                 line->set_y0 (0.0);
121                 line->set_y1 (_height);
122                 line->set_outline_color (color);
123                 line->show ();
124         }
125 }
126