Bit of a hack to make the port matrix for port inserts at least vaguely usable.
[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 <boost/shared_ptr.hpp>
30 #include "ardour/bundle.h"
31 #include "port_group.h"
32
33 /** The `port matrix' UI.  This is a widget which lets the user alter
34  *  associations between one set of ports and another.  e.g. to connect
35  *  things together.
36  *
37  *  It is made up of a body, PortMatrixBody, which is rendered using cairo,
38  *  and some scrollbars and other stuff.  All of this is arranged inside the
39  *  VBox that we inherit from.
40  */
41
42 namespace ARDOUR {
43         class Bundle;
44 }
45
46 class PortMatrixBody;
47
48 class PortMatrix : public Gtk::VBox
49 {
50 public:
51         PortMatrix (ARDOUR::Session&, ARDOUR::DataType);
52         ~PortMatrix ();
53
54         void set_type (ARDOUR::DataType);
55
56         ARDOUR::DataType type () const {
57                 return _type;
58         }
59         
60         void disassociate_all ();
61         void setup_scrollbars ();
62         void popup_channel_context_menu (int, uint32_t, uint32_t);
63
64         int min_height_divisor () const {
65                 return _min_height_divisor;
66         }
67         void set_min_height_divisor (int f) {
68                 _min_height_divisor = f;
69         }
70
71         enum Arrangement {
72                 TOP_TO_RIGHT,  ///< column labels on top, row labels to the right
73                 LEFT_TO_BOTTOM ///< row labels to the left, column labels on the bottom
74         };
75
76         /** @return Arrangement in use */
77         Arrangement arrangement () const {
78                 return _arrangement;
79         }
80
81         PortGroupList const * columns () const;
82
83         /** @return index into the _ports array for the list which is displayed as columns */
84         int column_index () const {
85                 return _column_index;
86         }
87
88         PortGroupList const * rows () const;
89
90         /** @return index into the _ports array for the list which is displayed as rows */
91         int row_index () const {
92                 return _row_index;
93         }
94
95         PortGroupList const * ports (int d) const {
96                 return &_ports[d];
97         }
98         
99         void setup ();
100         virtual void setup_ports (int) = 0;
101         void setup_all_ports ();
102
103         /** @param c Channels; where c[0] is from _ports[0] and c[1] is from _ports[1].
104          *  @param s New state.
105          */
106         virtual void set_state (ARDOUR::BundleChannel c[2], bool s) = 0;
107
108         enum State {
109                 ASSOCIATED,     ///< the ports are associaed
110                 NOT_ASSOCIATED, ///< the ports are not associated
111                 UNKNOWN         ///< we don't know anything about these two ports' relationship
112         };
113
114         /** @param c Channels; where c[0] is from _ports[0] and c[1] is from _ports[1].
115          *  @return state
116          */
117         virtual State get_state (ARDOUR::BundleChannel c[2]) const = 0;
118         virtual bool list_is_global (int) const = 0;
119
120         virtual void add_channel (boost::shared_ptr<ARDOUR::Bundle>) = 0;
121         virtual bool can_remove_channels (int) const = 0;
122         virtual void remove_channel (ARDOUR::BundleChannel) = 0;
123         virtual bool can_rename_channels (int) const = 0;
124         virtual void rename_channel (ARDOUR::BundleChannel) {}
125         
126         enum Result {
127                 Cancelled,
128                 Accepted
129         };
130
131         sigc::signal<void, Result> Finished;
132
133 protected:
134
135         /** We have two port group lists.  One will be presented on the rows of the matrix,
136             the other on the columns.  The PortMatrix chooses the arrangement based on which has
137             more ports in it.  Subclasses must fill these two lists with the port groups that they
138             wish to present.  The PortMatrix will arrange its layout such that signal flow is vaguely
139             from left to right as you go from list 0 to list 1.  Hence subclasses which deal with
140             inputs and outputs should put outputs in list 0 and inputs in list 1. */
141         PortGroupList _ports[2];
142         ARDOUR::Session& _session;
143         
144 private:
145
146         void hscroll_changed ();
147         void vscroll_changed ();
148         void routes_changed ();
149         void reconnect_to_routes ();
150         void visibility_toggled (boost::weak_ptr<PortGroup>, Gtk::CheckButton *);
151         void select_arrangement ();
152         void remove_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, uint32_t);
153         void rename_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, uint32_t);
154         void disassociate_all_on_channel (boost::weak_ptr<ARDOUR::Bundle>, uint32_t, int);
155         void setup_global_ports ();
156
157         /// port type that we are working with
158         ARDOUR::DataType _type;
159         std::vector<sigc::connection> _route_connections;
160
161         PortMatrixBody* _body;
162         Gtk::HScrollbar _hscroll;
163         Gtk::VScrollbar _vscroll;
164         Gtk::HBox _main_hbox;
165         Gtk::HBox _column_visibility_box;
166         bool _column_visibility_box_added;
167         Gtk::Label _column_visibility_label;
168         std::vector<Gtk::CheckButton*> _column_visibility_buttons;
169         Gtk::VBox _row_visibility_box;
170         bool _row_visibility_box_added;
171         Gtk::Label _row_visibility_label;
172         std::vector<Gtk::CheckButton*> _row_visibility_buttons;
173         Gtk::Table _scroller_table;
174         Gtk::Menu* _menu;
175         bool _setup_once;
176         Arrangement _arrangement;
177         int _row_index;
178         int _column_index;
179         int _min_height_divisor;
180 };
181
182 #endif