📄 gntbox.c
字号:
#include "gntbox.h"#include "gntutils.h"#include <string.h>enum{ SIGS = 1,};static GntWidgetClass *parent_class = NULL;static GntWidget * find_focusable_widget(GntBox *box);static voidadd_to_focus(gpointer value, gpointer data){ GntBox *box = GNT_BOX(data); GntWidget *w = GNT_WIDGET(value); if (GNT_IS_BOX(w)) g_list_foreach(GNT_BOX(w)->list, add_to_focus, box); else if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_CAN_TAKE_FOCUS)) box->focus = g_list_append(box->focus, w);}static voidget_title_thingies(GntBox *box, char *title, int *p, int *r){ GntWidget *widget = GNT_WIDGET(box); int len; char *end = (char*)gnt_util_onscreen_width_to_pointer(title, widget->priv.width - 4, &len); if (p) *p = (widget->priv.width - len) / 2; if (r) *r = (widget->priv.width + len) / 2; *end = '\0';}static voidgnt_box_draw(GntWidget *widget){ GntBox *box = GNT_BOX(widget); if (box->focus == NULL && widget->parent == NULL) g_list_foreach(box->list, add_to_focus, box); g_list_foreach(box->list, (GFunc)gnt_widget_draw, NULL); gnt_box_sync_children(box); if (box->title && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) { int pos, right; char *title = g_strdup(box->title); get_title_thingies(box, title, &pos, &right); if (gnt_widget_has_focus(widget)) wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_TITLE)); else wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_TITLE_D)); mvwaddch(widget->window, 0, pos-1, ACS_RTEE | COLOR_PAIR(GNT_COLOR_NORMAL)); mvwaddstr(widget->window, 0, pos, title); mvwaddch(widget->window, 0, right, ACS_LTEE | COLOR_PAIR(GNT_COLOR_NORMAL)); g_free(title); } GNTDEBUG;}static voidreposition_children(GntWidget *widget){ GList *iter; GntBox *box = GNT_BOX(widget); int w, h, curx, cury, max; gboolean has_border = FALSE; w = h = 0; max = 0; curx = widget->priv.x; cury = widget->priv.y; if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_BORDER)) { has_border = TRUE; curx += 1; cury += 1; } for (iter = box->list; iter; iter = iter->next) { if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(iter->data), GNT_WIDGET_INVISIBLE)) continue; gnt_widget_set_position(GNT_WIDGET(iter->data), curx, cury); gnt_widget_get_size(GNT_WIDGET(iter->data), &w, &h); if (box->vertical) { if (h) { cury += h + box->pad; if (max < w) max = w; } } else { if (w) { curx += w + box->pad; if (max < h) max = h; } } } if (has_border) { curx += 1; cury += 1; max += 2; } if (box->list) { if (box->vertical) cury -= box->pad; else curx -= box->pad; } if (box->vertical) { widget->priv.width = max; widget->priv.height = cury - widget->priv.y; } else { widget->priv.width = curx - widget->priv.x; widget->priv.height = max; }}static voidgnt_box_set_position(GntWidget *widget, int x, int y){ GList *iter; int changex, changey; changex = widget->priv.x - x; changey = widget->priv.y - y; for (iter = GNT_BOX(widget)->list; iter; iter = iter->next) { GntWidget *w = GNT_WIDGET(iter->data); gnt_widget_set_position(w, w->priv.x - changex, w->priv.y - changey); }}static voidgnt_box_size_request(GntWidget *widget){ GntBox *box = GNT_BOX(widget); GList *iter; int maxw = 0, maxh = 0; g_list_foreach(box->list, (GFunc)gnt_widget_size_request, NULL); for (iter = box->list; iter; iter = iter->next) { int w, h; gnt_widget_get_size(GNT_WIDGET(iter->data), &w, &h); if (maxh < h) maxh = h; if (maxw < w) maxw = w; } for (iter = box->list; iter; iter = iter->next) { int w, h; GntWidget *wid = GNT_WIDGET(iter->data); gnt_widget_get_size(wid, &w, &h); if (box->homogeneous) { if (box->vertical) h = maxh; else w = maxw; } if (box->fill) { if (box->vertical) w = maxw; else h = maxh; } gnt_widget_set_size(wid, w, h); } reposition_children(widget);}static voidgnt_box_map(GntWidget *widget){ if (widget->priv.width == 0 || widget->priv.height == 0) { gnt_widget_size_request(widget); find_focusable_widget(GNT_BOX(widget)); } GNTDEBUG;}/* Ensures that the current widget can take focus */static GntWidget *find_focusable_widget(GntBox *box){ /* XXX: Make sure the widget is visible? */ if (box->focus == NULL && GNT_WIDGET(box)->parent == NULL) g_list_foreach(box->list, add_to_focus, box); if (box->active == NULL && box->focus) box->active = box->focus->data; return box->active;}static voidfind_next_focus(GntBox *box){ gpointer last = box->active; do { GList *iter = g_list_find(box->focus, box->active); if (iter && iter->next) box->active = iter->next->data; else if (box->focus) box->active = box->focus->data; if (!GNT_WIDGET_IS_FLAG_SET(box->active, GNT_WIDGET_INVISIBLE)) break; } while (box->active != last);}static voidfind_prev_focus(GntBox *box){ gpointer last = box->active; if (!box->focus) return; do { GList *iter = g_list_find(box->focus, box->active); if (!iter) box->active = box->focus->data; else if (!iter->prev) box->active = g_list_last(box->focus)->data; else box->active = iter->prev->data; if (!GNT_WIDGET_IS_FLAG_SET(box->active, GNT_WIDGET_INVISIBLE)) break; } while (box->active != last);}static gbooleangnt_box_key_pressed(GntWidget *widget, const char *text){ GntBox *box = GNT_BOX(widget); GntWidget *now; if (box->active == NULL && !find_focusable_widget(box)) return FALSE; if (gnt_widget_key_pressed(box->active, text)) return TRUE; now = box->active; if (text[0] == 27) { if (strcmp(text, GNT_KEY_LEFT) == 0) { find_prev_focus(box); } else if (strcmp(text, GNT_KEY_RIGHT) == 0) { find_next_focus(box); } } else if (text[0] == '\t') { find_next_focus(box); } if (now && now != box->active) { gnt_widget_set_focus(now, FALSE); gnt_widget_set_focus(box->active, TRUE); return TRUE; } return FALSE;}static voidgnt_box_lost_focus(GntWidget *widget){ GntWidget *w = GNT_BOX(widget)->active; if (w) gnt_widget_set_focus(w, FALSE); gnt_widget_draw(widget);}static voidgnt_box_gained_focus(GntWidget *widget){ GntWidget *w = GNT_BOX(widget)->active; if (w) gnt_widget_set_focus(w, TRUE); gnt_widget_draw(widget);}static voidgnt_box_destroy(GntWidget *w){ GntBox *box = GNT_BOX(w); gnt_box_remove_all(box); gnt_screen_release(w);}static voidgnt_box_expose(GntWidget *widget, int x, int y, int width, int height){ WINDOW *win = newwin(height, width, widget->priv.y + y, widget->priv.x + x); copywin(widget->window, win, y, x, 0, 0, height - 1, width - 1, FALSE); wrefresh(win); delwin(win);}static gbooleangnt_box_confirm_size(GntWidget *widget, int width, int height){ GList *iter; GntBox *box = GNT_BOX(widget); int wchange, hchange; if (!box->list) return TRUE; wchange = widget->priv.width - width; hchange = widget->priv.height - height; if (wchange == 0 && hchange == 0) return TRUE; /* Quit playing games */ /* XXX: Right now, I am trying to just apply all the changes to * just one widget. It should be possible to distribute the * changes to all the widgets in the box. */ for (iter = box->list; iter; iter = iter->next) { GntWidget *wid = iter->data; int w, h; gnt_widget_get_size(wid, &w, &h); if (gnt_widget_confirm_size(wid, w - wchange, h - hchange)) { GList *i; for (i = box->list; i; i = i->next) { int tw, th; if (i == iter) continue; gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th); if (box->vertical) { if (!gnt_widget_confirm_size(i->data, tw - wchange, th)) { /* If we are decreasing the size and the widget is going * to be too large to fit into the box, then do not allow * resizing. */ if (wchange > 0 && tw >= widget->priv.width) return FALSE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -