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