summaryrefslogtreecommitdiff
path: root/src/datastruct/split_tree.zig
diff options
context:
space:
mode:
authorMitchell Hashimoto <m@mitchellh.com>2025-08-06 09:52:41 -0700
committerMitchell Hashimoto <m@mitchellh.com>2025-08-07 08:14:02 -0700
commitfa08434b28580229c39082dc4f1de6731ed0ed3b (patch)
treeb104f16828a52aed913d3082c86a484696bff7c2 /src/datastruct/split_tree.zig
parentad1cfe8347144575e65f590cdd6ca83badc4dd21 (diff)
apprt/gtk-ng: initial GhosttySplitTree widget
Diffstat (limited to 'src/datastruct/split_tree.zig')
-rw-r--r--src/datastruct/split_tree.zig37
1 files changed, 32 insertions, 5 deletions
diff --git a/src/datastruct/split_tree.zig b/src/datastruct/split_tree.zig
index 9cd929faa..759387073 100644
--- a/src/datastruct/split_tree.zig
+++ b/src/datastruct/split_tree.zig
@@ -37,6 +37,9 @@ const Allocator = std.mem.Allocator;
/// for the debug view. If this isn't specified then the node handle
/// will be used.
///
+/// Note: for both the ref and unref functions, the allocator is optional.
+/// If the functions take less arguments, then the allocator will not be
+/// passed.
pub fn SplitTree(comptime V: type) type {
return struct {
const Self = @This();
@@ -88,8 +91,8 @@ pub fn SplitTree(comptime V: type) type {
const alloc = arena.allocator();
const nodes = try alloc.alloc(Node, 1);
- nodes[0] = .{ .leaf = try view.ref(gpa) };
- errdefer view.unref(gpa);
+ nodes[0] = .{ .leaf = try viewRef(view, gpa) };
+ errdefer viewUnref(view, gpa);
return .{
.arena = arena,
@@ -104,7 +107,7 @@ pub fn SplitTree(comptime V: type) type {
// Unref all our views
const gpa: Allocator = self.arena.child_allocator;
for (self.nodes) |node| switch (node) {
- .leaf => |view| view.unref(gpa),
+ .leaf => |view| viewUnref(view, gpa),
.split => {},
};
self.arena.deinit();
@@ -113,6 +116,12 @@ pub fn SplitTree(comptime V: type) type {
self.* = undefined;
}
+ /// Returns true if this is an empty tree.
+ pub fn isEmpty(self: *const Self) bool {
+ // An empty tree has no nodes.
+ return self.nodes.len == 0;
+ }
+
/// An iterator over all the views in the tree.
pub fn iterator(
self: *const Self,
@@ -367,13 +376,13 @@ pub fn SplitTree(comptime V: type) type {
errdefer for (0..reffed) |i| {
switch (nodes[i]) {
.split => {},
- .leaf => |view| view.unref(gpa),
+ .leaf => |view| viewUnref(view, gpa),
}
};
for (0..nodes.len) |i| {
switch (nodes[i]) {
.split => {},
- .leaf => |view| nodes[i] = .{ .leaf = try view.ref(gpa) },
+ .leaf => |view| nodes[i] = .{ .leaf = try viewRef(view, gpa) },
}
reffed = i;
}
@@ -658,6 +667,24 @@ pub fn SplitTree(comptime V: type) type {
try writer.writeAll(row);
}
}
+
+ fn viewRef(view: *View, gpa: Allocator) Allocator.Error!*View {
+ const func = @typeInfo(@TypeOf(View.ref)).@"fn";
+ return switch (func.params.len) {
+ 1 => view.ref(),
+ 2 => try view.ref(gpa),
+ else => @compileError("invalid view ref function"),
+ };
+ }
+
+ fn viewUnref(view: *View, gpa: Allocator) void {
+ const func = @typeInfo(@TypeOf(View.unref)).@"fn";
+ switch (func.params.len) {
+ 1 => view.unref(),
+ 2 => view.unref(gpa),
+ else => @compileError("invalid view unref function"),
+ }
+ }
};
}