📄 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 + -