Port port group type labels in-line with the tabs.
[ardour.git] / gtk2_ardour / port_matrix.h
1 /*
2     Copyright (C) 2002-2009 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 #ifndef __gtk_ardour_port_matrix_h__
21 #define __gtk_ardour_port_matrix_h__
22
23 #include <list>
24 #include <gtkmm/box.h>
25 #include <gtkmm/scrollbar.h>
26 #include <gtkmm/table.h>
27 #include <gtkmm/label.h>
28 #include <gtkmm/checkbutton.h>
29 #include <gtkmm/notebook.h>
30 #include <boost/shared_ptr.hpp>
31 #include "ardour/bundle.h"
32 #include "port_group.h"
33 #include "port_matrix_types.h"
34 #include "i18n.h"
35
36 /** The `port matrix' UI.  This is a widget which lets the user alter
37  *  associations between one set of ports and another.  e.g. to connect
38  *  things together.
39  *
40  *  It is made up of a body, PortMatrixBody, which is rendered using cairo,
41  *  and some scrollbars and other stuff.  All of this is arranged inside the
42  *  Table that we inherit from.
43  */
44
45 namespace ARDOUR {
46         class Bundle;
47 }
48
49 class PortMatrixBody;
50
51 class PortMatrix : public Gtk::Table
52 {
53 public:
54         PortMatrix (Gtk::Window*, ARDOUR::Session&, ARDOUR::DataType);
55         ~PortMatrix ();
56
57         void set_type (ARDOUR::DataType);
58
59         ARDOUR::DataType type () const {
60                 return _type;
61         }
62
63         void disassociate_all ();
64         void setup_scrollbars ();
65         void popup_menu (ARDOUR::BundleChannel, ARDOUR::BundleChannel, uint32_t);
66
67         int min_height_divisor () const {
68                 return _min_height_divisor;
69         }
70         void set_min_height_divisor (int f) {
71                 _min_height_divisor = f;
72         }
73
74         enum Arrangement {
75                 TOP_TO_RIGHT,  ///< column labels on top, row labels to the right
76                 LEFT_TO_BOTTOM ///< row labels to the left, column labels on the bottom
77         };
78
79         
80         /** @return Arrangement in use */
81         Arrangement arrangement () const {
82                 return _arrangement;
83         }
84
85         bool show_only_bundles () const {
86                 return _show_only_bundles;
87         }
88
89         PortGroupList const * columns () const;
90         boost::shared_ptr<PortGroup> visible_columns () const;
91
92         /** @return index into the _ports array for the list which is displayed as columns */
93         int column_index () const {
94                 return _column_index;
95         }
96
97         PortGroupList const * rows () const;
98         boost::shared_ptr<PortGroup> visible_rows () const;
99
100         /** @return index into the _ports array for the list which is displayed as rows */
101         int row_index () const {
102                 return _row_index;
103         }
104
105         PortGroupList const * ports (int d) const {
106                 return &_ports[d];
107         }
108
109         boost::shared_ptr<const PortGroup> visible_ports (int d) const {
110                 return _visible_ports[d];
111         }
112         
113         void init ();
114         void setup ();
115         virtual void setup_ports (int) = 0;
116         void setup_all_ports ();
117
118         std::pair<uint32_t, uint32_t> max_size () const;
119
120         /** @param c Channels; where c[0] is from _ports[0] and c[1] is from _ports[1].
121          *  @param s New state.
122          */
123         virtual void set_state (ARDOUR::BundleChannel c[2], bool s) = 0;
124
125         /** @param c Channels; where c[0] is from _ports[0] and c[1] is from _ports[1].
126          *  @return state
127          */
128         virtual PortMatrixNode::State get_state (ARDOUR::BundleChannel c[2]) const = 0;
129         virtual bool list_is_global (int) const = 0;
130
131         virtual bool can_add_channel (boost::shared_ptr<ARDOUR::Bundle>) const;
132         virtual void add_channel (boost::shared_ptr<ARDOUR::Bundle>);
133         virtual bool can_remove_channels (boost::shared_ptr<ARDOUR::Bundle>) const;
134         virtual void remove_channel (ARDOUR::BundleChannel);
135         virtual bool can_rename_channels (boost::shared_ptr<ARDOUR::Bundle>) const {
136                 return false;
137         }
138         virtual void rename_channel (ARDOUR::BundleChannel) {}
139         virtual std::string disassociation_verb () const = 0;
140         virtual std::string channel_noun () const { return _("channel"); }
141
142         enum Result {
143                 Cancelled,
144                 Accepted
145         };
146
147         sigc::signal<void, Result> Finished;
148
149 protected:
150
151         /** We have two port group lists.  One will be presented on the rows of the matrix,
152             the other on the columns.  The PortMatrix chooses the arrangement based on which has
153             more ports in it.  Subclasses must fill these two lists with the port groups that they
154             wish to present.  The PortMatrix will arrange its layout such that signal flow is vaguely
155             from left to right as you go from list 0 to list 1.  Hence subclasses which deal with
156             inputs and outputs should put outputs in list 0 and inputs in list 1. */
157         PortGroupList _ports[2];
158         boost::shared_ptr<PortGroup> _visible_ports[2];
159         ARDOUR::Session& _session;
160
161 private:
162
163         void hscroll_changed ();
164         void vscroll_changed ();
165         void routes_changed ();
166         void reconnect_to_routes ();
167         void select_arrangement ();
168         void add_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>);
169         void remove_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, uint32_t);
170         void rename_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, uint32_t);
171         void disassociate_all_on_channel (boost::weak_ptr<ARDOUR::Bundle>, uint32_t, int);
172         void setup_global_ports ();
173         void toggle_show_only_bundles ();
174         bool on_scroll_event (GdkEventScroll *);
175         boost::shared_ptr<ARDOUR::IO> io_from_bundle (boost::shared_ptr<ARDOUR::Bundle>) const;
176         void bundle_changed (ARDOUR::Bundle::Change);
177         void setup_notebooks ();
178         void remove_notebook_pages (Gtk::Notebook &);
179         void v_page_selected (GtkNotebookPage *, guint);
180         void h_page_selected (GtkNotebookPage *, guint);
181
182         Gtk::Window* _parent;
183
184         /// port type that we are working with
185         ARDOUR::DataType _type;
186         std::vector<sigc::connection> _route_connections;
187
188         PortMatrixBody* _body;
189         Gtk::HScrollbar _hscroll;
190         Gtk::VScrollbar _vscroll;
191         Gtk::Notebook _vnotebook;
192         Gtk::Notebook _hnotebook;
193         Gtk::Label _vlabel;
194         Gtk::Label _hlabel;
195         Gtk::VBox _vbox;
196         Gtk::HBox _hbox;
197         Gtk::Menu* _menu;
198         Arrangement _arrangement;
199         int _row_index;
200         int _column_index;
201         int _min_height_divisor;
202         bool _show_only_bundles;
203         bool _inhibit_toggle_show_only_bundles;
204         bool _in_setup_notebooks;
205 };
206
207 #endif