Various tweaks to the port matrix: open to full size; remove buttons and move their functionality into a context menu;

set maximum size hint to stop port matrix windows being resized beyond their useful size; remove visibility checkbuttons -
visibility now controlled through menu or by clicking on group names; port groups fold down to a small tab when hidden;
don't swap the orientation of the matrix once it has been opened.

git-svn-id: svn://localhost/ardour2/branches/3.0@5373 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2009-07-17 22:54:45 +00:00
parent b89a786b3e
commit 50437bff22
16 changed files with 786 additions and 665 deletions

View File

@ -28,6 +28,8 @@
#include "i18n.h"
using namespace std;
GlobalPortMatrix::GlobalPortMatrix (ARDOUR::Session& s, ARDOUR::DataType t)
: PortMatrix (s, t)
{
@ -119,27 +121,25 @@ GlobalPortMatrixWindow::GlobalPortMatrixWindow (ARDOUR::Session& s, ARDOUR::Data
break;
}
Gtk::HBox* buttons_hbox = Gtk::manage (new Gtk::HBox);
_rescan_button.set_label (_("Rescan"));
_rescan_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::REFRESH, Gtk::ICON_SIZE_BUTTON)));
_rescan_button.signal_clicked().connect (sigc::mem_fun (_port_matrix, &GlobalPortMatrix::setup_all_ports));
buttons_hbox->pack_start (_rescan_button, Gtk::PACK_SHRINK);
_show_ports_button.set_label (_("Show individual ports"));
_show_ports_button.set_active (true);
_show_ports_button.signal_toggled().connect (sigc::mem_fun (*this, &GlobalPortMatrixWindow::show_ports_toggled));
buttons_hbox->pack_start (_show_ports_button, Gtk::PACK_SHRINK);
Gtk::VBox* vbox = Gtk::manage (new Gtk::VBox);
vbox->pack_start (_port_matrix);
vbox->pack_start (*buttons_hbox, Gtk::PACK_SHRINK);
add (*vbox);
add (_port_matrix);
show_all ();
/* XXX: hack to make the window full-size on opening. This may not work for
people with very large monitors */
resize (32768, 32768);
}
void
GlobalPortMatrixWindow::show_ports_toggled ()
GlobalPortMatrixWindow::on_realize ()
{
_port_matrix.set_show_only_bundles (!_show_ports_button.get_active());
Window::on_realize ();
pair<uint32_t, uint32_t> const m = _port_matrix.max_size ();
GdkGeometry g;
g.max_width = m.first;
g.max_height = m.second;
set_geometry_hints (*this, g, Gdk::HINT_MAX_SIZE);
}

View File

@ -63,7 +63,7 @@ public:
GlobalPortMatrixWindow (ARDOUR::Session&, ARDOUR::DataType);
private:
void show_ports_toggled ();
void on_realize ();
GlobalPortMatrix _port_matrix;
Gtk::Button _rescan_button;

View File

@ -181,100 +181,22 @@ IOSelector::list_is_global (int dim) const
}
IOSelectorWindow::IOSelectorWindow (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO> io, bool can_cancel)
: ArdourDialog ("I/O selector")
, _selector (session, io)
, add_button (_("Add Port"))
, disconnect_button (_("Disconnect All"))
, ok_button (can_cancel ? _("OK"): _("Close"))
, cancel_button (_("Cancel"))
, rescan_button (_("Rescan"))
: _selector (session, io)
{
/* XXX: what's this for? */
add_events (Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK);
set_name ("IOSelectorWindow2");
set_title (_("I/O selector"));
/* Disconnect All button */
disconnect_button.set_name ("IOSelectorButton");
disconnect_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::DISCONNECT, Gtk::ICON_SIZE_BUTTON)));
disconnect_button.signal_clicked().connect (sigc::mem_fun (_selector, &IOSelector::disassociate_all));
get_action_area()->pack_start (disconnect_button, false, false);
/* Add Port button */
add_button.set_name ("IOSelectorButton");
add_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::ADD, Gtk::ICON_SIZE_BUTTON)));
get_action_area()->pack_start (add_button, false, false);
add_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (_selector, &IOSelector::add_channel), boost::shared_ptr<Bundle> ()));
/* Rescan button */
rescan_button.set_name ("IOSelectorButton");
rescan_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::REFRESH, Gtk::ICON_SIZE_BUTTON)));
rescan_button.signal_clicked().connect (sigc::mem_fun (*this, &IOSelectorWindow::rescan));
get_action_area()->pack_start (rescan_button, false, false);
io->PortCountChanged.connect (sigc::hide (mem_fun (*this, &IOSelectorWindow::ports_changed)));
/* Cancel button */
if (can_cancel) {
cancel_button.set_name ("IOSelectorButton");
cancel_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::CANCEL, Gtk::ICON_SIZE_BUTTON)));
get_action_area()->pack_start (cancel_button, false, false);
} else {
cancel_button.hide();
}
cancel_button.signal_clicked().connect (mem_fun(*this, &IOSelectorWindow::cancel));
/* OK button */
ok_button.set_name ("IOSelectorButton");
if (!can_cancel) {
ok_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::CLOSE, Gtk::ICON_SIZE_BUTTON)));
}
ok_button.signal_clicked().connect (mem_fun(*this, &IOSelectorWindow::accept));
get_action_area()->pack_start (ok_button, false, false);
get_vbox()->set_spacing (8);
get_vbox()->pack_start (_selector, true, true);
add (_selector);
set_position (Gtk::WIN_POS_MOUSE);
io_name_changed (this);
ports_changed ();
show_all ();
signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), this));
}
void
IOSelectorWindow::ports_changed ()
{
/* XXX make this insensitive based on port connectivity, not
port counts.
*/
add_button.set_sensitive (true);
}
void
IOSelectorWindow::rescan ()
{
_selector.setup_ports (_selector.other());
}
void
IOSelectorWindow::cancel ()
{
_selector.Finished (IOSelector::Cancelled);
hide ();
}
void
IOSelectorWindow::accept ()
{
_selector.Finished (IOSelector::Accepted);
hide ();
resize (32768, 32768);
}
void
@ -300,6 +222,21 @@ IOSelectorWindow::io_name_changed (void* src)
set_title (title);
}
void
IOSelectorWindow::on_realize ()
{
Window::on_realize ();
pair<uint32_t, uint32_t> const m = _selector.max_size ();
GdkGeometry g;
g.max_width = m.first;
g.max_height = m.second;
set_geometry_hints (*this, g, Gdk::HINT_MAX_SIZE);
}
PortInsertUI::PortInsertUI (ARDOUR::Session& sess, boost::shared_ptr<ARDOUR::PortInsert> pi)
: input_selector (sess, pi->input())
, output_selector (sess, pi->output())
@ -330,8 +267,7 @@ PortInsertWindow::PortInsertWindow (ARDOUR::Session& sess, boost::shared_ptr<ARD
: ArdourDialog ("port insert dialog"),
_portinsertui (sess, pi),
ok_button (can_cancel ? _("OK"): _("Close")),
cancel_button (_("Cancel")),
rescan_button (_("Rescan"))
cancel_button (_("Cancel"))
{
set_name ("IOSelectorWindow");
@ -344,10 +280,7 @@ PortInsertWindow::PortInsertWindow (ARDOUR::Session& sess, boost::shared_ptr<ARD
ok_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::CLOSE, Gtk::ICON_SIZE_BUTTON)));
}
cancel_button.set_name ("IOSelectorButton");
rescan_button.set_name ("IOSelectorButton");
rescan_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::REFRESH, Gtk::ICON_SIZE_BUTTON)));
get_action_area()->pack_start (rescan_button, false, false);
if (can_cancel) {
cancel_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::CANCEL, Gtk::ICON_SIZE_BUTTON)));
get_action_area()->pack_start (cancel_button, false, false);

View File

@ -71,7 +71,7 @@ class IOSelector : public PortMatrix
bool _find_inputs_for_io_outputs;
};
class IOSelectorWindow : public ArdourDialog
class IOSelectorWindow : public Gtk::Window
{
public:
IOSelectorWindow (ARDOUR::Session&, boost::shared_ptr<ARDOUR::IO>, bool can_cancel = false);
@ -80,23 +80,11 @@ class IOSelectorWindow : public ArdourDialog
protected:
void on_map ();
void on_realize ();
private:
IOSelector _selector;
/* overall operation buttons */
Gtk::Button add_button;
Gtk::Button disconnect_button;
Gtk::Button ok_button;
Gtk::Button cancel_button;
Gtk::Button rescan_button;
void cancel ();
void accept ();
void rescan ();
void ports_changed ();
void io_name_changed (void *src);
};
@ -128,7 +116,6 @@ class PortInsertWindow : public ArdourDialog
Gtk::Button ok_button;
Gtk::Button cancel_button;
Gtk::Button rescan_button;
Gtk::Frame button_frame;
void cancel ();

