2 Copyright (C) 2009 Paul Davis
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.
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.
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.
20 #include <gtkmm/stock.h>
21 #include "ardour/session.h"
22 #include "ardour/route_group.h"
23 #include "ardour/route.h"
25 #include "gui_thread.h"
26 #include "route_group_dialog.h"
27 #include "group_tabs.h"
33 using namespace ARDOUR
;
34 using Gtkmm2ext::Keyboard
;
36 GroupTabs::GroupTabs (Editor
* e
)
37 : EditorComponent (e
),
45 GroupTabs::set_session (Session
* s
)
47 EditorComponent::set_session (s
);
50 _session
->RouteGroupChanged
.connect (_session_connections
, invalidator (*this), boost::bind (&GroupTabs::set_dirty
, this), gui_context());
55 /** Handle a size request.
56 * @param req GTK requisition
59 GroupTabs::on_size_request (Gtk::Requisition
*req
)
61 /* Use a dummy, small width and the actual height that we want */
67 GroupTabs::on_button_press_event (GdkEventButton
* ev
)
69 using namespace Menu_Helpers
;
71 double const p
= primary_coordinate (ev
->x
, ev
->y
);
73 list
<Tab
>::iterator prev
;
74 list
<Tab
>::iterator next
;
75 Tab
* t
= click_to_tab (p
, &prev
, &next
);
77 _drag_min
= prev
!= _tabs
.end() ? prev
->to
: 0;
78 _drag_max
= next
!= _tabs
.end() ? next
->from
: extent ();
80 if (ev
->button
== 1) {
85 _dragging_new_tab
= true;
87 if (next
== _tabs
.end()) {
91 list
<Tab
>::iterator j
= _tabs
.insert (next
, n
);
96 _dragging_new_tab
= false;
103 double const h
= (t
->from
+ t
->to
) / 2;
105 _drag_moving
= t
->from
;
107 _drag_offset
= p
- t
->from
;
109 _drag_moving
= t
->to
;
110 _drag_fixed
= t
->from
;
111 _drag_offset
= p
- t
->to
;
114 } else if (ev
->button
== 3) {
116 RouteGroup
* g
= t
? t
->group
: 0;
117 Menu
* m
= get_menu (g
);
119 m
->popup (ev
->button
, ev
->time
);
129 GroupTabs::on_motion_notify_event (GdkEventMotion
* ev
)
131 if (_dragging
== 0) {
135 double const p
= primary_coordinate (ev
->x
, ev
->y
);
137 if (p
!= _drag_first
) {
141 _drag_moving
= p
- _drag_offset
;
143 _dragging
->from
= min (_drag_moving
, _drag_fixed
);
144 _dragging
->to
= max (_drag_moving
, _drag_fixed
);
146 _dragging
->from
= max (_dragging
->from
, _drag_min
);
147 _dragging
->to
= min (_dragging
->to
, _drag_max
);
157 GroupTabs::on_button_release_event (GdkEventButton
* ev
)
159 if (_dragging
== 0) {
165 if (_dragging
->group
) {
167 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
170 RouteGroupDialog
d (_dragging
->group
, Gtk::Stock::APPLY
);
175 /* toggle active state */
176 _dragging
->group
->set_active (!_dragging
->group
->is_active (), this);
183 RouteList routes
= routes_for_tab (_dragging
);
185 if (!routes
.empty()) {
186 if (_dragging_new_tab
) {
187 RouteGroup
* g
= new_route_group ();
189 for (RouteList::iterator i
= routes
.begin(); i
!= routes
.end(); ++i
) {
194 boost::shared_ptr
<RouteList
> r
= _session
->get_routes ();
195 for (RouteList::iterator i
= r
->begin(); i
!= r
->end(); ++i
) {
197 if (find (routes
.begin(), routes
.end(), *i
) == routes
.end()) {
198 /* this route is not on the list of those that should be in _dragging's group */
199 if ((*i
)->route_group() == _dragging
->group
) {
200 _dragging
->group
->remove (*i
);
203 _dragging
->group
->add (*i
);
219 GroupTabs::render (cairo_t
* cr
)
221 if (_dragging
== 0) {
222 _tabs
= compute_tabs ();
227 cairo_set_source_rgb (cr
, 0, 0, 0);
228 cairo_rectangle (cr
, 0, 0, _width
, _height
);
233 for (list
<Tab
>::const_iterator i
= _tabs
.begin(); i
!= _tabs
.end(); ++i
) {
239 /** Convert a click position to a tab.
240 * @param c Click position.
241 * @param prev Filled in with the previous tab to the click, or 0.
242 * @param next Filled in with the next tab after the click, or 0.
243 * @return Tab under the click, or 0.
247 GroupTabs::click_to_tab (double c
, list
<Tab
>::iterator
* prev
, list
<Tab
>::iterator
* next
)
249 *prev
= *next
= _tabs
.end ();
252 list
<Tab
>::iterator i
= _tabs
.begin ();
253 while (i
!= _tabs
.end()) {
265 if (i
->from
<= c
&& c
< i
->to
) {
272 if (i
!= _tabs
.end()) {