╭ changed ──────────────╮ │src/ui/Repo/Patches.zig│ ╰───────────────────────╯ ╭──────────────────────────────────────────╮ │2 const builtin = @import("builtin"); │ │3 const evt = @import("../../event.zig");│ │4 const ui = @import("../../ui.zig"); │ │5 -const inp = @import("../input.zig"); │ │5 const xit = @import("xit"); │ │6 const rp = xit.repo; │ │7 const hash = xit.hash; │ ╰──────────────────────────────────────────╯ ╭──────────────────────────────────────────────────╮ │19 pub const Source = struct { │ │20 box: wgt.Box(ui.Widget), │ │21 session: *ui.Session, │ │23 - selected: Kind, │ │22 selectors: std.enums.EnumMap(Kind, usize),│ │23 │ │24 pub const Kind = enum { fork, branch }; │ ╰──────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │47 try input_box.setContent(allocator, initial); │ │48 try box.children.put(allocator, input_box.getFocus().id, .{ .widget = .{ .text_input = input_box }, .rect = null, .min_size = .{ .width = 15, .height = 3 } });│ │49 box.getFocus().child_id = selectors.get(selected) orelse input_box.getFocus().id; │ │52 - return .{ .box = box, .session = session, .selected = selected, .selectors = selectors }; │ │50 + return .{ .box = box, .session = session, .selectors = selectors }; │ │51 } │ │52 │ │53 pub fn field(self: *Source) *wgt.TextInput { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────╮ │58 unreachable; │ │59 } │ │60 │ │61 + // the selection is whichever selector focus last landed on, like every │ │62 + // other selection in the ui, so a click (which only moves focus on the │ │63 + // web) selects. the branch text input is only reachable while branch is│ │64 + // selected, so focus on it means branch too. │ │65 + pub fn selectedKind(self: *Source) Kind { │ │66 + const current = self.box.getFocus().child_id orelse return .branch; │ │67 + var iter = self.selectors.iterator(); │ │68 + while (iter.next()) |selector| { │ │69 + if (selector.value.* == current) return selector.key; │ │70 + } │ │71 + return .branch; │ │72 + } │ │73 + │ │74 pub fn deinit(self: *Source, allocator: std.mem.Allocator) void { │ │75 self.box.deinit(allocator); │ │76 } │ ╰────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 89 │ │ 90 pub fn build(self: *Source, allocator: std.mem.Allocator, constraint: xitui.layout.Constraint, root_focus: *xitui.focus.Focus) !void {│ │ 91 self.clearGrid(); │ │ 92 + const selected = self.selectedKind(); │ │ 93 for (self.box.children.keys(), self.box.children.values()) |id, *child| switch (child.widget) { │ │ 82 - .text_input => child.hidden = switch (self.selected) { │ │ 83 - .fork => true, │ │ 84 - .branch => false, │ │ 85 - }, │ │ 94 + .text_input => child.hidden = selected == .fork, │ │ 95 .text_box => |*selector| { │ │ 87 - const selected = id == self.selectors.get(self.selected); │ │ 88 - selector.options.border_style = if (selected) .single else .hidden; │ │ 89 - selector.options.inverted = selected; │ │ 96 + const is_selected = id == self.selectors.get(selected); │ │ 97 + selector.options.border_style = if (is_selected) .single else .hidden; │ │ 98 + selector.options.inverted = is_selected; │ │ 99 }, │ │100 else => {}, │ │101 }; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │106 } │ │107 │ │108 pub fn input(self: *Source, allocator: std.mem.Allocator, key: xitui.input.Key, root_focus: *xitui.focus.Focus) !void {│ │100 - if (key == .mouse) { │ │101 - var iter = self.selectors.iterator(); │ │102 - while (iter.next()) |selector| { │ │103 - if (inp.leftClickOn(root_focus, selector.value.*, key.mouse)) { │ │104 - self.selected = selector.key; │ │105 - return; │ │106 - } │ │107 - } │ │108 - } │ │109 const current = self.box.getFocus().child_id orelse return; │ │110 const text_input = self.field(); │ │111 if (current == text_input.getFocus().id) { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────╮ │112 if (key == .arrow_left) { │ │113 - if (self.selectors.get(self.selected)) |id| {│ │113 + if (self.selectors.get(.branch)) |id| { │ │114 root_focus.setFocus(id); │ │115 return; │ │116 } │ ╰──────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────╮ │121 var iter = self.selectors.iterator(); │ │122 var previous: ?Kind = null; │ │123 while (iter.next()) |selector| { │ │124 - if (selector.value.* == current) { │ │125 - self.selected = selector.key; │ │126 - break; │ │127 - } │ │124 + if (selector.value.* == current) break;│ │125 previous = selector.key; │ │126 } else return; │ │127 switch (key) { │ ╰────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │131 - .arrow_left => if (previous) |kind| { │ │132 - self.selected = kind; │ │133 - root_focus.setFocus(self.selectors.get(kind) orelse return); │ │134 - }, │ │135 - .arrow_right => if (iter.next()) |next| { │ │136 - self.selected = next.key; │ │137 - root_focus.setFocus(next.value.*); │ │138 - } else if (self.selected == .branch) root_focus.setFocus(text_input.getFocus().id), │ │139 - .enter => if (self.selected == .branch) root_focus.setFocus(text_input.getFocus().id), │ │128 + .arrow_left => if (previous) |kind| root_focus.setFocus(self.selectors.get(kind) orelse return), │ │129 + // past the last selector (branch) lies its text input │ │130 + .arrow_right => if (iter.next()) |next| root_focus.setFocus(next.value.*) else root_focus.setFocus(text_input.getFocus().id),│ │131 + .enter => if (self.selectedKind() == .branch) root_focus.setFocus(text_input.getFocus().id), │ │132 else => {}, │ │133 } │ │134 } │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────────────╮ │src/ui/widget/thread.zig│ ╰────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2332 if (formWidget(form, .patch_source)) |source| { │ │2333 source.field().options.label = if (failure == .invalid_source_branch) " source branch (not found) " else if (failure == .same_branch) " source branch (same as target) " else if (failure == .unrelated_branches) " source branch (unrelated) " else " source branch ";│ │2334 const submit = formWidget(form, .submit_button) orelse return error.MissingFormField; │ │2335 - try submit.setLabel(allocator, switch (source.selected) { │ │2335 + try submit.setLabel(allocator, switch (source.selectedKind()) { │ │2336 .fork => "submit draft", │ │2337 .branch => "submit patch", │ │2338 }); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