rectFor
Parameters
- self:*BoxWidget
- *BoxWidget
- id:dvui.Id
- dvui.Id
- min_size:Size
- Size
- e:Options.Expand
- Options.Expand
- g:Options.Gravity
- Options.Gravity
Source
Implementation
pub fn rectFor(self: *BoxWidget, id: dvui.Id, min_size: Size, e: Options.Expand, g: Options.Gravity) Rect {
if (self.first_child) {
self.first_child = false;
// Lazily running this stuff that used to be in init so that using
// .data().rectSet() after init works.
// our rect for children has to start at 0,0
self.child_rect = self.data().contentRect().justSize();
if (self.data_prev) |dp| {
if (self.init_opts.equal_space) {
if (dp.packed_children > 0) {
switch (self.init_opts.dir) {
.horizontal => self.pixels_per_w = self.child_rect.w / dp.packed_children,
.vertical => self.pixels_per_w = self.child_rect.h / dp.packed_children,
}
}
} else {
var packed_weight = dp.total_weight;
if (self.init_opts.num_packed_expanded) |num| {
packed_weight = @floatFromInt(num);
}
if (packed_weight > 0) {
switch (self.init_opts.dir) {
.horizontal => self.pixels_per_w = @max(0, self.child_rect.w - dp.min_space_taken) / packed_weight,
.vertical => self.pixels_per_w = @max(0, self.child_rect.h - dp.min_space_taken) / packed_weight,
}
}
}
}
}
if (builtin.mode == .Debug) {
if (self.child_id != .zero) {
dvui.logError(@src(), error.BadOrder, "rectFor called before previous widget called minSizeForChild", .{});
}
self.child_id = id;
}
self.child_positioned = switch (self.init_opts.dir) {
.horizontal => g.x > 0 and g.x < 1.0,
.vertical => g.y > 0 and g.y < 1.0,
};
if (self.child_positioned) {
// don't pack this, we treat this like overlay - put it where they asked
return dvui.placeIn(self.data().contentRect().justSize(), min_size, e, g);
}
self.packed_children += 1;
var current_weight: f32 = 0.0;
if ((self.init_opts.dir == .horizontal and e.isHorizontal()) or (self.init_opts.dir == .vertical and e.isVertical())) {
current_weight = 1.0;
}
self.total_weight += current_weight;
const available = self.child_rect;
// adjust min size for expand ratio, which is forced
var ms = min_size;
self.ratio_extra = 0;
if (e == .ratio and ms.w != 0 and ms.h != 0) {
switch (self.init_opts.dir) {
.horizontal => {
const ratio = ms.w / ms.h;
ms.h = available.h;
ms.w = available.h * ratio;
self.ratio_extra = ms.w - min_size.w;
},
.vertical => {
const ratio = ms.h / ms.w;
ms.h = available.w * ratio;
ms.w = available.w;
self.ratio_extra = ms.h - min_size.h;
},
}
}
// min size after ratio
const child_min_size = ms;
const ret: Rect = if (self.init_opts.equal_space) blk: {
// position child inside the space we allocate for it
switch (self.init_opts.dir) {
.horizontal => {
ms.w = self.pixels_per_w;
ms.h = available.h;
const avail = dvui.placeIn(available, ms, .none, g);
self.removeSpace(avail, g);
break :blk dvui.placeIn(avail, child_min_size, e, g);
},
.vertical => {
ms.h = self.pixels_per_w;
ms.w = available.w;
const avail = dvui.placeIn(available, ms, .none, g);
self.removeSpace(avail, g);
break :blk dvui.placeIn(avail, child_min_size, e, g);
},
}
} else blk: {
// adjust min size for normal expand (since you only get prorated extra space)
// - keep the expand in the non box direction
var ee: Options.Expand = .none;
switch (self.init_opts.dir) {
.horizontal => {
ms.w += self.pixels_per_w * current_weight;
if (e.isVertical()) ee = .vertical;
},
.vertical => {
ms.h += self.pixels_per_w * current_weight;
if (e.isHorizontal()) ee = .horizontal;
},
}
const ret = dvui.placeIn(available, ms, ee, g);
self.removeSpace(ret, g);
break :blk ret;
};
switch (self.init_opts.dir) {
.horizontal => if (ret.w + 0.001 < child_min_size.w) {
self.ran_off = true;
},
.vertical => if (ret.h + 0.001 < child_min_size.h) {
self.ran_off = true;
},
}
return ret;
}