Fix crash when setting loop or punch range after creating a new session (and probably...
[ardour.git] / gtk2_ardour / editor_group_tabs.cc
1 /*
2     Copyright (C) 2009 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 "ardour/route_group.h"
21 #include "editor_group_tabs.h"
22 #include "editor.h"
23 #include "route_time_axis.h"
24 #include "utils.h"
25 #include "editor_route_groups.h"
26
27 using namespace std;
28 using namespace ARDOUR;
29
30 EditorGroupTabs::EditorGroupTabs (Editor* e)
31         : GroupTabs (e)
32 {
33
34 }
35
36 list<GroupTabs::Tab>
37 EditorGroupTabs::compute_tabs () const
38 {
39         list<Tab> tabs;
40
41         Tab tab;
42         tab.from = 0;
43         tab.group = 0;
44
45         int32_t y = 0;
46         for (TrackViewList::iterator i = _editor->track_views.begin(); i != _editor->track_views.end(); ++i) {
47
48                 if ((*i)->marked_for_display() == false) {
49                         continue;
50                 }
51
52                 RouteGroup* g = (*i)->route_group ();
53
54                 if (g != tab.group) {
55                         if (tab.group) {
56                                 tab.to = y;
57                                 tabs.push_back (tab);
58                         }
59
60                         tab.from = y;
61                         tab.group = g;
62                         tab.colour = (*i)->color ();
63                 }
64
65                 y += (*i)->effective_height ();
66         }
67
68         if (tab.group) {
69                 tab.to = y;
70                 tabs.push_back (tab);
71         }
72
73         return tabs;
74 }
75
76 void
77 EditorGroupTabs::draw_tab (cairo_t* cr, Tab const & tab) const
78 {
79         double const arc_radius = _width;
80
81         if (tab.group && tab.group->is_active()) {
82                 cairo_set_source_rgba (cr, tab.colour.get_red_p (), tab.colour.get_green_p (), tab.colour.get_blue_p (), 1);
83         } else {
84                 cairo_set_source_rgba (cr, 1, 1, 1, 0.2);
85         }
86         
87         cairo_move_to (cr, 0, tab.from + arc_radius);
88         cairo_arc (cr, _width, tab.from + arc_radius, arc_radius, M_PI, 3 * M_PI / 2);
89         cairo_line_to (cr, _width, tab.to);
90         cairo_arc (cr, _width, tab.to - arc_radius, arc_radius, M_PI / 2, M_PI);
91         cairo_line_to (cr, 0, tab.from + arc_radius);
92         cairo_fill (cr);
93
94         if (tab.group) {
95                 pair<string, double> const f = fit_to_pixels (cr, tab.group->name(), tab.to - tab.from - arc_radius * 2);
96                 
97                 cairo_text_extents_t ext;
98                 cairo_text_extents (cr, tab.group->name().c_str(), &ext);
99                 
100                 cairo_set_source_rgb (cr, 1, 1, 1);
101                 cairo_move_to (cr, _width - ext.height / 2, tab.from + (f.second + tab.to - tab.from) / 2);
102                 cairo_save (cr);
103                 cairo_rotate (cr, - M_PI / 2);
104                 cairo_show_text (cr, f.first.c_str());
105                 cairo_restore (cr);
106         }
107 }
108
109 double
110 EditorGroupTabs::primary_coordinate (double, double y) const
111 {
112         return y;
113 }
114
115 RouteList
116 EditorGroupTabs::routes_for_tab (Tab const * t) const
117 {
118         RouteList routes;
119         int32_t y = 0;
120         
121         for (TrackViewList::iterator i = _editor->track_views.begin(); i != _editor->track_views.end(); ++i) {
122
123                 if ((*i)->marked_for_display() == false) {
124                         continue;
125                 }
126
127                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
128                 if (rtv) {
129
130                         if (y >= t->to) {
131                                 /* tab finishes before this track starts */
132                                 break;
133                         }
134
135                         double const h = y + (*i)->effective_height() / 2;
136
137                         if (t->from < h && t->to > h) {
138                                 routes.push_back (rtv->route ());
139                         }
140                 }
141
142                 y += (*i)->effective_height ();
143         }
144
145         return routes;
146 }
147
148
149 Gtk::Menu*
150 EditorGroupTabs::get_menu (RouteGroup *g)
151 {
152         return _editor->_route_groups->menu (g);
153 }
154
155 ARDOUR::RouteGroup *
156 EditorGroupTabs::new_route_group () const
157 {
158         return _editor->_route_groups->new_route_group ();
159 }