* made channel selector look quite nice, see http://www.flickr.com/photos/24012642...
[ardour.git] / gtk2_ardour / midi_channel_selector.cc
1 #include "midi_channel_selector.h"
2 #include "gtkmm/separator.h"
3 #include "i18n.h"
4 #include <sstream>
5
6 using namespace std;
7 using namespace Gtk;
8 using namespace sigc;
9
10 MidiChannelSelector::MidiChannelSelector(int no_rows, int no_columns, int start_row, int start_column) :
11         Table(no_rows, no_columns, true)
12 {       
13         assert(no_rows >= 4);
14         assert(no_rows >= start_row + 4);
15         assert(no_columns >=4);
16         assert(no_columns >= start_column + 4);
17         
18         property_column_spacing() = 0;
19         property_row_spacing() = 0;
20         
21         uint8_t channel_nr = 0;
22         for(int row = 0; row < 4; ++row) {
23                 for(int column = 0; column < 4; ++column) {
24                         ostringstream channel;
25                         channel << int(++channel_nr);
26                         _button_labels[row][column].set_text(channel.str());
27                         _button_labels[row][column].set_justify(JUSTIFY_RIGHT);
28                         _buttons[row][column].add(_button_labels[row][column]);
29                         _buttons[row][column].signal_toggled().connect(
30                                 bind(
31                                         mem_fun(this, &MidiChannelSelector::button_toggled),
32                                         &_buttons[row][column],
33                                         channel_nr - 1));
34
35                         int table_row    = start_row + row;
36                         int table_column = start_column + column;
37                         attach(_buttons[row][column], table_column, table_column + 1, table_row, table_row + 1);
38                 }
39         }
40 }
41
42 MidiChannelSelector::~MidiChannelSelector()
43 {
44 }
45
46 SingleMidiChannelSelector::SingleMidiChannelSelector(uint8_t active_channel)
47         : MidiChannelSelector()
48 {
49         _active_button = 0;
50         ToggleButton *button = &_buttons[active_channel / 4][active_channel % 4];
51         button->set_active(true);
52         _active_button = button;
53         _active_channel = active_channel;
54 }
55
56 void
57 SingleMidiChannelSelector::button_toggled(ToggleButton *button, uint8_t channel)
58 {
59         if(button->get_active()) {
60                 if(_active_button) {
61                         _active_button->set_active(false);
62                 }
63                 _active_button = button;
64                 _active_channel = channel;
65                 channel_selected.emit(channel);
66         } 
67 }
68
69 MidiMultipleChannelSelector::MidiMultipleChannelSelector(uint16_t initial_selection)
70         : MidiChannelSelector(4, 6, 0, 0)
71 {
72         _select_all.add(*manage(new Label(_("All"))));
73         _select_all.signal_clicked().connect(
74                         bind(mem_fun(this, &MidiMultipleChannelSelector::select_all), true));
75         
76         _select_none.add(*manage(new Label(_("None"))));
77         _select_none.signal_clicked().connect(
78                         bind(mem_fun(this, &MidiMultipleChannelSelector::select_all), false));
79         
80         _invert_selection.add(*manage(new Label(_("Invert"))));
81         _invert_selection.signal_clicked().connect(
82                         mem_fun(this, &MidiMultipleChannelSelector::invert_selection));
83         
84         _force_channel.add(*manage(new Label(_("Force"))));
85
86         set_homogeneous(false);
87         attach(*manage(new VSeparator()), 4, 5, 0, 4, SHRINK, FILL, 0, 0);
88         //set_row_spacing(4, -5);
89         attach(_select_all,       5, 6, 0, 1);
90         attach(_select_none,      5, 6, 1, 2);
91         attach(_invert_selection, 5, 6, 2, 3);
92         attach(_force_channel,    5, 6, 3, 4);
93         
94         _selected_channels = 0;
95         for(uint16_t i = 0; i < 16; i++) {
96                 ToggleButton *button = &_buttons[i / 4][i % 4];
97                 if(initial_selection & (1L << i)) {
98                         button->set_active(true);
99                 } else {
100                         button->set_active(false);
101                 }
102         }
103 }
104
105 void
106 MidiMultipleChannelSelector::button_toggled(ToggleButton *button, uint8_t channel)
107 {
108         _selected_channels = _selected_channels ^ (1L << channel); 
109         selection_changed.emit(_selected_channels);
110 }
111
112 void 
113 MidiMultipleChannelSelector::select_all(bool on)
114 {
115         for(uint16_t i = 0; i < 16; i++) {
116                 ToggleButton *button = &_buttons[i / 4][i % 4];
117                 button->set_active(on);
118         }
119         selection_changed.emit(_selected_channels);
120 }
121
122 void 
123 MidiMultipleChannelSelector::invert_selection(void)
124 {
125         for(uint16_t i = 0; i < 16; i++) {
126                 ToggleButton *button = &_buttons[i / 4][i % 4];
127                 if(button->get_active()) {
128                         button->set_active(false);
129                 } else {
130                         button->set_active(true);
131                 }
132         }
133         selection_changed.emit(_selected_channels);
134 }
135