init
It's expected to call this when self is undefined
Parameters
- self:*ScrollAreaWidget
- *ScrollAreaWidget
- src:std.builtin.SourceLocation
- std.builtin.SourceLocation
- init_opts:InitOpts
- InitOpts
- opts:Options
- Options
Source
Implementation
pub fn init(self: *ScrollAreaWidget, src: std.builtin.SourceLocation, init_opts: InitOpts, opts: Options) void {
self.* = .{
.hbox = undefined, // set below
};
self.hbox.init(src, .{ .dir = .horizontal }, defaults.override(opts));
if (init_opts.scroll_info) |si| {
self.si = si;
if (init_opts.vertical != null) {
dvui.log.debug("ScrollAreaWidget {x} init_opts.vertical .{s} overridden by init_opts.scroll_info.vertical .{s}\n", .{ self.hbox.data().id, @tagName(init_opts.vertical.?), @tagName(si.vertical) });
}
if (init_opts.horizontal != null) {
dvui.log.debug("ScrollAreaWidget {x} init_opts.horizontal .{s} overridden by init_opts.scroll_info.horizontal .{s}\n", .{ self.hbox.data().id, @tagName(init_opts.horizontal.?), @tagName(si.horizontal) });
}
} else {
self.si = dvui.dataGetPtrDefault(null, self.hbox.data().id, "_scroll_info", ScrollInfo, .{});
// outside code might have changed what direction we scroll in
self.si.vertical = init_opts.vertical orelse .auto;
self.si.horizontal = init_opts.horizontal orelse .none;
}
self.hbox.drawBackground();
const focus_target = init_opts.focus_id orelse dvui.dataGet(null, self.hbox.data().id, "_scroll_id", dvui.Id);
const crect = self.hbox.data().contentRect();
// First assume ScrollContainer gets all our space.
self.si.viewport.w = crect.w;
self.si.viewport.h = crect.h;
// Now adjust if we got insets from last frame.
if (dvui.dataGet(null, self.hbox.data().id, "_linsets", dvui.Size)) |inset| {
self.si.viewport.w -= inset.w;
self.si.viewport.h -= inset.h;
} else if (!dvui.firstFrame(self.hbox.data().id)) {
dvui.log.debug("ScrollAreaWidget {x} missing insets from last frame\n", .{self.hbox.data().id});
}
// due to floating point inaccuracies, give ourselves a tiny bit of extra wiggle room
var do_vbar = false;
var do_hbar = false;
if (self.si.vertical != .none) {
if (init_opts.vertical_bar == .show or (init_opts.vertical_bar.autoAny() and (self.si.virtual_size.h > (self.si.viewport.h + 0.001)))) {
do_vbar = true;
if (init_opts.vertical_bar != .auto_overlay) {
self.si.viewport.w -= ScrollBarWidget.defaults.min_sizeGet().w;
}
}
}
if (self.si.horizontal != .none) {
if (init_opts.horizontal_bar == .show or (init_opts.horizontal_bar.autoAny() and (self.si.virtual_size.w > (self.si.viewport.w + 0.001)))) {
do_hbar = true;
if (init_opts.horizontal_bar != .auto_overlay) {
self.si.viewport.h -= ScrollBarWidget.defaults.min_sizeGet().h;
}
}
}
// test for vbar again because hbar might have removed some of our room
if (!do_vbar and do_hbar and self.si.vertical != .none) {
if (init_opts.vertical_bar.autoAny() and (self.si.virtual_size.h > (self.si.viewport.h + 0.001))) {
do_vbar = true;
if (init_opts.vertical_bar != .auto_overlay) {
self.si.viewport.w -= ScrollBarWidget.defaults.min_sizeGet().w;
}
}
}
if (do_vbar) {
// do the scrollbars first so that they still appear even if there's not enough space
const overlay = init_opts.vertical_bar == .auto_overlay;
self.vbar = @as(ScrollBarWidget, undefined); // Must be a non-null value for `.?` bellow
self.vbar.?.init(
@src(),
.{ .scroll_info = self.si, .focus_id = focus_target },
self.hbox.data().options.strip().override(.{ .gravity_x = if (overlay) 0.999 else 1.0, .expand = .vertical }),
);
if (overlay) {
self.vbar_grab = self.vbar.?.grab();
} else {
self.vbar.?.grab().draw();
}
self.vbar.?.deinit();
}
self.vbox.init(@src(), .{ .dir = .vertical }, self.hbox.data().options.strip().override(.{ .expand = .both, .name = "ScrollAreaWidget vbox" }));
self.vbox.drawBackground();
if (do_hbar) {
const overlay = init_opts.horizontal_bar == .auto_overlay;
self.hbar = @as(ScrollBarWidget, undefined); // Must be a non-null value for `.?` bellow
self.hbar.?.init(
@src(),
.{ .direction = .horizontal, .scroll_info = self.si, .focus_id = focus_target },
self.hbox.data().options.strip().override(.{ .expand = .horizontal, .gravity_y = if (overlay) 0.999 else 1.0 }),
);
if (overlay) {
self.hbar_grab = self.hbar.?.grab();
} else {
self.hbar.?.grab().draw();
}
self.hbar.?.deinit();
}
if (init_opts.container) {
const container_opts = self.hbox.data().options.strip().override(.{ .expand = .both });
self.scroll = @as(ScrollContainerWidget, undefined);
self.scroll.?.init(@src(), self.si, .{ .scroll_area = self, .lock_visible = init_opts.lock_visible, .user_scroll = init_opts.user_scroll, .frame_viewport = init_opts.frame_viewport, .process_events_after = init_opts.process_events_after }, container_opts);
self.scroll.?.processEvents();
self.scroll.?.processVelocity();
}
}