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