incomplete merge of master into windows (requires upcoming changes to master to be...
[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 <glibmm.h>
26 #include <gdkmm.h>
27
28 #include "pbd/pathscanner.h"
29
30 #include "gtkmm2ext/keyboard.h"
31 #include "gtkmm2ext/selector.h"
32 #include "gtkmm2ext/utils.h"
33
34 using namespace std;
35 using namespace Gtkmm2ext;
36
37 Selector::Selector (void (*func)(Glib::RefPtr<Gtk::ListStore>, void *), void *arg,
38                     vector<string> titles)
39 {
40         scroll.add (tview);
41         scroll.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
42
43         pack_start (scroll, true, true);
44
45         vector<string>::iterator i;
46         for (i = titles.begin(); i != titles.end(); ++i) {
47                 Gtk::TreeModelColumn<Glib::ustring> title;
48                 column_records.add(title);
49         }
50
51         lstore = Gtk::ListStore::create(column_records);
52         tview.set_model(lstore);
53
54         update_contents.connect(mem_fun(*this,&Selector::rescan));
55
56         tview.show ();
57
58         refiller = func;
59         refill_arg = arg;
60         selected_row = -1;
61         selected_column = -1;
62 }
63
64 Selector::~Selector ()
65
66 {
67         /* ensure that any row data set with set_row_data_full() is deleted */
68         hide_all ();
69         lstore.clear ();
70 }
71
72 void
73 Selector::on_map()
74
75 {
76         Gtk::VBox::on_map ();
77
78         selected_row = -1;
79         selected_column = -1;
80         refill();
81 }
82
83 void
84 Selector::on_show()
85 {
86         VBox::on_show();
87
88         rescan();
89 }
90
91 void
92 Selector::reset (void (*func)(Glib::RefPtr<Gtk::ListStore>, void *), void *arg)
93
94 {
95         refiller = func;
96         refill_arg = arg;
97         selected_row = -1;
98         selected_column = -1;
99
100         refill();
101 }
102
103 void
104 Selector::refill ()
105
106 {
107         if (refiller) {
108                 lstore.clear ();
109                 refiller (lstore, refill_arg);
110         }
111 }
112
113 gint
114 Selector::_accept (gpointer arg)
115
116 {
117         ((Selector *) arg)->accept ();
118         return FALSE;
119 }
120
121 gint
122 Selector::_chosen (gpointer arg)
123
124 {
125         ((Selector *) arg)->chosen ();
126         return FALSE;
127 }
128
129 gint
130 Selector::_shift_clicked (gpointer arg)
131 {
132         ((Selector *) arg)->shift_clicked ();
133         return FALSE;
134 }
135
136 gint
137 Selector::_control_clicked (gpointer arg)
138 {
139         ((Selector *) arg)->control_clicked ();
140         return FALSE;
141 }
142
143 void
144 Selector::accept ()
145 {
146         Glib::RefPtr<Gtk::TreeSelection> tree_sel = tview.get_selection();
147         Gtk::TreeModel::iterator iter = tree_sel->get_selected();
148
149         if (iter) {
150
151                 selection_made (new Result (tview, tree_sel));
152         } else {
153                 cancel ();
154         }
155 }
156
157 void
158 Selector::chosen ()
159 {
160         Glib::RefPtr<Gtk::TreeSelection> tree_sel = tview.get_selection();
161         Gtk::TreeModel::iterator iter = tree_sel->get_selected();
162         
163         if (iter) {
164                 choice_made (new Result (tview, tree_sel));
165         } else {
166                 cancel ();
167         }
168 }
169
170 void
171 Selector::shift_clicked ()
172 {
173         Glib::RefPtr<Gtk::TreeSelection> tree_sel = tview.get_selection();
174         Gtk::TreeModel::iterator iter = tree_sel->get_selected();
175
176         if (iter) {
177                 shift_made (new Result (tview, tree_sel));
178         } else {
179                 cancel ();
180         }
181 }
182
183 void
184 Selector::control_clicked ()
185 {
186         Glib::RefPtr<Gtk::TreeSelection> tree_sel = tview.get_selection();
187         Gtk::TreeModel::iterator iter = tree_sel->get_selected();
188
189         if (iter) {
190                 control_made (new Result (tview, tree_sel));
191         } else {
192                 cancel ();
193         }
194 }
195
196 void
197 Selector::cancel ()
198 {
199         Glib::RefPtr<Gtk::TreeSelection> tree_sel = tview.get_selection();
200         tree_sel->unselect_all();
201
202         selection_made (new Result (tview, tree_sel));
203 }
204
205 void
206 Selector::rescan ()
207
208 {
209         selected_row = -1;
210         selected_column = -1;
211         refill ();
212         show_all ();
213 }
214
215 struct string_cmp {
216     bool operator()(const string* a, const string* b) {
217             return *a < *b;
218     }
219 };
220
221 bool
222 TreeView_Selector::on_button_press_event(GdkEventButton* ev)
223 {
224         bool return_value = TreeView::on_button_press_event(ev);
225
226         if (ev && (ev->type == GDK_BUTTON_RELEASE || ev->type == GDK_2BUTTON_PRESS)) {
227                 if (ev->state & Keyboard::PrimaryModifier) {
228                         g_idle_add (Selector::_control_clicked, this);
229                 } else if (ev->state & Keyboard::TertiaryModifier) {
230                         g_idle_add (Selector::_shift_clicked, this);
231                 } else if (ev->type == GDK_2BUTTON_PRESS) {
232                         g_idle_add (Selector::_accept, this);
233                 } else {
234                         g_idle_add (Selector::_chosen, this);
235                 }
236         }
237
238         return return_value;
239 }