Mercurial > pidgin
comparison finch/libgnt/gnttree.c @ 18404:9a0f99ea664d
Resize tree-columns nicely when the tree is resized. We can tell it to
set a fixed with for a column, or maintain the width-ratio when resizing.
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Sun, 01 Jul 2007 12:21:30 +0000 |
parents | 1f9db757efc2 |
children | 69cc1a4ef6ab |
comparison
equal
deleted
inserted
replaced
18403:8ee1f173253c | 18404:9a0f99ea664d |
---|---|
29 #include <ctype.h> | 29 #include <ctype.h> |
30 | 30 |
31 #define SEARCH_TIMEOUT 4000 /* 4 secs */ | 31 #define SEARCH_TIMEOUT 4000 /* 4 secs */ |
32 #define SEARCHING(tree) (tree->search && tree->search->len > 0) | 32 #define SEARCHING(tree) (tree->search && tree->search->len > 0) |
33 | 33 |
34 #define COLUMN_INVISIBLE(tree, index) (tree->columns[index].flags & GNT_TREE_COLUMN_INVISIBLE) | |
35 | |
34 enum | 36 enum |
35 { | 37 { |
36 SIG_SELECTION_CHANGED, | 38 SIG_SELECTION_CHANGED, |
37 SIG_SCROLLED, | 39 SIG_SCROLLED, |
38 SIG_TOGGLED, | 40 SIG_TOGGLED, |
72 | 74 |
73 static void tree_selection_changed(GntTree *, GntTreeRow *, GntTreeRow *); | 75 static void tree_selection_changed(GntTree *, GntTreeRow *, GntTreeRow *); |
74 | 76 |
75 static GntWidgetClass *parent_class = NULL; | 77 static GntWidgetClass *parent_class = NULL; |
76 static guint signals[SIGS] = { 0 }; | 78 static guint signals[SIGS] = { 0 }; |
79 | |
80 static void | |
81 readjust_columns(GntTree *tree) | |
82 { | |
83 int i, col, total; | |
84 int width; | |
85 #define WIDTH(i) tree->columns[i].width_ratio ? tree->columns[i].width_ratio : tree->columns[i].width | |
86 gnt_widget_get_size(GNT_WIDGET(tree), &width, NULL); | |
87 for (i = 0, total = 0; i < tree->ncol ; i++) { | |
88 if (tree->columns[i].flags & GNT_TREE_COLUMN_INVISIBLE) | |
89 continue; | |
90 if (tree->columns[i].flags & GNT_TREE_COLUMN_FIXED_SIZE) | |
91 width -= WIDTH(i); | |
92 else | |
93 total += WIDTH(i); | |
94 } | |
95 | |
96 if (total == 0) | |
97 return; | |
98 | |
99 for (i = 0; i < tree->ncol; i++) { | |
100 if (tree->columns[i].flags & GNT_TREE_COLUMN_INVISIBLE) | |
101 continue; | |
102 if (tree->columns[i].flags & GNT_TREE_COLUMN_FIXED_SIZE) | |
103 col = WIDTH(i); | |
104 else | |
105 col = WIDTH(i) * width / total; | |
106 gnt_tree_set_col_width(GNT_TREE(tree), i, col); | |
107 } | |
108 } | |
77 | 109 |
78 /* Move the item at position old to position new */ | 110 /* Move the item at position old to position new */ |
79 static GList * | 111 static GList * |
80 g_list_reposition_child(GList *list, int old, int new) | 112 g_list_reposition_child(GList *list, int old, int new) |
81 { | 113 { |
247 GList *iter; | 279 GList *iter; |
248 int i; | 280 int i; |
249 gboolean notfirst = FALSE; | 281 gboolean notfirst = FALSE; |
250 int lastvisible = tree->ncol; | 282 int lastvisible = tree->ncol; |
251 | 283 |
252 while (lastvisible && tree->columns[lastvisible].invisible) | 284 while (lastvisible && COLUMN_INVISIBLE(tree, lastvisible)) |
253 lastvisible--; | 285 lastvisible--; |
254 | 286 |
255 for (i = 0, iter = row->columns; i < tree->ncol && iter; i++, iter = iter->next) | 287 for (i = 0, iter = row->columns; i < tree->ncol && iter; i++, iter = iter->next) |
256 { | 288 { |
257 GntTreeCol *col = iter->data; | 289 GntTreeCol *col = iter->data; |
259 int len = gnt_util_onscreen_width(col->text, NULL); | 291 int len = gnt_util_onscreen_width(col->text, NULL); |
260 int fl = 0; | 292 int fl = 0; |
261 gboolean cut = FALSE; | 293 gboolean cut = FALSE; |
262 int width; | 294 int width; |
263 | 295 |
264 if (tree->columns[i].invisible) | 296 if (COLUMN_INVISIBLE(tree, i)) |
265 continue; | 297 continue; |
266 | 298 |
267 if (i == lastvisible) | 299 if (i == lastvisible) |
268 width = GNT_WIDGET(tree)->priv.width - gnt_util_onscreen_width(string->str, NULL); | 300 width = GNT_WIDGET(tree)->priv.width - gnt_util_onscreen_width(string->str, NULL); |
269 else | 301 else |
333 int x = pos; | 365 int x = pos; |
334 gboolean notfirst = FALSE; | 366 gboolean notfirst = FALSE; |
335 | 367 |
336 for (i = 0; i < tree->ncol - 1; i++) | 368 for (i = 0; i < tree->ncol - 1; i++) |
337 { | 369 { |
338 if (!tree->columns[i].invisible) { | 370 if (!COLUMN_INVISIBLE(tree, i)) { |
339 notfirst = TRUE; | 371 notfirst = TRUE; |
340 NEXT_X; | 372 NEXT_X; |
341 } | 373 } |
342 if (!tree->columns[i+1].invisible && notfirst) | 374 if (!COLUMN_INVISIBLE(tree, i+1) && notfirst) |
343 mvwaddch(widget->window, y, x, type); | 375 mvwaddch(widget->window, y, x, type); |
344 } | 376 } |
345 } | 377 } |
346 | 378 |
347 static void | 379 static void |
381 mvwhline(widget->window, pos, pos, ' ' | COLOR_PAIR(GNT_COLOR_NORMAL), | 413 mvwhline(widget->window, pos, pos, ' ' | COLOR_PAIR(GNT_COLOR_NORMAL), |
382 widget->priv.width - pos - 1); | 414 widget->priv.width - pos - 1); |
383 | 415 |
384 for (i = 0; i < tree->ncol; i++) | 416 for (i = 0; i < tree->ncol; i++) |
385 { | 417 { |
386 if (tree->columns[i].invisible) { | 418 if (COLUMN_INVISIBLE(tree, i)) { |
387 continue; | 419 continue; |
388 } | 420 } |
389 mvwaddstr(widget->window, pos, x + 1, tree->columns[i].title); | 421 mvwaddstr(widget->window, pos, x + 1, tree->columns[i].title); |
390 NEXT_X; | 422 NEXT_X; |
391 } | 423 } |
553 if (widget->priv.width == 0) | 585 if (widget->priv.width == 0) |
554 { | 586 { |
555 GntTree *tree = GNT_TREE(widget); | 587 GntTree *tree = GNT_TREE(widget); |
556 int i, width = 0; | 588 int i, width = 0; |
557 for (i = 0; i < tree->ncol; i++) | 589 for (i = 0; i < tree->ncol; i++) |
558 if (!tree->columns[i].invisible) | 590 if (!COLUMN_INVISIBLE(tree, i)) |
559 width += tree->columns[i].width + 1; | 591 width += tree->columns[i].width + 1; |
560 widget->priv.width = width; | 592 widget->priv.width = width; |
561 } | 593 } |
562 } | 594 } |
563 | 595 |
827 | 859 |
828 static void | 860 static void |
829 gnt_tree_size_changed(GntWidget *widget, int w, int h) | 861 gnt_tree_size_changed(GntWidget *widget, int w, int h) |
830 { | 862 { |
831 GntTree *tree = GNT_TREE(widget); | 863 GntTree *tree = GNT_TREE(widget); |
832 int i; | |
833 int n = 0; | |
834 if (widget->priv.width <= 0) | 864 if (widget->priv.width <= 0) |
835 return; | 865 return; |
836 for (i = 0; i < tree->ncol; ++i) | 866 |
837 n += tree->columns[i].width; | 867 readjust_columns(tree); |
838 if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) | |
839 tree->columns[tree->ncol - 1].width += widget->priv.width - n - 1 * tree->ncol; | |
840 else | |
841 tree->columns[tree->ncol - 1].width += widget->priv.width - n - 2 - 1 * tree->ncol; | |
842 } | 868 } |
843 | 869 |
844 static gboolean | 870 static gboolean |
845 start_search(GntBindable *bindable, GList *list) | 871 start_search(GntBindable *bindable, GList *list) |
846 { | 872 { |
1522 void gnt_tree_set_col_width(GntTree *tree, int col, int width) | 1548 void gnt_tree_set_col_width(GntTree *tree, int col, int width) |
1523 { | 1549 { |
1524 g_return_if_fail(col < tree->ncol); | 1550 g_return_if_fail(col < tree->ncol); |
1525 | 1551 |
1526 tree->columns[col].width = width; | 1552 tree->columns[col].width = width; |
1553 if (tree->columns[col].width_ratio == 0) | |
1554 tree->columns[col].width_ratio = width; | |
1527 } | 1555 } |
1528 | 1556 |
1529 void gnt_tree_set_column_title(GntTree *tree, int index, const char *title) | 1557 void gnt_tree_set_column_title(GntTree *tree, int index, const char *title) |
1530 { | 1558 { |
1531 g_free(tree->columns[index].title); | 1559 g_free(tree->columns[index].title); |
1596 } | 1624 } |
1597 | 1625 |
1598 twidth = 1 + 2 * (!GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_NO_BORDER)); | 1626 twidth = 1 + 2 * (!GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(tree), GNT_WIDGET_NO_BORDER)); |
1599 for (i = 0; i < tree->ncol; i++) { | 1627 for (i = 0; i < tree->ncol; i++) { |
1600 gnt_tree_set_col_width(tree, i, widths[i]); | 1628 gnt_tree_set_col_width(tree, i, widths[i]); |
1601 if (!tree->columns[i].invisible) | 1629 if (!COLUMN_INVISIBLE(tree, i)) |
1602 twidth += widths[i] + (tree->show_separator ? 1 : 0) + 1; | 1630 twidth += widths[i] + (tree->show_separator ? 1 : 0) + 1; |
1603 } | 1631 } |
1604 g_free(widths); | 1632 g_free(widths); |
1605 | 1633 |
1606 gnt_widget_set_size(GNT_WIDGET(tree), twidth, -1); | 1634 gnt_widget_set_size(GNT_WIDGET(tree), twidth, -1); |
1611 g_hash_table_foreach_remove(tree->hash, return_true, NULL); | 1639 g_hash_table_foreach_remove(tree->hash, return_true, NULL); |
1612 g_hash_table_destroy(tree->hash); | 1640 g_hash_table_destroy(tree->hash); |
1613 tree->hash = g_hash_table_new_full(hash, eq, kd, free_tree_row); | 1641 tree->hash = g_hash_table_new_full(hash, eq, kd, free_tree_row); |
1614 } | 1642 } |
1615 | 1643 |
1644 static void | |
1645 set_column_flag(GntTree *tree, int col, GntTreeColumnFlag flag, gboolean set) | |
1646 { | |
1647 if (set) | |
1648 tree->columns[col].flags |= flag; | |
1649 else | |
1650 tree->columns[col].flags &= ~flag; | |
1651 } | |
1652 | |
1616 void gnt_tree_set_column_visible(GntTree *tree, int col, gboolean vis) | 1653 void gnt_tree_set_column_visible(GntTree *tree, int col, gboolean vis) |
1617 { | 1654 { |
1618 g_return_if_fail(col < tree->ncol); | 1655 g_return_if_fail(col < tree->ncol); |
1619 tree->columns[col].invisible = !vis; | 1656 set_column_flag(tree, col, GNT_TREE_COLUMN_INVISIBLE, !vis); |
1620 } | 1657 } |
1621 | 1658 |
1659 void gnt_tree_set_column_resizable(GntTree *tree, int col, gboolean res) | |
1660 { | |
1661 g_return_if_fail(col < tree->ncol); | |
1662 set_column_flag(tree, col, GNT_TREE_COLUMN_FIXED_SIZE, !res); | |
1663 } | |
1664 | |
1665 void gnt_tree_set_column_width_ratio(GntTree *tree, int cols[]) | |
1666 { | |
1667 int i; | |
1668 for (i = 0; i < tree->ncol && cols[i]; i++) { | |
1669 tree->columns[i].width_ratio = cols[i]; | |
1670 } | |
1671 } | |
1672 |