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