Improvements to the port matrix (I think). Sizing of the cairo section should be...
[ardour.git] / gtk2_ardour / port_matrix.cc
1 /*
2     Copyright (C) 2002-2007 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 <gtkmm/label.h>
21 #include <gtkmm/enums.h>
22 #include <gtkmm/menu.h>
23 #include <gtkmm/menu_elems.h>
24 #include <gtkmm/menuitem.h>
25 #include <gtkmm/menushell.h>
26 #include <glibmm/objectbase.h>
27 #include <gtkmm2ext/doi.h>
28 #include "ardour/data_type.h"
29 #include "i18n.h"
30 #include "port_matrix.h"
31
32 using namespace Gtk;
33
34 PortMatrix::PortMatrix (ARDOUR::Session& session, ARDOUR::DataType type, bool offer_inputs, PortGroupList::Mask mask)
35         : _offer_inputs (offer_inputs), _port_group_list (session, type, offer_inputs, mask), _type (type), matrix (this)
36 {
37         _side_vbox_pad = 0;
38
39         _visibility_checkbutton_box.pack_start (*(manage (new Label (_("Connections displayed: ")))), false, false, 10);
40         pack_start (_visibility_checkbutton_box, false, false);
41
42         _scrolled_window.set_policy (POLICY_ALWAYS, POLICY_AUTOMATIC);
43         _scrolled_window.set_shadow_type (SHADOW_NONE);
44
45         _scrolled_window.add (matrix);
46
47         if (offer_inputs) {
48                 _overall_hbox.pack_start (_side_vbox, false, false, 6);
49                 _overall_hbox.pack_start (_scrolled_window, true, true);
50         } else {
51                 _overall_hbox.pack_start (_scrolled_window, true, true, 6);
52                 _overall_hbox.pack_start (_side_vbox, false, false);
53         }
54
55         pack_start (_overall_hbox);
56 }
57
58 PortMatrix::~PortMatrix ()
59 {
60         clear ();
61 }
62
63 void 
64 PortMatrix::set_ports (const std::list<std::string>& ports)
65 {
66         matrix.set_ports (ports);
67 }
68
69 /** Clear out the things that change when the number of source or destination ports changes */
70 void
71 PortMatrix::clear ()
72 {
73         /* remove lurking, invisible label and padding */
74         
75         _side_vbox.children().clear ();
76
77         delete _side_vbox_pad;
78         _side_vbox_pad = 0;
79
80         for (std::vector<PortGroupUI*>::iterator i = _port_group_ui.begin(); i != _port_group_ui.end(); ++i) {
81                 _visibility_checkbutton_box.remove ((*i)->get_visibility_checkbutton());
82                 delete *i;
83         }
84
85         _port_group_ui.clear ();
86 }
87
88 /** Set up the dialogue */
89 void
90 PortMatrix::setup ()
91 {
92         /* sort out the ports that we'll offer to connect to */
93         _port_group_list.refresh ();
94         
95         clear ();
96
97         _side_vbox_pad = new Label (""); /* unmanaged, explicitly deleted */
98
99         _side_vbox.pack_start (*_side_vbox_pad, false, false);
100         _side_vbox.pack_start (*manage (new Label ("")));
101
102         matrix.clear ();
103
104         /* Matrix and visibility checkbuttons */
105         for (PortGroupList::iterator i = _port_group_list.begin(); i != _port_group_list.end(); ++i) {
106
107                 PortGroupUI* t = new PortGroupUI (*this, **i);
108                 
109                 _port_group_ui.push_back (t);
110
111                 matrix.add_group (**i);
112
113                 _visibility_checkbutton_box.pack_start (t->get_visibility_checkbutton(), false, false);
114
115                 CheckButton* chk = dynamic_cast<CheckButton*>(&t->get_visibility_checkbutton());
116
117                 if (chk) { 
118                         chk->signal_toggled().connect (sigc::mem_fun (*this, &PortMatrix::reset_visibility));
119                 }
120         }
121
122         show_all ();
123
124         reset_visibility ();
125 }
126
127 void
128 PortMatrix::reset_visibility ()
129 {
130         for (std::vector<PortGroupUI*>::iterator i = _port_group_ui.begin(); i != _port_group_ui.end(); ++i) {
131
132                 (*i)->setup_visibility ();
133                 
134                 if ((*i)->port_group().visible) {
135                         matrix.show_group ((*i)->port_group());
136                 } else {
137                         matrix.hide_group ((*i)->port_group());
138                 }
139         }
140 }
141
142
143 /** Handle a button press on a row label */
144 bool
145 PortMatrix::row_label_button_pressed (GdkEventButton* e, int r)
146 {
147         if (e->type != GDK_BUTTON_PRESS || e->button != 3) {
148                 return false;
149         }
150
151         Menu* menu = manage (new Menu);
152         Menu_Helpers::MenuList& items = menu->items ();
153         menu->set_name ("ArdourContextMenu");
154
155         bool const can_add = maximum_rows () > n_rows ();
156         bool const can_remove = minimum_rows () < n_rows ();
157         std::string const name = row_name (r);
158         
159         items.push_back (
160                 Menu_Helpers::MenuElem (string_compose(_("Add %1"), row_descriptor()), sigc::mem_fun (*this, &PortMatrix::add_row))
161                 );
162
163         items.back().set_sensitive (can_add);
164
165         items.push_back (
166                 Menu_Helpers::MenuElem (string_compose(_("Remove %1 \"%2\""), row_descriptor(), name), sigc::bind (sigc::mem_fun (*this, &PortMatrix::remove_row), r))
167                 );
168
169         items.back().set_sensitive (can_remove);
170
171         menu->popup (e->button, e->time);
172         
173         return true;
174 }
175
176 void
177 PortMatrix::set_type (ARDOUR::DataType t)
178 {
179         _type = t;
180         _port_group_list.set_type (t);
181         setup ();
182 }
183
184 void
185 PortMatrix::set_offer_inputs (bool i)
186 {
187         _offer_inputs = i;
188         _port_group_list.set_offer_inputs (i);
189         setup ();
190 }
191