📄 gtkcols.c
字号:
g_return_if_fail(cols != NULL); g_return_if_fail(IS_COLUMNS(cols)); g_return_if_fail(widget != NULL); for (children = cols->children; children && (child = children->data); children = children->next) { if (child->widget != widget) continue; child->force_left = TRUE; if (GTK_WIDGET_VISIBLE(widget)) gtk_widget_queue_resize(GTK_WIDGET(cols)); break; }}void columns_taborder_last(Columns *cols, GtkWidget *widget){ GtkWidget *childw; GList *children; g_return_if_fail(cols != NULL); g_return_if_fail(IS_COLUMNS(cols)); g_return_if_fail(widget != NULL); for (children = cols->taborder; children && (childw = children->data); children = children->next) { if (childw != widget) continue; cols->taborder = g_list_remove_link(cols->taborder, children); g_list_free(children); cols->taborder = g_list_append(cols->taborder, widget); break; }}/* * Override GtkContainer's focus movement so the user can * explicitly specify the tab order. */static gint columns_focus(GtkContainer *container, GtkDirectionType dir){ Columns *cols; GList *pos; GtkWidget *focuschild; g_return_val_if_fail(container != NULL, FALSE); g_return_val_if_fail(IS_COLUMNS(container), FALSE); cols = COLUMNS(container); if (!GTK_WIDGET_DRAWABLE(cols) || !GTK_WIDGET_IS_SENSITIVE(cols)) return FALSE; if (!GTK_WIDGET_CAN_FOCUS(container) && (dir == GTK_DIR_TAB_FORWARD || dir == GTK_DIR_TAB_BACKWARD)) { focuschild = container->focus_child; gtk_container_set_focus_child(container, NULL); if (dir == GTK_DIR_TAB_FORWARD) pos = cols->taborder; else pos = g_list_last(cols->taborder); while (pos) { GtkWidget *child = pos->data; if (focuschild) { if (focuschild == child) { focuschild = NULL; /* now we can start looking in here */ if (GTK_WIDGET_DRAWABLE(child) && GTK_IS_CONTAINER(child) && !GTK_WIDGET_HAS_FOCUS(child)) { if (gtk_container_focus(GTK_CONTAINER(child), dir)) return TRUE; } } } else if (GTK_WIDGET_DRAWABLE(child)) { if (GTK_IS_CONTAINER(child)) { if (gtk_container_focus(GTK_CONTAINER(child), dir)) return TRUE; } else if (GTK_WIDGET_CAN_FOCUS(child)) { gtk_widget_grab_focus(child); return TRUE; } } if (dir == GTK_DIR_TAB_FORWARD) pos = pos->next; else pos = pos->prev; } return FALSE; } else return columns_inherited_focus(container, dir);}/* * Now here comes the interesting bit. The actual layout part is * done in the following two functions: * * columns_size_request() examines the list of widgets held in the * Columns, and returns a requisition stating the absolute minimum * size it can bear to be. * * columns_size_allocate() is given an allocation telling it what * size the whole container is going to be, and it calls * gtk_widget_size_allocate() on all of its (visible) children to * set their size and position relative to the top left of the * container. */static void columns_size_request(GtkWidget *widget, GtkRequisition *req){ Columns *cols; ColumnsChild *child; GList *children; gint i, ncols, colspan, *colypos; const gint *percentages; static const gint onecol[] = { 100 }; g_return_if_fail(widget != NULL); g_return_if_fail(IS_COLUMNS(widget)); g_return_if_fail(req != NULL); cols = COLUMNS(widget); req->width = 0; req->height = cols->spacing; ncols = 1; colypos = g_new(gint, 1); colypos[0] = 0; percentages = onecol; for (children = cols->children; children && (child = children->data); children = children->next) { GtkRequisition creq; if (!child->widget) { /* Column reconfiguration. */ for (i = 1; i < ncols; i++) { if (colypos[0] < colypos[i]) colypos[0] = colypos[i]; } ncols = child->ncols; percentages = child->percentages; colypos = g_renew(gint, colypos, ncols); for (i = 1; i < ncols; i++) colypos[i] = colypos[0]; continue; } /* Only take visible widgets into account. */ if (!GTK_WIDGET_VISIBLE(child->widget)) continue; gtk_widget_size_request(child->widget, &creq); colspan = child->colspan ? child->colspan : ncols-child->colstart; /* * To compute width: we know that creq.width plus * cols->spacing needs to equal a certain percentage of the * full width of the container. So we work this value out, * figure out how wide the container will need to be to * make that percentage of it equal to that width, and * ensure our returned width is at least that much. Very * simple really. */ { int percent, thiswid, fullwid; percent = 0; for (i = 0; i < colspan; i++) percent += percentages[child->colstart+i]; thiswid = creq.width + cols->spacing; /* * Since creq is the _minimum_ size the child needs, we * must ensure that it gets _at least_ that size. * Hence, when scaling thiswid up to fullwid, we must * round up, which means adding percent-1 before * dividing by percent. */ fullwid = (thiswid * 100 + percent - 1) / percent; /* * The above calculation assumes every widget gets * cols->spacing on the right. So we subtract * cols->spacing here to account for the extra load of * spacing on the right. */ if (req->width < fullwid - cols->spacing) req->width = fullwid - cols->spacing; } /* * To compute height: the widget's top will be positioned * at the largest y value so far reached in any of the * columns it crosses. Then it will go down by creq.height * plus padding; and the point it reaches at the bottom is * the new y value in all those columns, and minus the * padding it is also a lower bound on our own size * request. */ { int topy, boty; topy = 0; for (i = 0; i < colspan; i++) { if (topy < colypos[child->colstart+i]) topy = colypos[child->colstart+i]; } boty = topy + creq.height + cols->spacing; for (i = 0; i < colspan; i++) { colypos[child->colstart+i] = boty; } if (req->height < boty - cols->spacing) req->height = boty - cols->spacing; } } req->width += 2*GTK_CONTAINER(cols)->border_width; req->height += 2*GTK_CONTAINER(cols)->border_width; g_free(colypos);}static void columns_size_allocate(GtkWidget *widget, GtkAllocation *alloc){ Columns *cols; ColumnsChild *child; GList *children; gint i, ncols, colspan, border, *colxpos, *colypos; const gint *percentages; static const gint onecol[] = { 100 }; g_return_if_fail(widget != NULL); g_return_if_fail(IS_COLUMNS(widget)); g_return_if_fail(alloc != NULL); cols = COLUMNS(widget); widget->allocation = *alloc; border = GTK_CONTAINER(cols)->border_width; ncols = 1; percentages = onecol; /* colxpos gives the starting x position of each column. * We supply n+1 of them, so that we can find the RH edge easily. * All ending x positions are expected to be adjusted afterwards by * subtracting the spacing. */ colxpos = g_new(gint, 2); colxpos[0] = 0; colxpos[1] = alloc->width - 2*border + cols->spacing; /* As in size_request, colypos is the lowest y reached in each column. */ colypos = g_new(gint, 1); colypos[0] = 0; for (children = cols->children; children && (child = children->data); children = children->next) { GtkRequisition creq; GtkAllocation call; if (!child->widget) { gint percent; /* Column reconfiguration. */ for (i = 1; i < ncols; i++) { if (colypos[0] < colypos[i]) colypos[0] = colypos[i]; } ncols = child->ncols; percentages = child->percentages; colypos = g_renew(gint, colypos, ncols); for (i = 1; i < ncols; i++) colypos[i] = colypos[0]; colxpos = g_renew(gint, colxpos, ncols + 1); colxpos[0] = 0; percent = 0; for (i = 0; i < ncols; i++) { percent += percentages[i]; colxpos[i+1] = (((alloc->width - 2*border) + cols->spacing) * percent / 100); } continue; } /* Only take visible widgets into account. */ if (!GTK_WIDGET_VISIBLE(child->widget)) continue; gtk_widget_get_child_requisition(child->widget, &creq); colspan = child->colspan ? child->colspan : ncols-child->colstart; /* * Starting x position is cols[colstart]. * Ending x position is cols[colstart+colspan] - spacing. * * Unless we're forcing left, in which case the width is * exactly the requisition width. */ call.x = alloc->x + border + colxpos[child->colstart]; if (child->force_left) call.width = creq.width; else call.width = (colxpos[child->colstart+colspan] - colxpos[child->colstart] - cols->spacing); /* * To compute height: the widget's top will be positioned * at the largest y value so far reached in any of the * columns it crosses. Then it will go down by creq.height * plus padding; and the point it reaches at the bottom is * the new y value in all those columns. */ { int topy, boty; topy = 0; for (i = 0; i < colspan; i++) { if (topy < colypos[child->colstart+i]) topy = colypos[child->colstart+i]; } call.y = alloc->y + border + topy; call.height = creq.height; boty = topy + creq.height + cols->spacing; for (i = 0; i < colspan; i++) { colypos[child->colstart+i] = boty; } } gtk_widget_size_allocate(child->widget, &call); } g_free(colxpos); g_free(colypos); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -