mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 14:54:56 +01:00
Various tweaks to group tabs, the main upshot of which is that you can start
a drag in an empty part of the group tab display and drag out a new route group. git-svn-id: svn://localhost/ardour2/branches/3.0@6249 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
35d86425ba
commit
759267af15
9 changed files with 224 additions and 176 deletions
|
|
@ -54,14 +54,12 @@ EditorGroupTabs::compute_tabs () const
|
||||||
if (g != tab.group) {
|
if (g != tab.group) {
|
||||||
if (tab.group) {
|
if (tab.group) {
|
||||||
tab.to = y;
|
tab.to = y;
|
||||||
tab.last_ui_size = (*i)->effective_height ();
|
|
||||||
tabs.push_back (tab);
|
tabs.push_back (tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
tab.from = y;
|
tab.from = y;
|
||||||
tab.group = g;
|
tab.group = g;
|
||||||
tab.colour = (*i)->color ();
|
tab.colour = (*i)->color ();
|
||||||
tab.first_ui_size = (*i)->effective_height ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
y += (*i)->effective_height ();
|
y += (*i)->effective_height ();
|
||||||
|
|
@ -80,12 +78,12 @@ EditorGroupTabs::draw_tab (cairo_t* cr, Tab const & tab) const
|
||||||
{
|
{
|
||||||
double const arc_radius = _width;
|
double const arc_radius = _width;
|
||||||
|
|
||||||
if (tab.group->is_active()) {
|
if (tab.group && tab.group->is_active()) {
|
||||||
cairo_set_source_rgba (cr, tab.colour.get_red_p (), tab.colour.get_green_p (), tab.colour.get_blue_p (), 1);
|
cairo_set_source_rgba (cr, tab.colour.get_red_p (), tab.colour.get_green_p (), tab.colour.get_blue_p (), 1);
|
||||||
} else {
|
} else {
|
||||||
cairo_set_source_rgba (cr, 1, 1, 1, 0.2);
|
cairo_set_source_rgba (cr, 1, 1, 1, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_move_to (cr, 0, tab.from + arc_radius);
|
cairo_move_to (cr, 0, tab.from + arc_radius);
|
||||||
cairo_arc (cr, _width, tab.from + arc_radius, arc_radius, M_PI, 3 * M_PI / 2);
|
cairo_arc (cr, _width, tab.from + arc_radius, arc_radius, M_PI, 3 * M_PI / 2);
|
||||||
cairo_line_to (cr, _width, tab.to);
|
cairo_line_to (cr, _width, tab.to);
|
||||||
|
|
@ -93,17 +91,19 @@ EditorGroupTabs::draw_tab (cairo_t* cr, Tab const & tab) const
|
||||||
cairo_line_to (cr, 0, tab.from + arc_radius);
|
cairo_line_to (cr, 0, tab.from + arc_radius);
|
||||||
cairo_fill (cr);
|
cairo_fill (cr);
|
||||||
|
|
||||||
pair<string, double> const f = fit_to_pixels (cr, tab.group->name(), tab.to - tab.from - arc_radius * 2);
|
if (tab.group) {
|
||||||
|
pair<string, double> const f = fit_to_pixels (cr, tab.group->name(), tab.to - tab.from - arc_radius * 2);
|
||||||
cairo_text_extents_t ext;
|
|
||||||
cairo_text_extents (cr, tab.group->name().c_str(), &ext);
|
cairo_text_extents_t ext;
|
||||||
|
cairo_text_extents (cr, tab.group->name().c_str(), &ext);
|
||||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
|
||||||
cairo_move_to (cr, _width - ext.height / 2, tab.from + (f.second + tab.to - tab.from) / 2);
|
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||||
cairo_save (cr);
|
cairo_move_to (cr, _width - ext.height / 2, tab.from + (f.second + tab.to - tab.from) / 2);
|
||||||
cairo_rotate (cr, - M_PI / 2);
|
cairo_save (cr);
|
||||||
cairo_show_text (cr, f.first.c_str());
|
cairo_rotate (cr, - M_PI / 2);
|
||||||
cairo_restore (cr);
|
cairo_show_text (cr, f.first.c_str());
|
||||||
|
cairo_restore (cr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
|
|
@ -112,12 +112,12 @@ EditorGroupTabs::primary_coordinate (double, double y) const
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
RouteList
|
||||||
EditorGroupTabs::reflect_tabs (list<Tab> const & tabs)
|
EditorGroupTabs::routes_for_tab (Tab const * t) const
|
||||||
{
|
{
|
||||||
list<Tab>::const_iterator j = tabs.begin ();
|
RouteList routes;
|
||||||
|
|
||||||
int32_t y = 0;
|
int32_t y = 0;
|
||||||
|
|
||||||
for (Editor::TrackViewList::iterator i = _editor->track_views.begin(); i != _editor->track_views.end(); ++i) {
|
for (Editor::TrackViewList::iterator i = _editor->track_views.begin(); i != _editor->track_views.end(); ++i) {
|
||||||
|
|
||||||
if ((*i)->marked_for_display() == false) {
|
if ((*i)->marked_for_display() == false) {
|
||||||
|
|
@ -127,31 +127,22 @@ EditorGroupTabs::reflect_tabs (list<Tab> const & tabs)
|
||||||
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
|
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
|
||||||
if (rtv) {
|
if (rtv) {
|
||||||
|
|
||||||
if (j == tabs.end()) {
|
if (y >= t->to) {
|
||||||
|
/* tab finishes before this track starts */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* already run out of tabs, so no edit group */
|
double const h = y + (*i)->effective_height() / 2;
|
||||||
rtv->route()->set_route_group (0, this);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (y >= j->to) {
|
|
||||||
/* this tab finishes before this track starts, so onto the next tab */
|
|
||||||
++j;
|
|
||||||
}
|
|
||||||
|
|
||||||
double const h = y + (*i)->effective_height() / 2;
|
|
||||||
|
|
||||||
if (j->from < h && j->to > h) {
|
|
||||||
rtv->route()->set_route_group (j->group, this);
|
|
||||||
} else {
|
|
||||||
rtv->route()->set_route_group (0, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (t->from < h && t->to > h) {
|
||||||
|
routes.push_back (rtv->route ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
y += (*i)->effective_height ();
|
y += (*i)->effective_height ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return routes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -160,3 +151,9 @@ EditorGroupTabs::get_menu (RouteGroup *g)
|
||||||
{
|
{
|
||||||
return _editor->_route_groups->menu (g);
|
return _editor->_route_groups->menu (g);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ARDOUR::RouteGroup *
|
||||||
|
EditorGroupTabs::new_route_group () const
|
||||||
|
{
|
||||||
|
return _editor->_route_groups->new_route_group ();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,10 @@ private:
|
||||||
std::list<Tab> compute_tabs () const;
|
std::list<Tab> compute_tabs () const;
|
||||||
void draw_tab (cairo_t *, Tab const &) const;
|
void draw_tab (cairo_t *, Tab const &) const;
|
||||||
double primary_coordinate (double, double) const;
|
double primary_coordinate (double, double) const;
|
||||||
void reflect_tabs (std::list<Tab> const &);
|
ARDOUR::RouteList routes_for_tab (Tab const *) const;
|
||||||
double extent () const {
|
double extent () const {
|
||||||
return _height;
|
return _height;
|
||||||
}
|
}
|
||||||
Gtk::Menu* get_menu (ARDOUR::RouteGroup* g);
|
Gtk::Menu* get_menu (ARDOUR::RouteGroup* g);
|
||||||
|
ARDOUR::RouteGroup* new_route_group () const;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ EditorRouteGroups::EditorRouteGroups (Editor* e)
|
||||||
w->show();
|
w->show();
|
||||||
remove_button->add (*w);
|
remove_button->add (*w);
|
||||||
|
|
||||||
add_button->signal_clicked().connect (mem_fun (*this, &EditorRouteGroups::new_route_group));
|
add_button->signal_clicked().connect (hide_return (mem_fun (*this, &EditorRouteGroups::new_route_group)));
|
||||||
remove_button->signal_clicked().connect (mem_fun (*this, &EditorRouteGroups::remove_selected));
|
remove_button->signal_clicked().connect (mem_fun (*this, &EditorRouteGroups::remove_selected));
|
||||||
|
|
||||||
button_box->pack_start (*add_button);
|
button_box->pack_start (*add_button);
|
||||||
|
|
@ -182,7 +182,7 @@ EditorRouteGroups::menu (RouteGroup* g)
|
||||||
_menu->set_name ("ArdourContextMenu");
|
_menu->set_name ("ArdourContextMenu");
|
||||||
MenuList& items = _menu->items();
|
MenuList& items = _menu->items();
|
||||||
|
|
||||||
items.push_back (MenuElem (_("New..."), mem_fun(*this, &EditorRouteGroups::new_route_group)));
|
items.push_back (MenuElem (_("New..."), hide_return (mem_fun(*this, &EditorRouteGroups::new_route_group))));
|
||||||
items.push_back (MenuElem (_("New From"), *new_from));
|
items.push_back (MenuElem (_("New From"), *new_from));
|
||||||
if (g) {
|
if (g) {
|
||||||
items.push_back (MenuElem (_("Edit..."), bind (mem_fun (*this, &EditorRouteGroups::edit), g)));
|
items.push_back (MenuElem (_("Edit..."), bind (mem_fun (*this, &EditorRouteGroups::edit), g)));
|
||||||
|
|
@ -231,8 +231,8 @@ EditorRouteGroups::set_activation (RouteGroup* g, bool a)
|
||||||
g->set_active (a, this);
|
g->set_active (a, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
ARDOUR::RouteGroup *
|
||||||
EditorRouteGroups::new_route_group ()
|
EditorRouteGroups::new_route_group () const
|
||||||
{
|
{
|
||||||
RouteGroup* g = new RouteGroup (
|
RouteGroup* g = new RouteGroup (
|
||||||
*_session,
|
*_session,
|
||||||
|
|
@ -244,13 +244,14 @@ EditorRouteGroups::new_route_group ()
|
||||||
RouteGroupDialog d (g, Gtk::Stock::NEW);
|
RouteGroupDialog d (g, Gtk::Stock::NEW);
|
||||||
int const r = d.do_run ();
|
int const r = d.do_run ();
|
||||||
|
|
||||||
if (r == Gtk::RESPONSE_OK) {
|
if (r != Gtk::RESPONSE_OK) {
|
||||||
_session->add_route_group (g);
|
|
||||||
} else {
|
|
||||||
delete g;
|
delete g;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_session->add_route_group (g);
|
||||||
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
EditorRouteGroups::run_new_group_dialog (const RouteList& rl)
|
EditorRouteGroups::run_new_group_dialog (const RouteList& rl)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ public:
|
||||||
Gtk::Menu* menu (ARDOUR::RouteGroup *);
|
Gtk::Menu* menu (ARDOUR::RouteGroup *);
|
||||||
|
|
||||||
void clear ();
|
void clear ();
|
||||||
|
ARDOUR::RouteGroup* new_route_group () const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
@ -71,7 +72,6 @@ private:
|
||||||
|
|
||||||
void row_change (const Gtk::TreeModel::Path&,const Gtk::TreeModel::iterator&);
|
void row_change (const Gtk::TreeModel::Path&,const Gtk::TreeModel::iterator&);
|
||||||
void name_edit (const Glib::ustring&, const Glib::ustring&);
|
void name_edit (const Glib::ustring&, const Glib::ustring&);
|
||||||
void new_route_group ();
|
|
||||||
void new_from_selection ();
|
void new_from_selection ();
|
||||||
void new_from_rec_enabled ();
|
void new_from_rec_enabled ();
|
||||||
void new_from_soloed ();
|
void new_from_soloed ();
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#include <gtkmm/stock.h>
|
#include <gtkmm/stock.h>
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
#include "ardour/route_group.h"
|
#include "ardour/route_group.h"
|
||||||
|
#include "ardour/route.h"
|
||||||
#include "route_group_dialog.h"
|
#include "route_group_dialog.h"
|
||||||
#include "group_tabs.h"
|
#include "group_tabs.h"
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
|
|
@ -31,7 +32,8 @@ using namespace ARDOUR;
|
||||||
|
|
||||||
GroupTabs::GroupTabs (Editor* e)
|
GroupTabs::GroupTabs (Editor* e)
|
||||||
: EditorComponent (e),
|
: EditorComponent (e),
|
||||||
_dragging (0)
|
_dragging (0),
|
||||||
|
_dragging_new_tab (0)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -63,25 +65,45 @@ GroupTabs::on_button_press_event (GdkEventButton* ev)
|
||||||
|
|
||||||
double const p = primary_coordinate (ev->x, ev->y);
|
double const p = primary_coordinate (ev->x, ev->y);
|
||||||
|
|
||||||
Tab* prev;
|
list<Tab>::iterator prev;
|
||||||
Tab* next;
|
list<Tab>::iterator next;
|
||||||
Tab* t = click_to_tab (p, &prev, &next);
|
Tab* t = click_to_tab (p, &prev, &next);
|
||||||
|
|
||||||
if (ev->button == 1 && t) {
|
_drag_min = prev != _tabs.end() ? prev->to : 0;
|
||||||
|
_drag_max = next != _tabs.end() ? next->from : extent ();
|
||||||
|
|
||||||
|
if (ev->button == 1) {
|
||||||
|
|
||||||
|
if (t == 0) {
|
||||||
|
Tab n;
|
||||||
|
n.from = n.to = p;
|
||||||
|
_dragging_new_tab = true;
|
||||||
|
|
||||||
|
if (next == _tabs.end()) {
|
||||||
|
_tabs.push_back (n);
|
||||||
|
t = &_tabs.back ();
|
||||||
|
} else {
|
||||||
|
list<Tab>::iterator j = _tabs.insert (next, n);
|
||||||
|
t = &(*j);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_dragging_new_tab = false;
|
||||||
|
}
|
||||||
|
|
||||||
_dragging = t;
|
_dragging = t;
|
||||||
_drag_moved = false;
|
_drag_moved = false;
|
||||||
_drag_last = p;
|
_drag_first = p;
|
||||||
|
|
||||||
double const h = (t->from + t->to) / 2;
|
double const h = (t->from + t->to) / 2;
|
||||||
_drag_from = p < h;
|
if (p < h) {
|
||||||
|
_drag_moving = t->from;
|
||||||
if (_drag_from) {
|
_drag_fixed = t->to;
|
||||||
/* limit is the end of the previous tab */
|
_drag_offset = p - t->from;
|
||||||
_drag_limit = prev ? prev->to : 0;
|
|
||||||
} else {
|
} else {
|
||||||
/* limit is the start of the next tab */
|
_drag_moving = t->to;
|
||||||
_drag_limit = next ? next->from : extent ();
|
_drag_fixed = t->from;
|
||||||
|
_drag_offset = p - t->to;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (ev->button == 3) {
|
} else if (ev->button == 3) {
|
||||||
|
|
@ -107,50 +129,21 @@ GroupTabs::on_motion_notify_event (GdkEventMotion* ev)
|
||||||
|
|
||||||
double const p = primary_coordinate (ev->x, ev->y);
|
double const p = primary_coordinate (ev->x, ev->y);
|
||||||
|
|
||||||
if (p != _drag_last) {
|
if (p != _drag_first) {
|
||||||
_drag_moved = true;
|
_drag_moved = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_drag_from) {
|
_drag_moving = p - _drag_offset;
|
||||||
|
|
||||||
double f = _dragging->from + p - _drag_last;
|
_dragging->from = min (_drag_moving, _drag_fixed);
|
||||||
|
_dragging->to = max (_drag_moving, _drag_fixed);
|
||||||
|
|
||||||
if (f < _drag_limit) {
|
_dragging->from = max (_dragging->from, _drag_min);
|
||||||
/* limit drag in the `too big' direction */
|
_dragging->to = min (_dragging->to, _drag_max);
|
||||||
f = _drag_limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
double const t = _dragging->to - _dragging->last_ui_size;
|
|
||||||
if (f > t) {
|
|
||||||
/* limit drag in the `too small' direction */
|
|
||||||
f = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
_dragging->from = f;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
double t = _dragging->to + p - _drag_last;
|
|
||||||
|
|
||||||
if (t > _drag_limit) {
|
|
||||||
/* limit drag in the `too big' direction */
|
|
||||||
t = _drag_limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
double const f = _dragging->from + _dragging->first_ui_size;
|
|
||||||
if (t < f) {
|
|
||||||
/* limit drag in the `too small' direction */
|
|
||||||
t = f;
|
|
||||||
}
|
|
||||||
|
|
||||||
_dragging->to = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_dirty ();
|
set_dirty ();
|
||||||
queue_draw ();
|
queue_draw ();
|
||||||
|
|
||||||
_drag_last = p;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -164,28 +157,56 @@ GroupTabs::on_button_release_event (GdkEventButton* ev)
|
||||||
|
|
||||||
if (!_drag_moved) {
|
if (!_drag_moved) {
|
||||||
|
|
||||||
if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
|
if (_dragging->group) {
|
||||||
|
|
||||||
/* edit */
|
if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
|
||||||
RouteGroupDialog d (_dragging->group, Gtk::Stock::APPLY);
|
|
||||||
d.do_run ();
|
/* edit */
|
||||||
|
RouteGroupDialog d (_dragging->group, Gtk::Stock::APPLY);
|
||||||
} else {
|
d.do_run ();
|
||||||
|
|
||||||
/* toggle active state */
|
} else {
|
||||||
_dragging->group->set_active (!_dragging->group->is_active (), this);
|
|
||||||
_dragging = 0;
|
/* toggle active state */
|
||||||
|
_dragging->group->set_active (!_dragging->group->is_active (), this);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* finish drag */
|
/* finish drag */
|
||||||
_dragging = 0;
|
RouteList routes = routes_for_tab (_dragging);
|
||||||
reflect_tabs (_tabs);
|
|
||||||
|
if (!routes.empty()) {
|
||||||
|
if (_dragging_new_tab) {
|
||||||
|
RouteGroup* g = new_route_group ();
|
||||||
|
if (g) {
|
||||||
|
for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
|
||||||
|
(*i)->set_route_group (g, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
boost::shared_ptr<RouteList> r = _session->get_routes ();
|
||||||
|
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||||
|
|
||||||
|
if (find (routes.begin(), routes.end(), *i) == routes.end()) {
|
||||||
|
/* this route is not on the list of those that should be in _dragging's group */
|
||||||
|
if ((*i)->route_group() == _dragging->group) {
|
||||||
|
(*i)->drop_route_group (this);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(*i)->set_route_group (_dragging->group, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
set_dirty ();
|
set_dirty ();
|
||||||
queue_draw ();
|
queue_draw ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_dragging = 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -218,29 +239,39 @@ GroupTabs::render (cairo_t* cr)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
GroupTabs::Tab *
|
GroupTabs::Tab *
|
||||||
GroupTabs::click_to_tab (double c, Tab** prev, Tab** next)
|
GroupTabs::click_to_tab (double c, list<Tab>::iterator* prev, list<Tab>::iterator* next)
|
||||||
{
|
{
|
||||||
*prev = 0;
|
*prev = *next = _tabs.end ();
|
||||||
|
Tab* under = 0;
|
||||||
|
|
||||||
list<Tab>::iterator i = _tabs.begin ();
|
list<Tab>::iterator i = _tabs.begin ();
|
||||||
while (i != _tabs.end() && (c < i->from || c > i->to)) {
|
while (i != _tabs.end()) {
|
||||||
*prev = &(*i);
|
|
||||||
|
if (i->from > c) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i->to < c) {
|
||||||
|
*prev = i;
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i->from <= c && c < i->to) {
|
||||||
|
under = &(*i);
|
||||||
|
}
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == _tabs.end()) {
|
if (i != _tabs.end()) {
|
||||||
*next = 0;
|
*next = i;
|
||||||
return 0;
|
|
||||||
|
if (under) {
|
||||||
|
*next++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list<Tab>::iterator j = i;
|
return under;
|
||||||
++j;
|
|
||||||
if (j == _tabs.end()) {
|
|
||||||
*next = 0;
|
|
||||||
} else {
|
|
||||||
*next = &(*j);
|
|
||||||
}
|
|
||||||
|
|
||||||
return &(*i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,12 +41,12 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
struct Tab {
|
struct Tab {
|
||||||
double from; ///< start coordinate
|
Tab () : group (0) {}
|
||||||
double to; ///< end coordinate
|
|
||||||
|
double from;
|
||||||
|
double to;
|
||||||
Gdk::Color colour; ///< colour
|
Gdk::Color colour; ///< colour
|
||||||
ARDOUR::RouteGroup* group; ///< route group
|
ARDOUR::RouteGroup* group; ///< route group
|
||||||
double first_ui_size; ///< GUI size of the first route in the group
|
|
||||||
double last_ui_size; ///< GUI size of the last route in the group
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -67,10 +67,7 @@ private:
|
||||||
*/
|
*/
|
||||||
virtual double primary_coordinate (double, double) const = 0;
|
virtual double primary_coordinate (double, double) const = 0;
|
||||||
|
|
||||||
/** Take a list of tabs and alter the route groups to reflect the tabs.
|
virtual ARDOUR::RouteList routes_for_tab (Tab const * t) const = 0;
|
||||||
* @param tabs.
|
|
||||||
*/
|
|
||||||
virtual void reflect_tabs (std::list<Tab> const & tabs) = 0;
|
|
||||||
|
|
||||||
/** @return Size of the widget along the primary axis */
|
/** @return Size of the widget along the primary axis */
|
||||||
virtual double extent () const = 0;
|
virtual double extent () const = 0;
|
||||||
|
|
@ -80,18 +77,24 @@ private:
|
||||||
*/
|
*/
|
||||||
virtual Gtk::Menu* get_menu (ARDOUR::RouteGroup* g) = 0;
|
virtual Gtk::Menu* get_menu (ARDOUR::RouteGroup* g) = 0;
|
||||||
|
|
||||||
|
virtual ARDOUR::RouteGroup* new_route_group () const = 0;
|
||||||
|
|
||||||
void render (cairo_t *);
|
void render (cairo_t *);
|
||||||
void on_size_request (Gtk::Requisition *);
|
void on_size_request (Gtk::Requisition *);
|
||||||
bool on_button_press_event (GdkEventButton *);
|
bool on_button_press_event (GdkEventButton *);
|
||||||
bool on_motion_notify_event (GdkEventMotion *);
|
bool on_motion_notify_event (GdkEventMotion *);
|
||||||
bool on_button_release_event (GdkEventButton *);
|
bool on_button_release_event (GdkEventButton *);
|
||||||
|
|
||||||
Tab * click_to_tab (double, Tab**, Tab**);
|
Tab * click_to_tab (double, std::list<Tab>::iterator *, std::list<Tab>::iterator *);
|
||||||
|
|
||||||
std::list<Tab> _tabs; ///< current list of tabs
|
std::list<Tab> _tabs; ///< current list of tabs
|
||||||
Tab* _dragging; ///< tab being dragged, or 0
|
Tab* _dragging; ///< tab being dragged, or 0
|
||||||
|
bool _dragging_new_tab; ///< true if we're dragging a new tab
|
||||||
bool _drag_moved; ///< true if there has been movement during any current drag
|
bool _drag_moved; ///< true if there has been movement during any current drag
|
||||||
bool _drag_from; ///< true if the drag is of the `from' end of the tab, otherwise it's the `to' end
|
double _drag_fixed; ///< the position of the fixed end of the tab being dragged
|
||||||
double _drag_last; ///< last mouse pointer position during drag
|
double _drag_moving; ///< the position of the moving end of the tab being dragged
|
||||||
double _drag_limit; ///< limit of the current drag
|
double _drag_offset; ///< offset from the mouse to the end of the tab being dragged
|
||||||
|
double _drag_min; ///< minimum position for drag
|
||||||
|
double _drag_max; ///< maximum position for drag
|
||||||
|
double _drag_first; ///< first mouse pointer position during drag
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -63,14 +63,12 @@ MixerGroupTabs::compute_tabs () const
|
||||||
if (g != tab.group) {
|
if (g != tab.group) {
|
||||||
if (tab.group) {
|
if (tab.group) {
|
||||||
tab.to = x;
|
tab.to = x;
|
||||||
tab.last_ui_size = s->get_width ();
|
|
||||||
tabs.push_back (tab);
|
tabs.push_back (tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
tab.from = x;
|
tab.from = x;
|
||||||
tab.group = g;
|
tab.group = g;
|
||||||
tab.colour = s->color ();
|
tab.colour = s->color ();
|
||||||
tab.first_ui_size = s->get_width ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
x += s->get_width ();
|
x += s->get_width ();
|
||||||
|
|
@ -89,7 +87,7 @@ MixerGroupTabs::draw_tab (cairo_t* cr, Tab const & tab) const
|
||||||
{
|
{
|
||||||
double const arc_radius = _height;
|
double const arc_radius = _height;
|
||||||
|
|
||||||
if (tab.group->is_active()) {
|
if (tab.group && tab.group->is_active()) {
|
||||||
cairo_set_source_rgba (cr, tab.colour.get_red_p (), tab.colour.get_green_p (), tab.colour.get_blue_p (), 1);
|
cairo_set_source_rgba (cr, tab.colour.get_red_p (), tab.colour.get_green_p (), tab.colour.get_blue_p (), 1);
|
||||||
} else {
|
} else {
|
||||||
cairo_set_source_rgba (cr, 1, 1, 1, 0.2);
|
cairo_set_source_rgba (cr, 1, 1, 1, 0.2);
|
||||||
|
|
@ -101,16 +99,18 @@ MixerGroupTabs::draw_tab (cairo_t* cr, Tab const & tab) const
|
||||||
cairo_line_to (cr, tab.from, _height);
|
cairo_line_to (cr, tab.from, _height);
|
||||||
cairo_fill (cr);
|
cairo_fill (cr);
|
||||||
|
|
||||||
pair<string, double> const f = fit_to_pixels (cr, tab.group->name(), tab.to - tab.from - arc_radius * 2);
|
if (tab.group) {
|
||||||
|
pair<string, double> const f = fit_to_pixels (cr, tab.group->name(), tab.to - tab.from - arc_radius * 2);
|
||||||
cairo_text_extents_t ext;
|
|
||||||
cairo_text_extents (cr, tab.group->name().c_str(), &ext);
|
cairo_text_extents_t ext;
|
||||||
|
cairo_text_extents (cr, tab.group->name().c_str(), &ext);
|
||||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
|
||||||
cairo_move_to (cr, tab.from + (tab.to - tab.from - f.second) / 2, _height - ext.height / 2);
|
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||||
cairo_save (cr);
|
cairo_move_to (cr, tab.from + (tab.to - tab.from - f.second) / 2, _height - ext.height / 2);
|
||||||
cairo_show_text (cr, f.first.c_str());
|
cairo_save (cr);
|
||||||
cairo_restore (cr);
|
cairo_show_text (cr, f.first.c_str());
|
||||||
|
cairo_restore (cr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
|
|
@ -119,45 +119,36 @@ MixerGroupTabs::primary_coordinate (double x, double) const
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
RouteList
|
||||||
MixerGroupTabs::reflect_tabs (list<Tab> const & tabs)
|
MixerGroupTabs::routes_for_tab (Tab const * t) const
|
||||||
{
|
{
|
||||||
list<Tab>::const_iterator j = tabs.begin ();
|
RouteList routes;
|
||||||
|
|
||||||
int32_t x = 0;
|
int32_t x = 0;
|
||||||
|
|
||||||
TreeModel::Children rows = _mixer->track_model->children ();
|
TreeModel::Children rows = _mixer->track_model->children ();
|
||||||
for (TreeModel::Children::iterator i = rows.begin(); i != rows.end(); ++i) {
|
for (TreeModel::Children::iterator i = rows.begin(); i != rows.end(); ++i) {
|
||||||
|
|
||||||
MixerStrip* s = (*i)[_mixer->track_columns.strip];
|
MixerStrip* s = (*i)[_mixer->track_columns.strip];
|
||||||
|
|
||||||
if (s->route()->is_master() || s->route()->is_control() || !s->marked_for_display()) {
|
if (s->route()->is_master() || s->route()->is_control() || !s->marked_for_display()) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x >= t->to) {
|
||||||
|
/* tab finishes before this track starts */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (j == tabs.end()) {
|
double const h = x + s->get_width() / 2;
|
||||||
|
|
||||||
/* already run out of tabs, so no edit group */
|
|
||||||
s->route()->set_route_group (0, this);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (x >= j->to) {
|
|
||||||
/* this tab finishes before this track starts, so onto the next tab */
|
|
||||||
++j;
|
|
||||||
}
|
|
||||||
|
|
||||||
double const h = x + s->get_width() / 2;
|
|
||||||
|
|
||||||
if (j->from < h && j->to > h) {
|
|
||||||
s->route()->set_route_group (j->group, this);
|
|
||||||
} else {
|
|
||||||
s->route()->set_route_group (0, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (t->from < h && t->to > h) {
|
||||||
|
routes.push_back (s->route ());
|
||||||
}
|
}
|
||||||
|
|
||||||
x += s->get_width ();
|
x += s->get_width ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return routes;
|
||||||
}
|
}
|
||||||
|
|
||||||
Gtk::Menu*
|
Gtk::Menu*
|
||||||
|
|
@ -205,3 +196,25 @@ MixerGroupTabs::destroy_subgroup (RouteGroup* g)
|
||||||
{
|
{
|
||||||
g->destroy_subgroup ();
|
g->destroy_subgroup ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ARDOUR::RouteGroup *
|
||||||
|
MixerGroupTabs::new_route_group () const
|
||||||
|
{
|
||||||
|
RouteGroup* g = new RouteGroup (
|
||||||
|
*_session,
|
||||||
|
"",
|
||||||
|
RouteGroup::Active,
|
||||||
|
(RouteGroup::Property) (RouteGroup::Gain | RouteGroup::Mute | RouteGroup::Solo | RouteGroup::RecEnable)
|
||||||
|
);
|
||||||
|
|
||||||
|
RouteGroupDialog d (g, Gtk::Stock::NEW);
|
||||||
|
int const r = d.do_run ();
|
||||||
|
|
||||||
|
if (r != Gtk::RESPONSE_OK) {
|
||||||
|
delete g;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_session->add_route_group (g);
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,12 @@ private:
|
||||||
std::list<Tab> compute_tabs () const;
|
std::list<Tab> compute_tabs () const;
|
||||||
void draw_tab (cairo_t *, Tab const &) const;
|
void draw_tab (cairo_t *, Tab const &) const;
|
||||||
double primary_coordinate (double, double) const;
|
double primary_coordinate (double, double) const;
|
||||||
void reflect_tabs (std::list<Tab> const &);
|
ARDOUR::RouteList routes_for_tab (Tab const *) const;
|
||||||
double extent () const {
|
double extent () const {
|
||||||
return _width;
|
return _width;
|
||||||
}
|
}
|
||||||
Gtk::Menu* get_menu (ARDOUR::RouteGroup* g);
|
Gtk::Menu* get_menu (ARDOUR::RouteGroup* g);
|
||||||
|
ARDOUR::RouteGroup* new_route_group () const;
|
||||||
|
|
||||||
void edit_group (ARDOUR::RouteGroup *);
|
void edit_group (ARDOUR::RouteGroup *);
|
||||||
void remove_group (ARDOUR::RouteGroup *);
|
void remove_group (ARDOUR::RouteGroup *);
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ RouteGroupDialog::RouteGroupDialog (RouteGroup* g, StockID const & s)
|
||||||
_name.set_text (_group->name ());
|
_name.set_text (_group->name ());
|
||||||
_active.set_active (_group->is_active ());
|
_active.set_active (_group->is_active ());
|
||||||
|
|
||||||
_name.signal_activate ().connect (sigc::bind (mem_fun (*this, &Dialog::response), RESPONSE_ACCEPT));
|
_name.signal_activate ().connect (sigc::bind (mem_fun (*this, &Dialog::response), RESPONSE_OK));
|
||||||
|
|
||||||
_gain.set_active (_group->property (RouteGroup::Gain));
|
_gain.set_active (_group->property (RouteGroup::Gain));
|
||||||
_relative.set_active (_group->is_relative());
|
_relative.set_active (_group->is_relative());
|
||||||
|
|
@ -117,6 +117,7 @@ RouteGroupDialog::RouteGroupDialog (RouteGroup* g, StockID const & s)
|
||||||
|
|
||||||
add_button (Stock::CANCEL, RESPONSE_CANCEL);
|
add_button (Stock::CANCEL, RESPONSE_CANCEL);
|
||||||
add_button (s, RESPONSE_OK);
|
add_button (s, RESPONSE_OK);
|
||||||
|
set_default_response (RESPONSE_OK);
|
||||||
|
|
||||||
show_all_children ();
|
show_all_children ();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue