fulfill the promise of an in-library Keyboard object, and use platform specific modif...
[ardour.git] / libs / gtkmm2ext / selector.cc
1 /*
2     Copyright (C) 1999 Paul Barton-Davis 
3     This program is free software; you can redistribute it and/or modify
4     it under the terms of the GNU General Public License as published by
5     the Free Software Foundation; either version 2 of the License, or
6     (at your option) any later version.
7
8     This program is distributed in the hope that it will be useful,
9     but WITHOUT ANY WARRANTY; without even the implied warranty of
10     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11     GNU General Public License for more details.
12
13     You should have received a copy of the GNU General Public License
14     along with this program; if not, write to the Free Software
15     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
17     $Id$
18 */
19
20 #include <algorithm>
21 #include <functional>
22 #include <vector>
23 #include <string>
24
25 #include "pbd/pathscanner.h"
26
27 #include "gtkmm2ext/keyboard.h"
28 #include "gtkmm2ext/selector.h"
29 #include "gtkmm2ext/utils.h"
30
31 using namespace std;
32 using namespace Gtkmm2ext;
33
34 Selector::Selector (void (*func)(Glib::RefPtr<Gtk::ListStore>, void *), void *arg,
35                     vector<string> titles)
36 {
37         scroll.add (tview);
38         scroll.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
39
40         pack_start (scroll, true, true);
41
42         vector<string>::iterator i;
43         for (i = titles.begin(); i != titles.end(); ++i) {
44                 Gtk::TreeModelColumn<Glib::ustring> title;
45                 column_records.add(title);
46         }
47
48         lstore = Gtk::ListStore::create(column_records);
49         tview.set_model(lstore);
50
51         update_contents.connect(mem_fun(*this,&Selector::rescan));
52
53         tview.show ();
54
55         refiller = func;
56         refill_arg = arg;
57         selected_row = -1;
58         selected_column = -1;
59 }
60
61 Selector::~Selector ()
62
63 {
64         /* ensure that any row data set with set_row_data_full() is deleted */
65         hide_all ();
66         lstore.clear ();
67 }
68
69 void
70 Selector::on_map()
71
72 {
73         Gtk::VBox::on_map ();
74
75         selected_row = -1;
76         selected_column = -1;
77         refill();
78 }
79
80 void
81 Selector::on_show()
82 {
83         VBox::on_show();
84
85         rescan();
86 }
87
88 void
89 Selector::reset (void (*func)(Glib::RefPtr<Gtk::ListStore>, void *), void *arg)
90
91 {
92         refiller = func;
93         refill_arg = arg;
94         selected_row = -1;
95         selected_column = -1;
96
97         refill();
98 }
99
100 void
101 Selector::refill ()
102
103 {
104         if (refiller) {
105                 lstore.clear ();
106                 refiller (lstore, refill_arg);
107         }
108 }
109
110 gint
111 Selector::_accept (gpointer arg)
112
113 {
114         ((Selector *) arg)->accept ();
115         return FALSE;
116 }
117
118 gint
119 Selector::_chosen (gpointer arg)
120
121 {
122         ((Selector *) arg)->chosen ();
123         return FALSE;
124 }
125
126 gint
127 Selector::_shift_clicked (gpointer arg)
128 {
129         ((Selector *) arg)->shift_clicked ();
130         return FALSE;
131 }
132
133 gint
134 Selector::_control_clicked (gpointer arg)
135 {
136         ((Selector *) arg)->control_clicked ();
137         return FALSE;
138 }
139
140 void
141 Selector::accept ()
142 {
143         Glib::RefPtr<Gtk::TreeSelection> tree_sel = tview.get_selection();
144         Gtk::TreeModel::iterator iter = tree_sel->get_selected();
145
146         if (iter) {
147
148                 selection_made (new Result (tview, tree_sel));
149         } else {
150                 cancel ();
151         }
152 }
153
154 void
155 Selector::chosen ()
156 {
157         Glib::RefPtr<Gtk::TreeSelection> tree_sel = tview.get_selection();
158         Gtk::TreeModel::iterator iter = tree_sel->get_selected();
159         
160         if (iter) {
161                 choice_made (new Result (tview, tree_sel));
162         } else {
163                 cancel ();
164         }
165 }
166
167 void
168 Selector::shift_clicked ()
169 {
170         Glib::RefPtr<Gtk::TreeSelection> tree_sel = tview.get_selection();
171         Gtk::TreeModel::iterator iter = tree_sel->get_selected();
172
173         if (iter) {
174                 shift_made (new Result (tview, tree_sel));
175         } else {
176                 cancel ();
177         }
178 }
179
180 void
181 Selector::control_clicked ()
182 {
183         Glib::RefPtr<Gtk::TreeSelection> tree_sel = tview.get_selection();
184         Gtk::TreeModel::iterator iter = tree_sel->get_selected();
185
186         if (iter) {
187                 control_made (new Result (tview, tree_sel));
188         } else {
189                 cancel ();
190         }
191 }
192
193 void
194 Selector::cancel ()
195 {
196         Glib::RefPtr<Gtk::TreeSelection> tree_sel = tview.get_selection();
197         tree_sel->unselect_all();
198
199         selection_made (new Result (tview, tree_sel));
200 }
201
202 void
203 Selector::rescan ()
204
205 {
206         selected_row = -1;
207         selected_column = -1;
208         refill ();
209         show_all ();
210 }
211
212 struct string_cmp {
213     bool operator()(const string* a, const string* b) {
214             return *a < *b;
215     }
216 };
217
218 bool
219 TreeView_Selector::on_button_press_event(GdkEventButton* ev)
220 {
221         bool return_value = TreeView::on_button_press_event(ev);
222
223         if (ev && (ev->type == GDK_BUTTON_RELEASE || ev->type == GDK_2BUTTON_PRESS)) {
224                 if (ev->state & Keyboard::PrimaryModifier) {
225                         g_idle_add (Selector::_control_clicked, this);
226                 } else if (ev->state & Keyboard::TertiaryModifier) {
227                         g_idle_add (Selector::_shift_clicked, this);
228                 } else if (ev->type == GDK_2BUTTON_PRESS) {
229                         g_idle_add (Selector::_accept, this);
230                 } else {
231                         g_idle_add (Selector::_chosen, this);
232                 }
233         }
234
235         return return_value;
236 }