╭ Settings.zig ─────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
1 const std = @import("std"); 2 const ui = @import("../ui.zig"); 3 const xit = @import("xit"); 4 const xitui = xit.xitui; 5 const wgt = xitui.widget; 6 const layout = xitui.layout; 7 const inp = xitui.input; 8 const Grid = xitui.grid.Grid; 9 const Focus = xitui.focus.Focus; 10 11 const Self = @This(); 12 13 const label_on = "turn off ANSI art"; 14 const label_off = "turn on ANSI art"; 15 16 pub fn init() Self { 17 return .{}; 18 } 19 20 pub const View = struct { 21 center: ui.Center, 22 data: *const Self, 23 session: *ui.Session, 24 button_id: usize, 25 26 const button_index: usize = 0; 27 28 pub fn init(allocator: std.mem.Allocator, data: *const Self, session: *ui.Session) !View { 29 const logged_in = session.data.user_id != null; 30 31 var box = wgt.Box(ui.Widget).init(.{ .border_style = null, .rounded_corners = true, .direction = .vert }); 32 errdefer box.deinit(allocator); 33 box.getFocus().kind = .{ .custom = if (logged_in) "form:/ansi" else "form:" }; 34 35 var button_id: usize = undefined; 36 { 37 var button = try wgt.TextBox(ui.Widget).init(allocator, labelFor(session), .{ .border_style = .single, .rounded_corners = true, .wrap_kind = .none }); 38 errdefer button.deinit(allocator); 39 button.getFocus().focusable = true; 40 // the renderer distinguishes plain clickables from buttons that 41 // should POST to a server route by this kind. 42 button.getFocus().kind = .{ .custom = "submit" }; 43 button_id = button.getFocus().id; 44 try box.children.put(allocator, button.getFocus().id, .{ 45 .widget = .{ .text_box = button }, 46 .rect = null, 47 .min_size = null, 48 }); 49 } 50 51 box.getFocus().child_id = button_id; 52 53 return .{ 54 .center = try ui.Center.init(allocator, .{ .box = box }, .both), 55 .data = data, 56 .session = session, 57 .button_id = button_id, 58 }; 59 } 60 61 pub fn deinit(self: *View, allocator: std.mem.Allocator) void { 62 self.center.deinit(allocator); 63 } 64 65 pub fn build(self: *View, allocator: std.mem.Allocator, constraint: layout.Constraint, root_focus: *Focus) !void { 66 const box = &self.center.child.box; 67 if (box.children.values().len > 0) { 68 const button = &box.children.values()[button_index].widget.text_box; 69 button.box.children.values()[0].widget.text.content = labelFor(self.session); 70 } 71 try self.center.build(allocator, constraint, root_focus); 72 } 73 74 pub fn input(self: *View, allocator: std.mem.Allocator, key: inp.Key, root_focus: *Focus) !void { 75 _ = allocator; 76 switch (key) { 77 .enter => try self.toggle(), 78 .mouse => |mouse| { 79 if (mouse.action == .press and mouse.action.press == .left) { 80 if (root_focus.children.get(self.button_id)) |entry| { 81 const r = entry.rect; 82 if (mouse.x >= r.x and mouse.y >= r.y and 83 mouse.x < r.x + r.size.width and mouse.y < r.y + r.size.height) 84 { 85 try self.toggle(); 86 } 87 } 88 } 89 }, 90 else => {}, 91 } 92 } 93 94 // enqueue the toggle; the host drains it (applying + persisting) this frame. 95 fn toggle(self: *View) !void { 96 try self.session.push(.toggle_ansi); 97 } 98 99 pub fn clearGrid(self: *View) void { 100 self.center.clearGrid(); 101 } 102 103 pub fn getGrid(self: View) ?Grid { 104 return self.center.getGrid(); 105 } 106 107 pub fn getFocus(self: *View) *Focus { 108 return self.center.getFocus(); 109 } 110 111 pub fn getSelectedIndex(self: View) ?usize { 112 _ = self; 113 return 0; 114 } 115 }; 116 117 fn labelFor(session: *const ui.Session) []const u8 { 118 return if (session.data.enable_ansi) label_on else label_off; 119 } 120