View File

@ -32,23 +32,26 @@
#include "port_matrix_body.h"
#include "i18n.h"
using namespace std;
using namespace sigc;
using namespace Gtk;
/** PortMatrix constructor.
* @param session Our session.
* @param type Port type that we are handling.
*/
PortMatrix::PortMatrix (ARDOUR::Session& session, ARDOUR::DataType type)
: Gtk::Table (2, 2),
: Table (2, 2),
_session (session),
_type (type),
_column_visibility_box_added (false),
_row_visibility_box_added (false),
_menu (0),
_setup_once (false),
_arrangement (TOP_TO_RIGHT),
_row_index (0),
_column_index (1),
_min_height_divisor (1),
_show_only_bundles (false)
_show_only_bundles (false),
_inhibit_toggle_show_only_bundles (false),
_first_setup (true)
{
_body = new PortMatrixBody (this);
@ -56,38 +59,30 @@ PortMatrix::PortMatrix (ARDOUR::Session& session, ARDOUR::DataType type)
_ports[i].set_type (type);
/* watch for the content of _ports[] changing */
_ports[i].Changed.connect (sigc::mem_fun (*this, &PortMatrix::setup));
_ports[i].Changed.connect (mem_fun (*this, &PortMatrix::setup));
}
_row_visibility_box.pack_start (_row_visibility_label, Gtk::PACK_SHRINK);
_column_visibility_box.pack_start (_column_visibility_label, Gtk::PACK_SHRINK);
_hscroll.signal_value_changed().connect (sigc::mem_fun (*this, &PortMatrix::hscroll_changed));
_vscroll.signal_value_changed().connect (sigc::mem_fun (*this, &PortMatrix::vscroll_changed));
_hscroll.signal_value_changed().connect (mem_fun (*this, &PortMatrix::hscroll_changed));
_vscroll.signal_value_changed().connect (mem_fun (*this, &PortMatrix::vscroll_changed));
/* watch for routes being added or removed */
_session.RouteAdded.connect (sigc::hide (sigc::mem_fun (*this, &PortMatrix::routes_changed)));
_session.RouteAdded.connect (sigc::hide (mem_fun (*this, &PortMatrix::routes_changed)));
/* and also bundles */
_session.BundleAdded.connect (sigc::hide (sigc::mem_fun (*this, &PortMatrix::setup_global_ports)));
_session.BundleAdded.connect (sigc::hide (mem_fun (*this, &PortMatrix::setup_global_ports)));
reconnect_to_routes ();
attach (*_body, 0, 1, 0, 1);
attach (_vscroll, 1, 2, 0, 1, SHRINK);
attach (_hscroll, 0, 1, 1, 2, FILL | EXPAND, SHRINK);
show_all ();
}
PortMatrix::~PortMatrix ()
{
delete _body;
for (std::vector<Gtk::CheckButton*>::iterator i = _column_visibility_buttons.begin(); i != _column_visibility_buttons.end(); ++i) {
delete *i;
}
for (std::vector<Gtk::CheckButton*>::iterator i = _row_visibility_buttons.begin(); i != _row_visibility_buttons.end(); ++i) {
delete *i;
}
delete _menu;
}
@ -95,7 +90,7 @@ PortMatrix::~PortMatrix ()
void
PortMatrix::reconnect_to_routes ()
{
for (std::vector<sigc::connection>::iterator i = _route_connections.begin(); i != _route_connections.end(); ++i) {
for (vector<connection>::iterator i = _route_connections.begin(); i != _route_connections.end(); ++i) {
i->disconnect ();
}
_route_connections.clear ();
@ -103,7 +98,7 @@ PortMatrix::reconnect_to_routes ()
boost::shared_ptr<ARDOUR::RouteList> routes = _session.get_routes ();
for (ARDOUR::RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
_route_connections.push_back (
(*i)->processors_changed.connect (sigc::mem_fun (*this, &PortMatrix::setup_global_ports))
(*i)->processors_changed.connect (mem_fun (*this, &PortMatrix::setup_global_ports))
);
}
}
@ -120,117 +115,16 @@ PortMatrix::routes_changed ()
void
PortMatrix::setup ()
{
select_arrangement ();
if (_first_setup) {
select_arrangement ();
}
_body->setup ();
setup_scrollbars ();
queue_draw ();
if (_setup_once) {
/* we've set up before, so we need to clean up before re-setting-up */
/* XXX: we ought to be able to do this by just getting a list of children
from each container widget, but I couldn't make that work */
for (std::vector<Gtk::CheckButton*>::iterator i = _column_visibility_buttons.begin(); i != _column_visibility_buttons.end(); ++i) {
_column_visibility_box.remove (**i);
delete *i;
}
_column_visibility_buttons.clear ();
for (std::vector<Gtk::CheckButton*>::iterator i = _row_visibility_buttons.begin(); i != _row_visibility_buttons.end(); ++i) {
_row_visibility_box.remove (**i);
delete *i;
}
_row_visibility_buttons.clear ();
_scroller_table.remove (_vscroll);
_scroller_table.remove (*_body);
_scroller_table.remove (_hscroll);
remove (_scroller_table);
if (_row_visibility_box_added) {
remove (_row_visibility_box);
}
if (_column_visibility_box_added) {
remove (_column_visibility_box);
}
}
if (_column_index == 0) {
_column_visibility_label.set_text (_("Show Outputs"));
_row_visibility_label.set_text (_("Show Inputs"));
} else {
_column_visibility_label.set_text (_("Show Inputs"));
_row_visibility_label.set_text (_("Show Outputs"));
}
for (PortGroupList::List::const_iterator i = columns()->begin(); i != columns()->end(); ++i) {
Gtk::CheckButton* b = new Gtk::CheckButton ((*i)->name);
b->set_active ((*i)->visible());
boost::weak_ptr<PortGroup> w (*i);
b->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &PortMatrix::visibility_toggled), w, b));
_column_visibility_buttons.push_back (b);
_column_visibility_box.pack_start (*b, Gtk::PACK_SHRINK);
}
for (PortGroupList::List::const_iterator i = rows()->begin(); i != rows()->end(); ++i) {
Gtk::CheckButton* b = new Gtk::CheckButton ((*i)->name);
b->set_active ((*i)->visible());
boost::weak_ptr<PortGroup> w (*i);
b->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &PortMatrix::visibility_toggled), w, b));
_row_visibility_buttons.push_back (b);
_row_visibility_box.pack_start (*b, Gtk::PACK_SHRINK);
}
if (_arrangement == TOP_TO_RIGHT) {
_scroller_table.attach (_hscroll, 0, 1, 0, 1, Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
_scroller_table.attach (*_body, 0, 1, 1, 2);
_scroller_table.attach (_vscroll, 1, 2, 1, 2, Gtk::SHRINK);
attach (_scroller_table, 0, 1, 1, 2, Gtk::FILL | Gtk::EXPAND, Gtk::FILL | Gtk::EXPAND);
if (rows()->size() > 1) {
attach (_row_visibility_box, 1, 2, 1, 2, Gtk::SHRINK, Gtk::SHRINK);
_row_visibility_box_added = true;
} else {
_row_visibility_box_added = false;
}
if (columns()->size() > 1) {
attach (_column_visibility_box, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
_column_visibility_box_added = true;
} else {
_column_visibility_box_added = false;
}
} else {
_scroller_table.attach (_vscroll, 0, 1, 0, 1, Gtk::SHRINK);
_scroller_table.attach (*_body, 1, 2, 0, 1);
_scroller_table.attach (_hscroll, 1, 2, 1, 2, Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK);
if (rows()->size() > 1) {
attach (_row_visibility_box, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
_row_visibility_box_added = true;
} else {
_row_visibility_box_added = false;
}
attach (_scroller_table, 1, 2, 0, 1, Gtk::FILL | Gtk::EXPAND, Gtk::FILL | Gtk::EXPAND);
if (columns()->size() > 1) {
attach (_column_visibility_box, 1, 2, 1, 2, Gtk::SHRINK, Gtk::SHRINK);
_column_visibility_box_added = true;
} else {
_column_visibility_box_added = false;
}
}
_setup_once = true;
_first_setup = false;
show_all ();
}
@ -259,7 +153,7 @@ PortMatrix::vscroll_changed ()
void
PortMatrix::setup_scrollbars ()
{
Gtk::Adjustment* a = _hscroll.get_adjustment ();
Adjustment* a = _hscroll.get_adjustment ();
a->set_lower (0);
a->set_upper (_body->full_scroll_width());
a->set_page_size (_body->alloc_scroll_width());
@ -346,90 +240,113 @@ PortMatrix::rows () const
return &_ports[_row_index];
}
/** A group visibility checkbutton has been toggled.
* @param w Group.
* @param b Button.
*/
void
PortMatrix::visibility_toggled (boost::weak_ptr<PortGroup> w, Gtk::CheckButton* b)
PortMatrix::popup_menu (
pair<boost::shared_ptr<PortGroup>, ARDOUR::BundleChannel> column,
pair<boost::shared_ptr<PortGroup>, ARDOUR::BundleChannel> row,
uint32_t t
)
{
boost::shared_ptr<PortGroup> g = w.lock ();
if (!g) {
return;
}
using namespace Menu_Helpers;
g->set_visible (b->get_active());
_body->setup ();
setup_scrollbars ();
queue_draw ();
}
void
PortMatrix::popup_channel_context_menu (int dim, uint32_t N, uint32_t t)
{
delete _menu;
_menu = new Gtk::Menu;
_menu = new Menu;
_menu->set_name ("ArdourContextMenu");
Gtk::Menu_Helpers::MenuList& items = _menu->items ();
MenuList& items = _menu->items ();
ARDOUR::BundleChannel bc;
boost::shared_ptr<PortGroup> pg[2];
pg[_column_index] = column.first;
pg[_row_index] = row.first;
PortGroup::BundleList const r = _ports[dim].bundles();
for (PortGroup::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) {
if (N < i->bundle->nchannels ()) {
bc = ARDOUR::BundleChannel (i->bundle, N);
break;
} else {
N -= i->bundle->nchannels ();
}
}
ARDOUR::BundleChannel bc[2];
bc[_column_index] = column.second;
bc[_row_index] = row.second;
if (bc.bundle) {
char buf [64];
bool have_one = false;
char buf [64];
if (can_rename_channels (dim)) {
snprintf (buf, sizeof (buf), _("Rename '%s'..."), bc.bundle->channel_name (bc.channel).c_str());
boost::weak_ptr<ARDOUR::Bundle> w (bc.bundle);
items.push_back (
Gtk::Menu_Helpers::MenuElem (
buf,
sigc::bind (sigc::mem_fun (*this, &PortMatrix::rename_channel_proxy), w, bc.channel)
)
);
for (int dim = 0; dim < 2; ++dim) {
have_one = true;
}
if (pg[dim]) {
if (can_remove_channels (dim)) {
snprintf (buf, sizeof (buf), _("Remove '%s'"), bc.bundle->channel_name (bc.channel).c_str());
boost::weak_ptr<ARDOUR::Bundle> w (bc.bundle);
items.push_back (
Gtk::Menu_Helpers::MenuElem (
buf,
sigc::bind (sigc::mem_fun (*this, &PortMatrix::remove_channel_proxy), w, bc.channel)
)
);
have_one = true;
}
if (have_one) {
items.push_back (Gtk::Menu_Helpers::SeparatorElem ());
}
boost::weak_ptr<ARDOUR::Bundle> w (bc.bundle);
items.push_back (Gtk::Menu_Helpers::MenuElem (
_("Disassociate all"),
sigc::bind (sigc::mem_fun (*this, &PortMatrix::disassociate_all_on_channel), w, bc.channel, dim)
)
);
boost::weak_ptr<PortGroup> wp (pg[dim]);
_menu->popup (1, t);
if (pg[dim]->visible()) {
if (dim == 0) {
snprintf (buf, sizeof (buf), _("Hide '%s' sources"), pg[dim]->name.c_str());
} else {
snprintf (buf, sizeof (buf), _("Hide '%s' destinations"), pg[dim]->name.c_str());
}
items.push_back (MenuElem (buf, bind (mem_fun (*this, &PortMatrix::hide_group), wp)));
} else {
if (dim == 0) {
snprintf (buf, sizeof (buf), _("Show '%s' sources"), pg[dim]->name.c_str());
} else {
snprintf (buf, sizeof (buf), _("Show '%s' destinations"), pg[dim]->name.c_str());
}
items.push_back (MenuElem (buf, bind (mem_fun (*this, &PortMatrix::show_group), wp)));
}
}
if (bc[dim].bundle) {
bool have_one = false;
if (can_rename_channels (dim)) {
snprintf (buf, sizeof (buf), _("Rename '%s'..."), bc[dim].bundle->channel_name (bc[dim].channel).c_str());
boost::weak_ptr<ARDOUR::Bundle> w (bc[dim].bundle);
items.push_back (
MenuElem (
buf,
bind (mem_fun (*this, &PortMatrix::rename_channel_proxy), w, bc[dim].channel)
)
);
have_one = true;
}
if (can_remove_channels (dim)) {
snprintf (buf, sizeof (buf), _("Remove '%s'"), bc[dim].bundle->channel_name (bc[dim].channel).c_str());
boost::weak_ptr<ARDOUR::Bundle> w (bc[dim].bundle);
items.push_back (
MenuElem (
buf,
bind (mem_fun (*this, &PortMatrix::remove_channel_proxy), w, bc[dim].channel)
)
);
have_one = true;
}
boost::weak_ptr<ARDOUR::Bundle> w (bc[dim].bundle);
if (_show_only_bundles) {
snprintf (buf, sizeof (buf), _("Disassociate all from '%s'"), bc[dim].bundle->name().c_str());
} else {
snprintf (
buf, sizeof (buf), _("Disassociate all from '%s/%s'"),
bc[dim].bundle->name().c_str(), bc[dim].bundle->channel_name (bc[dim].channel).c_str()
);
}
items.push_back (
MenuElem (buf, bind (mem_fun (*this, &PortMatrix::disassociate_all_on_channel), w, bc[dim].channel, dim))
);
}
}
items.push_back (SeparatorElem ());
items.push_back (MenuElem (_("Rescan"), mem_fun (*this, &PortMatrix::setup_all_ports)));
items.push_back (CheckMenuElem (_("Show individual ports"), mem_fun (*this, &PortMatrix::toggle_show_only_bundles)));
CheckMenuItem* i = dynamic_cast<CheckMenuItem*> (&items.back());
_inhibit_toggle_show_only_bundles = true;
i->set_active (!_show_only_bundles);
_inhibit_toggle_show_only_bundles = false;
_menu->popup (1, t);
}
@ -500,10 +417,47 @@ PortMatrix::setup_all_ports ()
}
void
PortMatrix::set_show_only_bundles (bool s)
PortMatrix::toggle_show_only_bundles ()
{
_show_only_bundles = s;
if (_inhibit_toggle_show_only_bundles) {
return;
}
_show_only_bundles = !_show_only_bundles;
_body->setup ();
setup_scrollbars ();
queue_draw ();
}
void
PortMatrix::hide_group (boost::weak_ptr<PortGroup> w)
{
boost::shared_ptr<PortGroup> g = w.lock ();
if (!g) {
return;
}
g->set_visible (false);
}
void
PortMatrix::show_group (boost::weak_ptr<PortGroup> w)
{
boost::shared_ptr<PortGroup> g = w.lock ();
if (!g) {
return;
}
g->set_visible (true);
}
pair<uint32_t, uint32_t>
PortMatrix::max_size () const
{
pair<uint32_t, uint32_t> m = _body->max_size ();
m.first += _vscroll.get_width ();
m.second += _hscroll.get_height ();
return m;
}

View File

@ -60,7 +60,11 @@ public:
void disassociate_all ();
void setup_scrollbars ();
void popup_channel_context_menu (int, uint32_t, uint32_t);
void popup_menu (
std::pair<boost::shared_ptr<PortGroup>, ARDOUR::BundleChannel>,
std::pair<boost::shared_ptr<PortGroup>, ARDOUR::BundleChannel>,
uint32_t
);
int min_height_divisor () const {
return _min_height_divisor;
@ -83,8 +87,6 @@ public:
return _show_only_bundles;
}
void set_show_only_bundles (bool);
PortGroupList const * columns () const;
/** @return index into the _ports array for the list which is displayed as columns */
@ -107,6 +109,8 @@ public:
virtual void setup_ports (int) = 0;
void setup_all_ports ();
std::pair<uint32_t, uint32_t> max_size () const;
/** @param c Channels; where c[0] is from _ports[0] and c[1] is from _ports[1].
* @param s New state.
*/
@ -148,12 +152,14 @@ private:
void vscroll_changed ();
void routes_changed ();
void reconnect_to_routes ();
void visibility_toggled (boost::weak_ptr<PortGroup>, Gtk::CheckButton *);
void select_arrangement ();
void remove_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, uint32_t);
void rename_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, uint32_t);
void disassociate_all_on_channel (boost::weak_ptr<ARDOUR::Bundle>, uint32_t, int);
void setup_global_ports ();
void hide_group (boost::weak_ptr<PortGroup>);
void show_group (boost::weak_ptr<PortGroup>);
void toggle_show_only_bundles ();
/// port type that we are working with
ARDOUR::DataType _type;
@ -162,22 +168,14 @@ private:
PortMatrixBody* _body;
Gtk::HScrollbar _hscroll;
Gtk::VScrollbar _vscroll;
Gtk::HBox _column_visibility_box;
bool _column_visibility_box_added;
Gtk::Label _column_visibility_label;
std::vector<Gtk::CheckButton*> _column_visibility_buttons;
Gtk::VBox _row_visibility_box;
bool _row_visibility_box_added;
Gtk::Label _row_visibility_label;
std::vector<Gtk::CheckButton*> _row_visibility_buttons;
Gtk::Table _scroller_table;
Gtk::Menu* _menu;
bool _setup_once;
Arrangement _arrangement;
int _row_index;
int _column_index;
int _min_height_divisor;
bool _show_only_bundles;
bool _inhibit_toggle_show_only_bundles;
bool _first_setup;
};
#endif

