╭ changed ───────────╮ │src/ui/Repo/Undo.zig│ ╰────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │431 errdefer scroll.deinit(allocator); │ │432 try box.children.put(allocator, scroll.getFocus().id, .{ .widget = .{ .scroll = scroll }, .rect = null, .min_size = .{ .width = list_max_width, .height = null }, .max_size = .{ .width = list_max_width, .height = null } });│ │433 } │ │434 + // the detail scroll, below the way back to a hidden list │ │435 { │ │436 + var frame = try wgt.Box(ui.Widget).init(allocator, .{ .border = null, .direction = .vert }); │ │437 + errdefer frame.deinit(allocator); │ │438 + try ui.widget.addListBack(allocator, &frame, "← back to undo list"); │ │439 var scroll = blk: { │ │440 var details = try wgt.Box(ui.Widget).init(allocator, .{ .border = null, .direction = .vert }); │ │441 errdefer details.deinit(allocator); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │448 }; │ │449 errdefer scroll.deinit(allocator); │ │450 scroll.getFocus().mode = .mouse; │ │447 - try box.children.put(allocator, scroll.getFocus().id, .{ .widget = .{ .scroll = scroll }, .rect = null, .min_size = .{ .width = detail_min_width, .height = null } });│ │451 + frame.getFocus().child_id = scroll.getFocus().id; │ │452 + try frame.children.put(allocator, scroll.getFocus().id, .{ .widget = .{ .scroll = scroll }, .rect = null, .min_size = null }); │ │453 + try box.children.put(allocator, frame.getFocus().id, .{ .widget = .{ .box = frame }, .rect = null, .min_size = .{ .width = detail_min_width, .height = null } }); │ │454 } │ │455 box.getFocus().child_id = box.children.keys()[if (data.items.len > 0) 1 else 0]; │ │456 try outer.children.put(allocator, box.getFocus().id, .{ .widget = .{ .box = box }, .rect = null, .min_size = null }); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────╮ │512 } │ │513 fn listScroll(self: *View) *wgt.Scroll(ui.Widget) { │ │514 return &self.contentBox().children.values()[0].widget.scroll; │ │515 + } │ │516 + fn detailFrame(self: *View) *wgt.Box(ui.Widget) { │ │517 + return &self.contentBox().children.values()[1].widget.box; │ │518 } │ │519 fn detailScroll(self: *View) *wgt.Scroll(ui.Widget) { │ │511 - return &self.contentBox().children.values()[1].widget.scroll; │ │520 + return &self.detailFrame().children.values()[ui.widget.list_pane_index].widget.scroll;│ │521 } │ │522 fn selected(self: *View) ?usize { │ │523 const rows = &self.listScroll().child.box; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────╮ │525 return if (index < self.data.items.len) index else null; │ │526 } │ │527 fn detailActive(self: *View) bool { │ │519 - return self.contentBox().getFocus().child_id == self.detailScroll().getFocus().id;│ │528 + return self.contentBox().getFocus().child_id == self.detailFrame().getFocus().id; │ │529 } │ │530 │ │531 fn refreshDetail(self: *View, allocator: std.mem.Allocator) !void { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────╮ │564 self.detailScroll().x = 0; │ │565 self.detailScroll().y = 0; │ │566 self.detailScroll().getFocus().version +%= 1; │ │567 + ui.widget.setListBackLink(self.detailFrame(), item.link);│ │568 self.detailed_index = index; │ │569 } │ │570 │ ╰──────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │583 } │ │584 for (rows.children.keys(), rows.children.values()) |id, *child| ui.widget.markSelected(&child.widget.text_box, rows.getFocus().child_id == id);│ │585 const both_fit = if (constraint.max_size.width) |width| width >= list_max_width + detail_min_width else true; │ │586 + ui.widget.showListBack(self.detailFrame(), !both_fit); │ │587 self.contentBox().children.values()[0].max_size = if (both_fit) .{ .width = list_max_width, .height = null } else null; │ │588 const width = if (constraint.max_size.width) |value| if (both_fit) value - list_max_width else value else detail_min_width; │ │589 self.contentBox().children.values()[1].min_size = .{ .width = width, .height = null }; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │603 if (direction == .up) root_focus.setFocus(self.headerBox().getFocus().id) else try self.clearInput(key, root_focus);│ │604 return; │ │605 } │ │606 + // the way back to the list, by enter or a click │ │607 + if (self.detailActive()) if (ui.widget.listBackId(self.detailFrame())) |id| { │ │608 + if (inp.activated(root_focus, id, key)) return self.focusList(root_focus); │ │609 + if (root_focus.grandchild_id == id) return switch (direction) { │ │610 + .up => root_focus.setFocus(self.headerBox().getFocus().id), │ │611 + .down => root_focus.setFocus(self.detailScroll().getFocus().id), │ │612 + .none => if (key == .arrow_left) self.focusList(root_focus), │ │613 + }; │ │614 + if (direction == .up and self.contentAtTop()) return root_focus.setFocus(id); │ │615 + }; │ │616 if (direction == .up and self.contentAtTop()) { │ │617 root_focus.setFocus(self.headerBox().getFocus().id); │ │618 return; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │629 if (inp.rowDelta(key, @intCast(details.children.count()))) |delta| { │ │630 ui.widget.moveRowFocus(details, self.detailScroll(), root_focus, delta); │ │631 } else if (key == .arrow_left) { │ │611 - root_focus.setFocus(self.listScroll().getFocus().id); │ │632 + self.focusList(root_focus); │ │633 } │ │634 } else if (inp.rowDelta(key, @intCast(self.listScroll().child.box.children.count()))) |delta| {│ │635 ui.widget.moveRowFocus(&self.listScroll().child.box, self.listScroll(), root_focus, delta);│ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────╮ │636 } else switch (key) { │ │616 - .arrow_right, .enter => if (self.selected() != null) { │ │617 - root_focus.setFocus(self.detailScroll().getFocus().id); │ │618 - }, │ │637 + .arrow_right, .enter => if (self.selected() != null) self.focusDetail(root_focus),│ │638 else => {}, │ │639 } │ │640 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │641 │ │642 + // enter the detail pane, landing on the way back to the list when it shows │ │643 + fn focusDetail(self: *View, root_focus: *Focus) void { │ │644 + if (ui.widget.listBackId(self.detailFrame()) != null) return ui.widget.focusListBack(self.detailFrame(), root_focus);│ │645 + root_focus.setFocus(self.detailScroll().getFocus().id); │ │646 + } │ │647 + │ │648 + fn focusList(self: *View, root_focus: *Focus) void { │ │649 + root_focus.setFocus(self.listScroll().getFocus().id); │ │650 + } │ │651 + │ │652 // the confirm button submits the form the web renderer posts │ │653 fn clearInput(self: *View, key: Key, root_focus: *Focus) !void { │ │654 const center = &self.box.children.values()[content_index].widget.center; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