Added scrolled window
[irreco.git] / irreco / src / core / irreco_listbox.c
bloba16cf9132168853294209d99919192cac8f8d214
1 /*
2 * irreco - Ir Remote Control
3 * Copyright (C) 2007 Arto Karppinen (arto.karppinen@iki.fi)
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "irreco_listbox.h"
22 /**
23 * @addtogroup IrrecoListbox
24 * @ingroup Irreco
26 * A base class for Irreco listbox classes.
28 * The basic structure is to have a GtkTreview widget inside a
29 * GtkScrolledWindow, and provide convenience frappers for so you dont have
30 * to deal with GtkTreview directly.
32 * That is, IrrecoListbox classes provide a simple listboxes, without all
33 * that tree nonsense.
35 * Subclasses must set these variables, or this class will not work:
36 * IRRECO_LISTBOX(self)->list_store
37 * IRRECO_LISTBOX(self)->tree_view
38 * IRRECO_LISTBOX(self)->tree_selection
39 * IRRECO_LISTBOX(self)->data_col_id
40 * IRRECO_LISTBOX(self)->text_col_id
42 * @{ @file
43 * Source file of @ref IrrecoListbox.
48 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
49 /* Prototypes. */
50 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
51 #if 0
52 static void irreco_listbox_scrolled_size_request(GtkWidget *widget,
53 GtkRequisition *requisition,
54 IrrecoListbox *self);
55 #endif
58 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
59 /* Construction & Destruction */
60 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
62 /**
63 * @name Construction & Destruction
64 * @{
67 G_DEFINE_TYPE(IrrecoListbox, irreco_listbox, GTK_TYPE_HBOX)
69 static void irreco_listbox_class_init(IrrecoListboxClass *klass)
73 static void irreco_listbox_init(IrrecoListbox *self)
75 IRRECO_ENTER
77 self->select_new_rows = TRUE;
78 gtk_box_set_spacing(GTK_BOX(self), 1);
79 #if 0
80 /* Connect signals. */
81 g_signal_connect(G_OBJECT(self), "size-request",
82 G_CALLBACK(irreco_listbox_scrolled_size_request),
83 self);
84 #endif
85 IRRECO_RETURN
88 /** @} */
92 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
93 /* Public Functions */
94 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
96 /**
97 * @name Public Functions
98 * @{
102 * Set if new rows added to the listbox will automatically be selected.
104 void irreco_listbox_set_select_new_rows(IrrecoListbox *self,
105 gboolean select_new_rows)
107 IRRECO_ENTER
108 self->select_new_rows = select_new_rows;
109 IRRECO_RETURN
112 void irreco_listbox_set_autosize(IrrecoListbox *self,
113 gint min_width,
114 gint max_width,
115 gint min_height,
116 gint max_height)
118 IRRECO_ENTER
119 if ((self->min_width = min_width) < 0) self->min_width = 0;
120 if ((self->max_width = max_width) < 0) self->max_width = 0;
121 if ((self->min_height = min_height) < 0) self->min_height = 0;
122 if ((self->max_height = max_height) < 0) self->max_height = 0;
123 IRRECO_RETURN
126 void irreco_listbox_clear(IrrecoListbox *self)
128 IRRECO_ENTER
129 gtk_list_store_clear(self->list_store);
130 IRRECO_RETURN
134 * Get GtkTreeIter for some index in the listbox.
136 gboolean irreco_listbox_get_iter(IrrecoListbox *self,
137 gint index, GtkTreeIter * iter)
139 gboolean rvalue;
140 GtkTreeModel *model;
141 GtkTreePath *path;
142 IRRECO_ENTER
144 IRRECO_DEBUG("Index \"%i\".\n", index);
145 model = gtk_tree_view_get_model(GTK_TREE_VIEW(
146 self->tree_view));
147 path = gtk_tree_path_new_from_indices(index, -1);
148 rvalue = gtk_tree_model_get_iter(model, iter, path);
149 gtk_tree_path_free(path);
150 IRRECO_RETURN_INT(rvalue);
154 * Select a row.
156 gboolean irreco_listbox_set_selection(IrrecoListbox *self, gint index)
158 GtkTreeIter iter;
159 IRRECO_ENTER
161 IRRECO_DEBUG("Selecting row \"%i\".\n", index);
162 if (irreco_listbox_get_iter(self, index, &iter)) {
163 gtk_tree_selection_select_iter(self->tree_selection, &iter);
164 IRRECO_RETURN_BOOL(TRUE);
166 IRRECO_RETURN_BOOL(FALSE);
170 * Get currect selection of listbox.
172 * @par Example
173 * @code
174 * gint sel_index = -1;
175 * gchar *sel_label = NULL;
176 * gpointer sel_user_data = NULL;
177 * irreco_listbox_get_selection(IRRECO_LISTBOX(listbox),
178 * &sel_index, &sel_label, &sel_user_data);
179 * @endcode
181 gboolean irreco_listbox_get_selection(IrrecoListbox *self,
182 gint *index,
183 gchar **label,
184 gpointer *user_data)
186 gboolean rvalue = FALSE;
187 GtkTreeIter iter;
188 GtkTreeModel *model = NULL;
189 GtkTreePath *path = NULL;
190 gint *path_indices = NULL;
191 GtkTreeSelection *selection = NULL;
192 gint sel_index = -1;
193 gchar *sel_label = NULL;
194 gpointer sel_user_data = NULL;
195 IRRECO_ENTER
197 /* Get currect selection, if set. */
198 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(self->tree_view));
199 if (gtk_tree_selection_get_selected(self->tree_selection,
200 &model, &iter)) {
201 path = gtk_tree_model_get_path(model, &iter);
202 path_indices = gtk_tree_path_get_indices(path);
203 sel_index = path_indices[0];
204 gtk_tree_path_free(path);
205 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
206 self->text_col_id, &sel_label,
207 self->data_col_id, &sel_user_data,
208 -1);
209 rvalue = TRUE;
212 IRRECO_DEBUG("Selection \"%i\" \"%s\" \"%p\"\n",
213 sel_index, sel_label, sel_user_data);
215 /* Store values to pointers. */
216 if (index) *index = sel_index;
217 if (user_data) *user_data = sel_user_data;
218 if (label) {
219 *label = sel_label;
220 } else {
221 g_free(label);
224 IRRECO_RETURN_BOOL(rvalue);
227 gint irreco_listbox_get_selection_index(IrrecoListbox *self)
229 gint sel_index = -1;
230 IRRECO_ENTER;
232 irreco_listbox_get_selection(self, &sel_index, NULL, NULL);
233 IRRECO_RETURN_INT(sel_index);
236 gchar *irreco_listbox_get_selection_label(IrrecoListbox *self)
238 gchar *sel_label = NULL;
239 IRRECO_ENTER;
241 irreco_listbox_get_selection(self, NULL, &sel_label, NULL);
242 IRRECO_RETURN_STR(sel_label);
245 gpointer irreco_listbox_get_selection_data(IrrecoListbox *self)
247 gpointer sel_user_data = NULL;
248 IRRECO_ENTER;
250 irreco_listbox_get_selection(self, NULL, NULL, &sel_user_data);
251 IRRECO_RETURN_PTR(sel_user_data);
255 * Move the currently selected row upwards.
257 gboolean irreco_listbox_move_selected_up(IrrecoListbox *self)
259 gint sel_index;
260 IRRECO_ENTER
262 sel_index = irreco_listbox_get_selection_index(self);
263 if (sel_index == -1) IRRECO_RETURN_BOOL(FALSE);
264 IRRECO_RETURN_BOOL(irreco_listbox_move(
265 self, sel_index, sel_index - 1));
269 * Move the currently selected row downwards.
271 gboolean irreco_listbox_move_selected_down(IrrecoListbox *self)
273 gint sel_index;
274 IRRECO_ENTER
276 sel_index = irreco_listbox_get_selection_index(self);
277 if (sel_index == -1) IRRECO_RETURN_BOOL(FALSE);
278 IRRECO_RETURN_BOOL(irreco_listbox_move(
279 self, sel_index, sel_index + 1));
282 gboolean irreco_listbox_move(IrrecoListbox *self,
283 gint from_index,
284 gint to_index)
286 GtkTreeIter from_iter;
287 GtkTreeIter to_iter;
288 IRRECO_ENTER
290 /* Check indices. We assume that below zero means first,
291 and above list lenght means last. */
292 if (from_index < 0) {
293 from_index = 0;
294 } else if (from_index > self->list_store->length) {
295 IRRECO_RETURN_BOOL(FALSE);
298 if (to_index > self->list_store->length) {
299 to_index = self->list_store->length;
300 } else if (to_index < 0) {
301 IRRECO_RETURN_BOOL(FALSE);
304 IRRECO_DEBUG("Moving item from index \"%i\" to index \"%i\".\n",
305 from_index, to_index);
307 if (irreco_listbox_get_iter(self, from_index, &from_iter)
308 && irreco_listbox_get_iter(self, to_index, &to_iter)) {
309 if (from_index > to_index) {
310 IRRECO_DEBUG("Moving up.\n");
311 gtk_list_store_move_before(self->list_store,
312 &from_iter, &to_iter);
313 } else {
314 IRRECO_DEBUG("Moving down.\n");
315 gtk_list_store_move_after(self->list_store,
316 &from_iter, &to_iter);
319 /* Set selection to the moved row. */
320 if (gtk_tree_selection_iter_is_selected(
321 self->tree_selection, &from_iter)) {
322 } else {
323 gtk_tree_selection_select_iter(self->tree_selection,
324 &from_iter);
327 IRRECO_RETURN_BOOL(TRUE);
330 IRRECO_RETURN_BOOL(FALSE);
333 gboolean irreco_listbox_remove_selected(IrrecoListbox *self)
335 gint index;
336 GtkTreeIter iter;
337 gint sel_index;
338 IRRECO_ENTER
340 sel_index = irreco_listbox_get_selection_index(self);
341 if ((index = sel_index) == -1
342 || irreco_listbox_get_iter(self, index, &iter) == FALSE) {
343 IRRECO_RETURN_BOOL(FALSE);
346 /* Attemt to select another row before we destroy the current one.
347 This helps to prevent double selection changed events being sent,
348 when the old row is destroyed (and thus unselected) and selecting
349 another row afterwards. */
350 irreco_listbox_set_selection(self, index - 1)
351 || irreco_listbox_set_selection(self, index + 1);
353 gtk_list_store_remove(self->list_store, &iter);
354 IRRECO_RETURN_BOOL(TRUE);
357 gboolean irreco_listbox_remove(IrrecoListbox *self, gint index)
359 GtkTreeIter iter;
360 IRRECO_ENTER
362 if (irreco_listbox_get_iter(self, index, &iter) == FALSE) {
363 IRRECO_RETURN_BOOL(FALSE);
365 gtk_list_store_remove(self->list_store, &iter);
366 IRRECO_RETURN_BOOL(TRUE);
369 /** @} */
373 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
374 /* Events and Callbacks */
375 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
378 * @name Events and Callbacks
379 * @{
381 #if 0
382 static void irreco_listbox_scrolled_size_request(GtkWidget *widget,
383 GtkRequisition *requisition,
384 IrrecoListbox *self)
386 IRRECO_ENTER
388 if (requisition->width < self->min_width) {
389 requisition->width = self->min_width;
390 } else if (requisition->width > self->max_width) {
391 requisition->width = self->max_width;
394 if (requisition->height < self->min_height) {
395 requisition->height = self->min_height;
396 } else if (requisition->height > self->max_height) {
397 requisition->height = self->max_height;
400 IRRECO_RETURN
402 #endif
403 /** @} */
405 /** @} */