View File

@ -26,6 +26,8 @@
#include "port_matrix_row_labels.h"
#include "port_matrix_grid.h"
using namespace std;
PortMatrixBody::PortMatrixBody (PortMatrix* p)
: _matrix (p),
_xoffset (0),
@ -138,9 +140,9 @@ PortMatrixBody::on_expose_event (GdkEventExpose* event)
void
PortMatrixBody::on_size_request (Gtk::Requisition *req)
{
std::pair<int, int> const col = _column_labels->dimensions ();
std::pair<int, int> const row = _row_labels->dimensions ();
std::pair<int, int> const grid = _grid->dimensions ();
pair<int, int> const col = _column_labels->dimensions ();
pair<int, int> const row = _row_labels->dimensions ();
pair<int, int> const grid = _grid->dimensions ();
/* don't ask for the maximum size of our contents, otherwise GTK won't
let the containing window shrink below this size */
@ -149,8 +151,8 @@ PortMatrixBody::on_size_request (Gtk::Requisition *req)
int const min_width = 512;
int const min_height = 512;
req->width = std::min (min_width, std::max (col.first, grid.first + row.first));
req->height = std::min (min_height / _matrix->min_height_divisor(), col.second + grid.second);
req->width = min (min_width, max (col.first, grid.first + row.first));
req->height = min (min_height / _matrix->min_height_divisor(), col.second + grid.second);
}
void
@ -169,9 +171,10 @@ void
PortMatrixBody::compute_rectangles ()
{
/* full sizes of components */
std::pair<uint32_t, uint32_t> const col = _column_labels->dimensions ();
std::pair<uint32_t, uint32_t> const row = _row_labels->dimensions ();
std::pair<uint32_t, uint32_t> const grid = _grid->dimensions ();
pair<uint32_t, uint32_t> const col = _column_labels->dimensions ();
uint32_t col_overhang = _column_labels->overhang ();
pair<uint32_t, uint32_t> const row = _row_labels->dimensions ();
pair<uint32_t, uint32_t> const grid = _grid->dimensions ();
Gdk::Rectangle col_rect;
Gdk::Rectangle row_rect;
@ -179,35 +182,19 @@ PortMatrixBody::compute_rectangles ()
if (_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT) {
/* build from top left */
col_rect.set_x (0);
col_rect.set_y (0);
grid_rect.set_x (0);
if (_alloc_width > col.first) {
col_rect.set_width (col.first);
} else {
col_rect.set_width (_alloc_width);
}
/* move down to y division */
uint32_t y = 0;
if (_alloc_height > col.second) {
y = col.second;
} else {
y = _alloc_height;
}
col_rect.set_width (min (col.first, _alloc_width));
uint32_t const y = min (_alloc_height, col.second);
col_rect.set_height (y);
row_rect.set_y (y);
row_rect.set_height (_alloc_height - y);
grid_rect.set_y (y);
grid_rect.set_height (_alloc_height - y);
/* move right to x division */
uint32_t x = 0;
if (_alloc_width > (grid.first + row.first)) {
x = grid.first;
@ -222,42 +209,22 @@ PortMatrixBody::compute_rectangles ()
} else if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
/* build from bottom right */
/* move left to x division */
uint32_t x = 0;
if (_alloc_width > (grid.first + row.first)) {
x = grid.first;
} else if (_alloc_width > row.first) {
x = _alloc_width - row.first;
}
grid_rect.set_x (_alloc_width - x);
grid_rect.set_width (x);
col_rect.set_width (col.first - grid.first + x);
col_rect.set_x (_alloc_width - col_rect.get_width());
row_rect.set_width (std::min (_alloc_width - x, row.first));
row_rect.set_x (_alloc_width - x - row_rect.get_width());
/* move up to the y division */
col_rect.set_height (min (_alloc_height, col.second));
uint32_t y = 0;
if (_alloc_height > col.second) {
y = col.second;
} else {
y = _alloc_height;
}
row_rect.set_x (0);
row_rect.set_y (0);
row_rect.set_width (min (_alloc_width, row.first));
row_rect.set_height (std::min (_alloc_height - col_rect.get_height(), row.second));
col_rect.set_y (_alloc_height - y);
col_rect.set_height (y);
grid_rect.set_x (row_rect.get_width());
grid_rect.set_y (0);
grid_rect.set_width (std::min (_alloc_width - row_rect.get_width(), grid.first));
grid_rect.set_height (row_rect.get_height ());
grid_rect.set_height (std::min (grid.second, _alloc_height - y));
grid_rect.set_y (_alloc_height - y - grid_rect.get_height());
row_rect.set_height (grid_rect.get_height());
row_rect.set_y (grid_rect.get_y());
col_rect.set_width (grid_rect.get_width () + col_overhang);
col_rect.set_x (row_rect.get_width() + grid_rect.get_width() - col_rect.get_width());
col_rect.set_y (row_rect.get_height());
}
_row_labels->set_parent_rectangle (row_rect);
@ -270,7 +237,7 @@ PortMatrixBody::setup ()
{
/* Discard any old connections to bundles */
for (std::list<sigc::connection>::iterator i = _bundle_connections.begin(); i != _bundle_connections.end(); ++i) {
for (list<sigc::connection>::iterator i = _bundle_connections.begin(); i != _bundle_connections.end(); ++i) {
i->disconnect ();
}
_bundle_connections.clear ();
@ -348,7 +315,7 @@ PortMatrixBody::on_button_press_event (GdkEventButton* ev)
_grid->button_press (
_grid->parent_to_component_x (ev->x),
_grid->parent_to_component_y (ev->y),
ev->button
ev->button, ev->time
);
} else if (Gdk::Region (_row_labels->parent_rectangle()).point_in (ev->x, ev->y)) {
@ -453,19 +420,10 @@ PortMatrixBody::set_mouseover (PortMatrixNode const & n)
void
PortMatrixBody::highlight_associated_channels (int dim, uint32_t N)
PortMatrixBody::highlight_associated_channels (int dim, ARDOUR::BundleChannel h)
{
ARDOUR::BundleChannel bc[2];
PortGroup::BundleList const a = _matrix->ports(dim)->bundles ();
for (PortGroup::BundleList::const_iterator i = a.begin(); i != a.end(); ++i) {
if (N < i->bundle->nchannels ()) {
bc[dim] = ARDOUR::BundleChannel (i->bundle, N);
break;
} else {
N -= i->bundle->nchannels ();
}
}
bc[dim] = h;
if (!bc[dim].bundle) {
return;
@ -507,4 +465,12 @@ PortMatrixBody::component_size_changed ()
_matrix->setup_scrollbars ();
}
pair<uint32_t, uint32_t>
PortMatrixBody::max_size () const
{
pair<uint32_t, uint32_t> const col = _column_labels->dimensions ();
pair<uint32_t, uint32_t> const row = _row_labels->dimensions ();
pair<uint32_t, uint32_t> const grid = _grid->dimensions ();
return make_pair (std::max (row.first, _column_labels->overhang()) + grid.first, col.second + grid.second);
}

View File

@ -61,8 +61,9 @@ public:
return _mouseover;
}
void highlight_associated_channels (int, uint32_t);
void highlight_associated_channels (int, ARDOUR::BundleChannel);
void component_size_changed ();
std::pair<uint32_t, uint32_t> max_size () const;
protected:
bool on_expose_event (GdkEventExpose *);

View File

@ -28,7 +28,8 @@
using namespace std;
PortMatrixColumnLabels::PortMatrixColumnLabels (PortMatrix* m, PortMatrixBody* b)
: PortMatrixLabels (m, b)
: PortMatrixLabels (m, b),
_overhang (0)
{
}
@ -92,6 +93,8 @@ PortMatrixColumnLabels::compute_dimensions ()
if (ext.height > _highest_group_name) {
_highest_group_name = ext.height;
}
} else {
_width += column_width ();
}
}
@ -109,7 +112,8 @@ PortMatrixColumnLabels::compute_dimensions ()
_height = parallelogram_height + _highest_group_name + 2 * name_pad();
_width += parallelogram_height / tan (angle ());
_overhang = parallelogram_height / tan (angle ());
_width += _overhang;
}
double
@ -144,18 +148,18 @@ PortMatrixColumnLabels::render (cairo_t* cr)
int g = 0;
for (PortGroupList::List::const_iterator i = _matrix->columns()->begin(); i != _matrix->columns()->end(); ++i) {
if (!(*i)->visible() || (*i)->bundles().empty()) {
continue;
}
/* compute width of this group */
uint32_t w = 0;
if (_matrix->show_only_bundles()) {
w = (*i)->bundles().size() * column_width();
if (!(*i)->visible() || (*i)->bundles().empty()) {
w = column_width ();
} else {
w = (*i)->total_channels() * column_width();
}
if (_matrix->show_only_bundles()) {
w = (*i)->bundles().size() * column_width();
} else {
w = (*i)->total_channels() * column_width();
}
}
/* rectangle */
set_source_rgb (cr, get_a_group_colour (g));
double const rh = _highest_group_name + 2 * name_pad();
@ -165,36 +169,49 @@ PortMatrixColumnLabels::render (cairo_t* cr)
cairo_rectangle (cr, x, _height - rh, w, rh);
}
cairo_fill (cr);
string const upper = Glib::ustring ((*i)->name).uppercase ();
pair<string, double> const display = fit_to_pixels (cr, upper, w);
/* plot it */
set_source_rgb (cr, text_colour());
cairo_move_to (cr, x + (w - display.second) / 2, y);
cairo_show_text (cr, display.first.c_str());
x += w;
++g;
}
/* BUNDLE PARALLELOGRAM-TYPE-THING AND NAME */
x = 0;
int N = 0;
PortGroup::BundleList const bundles = _matrix->columns()->bundles();
for (PortGroup::BundleList::const_iterator i = bundles.begin (); i != bundles.end(); ++i) {
Gdk::Color c = i->has_colour ? i->colour : get_a_bundle_colour (N);
render_bundle_name (cr, c, x, 0, i->bundle);
for (PortGroupList::List::const_iterator i = _matrix->columns()->begin(); i != _matrix->columns()->end(); ++i) {
if ((*i)->visible ()) {
PortGroup::BundleList const & bundles = (*i)->bundles ();
for (PortGroup::BundleList::const_iterator j = bundles.begin (); j != bundles.end(); ++j) {
Gdk::Color c = j->has_colour ? j->colour : get_a_bundle_colour (N);
render_bundle_name (cr, c, x, 0, j->bundle);
if (_matrix->show_only_bundles()) {
x += column_width();
} else {
x += j->bundle->nchannels () * column_width();
}
++N;
}
if (_matrix->show_only_bundles()) {
x += column_width();
} else {
x += i->bundle->nchannels () * column_width();
}
++N;
x += column_width ();
}
}
@ -203,15 +220,27 @@ PortMatrixColumnLabels::render (cairo_t* cr)
if (!_matrix->show_only_bundles()) {
x = 0;
N = 0;
for (PortGroup::BundleList::const_iterator i = bundles.begin (); i != bundles.end(); ++i) {
for (uint32_t j = 0; j < i->bundle->nchannels(); ++j) {
Gdk::Color c = i->has_colour ? i->colour : get_a_bundle_colour (N);
render_channel_name (cr, c, x, 0, ARDOUR::BundleChannel (i->bundle, j));
x += column_width();
}
for (PortGroupList::List::const_iterator i = _matrix->columns()->begin(); i != _matrix->columns()->end(); ++i) {
++N;
if ((*i)->visible ()) {
PortGroup::BundleList const & bundles = (*i)->bundles ();
for (PortGroup::BundleList::const_iterator j = bundles.begin (); j != bundles.end(); ++j) {
for (uint32_t k = 0; k < j->bundle->nchannels(); ++k) {
Gdk::Color c = j->has_colour ? j->colour : get_a_bundle_colour (N);
render_channel_name (cr, c, x, 0, ARDOUR::BundleChannel (j->bundle, k));
x += column_width();
}
++N;
}
} else {
x += column_width ();
}
}
}
}
@ -484,43 +513,102 @@ PortMatrixColumnLabels::queue_draw_for (ARDOUR::BundleChannel const & bc)
}
}
pair<boost::shared_ptr<PortGroup>, ARDOUR::BundleChannel>
PortMatrixColumnLabels::x_position_to_group_and_channel (double x, double y) const
{
uint32_t cx = 0;
uint32_t const gh = _highest_group_name + 2 * name_pad();
bool group_name = false;
if (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM) {
if (y > (_height - gh)) {
group_name = true;
cx = x;
} else {
cx = x - (_height - gh - y) * tan (angle ());
}
} else {
if (y < gh) {
group_name = true;
cx = x - _overhang;
} else {
cx = x - (_height - y) * tan (angle ());
}
}
uint32_t px = 0;
pair<boost::shared_ptr<PortGroup>, ARDOUR::BundleChannel> gc;
for (PortGroupList::List::const_iterator i = _matrix->columns()->begin(); i != _matrix->columns()->end(); ++i) {
if (!(*i)->visible()) {
uint32_t const gw = group_width (*i);
if (px <= cx && cx < (px + gw)) {
return make_pair (*i, ARDOUR::BundleChannel ());
} else {
px += gw;
}
} else {
PortGroup::BundleList bundles = (*i)->bundles ();
for (PortGroup::BundleList::iterator j = bundles.begin(); j != bundles.end(); ++j) {
if (_matrix->show_only_bundles()) {
if (px <= cx && cx < (px + column_width())) {
return make_pair (*i, ARDOUR::BundleChannel (j->bundle, 0));
} else {
px += column_width ();
}
} else {
for (uint32_t k = 0; k < j->bundle->nchannels(); ++k) {
if (px <= cx && cx < (px + column_width())) {
if (group_name) {
return make_pair (*i, ARDOUR::BundleChannel ());
} else {
return make_pair (*i, ARDOUR::BundleChannel (j->bundle, k));
}
}
px += column_width ();
}
}
}
}
}
return make_pair (boost::shared_ptr<PortGroup> (), ARDOUR::BundleChannel ());
}
void
PortMatrixColumnLabels::button_press (double x, double y, int b, uint32_t t)
{
uint32_t N = _matrix->columns()->total_visible_channels ();
uint32_t i = 0;
for (; i < N; ++i) {
vector<pair<double, double> > const shape = port_name_shape (i * column_width(), 0);
uint32_t j = 0;
for (; j < 4; ++j) {
uint32_t k = (j + 1) % 4;
double const P = (y - shape[j].second) * (shape[k].first - shape[j].first) -
(x - shape[j].first) * (shape[k].second - shape[j].second);
if (P > 0) {
break;
}
}
if (j == 4) {
break;
}
}
if (i == N) {
return;
}
pair<boost::shared_ptr<PortGroup>, ARDOUR::BundleChannel> gc = x_position_to_group_and_channel (x, y);
switch (b) {
case 1:
_body->highlight_associated_channels (_matrix->column_index(), i);
break;
case 3:
_matrix->popup_channel_context_menu (_matrix->column_index(), i, t);
break;
if (b == 1) {
if (gc.second.bundle) {
_body->highlight_associated_channels (_matrix->column_index(), gc.second);
} else if (gc.first) {
gc.first->set_visible (!gc.first->visible ());
}
} else if (b == 3) {
_matrix->popup_menu (
gc,
make_pair (boost::shared_ptr<PortGroup> (), ARDOUR::BundleChannel ()),
t
);
}
}

View File

@ -44,6 +44,10 @@ public:
double parent_to_component_y (double y) const;
void mouseover_changed (PortMatrixNode const &);
uint32_t overhang () const {
return _overhang;
}
private:
void render_bundle_name (cairo_t *, Gdk::Color, double, double, boost::shared_ptr<ARDOUR::Bundle>);
void render_channel_name (cairo_t *, Gdk::Color, double, double, ARDOUR::BundleChannel const &);
@ -60,11 +64,13 @@ private:
return _height - _highest_group_name - 2 * name_pad();
}
// PortGroup::BundleList _bundles;
std::pair<boost::shared_ptr<PortGroup>, ARDOUR::BundleChannel> x_position_to_group_and_channel (double, double) const;
double _longest_bundle_name;
double _longest_channel_name;
double _highest_text;
double _highest_group_name;
uint32_t _overhang;
};
#endif

