VKeybd: Pass on primary (Ctrl/Cmd) shortcuts
[ardour.git] / gtk2_ardour / port_matrix.h
1 /*
2  * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
3  * Copyright (C) 2008-2012 Paul Davis <paul@linuxaudiosystems.com>
4  * Copyright (C) 2009-2011 David Robillard <d@drobilla.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #ifndef __gtk_ardour_port_matrix_h__
22 #define __gtk_ardour_port_matrix_h__
23
24 #include <list>
25 #include <gtkmm/box.h>
26 #include <gtkmm/scrollbar.h>
27 #include <gtkmm/table.h>
28 #include <gtkmm/label.h>
29 #include <gtkmm/checkbutton.h>
30 #include <gtkmm/notebook.h>
31 #include <boost/shared_ptr.hpp>
32
33 #include "ardour/bundle.h"
34 #include "ardour/types.h"
35 #include "ardour/session_handle.h"
36
37 #include "port_group.h"
38 #include "port_matrix_types.h"
39
40 /** The `port matrix' UI.  This is a widget which lets the user alter
41  *  associations between one set of ports and another.  e.g. to connect
42  *  things together.
43  *
44  *  It is made up of a body, PortMatrixBody, which is rendered using cairo,
45  *  and some scrollbars and other stuff.  All of this is arranged inside the
46  *  Table that we inherit from.
47  */
48
49 namespace ARDOUR {
50         class Bundle;
51 }
52
53 namespace Gtk {
54         namespace Menu_Helpers {
55                 class MenuList;
56         }
57 }
58
59 class PortMatrixBody;
60
61 class PortMatrix : public Gtk::Table, public ARDOUR::SessionHandlePtr
62 {
63 public:
64         PortMatrix (Gtk::Window*, ARDOUR::Session *, ARDOUR::DataType);
65         ~PortMatrix ();
66
67         void set_type (ARDOUR::DataType);
68
69         ARDOUR::DataType type () const {
70                 return _type;
71         }
72
73         void disassociate_all ();
74         void setup_scrollbars ();
75         void popup_menu (ARDOUR::BundleChannel, ARDOUR::BundleChannel, uint32_t);
76
77         int min_height_divisor () const {
78                 return _min_height_divisor;
79         }
80         void set_min_height_divisor (int f) {
81                 _min_height_divisor = f;
82         }
83
84         enum Arrangement {
85                 TOP_TO_RIGHT,  ///< column labels on top, row labels to the right
86                 LEFT_TO_BOTTOM ///< row labels to the left, column labels on the bottom
87         };
88
89
90         /** @return Arrangement in use */
91         Arrangement arrangement () const {
92                 return _arrangement;
93         }
94
95         bool show_only_bundles () const {
96                 return _show_only_bundles;
97         }
98
99         PortGroupList const * columns () const;
100         boost::shared_ptr<const PortGroup> visible_columns () const;
101
102         /** @return index into the _ports array for the list which is displayed as columns */
103         int column_index () const {
104                 return _column_index;
105         }
106
107         PortGroupList const * rows () const;
108         boost::shared_ptr<const PortGroup> visible_rows () const;
109
110         /** @return index into the _ports array for the list which is displayed as rows */
111         int row_index () const {
112                 return _row_index;
113         }
114
115         PortGroupList const * ports (int d) const {
116                 return &_ports[d];
117         }
118
119         boost::shared_ptr<const PortGroup> visible_ports (int d) const;
120
121         void init ();
122         void setup ();
123         virtual void setup_ports (int) = 0;
124         void setup_all_ports ();
125
126         std::pair<uint32_t, uint32_t> max_size () const;
127
128         bool should_show (ARDOUR::DataType) const;
129         uint32_t count_of_our_type (ARDOUR::ChanCount) const;
130         uint32_t count_of_our_type_min_1 (ARDOUR::ChanCount) const;
131
132         PortMatrixNode::State get_association (PortMatrixNode) const;
133
134         void flip ();
135         bool key_press (GdkEventKey *);
136
137         /** @param c Channels; where c[0] is from _ports[0] and c[1] is from _ports[1].
138          *  @param s New state.
139          */
140         virtual void set_state (ARDOUR::BundleChannel c[2], bool s) = 0;
141
142         /** @param c Channels; where c[0] is from _ports[0] and c[1] is from _ports[1].
143          *  @return state
144          */
145         virtual PortMatrixNode::State get_state (ARDOUR::BundleChannel c[2]) const = 0;
146         virtual bool list_is_global (int) const = 0;
147
148         virtual bool can_add_channels (boost::shared_ptr<ARDOUR::Bundle>) const;
149         virtual void add_channel (boost::shared_ptr<ARDOUR::Bundle>, ARDOUR::DataType);
150         virtual bool can_remove_channels (boost::shared_ptr<ARDOUR::Bundle>) const;
151         virtual void remove_channel (ARDOUR::BundleChannel);
152         virtual void remove_all_channels (boost::weak_ptr<ARDOUR::Bundle>);
153         virtual bool can_rename_channels (boost::shared_ptr<ARDOUR::Bundle>) const {
154                 return false;
155         }
156         virtual void rename_channel (ARDOUR::BundleChannel) {}
157         virtual std::string disassociation_verb () const = 0;
158         virtual std::string channel_noun () const;
159
160         enum Result {
161                 Cancelled,
162                 Accepted
163         };
164
165         sigc::signal<void, Result> Finished;
166
167         static bool bundle_with_channels (boost::shared_ptr<ARDOUR::Bundle>);
168
169 protected:
170
171         /** We have two port group lists.  One will be presented on the rows of the matrix,
172             the other on the columns.  The PortMatrix chooses the arrangement based on which has
173             more ports in it.  Subclasses must fill these two lists with the port groups that they
174             wish to present.  The PortMatrix will arrange its layout such that signal flow is vaguely
175             from left to right as you go from list 0 to list 1.  Hence subclasses which deal with
176             inputs and outputs should put outputs in list 0 and inputs in list 1. */
177         PortGroupList _ports[2];
178
179 private:
180
181         void hscroll_changed ();
182         void vscroll_changed ();
183         void routes_changed ();
184         void reconnect_to_routes ();
185         void select_arrangement ();
186         bool can_add_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, ARDOUR::DataType) const;
187         void add_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, ARDOUR::DataType);
188         void remove_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, uint32_t);
189         void rename_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, uint32_t);
190         void disassociate_all_on_channel (boost::weak_ptr<ARDOUR::Bundle>, uint32_t, int);
191         void disassociate_all_on_bundle (boost::weak_ptr<ARDOUR::Bundle>, int);
192         void setup_global_ports ();
193         void setup_global_ports_proxy ();
194         void toggle_show_only_bundles ();
195         bool on_scroll_event (GdkEventScroll *);
196         boost::shared_ptr<ARDOUR::IO> io_from_bundle (boost::shared_ptr<ARDOUR::Bundle>) const;
197         void setup_notebooks ();
198         void remove_notebook_pages (Gtk::Notebook &);
199         void notebook_page_selected (GtkNotebookPage *, guint);
200         void route_processors_changed (ARDOUR::RouteProcessorChange);
201         void body_dimensions_changed ();
202         void session_going_away ();
203         void add_remove_option (Gtk::Menu_Helpers::MenuList &, boost::weak_ptr<ARDOUR::Bundle>, int);
204         void add_disassociate_option (Gtk::Menu_Helpers::MenuList &, boost::weak_ptr<ARDOUR::Bundle>, int, int);
205         void port_connected_or_disconnected ();
206         void update_tab_highlighting ();
207         std::pair<int, int> check_flip () const;
208         bool can_flip () const;
209
210         Gtk::Window* _parent;
211
212         /** port type that we are working with, or NIL if we are working with all of them */
213         ARDOUR::DataType _type;
214         PBD::ScopedConnectionList _route_connections;
215         PBD::ScopedConnectionList _changed_connections;
216         PBD::ScopedConnectionList _bundle_changed_connections;
217
218         PortMatrixBody* _body;
219         Gtk::HScrollbar _hscroll;
220         Gtk::VScrollbar _vscroll;
221         Gtk::Notebook _vnotebook;
222         Gtk::Notebook _hnotebook;
223         Gtk::Label _vlabel;
224         Gtk::Label _hlabel;
225         Gtk::VBox _vbox;
226         Gtk::HBox _hbox;
227         Gtk::Label _hspacer;
228         Gtk::Label _vspacer;
229         Gtk::Menu* _menu;
230         Arrangement _arrangement;
231         int _row_index;
232         int _column_index;
233         int _min_height_divisor;
234         bool _show_only_bundles;
235         bool _inhibit_toggle_show_only_bundles;
236         bool _ignore_notebook_page_selected;
237 };
238
239 #endif