Contents of /trunk/src/list.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 146 - (show annotations)
Thu Mar 26 12:35:38 2009 UTC (15 years, 2 months ago) by harbaum
File MIME type: text/plain
File size: 8430 byte(s)
Generic selection list widget
1 /*
2 * Copyright (C) 2008 Till Harbaum <till@harbaum.org>.
3 *
4 * This file is part of OSM2Go.
5 *
6 * OSM2Go is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * OSM2Go is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with OSM2Go. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /*
21 * list.c - generic implementation of a list style widget:
22 *
23 * +---------+-----------+
24 * | Key | Key |
25 * +---------+-----------+
26 * | Test1 Test2 ^|
27 * | Test3 Test4 #|
28 * | ||
29 * | v|
30 * +---------------------+
31 * ( Add )( Edit )(Remove)
32 */
33
34 #include "appdata.h"
35
36 #include <stdarg.h>
37
38 static const char *list_button_id_to_name(list_button_t id) {
39 const char *names[] = { "btn_new", "btn_edit", "btn_remove",
40 "btn_user0", "btn_user1", "btn_user2" };
41 g_assert(id < 6);
42 return names[id];
43 }
44
45 GtkWidget *list_get_view(GtkWidget *list) {
46 return g_object_get_data(G_OBJECT(list), "view");
47 }
48
49 /* a list supports up to three user defined buttons besides */
50 /* add, edit and remove */
51 void list_set_user_buttons(GtkWidget *list, ...) {
52 va_list ap;
53 GtkWidget *table = g_object_get_data(G_OBJECT(list), "table");
54 void *data = g_object_get_data(G_OBJECT(list), "userdata");
55
56 /* make space for user buttons */
57 gtk_table_resize(GTK_TABLE(table), 2, 3);
58
59 va_start(ap, list);
60 list_button_t id = va_arg(ap, list_button_t);
61 while(id) {
62 char *label = va_arg(ap, char*);
63 GCallback cb = va_arg(ap, GCallback);
64
65 GtkWidget *button = gtk_button_new_with_label(label);
66 gtk_table_attach_defaults(GTK_TABLE(table), button,
67 id-LIST_BUTTON_USER0, id-LIST_BUTTON_USER0+1, 1, 2);
68 g_object_set_data(G_OBJECT(list), list_button_id_to_name(id), button);
69 gtk_signal_connect(GTK_OBJECT(button), "clicked",
70 GTK_SIGNAL_FUNC(cb), data);
71
72 id = va_arg(ap, list_button_t);
73 }
74
75 va_end(ap);
76 }
77
78 void list_set_columns(GtkWidget *list, ...) {
79 va_list ap;
80 GtkWidget *view = g_object_get_data(G_OBJECT(list), "view");
81
82 va_start(ap, list);
83 char *name = va_arg(ap, char*);
84 while(name) {
85 int hlkey = -1, key = va_arg(ap, int);
86 int flags = va_arg(ap, int);
87
88 if(flags & LIST_FLAG_CAN_HIGHLIGHT)
89 hlkey = va_arg(ap, int);
90
91 GtkTreeViewColumn *column = NULL;
92 if(!(flags & LIST_FLAG_STOCK_ICON)) {
93 GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
94 g_object_set(renderer,
95 "ellipsize", PANGO_ELLIPSIZE_END,
96 (flags & LIST_FLAG_CAN_HIGHLIGHT)?"background":NULL, "red",
97 NULL );
98 column = gtk_tree_view_column_new_with_attributes(name, renderer,
99 "text", key,
100 (flags & LIST_FLAG_CAN_HIGHLIGHT)?"background-set":NULL, hlkey,
101 NULL);
102 gtk_tree_view_column_set_expand(column, flags & LIST_FLAG_EXPAND);
103 } else {
104 GtkCellRenderer *pixbuf_renderer = gtk_cell_renderer_pixbuf_new();
105 column = gtk_tree_view_column_new_with_attributes(name,
106 pixbuf_renderer, "stock_id", key, NULL);
107 }
108
109 gtk_tree_view_insert_column(GTK_TREE_VIEW(view), column, -1);
110
111 name = va_arg(ap, char*);
112 }
113
114 va_end(ap);
115 }
116
117 static GtkWidget *list_button_get(GtkWidget *list, list_button_t id) {
118 return g_object_get_data(G_OBJECT(list), list_button_id_to_name(id));
119 }
120
121 void list_button_connect(GtkWidget *list, list_button_t id,
122 GCallback cb, gpointer data) {
123 GtkWidget *but = list_button_get(list, id);
124 gtk_signal_connect(GTK_OBJECT(but), "clicked", GTK_SIGNAL_FUNC(cb), data);
125 }
126
127 /* put a custom widget into one of the button slots */
128 void list_set_custom_user_button(GtkWidget *list, list_button_t id,
129 GtkWidget *widget) {
130 GtkWidget *table = g_object_get_data(G_OBJECT(list), "table");
131 g_assert((id >= 3) && (id < 6));
132
133 /* make space for user buttons */
134 gtk_table_resize(GTK_TABLE(table), 2, 3);
135
136 gtk_table_attach_defaults(GTK_TABLE(table), widget,
137 id-LIST_BUTTON_USER0, id-LIST_BUTTON_USER0+1, 1, 2);
138 g_object_set_data(G_OBJECT(list), list_button_id_to_name(id), widget);
139 }
140
141 GtkTreeSelection *list_get_selection(GtkWidget *list) {
142 GtkWidget *view = g_object_get_data(G_OBJECT(list), "view");
143 return gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
144 }
145
146 void list_button_enable(GtkWidget *list, list_button_t id, gboolean enable) {
147 GtkWidget *but = list_button_get(list, id);
148 gtk_widget_set_sensitive(but, enable);
149 }
150
151 void list_set_store(GtkWidget *list, GtkListStore *store) {
152 gtk_tree_view_set_model(
153 GTK_TREE_VIEW(g_object_get_data(G_OBJECT(list), "view")),
154 GTK_TREE_MODEL(store));
155 }
156
157 void list_set_selection_function(GtkWidget *list, GtkTreeSelectionFunc func,
158 gpointer data) {
159 GtkWidget *view = g_object_get_data(G_OBJECT(list), "view");
160 gtk_tree_selection_set_select_function(
161 gtk_tree_view_get_selection(GTK_TREE_VIEW(view)),
162 func, data, NULL);
163 }
164
165 /* default selection function enables edit and remove if a row is being */
166 /* selected */
167 static gboolean
168 list_selection_function(GtkTreeSelection *selection, GtkTreeModel *model,
169 GtkTreePath *path, gboolean path_currently_selected,
170 gpointer list) {
171 GtkTreeIter iter;
172
173 if(gtk_tree_model_get_iter(model, &iter, path)) {
174 g_assert(gtk_tree_path_get_depth(path) == 1);
175
176 list_button_enable(GTK_WIDGET(list), LIST_BUTTON_REMOVE, TRUE);
177 list_button_enable(GTK_WIDGET(list), LIST_BUTTON_EDIT, TRUE);
178 }
179
180 return TRUE; /* allow selection state to change */
181 }
182
183 void list_set_static_buttons(GtkWidget *list, GCallback cb_new,
184 GCallback cb_edit, GCallback cb_remove, gpointer data) {
185 GtkWidget *table = g_object_get_data(G_OBJECT(list), "table");
186 g_object_set_data(G_OBJECT(list), "userdata", data);
187
188 /* add the three default buttons, but keep the disabled for now */
189 GtkWidget *button = NULL;
190 if(cb_new) {
191 button = gtk_button_new_with_label(_("Add..."));
192 gtk_table_attach_defaults(GTK_TABLE(table), button, 0, 1, 0, 1);
193 gtk_widget_set_sensitive(button, TRUE);
194 g_object_set_data(G_OBJECT(list), "btn_new", button);
195 gtk_signal_connect(GTK_OBJECT(button), "clicked",
196 GTK_SIGNAL_FUNC(cb_new), data);
197 }
198
199 if(cb_edit) {
200 button = gtk_button_new_with_label(_("Edit..."));
201 gtk_table_attach_defaults(GTK_TABLE(table), button, 1, 2, 0, 1);
202 gtk_widget_set_sensitive(button, FALSE);
203 g_object_set_data(G_OBJECT(list), "btn_edit", button);
204 gtk_signal_connect(GTK_OBJECT(button), "clicked",
205 GTK_SIGNAL_FUNC(cb_edit), data);
206 }
207
208 if(cb_remove) {
209 button = gtk_button_new_with_label(_("Remove"));
210 gtk_table_attach_defaults(GTK_TABLE(table), button, 2, 3, 0, 1);
211 gtk_widget_set_sensitive(button, FALSE);
212 g_object_set_data(G_OBJECT(list), "btn_remove", button);
213 gtk_signal_connect(GTK_OBJECT(button), "clicked",
214 GTK_SIGNAL_FUNC(cb_remove), data);
215 }
216 }
217
218 GtkTreeModel *list_get_model(GtkWidget *list) {
219 return gtk_tree_view_get_model(GTK_TREE_VIEW(
220 g_object_get_data(G_OBJECT(list), "view")));
221 }
222
223 /* a generic list widget with "add", "edit" and "remove" buttons as used */
224 /* for all kinds of lists in osm2go */
225 GtkWidget *list_new(void) {
226
227 GtkWidget *vbox = gtk_vbox_new(FALSE,3);
228 GtkWidget *view = gtk_tree_view_new();
229 g_object_set_data(G_OBJECT(vbox), "view", view);
230
231 gtk_tree_selection_set_select_function(
232 gtk_tree_view_get_selection(GTK_TREE_VIEW(view)),
233 list_selection_function, vbox, NULL);
234
235 /* put view into a scrolled window */
236 GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
237 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
238 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
239 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window),
240 GTK_SHADOW_ETCHED_IN);
241 gtk_container_add(GTK_CONTAINER(scrolled_window), view);
242 gtk_box_pack_start_defaults(GTK_BOX(vbox), scrolled_window);
243
244 /* add button box */
245 GtkWidget *table = gtk_table_new(1, 3, TRUE);
246 g_object_set_data(G_OBJECT(vbox), "table", table);
247
248 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
249
250 return vbox;
251 }
252