╭ changed ──────────────╮ │src/ui/Repo/Commits.zig│ ╰───────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────────────────╮ │12 const Grid = xitui.grid.Grid; │ │13 const Focus = xitui.focus.Focus; │ │14 const inp = @import("../input.zig"); │ │15 - │ │16 -pub const SubHeader = @import("Commits/SubHeader.zig"); │ │15 │ │16 // how many commits a page shows before a "next" link appears.│ │17 const page_size = 20; │ ╰──────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────╮ │48 // the first oid of the next page, or null when this is the last page.│ │49 next_start: ?[]const u8, │ │50 // the "viewing <ref> <value>" banner shown above the log. │ │53 -sub_header: SubHeader, │ │51 +header: Header, │ │52 │ │53 const Self = @This(); │ │54 │ ╰──────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────╮ │137 .ref_or_oid_value = resolved.value, │ │138 .commits = try aa.dupe(Commit, buf[0..count]), │ │139 .next_start = next_start, │ │142 - .sub_header = try SubHeader.init(aa, resolved.ref_or_oid, resolved.value),│ │140 + .header = try Header.init(aa, resolved.ref_or_oid, resolved.value), │ │141 }; │ │142 } │ │143 │ ╰───────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────╮ │149 .ref_or_oid_value = try aa.dupe(u8, value), │ │150 .commits = &.{}, │ │151 .next_start = null, │ │154 - .sub_header = try SubHeader.init(aa, ref_or_oid, value),│ │152 + .header = try Header.init(aa, ref_or_oid, value), │ │153 }; │ │154 } │ │155 │ ╰─────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────╮ │300 // a vertical stack: the "viewing <ref>" banner on top, then a horizontal │ │301 // split with the commit list on the left and a diff pane on the right │ │302 // showing the selected commit's diff. │ │305 - box: wgt.Box(ui.Widget), // vert: [sub_header_index] = banner, [content_index] = split│ │303 + box: wgt.Box(ui.Widget), // vert: [header_index] = banner, [content_index] = split │ │304 data: *const Self, │ │305 session: *ui.Session, │ │306 // the commit whose diff the pane currently shows (index into data.commits). │ ╰───────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────╮ │307 diffed_index: ?usize, │ │308 │ │311 - const sub_header_index: usize = 0; │ │309 + const header_index: usize = 0; │ │310 const content_index: usize = 1; │ │311 // indices within the content box (the horizontal split).│ │312 const list_index: usize = 0; │ ╰──────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │320 │ │321 // the ref banner at the top. │ │322 { │ │325 - var sub_header = try SubHeader.View.init(allocator, &data.sub_header, session); │ │326 - errdefer sub_header.deinit(allocator); │ │327 - try outer.children.put(allocator, sub_header.getFocus().id, .{ .widget = .{ .repo_commits_sub_header = sub_header }, .rect = null, .min_size = .{ .width = null, .height = 3 } });│ │323 + var header = try Header.View.init(allocator, &data.header, session); │ │324 + errdefer header.deinit(allocator); │ │325 + try outer.children.put(allocator, header.getFocus().id, .{ .widget = .{ .repo_commits_header = header }, .rect = null, .min_size = .{ .width = null, .height = 3 } }); │ │326 } │ │327 │ │328 var box = try wgt.Box(ui.Widget).init(allocator, .{ .border_style = null, .direction = .horiz }); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │814 return std.fmt.allocPrint(page_arena.allocator(), "ai:{s}", .{url}); │ │815 } │ │816 │ │817 +// the "viewing <ref_or_oid> <value>" banner shown above the log. │ │818 +pub const Header = struct { │ │819 + content: []const u8, │ │820 + │ │821 + pub fn init(aa: std.mem.Allocator, ref_or_oid: ui.RoutablePage.RefOrOid, value: []const u8) !Header { │ │822 + return .{ │ │823 + .content = try std.fmt.allocPrint(aa, "viewing {s} {s}", .{ @tagName(ref_or_oid), value }), │ │824 + }; │ │825 + } │ │826 + │ │827 + pub const View = struct { │ │828 + text_box: wgt.TextBox(ui.Widget), │ │829 + data: *const Header, │ │830 + │ │831 + pub fn init(allocator: std.mem.Allocator, data: *const Header, session: *ui.Session) !Header.View { │ │832 + _ = session; │ │833 + var text_box = try wgt.TextBox(ui.Widget).init(allocator, data.content, .{ .border_style = .hidden, .wrap_kind = .none });│ │834 + errdefer text_box.deinit(allocator); │ │835 + return .{ .text_box = text_box, .data = data }; │ │836 + } │ │837 + │ │838 + pub fn deinit(self: *Header.View, allocator: std.mem.Allocator) void { │ │839 + self.text_box.deinit(allocator); │ │840 + } │ │841 + │ │842 + pub fn build(self: *Header.View, allocator: std.mem.Allocator, constraint: layout.Constraint, root_focus: *Focus) !void { │ │843 + // a single line plus the hidden border is 3 rows tall; stretch the box to │ │844 + // the full width by handing the available width down as a min width. │ │845 + try self.text_box.build(allocator, .{ │ │846 + .min_size = .{ .width = constraint.max_size.width, .height = null }, │ │847 + .max_size = constraint.max_size, │ │848 + }, root_focus); │ │849 + } │ │850 + │ │851 + pub fn input(self: *Header.View, allocator: std.mem.Allocator, key: Key, root_focus: *Focus) !void { │ │852 + _ = self; │ │853 + _ = allocator; │ │854 + _ = key; │ │855 + _ = root_focus; │ │856 + } │ │857 + │ │858 + pub fn clearGrid(self: *Header.View) void { │ │859 + self.text_box.clearGrid(); │ │860 + } │ │861 + │ │862 + pub fn getGrid(self: Header.View) ?Grid { │ │863 + return self.text_box.getGrid(); │ │864 + } │ │865 + │ │866 + pub fn getFocus(self: *Header.View) *Focus { │ │867 + return self.text_box.getFocus(); │ │868 + } │ │869 + }; │ │870 +}; │ │871 + │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