高度适应宽度
在这里,我们进入 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; }
既然我们知道如何获取子部件的候选宽度,我们就可以完成在相反方向上进行测量的函数。和之前一样,我们最终返回子部件所需的最大高度,因为我们的布局是水平的。
请注意,在这种情况下,orientation 是 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 已经给了我们尺寸)。




