╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │915 self.arena.deinit(); │ │916 } │ │917 │ │918 - // `links`, when given, is parallel to `items`: a non-empty entry sets that │ │919 - // item's focus kind to `.{ .custom = link }` (e.g. "a:/user/foo"), which the │ │920 - // web renderer turns into an anchor. pass null when items aren't links. │ │918 + // one flow item: its display text plus an optional link. a non-empty `link` │ │919 + // sets the item's focus kind such as `.{ .custom = "a:/user/foo" }`, which │ │920 + // the web renderer turns into an anchor. │ │921 + pub const Item = struct { text: []const u8, link: []const u8 = "" }; │ │922 + │ │923 // both the item text and the link are copied into the arena, so the caller's │ │924 // slices needn't outlive this call. │ │923 - pub fn setItems(self: *FlowBox, allocator: std.mem.Allocator, items: []const []const u8, links: ?[]const []const u8) !void {│ │925 + pub fn setItems(self: *FlowBox, allocator: std.mem.Allocator, items: []const Item) !void { │ │926 for (self.text_boxes.items) |*tb| tb.deinit(allocator); │ │927 self.text_boxes.clearAndFree(allocator); │ │928 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │934 self.focus.clear(); │ │935 self.focus.child_id = null; │ │936 │ │935 - for (items, 0..) |item, i| { │ │936 - const line = try aa.dupe(u8, item); │ │937 + for (items) |item| { │ │938 + const line = try aa.dupe(u8, item.text); │ │939 │ │940 var text_box = try wgt.TextBox(Widget).init(allocator, line, .{ .border_style = .hidden, .rounded_corners = true, .wrap_kind = .word });│ │941 errdefer text_box.deinit(allocator); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │942 text_box.getFocus().focusable = true; │ │943 │ │942 - if (links) |link_items| { │ │943 - if (i < link_items.len and link_items[i].len > 0) { │ │944 - text_box.getFocus().kind = .{ .custom = try aa.dupe(u8, link_items[i]) };│ │945 - } │ │944 + if (item.link.len > 0) { │ │945 + text_box.getFocus().kind = .{ .custom = try aa.dupe(u8, item.link) }; │ │946 } │ │947 │ │948 try self.text_boxes.append(allocator, text_box); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1054 self.scroll.deinit(allocator); │ │1055 } │ │1056 │ │1057 - pub fn setItems(self: *Scroll, allocator: std.mem.Allocator, items: []const []const u8, links: ?[]const []const u8) !void {│ │1057 + pub fn setItems(self: *Scroll, allocator: std.mem.Allocator, items: []const Item) !void { │ │1058 self.scroll.x = 0; │ │1059 self.scroll.y = 0; │ │1060 - try self.inner().setItems(allocator, items, links); │ │1060 + try self.inner().setItems(allocator, items); │ │1061 } │ │1062 │ │1063 pub fn build(self: *Scroll, allocator: std.mem.Allocator, constraint: layout.Constraint, root_focus: *Focus) !void { │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