Give route groups their own colour, settable from the route
[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 #include "editor_routes.h"
27 #include "i18n.h"
28
29 using namespace std;
30 using namespace ARDOUR;
31
32 EditorGroupTabs::EditorGroupTabs (Editor* e)
33         : EditorComponent (e)
34 {
35
36 }
37
38 list<GroupTabs::Tab>
39 EditorGroupTabs::compute_tabs () const
40 {
41         list<Tab> tabs;
42
43         Tab tab;
44         tab.from = 0;
45         tab.group = 0;
46
47         int32_t y = 0;
48         for (TrackViewList::iterator i = _editor->track_views.begin(); i != _editor->track_views.end(); ++i) {
49
50                 if ((*i)->marked_for_display() == false) {
51                         continue;
52                 }
53
54                 RouteGroup* g = (*i)->route_group ();
55
56                 if (g != tab.group) {
57                         if (tab.group) {
58                                 tab.to = y;
59                                 tabs.push_back (tab);
60                         }
61
62                         tab.from = y;
63                         tab.group = g;
64                         if (g) {
65                                 tab.color = group_color (g);
66                         }
67                 }
68
69                 y += (*i)->effective_height ();
70         }
71
72         if (tab.group) {
73                 tab.to = y;
74                 tabs.push_back (tab);
75         }
76
77         return tabs;
78 }
79
80 void
81 EditorGroupTabs::draw_tab (cairo_t* cr, Tab const & tab) const
82 {
83         double const arc_radius = _width;
84
85         if (tab.group && tab.group->is_active()) {
86                 cairo_set_source_rgba (cr, tab.color.get_red_p (), tab.color.get_green_p (), tab.color.get_blue_p (), 1);
87         } else {
88                 cairo_set_source_rgba (cr, 1, 1, 1, 0.2);
89         }
90
91         cairo_move_to (cr, 0, tab.from + arc_radius);
92         cairo_arc (cr, _width, tab.from + arc_radius, arc_radius, M_PI, 3 * M_PI / 2);
93         cairo_line_to (cr, _width, tab.to);
94         cairo_arc (cr, _width, tab.to - arc_radius, arc_radius, M_PI / 2, M_PI);
95         cairo_line_to (cr, 0, tab.from + arc_radius);
96         cairo_fill (cr);
97
98         if (tab.group) {
99                 pair<string, double> const f = fit_to_pixels (cr, tab.group->name(), tab.to - tab.from - arc_radius * 2);
100
101                 cairo_text_extents_t ext;
102                 cairo_text_extents (cr, tab.group->name().c_str(), &ext);
103
104                 cairo_set_source_rgb (cr, 1, 1, 1);
105                 cairo_move_to (cr, _width - ext.height / 2, tab.from + (f.second + tab.to - tab.from) / 2);
106                 cairo_save (cr);
107                 cairo_rotate (cr, - M_PI / 2);
108                 cairo_show_text (cr, f.first.c_str());
109                 cairo_restore (cr);
110         }
111 }
112
113 double
114 EditorGroupTabs::primary_coordinate (double, double y) const
115 {
116         return y;
117 }
118
119 RouteList
120 EditorGroupTabs::routes_for_tab (Tab const * t) const
121 {
122         RouteList routes;
123         int32_t y = 0;
124
125         for (TrackViewList::iterator i = _editor->track_views.begin(); i != _editor->track_views.end(); ++i) {
126
127                 if ((*i)->marked_for_display() == false) {
128                         continue;
129                 }
130
131                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
132                 if (rtv) {
133
134                         if (y >= t->to) {
135                                 /* tab finishes before this track starts */
136                                 break;
137                         }
138
139                         double const h = y + (*i)->effective_height() / 2;
140
141                         if (t->from < h && t->to > h) {
142                                 routes.push_back (rtv->route ());
143                         }
144                 }
145
146                 y += (*i)->effective_height ();
147         }
148
149         return routes;
150 }
151
152
153 void
154 EditorGroupTabs::add_menu_items (Gtk::Menu* m, RouteGroup* g)
155 {
156         using namespace Gtk::Menu_Helpers;
157
158         if (g) {
159                 MenuList& items = m->items ();
160                 items.push_back (MenuElem (_("Fit to Window"), sigc::bind (sigc::mem_fun (*_editor, &Editor::fit_route_group), g)));
161         }
162 }
163
164 PBD::PropertyList
165 EditorGroupTabs::default_properties () const
166 {
167         PBD::PropertyList plist;
168
169         plist.add (Properties::active, true);
170         plist.add (Properties::mute, true);
171         plist.add (Properties::solo, true);
172         plist.add (Properties::recenable, true);
173         plist.add (Properties::edit, true);
174
175         return plist;
176 }
177
178 string
179 EditorGroupTabs::order_key () const
180 {
181         return X_("editor");
182 }
183
184 RouteList
185 EditorGroupTabs::selected_routes () const
186 {
187         RouteList rl;
188
189         for (TrackSelection::iterator i = _editor->get_selection().tracks.begin(); i != _editor->get_selection().tracks.end(); ++i) {
190                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
191                 if (rtv) {
192                         rl.push_back (rtv->route());
193                 }
194         }
195
196         return rl;
197 }
198
199 void
200 EditorGroupTabs::sync_order_keys ()
201 {
202         _editor->_routes->sync_order_keys ("");
203 }