Mercurial > pidgin
comparison console/libgnt/gnttree.c @ 13850:0e1e59770cb0
[gaim-migrate @ 16308]
This is my first commit here. So don't yell at me if things get borked.
Also, I haven't looked at the auto-thingies yet. So don't puke at the
Makefiles.
Files in console/libgnt/ are for the 'Gaim/GObjectified Ncurses Toolkit'
library. Files in console/ uses libgaim and libgnt. Currently, only the
buddylist-ui is 'functional', ie. the buddy-list updates when someone
logs on or logs off. It still needs a lot of work.
committer: Tailor Script <tailor@pidgin.im>
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Thu, 22 Jun 2006 08:33:54 +0000 |
parents | |
children | 41753203a94d |
comparison
equal
deleted
inserted
replaced
13849:8d1c55309e3c | 13850:0e1e59770cb0 |
---|---|
1 #include "gnttree.h" | |
2 | |
3 enum | |
4 { | |
5 SIGS = 1, | |
6 }; | |
7 | |
8 /* XXX: Make this one into a GObject? | |
9 * ... Probably not */ | |
10 struct _GnTreeRow | |
11 { | |
12 void *key; | |
13 char *text; | |
14 void *data; /* XXX: unused */ | |
15 | |
16 GntTreeRow *parent; | |
17 GntTreeRow *child; | |
18 GntTreeRow *next; | |
19 }; | |
20 | |
21 static GntWidgetClass *parent_class = NULL; | |
22 static guint signals[SIGS] = { 0 }; | |
23 | |
24 /* XXX: This is ugly, but what can you do ... */ | |
25 static void | |
26 gnt_tree_refresh(GntTree *tree) | |
27 { | |
28 GntWidget *widget = GNT_WIDGET(tree); | |
29 int pos; | |
30 | |
31 if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) | |
32 pos = 0; | |
33 else | |
34 pos = 1; | |
35 | |
36 copywin(tree->scroll, widget->window, tree->top, 0, | |
37 pos, pos, widget->priv.height - pos - 1, widget->priv.width - pos - 1, FALSE); | |
38 wrefresh(widget->window); | |
39 } | |
40 | |
41 static void | |
42 redraw_tree(GntTree *tree) | |
43 { | |
44 int start; | |
45 GntWidget *widget = GNT_WIDGET(tree); | |
46 GList *iter; | |
47 | |
48 wbkgd(tree->scroll, COLOR_PAIR(GNT_COLOR_NORMAL)); | |
49 | |
50 /* XXX: Add the rows */ | |
51 for (start = tree->top, iter = g_list_nth(tree->list, tree->top); | |
52 iter && start < tree->bottom; start++, iter = iter->next) | |
53 { | |
54 char str[2096]; /* XXX: This should be safe for any terminal */ | |
55 GntTreeRow *row = g_hash_table_lookup(tree->hash, iter->data); | |
56 | |
57 snprintf(str, widget->priv.width - 2, "%s\n", row->text); | |
58 | |
59 if (start == tree->current) | |
60 { | |
61 wbkgdset(tree->scroll, '\0' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT)); | |
62 mvwprintw(tree->scroll, start, 0, str); | |
63 wbkgdset(tree->scroll, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); | |
64 } | |
65 else | |
66 mvwprintw(tree->scroll, start, 0, str); | |
67 } | |
68 | |
69 while (start < tree->bottom) | |
70 { | |
71 wmove(tree->scroll, start, 0); | |
72 wclrtoeol(tree->scroll); | |
73 start++; | |
74 } | |
75 | |
76 gnt_tree_refresh(tree); | |
77 } | |
78 | |
79 static void | |
80 gnt_tree_draw(GntWidget *widget) | |
81 { | |
82 GntTree *tree = GNT_TREE(widget); | |
83 | |
84 /* For the Tree (or anything that scrolls), we will create a 'hidden' window | |
85 * of 'large enough' size. We never wrefresh that hidden-window, instead we | |
86 * just 'scroll' it, and wrefresh the subwindow */ | |
87 | |
88 if (tree->scroll == NULL) | |
89 { | |
90 tree->scroll = newwin(SCROLL_HEIGHT, widget->priv.width, widget->priv.y, widget->priv.x); | |
91 scrollok(tree->scroll, TRUE); | |
92 wsetscrreg(tree->scroll, 0, SCROLL_HEIGHT - 1); | |
93 | |
94 tree->top = 0; | |
95 tree->bottom = widget->priv.height - | |
96 (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER) ? 0 : 2); | |
97 } | |
98 | |
99 redraw_tree(tree); | |
100 | |
101 DEBUG; | |
102 } | |
103 | |
104 static void | |
105 gnt_tree_size_request(GntWidget *widget) | |
106 { | |
107 if (widget->priv.height == 0) | |
108 widget->priv.height = 10; /* XXX: Why?! */ | |
109 if (widget->priv.width == 0) | |
110 widget->priv.width = 20; /* YYY: 'cuz ... */ | |
111 } | |
112 | |
113 static void | |
114 gnt_tree_map(GntWidget *widget) | |
115 { | |
116 if (widget->priv.width == 0 || widget->priv.height == 0) | |
117 gnt_widget_size_request(widget); | |
118 DEBUG; | |
119 } | |
120 | |
121 static gboolean | |
122 gnt_tree_key_pressed(GntWidget *widget, const char *text) | |
123 { | |
124 GntTree *tree = GNT_TREE(widget); | |
125 if (text[0] == 27) | |
126 { | |
127 if (strcmp(text+1, GNT_KEY_DOWN) == 0 && tree->current < g_list_length(tree->list) - 1) | |
128 { | |
129 tree->current++; | |
130 if (tree->current >= tree->bottom) | |
131 gnt_tree_scroll(tree, 1 + tree->current - tree->bottom); | |
132 redraw_tree(tree); | |
133 } | |
134 else if (strcmp(text+1, GNT_KEY_UP) == 0 && tree->current > 0) | |
135 { | |
136 tree->current--; | |
137 if (tree->current < tree->top) | |
138 gnt_tree_scroll(tree, tree->current - tree->top); | |
139 redraw_tree(tree); | |
140 } | |
141 } | |
142 else if (text[0] == '\r') | |
143 { | |
144 gnt_widget_activate(widget); | |
145 } | |
146 | |
147 return FALSE; | |
148 } | |
149 | |
150 static void | |
151 gnt_tree_destroy(GntWidget *widget) | |
152 { | |
153 GntTree *tree = GNT_TREE(widget); | |
154 | |
155 g_hash_table_destroy(tree->hash); | |
156 g_list_free(tree->list); | |
157 } | |
158 | |
159 static void | |
160 gnt_tree_class_init(GntWidgetClass *klass) | |
161 { | |
162 GObjectClass *obj_class = G_OBJECT_CLASS(klass); | |
163 | |
164 parent_class = GNT_WIDGET_CLASS(klass); | |
165 parent_class->destroy = gnt_tree_destroy; | |
166 parent_class->draw = gnt_tree_draw; | |
167 parent_class->map = gnt_tree_map; | |
168 parent_class->size_request = gnt_tree_size_request; | |
169 parent_class->key_pressed = gnt_tree_key_pressed; | |
170 | |
171 DEBUG; | |
172 } | |
173 | |
174 static void | |
175 gnt_tree_init(GTypeInstance *instance, gpointer class) | |
176 { | |
177 DEBUG; | |
178 } | |
179 | |
180 /****************************************************************************** | |
181 * GntTree API | |
182 *****************************************************************************/ | |
183 GType | |
184 gnt_tree_get_gtype(void) | |
185 { | |
186 static GType type = 0; | |
187 | |
188 if(type == 0) | |
189 { | |
190 static const GTypeInfo info = { | |
191 sizeof(GntTreeClass), | |
192 NULL, /* base_init */ | |
193 NULL, /* base_finalize */ | |
194 (GClassInitFunc)gnt_tree_class_init, | |
195 NULL, /* class_finalize */ | |
196 NULL, /* class_data */ | |
197 sizeof(GntTree), | |
198 0, /* n_preallocs */ | |
199 gnt_tree_init, /* instance_init */ | |
200 }; | |
201 | |
202 type = g_type_register_static(GNT_TYPE_WIDGET, | |
203 "GntTree", | |
204 &info, 0); | |
205 } | |
206 | |
207 return type; | |
208 } | |
209 | |
210 GntWidget *gnt_tree_new() | |
211 { | |
212 GntWidget *widget = g_object_new(GNT_TYPE_TREE, NULL); | |
213 GntTree *tree = GNT_TREE(widget); | |
214 | |
215 tree->hash = g_hash_table_new(g_direct_hash, g_direct_equal); | |
216 | |
217 return widget; | |
218 } | |
219 | |
220 void gnt_tree_set_visible_rows(GntTree *tree, int rows) | |
221 { | |
222 GntWidget *widget = GNT_WIDGET(tree); | |
223 widget->priv.height = rows; | |
224 if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) | |
225 widget->priv.height += 2; | |
226 } | |
227 | |
228 int gnt_tree_get_visible_rows(GntTree *tree) | |
229 { | |
230 GntWidget *widget = GNT_WIDGET(tree); | |
231 int ret = widget->priv.height; | |
232 if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) | |
233 widget->priv.height -= 2; | |
234 } | |
235 | |
236 void gnt_tree_scroll(GntTree *tree, int count) | |
237 { | |
238 if (tree->top == 0 && count < 0) | |
239 return; | |
240 | |
241 if (count > 0 && tree->bottom + count >= g_list_length(tree->list)) | |
242 count = g_list_length(tree->list) - tree->bottom; | |
243 else if (count < 0 && tree->top + count < 0) | |
244 count = -tree->top; | |
245 | |
246 tree->top += count; | |
247 tree->bottom += count; | |
248 | |
249 /*wscrl(tree->scroll, count);*/ | |
250 gnt_tree_refresh(tree); | |
251 } | |
252 | |
253 void gnt_tree_add_row_after(GntTree *tree, void *key, const char *text, void *parent, void *bigbro) | |
254 { | |
255 GntTreeRow *row = g_new0(GntTreeRow, 1), *pr = NULL; | |
256 | |
257 row->key = key; | |
258 row->text = g_strdup(text); | |
259 row->data = NULL; | |
260 | |
261 g_hash_table_insert(tree->hash, key, row); | |
262 | |
263 if (tree->root == NULL) | |
264 { | |
265 tree->root = row; | |
266 tree->list = g_list_prepend(tree->list, key); | |
267 } | |
268 else | |
269 { | |
270 int position; | |
271 | |
272 if (bigbro) | |
273 { | |
274 pr = g_hash_table_lookup(tree->hash, bigbro); | |
275 if (pr) | |
276 { | |
277 row->next = pr->next; | |
278 pr->next = row; | |
279 row->parent = pr->parent; | |
280 | |
281 position = g_list_index(tree->list, bigbro); | |
282 } | |
283 } | |
284 | |
285 if (pr == NULL && parent) | |
286 { | |
287 pr = g_hash_table_lookup(tree->hash, parent); | |
288 if (pr) | |
289 { | |
290 row->next = pr->child; | |
291 pr->child = row; | |
292 row->parent = pr; | |
293 | |
294 position = g_list_index(tree->list, parent); | |
295 } | |
296 } | |
297 | |
298 if (pr == NULL) | |
299 { | |
300 row->next = tree->root; | |
301 tree->root = row; | |
302 | |
303 tree->list = g_list_prepend(tree->list, key); | |
304 } | |
305 else | |
306 { | |
307 tree->list = g_list_insert(tree->list, key, position + 1); | |
308 } | |
309 } | |
310 | |
311 if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_MAPPED)) | |
312 redraw_tree(tree); | |
313 } | |
314 | |
315 gpointer gnt_tree_get_selection_data(GntTree *tree) | |
316 { | |
317 return g_list_nth(tree->list, tree->current); | |
318 } | |
319 | |
320 int gnt_tree_get_selection_index(GntTree *tree) | |
321 { | |
322 return tree->current; | |
323 } | |
324 | |
325 void gnt_tree_remove(GntTree *tree, gpointer key) | |
326 { | |
327 GntTreeRow *row = g_hash_table_lookup(tree->hash, key); | |
328 if (row) | |
329 { | |
330 int len, pos; | |
331 | |
332 g_free(row->text); | |
333 g_free(row); | |
334 | |
335 pos = g_list_index(tree->list, key); | |
336 | |
337 g_hash_table_remove(tree->hash, key); | |
338 tree->list = g_list_remove(tree->list, key); | |
339 | |
340 if (pos >= tree->top && pos < tree->bottom) | |
341 { | |
342 redraw_tree(tree); | |
343 } | |
344 } | |
345 } | |
346 |