Merge branch 'windows' into windows+cc
[ardour.git] / libs / canvas / line_set.cc
1 /*
2     Copyright (C) 2011-2013 Paul Davis
3     Author: Carl Hetherington <cth@carlh.net>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include "canvas/line_set.h"
21 #include "canvas/utils.h"
22
23 using namespace std;
24 using namespace ArdourCanvas;
25
26 /* XXX: hard-wired to horizontal only */
27
28 class LineSorter {
29 public:
30         bool operator() (LineSet::Line& a, LineSet::Line& b) {
31                 return a.y < b.y;
32         }
33 };
34
35 LineSet::LineSet (Group* parent)
36         : Item (parent)
37         , _height (0)
38 {
39
40 }
41
42
43 void
44 LineSet::compute_bounding_box () const
45 {
46         if (_lines.empty ()) {
47                 _bounding_box = boost::optional<Rect> ();
48                 _bounding_box_dirty = false;
49                 return;
50         }
51         
52         _bounding_box = Rect (0, _lines.front().y, COORD_MAX, min (_height, _lines.back().y));
53         _bounding_box_dirty = false;
54 }
55
56 void
57 LineSet::set_height (Distance height)
58 {
59         begin_change ();
60
61         _height = height;
62
63         _bounding_box_dirty = true;
64         end_change ();
65 }
66
67 void
68 LineSet::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
69 {
70         for (list<Line>::const_iterator i = _lines.begin(); i != _lines.end(); ++i) {
71                 if (i->y > area.y1) {
72                         break;
73                 } else if (i->y > area.y0) {
74                         set_source_rgba (context, i->color);
75                         context->set_line_width (i->width);
76                         Duple p0 = item_to_window (Duple (area.x0, i->y));
77                         Duple p1 = item_to_window (Duple (area.x1, i->y));
78                         context->move_to (p0.x, p0.y);
79                         context->line_to (p1.x, p1.y);
80                         context->stroke ();
81                 }
82         }
83 }
84
85 void
86 LineSet::add (Coord y, Distance width, Color color)
87 {
88         begin_change ();
89         
90         _lines.push_back (Line (y, width, color));
91         _lines.sort (LineSorter ());
92
93         _bounding_box_dirty = true;
94         end_change ();
95 }
96
97 void
98 LineSet::clear ()
99 {
100         begin_change ();
101         _lines.clear ();
102         _bounding_box_dirty = true;
103         end_change ();
104 }