View File

@ -21,6 +21,8 @@
#include "port_matrix.h"
#include "port_matrix_body.h"
using namespace std;
/** Constructor.
* @param p Port matrix that we're in.
*/
@ -98,7 +100,7 @@ PortMatrixComponent::set_source_rgba (cairo_t *cr, Gdk::Color const & c, double
cairo_set_source_rgba (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p(), a);
}
std::pair<uint32_t, uint32_t>
pair<uint32_t, uint32_t>
PortMatrixComponent::dimensions ()
{
if (_dimension_computation_required) {
@ -107,7 +109,7 @@ PortMatrixComponent::dimensions ()
_body->component_size_changed ();
}
return std::make_pair (_width, _height);
return make_pair (_width, _height);
}
Gdk::Color
@ -115,3 +117,95 @@ PortMatrixComponent::background_colour ()
{
return _matrix->get_style()->get_bg (Gtk::STATE_NORMAL);
}
uint32_t
PortMatrixComponent::group_width (boost::shared_ptr<const PortGroup> g) const
{
uint32_t width = 0;
if (g->visible()) {
PortGroup::BundleList const & bundles = g->bundles ();
if (_matrix->show_only_bundles()) {
width = bundles.size() * column_width ();
} else {
for (PortGroup::BundleList::const_iterator i = bundles.begin(); i != bundles.end(); ++i) {
width += i->bundle->nchannels() * column_width ();
}
}
} else {
width = column_width ();
}
return width;
}
uint32_t
PortMatrixComponent::group_height (boost::shared_ptr<const PortGroup> g) const
{
uint32_t height = 0;
if (g->visible ()) {
PortGroup::BundleList const & bundles = g->bundles ();
if (_matrix->show_only_bundles()) {
height = bundles.size() * row_height ();
} else {
for (PortGroup::BundleList::const_iterator i = bundles.begin(); i != bundles.end(); ++i) {
height += i->bundle->nchannels() * row_height ();
}
}
} else {
height = row_height ();
}
return height;
}
pair<boost::shared_ptr<PortGroup>, ARDOUR::BundleChannel>
PortMatrixComponent::y_position_to_group_and_channel (double y) const
{
PortGroupList::List::const_iterator i = _matrix->rows()->begin();
while (i != _matrix->rows()->end()) {
uint32_t const gh = group_height (*i);
if (y < gh) {
/* it's in this group */
PortGroup::BundleList const & bundles = (*i)->bundles ();
for (PortGroup::BundleList::const_iterator j = bundles.begin(); j != bundles.end(); ++j) {
if (_matrix->show_only_bundles()) {
if (y < row_height()) {
return make_pair (*i, ARDOUR::BundleChannel (j->bundle, 0));
} else {
y -= row_height ();
}
} else {
uint32_t const h = j->bundle->nchannels () * row_height ();
if (y < h) {
return make_pair (*i, ARDOUR::BundleChannel (j->bundle, y / row_height()));
} else {
y -= h;
}
}
}
} else {
y -= gh;
}
++i;
}
return make_pair (boost::shared_ptr<PortGroup> (), ARDOUR::BundleChannel (boost::shared_ptr<ARDOUR::Bundle> (), 0));
}

