This commit is contained in:
Jeeves 2024-04-07 14:03:38 -06:00
parent 80f1d8f8a0
commit 8cf18400e2
3 changed files with 297 additions and 60 deletions

View file

@ -18,22 +18,32 @@ pub fn main() !void {
var box1 = Terminal.Box.init(allocator);
defer box1.deinit();
box1.content = "hi";
box1.top = 0;
box1.bottom = 0;
box1.left = 0;
box1.right = 0;
box1.border_fg = try Terminal.Color.init("#ff8855");
box1.top = 1;
box1.bottom = 1;
box1.left = 1;
box1.right = 1;
var box2 = Terminal.Box.init(allocator);
defer box2.deinit();
box2.content = "hi";
box2.top = 0;
box2.bottom = 0;
box2.left = 0;
box2.right = 0;
box2.border_fg = try Terminal.Color.init("#aaff55");
box2.top = 1;
box2.bottom = 1;
box2.left = 1;
box2.right = 1;
var box3 = Terminal.Box.init(allocator);
defer box3.deinit();
box3.border_bg = try Terminal.Color.init("#aa33ff");
box3.border_type = .bg;
box3.top = 1;
box3.bottom = 1;
box3.left = 1;
box3.right = 1;
try term.box.addChild(&box1);
try box1.addChild(&box2);
try box2.addChild(&box3);
while (true) {
const events = try term.getEvents();
@ -93,7 +103,6 @@ pub const Terminal = struct {
};
errdefer term.tty.close();
errdefer term.info.deinit();
term.box.position = .{ .x = 0, .y = 0, .width = 50, .height = 20 };
try term.uncook();
try attachSignalHandlers();
try term.updateWinSize();
@ -192,16 +201,18 @@ pub const Terminal = struct {
const ret = os.linux.ioctl(0, os.linux.T.IOCGWINSZ, @intFromPtr(&sz));
// std.debug.print("ret: {d}, {any}\r\n", .{ ret, sz });
if (ret == 0) {
self.box.position = .{
self.box.rect = .{
.x = 0,
.y = 0,
.height = @intCast(sz.ws_row),
.width = @intCast(sz.ws_col),
.h = @intCast(sz.ws_row),
.w = @intCast(sz.ws_col),
};
self.box.makeDirty();
} else unreachable; // TODO: handle else case
}
pub fn draw(self: *Terminal) !void {
if (self.box.dirty) try self.clearScreen();
try self.box.draw(self);
}
@ -277,18 +288,22 @@ pub const Terminal = struct {
// }
// }
pub fn setFg(self: *Terminal, color: Color) !void {
try self.info.writeString(.set_rgb_foreground, self.tty.writer(), &[_]u32{ @intCast(color.r), @intCast(color.g), @intCast(color.b) });
}
pub fn setBg(self: *Terminal, color: Color) !void {
try self.info.writeString(.set_rgb_background, self.tty.writer(), &[_]u32{ @intCast(color.r), @intCast(color.g), @intCast(color.b) });
}
pub const Info = @import("terminfo.zig");
pub const Color = @import("color.zig").RGB;
pub const Box = struct {
parent: ?*Box,
children: std.ArrayList(*Box),
position: ?struct {
x: u32,
y: u32,
width: u32,
height: u32,
} = null,
rect: ?Rect = null, // TODO: maybe unionize this with .parent
dirty: bool = true,
left: u32,
@ -298,8 +313,8 @@ pub const Terminal = struct {
border_type: enum { line, bg } = .line,
border_char: u8 = ' ',
border_bg: i16 = -1,
border_fg: i16 = -1,
border_bg: Color = Color{ .r = 0, .g = 0, .b = 0 },
border_fg: Color = Color{ .r = 0xff, .g = 0xff, .b = 0xff },
content: []const u8 = "",
@ -322,20 +337,6 @@ pub const Terminal = struct {
pub fn addChild(self: *Box, child: *Box) !void {
std.debug.assert(child.parent == null);
child.parent = self;
std.debug.assert(self.position != null);
child.position = if (self.border_type == .line) .{
.x = self.position.?.x + child.left,
.y = self.position.?.y + child.top,
.width = self.position.?.width - child.right - child.left,
.height = self.position.?.height,
} else .{
.x = self.position.?.x + child.left,
.y = self.position.?.y + child.top,
.width = self.position.?.width,
.height = self.position.?.height,
};
try self.children.append(child);
}
@ -361,11 +362,20 @@ pub const Terminal = struct {
_ = idx;
}
fn makeDirty(self: *Box) void {
self.dirty = true;
for (self.children.items) |child| child.makeDirty();
}
pub fn draw(self: *Box, term: *Terminal) !void {
if (self.dirty) {
// if (self != &term.box) self.calcRect();
const rect = self.getRect();
// std.debug.print("{any}\r\n", .{rect});
switch (self.border_type) {
.line => {
try term.setFg(self.border_fg);
try term.setBg(self.border_bg);
var x: u32 = 0;
var y: u32 = 0;
try term.cursorSet(rect.x, rect.y);
@ -376,16 +386,25 @@ pub const Terminal = struct {
while (y < rect.h - 1) : (y += 1) {
try term.cursorSet(rect.x, rect.y + y);
try term.print("", .{});
try term.cursorSet(rect.w, rect.y + y);
try term.cursorSet(rect.x + rect.w - 1, rect.y + y);
try term.print("", .{});
}
x = 0;
try term.cursorSet(rect.x, rect.h);
try term.cursorSet(rect.x, rect.y + rect.h - 1);
try term.print("", .{});
while (x < rect.w - 2) : (x += 1) try term.print("", .{});
try term.print("", .{});
},
.bg => {},
.bg => {
try term.setBg(self.border_bg);
var y: u32 = 0;
try term.cursorSet(rect.x, rect.y);
while (y < rect.h) : (y += 1) {
try term.cursorSet(rect.x, rect.y + y);
var x: u32 = 0;
while (x < rect.w) : (x += 1) try term.print(" ", .{});
}
},
}
self.dirty = false;
}
@ -393,25 +412,18 @@ pub const Terminal = struct {
}
fn getRect(self: *Box) Rect {
var rect = Rect{
.x = self.position.?.x,
.y = self.position.?.y,
.w = self.position.?.width,
.h = self.position.?.height,
};
// if (self.border_type == .line) {
// rect.x += 1;
// rect.y += 1;
// rect.w -= 2;
// rect.h -= 2;
// }
var rect: Rect = undefined;
if (self.parent) |parent| {
const parent_rect = parent.getRect();
rect.x += parent_rect.x + self.left;
rect.y += parent_rect.y + self.top;
rect.w += parent_rect.x + self.right;
rect.h -= parent_rect.y + self.bottom;
}
rect.x = parent_rect.x + self.left;
rect.y = parent_rect.y + self.top;
rect.w = parent_rect.w + parent_rect.x - rect.x - self.right;
rect.h = parent_rect.h + parent_rect.y - rect.y - self.bottom;
// if (parent.parent) |p| {
// rect.w += p.rect.?.x;
// rect.h += p.rect.?.y;
// }
} else return self.rect.?;
return rect;
}
const Rect = struct { x: u32, y: u32, w: u32, h: u32 };