高度换宽度
这是我们进入 GTK+ 尺寸分配更深层部分的地方。高度换宽度意味着小部件没有单一的最小尺寸,但它可能会为了获得更大的高度而适应更小的宽度。大多数小部件不是这样的。此行为的典型示例是可以将其文本包装在多行中的标签
高度换宽度使尺寸分配的成本更高,因此容器必须通过设置请求模式 来显式启用它。通常,容器应查看其子项并使用大多数子项首选的请求模式。为了简单起见,我们在此处对高度换宽度进行硬编码
static GtkSizeRequestMode
gtk_center_box_get_request_mode (GtkWidget *widget)
{
return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
}
两种方式都测量
编写可以处理高度换宽度的 measure() 函数的惯用方法是将其分解为两种情况:一种是沿着布局方向进行测量,另一种是沿着相反方向进行测量。
if (orientation == GTK_ORIENTATION_HORIZONTAL)
measure_orientation (widget, for_size,
orientation,
minimum, natural,
minimum_baseline, natural_baseline);
else
measure_opposite (widget, for_size,
orientation,
minimum, natural,
minimum_baseline, natural_baseline);
沿着方向进行测量就像我们一直以来的 measure() 函数一样:我们得到一个高度,因此我们询问所有子项对于该高度需要多少宽度,然后我们将答案相加。
沿着相反方向进行测量意味着回答问题:给定此宽度,您需要多少高度?我们要问子项相同的问题,但是我们应该给每个子项提供什么宽度?我们不能只是将全部宽度传递给每个子项,因为我们不希望它们重叠。
分配
为了解决这个问题,我们需要在子项之间分配 可用宽度。这正是我们的 size_allocate() 函数正在执行的操作,因此我们需要将 size_allocate() 的内部部分分解为一个单独的函数。
毫不奇怪,我们将把新函数命名为 distribute()。
static void
distribute (GtkCenterBox *self,
int for_size,
int size,
GtkRequestedSize *sizes)
{
/* Do whatever size_allocate() used to do
* to determine sizes
*/
sizes[0].minimum_size = start_size;
sizes[1].minimum_size = center_size;
sizes[2].minimum_size = end_size;
}
既然我们知道如何获取子元素的候选宽度,我们就可以完成反方向的测量函数。和之前一样,我们最终返回子元素所需高度的最大值,因为我们的布局是水平的。
请注意,在这种情况下,方向是 GTK_ORIENTATION_VERTICAL,因此 gtk_widget_measure() 调用返回的 min 和 nat 值是高度。
distribute (self, -1, width, sizes);
gtk_widget_measure (start_widget,
orientation,
sizes[0].minimum_size,
&start_min, &start_nat,
&min_baseline, &nat_baseline);
gtk_widget_measure (center_widget,
orientation,
sizes[1].minimum_size,
¢er_min, ¢er_nat,
&min_baseline, &nat_baseline);
gtk_widget_measure (end_widget,
orientation,
sizes[2].minimum_size,
&end_min, &end_nat,
&min_baseline, &nat_baseline);
*minimum = MAX (start_min, center_min, end_min);
*natural = MAX (start_nat, center_nat, end_nat);
既然我们已经将 size_allocate() 的大部分工作分解到 distribute() 函数中,我们可以直接从那里调用它,然后执行剩余的必要工作来为子元素分配位置(因为 distribute 已经给了我们大小)。
已展开
略小于自然大小
更小
以及更小
以及更小
参考文献
容器的秘密:尺寸分配
容器的秘密:尺寸分配,第 2 部分
容器的秘密:尺寸分配,第 3 部分
这些更改的代码
关于宽度适应高度几何管理的文档