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