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