View File

@ -22,10 +22,16 @@
#include <stdint.h>
#include <gtkmm/eventbox.h>
#include <boost/shared_ptr.hpp>
class PortMatrix;
class PortMatrixBody;
class PortMatrixNode;
class PortGroup;
namespace ARDOUR {
class BundleChannel;
}
/** One component of the PortMatrix. This is a cairo-rendered
* Pixmap.
@ -166,6 +172,9 @@ protected:
void set_source_rgb (cairo_t *, Gdk::Color const &);
void set_source_rgba (cairo_t *, Gdk::Color const &, double);
uint32_t group_width (boost::shared_ptr<const PortGroup>) const;
uint32_t group_height (boost::shared_ptr<const PortGroup>) const;
std::pair<boost::shared_ptr<PortGroup>, ARDOUR::BundleChannel> y_position_to_group_and_channel (double) const;
/** Render the complete component to a cairo context. */
virtual void render (cairo_t *) = 0;

View File

@ -25,6 +25,8 @@
#include "port_matrix.h"
#include "port_matrix_body.h"
using namespace std;
PortMatrixGrid::PortMatrixGrid (PortMatrix* m, PortMatrixBody* b)
: PortMatrixComponent (m, b)
{
@ -35,23 +37,13 @@ void
PortMatrixGrid::compute_dimensions ()
{
_width = 0;
PortGroup::BundleList const c = _matrix->columns()->bundles();
if (_matrix->show_only_bundles()) {
_width = c.size() * column_width();
} else {
for (PortGroup::BundleList::const_iterator i = c.begin(); i != c.end(); ++i) {
_width += i->bundle->nchannels() * column_width();
}
for (PortGroupList::List::const_iterator i = _matrix->columns()->begin(); i != _matrix->columns()->end(); ++i) {
_width += group_width (*i);
}
_height = 0;
PortGroup::BundleList const r = _matrix->rows()->bundles();
if (_matrix->show_only_bundles()) {
_height = r.size() * column_width();
} else {
for (PortGroup::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) {
_height += i->bundle->nchannels() * row_height();
}
for (PortGroupList::List::const_iterator i = _matrix->rows()->begin(); i != _matrix->rows()->end(); ++i) {
_height += group_height (*i);
}
}
@ -59,83 +51,112 @@ PortMatrixGrid::compute_dimensions ()
void
PortMatrixGrid::render (cairo_t* cr)
{
/* BACKGROUND */
set_source_rgb (cr, background_colour());
cairo_rectangle (cr, 0, 0, _width, _height);
cairo_fill (cr);
uint32_t x = 0;
for (PortGroupList::List::const_iterator c = _matrix->columns()->begin(); c != _matrix->columns()->end(); ++c) {
uint32_t y = 0;
for (PortGroupList::List::const_iterator r = _matrix->rows()->begin(); r != _matrix->rows()->end(); ++r) {
if ((*c)->visible() && (*r)->visible()) {
render_group_pair (cr, *r, *c, x, y);
}
y += group_height (*r);
}
x += group_width (*c);
}
}
void
PortMatrixGrid::render_group_pair (cairo_t* cr, boost::shared_ptr<const PortGroup> row, boost::shared_ptr<const PortGroup> column, uint32_t const x, uint32_t const y)
{
PortGroup::BundleList const & row_bundles = row->bundles();
PortGroup::BundleList const & column_bundles = column->bundles();
/* unfortunately we need to compute the height of the row group here */
uint32_t height = group_height (row);
uint32_t tx = x;
/* VERTICAL GRID LINES */
set_source_rgb (cr, grid_colour());
uint32_t x = 0;
PortGroup::BundleList const c = _matrix->columns()->bundles();
uint32_t N = 0;
for (PortGroup::BundleList::const_iterator i = c.begin(); i != c.end(); ++i) {
if (!_matrix->show_only_bundles()) {
cairo_set_line_width (cr, thin_grid_line_width());
for (uint32_t j = 1; j < i->bundle->nchannels(); ++j) {
x += column_width();
cairo_move_to (cr, x, 0);
cairo_line_to (cr, x, _height);
cairo_stroke (cr);
}
}
if (N < (c.size() - 1)) {
x += column_width();
cairo_set_line_width (cr, thick_grid_line_width());
cairo_move_to (cr, x, 0);
cairo_line_to (cr, x, _height);
cairo_stroke (cr);
}
++N;
}
uint32_t grid_width = x + column_width();
/* HORIZONTAL GRID LINES */
uint32_t y = 0;
N = 0;
PortGroup::BundleList const r = _matrix->rows()->bundles();
for (PortGroup::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) {
for (PortGroup::BundleList::const_iterator i = column_bundles.begin(); i != column_bundles.end(); ++i) {
cairo_set_line_width (cr, thick_grid_line_width());
cairo_move_to (cr, tx, y);
cairo_line_to (cr, tx, y + height);
cairo_stroke (cr);
if (!_matrix->show_only_bundles()) {
cairo_set_line_width (cr, thin_grid_line_width());
for (uint32_t j = 1; j < i->bundle->nchannels(); ++j) {
y += row_height();
cairo_move_to (cr, 0, y);
cairo_line_to (cr, grid_width, y);
for (uint32_t j = 0; j < i->bundle->nchannels(); ++j) {
tx += column_width ();
cairo_move_to (cr, tx, y);
cairo_line_to (cr, tx, y + height);
cairo_stroke (cr);
}
} else {
tx += column_width ();
}
if (N < (r.size() - 1)) {
y += row_height();
cairo_set_line_width (cr, thick_grid_line_width());
cairo_move_to (cr, 0, y);
cairo_line_to (cr, grid_width, y);
cairo_stroke (cr);
}
++N;
}
/* ASSOCIATION INDICATORS */
uint32_t const width = tx - x;
uint32_t ty = y;
uint32_t bx = 0;
uint32_t by = 0;
/* HORIZONTAL GRID LINES */
N = 0;
for (PortGroup::BundleList::const_iterator i = row_bundles.begin(); i != row_bundles.end(); ++i) {
cairo_set_line_width (cr, thick_grid_line_width());
cairo_move_to (cr, x, ty);
cairo_line_to (cr, x + width, ty);
cairo_stroke (cr);
if (!_matrix->show_only_bundles()) {
cairo_set_line_width (cr, thin_grid_line_width());
for (uint32_t j = 0; j < i->bundle->nchannels(); ++j) {
ty += row_height ();
cairo_move_to (cr, x, ty);
cairo_line_to (cr, x + width, ty);
cairo_stroke (cr);
}
} else {
ty += row_height ();
}
++N;
}
/* ASSOCIATION INDICATORS */
uint32_t bx = x;
uint32_t by = y;
if (_matrix->show_only_bundles()) {
for (PortGroup::BundleList::const_iterator i = c.begin(); i != c.end(); ++i) {
by = 0;
for (PortGroup::BundleList::const_iterator i = column_bundles.begin(); i != column_bundles.end(); ++i) {
by = y;
for (PortGroup::BundleList::const_iterator j = r.begin(); j != r.end(); ++j) {
for (PortGroup::BundleList::const_iterator j = row_bundles.begin(); j != row_bundles.end(); ++j) {
PortMatrixNode::State s = bundle_to_bundle_state (i->bundle, j->bundle);
switch (s) {
case PortMatrixNode::UNKNOWN:
@ -155,19 +176,20 @@ PortMatrixGrid::render (cairo_t* cr)
}
bx += column_width();
}
} else {
for (PortGroup::BundleList::const_iterator i = c.begin(); i != c.end(); ++i) {
by = 0;
for (PortGroup::BundleList::const_iterator i = column_bundles.begin(); i != column_bundles.end(); ++i) {
by = y;
for (PortGroup::BundleList::const_iterator j = r.begin(); j != r.end(); ++j) {
for (PortGroup::BundleList::const_iterator j = row_bundles.begin(); j != row_bundles.end(); ++j) {
x = bx;
tx = bx;
for (uint32_t k = 0; k < i->bundle->nchannels (); ++k) {
y = by;
ty = by;
for (uint32_t l = 0; l < j->bundle->nchannels (); ++l) {
ARDOUR::BundleChannel c[2];
@ -178,24 +200,24 @@ PortMatrixGrid::render (cairo_t* cr)
switch (s) {
case PortMatrixNode::ASSOCIATED:
draw_association_indicator (cr, x, y);
draw_association_indicator (cr, tx, ty);
break;
case PortMatrixNode::UNKNOWN:
draw_unknown_indicator (cr, x, y);
draw_unknown_indicator (cr, tx, ty);
break;
case PortMatrixNode::NOT_ASSOCIATED:
break;
default:
break;
}
y += row_height();
ty += row_height();
}
x += column_width();
tx += column_width();
}
by += j->bundle->nchannels () * row_height();
@ -240,43 +262,63 @@ PortMatrixNode
PortMatrixGrid::position_to_node (double x, double y) const
{
return PortMatrixNode (
position_to_channel (y, _matrix->rows()->bundles(), row_height()),
position_to_channel (x, _matrix->columns()->bundles(), column_width())
y_position_to_group_and_channel (y).second,
x_position_to_group_and_channel (x).second
);
}
ARDOUR::BundleChannel
PortMatrixGrid::position_to_channel (double p, PortGroup::BundleList const & bundles, double inc) const
pair<boost::shared_ptr<PortGroup>, ARDOUR::BundleChannel>
PortMatrixGrid::x_position_to_group_and_channel (double x) const
{
uint32_t pos = p / inc;
PortGroupList::List::const_iterator i = _matrix->columns()->begin();
while (i != _matrix->columns()->end()) {
uint32_t const gw = group_width (*i);
if (x < gw) {
/* it's in this group */
PortGroup::BundleList const & bundles = (*i)->bundles ();
for (PortGroup::BundleList::const_iterator j = bundles.begin(); j != bundles.end(); ++j) {
if (_matrix->show_only_bundles()) {
if (x < column_width()) {
return make_pair (*i, ARDOUR::BundleChannel (j->bundle, 0));
} else {
x -= column_width ();
}
} else {
uint32_t const w = j->bundle->nchannels () * column_width ();
if (x < w) {
return make_pair (*i, ARDOUR::BundleChannel (j->bundle, x / column_width()));
} else {
x -= w;
}
}
if (_matrix->show_only_bundles()) {
for (PortGroup::BundleList::const_iterator i = bundles.begin(); i != bundles.end(); ++i) {
if (pos == 0) {
return ARDOUR::BundleChannel (i->bundle, 0);
} else {
pos--;
}
} else {
x -= gw;
}
} else {
for (PortGroup::BundleList::const_iterator i = bundles.begin(); i != bundles.end(); ++i) {
if (pos < i->bundle->nchannels()) {
return ARDOUR::BundleChannel (i->bundle, pos);
} else {
pos -= i->bundle->nchannels();
}
}
++i;
}
return ARDOUR::BundleChannel (boost::shared_ptr<ARDOUR::Bundle> (), 0);
return make_pair (boost::shared_ptr<PortGroup> (), ARDOUR::BundleChannel (boost::shared_ptr<ARDOUR::Bundle> (), 0));
}
double
PortMatrixGrid::channel_position (
ARDOUR::BundleChannel bc,
@ -307,54 +349,62 @@ PortMatrixGrid::channel_position (
}
void
PortMatrixGrid::button_press (double x, double y, int b)
PortMatrixGrid::button_press (double x, double y, int b, uint32_t t)
{
PortMatrixNode const node = position_to_node (x, y);
if (_matrix->show_only_bundles()) {
PortMatrixNode::State const s = bundle_to_bundle_state (node.column.bundle, node.row.bundle);
for (uint32_t i = 0; i < node.column.bundle->nchannels(); ++i) {
for (uint32_t j = 0; j < node.row.bundle->nchannels(); ++j) {
ARDOUR::BundleChannel c[2];
c[_matrix->column_index()] = ARDOUR::BundleChannel (node.column.bundle, i);
c[_matrix->row_index()] = ARDOUR::BundleChannel (node.row.bundle, j);
if (s == PortMatrixNode::NOT_ASSOCIATED || s == PortMatrixNode::PARTIAL) {
_matrix->set_state (c, i == j);
} else {
_matrix->set_state (c, false);
if (b == 1) {
PortMatrixNode const node = position_to_node (x, y);
if (_matrix->show_only_bundles()) {
PortMatrixNode::State const s = bundle_to_bundle_state (node.column.bundle, node.row.bundle);
for (uint32_t i = 0; i < node.column.bundle->nchannels(); ++i) {
for (uint32_t j = 0; j < node.row.bundle->nchannels(); ++j) {
ARDOUR::BundleChannel c[2];
c[_matrix->column_index()] = ARDOUR::BundleChannel (node.column.bundle, i);
c[_matrix->row_index()] = ARDOUR::BundleChannel (node.row.bundle, j);
if (s == PortMatrixNode::NOT_ASSOCIATED || s == PortMatrixNode::PARTIAL) {
_matrix->set_state (c, i == j);
} else {
_matrix->set_state (c, false);
}
}
}
}
} else {
if (node.row.bundle && node.column.bundle) {
ARDOUR::BundleChannel c[2];
c[_matrix->row_index()] = node.row;
c[_matrix->column_index()] = node.column;
} else {
PortMatrixNode::State const s = _matrix->get_state (c);
if (s == PortMatrixNode::ASSOCIATED || s == PortMatrixNode::NOT_ASSOCIATED) {
bool const n = !(s == PortMatrixNode::ASSOCIATED);
if (node.row.bundle && node.column.bundle) {
ARDOUR::BundleChannel c[2];
c[_matrix->row_index()] = node.row;
c[_matrix->column_index()] = node.column;
_matrix->set_state (c, n);
PortMatrixNode::State const s = _matrix->get_state (c);
if (s == PortMatrixNode::ASSOCIATED || s == PortMatrixNode::NOT_ASSOCIATED) {
bool const n = !(s == PortMatrixNode::ASSOCIATED);
ARDOUR::BundleChannel c[2];
c[_matrix->row_index()] = node.row;
c[_matrix->column_index()] = node.column;
_matrix->set_state (c, n);
}
}
}
}
require_render ();
_body->queue_draw ();
require_render ();
_body->queue_draw ();
} else if (b == 3) {
_matrix->popup_menu (x_position_to_group_and_channel (x), y_position_to_group_and_channel (y), t);
}
}
void

View File

@ -41,7 +41,7 @@ class PortMatrixGrid : public PortMatrixComponent
public:
PortMatrixGrid (PortMatrix *, PortMatrixBody *);
void button_press (double, double, int);
void button_press (double, double, int, uint32_t);
void mouseover_event (double, double);
double component_to_parent_x (double x) const;
@ -55,10 +55,11 @@ private:
void compute_dimensions ();
void render (cairo_t *);
void render_group_pair (cairo_t *, boost::shared_ptr<const PortGroup>, boost::shared_ptr<const PortGroup>, uint32_t, uint32_t);
double channel_position (ARDOUR::BundleChannel, PortGroup::BundleList const &, double) const;
PortMatrixNode position_to_node (double, double) const;
ARDOUR::BundleChannel position_to_channel (double, PortGroup::BundleList const &, double) const;
std::pair<boost::shared_ptr<PortGroup>, ARDOUR::BundleChannel> x_position_to_group_and_channel (double) const;
void queue_draw_for (PortMatrixNode const &);
void draw_association_indicator (cairo_t *, uint32_t, uint32_t, double p = 1);
void draw_unknown_indicator (cairo_t *, uint32_t, uint32_t);

View File

@ -27,6 +27,8 @@
#include "i18n.h"
#include "utils.h"
using namespace std;
PortMatrixRowLabels::PortMatrixRowLabels (PortMatrix* m, PortMatrixBody* b)
: PortMatrixLabels (m, b)
{
@ -43,6 +45,7 @@ PortMatrixRowLabels::compute_dimensions ()
_longest_port_name = 0;
_longest_bundle_name = 0;
_height = 0;
PortGroup::BundleList const r = _matrix->rows()->bundles();
for (PortGroup::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) {
for (uint32_t j = 0; j < i->bundle->nchannels(); ++j) {
@ -74,6 +77,9 @@ PortMatrixRowLabels::compute_dimensions ()
if (ext.height > _highest_group_name) {
_highest_group_name = ext.height;
}
} else {
/* add another row_height for a tab for this hidden group */
_height += row_height ();
}
}
@ -113,28 +119,28 @@ PortMatrixRowLabels::render (cairo_t* cr)
int g = 0;
for (PortGroupList::List::const_iterator i = _matrix->rows()->begin(); i != _matrix->rows()->end(); ++i) {
if (!(*i)->visible() || (*i)->bundles().empty()) {
continue;
}
/* compute height of this group */
double h = 0;
if (_matrix->show_only_bundles()) {
h = (*i)->bundles().size() * row_height();
if (!(*i)->visible() || (*i)->bundles().empty()) {
h = row_height ();
} else {
h = (*i)->total_channels () * row_height();
if (_matrix->show_only_bundles()) {
h = (*i)->bundles().size() * row_height();
} else {
h = (*i)->total_channels () * row_height();
}
}
/* rectangle */
set_source_rgb (cr, get_a_group_colour (g));
double const rw = _highest_group_name + 2 * name_pad();
cairo_rectangle (cr, x, y, rw, h);
cairo_fill (cr);
/* hence what abbreviation (or not) we need for the group name */
std::string const upper = Glib::ustring ((*i)->name).uppercase ();
std::pair<std::string, double> display = fit_to_pixels (cr, upper, h);
string const upper = Glib::ustring ((*i)->name).uppercase ();
pair<string, double> display = fit_to_pixels (cr, upper, h);
/* plot it */
set_source_rgb (cr, text_colour());
cairo_move_to (cr, x + rw - name_pad(), y + (h + display.second) / 2);
@ -142,35 +148,41 @@ PortMatrixRowLabels::render (cairo_t* cr)
cairo_rotate (cr, - M_PI / 2);
cairo_show_text (cr, display.first.c_str());
cairo_restore (cr);
y += h;
++g;
}
/* BUNDLE NAMES */
/* BUNDLE AND PORT NAMES */
y = 0;
int N = 0;
PortGroup::BundleList const r = _matrix->rows()->bundles();
for (PortGroup::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) {
render_bundle_name (cr, i->has_colour ? i->colour : get_a_bundle_colour (N), 0, y, i->bundle);
int const n = _matrix->show_only_bundles() ? 1 : i->bundle->nchannels();
y += row_height() * n;
++N;
}
int M = 0;
for (PortGroupList::List::const_iterator i = _matrix->rows()->begin(); i != _matrix->rows()->end(); ++i) {
/* PORT NAMES */
if ((*i)->visible ()) {
PortGroup::BundleList const & bundles = (*i)->bundles ();
for (PortGroup::BundleList::const_iterator j = bundles.begin(); j != bundles.end(); ++j) {
render_bundle_name (cr, j->has_colour ? j->colour : get_a_bundle_colour (N), 0, y, j->bundle);
if (!_matrix->show_only_bundles()) {
y = 0;
N = 0;
for (PortGroup::BundleList::const_iterator i = r.begin(); i != r.end(); ++i) {
for (uint32_t j = 0; j < i->bundle->nchannels(); ++j) {
render_channel_name (cr, i->has_colour ? i->colour : get_a_bundle_colour (N), 0, y, ARDOUR::BundleChannel (i->bundle, j));
y += row_height();
if (!_matrix->show_only_bundles()) {
for (uint32_t k = 0; k < j->bundle->nchannels(); ++k) {
Gdk::Color c = j->has_colour ? j->colour : get_a_bundle_colour (M);
render_channel_name (cr, c, 0, y, ARDOUR::BundleChannel (j->bundle, k));
y += row_height();
++M;
}
} else {
y += row_height();
}
++N;
}
++N;
} else {
y += row_height ();
}
}
}
@ -178,25 +190,48 @@ PortMatrixRowLabels::render (cairo_t* cr)
void
PortMatrixRowLabels::button_press (double x, double y, int b, uint32_t t)
{
switch (b) {
case 1:
_body->highlight_associated_channels (_matrix->row_index(), y / row_height ());
break;
case 3:
maybe_popup_context_menu (x, y, t);
break;
}
}
uint32_t const gw = (_highest_group_name + 2 * name_pad());
void
PortMatrixRowLabels::maybe_popup_context_menu (double x, double y, uint32_t t)
{
if ( (_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM && x > (_longest_bundle_name + name_pad() * 2)) ||
(_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT && x < (_longest_port_name + name_pad() * 2))
pair<boost::shared_ptr<PortGroup>, ARDOUR::BundleChannel> w = y_position_to_group_and_channel (y);
if (
(_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM && x < gw) ||
(_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT && x > (_width - gw))
) {
_matrix->popup_channel_context_menu (_matrix->row_index(), y / row_height(), t);
w.second.bundle.reset ();
}
if (b == 1) {
if (w.second.bundle) {
_body->highlight_associated_channels (_matrix->row_index(), w.second);
} else {
if (w.first) {
w.first->set_visible (!w.first->visible());
}
}
} else if (b == 3) {
if (
(_matrix->arrangement() == PortMatrix::LEFT_TO_BOTTOM && x < (_longest_port_name + name_pad() * 2)) ||
(_matrix->arrangement() == PortMatrix::TOP_TO_RIGHT && x > (_longest_port_name + name_pad() * 2))
) {
_matrix->popup_menu (
make_pair (boost::shared_ptr<PortGroup> (), ARDOUR::BundleChannel ()),
make_pair (w.first, ARDOUR::BundleChannel ()),
t
);
} else {
_matrix->popup_menu (
make_pair (boost::shared_ptr<PortGroup> (), ARDOUR::BundleChannel ()),
make_pair (w.first, ARDOUR::BundleChannel ()),
t
);
}
}
}

View File

@ -63,7 +63,6 @@ private:
void rename_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, uint32_t);
void queue_draw_for (ARDOUR::BundleChannel const &);
double port_name_x () const;
void maybe_popup_context_menu (double, double, uint32_t);
double bundle_name_x () const;
double _longest_port_name;