📄 gnttree.c
字号:
{ GntTree *tree = GNT_TREE(widget); int i, width = 0; for (i = 0; i < tree->ncol; i++) if (!tree->columns[i].invisible) width += tree->columns[i].width + 1; widget->priv.width = width; }}static voidgnt_tree_map(GntWidget *widget){ GntTree *tree = GNT_TREE(widget); if (widget->priv.width == 0 || widget->priv.height == 0) { gnt_widget_size_request(widget); } tree->top = tree->root; tree->current = tree->root; GNTDEBUG;}static voidtree_selection_changed(GntTree *tree, GntTreeRow *old, GntTreeRow *current){ g_signal_emit(tree, signals[SIG_SELECTION_CHANGED], 0, old ? old->key : NULL, current ? current->key : NULL);}static gbooleanaction_down(GntBindable *bind, GList *null){ int dist; GntTree *tree = GNT_TREE(bind); GntTreeRow *old = tree->current; GntTreeRow *row = get_next(tree->current); if (row == NULL) return FALSE; tree->current = row; if ((dist = get_distance(tree->current, tree->bottom)) < 0) gnt_tree_scroll(tree, -dist); else redraw_tree(tree); if (old != tree->current) tree_selection_changed(tree, old, tree->current); return TRUE;}static gbooleanaction_move_parent(GntBindable *bind, GList *null){ GntTree *tree = GNT_TREE(bind); GntTreeRow *row = tree->current; int dist; if (!row->parent || SEARCHING(tree)) return FALSE; tree->current = row->parent; if ((dist = get_distance(tree->current, tree->top)) > 0) gnt_tree_scroll(tree, -dist); else redraw_tree(tree); tree_selection_changed(tree, row, tree->current); return TRUE;}static gbooleanaction_up(GntBindable *bind, GList *list){ int dist; GntTree *tree = GNT_TREE(bind); GntTreeRow *old = tree->current; GntTreeRow *row = get_prev(tree->current); if (!row) return FALSE; tree->current = row; if ((dist = get_distance(tree->current, tree->top)) > 0) gnt_tree_scroll(tree, -dist); else redraw_tree(tree); if (old != tree->current) tree_selection_changed(tree, old, tree->current); return TRUE;}static gbooleanaction_page_down(GntBindable *bind, GList *null){ GntTree *tree = GNT_TREE(bind); GntTreeRow *old = tree->current; GntTreeRow *row = get_next(tree->bottom); if (row) { int dist = get_distance(tree->top, tree->current); tree->top = tree->bottom; tree->current = get_next_n_opt(tree->top, dist, NULL); redraw_tree(tree); } else if (tree->current != tree->bottom) { tree->current = tree->bottom; redraw_tree(tree); } if (old != tree->current) tree_selection_changed(tree, old, tree->current); return TRUE;}static gbooleanaction_page_up(GntBindable *bind, GList *null){ GntWidget *widget = GNT_WIDGET(bind); GntTree *tree = GNT_TREE(bind); GntTreeRow *row; GntTreeRow *old = tree->current; if (tree->top != tree->root) { int dist = get_distance(tree->top, tree->current); row = get_prev_n(tree->top, widget->priv.height - 1 - tree->show_title * 2 - 2 * (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER) == 0)); if (row == NULL) row = tree->root; tree->top = row; tree->current = get_next_n_opt(tree->top, dist, NULL); redraw_tree(tree); } else if (tree->current != tree->top) { tree->current = tree->top; redraw_tree(tree); } if (old != tree->current) tree_selection_changed(tree, old, tree->current); return TRUE;}static voidend_search(GntTree *tree){ if (tree->search) { g_source_remove(tree->search_timeout); g_string_free(tree->search, TRUE); tree->search = NULL; tree->search_timeout = 0; }}static gbooleansearch_timeout(gpointer data){ GntTree *tree = data; end_search(tree); redraw_tree(tree); return FALSE;}static gbooleangnt_tree_key_pressed(GntWidget *widget, const char *text){ GntTree *tree = GNT_TREE(widget); GntTreeRow *old = tree->current; if (text[0] == '\r') { end_search(tree); gnt_widget_activate(widget); } else if (tree->search) { gboolean changed = TRUE; if (isalnum(*text)) { tree->search = g_string_append_c(tree->search, *text); } else if (g_utf8_collate(text, GNT_KEY_BACKSPACE) == 0) { if (tree->search->len) tree->search->str[--tree->search->len] = '\0'; } else changed = FALSE; if (changed) { redraw_tree(tree); g_source_remove(tree->search_timeout); tree->search_timeout = g_timeout_add(SEARCH_TIMEOUT, search_timeout, tree); } return TRUE; } else if (text[0] == ' ' && text[1] == 0) { /* Space pressed */ GntTreeRow *row = tree->current; if (row && row->child) { row->collapsed = !row->collapsed; redraw_tree(tree); g_signal_emit(tree, signals[SIG_COLLAPSED], 0, row->key, row->collapsed); } else if (row && row->choice) { row->isselected = !row->isselected; g_signal_emit(tree, signals[SIG_TOGGLED], 0, row->key); redraw_tree(tree); } } if (old != tree->current) { tree_selection_changed(tree, old, tree->current); return TRUE; } return FALSE;}static voidgnt_tree_destroy(GntWidget *widget){ GntTree *tree = GNT_TREE(widget); int i; end_search(tree); if (tree->hash) g_hash_table_destroy(tree->hash); g_list_free(tree->list); for (i = 0; i < tree->ncol; i++) { g_free(tree->columns[i].title); } g_free(tree->columns);}static gbooleangnt_tree_clicked(GntWidget *widget, GntMouseEvent event, int x, int y){ GntTree *tree = GNT_TREE(widget); GntTreeRow *old = tree->current; if (event == GNT_MOUSE_SCROLL_UP) { action_up(GNT_BINDABLE(widget), NULL); } else if (event == GNT_MOUSE_SCROLL_DOWN) { action_down(GNT_BINDABLE(widget), NULL); } else if (event == GNT_LEFT_MOUSE_DOWN) { GntTreeRow *row; GntTree *tree = GNT_TREE(widget); int pos = 1; if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) pos = 0; if (tree->show_title) pos += 2; pos = y - widget->priv.y - pos; row = get_next_n(tree->top, pos); if (row && tree->current != row) { GntTreeRow *old = tree->current; tree->current = row; redraw_tree(tree); tree_selection_changed(tree, old, tree->current); } else if (row && row == tree->current) { if (row->choice) { row->isselected = !row->isselected; g_signal_emit(tree, signals[SIG_TOGGLED], 0, row->key); redraw_tree(tree); } else { gnt_widget_activate(widget); } } } else { return FALSE; } if (old != tree->current) { tree_selection_changed(tree, old, tree->current); } return TRUE;}static voidgnt_tree_size_changed(GntWidget *widget, int w, int h){ GntTree *tree = GNT_TREE(widget); int i; int n = 0; if (widget->priv.width <= 0) return; for (i = 0; i < tree->ncol; ++i) n += tree->columns[i].width; if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) tree->columns[tree->ncol - 1].width += widget->priv.width - n - 1 * tree->ncol; else tree->columns[tree->ncol - 1].width += widget->priv.width - n - 2 - 1 * tree->ncol;}static gbooleanstart_search(GntBindable *bindable, GList *list){ GntTree *tree = GNT_TREE(bindable); if (tree->search) return FALSE; tree->search = g_string_new(NULL); tree->search_timeout = g_timeout_add(SEARCH_TIMEOUT, search_timeout, tree); return TRUE;}static gbooleanend_search_action(GntBindable *bindable, GList *list){ GntTree *tree = GNT_TREE(bindable); if (tree->search == NULL) return FALSE; end_search(tree); redraw_tree(tree); return TRUE;}static voidgnt_tree_class_init(GntTreeClass *klass){ GntBindableClass *bindable = GNT_BINDABLE_CLASS(klass); parent_class = GNT_WIDGET_CLASS(klass); parent_class->destroy = gnt_tree_destroy; parent_class->draw = gnt_tree_draw; parent_class->map = gnt_tree_map; parent_class->size_request = gnt_tree_size_request; parent_class->key_pressed = gnt_tree_key_pressed; parent_class->clicked = gnt_tree_clicked; parent_class->size_changed = gnt_tree_size_changed; signals[SIG_SELECTION_CHANGED] = g_signal_new("selection-changed", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntTreeClass, selection_changed), NULL, NULL, gnt_closure_marshal_VOID__POINTER_POINTER, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); signals[SIG_SCROLLED] = g_signal_new("scrolled", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); signals[SIG_TOGGLED] = g_signal_new("toggled", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(GntTreeClass, toggled), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[SIG_COLLAPSED] = g_signal_new("collapse-toggled", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, gnt_closure_marshal_VOID__POINTER_BOOLEAN, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_BOOLEAN); gnt_bindable_class_register_action(bindable, "move-up", action_up, GNT_KEY_UP, NULL); gnt_bindable_register_binding(bindable, "move-up", GNT_KEY_CTRL_P, NULL); gnt_bindable_class_register_action(bindable, "move-down", action_down, GNT_KEY_DOWN, NULL); gnt_bindable_register_binding(bindable, "move-down", GNT_KEY_CTRL_N, NULL); gnt_bindable_class_register_action(bindable, "move-parent", action_move_parent, GNT_KEY_BACKSPACE, NULL); gnt_bindable_class_register_action(bindable, "page-up", action_page_up, GNT_KEY_PGUP, NULL); gnt_bindable_class_register_action(bindable, "page-down", action_page_down, GNT_KEY_PGDOWN, NULL); gnt_bindable_class_register_action(bindable, "start-search", start_search, "/", NULL); gnt_bindable_class_register_action(bindable, "end-search", end_search_action, "\033", NULL); gnt_style_read_actions(G_OBJECT_CLASS_TYPE(klass), bindable); GNTDEBUG;}static voidgnt_tree_init(GTypeInstance *instance, gpointer class){ GntWidget *widget = GNT_WIDGET(instance); GntTree *tree = GNT_TREE(widget); tree->show_separator = TRUE; GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X | GNT_WIDGET_GROW_Y); widget->priv.minw = 4; widget->priv.minh = 1; GNTDEBUG;}/****************************************************************************** * GntTree API *****************************************************************************/GTypegnt_tree_get_gtype(void){ static GType type = 0; if(type == 0) { static const GTypeInfo info = { sizeof(GntTreeClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc)gnt_tree_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof(GntTree), 0, /* n_preallocs */ gnt_tree_init, /* instance_init */ NULL /* value_table */ }; type = g_type_register_static(GNT_TYPE_WIDGET, "GntTree", &info, 0); } return type;}static voidfree_tree_col(gpointer data){ GntTreeCol *col = data; g_free(col->text); g_free(col);}static voidfree_tree_row(gpointer data){ GntTreeRow *row = data; if (!row) return; g_list_foreach(row->columns, (GFunc)free_tree_col, NULL); g_list_free(row->columns); g_free(row);}GntWidget *gnt_tree_new(){ return gnt_tree_new_with_columns(1);}void gnt_tree_set_visible_rows(GntTree *tree, int rows){ GntWidget *widget = GNT_WIDGET(tree); widget->priv.height = rows; if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) widget->priv.height += 2;}int gnt_tree_get_visible_rows(GntTree *tree){ GntWidget *widget = GNT_WIDGET(tree); int ret = widget->priv.height; if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) ret -= 2; return ret;}const GList *gnt_tree_get_rows(GntTree *tree){ return tree->list;}void gnt_tree_scroll(GntTree *tree, int count){ GntTreeRow *row; if (count < 0) { if (get_root_distance(tree->top) == 0) return; row = get_prev_n(tree->top, -count); if (row == NULL) row = tree->root; tree->top = row; } else { get_next_n_opt(tree->bottom, count, &count); tree->top = get_next_n(tree->top, count); } redraw_tree(tree); g_signal_emit(tree, signals[SIG_SCROLLED], 0, count);}static gpointerfind_position(GntTree *tree, gpointer key, gpointer parent){ GntTreeRow *row; if (tree->compare == NULL) return NULL; if (parent == NULL) row = tree->root; else row = g_hash_table_lookup(tree->hash, parent); if (!row) return NULL; if (parent) row = row->child; while (row) { if (tree->compare(key, row->key) < 0) return (row->prev ? row->prev->key : NULL); if (row->next) row = row->next; else return row->key; } return NULL;}void gnt_tree_sort_row(GntTree *tree, gpointer key){ GntTreeRow *row, *q, *s; int current, newp; if (!tree->compare) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -