diff --git a/src/app.zig b/src/app.zig index c416d44..65f9c78 100644 --- a/src/app.zig +++ b/src/app.zig @@ -745,6 +745,22 @@ fn showToolbar(self: *App) void { } } +fn updateUI(self: *App) !void { + self.ui.begin(); + defer self.ui.end(); + + const root_box = self.ui.getParent().?; + root_box.layout_axis = .Y; + + self.showToolbar(); + + if (self.shown_window == .channels) { + try self.showChannelsWindow(); + } else if (self.shown_window == .add_from_device) { + try self.showAddFromDeviceWindow(); + } +} + pub fn tick(self: *App) !void { for (self.channel_views.slice()) |*_view| { const view: *ChannelView = _view; @@ -769,21 +785,12 @@ pub fn tick(self: *App) !void { Platform.toggleConsoleWindow(); } - { - self.ui.begin(); - defer self.ui.end(); - - const root_box = self.ui.getParent().?; - root_box.layout_axis = .Y; - - self.showToolbar(); - - if (self.shown_window == .channels) { - try self.showChannelsWindow(); - } else if (self.shown_window == .add_from_device) { - try self.showAddFromDeviceWindow(); - } + // On the first frame, render the UI twice. + // So that on the second pass widgets that depend on sizes from other widgets have settled + if (self.ui.frame_index == 0) { + try self.updateUI(); } + try self.updateUI(); self.ui.draw(); } \ No newline at end of file diff --git a/src/ui.zig b/src/ui.zig index f81e7c8..907db5b 100644 --- a/src/ui.zig +++ b/src/ui.zig @@ -881,6 +881,8 @@ fn calcLayoutEnforceConstraints(self: *UI, box: *Box, axis: Axis) void { { var child_iter = self.iterChildrenByParent(box); while (child_iter.next()) |child| { + if (child.isPositionFixed(axis)) continue; + const child_semantic_size_axis = child.size.getAxis(axis).*; const child_size_axis = getVec2Axis(&child.persistent.size, axis).*; @@ -899,9 +901,17 @@ fn calcLayoutEnforceConstraints(self: *UI, box: *Box, axis: Axis) void { var index: usize = 0; var child_iter = self.iterChildrenByParent(box); while (child_iter.next()) |child| : (index += 1) { + if (child.isPositionFixed(axis)) continue; + const child_size_axis = getVec2Axis(&child.persistent.size, axis); child_size_axis.* -= children_fixups.buffer[index] * overflow_percent; + + // Recalculate all upward depedent sizes, because the parent size changed + var child_child_iter = self.iterChildrenByParent(child); + while (child_child_iter.next()) |child_child| { + self.calcLayoutUpwardsSize(child_child, axis); + } } } } @@ -1136,18 +1146,18 @@ pub fn pushScrollbar(self: *UI, key: UI.Key) *Box { }; self.pushParent(container); - const scroll_area = self.newBoxFromString("Scroll area"); - scroll_area.size = .{ + const content_area = self.newBoxFromString("Scroll area"); + content_area.size = .{ .x = UI.Size.percent(1, 0), .y = UI.Size.percent(1, 0), }; - self.pushParent(scroll_area); + self.pushParent(content_area); - return scroll_area; + return content_area; } pub fn popScrollbar(self: *UI) void { - const scroll_area = self.getParent().?; + const content_area = self.getParent().?; self.popParent(); // pop scroll area const scrollbar_area = self.newBoxFromString("Scrollbar area"); @@ -1159,8 +1169,9 @@ pub fn popScrollbar(self: *UI) void { self.pushParent(scrollbar_area); defer self.popParent(); - var scrollbar_size_percent = scroll_area.persistent.size.y / scroll_area.persistent.children_size.y; - scrollbar_size_percent = std.math.clamp(scrollbar_size_percent, 0, 1); + const visible_content_size = content_area.persistent.size.y; + const used_content_size = content_area.persistent.children_size.y; + const visible_percent = clamp(visible_content_size / used_content_size, 0, 1); const draggable = self.newBoxFromString("Scrollbar button"); draggable.background = rl.Color.dark_brown; @@ -1168,21 +1179,22 @@ pub fn popScrollbar(self: *UI) void { draggable.flags.insert(.draggable_y); draggable.size = .{ .x = UI.Size.percent(1, 1), - .y = UI.Size.percent(scrollbar_size_percent, 1), + .y = UI.Size.percent(visible_percent, 1), }; - const scrollbar_area_height = scrollbar_area.persistent.size.y; - const scrollbar_max_move = scrollbar_area_height * (1 - scrollbar_size_percent); + const scrollbar_height = scrollbar_area.persistent.size.y; + + const max_offset = scrollbar_height * (1 - visible_percent); const sroll_offset = &draggable.persistent.sroll_offset; const signal = self.signalFromBox(draggable); if (signal.dragged()) { - sroll_offset.* += signal.drag.y / scrollbar_max_move; + sroll_offset.* += signal.drag.y / max_offset; sroll_offset.* = clamp(sroll_offset.*, 0, 1); } - draggable.setFixedY(scrollbar_area.persistent.position.y + sroll_offset.* * scrollbar_max_move); - scroll_area.view_offset.y = sroll_offset.* * (1 - scrollbar_size_percent) * scroll_area.persistent.children_size.y; + draggable.setFixedY(scrollbar_area.persistent.position.y + sroll_offset.* * max_offset); + content_area.view_offset.y = sroll_offset.* * (1 - visible_percent) * used_content_size; self.popParent(); // pop container } \ No newline at end of file