diff --git a/src/hncore/Digraph.zig b/src/hncore/Digraph.zig index 74dff4f..c031256 100644 --- a/src/hncore/Digraph.zig +++ b/src/hncore/Digraph.zig @@ -108,16 +108,16 @@ pub fn Container(comptime T: type, comptime lessThanFn: LessThanFunc(T)) type { var begin: usize = undefined; var end : usize = undefined; - if (baseFrom < from) { + if (lessThanFn(baseFrom, from)) { begin = baseIdx; - while ((begin < n) and (self.map.items[begin].from < from)) { begin += 1; } + while ((begin < n) and lessThanFn(self.map.items[begin].from, from)) { begin += 1; } end = begin; while ((end < n) and (self.map.items[end].from == from)) { end += 1; } - } else if (baseFrom > from) { + } else if (lessThanFn(from, baseFrom)) { end = baseIdx; - while ((end > 0) and (self.map.items[end-1].from > from)) { end -= 1; } + while ((end > 0) and lessThanFn(from, self.map.items[end-1].from)) { end -= 1; } begin = end; while ((begin > 0) and (self.map.items[begin-1].from == from)) { begin -= 1; } @@ -144,9 +144,9 @@ pub fn Container(comptime T: type, comptime lessThanFn: LessThanFunc(T)) type { idx = (left + right) / 2; const target = self.map.items[idx].from; - if (target < from) { + if (lessThanFn(target, from)) { left = idx + 1; - } else if (target > from) { + } else if (lessThanFn(from, target)) { right = idx -| 1; } else { break; diff --git a/src/hncore/Merged.zig b/src/hncore/Merged.zig index 724a6a9..edd58e9 100644 --- a/src/hncore/Merged.zig +++ b/src/hncore/Merged.zig @@ -60,7 +60,6 @@ pub fn merge(a: anytype, b: anytype) Merged(@TypeOf(a), @TypeOf(b)) { } } return ret; - } test "merging 2 structs" { diff --git a/src/hncore/Mindmap.zig b/src/hncore/Mindmap.zig index d9b928c..a960de4 100644 --- a/src/hncore/Mindmap.zig +++ b/src/hncore/Mindmap.zig @@ -4,7 +4,7 @@ const Digraph = @import("./Digraph.zig"); pub const Node = @import("./Node.zig"); pub const NodeList = std.ArrayList(*Node); -pub const NodeDigraph = Digraph.Container(*Node, Digraph.lessThanFuncFor(*Node)); +pub const NodeDigraph = Digraph.Container(*const Node, Digraph.lessThanFuncFor(*const Node)); /// alloc: std.mem.Allocator, @@ -34,6 +34,20 @@ pub fn init(alloc: std.mem.Allocator) !@This() { try nodes.append(root); + var node1 = try alloc.create(Node); + errdefer alloc.destroy(node1); + node1.* = try Node.init(alloc, 1, "node1"); + errdefer node1.deinit(alloc); + try nodes.append(node1); + try digraph.connect(root, node1); + + var node2 = try alloc.create(Node); + errdefer alloc.destroy(node2); + node2.* = try Node.init(alloc, 2, "node1"); + errdefer node2.deinit(alloc); + try nodes.append(node2); + try digraph.connect(root, node2); + return .{ .alloc = alloc, .nodes = nodes, @@ -43,7 +57,7 @@ pub fn init(alloc: std.mem.Allocator) !@This() { } /// pub fn deinit(self: *@This()) void { - for (self.nodes) |node| { + for (self.nodes.items) |node| { node.deinit(self.alloc); self.alloc.destroy(node); } diff --git a/src/hnet/App.zig b/src/hnet/App.zig index 3b3c2d4..aa19444 100644 --- a/src/hnet/App.zig +++ b/src/hnet/App.zig @@ -2,23 +2,32 @@ const std = @import("std"); const dvui = @import("dvui"); const hncore = @import("hncore"); +const ui = @import("./ui.zig"); + +/// pub const App = struct { + /// + project: hncore.Project, + + /// pub fn init(alloc: std.mem.Allocator) !App { - _ = alloc; return App { + .project = try .init(alloc), }; } + /// pub fn deinit(self: *App) void { - _ = self; + self.project.deinit(); } + /// pub fn gui(self: *App) !void { + try self.guiMenu(); + try self.guiMain(); + } + fn guiMenu(self: *@This()) !void { _ = self; - try gui_menu(); - try gui_main(); - } - fn gui_menu() !void { var root = try dvui.menu(@src(), .horizontal, .{ .background = true, .expand = .horizontal }); defer root.deinit(); @@ -31,17 +40,15 @@ pub const App = struct { } } } - fn gui_main() !void { - var box = try dvui.scrollArea(@src(), .{}, .{ + fn guiMain(self: *@This()) !void { + var overlay = try dvui.overlay(@src(), .{ .expand = .both, - .color_fill = .{ .name = .fill_window }, .padding = dvui.Rect.all(8), + .color_fill = .{ .name = .fill_window }, + .background = true, }); - defer box.deinit(); + defer overlay.deinit(); - if (try dvui.button(@src(), "Zoom In", .{}, .{})) { - } - if (try dvui.button(@src(), "Zoom In", .{}, .{})) { - } + try ui.manipulator(self.project.mindmap.root, &self.project.mindmap.digraph); } }; diff --git a/src/hnet/main.zig b/src/hnet/main.zig index 1fd6c5f..285fb24 100644 --- a/src/hnet/main.zig +++ b/src/hnet/main.zig @@ -23,6 +23,7 @@ pub fn main() !void { defer win.deinit(); var app = try App.init(gpa.allocator()); + defer app.deinit(); while (true) { try win.begin( win.beginWait(backend.hasEvent()), diff --git a/src/hnet/ui.zig b/src/hnet/ui.zig new file mode 100644 index 0000000..13c7fd5 --- /dev/null +++ b/src/hnet/ui.zig @@ -0,0 +1,53 @@ +const std = @import("std"); +const dvui = @import("dvui"); +const hncore = @import("hncore"); + +/// +pub fn manipulator(root: *const hncore.Mindmap.Node, digraph: *const hncore.Mindmap.NodeDigraph) !void { + var overlay = try dvui.overlay(@src(), .{ + .expand = .both, + }); + defer overlay.deinit(); + + _ = try nodeTreeInManipulator(.{ .x = 100, .y = 100, }, root, digraph); +} + +/// +pub fn nodeTreeInManipulator(base: dvui.Point, node: *const hncore.Mindmap.Node, digraph: *const hncore.Mindmap.NodeDigraph) !dvui.Rect { + const size = try nodeInManipulator(base, node); + const childrenRect = nodeChildrenInManipulator( + .{ .x = base.x + size.x, .y = base.y, }, node, digraph); + return .{ + .x = base.x, + .y = base.y, + .w = childrenRect.w + size.w, + .h = @max(childrenRect.h, size.h), + }; +} + +/// +pub fn nodeInManipulator(base: dvui.Point, node: *const hncore.Mindmap.Node) !dvui.Rect { + var box = try dvui.box(@src(), .vertical, .{ + .id_extra = node.id, + .border = .all(1), + .rect = .{ .x = base.x, .y = base.y, .w = 100, .h = 20, }, + }); + defer box.deinit(); + return box.wd.borderRect(); +} + +/// +pub fn nodeChildrenInManipulator(base: dvui.Point, node: *const hncore.Mindmap.Node, digraph: *const hncore.Mindmap.NodeDigraph) dvui.Rect { + const parentMargin = 16; + const siblingMargin = 8; + + var childDepth : f32 = 0; + var childOffset: f32 = 0; + for (digraph.getChildrenOf(node)) |conn| { + const childRect = nodeTreeInManipulator( + .{ .x = base.x + parentMargin, .y = base.y + childOffset, }, conn.to, digraph) catch unreachable; + childOffset += childRect.h + siblingMargin; + childDepth = @max(childRect.w, childDepth); + } + return .{ .x = base.x, .y = base.y, .w = childDepth, .h = childOffset, }; +}