Mercurial > pidgin.yaz
annotate finch/libgnt/gnttree.c @ 18035:c168d1ae2012
A patch from Norbert Buchmuller:
"There's a 'setstatus' command implemented in 'gaim-remote', but there's
no 'getstatus'. For some tasks (eg. setting status to 'offline' on
hibernation and restoring it on resume) it would be useful if such
command existed."
I'm not sure if we're considering this API or not.
committer: Richard Laager <rlaager@wiktel.com>
author | Norbert Buchmuller <norbi@nix.hu> |
---|---|
date | Sun, 03 Jun 2007 19:34:16 +0000 |
parents | 467698ab6bf0 |
children | 3c3fc1432a01 8410511f4dbb |
rev | line source |
---|---|
15818 | 1 #include "gntmarshal.h" |
2 #include "gntstyle.h" | |
3 #include "gnttree.h" | |
4 #include "gntutils.h" | |
5 | |
6 #include <string.h> | |
7 #include <ctype.h> | |
8 | |
9 #define SEARCH_TIMEOUT 4000 /* 4 secs */ | |
16249
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
10 #define SEARCHING(tree) (tree->search && tree->search->len > 0) |
15818 | 11 |
12 enum | |
13 { | |
14 SIG_SELECTION_CHANGED, | |
15 SIG_SCROLLED, | |
16 SIG_TOGGLED, | |
16105
1983ecd15174
Remember the collapsed state of groups in the blist
Richard Nelson <wabz@pidgin.im>
parents:
15972
diff
changeset
|
17 SIG_COLLAPSED, |
15818 | 18 SIGS, |
19 }; | |
20 | |
21 #define TAB_SIZE 3 | |
22 | |
23 /* XXX: Make this one into a GObject? | |
24 * ... Probably not */ | |
15931
f00f2e283ffb
Some define changes. This helps in generating the python bindings.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
25 struct _GntTreeRow |
15818 | 26 { |
27 void *key; | |
28 void *data; /* XXX: unused */ | |
29 | |
30 gboolean collapsed; | |
31 gboolean choice; /* Is this a choice-box? | |
32 If choice is true, then child will be NULL */ | |
33 gboolean isselected; | |
34 GntTextFormatFlags flags; | |
35 | |
36 GntTreeRow *parent; | |
37 GntTreeRow *child; | |
38 GntTreeRow *next; | |
39 GntTreeRow *prev; | |
40 | |
41 GList *columns; | |
42 GntTree *tree; | |
43 }; | |
44 | |
15931
f00f2e283ffb
Some define changes. This helps in generating the python bindings.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
45 struct _GntTreeCol |
15818 | 46 { |
47 char *text; | |
48 int span; /* How many columns does it span? */ | |
49 }; | |
50 | |
16203
4f6a6443a1e3
emit/handle gnttree signals appropriately
Richard Nelson <wabz@pidgin.im>
parents:
16123
diff
changeset
|
51 static void tree_selection_changed(GntTree *, GntTreeRow *, GntTreeRow *); |
4f6a6443a1e3
emit/handle gnttree signals appropriately
Richard Nelson <wabz@pidgin.im>
parents:
16123
diff
changeset
|
52 |
15818 | 53 static GntWidgetClass *parent_class = NULL; |
54 static guint signals[SIGS] = { 0 }; | |
55 | |
56 /* Move the item at position old to position new */ | |
57 static GList * | |
58 g_list_reposition_child(GList *list, int old, int new) | |
59 { | |
60 gpointer item = g_list_nth_data(list, old); | |
61 list = g_list_remove(list, item); | |
62 if (old < new) | |
63 new--; /* because the positions would have shifted after removing the item */ | |
64 list = g_list_insert(list, item, new); | |
65 return list; | |
66 } | |
67 | |
68 static GntTreeRow * | |
69 _get_next(GntTreeRow *row, gboolean godeep) | |
70 { | |
71 if (row == NULL) | |
72 return NULL; | |
73 if (godeep && row->child) | |
74 return row->child; | |
75 if (row->next) | |
76 return row->next; | |
77 return _get_next(row->parent, FALSE); | |
78 } | |
79 | |
80 static gboolean | |
81 row_matches_search(GntTreeRow *row) | |
82 { | |
83 GntTree *t = row->tree; | |
84 if (t->search && t->search->len > 0) { | |
85 char *one = g_utf8_casefold(((GntTreeCol*)row->columns->data)->text, -1); | |
86 char *two = g_utf8_casefold(t->search->str, -1); | |
87 char *z = strstr(one, two); | |
88 g_free(one); | |
89 g_free(two); | |
90 if (z == NULL) | |
91 return FALSE; | |
92 } | |
93 return TRUE; | |
94 } | |
95 | |
96 static GntTreeRow * | |
97 get_next(GntTreeRow *row) | |
98 { | |
99 if (row == NULL) | |
100 return NULL; | |
101 while ((row = _get_next(row, !row->collapsed)) != NULL) { | |
102 if (row_matches_search(row)) | |
103 break; | |
104 } | |
105 return row; | |
106 } | |
107 | |
108 /* Returns the n-th next row. If it doesn't exist, returns NULL */ | |
109 static GntTreeRow * | |
110 get_next_n(GntTreeRow *row, int n) | |
111 { | |
112 while (row && n--) | |
113 row = get_next(row); | |
114 return row; | |
115 } | |
116 | |
117 /* Returns the n-th next row. If it doesn't exist, then the last non-NULL node */ | |
118 static GntTreeRow * | |
119 get_next_n_opt(GntTreeRow *row, int n, int *pos) | |
120 { | |
121 GntTreeRow *next = row; | |
122 int r = 0; | |
123 | |
124 if (row == NULL) | |
125 return NULL; | |
126 | |
127 while (row && n--) | |
128 { | |
129 row = get_next(row); | |
130 if (row) | |
131 { | |
132 next = row; | |
133 r++; | |
134 } | |
135 } | |
136 | |
137 if (pos) | |
138 *pos = r; | |
139 | |
140 return next; | |
141 } | |
142 | |
143 static GntTreeRow * | |
144 get_last_child(GntTreeRow *row) | |
145 { | |
146 if (row == NULL) | |
147 return NULL; | |
148 if (!row->collapsed && row->child) | |
149 row = row->child; | |
150 else | |
151 return row; | |
152 | |
153 while(row->next) | |
154 row = row->next; | |
16585
467698ab6bf0
Fix an odd selection issue when moving up.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16283
diff
changeset
|
155 return get_last_child(row); |
15818 | 156 } |
157 | |
158 static GntTreeRow * | |
159 get_prev(GntTreeRow *row) | |
160 { | |
161 if (row == NULL) | |
162 return NULL; | |
163 while (row) { | |
164 if (row->prev) | |
165 row = get_last_child(row->prev); | |
166 else | |
167 row = row->parent; | |
168 if (!row || row_matches_search(row)) | |
169 break; | |
170 } | |
171 return row; | |
172 } | |
173 | |
174 static GntTreeRow * | |
175 get_prev_n(GntTreeRow *row, int n) | |
176 { | |
177 while (row && n--) | |
178 row = get_prev(row); | |
179 return row; | |
180 } | |
181 | |
182 /* Distance of row from the root */ | |
183 /* XXX: This is uber-inefficient */ | |
184 static int | |
185 get_root_distance(GntTreeRow *row) | |
186 { | |
187 if (row == NULL) | |
188 return -1; | |
189 return get_root_distance(get_prev(row)) + 1; | |
190 } | |
191 | |
192 /* Returns the distance between a and b. | |
193 * If a is 'above' b, then the distance is positive */ | |
194 static int | |
195 get_distance(GntTreeRow *a, GntTreeRow *b) | |
196 { | |
197 /* First get the distance from a to the root. | |
198 * Then the distance from b to the root. | |
199 * Subtract. | |
200 * It's not that good, but it works. */ | |
201 int ha = get_root_distance(a); | |
202 int hb = get_root_distance(b); | |
203 | |
204 return (hb - ha); | |
205 } | |
206 | |
207 static int | |
208 find_depth(GntTreeRow *row) | |
209 { | |
210 int dep = -1; | |
211 | |
212 while (row) | |
213 { | |
214 dep++; | |
215 row = row->parent; | |
216 } | |
217 | |
218 return dep; | |
219 } | |
220 | |
221 static char * | |
222 update_row_text(GntTree *tree, GntTreeRow *row) | |
223 { | |
224 GString *string = g_string_new(NULL); | |
225 GList *iter; | |
226 int i; | |
15970
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
227 gboolean notfirst = FALSE; |
15971
05d347516fcd
Fine tune column hiding.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15970
diff
changeset
|
228 int lastvisible = tree->ncol; |
05d347516fcd
Fine tune column hiding.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15970
diff
changeset
|
229 |
05d347516fcd
Fine tune column hiding.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15970
diff
changeset
|
230 while (lastvisible && tree->columns[lastvisible].invisible) |
05d347516fcd
Fine tune column hiding.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15970
diff
changeset
|
231 lastvisible--; |
15818 | 232 |
233 for (i = 0, iter = row->columns; i < tree->ncol && iter; i++, iter = iter->next) | |
234 { | |
235 GntTreeCol *col = iter->data; | |
236 const char *text; | |
237 int len = gnt_util_onscreen_width(col->text, NULL); | |
238 int fl = 0; | |
239 gboolean cut = FALSE; | |
15971
05d347516fcd
Fine tune column hiding.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15970
diff
changeset
|
240 int width; |
15818 | 241 |
15970
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
242 if (tree->columns[i].invisible) |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
243 continue; |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
244 |
15971
05d347516fcd
Fine tune column hiding.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15970
diff
changeset
|
245 if (i == lastvisible) |
05d347516fcd
Fine tune column hiding.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15970
diff
changeset
|
246 width = GNT_WIDGET(tree)->priv.width - gnt_util_onscreen_width(string->str, NULL); |
05d347516fcd
Fine tune column hiding.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15970
diff
changeset
|
247 else |
05d347516fcd
Fine tune column hiding.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15970
diff
changeset
|
248 width = tree->columns[i].width; |
05d347516fcd
Fine tune column hiding.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15970
diff
changeset
|
249 |
15818 | 250 if (i == 0) |
251 { | |
252 if (row->choice) | |
253 { | |
254 g_string_append_printf(string, "[%c] ", | |
255 row->isselected ? 'X' : ' '); | |
256 fl = 4; | |
257 } | |
258 else if (row->parent == NULL && row->child) | |
259 { | |
260 if (row->collapsed) | |
261 { | |
262 string = g_string_append(string, "+ "); | |
263 } | |
264 else | |
265 { | |
266 string = g_string_append(string, "- "); | |
267 } | |
268 fl = 2; | |
269 } | |
270 else | |
271 { | |
272 fl = TAB_SIZE * find_depth(row); | |
273 g_string_append_printf(string, "%*s", fl, ""); | |
274 } | |
275 len += fl; | |
276 } | |
15970
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
277 else if (notfirst) |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
278 g_string_append_c(string, '|'); |
15818 | 279 else |
15970
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
280 g_string_append_c(string, ' '); |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
281 |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
282 notfirst = TRUE; |
15818 | 283 |
15971
05d347516fcd
Fine tune column hiding.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15970
diff
changeset
|
284 if (len > width) { |
05d347516fcd
Fine tune column hiding.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15970
diff
changeset
|
285 len = width - 1; |
15818 | 286 cut = TRUE; |
287 } | |
288 text = gnt_util_onscreen_width_to_pointer(col->text, len - fl, NULL); | |
289 string = g_string_append_len(string, col->text, text - col->text); | |
290 if (cut) { /* ellipsis */ | |
291 if (gnt_ascii_only()) | |
292 g_string_append_c(string, '~'); | |
293 else | |
294 string = g_string_append(string, "\342\200\246"); | |
295 len++; | |
296 } | |
297 | |
298 if (len < tree->columns[i].width && iter->next) | |
15971
05d347516fcd
Fine tune column hiding.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15970
diff
changeset
|
299 g_string_append_printf(string, "%*s", width - len, ""); |
15818 | 300 } |
301 return g_string_free(string, FALSE); | |
302 } | |
303 | |
15970
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
304 #define NEXT_X x += tree->columns[i].width + (i > 0 ? 1 : 0) |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
305 |
15818 | 306 static void |
307 tree_mark_columns(GntTree *tree, int pos, int y, chtype type) | |
308 { | |
309 GntWidget *widget = GNT_WIDGET(tree); | |
310 int i; | |
311 int x = pos; | |
15970
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
312 gboolean notfirst = FALSE; |
15818 | 313 |
314 for (i = 0; i < tree->ncol - 1; i++) | |
315 { | |
15970
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
316 if (!tree->columns[i].invisible) { |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
317 notfirst = TRUE; |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
318 NEXT_X; |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
319 } |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
320 if (!tree->columns[i+1].invisible && notfirst) |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
321 mvwaddch(widget->window, y, x, type); |
15818 | 322 } |
323 } | |
324 | |
325 static void | |
326 redraw_tree(GntTree *tree) | |
327 { | |
328 int start, i; | |
329 GntWidget *widget = GNT_WIDGET(tree); | |
330 GntTreeRow *row; | |
331 int pos, up, down; | |
332 int rows, scrcol; | |
333 | |
334 if (!GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_MAPPED)) | |
335 return; | |
336 | |
337 if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) | |
338 pos = 0; | |
339 else | |
340 pos = 1; | |
341 | |
342 if (tree->top == NULL) | |
343 tree->top = tree->root; | |
16203
4f6a6443a1e3
emit/handle gnttree signals appropriately
Richard Nelson <wabz@pidgin.im>
parents:
16123
diff
changeset
|
344 if (tree->current == NULL) { |
15818 | 345 tree->current = tree->root; |
16203
4f6a6443a1e3
emit/handle gnttree signals appropriately
Richard Nelson <wabz@pidgin.im>
parents:
16123
diff
changeset
|
346 tree_selection_changed(tree, NULL, tree->current); |
4f6a6443a1e3
emit/handle gnttree signals appropriately
Richard Nelson <wabz@pidgin.im>
parents:
16123
diff
changeset
|
347 } |
15818 | 348 |
349 wbkgd(widget->window, COLOR_PAIR(GNT_COLOR_NORMAL)); | |
350 | |
351 start = 0; | |
352 if (tree->show_title) | |
353 { | |
354 int i; | |
355 int x = pos; | |
356 | |
357 mvwhline(widget->window, pos + 1, pos, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), | |
358 widget->priv.width - pos - 1); | |
15970
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
359 mvwhline(widget->window, pos, pos, ' ' | COLOR_PAIR(GNT_COLOR_NORMAL), |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
360 widget->priv.width - pos - 1); |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
361 |
15818 | 362 for (i = 0; i < tree->ncol; i++) |
363 { | |
15970
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
364 if (tree->columns[i].invisible) { |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
365 continue; |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
366 } |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
367 mvwaddstr(widget->window, pos, x + 1, tree->columns[i].title); |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
368 NEXT_X; |
15818 | 369 } |
370 if (pos) | |
371 { | |
372 tree_mark_columns(tree, pos, 0, ACS_TTEE | COLOR_PAIR(GNT_COLOR_NORMAL)); | |
373 tree_mark_columns(tree, pos, widget->priv.height - pos, | |
374 ACS_BTEE | COLOR_PAIR(GNT_COLOR_NORMAL)); | |
375 } | |
376 tree_mark_columns(tree, pos, pos + 1, | |
377 (tree->show_separator ? ACS_PLUS : ACS_HLINE) | COLOR_PAIR(GNT_COLOR_NORMAL)); | |
378 tree_mark_columns(tree, pos, pos, | |
379 (tree->show_separator ? ACS_VLINE : ' ') | COLOR_PAIR(GNT_COLOR_NORMAL)); | |
380 start = 2; | |
381 } | |
382 | |
383 rows = widget->priv.height - pos * 2 - start - 1; | |
384 tree->bottom = get_next_n_opt(tree->top, rows, &down); | |
385 if (down < rows) | |
386 { | |
387 tree->top = get_prev_n(tree->bottom, rows); | |
388 if (tree->top == NULL) | |
389 tree->top = tree->root; | |
390 } | |
391 | |
392 up = get_distance(tree->top, tree->current); | |
393 if (up < 0) | |
394 tree->top = tree->current; | |
395 else if (up >= widget->priv.height - pos) | |
396 tree->top = get_prev_n(tree->current, rows); | |
397 | |
398 if (tree->top && !row_matches_search(tree->top)) | |
399 tree->top = get_next(tree->top); | |
400 row = tree->top; | |
401 scrcol = widget->priv.width - 1 - 2 * pos; /* exclude the borders and the scrollbar */ | |
402 for (i = start + pos; row && i < widget->priv.height - pos; | |
403 i++, row = get_next(row)) | |
404 { | |
405 char *str; | |
406 int wr; | |
407 | |
408 GntTextFormatFlags flags = row->flags; | |
409 int attr = 0; | |
410 | |
411 if (!row_matches_search(row)) | |
412 continue; | |
413 str = update_row_text(tree, row); | |
414 | |
415 if ((wr = gnt_util_onscreen_width(str, NULL)) > scrcol) | |
416 { | |
417 char *s = (char*)gnt_util_onscreen_width_to_pointer(str, scrcol, &wr); | |
418 *s = '\0'; | |
419 } | |
420 | |
421 if (flags & GNT_TEXT_FLAG_BOLD) | |
422 attr |= A_BOLD; | |
423 if (flags & GNT_TEXT_FLAG_UNDERLINE) | |
424 attr |= A_UNDERLINE; | |
425 if (flags & GNT_TEXT_FLAG_BLINK) | |
426 attr |= A_BLINK; | |
427 | |
428 if (row == tree->current) | |
429 { | |
430 if (gnt_widget_has_focus(widget)) | |
431 attr |= COLOR_PAIR(GNT_COLOR_HIGHLIGHT); | |
432 else | |
433 attr |= COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D); | |
434 } | |
435 else | |
436 { | |
437 if (flags & GNT_TEXT_FLAG_DIM) | |
438 attr |= (A_DIM | COLOR_PAIR(GNT_COLOR_DISABLED)); | |
439 else if (flags & GNT_TEXT_FLAG_HIGHLIGHT) | |
440 attr |= (A_DIM | COLOR_PAIR(GNT_COLOR_HIGHLIGHT)); | |
441 else | |
442 attr |= COLOR_PAIR(GNT_COLOR_NORMAL); | |
443 } | |
444 | |
445 wbkgdset(widget->window, '\0' | attr); | |
446 mvwaddstr(widget->window, i, pos, str); | |
447 whline(widget->window, ' ', scrcol - wr); | |
448 tree->bottom = row; | |
449 g_free(str); | |
450 tree_mark_columns(tree, pos, i, | |
451 (tree->show_separator ? ACS_VLINE : ' ') | attr); | |
452 } | |
453 | |
454 wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_NORMAL)); | |
455 while (i < widget->priv.height - pos) | |
456 { | |
457 mvwhline(widget->window, i, pos, ' ', | |
458 widget->priv.width - pos * 2 - 1); | |
459 tree_mark_columns(tree, pos, i, | |
460 (tree->show_separator ? ACS_VLINE : ' ')); | |
461 i++; | |
462 } | |
463 | |
464 scrcol = widget->priv.width - pos - 1; /* position of the scrollbar */ | |
465 rows--; | |
466 if (rows > 0) | |
467 { | |
468 int total; | |
469 int showing, position; | |
470 | |
471 get_next_n_opt(tree->root, g_list_length(tree->list), &total); | |
472 showing = rows * rows / MAX(total, 1) + 1; | |
473 showing = MIN(rows, showing); | |
474 | |
475 total -= rows; | |
476 up = get_distance(tree->root, tree->top); | |
477 down = total - up; | |
478 | |
479 position = (rows - showing) * up / MAX(1, up + down); | |
480 position = MAX((tree->top != tree->root), position); | |
481 | |
482 if (showing + position > rows) | |
483 position = rows - showing; | |
484 | |
485 if (showing + position == rows && row) | |
486 position = MAX(0, rows - 1 - showing); | |
487 else if (showing + position < rows && !row) | |
488 position = rows - showing; | |
489 | |
490 position += pos + start + 1; | |
491 | |
492 mvwvline(widget->window, pos + start + 1, scrcol, | |
493 ' ' | COLOR_PAIR(GNT_COLOR_NORMAL), rows); | |
494 mvwvline(widget->window, position, scrcol, | |
495 ACS_CKBOARD | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D), showing); | |
496 } | |
497 | |
498 mvwaddch(widget->window, start + pos, scrcol, | |
499 ((tree->top != tree->root) ? ACS_UARROW : ' ') | | |
500 COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D)); | |
501 | |
502 mvwaddch(widget->window, widget->priv.height - pos - 1, scrcol, | |
503 (row ? ACS_DARROW : ' ') | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D)); | |
504 | |
16249
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
505 /* If there's a search-text, show it in the bottom of the tree */ |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
506 if (tree->search && tree->search->len > 0) { |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
507 const char *str = gnt_util_onscreen_width_to_pointer(tree->search->str, scrcol - 1, NULL); |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
508 wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT_D)); |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
509 mvwaddnstr(widget->window, widget->priv.height - pos - 1, pos, |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
510 tree->search->str, str - tree->search->str); |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
511 } |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
512 |
15818 | 513 gnt_widget_queue_update(widget); |
514 } | |
515 | |
516 static void | |
517 gnt_tree_draw(GntWidget *widget) | |
518 { | |
519 GntTree *tree = GNT_TREE(widget); | |
520 | |
521 redraw_tree(tree); | |
522 | |
523 GNTDEBUG; | |
524 } | |
525 | |
526 static void | |
527 gnt_tree_size_request(GntWidget *widget) | |
528 { | |
529 if (widget->priv.height == 0) | |
530 widget->priv.height = 10; /* XXX: Why?! */ | |
531 if (widget->priv.width == 0) | |
532 { | |
533 GntTree *tree = GNT_TREE(widget); | |
534 int i, width = 0; | |
535 for (i = 0; i < tree->ncol; i++) | |
15970
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
536 if (!tree->columns[i].invisible) |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
537 width += tree->columns[i].width + 1; |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
538 widget->priv.width = width; |
15818 | 539 } |
540 } | |
541 | |
542 static void | |
543 gnt_tree_map(GntWidget *widget) | |
544 { | |
545 GntTree *tree = GNT_TREE(widget); | |
546 if (widget->priv.width == 0 || widget->priv.height == 0) | |
547 { | |
548 gnt_widget_size_request(widget); | |
549 } | |
550 tree->top = tree->root; | |
551 tree->current = tree->root; | |
552 GNTDEBUG; | |
553 } | |
554 | |
555 static void | |
556 tree_selection_changed(GntTree *tree, GntTreeRow *old, GntTreeRow *current) | |
557 { | |
558 g_signal_emit(tree, signals[SIG_SELECTION_CHANGED], 0, old ? old->key : NULL, | |
559 current ? current->key : NULL); | |
560 } | |
561 | |
562 static gboolean | |
563 action_down(GntBindable *bind, GList *null) | |
564 { | |
565 int dist; | |
566 GntTree *tree = GNT_TREE(bind); | |
567 GntTreeRow *old = tree->current; | |
568 GntTreeRow *row = get_next(tree->current); | |
569 if (row == NULL) | |
570 return FALSE; | |
571 tree->current = row; | |
572 if ((dist = get_distance(tree->current, tree->bottom)) < 0) | |
573 gnt_tree_scroll(tree, -dist); | |
574 else | |
575 redraw_tree(tree); | |
576 if (old != tree->current) | |
577 tree_selection_changed(tree, old, tree->current); | |
578 return TRUE; | |
579 } | |
580 | |
581 static gboolean | |
15972
5eb0621e0760
Backspace to jump to parent.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15971
diff
changeset
|
582 action_move_parent(GntBindable *bind, GList *null) |
5eb0621e0760
Backspace to jump to parent.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15971
diff
changeset
|
583 { |
5eb0621e0760
Backspace to jump to parent.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15971
diff
changeset
|
584 GntTree *tree = GNT_TREE(bind); |
5eb0621e0760
Backspace to jump to parent.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15971
diff
changeset
|
585 GntTreeRow *row = tree->current; |
16249
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
586 int dist; |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
587 |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
588 if (!row->parent || SEARCHING(tree)) |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
589 return FALSE; |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
590 |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
591 tree->current = row->parent; |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
592 if ((dist = get_distance(tree->current, tree->top)) > 0) |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
593 gnt_tree_scroll(tree, -dist); |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
594 else |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
595 redraw_tree(tree); |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
596 tree_selection_changed(tree, row, tree->current); |
15972
5eb0621e0760
Backspace to jump to parent.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15971
diff
changeset
|
597 return TRUE; |
5eb0621e0760
Backspace to jump to parent.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15971
diff
changeset
|
598 } |
5eb0621e0760
Backspace to jump to parent.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15971
diff
changeset
|
599 |
5eb0621e0760
Backspace to jump to parent.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15971
diff
changeset
|
600 static gboolean |
15818 | 601 action_up(GntBindable *bind, GList *list) |
602 { | |
603 int dist; | |
604 GntTree *tree = GNT_TREE(bind); | |
605 GntTreeRow *old = tree->current; | |
606 GntTreeRow *row = get_prev(tree->current); | |
607 if (!row) | |
608 return FALSE; | |
609 tree->current = row; | |
610 if ((dist = get_distance(tree->current, tree->top)) > 0) | |
611 gnt_tree_scroll(tree, -dist); | |
612 else | |
613 redraw_tree(tree); | |
614 if (old != tree->current) | |
615 tree_selection_changed(tree, old, tree->current); | |
616 | |
617 return TRUE; | |
618 } | |
619 | |
620 static gboolean | |
621 action_page_down(GntBindable *bind, GList *null) | |
622 { | |
623 GntTree *tree = GNT_TREE(bind); | |
624 GntTreeRow *old = tree->current; | |
625 GntTreeRow *row = get_next(tree->bottom); | |
626 if (row) | |
627 { | |
628 int dist = get_distance(tree->top, tree->current); | |
629 tree->top = tree->bottom; | |
630 tree->current = get_next_n_opt(tree->top, dist, NULL); | |
631 redraw_tree(tree); | |
632 } | |
633 else if (tree->current != tree->bottom) | |
634 { | |
635 tree->current = tree->bottom; | |
636 redraw_tree(tree); | |
637 } | |
638 | |
639 if (old != tree->current) | |
640 tree_selection_changed(tree, old, tree->current); | |
641 return TRUE; | |
642 } | |
643 | |
644 static gboolean | |
645 action_page_up(GntBindable *bind, GList *null) | |
646 { | |
647 GntWidget *widget = GNT_WIDGET(bind); | |
648 GntTree *tree = GNT_TREE(bind); | |
649 GntTreeRow *row; | |
650 GntTreeRow *old = tree->current; | |
651 | |
652 if (tree->top != tree->root) | |
653 { | |
654 int dist = get_distance(tree->top, tree->current); | |
655 row = get_prev_n(tree->top, widget->priv.height - 1 - | |
656 tree->show_title * 2 - 2 * (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER) == 0)); | |
657 if (row == NULL) | |
658 row = tree->root; | |
659 tree->top = row; | |
660 tree->current = get_next_n_opt(tree->top, dist, NULL); | |
661 redraw_tree(tree); | |
662 } | |
663 else if (tree->current != tree->top) | |
664 { | |
665 tree->current = tree->top; | |
666 redraw_tree(tree); | |
667 } | |
668 if (old != tree->current) | |
669 tree_selection_changed(tree, old, tree->current); | |
670 return TRUE; | |
671 } | |
672 | |
673 static void | |
674 end_search(GntTree *tree) | |
675 { | |
676 if (tree->search) { | |
677 g_source_remove(tree->search_timeout); | |
678 g_string_free(tree->search, TRUE); | |
679 tree->search = NULL; | |
680 tree->search_timeout = 0; | |
681 } | |
682 } | |
683 | |
684 static gboolean | |
685 search_timeout(gpointer data) | |
686 { | |
687 GntTree *tree = data; | |
688 | |
689 end_search(tree); | |
690 redraw_tree(tree); | |
691 | |
692 return FALSE; | |
693 } | |
694 | |
695 static gboolean | |
696 gnt_tree_key_pressed(GntWidget *widget, const char *text) | |
697 { | |
698 GntTree *tree = GNT_TREE(widget); | |
699 GntTreeRow *old = tree->current; | |
700 | |
701 if (text[0] == '\r') { | |
702 end_search(tree); | |
703 gnt_widget_activate(widget); | |
704 } else if (tree->search) { | |
16249
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
705 gboolean changed = TRUE; |
15818 | 706 if (isalnum(*text)) { |
707 tree->search = g_string_append_c(tree->search, *text); | |
16249
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
708 } else if (g_utf8_collate(text, GNT_KEY_BACKSPACE) == 0) { |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
709 if (tree->search->len) |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
710 tree->search->str[--tree->search->len] = '\0'; |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
711 } else |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
712 changed = FALSE; |
f02e611bdb6b
Show the search string in the tree.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16203
diff
changeset
|
713 if (changed) { |
15818 | 714 redraw_tree(tree); |
715 g_source_remove(tree->search_timeout); | |
716 tree->search_timeout = g_timeout_add(SEARCH_TIMEOUT, search_timeout, tree); | |
717 } | |
718 return TRUE; | |
719 } else if (text[0] == ' ' && text[1] == 0) { | |
720 /* Space pressed */ | |
721 GntTreeRow *row = tree->current; | |
722 if (row && row->child) | |
723 { | |
724 row->collapsed = !row->collapsed; | |
725 redraw_tree(tree); | |
16105
1983ecd15174
Remember the collapsed state of groups in the blist
Richard Nelson <wabz@pidgin.im>
parents:
15972
diff
changeset
|
726 g_signal_emit(tree, signals[SIG_COLLAPSED], 0, row->key, row->collapsed); |
15818 | 727 } |
728 else if (row && row->choice) | |
729 { | |
730 row->isselected = !row->isselected; | |
731 g_signal_emit(tree, signals[SIG_TOGGLED], 0, row->key); | |
732 redraw_tree(tree); | |
733 } | |
734 } | |
735 | |
736 if (old != tree->current) | |
737 { | |
738 tree_selection_changed(tree, old, tree->current); | |
739 return TRUE; | |
740 } | |
741 | |
742 return FALSE; | |
743 } | |
744 | |
745 static void | |
746 gnt_tree_destroy(GntWidget *widget) | |
747 { | |
748 GntTree *tree = GNT_TREE(widget); | |
749 int i; | |
750 | |
751 end_search(tree); | |
752 if (tree->hash) | |
753 g_hash_table_destroy(tree->hash); | |
754 g_list_free(tree->list); | |
755 | |
756 for (i = 0; i < tree->ncol; i++) | |
757 { | |
758 g_free(tree->columns[i].title); | |
759 } | |
760 g_free(tree->columns); | |
761 } | |
762 | |
763 static gboolean | |
764 gnt_tree_clicked(GntWidget *widget, GntMouseEvent event, int x, int y) | |
765 { | |
766 GntTree *tree = GNT_TREE(widget); | |
767 GntTreeRow *old = tree->current; | |
768 if (event == GNT_MOUSE_SCROLL_UP) { | |
769 action_up(GNT_BINDABLE(widget), NULL); | |
770 } else if (event == GNT_MOUSE_SCROLL_DOWN) { | |
771 action_down(GNT_BINDABLE(widget), NULL); | |
772 } else if (event == GNT_LEFT_MOUSE_DOWN) { | |
773 GntTreeRow *row; | |
774 GntTree *tree = GNT_TREE(widget); | |
775 int pos = 1; | |
776 if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) | |
777 pos = 0; | |
778 if (tree->show_title) | |
779 pos += 2; | |
780 pos = y - widget->priv.y - pos; | |
781 row = get_next_n(tree->top, pos); | |
782 if (row && tree->current != row) { | |
783 GntTreeRow *old = tree->current; | |
784 tree->current = row; | |
785 redraw_tree(tree); | |
786 tree_selection_changed(tree, old, tree->current); | |
787 } else if (row && row == tree->current) { | |
788 if (row->choice) { | |
789 row->isselected = !row->isselected; | |
790 g_signal_emit(tree, signals[SIG_TOGGLED], 0, row->key); | |
791 redraw_tree(tree); | |
792 } else { | |
793 gnt_widget_activate(widget); | |
794 } | |
795 } | |
796 } else { | |
797 return FALSE; | |
798 } | |
799 if (old != tree->current) { | |
800 tree_selection_changed(tree, old, tree->current); | |
801 } | |
802 return TRUE; | |
803 } | |
804 | |
805 static void | |
806 gnt_tree_size_changed(GntWidget *widget, int w, int h) | |
807 { | |
808 GntTree *tree = GNT_TREE(widget); | |
809 int i; | |
810 int n = 0; | |
811 if (widget->priv.width <= 0) | |
812 return; | |
813 for (i = 0; i < tree->ncol; ++i) | |
814 n += tree->columns[i].width; | |
815 if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) | |
816 tree->columns[tree->ncol - 1].width += widget->priv.width - n - 1 * tree->ncol; | |
817 else | |
818 tree->columns[tree->ncol - 1].width += widget->priv.width - n - 2 - 1 * tree->ncol; | |
819 } | |
820 | |
821 static gboolean | |
822 start_search(GntBindable *bindable, GList *list) | |
823 { | |
824 GntTree *tree = GNT_TREE(bindable); | |
825 if (tree->search) | |
826 return FALSE; | |
827 tree->search = g_string_new(NULL); | |
828 tree->search_timeout = g_timeout_add(SEARCH_TIMEOUT, search_timeout, tree); | |
829 return TRUE; | |
830 } | |
831 | |
832 static gboolean | |
833 end_search_action(GntBindable *bindable, GList *list) | |
834 { | |
835 GntTree *tree = GNT_TREE(bindable); | |
836 if (tree->search == NULL) | |
837 return FALSE; | |
838 end_search(tree); | |
839 redraw_tree(tree); | |
840 return TRUE; | |
841 } | |
842 | |
843 static void | |
844 gnt_tree_class_init(GntTreeClass *klass) | |
845 { | |
846 GntBindableClass *bindable = GNT_BINDABLE_CLASS(klass); | |
847 parent_class = GNT_WIDGET_CLASS(klass); | |
848 parent_class->destroy = gnt_tree_destroy; | |
849 parent_class->draw = gnt_tree_draw; | |
850 parent_class->map = gnt_tree_map; | |
851 parent_class->size_request = gnt_tree_size_request; | |
852 parent_class->key_pressed = gnt_tree_key_pressed; | |
853 parent_class->clicked = gnt_tree_clicked; | |
854 parent_class->size_changed = gnt_tree_size_changed; | |
855 | |
856 signals[SIG_SELECTION_CHANGED] = | |
857 g_signal_new("selection-changed", | |
858 G_TYPE_FROM_CLASS(klass), | |
859 G_SIGNAL_RUN_LAST, | |
860 G_STRUCT_OFFSET(GntTreeClass, selection_changed), | |
861 NULL, NULL, | |
862 gnt_closure_marshal_VOID__POINTER_POINTER, | |
863 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); | |
864 signals[SIG_SCROLLED] = | |
865 g_signal_new("scrolled", | |
866 G_TYPE_FROM_CLASS(klass), | |
867 G_SIGNAL_RUN_LAST, | |
868 0, | |
869 NULL, NULL, | |
870 g_cclosure_marshal_VOID__INT, | |
871 G_TYPE_NONE, 1, G_TYPE_INT); | |
872 signals[SIG_TOGGLED] = | |
873 g_signal_new("toggled", | |
874 G_TYPE_FROM_CLASS(klass), | |
875 G_SIGNAL_RUN_LAST, | |
876 G_STRUCT_OFFSET(GntTreeClass, toggled), | |
877 NULL, NULL, | |
878 g_cclosure_marshal_VOID__POINTER, | |
879 G_TYPE_NONE, 1, G_TYPE_POINTER); | |
16105
1983ecd15174
Remember the collapsed state of groups in the blist
Richard Nelson <wabz@pidgin.im>
parents:
15972
diff
changeset
|
880 signals[SIG_COLLAPSED] = |
1983ecd15174
Remember the collapsed state of groups in the blist
Richard Nelson <wabz@pidgin.im>
parents:
15972
diff
changeset
|
881 g_signal_new("collapse-toggled", |
1983ecd15174
Remember the collapsed state of groups in the blist
Richard Nelson <wabz@pidgin.im>
parents:
15972
diff
changeset
|
882 G_TYPE_FROM_CLASS(klass), |
1983ecd15174
Remember the collapsed state of groups in the blist
Richard Nelson <wabz@pidgin.im>
parents:
15972
diff
changeset
|
883 G_SIGNAL_RUN_LAST, |
1983ecd15174
Remember the collapsed state of groups in the blist
Richard Nelson <wabz@pidgin.im>
parents:
15972
diff
changeset
|
884 0, |
1983ecd15174
Remember the collapsed state of groups in the blist
Richard Nelson <wabz@pidgin.im>
parents:
15972
diff
changeset
|
885 NULL, NULL, |
1983ecd15174
Remember the collapsed state of groups in the blist
Richard Nelson <wabz@pidgin.im>
parents:
15972
diff
changeset
|
886 gnt_closure_marshal_VOID__POINTER_BOOLEAN, |
1983ecd15174
Remember the collapsed state of groups in the blist
Richard Nelson <wabz@pidgin.im>
parents:
15972
diff
changeset
|
887 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_BOOLEAN); |
15818 | 888 |
889 gnt_bindable_class_register_action(bindable, "move-up", action_up, | |
890 GNT_KEY_UP, NULL); | |
891 gnt_bindable_register_binding(bindable, "move-up", GNT_KEY_CTRL_P, NULL); | |
892 gnt_bindable_class_register_action(bindable, "move-down", action_down, | |
893 GNT_KEY_DOWN, NULL); | |
894 gnt_bindable_register_binding(bindable, "move-down", GNT_KEY_CTRL_N, NULL); | |
15972
5eb0621e0760
Backspace to jump to parent.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15971
diff
changeset
|
895 gnt_bindable_class_register_action(bindable, "move-parent", action_move_parent, |
5eb0621e0760
Backspace to jump to parent.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15971
diff
changeset
|
896 GNT_KEY_BACKSPACE, NULL); |
15818 | 897 gnt_bindable_class_register_action(bindable, "page-up", action_page_up, |
898 GNT_KEY_PGUP, NULL); | |
899 gnt_bindable_class_register_action(bindable, "page-down", action_page_down, | |
900 GNT_KEY_PGDOWN, NULL); | |
901 gnt_bindable_class_register_action(bindable, "start-search", start_search, | |
902 "/", NULL); | |
903 gnt_bindable_class_register_action(bindable, "end-search", end_search_action, | |
904 "\033", NULL); | |
905 | |
906 gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), bindable); | |
907 GNTDEBUG; | |
908 } | |
909 | |
910 static void | |
911 gnt_tree_init(GTypeInstance *instance, gpointer class) | |
912 { | |
913 GntWidget *widget = GNT_WIDGET(instance); | |
914 GntTree *tree = GNT_TREE(widget); | |
915 tree->show_separator = TRUE; | |
916 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X | GNT_WIDGET_GROW_Y); | |
917 widget->priv.minw = 4; | |
918 widget->priv.minh = 1; | |
919 GNTDEBUG; | |
920 } | |
921 | |
922 /****************************************************************************** | |
923 * GntTree API | |
924 *****************************************************************************/ | |
925 GType | |
926 gnt_tree_get_gtype(void) | |
927 { | |
928 static GType type = 0; | |
929 | |
930 if(type == 0) | |
931 { | |
932 static const GTypeInfo info = { | |
933 sizeof(GntTreeClass), | |
934 NULL, /* base_init */ | |
935 NULL, /* base_finalize */ | |
936 (GClassInitFunc)gnt_tree_class_init, | |
937 NULL, /* class_finalize */ | |
938 NULL, /* class_data */ | |
939 sizeof(GntTree), | |
940 0, /* n_preallocs */ | |
941 gnt_tree_init, /* instance_init */ | |
942 NULL /* value_table */ | |
943 }; | |
944 | |
945 type = g_type_register_static(GNT_TYPE_WIDGET, | |
946 "GntTree", | |
947 &info, 0); | |
948 } | |
949 | |
950 return type; | |
951 } | |
952 | |
953 static void | |
954 free_tree_col(gpointer data) | |
955 { | |
956 GntTreeCol *col = data; | |
957 | |
958 g_free(col->text); | |
959 g_free(col); | |
960 } | |
961 | |
962 static void | |
963 free_tree_row(gpointer data) | |
964 { | |
965 GntTreeRow *row = data; | |
966 | |
967 if (!row) | |
968 return; | |
969 | |
970 g_list_foreach(row->columns, (GFunc)free_tree_col, NULL); | |
971 g_list_free(row->columns); | |
972 g_free(row); | |
973 } | |
974 | |
975 GntWidget *gnt_tree_new() | |
976 { | |
977 return gnt_tree_new_with_columns(1); | |
978 } | |
979 | |
980 void gnt_tree_set_visible_rows(GntTree *tree, int rows) | |
981 { | |
982 GntWidget *widget = GNT_WIDGET(tree); | |
983 widget->priv.height = rows; | |
984 if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) | |
985 widget->priv.height += 2; | |
986 } | |
987 | |
988 int gnt_tree_get_visible_rows(GntTree *tree) | |
989 { | |
990 GntWidget *widget = GNT_WIDGET(tree); | |
991 int ret = widget->priv.height; | |
992 if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) | |
993 ret -= 2; | |
994 return ret; | |
995 } | |
996 | |
997 const GList *gnt_tree_get_rows(GntTree *tree) | |
998 { | |
999 return tree->list; | |
1000 } | |
1001 | |
1002 void gnt_tree_scroll(GntTree *tree, int count) | |
1003 { | |
1004 GntTreeRow *row; | |
1005 | |
1006 if (count < 0) | |
1007 { | |
1008 if (get_root_distance(tree->top) == 0) | |
1009 return; | |
1010 row = get_prev_n(tree->top, -count); | |
1011 if (row == NULL) | |
1012 row = tree->root; | |
1013 tree->top = row; | |
1014 } | |
1015 else | |
1016 { | |
1017 get_next_n_opt(tree->bottom, count, &count); | |
1018 tree->top = get_next_n(tree->top, count); | |
1019 } | |
1020 | |
1021 redraw_tree(tree); | |
1022 g_signal_emit(tree, signals[SIG_SCROLLED], 0, count); | |
1023 } | |
1024 | |
1025 static gpointer | |
1026 find_position(GntTree *tree, gpointer key, gpointer parent) | |
1027 { | |
1028 GntTreeRow *row; | |
1029 | |
1030 if (tree->compare == NULL) | |
1031 return NULL; | |
1032 | |
1033 if (parent == NULL) | |
1034 row = tree->root; | |
1035 else | |
1036 row = g_hash_table_lookup(tree->hash, parent); | |
1037 | |
1038 if (!row) | |
1039 return NULL; | |
1040 | |
1041 if (parent) | |
1042 row = row->child; | |
1043 | |
1044 while (row) | |
1045 { | |
1046 if (tree->compare(key, row->key) < 0) | |
1047 return (row->prev ? row->prev->key : NULL); | |
1048 if (row->next) | |
1049 row = row->next; | |
1050 else | |
1051 return row->key; | |
1052 } | |
1053 return NULL; | |
1054 } | |
1055 | |
1056 void gnt_tree_sort_row(GntTree *tree, gpointer key) | |
1057 { | |
1058 GntTreeRow *row, *q, *s; | |
1059 int current, newp; | |
1060 | |
1061 if (!tree->compare) | |
1062 return; | |
1063 | |
1064 row = g_hash_table_lookup(tree->hash, key); | |
1065 g_return_if_fail(row != NULL); | |
1066 | |
1067 current = g_list_index(tree->list, key); | |
1068 | |
1069 if (row->parent) | |
1070 s = row->parent->child; | |
1071 else | |
1072 s = tree->root; | |
1073 | |
1074 q = NULL; | |
1075 while (s) { | |
1076 if (tree->compare(row->key, s->key) < 0) | |
1077 break; | |
1078 q = s; | |
1079 s = s->next; | |
1080 } | |
1081 | |
1082 /* Move row between q and s */ | |
1083 if (row == q || row == s) | |
1084 return; | |
1085 | |
1086 if (q == NULL) { | |
1087 /* row becomes the first child of its parent */ | |
1088 row->prev->next = row->next; /* row->prev cannot be NULL at this point */ | |
1089 if (row->next) | |
1090 row->next->prev = row->prev; | |
1091 if (row->parent) | |
1092 row->parent->child = row; | |
1093 else | |
1094 tree->root = row; | |
1095 row->next = s; | |
1096 s->prev = row; /* s cannot be NULL */ | |
1097 row->prev = NULL; | |
1098 newp = g_list_index(tree->list, s) - 1; | |
1099 } else { | |
1100 if (row->prev) { | |
1101 row->prev->next = row->next; | |
1102 } else { | |
1103 /* row was the first child of its parent */ | |
1104 if (row->parent) | |
1105 row->parent->child = row->next; | |
1106 else | |
1107 tree->top = row->next; | |
1108 } | |
1109 | |
1110 if (row->next) | |
1111 row->next->prev = row->prev; | |
1112 | |
1113 q->next = row; | |
1114 row->prev = q; | |
1115 if (s) | |
1116 s->prev = row; | |
1117 row->next = s; | |
1118 newp = g_list_index(tree->list, q) + 1; | |
1119 } | |
1120 tree->list = g_list_reposition_child(tree->list, current, newp); | |
1121 | |
1122 redraw_tree(tree); | |
1123 } | |
1124 | |
1125 GntTreeRow *gnt_tree_add_row_after(GntTree *tree, void *key, GntTreeRow *row, void *parent, void *bigbro) | |
1126 { | |
1127 GntTreeRow *pr = NULL; | |
1128 | |
1129 g_hash_table_replace(tree->hash, key, row); | |
1130 row->tree = tree; | |
1131 | |
1132 if (bigbro == NULL && tree->compare) | |
1133 { | |
1134 bigbro = find_position(tree, key, parent); | |
1135 } | |
1136 | |
1137 if (tree->root == NULL) | |
1138 { | |
1139 tree->root = row; | |
1140 tree->list = g_list_prepend(tree->list, key); | |
1141 } | |
1142 else | |
1143 { | |
1144 int position = 0; | |
1145 | |
1146 if (bigbro) | |
1147 { | |
1148 pr = g_hash_table_lookup(tree->hash, bigbro); | |
1149 if (pr) | |
1150 { | |
1151 if (pr->next) pr->next->prev = row; | |
1152 row->next = pr->next; | |
1153 row->prev = pr; | |
1154 pr->next = row; | |
1155 row->parent = pr->parent; | |
1156 | |
1157 position = g_list_index(tree->list, bigbro); | |
1158 } | |
1159 } | |
1160 | |
1161 if (pr == NULL && parent) | |
1162 { | |
1163 pr = g_hash_table_lookup(tree->hash, parent); | |
1164 if (pr) | |
1165 { | |
1166 if (pr->child) pr->child->prev = row; | |
1167 row->next = pr->child; | |
1168 pr->child = row; | |
1169 row->parent = pr; | |
1170 | |
1171 position = g_list_index(tree->list, parent); | |
1172 } | |
1173 } | |
1174 | |
1175 if (pr == NULL) | |
1176 { | |
1177 GntTreeRow *r = tree->root; | |
1178 row->next = r; | |
1179 if (r) r->prev = row; | |
1180 if (tree->current == tree->root) | |
1181 tree->current = row; | |
1182 tree->root = row; | |
1183 tree->list = g_list_prepend(tree->list, key); | |
1184 } | |
1185 else | |
1186 { | |
1187 tree->list = g_list_insert(tree->list, key, position + 1); | |
1188 } | |
1189 } | |
1190 | |
1191 row->key = key; | |
1192 row->data = NULL; | |
1193 | |
1194 redraw_tree(tree); | |
1195 | |
1196 return row; | |
1197 } | |
1198 | |
1199 GntTreeRow *gnt_tree_add_row_last(GntTree *tree, void *key, GntTreeRow *row, void *parent) | |
1200 { | |
1201 GntTreeRow *pr = NULL, *br = NULL; | |
1202 | |
1203 if (parent) | |
1204 pr = g_hash_table_lookup(tree->hash, parent); | |
1205 | |
1206 if (pr) | |
1207 br = pr->child; | |
1208 else | |
1209 br = tree->root; | |
1210 | |
1211 if (br) | |
1212 { | |
1213 while (br->next) | |
1214 br = br->next; | |
1215 } | |
1216 | |
1217 return gnt_tree_add_row_after(tree, key, row, parent, br ? br->key : NULL); | |
1218 } | |
1219 | |
1220 gpointer gnt_tree_get_selection_data(GntTree *tree) | |
1221 { | |
1222 if (tree->current) | |
1223 return tree->current->key; /* XXX: perhaps we should just get rid of 'data' */ | |
1224 return NULL; | |
1225 } | |
1226 | |
1227 char *gnt_tree_get_selection_text(GntTree *tree) | |
1228 { | |
1229 if (tree->current) | |
1230 return update_row_text(tree, tree->current); | |
1231 return NULL; | |
1232 } | |
1233 | |
1234 GList *gnt_tree_get_selection_text_list(GntTree *tree) | |
1235 { | |
1236 GList *list = NULL, *iter; | |
1237 int i; | |
1238 | |
1239 if (!tree->current) | |
1240 return NULL; | |
1241 | |
1242 for (i = 0, iter = tree->current->columns; i < tree->ncol && iter; | |
1243 i++, iter = iter->next) | |
1244 { | |
1245 GntTreeCol *col = iter->data; | |
1246 list = g_list_append(list, g_strdup(col->text)); | |
1247 } | |
1248 | |
1249 return list; | |
1250 } | |
1251 | |
1252 void gnt_tree_remove(GntTree *tree, gpointer key) | |
1253 { | |
1254 GntTreeRow *row = g_hash_table_lookup(tree->hash, key); | |
1255 static int depth = 0; /* Only redraw after all child nodes are removed */ | |
1256 if (row) | |
1257 { | |
1258 gboolean redraw = FALSE; | |
1259 | |
1260 if (row->child) { | |
1261 depth++; | |
1262 while (row->child) { | |
1263 gnt_tree_remove(tree, row->child->key); | |
1264 } | |
1265 depth--; | |
1266 } | |
1267 | |
1268 if (get_distance(tree->top, row) >= 0 && get_distance(row, tree->bottom) >= 0) | |
1269 redraw = TRUE; | |
1270 | |
1271 /* Update root/top/current/bottom if necessary */ | |
1272 if (tree->root == row) | |
1273 tree->root = get_next(row); | |
1274 if (tree->top == row) | |
1275 { | |
1276 if (tree->top != tree->root) | |
1277 tree->top = get_prev(row); | |
1278 else | |
1279 tree->top = get_next(row); | |
1280 } | |
1281 if (tree->current == row) | |
1282 { | |
1283 if (tree->current != tree->root) | |
1284 tree->current = get_prev(row); | |
1285 else | |
1286 tree->current = get_next(row); | |
1287 tree_selection_changed(tree, row, tree->current); | |
1288 } | |
1289 if (tree->bottom == row) | |
1290 { | |
1291 tree->bottom = get_prev(row); | |
1292 } | |
1293 | |
1294 /* Fix the links */ | |
1295 if (row->next) | |
1296 row->next->prev = row->prev; | |
1297 if (row->parent && row->parent->child == row) | |
1298 row->parent->child = row->next; | |
1299 if (row->prev) | |
1300 row->prev->next = row->next; | |
1301 | |
1302 g_hash_table_remove(tree->hash, key); | |
1303 tree->list = g_list_remove(tree->list, key); | |
1304 | |
1305 if (redraw && depth == 0) | |
1306 { | |
1307 redraw_tree(tree); | |
1308 } | |
1309 } | |
1310 } | |
1311 | |
1312 static gboolean | |
1313 return_true(gpointer key, gpointer data, gpointer null) | |
1314 { | |
1315 return TRUE; | |
1316 } | |
1317 | |
1318 void gnt_tree_remove_all(GntTree *tree) | |
1319 { | |
1320 tree->root = NULL; | |
1321 g_hash_table_foreach_remove(tree->hash, (GHRFunc)return_true, tree); | |
1322 g_list_free(tree->list); | |
1323 tree->list = NULL; | |
1324 tree->current = tree->top = tree->bottom = NULL; | |
1325 } | |
1326 | |
1327 int gnt_tree_get_selection_visible_line(GntTree *tree) | |
1328 { | |
1329 return get_distance(tree->top, tree->current) + | |
1330 !!(GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_NO_BORDER)); | |
1331 } | |
1332 | |
1333 void gnt_tree_change_text(GntTree *tree, gpointer key, int colno, const char *text) | |
1334 { | |
1335 GntTreeRow *row; | |
1336 GntTreeCol *col; | |
1337 | |
1338 g_return_if_fail(colno < tree->ncol); | |
1339 | |
1340 row = g_hash_table_lookup(tree->hash, key); | |
1341 if (row) | |
1342 { | |
1343 col = g_list_nth_data(row->columns, colno); | |
1344 g_free(col->text); | |
16283
5187395d6b78
Debug is not necessary anymore, and don't crash on null text.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16249
diff
changeset
|
1345 col->text = g_strdup(text ? text : ""); |
15818 | 1346 |
1347 if (get_distance(tree->top, row) >= 0 && get_distance(row, tree->bottom) >= 0) | |
1348 redraw_tree(tree); | |
1349 } | |
1350 } | |
1351 | |
1352 GntTreeRow *gnt_tree_add_choice(GntTree *tree, void *key, GntTreeRow *row, void *parent, void *bigbro) | |
1353 { | |
1354 GntTreeRow *r; | |
1355 r = g_hash_table_lookup(tree->hash, key); | |
1356 g_return_val_if_fail(!r || !r->choice, NULL); | |
1357 | |
1358 if (bigbro == NULL) { | |
1359 if (tree->compare) | |
1360 bigbro = find_position(tree, key, parent); | |
1361 else { | |
1362 r = g_hash_table_lookup(tree->hash, parent); | |
1363 if (!r) | |
1364 r = tree->root; | |
1365 else | |
1366 r = r->child; | |
1367 if (r) { | |
1368 while (r->next) | |
1369 r = r->next; | |
1370 bigbro = r->key; | |
1371 } | |
1372 } | |
1373 } | |
1374 row = gnt_tree_add_row_after(tree, key, row, parent, bigbro); | |
1375 row->choice = TRUE; | |
1376 | |
1377 return row; | |
1378 } | |
1379 | |
1380 void gnt_tree_set_choice(GntTree *tree, void *key, gboolean set) | |
1381 { | |
1382 GntTreeRow *row = g_hash_table_lookup(tree->hash, key); | |
1383 | |
1384 if (!row) | |
1385 return; | |
1386 g_return_if_fail(row->choice); | |
1387 | |
1388 row->isselected = set; | |
1389 redraw_tree(tree); | |
1390 } | |
1391 | |
1392 gboolean gnt_tree_get_choice(GntTree *tree, void *key) | |
1393 { | |
1394 GntTreeRow *row = g_hash_table_lookup(tree->hash, key); | |
1395 | |
1396 if (!row) | |
1397 return FALSE; | |
1398 g_return_val_if_fail(row->choice, FALSE); | |
1399 | |
1400 return row->isselected; | |
1401 } | |
1402 | |
1403 void gnt_tree_set_row_flags(GntTree *tree, void *key, GntTextFormatFlags flags) | |
1404 { | |
1405 GntTreeRow *row = g_hash_table_lookup(tree->hash, key); | |
1406 if (!row || row->flags == flags) | |
1407 return; | |
1408 | |
1409 row->flags = flags; | |
1410 redraw_tree(tree); /* XXX: It shouldn't be necessary to redraw the whole darned tree */ | |
1411 } | |
1412 | |
1413 void gnt_tree_set_selected(GntTree *tree , void *key) | |
1414 { | |
1415 int dist; | |
1416 GntTreeRow *row = g_hash_table_lookup(tree->hash, key); | |
16203
4f6a6443a1e3
emit/handle gnttree signals appropriately
Richard Nelson <wabz@pidgin.im>
parents:
16123
diff
changeset
|
1417 if (!row || row == tree->current) |
15818 | 1418 return; |
1419 | |
1420 if (tree->top == NULL) | |
1421 tree->top = row; | |
1422 if (tree->bottom == NULL) | |
1423 tree->bottom = row; | |
1424 | |
1425 tree->current = row; | |
1426 if ((dist = get_distance(tree->current, tree->bottom)) < 0) | |
1427 gnt_tree_scroll(tree, -dist); | |
1428 else if ((dist = get_distance(tree->current, tree->top)) > 0) | |
1429 gnt_tree_scroll(tree, -dist); | |
1430 else | |
1431 redraw_tree(tree); | |
16203
4f6a6443a1e3
emit/handle gnttree signals appropriately
Richard Nelson <wabz@pidgin.im>
parents:
16123
diff
changeset
|
1432 tree_selection_changed(tree, row, tree->current); |
15818 | 1433 } |
1434 | |
1435 void _gnt_tree_init_internals(GntTree *tree, int col) | |
1436 { | |
1437 tree->ncol = col; | |
1438 tree->hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_tree_row); | |
1439 tree->columns = g_new0(struct _GntTreeColInfo, col); | |
1440 while (col--) | |
1441 { | |
1442 tree->columns[col].width = 15; | |
1443 } | |
1444 tree->list = NULL; | |
1445 tree->show_title = FALSE; | |
1446 } | |
1447 | |
1448 GntWidget *gnt_tree_new_with_columns(int col) | |
1449 { | |
1450 GntWidget *widget = g_object_new(GNT_TYPE_TREE, NULL); | |
1451 GntTree *tree = GNT_TREE(widget); | |
1452 | |
1453 _gnt_tree_init_internals(tree, col); | |
1454 | |
1455 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_SHADOW); | |
1456 gnt_widget_set_take_focus(widget, TRUE); | |
1457 | |
1458 return widget; | |
1459 } | |
1460 | |
1461 GntTreeRow *gnt_tree_create_row_from_list(GntTree *tree, GList *list) | |
1462 { | |
1463 GList *iter; | |
1464 int i; | |
1465 GntTreeRow *row = g_new0(GntTreeRow, 1); | |
1466 | |
1467 for (i = 0, iter = list; i < tree->ncol && iter; iter = iter->next, i++) | |
1468 { | |
1469 GntTreeCol *col = g_new0(GntTreeCol, 1); | |
1470 col->span = 1; | |
1471 col->text = g_strdup(iter->data ? iter->data : ""); | |
1472 | |
1473 row->columns = g_list_append(row->columns, col); | |
1474 } | |
1475 | |
1476 return row; | |
1477 } | |
1478 | |
1479 GntTreeRow *gnt_tree_create_row(GntTree *tree, ...) | |
1480 { | |
1481 int i; | |
1482 va_list args; | |
1483 GList *list = NULL; | |
1484 GntTreeRow *row; | |
1485 | |
1486 va_start(args, tree); | |
1487 for (i = 0; i < tree->ncol; i++) | |
1488 { | |
1489 list = g_list_append(list, va_arg(args, char *)); | |
1490 } | |
1491 va_end(args); | |
1492 | |
1493 row = gnt_tree_create_row_from_list(tree, list); | |
1494 g_list_free(list); | |
1495 | |
1496 return row; | |
1497 } | |
1498 | |
1499 void gnt_tree_set_col_width(GntTree *tree, int col, int width) | |
1500 { | |
1501 g_return_if_fail(col < tree->ncol); | |
1502 | |
1503 tree->columns[col].width = width; | |
1504 } | |
1505 | |
1506 void gnt_tree_set_column_titles(GntTree *tree, ...) | |
1507 { | |
1508 int i; | |
1509 va_list args; | |
1510 | |
1511 va_start(args, tree); | |
1512 for (i = 0; i < tree->ncol; i++) | |
1513 { | |
1514 const char *title = va_arg(args, const char *); | |
1515 tree->columns[i].title = g_strdup(title); | |
1516 } | |
1517 va_end(args); | |
1518 } | |
1519 | |
1520 void gnt_tree_set_show_title(GntTree *tree, gboolean set) | |
1521 { | |
1522 tree->show_title = set; | |
1523 GNT_WIDGET(tree)->priv.minh = (set ? 6 : 4); | |
1524 } | |
1525 | |
1526 void gnt_tree_set_compare_func(GntTree *tree, GCompareFunc func) | |
1527 { | |
1528 tree->compare = func; | |
1529 } | |
1530 | |
1531 void gnt_tree_set_expanded(GntTree *tree, void *key, gboolean expanded) | |
1532 { | |
1533 GntTreeRow *row = g_hash_table_lookup(tree->hash, key); | |
1534 if (row) { | |
1535 row->collapsed = !expanded; | |
1536 if (GNT_WIDGET(tree)->window) | |
1537 gnt_widget_draw(GNT_WIDGET(tree)); | |
16203
4f6a6443a1e3
emit/handle gnttree signals appropriately
Richard Nelson <wabz@pidgin.im>
parents:
16123
diff
changeset
|
1538 g_signal_emit(tree, signals[SIG_COLLAPSED], 0, key, row->collapsed); |
15818 | 1539 } |
1540 } | |
1541 | |
1542 void gnt_tree_set_show_separator(GntTree *tree, gboolean set) | |
1543 { | |
1544 tree->show_separator = set; | |
1545 } | |
1546 | |
1547 void gnt_tree_adjust_columns(GntTree *tree) | |
1548 { | |
1549 GntTreeRow *row = tree->root; | |
16123
bc280c341679
We don't need to do anything about the heights here.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16105
diff
changeset
|
1550 int *widths, i, twidth; |
15818 | 1551 |
1552 widths = g_new0(int, tree->ncol); | |
1553 while (row) { | |
1554 GList *iter; | |
1555 for (i = 0, iter = row->columns; iter; iter = iter->next, i++) { | |
1556 GntTreeCol *col = iter->data; | |
1557 int w = gnt_util_onscreen_width(col->text, NULL); | |
15968
0ab73bf1fef1
check-items are wider.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15931
diff
changeset
|
1558 if (i == 0 && row->choice) |
0ab73bf1fef1
check-items are wider.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15931
diff
changeset
|
1559 w += 4; |
15972
5eb0621e0760
Backspace to jump to parent.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15971
diff
changeset
|
1560 if (i == 0) { |
5eb0621e0760
Backspace to jump to parent.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15971
diff
changeset
|
1561 w += find_depth(row) * TAB_SIZE; |
5eb0621e0760
Backspace to jump to parent.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15971
diff
changeset
|
1562 } |
15818 | 1563 if (widths[i] < w) |
1564 widths[i] = w; | |
1565 } | |
15972
5eb0621e0760
Backspace to jump to parent.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15971
diff
changeset
|
1566 row = get_next(row); |
15818 | 1567 } |
1568 | |
1569 twidth = 1 + 2 * (!GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_NO_BORDER)); | |
1570 for (i = 0; i < tree->ncol; i++) { | |
1571 gnt_tree_set_col_width(tree, i, widths[i]); | |
15970
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
1572 if (!tree->columns[i].invisible) |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
1573 twidth += widths[i] + (tree->show_separator ? 1 : 0) + 1; |
15818 | 1574 } |
1575 g_free(widths); | |
1576 | |
16123
bc280c341679
We don't need to do anything about the heights here.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16105
diff
changeset
|
1577 gnt_widget_set_size(GNT_WIDGET(tree), twidth, -1); |
15818 | 1578 } |
1579 | |
1580 void gnt_tree_set_hash_fns(GntTree *tree, gpointer hash, gpointer eq, gpointer kd) | |
1581 { | |
1582 g_hash_table_foreach_remove(tree->hash, return_true, NULL); | |
1583 g_hash_table_destroy(tree->hash); | |
1584 tree->hash = g_hash_table_new_full(hash, eq, kd, free_tree_row); | |
1585 } | |
1586 | |
15970
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
1587 void gnt_tree_set_column_visible(GntTree *tree, int col, gboolean vis) |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
1588 { |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
1589 g_return_if_fail(col < tree->ncol); |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
1590 tree->columns[col].invisible = !vis; |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
1591 } |
790d1d003825
Allow making some columns invisible.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15968
diff
changeset
|
1592 |